Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/docs/docs/concepts/stories-and-workspaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ scheduled activation to the same story. An idempotency key protects individual s
requests from network retries. These are different concerns: the external id identifies the body
of work, while the key identifies one requested operation.

A project member can continue a story created by another member. The conversation is shared
project state rather than a private chat transcript.
Any organization member whose role grants it can continue a story created by another member. The
conversation is shared project state rather than a private chat transcript.

## Durable and replaceable state

Expand Down
3 changes: 2 additions & 1 deletion apps/docs/docs/contributors/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ similar handwritten versions.

## Main request path

A UI or MCP request enters the API, resolves a principal, checks project scope and permissions, and
A UI or MCP request enters the API, resolves a principal, checks its organization-wide role
permissions and — for a project-scoped API key — that the key's project matches the request, and
calls a domain service. Starting or continuing a story persists its message and turn in PostgreSQL.
The worker claims the turn, resolves an exact agent manifest, wakes the workspace provider,
prepares `.facility.yml`, issues repository credentials, and starts or resumes Claude Code or
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/docs/guides/operate-story.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Use `facility_get_story` to inspect status and `next_operations`. Use
`facility_get_conversation` with its cursor for durable message history. Each agent message is the
run's final response; progress messages and logs live in the run's activity
(`/turns/:turnId/activity`). The UI renders the same conversation as request-and-response
exchanges and can continue it under the current user's project membership.
exchanges and can continue it under the current user's organization role.

The story timeline is the review path across the whole delivery. It shows which agent, model,
session, workspace, branch, and initial SHA started each turn; the final SHA, commits, files, and
Expand Down
10 changes: 6 additions & 4 deletions apps/docs/docs/reference/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ Facility still enforces:
- secret redaction from persisted command events and API responses; and
- explicit confirmation and idempotency for durable workspace deletion.

Authorization uses organization membership, roles, and route permissions. Project-scoped API keys
are pinned to one project and cannot enumerate others. Organization administration rejects scoped
keys. Audit events record successful privileged mutations with actor, target, project, and request
id.
Authorization uses organization membership, roles, and route permissions. A human role is
organization-wide: its permissions apply to every project in the organization, and a project
boundary does not contain a person. Project-scoped API keys are pinned to one project and cannot
enumerate others, so a scoped key is the only mechanism that contains a principal to one project.
Organization administration rejects scoped keys. Audit events record successful privileged
mutations with actor, target, project, and request id.

GitHub webhook signatures are verified over the raw body before JSON parsing. The installation id
must map to one active organization, and delivery ids are deduplicated within that installation.
Expand Down
22 changes: 15 additions & 7 deletions apps/docs/docs/self-host/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,17 @@ the API from the deployment secret store.

## Authorization behavior

Any active project maintainer can read and continue the same story. Every project operation checks
organization and project scope. Cross-project lookups return 404 so scoped credentials cannot use
the API as an enumeration oracle.
Human authorization is organization-wide. A role grants its permissions across every project in the
organization, and reading and acting are separate grants: `projects:read` is what reads a story and
its conversation, while `workspaces:execute` is what continues one, opens its preview, or suspends
it. `workspaces:execute` does not imply read access, so a role needs both to follow a story and act
on it. There is no project membership and no project dimension on either: "maintainer on one
repository" cannot be expressed.

The project dimension exists for API keys. A project-scoped key is pinned to one project, and a
cross-project lookup returns 404 rather than 403 so a key cannot use the API as an enumeration
oracle. Reach for a scoped key when automation should be contained to one project, and note the
trade-off: audit events then record the key rather than a person.

Roles and route permissions govern humans and API keys. They do not change an agent manifest into
a restricted workspace profile: once a principal is allowed to execute an agent in a project, the
Expand All @@ -139,13 +147,13 @@ requests remain available in structured service logs and can be correlated with
## Preview authentication

Preview cookies are separate from control-plane sessions. A one-time handoff issues an expiring
preview cookie; each proxied request revalidates the user, project membership, workspace, service,
expiry, and revocation status.
preview cookie; each proxied request revalidates the user, organization membership, workspace,
service, expiry, and revocation status.

The preview origin must be on a different registered site from Facility control origins. Opening a
service creates a one-time handoff; consuming it sets a host-only preview cookie. The preview proxy
rechecks membership on each HTTP request and WebSocket upgrade, so revoking membership, the
session, or the workspace stops continued access.
rechecks organization membership on each HTTP request and WebSocket upgrade, so removing the member,
revoking the session, or deleting the workspace stops continued access.

Never send a Facility API key, OAuth token, or control-plane session cookie to the application
running inside a preview.
Expand Down
Loading