Skip to content

Access & permissions

Access in WilsonOS rests on three ideas kept deliberately separate, and one rule about agents. Everything else — sharing a brand with a partner, letting a client view their own campaign, keeping two people’s private conversations apart — follows from them.

Concept Is Is not
User A person with credentials An agent
Brand A workspace that holds work A permission
Access grant A person’s rights on a brand A property of either

Collapsing any two of these is the usual mistake. A brand is not a permission; a person’s rights are a separate record that names the brand and a role — today admin and operator, with a read-only viewer role designed for clients who should see their brand and nothing else.

Access is granted on the brand, not the row

Section titled “Access is granted on the brand, not the row”

A person has rights on a brand; every task, deliverable, media item, and document inherits from the brand it belongs to. Per-file grants are a special case, not the model — otherwise the permission surface grows with the data, and nobody can answer “who can see this?” without a human checking.

So the practical questions have short answers:

  • Can a partner work in one of my brands? Grant them access to that brand. They see its work; they do not see the other brands.
  • Can a client see just their campaign? A viewer grant on their brand. Read-only, brand-scoped.
  • Can I see everything? An admin grant across the workspace.

Agents are not users. An agent acts for a person within a brand, and everything it writes carries both facts: which agent produced this, and whose it is. When Scout generates a cover for you, the record says Scout, for you, in Code Pineapple. Ownership is assigned by the writer at the moment of writing — never inferred later from a folder name, which is how the wrong person ends up owning something.

Because an agent’s authority is borrowed, it is also bounded. A conversation’s agent runtime works under your authorisation, for that conversation, in that brand. It cannot reach another person’s conversations, another brand’s files, or the workspace’s secrets. See How agents run.

Brand access gets you into the brand’s work. It does not get you into someone else’s private conversation in that brand. A private conversation belongs to its owner; a shared room has an explicit participant list. Being a member is the only way in — and being a non-member means the room is simply absent from your list, not greyed out. See Conversations.

  1. Every record that holds someone’s content carries an owner. Not most — every one. A table without an owner cannot be shared, revoked, or deleted on request.
  2. Default deny. A new kind of record starts inaccessible and is opened deliberately.
  3. Enforced in the database, not only in the app. An app-layer check protects only the paths that remember to call it; row-level rules protect all of them. Trusted server-side tools that bypass those rules are never an end-user path.
  4. Credentials are never indexed, searched, or synced. Secrets live outside the searchable corpus by construction.
  5. Ownership is assigned at write time. By the writer, never by inference.

live Users, brands, brand-scoped access grants, sign-in, and conversation membership checks are live. direction Owner columns and database-enforced access on every content table are being extended table by table; today the system runs for a single operator and those extensions are in progress. proposed Per-tenant agent runtimes and per-tenant billing — what a real multi-customer launch requires — are designed, not scheduled.

Sources: docs/architecture/identity-access.md §3–4, docs/architecture/chat.md (authorization), docs/wilsonos-app/multi-tenant-conops.md · Last verified 2026-09-15