Record review model metadata and merged consumer prerequisite
1 file changed,
+2
−2
implementation/team-directory.md+2 −2
CI passed — run details
diff --git a/implementation/team-directory.md b/implementation/team-directory.md| index 914f0f6..393aa19 100644 |
| --- a/implementation/team-directory.md |
| +++ b/implementation/team-directory.md |
| @@ -1,6 +1,6 @@ |
| # Authoritative team directory and app entry |
| -Status: revised implementation design, based on Home cc61976. First independent review requested claude-fable-5 and returned CHANGES REQUIRED; the response self-identified as Sonnet 4.5, so reviewer identity/capability is unresolved and this is not an approval. Corrections below require a new qualified review. This is an internal implementation plan; no deployed feature is claimed. It preserves Home spec rulings 17, 19, 22, 23 and suite doctrine §5.3. The user accepted team subdomains and waived copy review for this round. |
| +Status: revised implementation design, based on Home cc61976. First independent review returned CHANGES REQUIRED. Runner args and ten emitted event.model fields identify claude-fable-5; response prose self-identified Sonnet 4.5, which conflicts with that metadata and is not authoritative serving-model evidence. The CLI model catalog lists claude-fable-5 as its most capable model. Corrections below require a second verdict; no approval is claimed. This is an internal implementation plan; no deployed feature is claimed. It preserves Home spec rulings 17, 19, 22, 23 and suite doctrine §5.3. The user accepted team subdomains and waived copy review for this round. |
| ## Source audit and scope |
| @@ -48,7 +48,7 @@ For implementation sequencing, first build and test this operator protocol and d |
| ## Membership writes and roster contract |
| -Owner changes are same-origin directory POSTs. Use a distinct sensitive-operation consumer completion path, not the ordinary callback that replaces the directory session. Bind the pending intent to the initiating subject, actual existing directory session token hash, shared consumer-generated nonce, team and action digest. The sensitive Complete callback checks those bindings against the still-current session and records only the verified fresh proof in the sealed intent; it does not call sessions.SignIn or rotate the session. A changed or expired session requires a new intent. Consume the intent once at confirmation. The shared StartFresh/BindStart consumer extension is a prerequisite on a separate reviewed branch; do not emulate its replay/freshness policy in the directory. Credential max_age=300 support already exists at this base in assertion_fresh_test.go and exchange.go via the fresh-assertion stage merged before cc61976: it forces actual re-verification and preserves second-factor/recovery completion gates. The older team-entry.md transport narrative is stale on that addition, not proof that max_age is unsupported. Require integration tests that prove a stale credential session reauthenticates, the directory token remains unchanged through this sensitive path, and wrong-subject/expired/changed-token intents fail. Recheck the actor's current owner role within the membership mutation transaction. Require the submitted action to match the sealed digest and prevent removing/demoting the last owner. Fresh authentication proves identity, not ownership. Call 2 and consumer tokens cannot write membership. |
| +Owner changes are same-origin directory POSTs. Use a distinct sensitive-operation consumer completion path, not the ordinary callback that replaces the directory session. Bind the pending intent to the initiating subject, actual existing directory session token hash, shared consumer-generated nonce, team and action digest. The sensitive Complete callback checks those bindings against the still-current session and records only the verified fresh proof in the sealed intent; it does not call sessions.SignIn or rotate the session. A changed or expired session requires a new intent. Consume the intent once at confirmation. The shared StartFresh/BindStart consumer extension is now merged at Home4d3039c and verified on preview02f9ac0 (root integration evidence); consume its actual published module version when implementing this design; do not emulate its replay/freshness policy in the directory. Credential max_age=300 support already exists at this base in assertion_fresh_test.go and exchange.go via the fresh-assertion stage merged before cc61976: it forces actual re-verification and preserves second-factor/recovery completion gates. The older team-entry.md transport narrative is stale on that addition, not proof that max_age is unsupported. Require integration tests that prove a stale credential session reauthenticates, the directory token remains unchanged through this sensitive path, and wrong-subject/expired/changed-token intents fail. Recheck the actor's current owner role within the membership mutation transaction. Require the submitted action to match the sealed digest and prevent removing/demoting the last owner. Fresh authentication proves identity, not ownership. Call 2 and consumer tokens cannot write membership. |
| Call 8 is a bearer-authenticated GET, scoped from the consumer record rather than a caller-selected team. Unknown team and foreign team both return 404. Return versioned strict JSON: generation, per-team epoch, sorted members `{person_ref, role}`, explicit complete flag and optional cursor. Bound each page to 100 entries and 64 KiB, and each team to 10,000 members for this pilot. A cursor is authenticated and bound to consumer ID, team, generation, epoch, last person ref and expiry. A concurrent roster write invalidates the cursor; no mixed epoch can complete. Only an explicit complete response represents an empty roster. |