[READ-ONLY] Mirror of https://github.com/flo-bit/contrail. atproto backend in a bottle flo-bit.dev/contrail/
0

Configure Feed

Select the types of activity you want to include in your feed.

docs(auth): document binding-layer trust assumptions

Two trust assumptions in the binding layer cannot be closed at the
Contrail layer alone:

- DID-doc service-entry rebind: deployments using
createDidDocBindingResolver inherit PLC's rotation-key authorization
model. Any rotation key on the owner's account can rewrite the
#atproto_space_authority service entry.

- PDS app password held for managed communities: community.provision
and community.adopt hold unscoped app passwords that can write any
record on the user-owned PDS, including the binding declaration
read by createPdsBindingResolver.

Both are constraints of their respective binding sources and
onboarding flows, not bugs. Document each so operators picking a
binding strategy can size them against their own threat model, with
pointers to the canonical issues for the upstream/protocol-level
work that would close them: #38 (DID-doc), #39 (PDS app password).

Tom Scanlan (May 8, 2026, 10:43 AM EDT) dffbd36c 428feead

+31
+22
docs/05-auth.md
··· 190 190 191 191 Public requests skip all verification middleware — no JWT parsing, no DID-doc fetch. Fast path. 192 192 193 + ## Trust assumptions 194 + 195 + Two trust assumptions in the binding layer cannot be closed at the Contrail layer alone. They are listed here so operators picking a binding strategy or onboarding flow can size them against their own threat model. 196 + 197 + ### DID-doc binding path 198 + 199 + The record host can resolve a space's authority from three sources (see [Spaces § Discovery](./06-spaces.md#discovery--binding-resolution)): 200 + 201 + - **Local enrollment** — the host's own `record_host_enrollments` table, written via `recordHost.enroll`. Owner-signed; the host has full control over what's stored. 202 + - **PDS record** — read from the owner's PDS at the space URI. 203 + - **DID-doc service entry** — read from `service[id="#atproto_space_authority"]` on the owner's DID doc. 204 + 205 + The DID-doc path inherits PLC's authorization model: any rotation key on the owner's account can submit an update op rewriting the service entry. There is no per-entry signature or "this entry can only be edited by key X" constraint at the PLC layer. 206 + 207 + If the integrity of the space-authority binding needs to exceed what any one of the owner's rotation keys can already do, configure the host to resolve via local enrollment instead, or wait for an upstream signed-binding mechanism. Tracked upstream as [flo-bit/contrail#38](https://github.com/flo-bit/contrail/issues/38). 208 + 209 + ### Contrail-held PDS app password 210 + 211 + Deployments running `community.provision` or `community.adopt` necessarily hold an ATProto app password for the user-owned PDS account so Contrail can write on the community's behalf. ATProto app passwords are unscoped at the PDS layer — they can write any record to the repo, including the `tools.atmo.space.declaration` record (or its embedded equivalent on a space-type record) that drives binding decisions in `createPdsBindingResolver`. 212 + 213 + This is an intentional consequence of the managed-community model, not a bug. Operators should treat stored app passwords with the same care as rotation keys, and reach for scoped app passwords (when ATProto adds them) or signed binding records to tighten the model further. Tracked upstream as [flo-bit/contrail#39](https://github.com/flo-bit/contrail/issues/39). 214 + 193 215 ## How the pieces fit 194 216 195 217 A typical flow for a third-party app acting as a user in a space:
+9
docs/10-deployment-shapes.md
··· 192 192 193 193 When in doubt, all-in-one. Splitting is for when you have a real operational reason to separate the two — different teams running them, different latency profiles, different scaling targets, different governance. 194 194 195 + ## Known trust assumptions 196 + 197 + Two assumptions in the binding layer cannot be closed at the Contrail layer alone, and which one applies depends on the shape you pick: 198 + 199 + - Deployments wiring `createDidDocBindingResolver` inherit PLC's rotation-key authorization model for the `#atproto_space_authority` service entry. Tracked as [flo-bit/contrail#38](https://github.com/flo-bit/contrail/issues/38). 200 + - Deployments running `community.provision` or `community.adopt` hold an unscoped ATProto app password for each provisioned PDS account. Tracked as [flo-bit/contrail#39](https://github.com/flo-bit/contrail/issues/39). 201 + 202 + See [Auth § Trust assumptions](./05-auth.md#trust-assumptions) for the constraints in detail and what binding source to prefer when those assumptions don't fit your threat model. 203 + 195 204 ## What's not here 196 205 197 206 - **Authority migration** — moving a space's authority from DID A to DID B. The architecture supports it (re-enroll on the host with the new authority binding) but no helper API yet.