Chapter 26

How Graph Space Gets Created

Every picture in Chapter 25 left one question unanswered: whose graph is this? A graph is not only Nodes and Edges. Who owns it, what range of data it holds, and who can reach it are part of the graph too. Vinc calls this boundary a space.

1. A space is one owner string

The graph engine has no notion of a team. It has one owner column holding an opaque string. A personal graph is a string beginning user:; a team graph is a string beginning team:. This is the owner of Chapter 10 §4.

That simplicity is why the whole team feature arrived without changing one line of schema. It is the dividend of the early decision to freeze field names and redefine only their meaning. A space is not a complicated separate object; it is the boundary that ownership scope draws.

2. Personal and team

A personal account is free or paid; a team is paid only. A person has one personal graph, and a team member has one team graph on top.

A team has three roles. A viewer may do every read. An editor adds the writes: document writes, merges, extraction, pack import. An admin adds the destructive operations: deleting Nodes and Edges, folding two Nodes, deleting a document, renaming a topic. Permissions are per operation, not per topic or per Node; finer permissions would mean planting a predicate in every query plan, which is separate work and was left out of the first version.

Enforcement happens at the hub, the point that cannot be bypassed because it holds the data, and again at the account's proxy. A drift test lives on both sides: the union of operation names in the role table must equal the proxy's allowlist, so adding an operation without assigning it a role breaks the build. That guard exists because a three-way list once drifted and killed one screen, on the web only, with nothing reporting it.

3. The owner does not come from the request

A client never names the graph it wants. The account service derives the owner from the authenticated subject and the requested team and signs it into an assertion. A client that could name the owner of its own graph would be a hole into another tenant.

Here sits the decisive point of the design. The team assertion is a new type, not a new field on the existing one. The reason is deployment order. Suppose an old hub meets a new account service. With a new field, the old hub does not know the field, sees a valid personal assertion, and forces the owner to personal. Team writes land silently in the member's personal graph. Team documents pile up where nobody looks, the team screen shows nothing, and there is no error anywhere. It is discovered days later as data loss.

With a new type, the old hub rejects it at the type check. Getting the deployment order wrong drops from a correctness problem to “the team feature is not open yet.”

4. The space is an argument

As Chapter 20 §4 said, which space a call works in is an argument on the call, and the default is personal. A session connected at a team address stays pinned to that team.

A default invites mistakes, and three guards repay them. A write reports the graph it landed in; initialization says where you are before anything is asked; and vinc_whoami answers which spaces this connection can reach and the role held in each. Call a tool without knowing which spaces exist and you can read or write the wrong graph.

5. Isolation on both sides

Mixing graphs of different owners breaks the trust a memory system rests on. It is not only a security concern; it is a retrieval-correctness one. A's search results must never contain B's Nodes.

So the scope is applied on both the read and the write path. Every match on a Concept, Episode or Record carries an owner predicate. Deletion and folding run only on an owner match, and if an owner is forced but the kind has no owner column, the operation is refused rather than run without a scope: an unscoped deletion is a cross-tenant deletion, so it fails closed. A fragment write skips a Node owned by someone else rather than merging it, because merging would restamp the owner and overwrite. The MCP layer overwrites any owner a client sends with the session's subject.

The lesson is one. One layer being right is not enough. The scope has to be in the key and in the column, on the read side and on the write side, or it leaks through the half that was left out. One transitional state remains in this graph: Bridge gained its owner column late, so old rows are empty and queries read “this owner or empty”. When the backfill is complete, deleting one clause makes it strict.

6. The blast radius of deletion

A member deleting their own account cannot harm the team graph. The erasure path can only derive a personal owner from a subject, so the team owner is structurally unreachable from it. A test pins that property rather than an inspection.

A team owner's account deletion is refused; they must delete the team or transfer ownership first. Team deletion is ordered and halts on failure: cancel the subscription, confirm the graph is erased, then delete the team, membership and invitation records.

A team graph carries no authorship record. Because the owner is the team, a Node does not say who wrote it. That needs a column and therefore a schema change, so it was left out of the first version and is written down as open.

7. Synchronization and space

The same owner's graph converges across machines. Graphs of different owners never merge into one synchronization scope.

Desktop synchronization of a team graph is not in the first version. Synchronization assumes one local graph maps to one account graph, and the cursor, the tombstone namespace and the conflict rules all stand on that pairing. Give one person a second remote graph and, until those three are redone, the personal graph and the team graph would overwrite each other. Web first is not a scheduling convenience; it is the boundary of what the present synchronization design can express.

8. Local use is not metered

Every limit in this chapter belongs to the hosted graph. Local mode is not counted and not metered. The desktop does ask for a sign-in at first launch, but that is an identity, not a limit: a check placed in a process on the user's own machine, opening a file the user owns, is a check the user can remove, so it is not a limit but an inconvenience. And working offline, with the documents staying on the machine, is what local mode is for.

The boundary that does hold is the one the server already enforces: anything that leaves the machine requires an account. The remote tool endpoint authenticates a key and stamps the owner from the reply, so there is no unauthenticated path to a hosted graph. Reaching the graph from a web AI, continuing on a second device and sharing packs all go through it.

9. A new space is not empty

When an account is created or a team is made, the account service writes in the Default Agents pack of Chapter 21: four roles under a reserved topic, not counted against a free account's topic cap. This is not a tier feature. Every space gets it.

In the end a space decides how far a graph is to be treated as one memory: whose memory it is, which data is searched together, who may change it. The graph now has time, evidence, shape, viewpoints to see it through, and a space wrapping the whole. What remains is how, inside that space, relations make before and after.

Continue with Chapter 27, How Causal Relationships Become Space.