oficina / suite Public

Clone
git clone https://amadan.net/oficina/suite

Plain git — no account needed to clone.

Download

Download this file

1# Findings on the suite sharing doctrine, revision 2
2
3**Verdict: request changes.** Reviewed by GPT-6 (Codex), 2026-09-05, independently of the draft and revision-2 authors. These are findings and proposed corrections, not new rulings. The doctrine has not been edited.
4
5The review covers the whole doctrine at `0c4f098`, including `git diff 609394e..HEAD`, and the sibling sources identified below. P1 means a trust boundary or promised security property is broken or lacks an enforceable design. P2 means a contract, adoption, or verification defect that needs correction before implementation.
6
7## Verdicts on the three priority changes
8
9| Change | Is the defect real? | Is the correction right? | Consequences |
10|---|---|---|---|
11| S2 intersects authorization with custody, §4.3 | Yes. A previously ingested id lets a consumer distinguish a private item still granted to the asker from a deleted item. The unintersected join in memoria §4.1 permits this. | Yes, for the stated current-visibility privacy guarantee. A determinate non-custodial item must not produce `VISIBLE` or an existence-revealing alternative. | The claim that correct consumers lose nothing is false. They can hold legitimately ingested items when visibility changes. See finding 8. The fix also does not erase those copies: finding 6. |
12| Typed asker on S2 and S6, §3 | Yes. Provisioning intent alone does not ensure that the two endpoints interpret the subject identically. | Yes. `{kind, value}` distinguishes a configuration mismatch from an authorization denial; `UNKNOWN` is the correct failure class. | Clean verdict on this change. Both request types and their fixtures must adopt it. Unknown or unsupported kinds must fail before item-dependent results; an unknown value of a supported kind can still be an ordinary denial. No extra network round trip is inherent in the tag. It does not prove shared authority or shared membership, and should not be claimed to do so. |
13| Hand-off checks `Origin` and asks for confirmation, §7.1 | Yes. Same-site cookies permit a sibling page to submit a credentialed form without a deliberate create action. | The two protections are appropriate, but the commit protocol is incomplete. The home citation supplies a return-host check and login-state binding, not an already specified document-confirmation protocol. | The receiving and committing requests need different rules. Existing middleware and content policy also block the proposed flow, and confirmation adds a round trip. See findings 4 and 9. |
14
15## Findings, ordered by severity
16
17### 1. P1 — Making directory rows authoritative leaves an instance-token route around roster step-up
18
19**Where:** doctrine §5.1, lines 221–225; §5.4, lines 279–283; §6, line 327; A.1. Home §6 and §9; Docs §9.1.
20
21**What is wrong:** §5.1 says the roster is the existing directory rows with `kind = member`, made authoritative. The doctrine also says home calls 1–6 are unchanged. Home call 2 lets an instance upsert and revoke its directory rows under a consumer token. Docs spells out the submitted `kind` at lines 607–608. That was safe only while directory rows were hints.
22
23**Why:** an instance can announce an attacker-controlled address as a member, or replay a queued pre-removal announcement. If call 8 derives the roster from those rows, the attacker becomes a team member without the owner action or fresh assertion required by §5.4. Conversely, instance-scoped deletion can affect membership if directory-row lifetime also defines roster lifetime. A table that serves both purposes needs a write-authority distinction; changing the reader does not create one.
24
25**Confidence:** high; this follows from the specified writers and the proposed source of truth, without assuming a broken token check.
26
27**Smallest correction:** give authoritative `(team, person, role)` membership its own owner-controlled record or equivalent protected provenance. Make call-2 rows projections/hints that cannot grant or revoke team standing. Amend the home-owned contract by citation after recording that boundary there. Test a member upsert, revoke, and delayed replay under an instance token against the authoritative roster.
28
29### 2. P1 — The compromised-home bound is false, including its claim of unavoidable evidence
30
31**Where:** doctrine §5.5, lines 292–301; §6.1, lines 359–361; §9 item 4, lines 502–503. Home §5.3–§5.5; activity design §2.2(b) and §5.1.
32
33**What is wrong:** the doctrine concedes that a compromised home can add members but says it still cannot read documents or act silently. It names owner step-up and the instance's cached roster as bounds on that compromise.
34
35**Why:** an added member can read team-visible content by definition. The attacker can use an account it controls after inserting that account into the roster. If compromise includes the credential origin and signing key, the attacker can also mint an assertion for an existing owner. The receiving grants join then authorizes that owner's actual rights; it cannot distinguish impersonation by the identity authority. The home spec explicitly identifies hostile `sub` as account takeover. This latter risk predates ruling 4.
36
37Step-up performed by the compromised authority does not constrain it. Nor is a directory row or notification unavoidable when the attacker controls the process that writes or sends it. Existing-identity impersonation need not create a membership row at all. The activity design already acknowledges that call 7 removes an observable distinction between normal home traffic and exfiltration (§2.2(b)).
38
39**Confidence:** high. A directory-origin XSS alone has a narrower scope; the doctrine must distinguish it from live directory-server or credential-origin compromise.
40
41**Smallest correction:** separate those threat models and disclose the resulting membership and impersonation capabilities in §5.5 and §9. Describe notifications as evidence produced by honest execution, unless an independent, enforceable audit mechanism is designed. Do not claim that an instance's grants join defeats compromise of the authority that names the grantee.
42
43### 3. P1 — The new writes have no contract for preserving or checking their source authority
44
45**Where:** doctrine §4.3, lines 185–188; §7.1–§7.2; §11; A.4. Memoria §5.2, §9.1, §10 gates 9, 17 and 19, and §12.
46
47**What is wrong:** transitive provenance is required, but the hand-off describes a document body and S8 describes actor and destination constraints. Neither defines how source identities and revisions survive a write into another app, or how that app enforces them on ordinary reads, exports, activity, and onward copies.
48
49**Why:** save an answer derived from a Sheet into Docs, then revoke or edit the Sheet. Docs' own grant to Ana is insufficient to authorize the saved answer under §4.3. Merely assigning the newly created Doc a Docs id must not reset authority. The generic declaration does not tell Docs how to recognize or check this case.
50
51There is also a concrete missing endpoint: an answer can include memoria-owned uploads or Notion material. Docs would need to check that source authority. Memoria decision 7, §9.1, and gate 17 explicitly prohibit sibling-facing endpoints; its §12 requires a new decision and leak entry before adding one. A.4 does not amend those clauses. A browser confirmation establishes the writer's intent, not an exemption from provenance.
52
53**Confidence:** high that the required contract is missing. A particular implementation might enforce the general rule correctly, but the proposed fixtures and amendments do not establish that it can.
54
55**Smallest correction:** define a bounded provenance envelope for both write paths, retain the original source authority, and require source checks on every disclosure path. Add the required memoria authorization surface through an explicit amendment, or defer hand-offs containing sources that the receiver cannot check. Add a two-hop write/read fixture with mixed authorities and a source revocation. Do not implicitly turn “save” into permanent republication.
56
57### 4. P1 — A confirmation page does not specify a protected commit, and a receiver check is too late to prevent cross-team transmission
58
59**Where:** doctrine §4.1, §7.1 lines 395–428, and §11 gate 7. Home §5.5–§5.6.
60
61**What is wrong:** the new rule describes the initial POST's origin check and a confirmation screen, but does not bind the final mutation to the reviewed pending body, the receiver's browser/session, or a single redemption. Applying the sibling-origin rule to both POSTs would also reject the final same-origin Docs form unless Docs unnecessarily had a consumer row for itself.
62
63**Why:** a bare second POST with a `confirm` flag can be submitted by the same allowed sibling that submitted the first. A screen appearing somewhere in the flow is not evidence that this browser reviewed this body. A nonce carried only in a URL is not itself browser binding; home §5.6 separately requires that binding to prevent login CSRF.
64
65The sending side needs a boundary too. If memoria's form action is misconfigured to another team's Docs host, the body has already reached that instance before its `Origin` check rejects it. §4.1's sibling HTTP-client guard does not automatically govern an HTML form action. This contradicts §0's literal “a byte … reaches an instance” test even when the receiver refuses to save it.
66
67**Confidence:** high that both obligations are unstated; this is a design gap, not a claim that a deployed hand-off is exploitable.
68
69**Smallest correction:** distinguish the draft-receipt and commit phases. Validate the exact same-team destination before rendering the sending form. Accept allowed sibling origins only at draft receipt; commit through a receiver-origin form against bounded, expiring, single-use pending state bound to the browser and authenticated person, with the reviewed body fixed server-side. Preserve safe rendering and framing restrictions. Gate forged commits, replay, changed bodies, session changes, absent/null origins, and a foreign-team destination before transmission. OWASP likewise treats same-site subdomains and actual request validation as distinct concerns ([CSRF prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)).
70
71### 5. P1 — Roster expiry does not yet bound revocation, and rollback can restore admission
72
73**Where:** doctrine §5.3 lines 249–275; §5.4 lines 285–286; §5.5 lines 298–299; §11 gate 5.
74
75**What is wrong:** a TTL triggers a refetch, but the doctrine never says what happens when that refetch fails. It still says requests enforce from the local copy and characterizes an outage or rollback as lag rather than admission.
76
77**Why:** cache epoch 10, remove Ana at epoch 11, then make the home unreachable. Retrying at expiry while continuing to enforce epoch 10 admits Ana indefinitely. Refusing stale membership decisions bounds that exposure, but costs availability and produces `UNKNOWN` for S2, not the gate's universal `NOT_VISIBLE`.
78
79A home restored to epoch 10 can also return Ana as a member to a receiver that already applied 11 unless lower epochs are rejected. An instance restored from backup must refresh before using its restored roster. A TTL alone does not settle either direction of rewind. “Within one epoch” is not an elapsed-time bound for an instance that has not learned the new epoch.
80
81**Confidence:** high; these are direct failure sequences for the specified cache.
82
83**Smallest correction:** state the usable-age limit and behavior after an unsuccessful refresh, including existing sessions and sibling reads. Publish a new roster only after a complete fetch and validation. Specify rewind detection/recovery and refresh-before-admission after restore. Express the revocation bound in time, including request deadline or grace if any; use a fake clock in gate 5 and separate successful revocation from unavailable authority. The TTL is an availability/security choice, not merely a sentence tightening or a number derivable from cold-wake latency.
84
85### 6. P1 — The “inside” invariant and leak bound ignore copies retained after visibility changes
86
87**Where:** doctrine §0 lines 38–41; §4.2; §9 item 1. Memoria §5.2, §6.1, §7.4 and §8.1.
88
89**What is wrong:** §0 describes current custody as an invariant, and §9 says a compromised sibling cannot read private items. The pull design necessarily retains formerly team-visible content after a source makes it private or deletes it.
90
91**Why:** memoria ingests revision 7 while team-visible; Docs then makes it private; memoria has not yet pulled `gone`. Publishing memoria's holdings now reveals content the team cannot currently read in Docs. S2 can prevent honest rendering, but cannot remove stored bytes. A compromised consumer can retain previously received content permanently. Memoria's snapshots, delayed pulls, and explicit circuit breaker against wholesale purges make it especially important not to equate denial at render with erasure of custody.
92
93This also limits the existence-hiding claim: `gone` can conceal the distinction between deletion and privatization; it cannot erase knowledge that an item existed before.
94
95**Confidence:** high; no implementation bug or malicious source is required for the initial retention window.
96
97**Smallest correction:** distinguish authorized acquisition, current authorization to render, and eventual retirement of honest cached copies. State the synchronization/retirement bound and restore obligation by citation. In §9 include historical content acquired while eligible and the inability to recall it from a compromised consumer. Rewrite §0's test to match those guarantees rather than promise instantaneous distributed erasure. Also scope the “across” test to suite-mediated flows: existing export/upload features cannot prevent a person deliberately copying material between teams.
98
99### 7. P2 — Gate 5 silently changes what removal means for guests and individual grants
100
101**Where:** doctrine §5.2 lines 227–237; §5.4; §11 gate 5, lines 569–572. Home §5.5; activity design §4–§5.2; Sheets §8.2; Docs §8.2.
102
103**What is wrong:** the gate requires every removed member to receive an empty call-7 response from every instance. The doctrine preserves instance-owned individual/guest grants and says nothing about guests changes.
104
105**Why:** remove Ana's team standing while leaving a valid grant to one document. The instance still owns that grant, and call 7 is specified to evaluate it. Returning its activity is correct under the cited contract. Returning empty solely because Ana is off the team roster revokes a right §5.2 leaves instance-side. S2's custody filter does not change the separate call-7 contract.
106
107**Confidence:** high. If complete offboarding is intended, that is an additional rule, not the current meaning of roster removal.
108
109**Smallest correction:** make gate 5's removed-person fixture explicitly have no remaining independent grants, and add a guest fixture that retains only its granted activity. Alternatively, specify a distinct complete-offboarding operation and its effect on instance grants. Do not implement that policy by asserting the desired empty list in a test.
110
111### 8. P2 — The S2 correction is right, but “costs a correct consumer nothing” is false
112
113**Where:** doctrine §4.3 lines 194–208; A.4. Memoria §4.1 and §6.1.
114
115**What is wrong:** the correction justifies its zero-cost claim using visibility at ingestion, even though its own attack depends on a later visibility change.
116
117**Why:** memoria correctly ingested a document when team-visible. It is now private but still granted to Ana; its `gone` row has not reached memoria, or an answer already being processed still contains it. Before this change, S2 could return `VISIBLE` for Ana. After it, S2 returns `NOT_VISIBLE`. Ana loses the passage and any derived answer requiring it in memoria, while direct access in the source app remains valid. Asking S2 about previously ingested content is exactly how a correct consumer checks current authorization.
118
119**Confidence:** high. This is a necessary product restriction under the chosen indistinguishability guarantee, not an argument to undo the intersection.
120
121**Smallest correction:** replace the zero-cost paragraph with that explicit consequence and a source-app fallback. Add a transition fixture: ingest, downgrade while retaining Ana's grant, query before feed catch-up, receive `NOT_VISIBLE`. Keep the private/deleted response equality. Require custody denial to dominate revision-specific diagnostics in S2 and S6; otherwise `STALE(cell)` or a numeric diagnostic can reopen an existence distinction.
122
123### 9. P2 — The hand-off needs middleware changes and an additional round trip
124
125**Where:** doctrine §7.1 lines 401–428; A.2 lines 710–713. Docs `internal/docs/app.go:406–445`; memoria `cmd/memoria/main.go:24,75–77`; their rastrillo pins.
126
127**What is wrong:** “no new machinery” and “neither costs a round trip” obscure actual consumer work. The proposed form cannot traverse the current sender and receiver unchanged.
128
129**Why:** memoria uses rastrillo v0.23.0's default `Content-Security-Policy`, whose `form-action 'self'` blocks a form targeting Docs. Docs places rastrillo v0.22.0's `csrf.Protect` above every route; its `SameOrigin` rejects `Sec-Fetch-Site: same-site` even with the legitimate memoria `Origin`. Its session middleware also refuses an unauthenticated POST rather than preserving its body through sign-in. Finally, for an already signed-in person, receipt → confirmation → commit requires a second POST where revision 1 committed on the first.
130
131**Confidence:** high. A temporary probe against Docs' actual pinned `csrf.Protect` produced `204` for a same-origin request and `403` for the proposed same-site request. Sender CSP and session behavior were checked in source, not exercised in a browser.
132
133**Smallest correction:** name the narrowly scoped sender `form-action` allowance, dedicated receiving route and its replacement origin guard, pending-body/sign-in handling, and additional confirmation round trip. Preserve the normal same-origin write protections elsewhere. Extend gate 7 through the real middleware and browser policy, including a successful same-team flow. A handler-only fixture would miss both blockers.
134
135### 10. P2 — Call 8 has no coherent paginated snapshot contract
136
137**Where:** doctrine §5.3 lines 244–247 and 269–271; §6 call 8.
138
139**What is wrong:** the review adds pagination but leaves the wire example unpaged, specifies no cap or cursor behavior, and says S2 and S6 already have cursors. They do not: their caps bound caller-supplied batches.
140
141**Why:** fetch page one at epoch 10, change the roster, then fetch page two at epoch 11. Combining the pages can produce a membership set that never existed, skip a removal, or omit an owner. Publishing a partial response has a similar effect. Neither the example nor the citation tells the client which snapshot it received or how to restart.
142
143**Confidence:** high, verified against memoria §6.1's signatures and §4.1's multiple-batch rule.
144
145**Smallest correction:** specify a bounded page shape with epoch-bound cursor, completion indication, and invalidated-cursor response. Require staging and atomic replacement only after all pages of one epoch arrive. Name restart behavior on epoch change and refusal to treat partial/failing results as an empty roster. Add concurrent-change and failed-middle-page fixtures. Replace the inaccurate comparison to S2/S6 pagination.
146
147### 11. P2 — The adopted S2 result vocabulary still lacks the source-behind case
148
149**Where:** doctrine §4.3 and §6's adoption of memoria §4.1; §11 gates 1–2. Memoria §4.1 lines 484–514 and its acknowledged §13 defect.
150
151**What is wrong:** the doctrine adopts four values without correcting the cited definition of `STALE`, which only covers a source that has moved past the requested revision.
152
153**Why:** memoria has revision 7 and a restored source has revision 5. Returning `VISIBLE` would serve an unverified revision; returning `NOT_VISIBLE` silently represents synchronization failure as a denial. The total decoder only checks response completeness and shape. It cannot repair a validly encoded wrong classification. Memoria already records this exact unresolved defect in §13.
154
155**Confidence:** high.
156
157**Smallest correction:** define the nonmatching-revision outcome for both directions, with a recovery distinction if needed. Preserve a loud failure whenever current revision authority cannot be established, while keeping determinate private/deleted denial indistinguishable. Add forward and backward revision fixtures and include the correction in A.4.
158
159### 12. P2 — The roster epoch does not pass the home claim test as cited
160
161**Where:** doctrine §5.3 lines 251–256; A.1 lines 687–691. Home §5.4.
162
163**What is wrong:** the doctrine says the epoch passes the existing test because a failed match is treated as absent. The home test requires non-identity claims to validate against a closed enumerated set and be cosmetically failable. A changing roster epoch is neither a closed cosmetic choice nor merely presentation data.
164
165**Why:** if “failed match” means a different valid epoch, discarding it suppresses the very refresh this feature needs. If it means a malformed claim, the text needs to say so. More fundamentally, suppressing a refresh can leave an old membership decision in force until TTL expiry. Refetching rather than trusting a claimed role is a useful safeguard, but it does not make this the same kind of claim as theme.
166
167**Confidence:** high about the citation mismatch. The bounded-staleness design can still be sound after finding 5 is resolved.
168
169**Smallest correction:** record a narrow invalidation-hint exception in the home-owned test, distinguishing invalid encoding from a valid differing epoch. Make call 8 authoritative and its freshness bound independent of the claim. Cite that exception here instead of saying the unchanged test already passes.
170
171### 13. P2 — The suite leak list omits new roster information and already-disclosed activity costs
172
173**Where:** doctrine §5.1, §5.3, §9, and §11 gate 8. Home §6/§10 and activity design §2.2 and §7.
174
175**What is wrong:** the list omits consequences of the features it adopts, and gate 8 claims the roster adds no column class.
176
177**Why:** home's existing directory `kind` distinguishes member from guest; it does not distinguish owner from member. The new `role` does. If stored openly, publishing the database now identifies team owners. If sealed, the disclosure and test need to say that. Call 8 also distributes the complete team roster and those roles to each instance, rather than just the people known to that instance under the old local models.
178
179The activity design explicitly discloses two suite effects in §2.2: a fine-grained signal of a person's front-door visits sent to their instances, and the loss of outbound-home traffic as a compromise signal. Neither appears in §9. Its §7 also retains last activity in RAM briefly after removal. Those are relevant alongside the existing title-in-RAM entry. Findings 2 and 6 identify two further bounds that need correction, rather than additional reassuring prose.
180
181**Confidence:** high; the old directory schema and the activity disclosures are explicit.
182
183**Smallest correction:** add citations for these costs in §9, choose the roster-role storage/disclosure treatment, and amend gate 8's expected disclosure accordingly. Exercise the actual persisted schema and failure paths; one roster fixture cannot prove that an entire database has no additional information class. An audit of column types alone also misses new information encoded in existing columns.
184
185### 14. P2 — The consuming amendments preserve contradictions and introduce restatements
186
187**Where:** doctrine §10; §12 steps 1–3; Appendix A; repository `AGENTS.md`.
188
189**What is wrong:** the prescribed amendments do not produce the cited, consistent specs that §12 says unblock implementation.
190
191**Why:** several concrete leftovers survive them:
192
193- A.2's proposed Docs sentence names sibling service “in suite shape”; §3 and §12 explicitly require Docs and Sheets to serve lone peers before the home exists. The amendment must name the independent sibling-token switch or cite it without narrowing the scope.
194- A.4 leaves memoria §11's explicit person-ref/home dependency on slice 1, its no-inbound-surface decision and gate, and its stale S7 admission gate. Replacing §4.3 alone does not remove those contradictions. Finding 3 makes the inbound-surface conflict operational rather than editorial.
195- A.1–A.3 prescribe paragraphs paraphrasing boundaries, membership, and egress. That is the practice `AGENTS.md` and §10 say to replace with ruling-and-commit citations. Adding a citation after another copy of a rule still leaves another copy to drift.
196
197**Confidence:** high; these are literal mismatches between the proposed replacements and the surviving source text.
198
199**Smallest correction:** revise Appendix A as a complete list of consuming sections and gates to replace with citations, including the independent shape/token switch, memoria sequencing, admission fixtures, and required new authority surface. Keep locally owned behavior local. Do not declare slice 1 unblocked until the resulting specs agree; the doctrine itself can remain findings-only in this review.
200
201### 15. P2 — Two stated sibling positions are not what their cited text says
202
203**Where:** doctrine §2, §8 lines 474–479, §10 lines 523–527, A.2 §11.2, and A.3's AGENTS amendment.
204
205**What is wrong:** the doctrine supplies a new reason for Docs' conversion-API rejection and treats Sheets' local spec-synchronization rule as a cross-repository rule.
206
207**Why:** Docs §11.2, lines 929–931, rejects conversion APIs because they send customer documents to a third party. It does not say the provider was unnamed or the sending unavoidable. A per-team optional converter with a named provider could satisfy suite §8, so the narrower reason is a policy qualification, not verification that the old rejection already meant it. The ruling may authorize that qualification; the cited passage does not establish its historical premise.
208
209Sheets `AGENTS.md`, lines 5–7, says that where **that file** disagrees with **its design spec**, the spec wins and the file must be fixed in the same commit. Both files are in Sheets. It does not demand one atomic commit spanning five repositories. Replacing that rule would remove a useful local consistency obligation to solve a problem it did not create.
210
211**Confidence:** high for both readings.
212
213**Smallest correction:** identify the Docs change as an intentional qualification under suite ruling 6, with its prior reason accurately cited. Retain Sheets' local same-commit rule and add a separate suite-citation requirement. Do not attribute the new positions to the earlier text.
214
215### 16. P2 — Citation currency can stay green across binding changes
216
217**Where:** doctrine §11 gate 9, lines 584–590; §10; Appendix A's introduction.
218
219**What is wrong:** the new measurable revision only has to increase for changes to §1 or §6. Binding behavior also lives in §3–§5 and §7–§8.
220
221**Why:** change the hand-off commit rule or roster stale-cache policy in its owning section, leave §6's citation untouched, and the prescribed revision can remain unchanged. A consumer of the old behavior passes currency indefinitely. The gate also does not specify checking that a claimed revision actually belongs to the cited commit. The appendix still asks only for a commit, although the new gate requires both.
222
223**Confidence:** high.
224
225**Smallest correction:** bump the revision for every normative contract change, wherever it lives; derive or verify revision from the cited commit; and update the consuming-section format consistently. A one-revision grace period is measurable, but remains a deliberate compatibility allowance, not proof that a consumer follows current security requirements.
226
227## Gate-by-gate assessment
228
229These are assessments of the proposed tests. No contract module exists here, so none of its gates was executed.
230
231| Gate | Can it be written as stated? |
232|---|---|
233| 1. Fixture conformance | The harness can be written. Complete golden requests/responses still need the missing call-8/write shapes and error precedence resolved. Generic conformance must distinguish the calls each app actually serves; S6, for example, belongs to Sheets. |
234| 2. S2 total decoder | Yes as a bounded decoder property, including an unsupported subject kind. It does not prove correct authorization or revision semantics: findings 8 and 11 need semantic fixtures. |
235| 3. Custody | Yes with clarified fixtures. “Grant on a deleted item” should mean a former grantee or retained grant row, not require a dangling live grant contrary to an app's schema. Compare responses for the same requested id in private/deleted alternative states. Add the transition in finding 8. |
236| 4. No cross-team dial | Literal zero connections for a server-issued redirect is impossible: the client must connect to the allowed first host to receive the redirect. Require zero connections for an initially forbidden host and zero **follow-up** connections after an allowed host redirects. Use two fixture servers or an instrumented transport. |
237| 5. Roster | Not yet. “After one epoch” lacks an observation/time condition; failed refresh and retained guest grants have conflicting expected results. See findings 5, 7 and 10. The lone-instance no-home-network assertion is independently testable. |
238| 6. Write-as-self | Yes for the three stated access checks, but derive actor identity from the authenticated consumer and test attempted actor spoofing. Actor/destination checks alone do not exercise provenance; finding 3 needs its own gate. |
239| 7. Hand-off | Not as a complete proof yet. Define receipt/commit states and test through actual middleware plus browser policy. A screen-render fixture cannot establish user-confirmed mutation. See findings 4 and 9. |
240| 8. Publish database | A seeded database disclosure test is feasible. The unchanged-information premise is false or at least undecided for owner roles, and a roster response fixture does not establish at-rest behavior. See finding 13. |
241| 9. Citation currency | Arithmetic is feasible; normative coverage and commit/revision agreement are missing. See finding 16. |
242
243## Sources and verification limits
244
245Paths below identify the exact local documents used. Section and line references in the findings refer to those files as read on 2026-09-05.
246
247| Source | Checkout and commit |
248|---|---|
249| [Doctrine](docs/superpowers/specs/2026-09-05-suite-sharing-doctrine.md) | This worktree, `0c4f098`; all sections read, revision-1 diff inspected. |
250| [Home design](/home/paulca/amadan.net/oficina/home/.claude/worktrees/trunk/docs/superpowers/specs/2026-08-30-home-design.md) | `home/.claude/worktrees/trunk`, `5a42f2d`. The supplied primary checkout is on older `domain/oficina-works` at `462df84`, which lacks rulings 17–21; those citations were checked against `main` instead. |
251| [Activity design](/home/paulca/amadan.net/oficina/home/.claude/worktrees/design-activity-pull/docs/superpowers/specs/2026-09-05-activity-pull-design.md) | `design-activity-pull`, `c9274bf`; still explicitly awaiting independent review. Adoption in principle is not approval of all its protocol details. |
252| [Memoria design](/home/paulca/amadan.net/oficina/memoria/docs/superpowers/specs/2026-09-03-memoria-design.md) | `617eb2a`; relevant contracts, grants, ingestion, snapshots, gates and acknowledged open defects inspected. |
253| [Docs design](/home/paulca/amadan.net/oficina/docs/docs/superpowers/specs/2026-08-30-docs-design.md) | `f6cf5c2`; also checked router/session integration and the v0.22.0 rastrillo CSRF implementation. |
254| [Sheets design](/home/paulca/amadan.net/oficina/sheets-core/docs/superpowers/specs/2026-08-30-sheets-design.md) | `bad02cb`; grants join, roles, home contract, PRODUCT.md and AGENTS.md checked. |
255| [Calendar design](/home/paulca/amadan.net/oficina/calendar/.claude/worktrees/calendar-first-screens/docs/superpowers/specs/2026-09-02-calendar-design.md) | `calendar-first-screens`, `f18898b`; no spec exists at the brief's primary-checkout path. The worktree spec and `internal/calendar/models.go` confirm the team-calendar grant model and absence of a commenter role. |
256
257The module-path claim in §10 is correct for the checked `go.mod` files: Docs alone still uses `github.com/carlosframework/docs`. The S4/S5 resolution is supported by memoria §6.1. The home really does specify return-host allowlisting and browser-bound login state; finding 4 concerns the additional document-write protocol, not the existence of those protections.
258
259Browser-request reasoning was checked against the [Fetch Standard's Origin handling](https://fetch.spec.whatwg.org/#origin-header) and [OWASP's CSRF guidance](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html). The middleware probe ran from a temporary file, using the installed dependency without network access; it made no live HTTP request. No end-to-end browser test or deployment was performed. Cross-repository discussions were not sent, and claims about Paul's private brainstorm or discussion 33's full contents were not treated as independently verified evidence.
260