Hierarchies
Organization → workspace → project → campaign, and what each level scopes.
docs/HIERARCHIES.md
What contains what, and what each level actually scopes.
Organization the tenant. Every query is filtered by it, without exception.
└── Workspace a brand or a client. The scope unit below org. (F-004, planned)
└── Project the unit of work. Everything below hangs off it.
├── Budget one amount per channel per period
├── Member WHO can see this project — the agency scoping mechanism
├── Campaign a paid-media campaign on one platform (planned)
├── Calendar scheduled posts and slots (planned)
└── Agent run a proposal awaiting approval
What each level is for
| Level | Scopes | Enforced by |
|---|---|---|
| Organization | Everything. A cross-tenant read must find nothing. | organizationId in every where, at the data-access layer |
| Workspace | A brand or client inside an org. Social accounts, projects and media belong to one. | Planned — F-004 |
| Project | The unit an agency contractor is invited into. Membership is the scope, not the role. | projectScope(); an out-of-scope project 404s, so ids cannot be probed |
| Project member | What that person may do inside a project once they can see it. | assertCanWriteProject(); viewer is read-only |
The rule that matters
Belonging to the organization is not enough for an external role. An agency or client user
sees a project only if a ProjectMember row exists for them — see
D-009 and D-019.
The check is an allow-list of internal roles, not a deny-list of external ones. That direction is deliberate: a deny-list fails open, so any role it did not anticipate would get org-wide read of every project, its budgets and its team. That was a real finding — S-002 in the security register.
Two role systems, on purpose
They answer different questions and are checked in different places.
| Organization role | Project role | |
|---|---|---|
| Values | owner · admin · member · agency · client | lead · contributor · viewer |
| Answers | "What can this person do in the company?" | "What can they do on this project?" |
| Lives on | User.role | ProjectMember.role |
| Governs | Creating projects, managing billing, approving agent runs | Editing one project and its budgets |
An internal role is governed by its organization role alone. Everyone else needs both.