0028 — Evidence does not need a project
Notes, meetings, and chat threads are owned by a person, can be attached to any number of projects or none, and are readable by whoever the knowledge they feed is readable by.
Decided. Workspace has a new domain called evidence. It stores three kinds of thing: notes
somebody typed, meeting transcripts, and chat threads copied in from Slack. Each one is called a
record.
A record is owned by the person who made it, not by a project. It can be attached to as many projects as you like, or to none at all.
By default the intelligence service reads a record and turns it into claims the company can search. A flag on the record turns that off.
Who can read a record
The rule in one sentence: if a record is teaching the company something, anyone at the company can look at it.
Checked in this order:
- The author can always read their own.
- If it is attached to projects, members of any of those projects can read it.
- If it is attached to no project and it feeds the knowledge layer, everyone at Flow can read it.
- If it is attached to no project and it does not feed the knowledge layer, only the author can read it.
- A platform admin can read every record, including opted-out unfiled notes.
Rule 3 is the one that needs explaining. Intelligence produces claims everyone can see, and every claim links back to the sentence it came from. If that sentence sat in a note only one person could open, the link would go nowhere. So the flag that says "use this for company knowledge" also has to say "let the company see this."
Editing is stricter than reading: the author, or a platform admin. Attaching your note to a shared project lets other people read it. It does not let them change it.
Alternatives
Make every record belong to a project, the way conversations do. This would leave the service with one access rule instead of two, and no "attached to nothing" case to handle.
Rejected because people write things down before the work has a name. If a project were required, the first thing you would do is create a fake one to hold the note — and that fake project then appears in every project list, every digest, and every permission check from then on. Meetings and Slack channels have the opposite problem: they cover several projects at once, so picking one is also wrong.
Give every person a private project when they join. This keeps the "everything belongs to a project" rule technically true.
Rejected because the rule then means nothing. A project with one member that exists only so a database column is not empty is not a project. It also puts a membership wall around every personal note, which is the opposite of what a company-wide knowledge layer is for.
Let only the author read an unattached record. This sounds safer and is actually broken, for the reason in rule 3: the claim would be public and its evidence would not be, so nobody could check whether the claim was true. Claims are company-scoped by construction (ADR 0025).
Put notes and the Slack and Zoom connectors in a separate service. Notes would then live apart from the projects and conversations they relate to, and searching would mean calling two services and merging the results for no benefit.
The connectors themselves are a separate question and still open. They need URLs the internet can reach and stored login tokens per vendor, and workspace is the service the UI depends on, so that is not a good place for them.
Why
- People write things down before anyone decides who owns them. A system that demands the filing first is a system nobody writes anything into.
- Slack and Zoom do not know what a Flow project is. A connector knows a channel and a list of speakers. If we made it guess a project it would guess wrong, and a wrong project is a wrong permission rather than a wrong label.
- The speaker has to be recorded, not the caller. Every line stores who said it: a display name, plus a Flow account and the vendor's own user id where those are known. A Slack bot posting Alice's message records Alice. Without this, every imported line looks like the bot wrote it, and counting how many different people said something becomes meaningless.
Consequences
- The read rule is written twice: in Go, in
evidence.CanRead, for reading one record, and in SQL for search. The two have to be kept in step. Search cannot filter after ranking, because a result you may not see would still take a slot in the top ten, and its absence would tell you it exists. - Somebody in a meeting who does not work at Flow is recorded at the
externaltier (ADR 0027). What they said can be quoted as the source of a claim. It never counts toward "several independent people said this", because three customers agreeing is three people outside the company agreeing. - Turning the knowledge flag off is not a hint. Intelligence runs the same cleanup it runs for a deleted line: every claim resting on that record is flagged for review. The claims are not deleted, because other evidence may also support them.
- Notes and conversations have different minimums before we spend money on a model. A conversation needs four messages and 800 characters. A note needs 200 characters and nothing else, because a note is one piece of text somebody chose to write.
- "Everything in this project" is now two lists: what the project owns, and what has been attached to it.
0027 — How trusted a claim is, kept separate from where it is in the workflow
A claim carries a workflow column and a trust column that do not depend on each other, and nothing is ever stored as simply true.
0041 — Azure Service Bus in all environments
RabbitMQ removed. Azure Service Bus is the only broker, with the emulator used locally.