Skip to content

fix(plugin-auth): the no-sign-in-account boot report states the email-verification rule as shipped - #20434

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-20413-boot-report-verification-text
Sep 28, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-20413-boot-report-verification-text

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #20413

Clause-②: no

Round 2 of the card, location 4: the plugin-auth boot report. Round 1 (PR #20421, landed as 24b70859) covered locations 1–3. This round completes the card. It changes text, comments and tests only. No admission decision, verification default or accepted value moves.

What changed

The no_sign_in_account_at_boot report tells an operator to recover a locked-out deployment by inviting one address. Its advice said an 'open' or 'email_domain' posture "forces email verification on the INVITED login too". Later, in remedy (b), the same message said verification is forced "unless an 'open' deployment has itself declared it off". The first sentence stopped being true when open began honouring a deployment's opt-out (65352b7d, #20406), so the message contradicted itself.

The rule, re-derived from packages/plugins/plugin-auth/src at 24b70859:

  • resolveEmailVerificationRequirement (audience-posture.ts), the one resolver the better-auth wiring and getPublicConfig() both read:
    • email_domain is always on;
    • open is on unless the declared value is false;
    • invite_only uses the declared value, off by default.
  • assertAudienceConfig refuses an explicit false under email_domain from any source. Under open it refuses a false whose declarant is console.
  • applyConfigPatch (auth-manager.ts) marks a patch as the deployment's unless its caller passes requireEmailVerificationFrom: 'console'.
  • The invitation carve-out in decideAudienceAdmission returns only admit and grantPermissionSet, so it cannot exempt anyone from verification. The only row born emailVerified: true is the walled-owner operator stamp, and an invitation-admitted creation never gets it.

The message now:

  • states the rule once, in the invitation paragraph:
    • the INVITED login meets the same email-verification rule as any sign-up;
    • email_domain is always ON;
    • open is ON unless the DEPLOYMENT declared it off (emailAndPassword.requireEmailVerification: false or OS_AUTH_REQUIRE_EMAIL_VERIFICATION=false), and a false stored only through the settings console is refused there;
    • invite_only follows that declaration and is OFF by default.
  • keeps the scoped no-mail-transport rider and the advice order ("close the posture back to 'invite_only' BEFORE that person registers"). It adds "and leave verification at its default OFF", because under invite_only a declared true would still apply.
  • in remedy (b), refers back to that rule ("wherever it is ON") instead of restating it.

The advice still matches content/docs/deployment/self-hosting.mdx ("Email verification under each posture"), which the module docblock names as this message's long form. That page already stated the rule correctly.

Files:

  • packages/plugins/plugin-auth/src/boot-sign-in-reachability.ts: the remedy string, plus the file docblock's invitation bullet (the old "third bullet below applies to the INVITED login too" sentence).
  • packages/plugins/plugin-auth/src/boot-sign-in-reachability.test.ts:
    • the pin at the old line 164 is flipped. It now asserts the new text's substance: the invited-login rule, email_domain always ON, the open conditional, the console refusal, and the rider's new wording.
    • two negative pins are added, one per old unconditional spelling.
    • a new #20389 describe drives each clause against the manager: open + the deployment's false wires OFF; the same false from the console is refused and stays ON, with the deployment patch as control; email_domain + false refuses the boot, with a control; invite_only is OFF by default and ON when declared.
    • three titles and comments that repeated the old quantifier now say "with nothing declared".
    • managerWith takes an optional deployment emailAndPassword block.
  • packages/plugins/plugin-auth/src/auth-manager.ts: one comment near the old line 2295 (the plugin-auth: a sign-up for an address that already has a sys_user row answers 200 and persists nothing (posture email_domain) #15587 uniqueness-refusal block), restated as "on by default".
  • packages/plugins/plugin-auth/src/signup-existing-address-refusal.test.ts: one docblock sentence (old line 30), restated the same way.
  • .changeset/20413-boot-report-verification-text.md: @objectstack/plugin-auth patch. The boot report prose ships.

Stale-phrase counts across packages/plugins/plugin-auth/src, BASE 24b70859 → HEAD 7898a47d: "INVITED login too" 2 → 0; "every posture other than 'invite_only' ('open'," 1 → 0; "self-registration FORCES requireEmailVerification on (see" 1 → 0; "self-registration-permitting posture FORCES requireEmailVerification" 1 → 0; "third bullet below applies to the INVITED login too" 1 → 0.

Verification (all at HEAD 7898a47d)

  • Build: pnpm --workspace-concurrency=2 --filter '@objectstack/plugin-auth^...' build, run through the verify lock: VERDICT command-exit 0. Then pnpm --filter @objectstack/plugin-auth build: check-dts-emitted 2/2.
  • Targeted tests: pnpm --filter @objectstack/plugin-auth exec vitest run --maxWorkers=2 src/boot-sign-in-reachability.test.ts src/signup-existing-address-refusal.test.ts gave Test Files 2 passed (2) / Tests 59 passed (59).
  • Package tests: pnpm --filter @objectstack/plugin-auth exec vitest run --maxWorkers=2 gave Test Files 114 passed (114) / Tests 2458 passed (2458).
  • Typecheck: pnpm --filter @objectstack/plugin-auth run typecheck exited 0. It runs tsc --noEmit, the examples project, and check:test-typecheck, which reported "OK … 10 file(s) / 94 error(s) … held in test-typecheck-debt.json".
  • Reverse verification. The fix was committed first. Each leg ran through scripts/ablation-replace.mjs in WRAP mode, with a driver trap that restores from HEAD by absolute path. The test imports the module by relative path, so it reads src/ and no rebuild was needed between legs.
    • Leg A put the old sentence back in place of the new one. The anchor went 1 → 0 and the blob went b0be40fa → d1b521c9. Result: Tests 1 failed | 50 passed (51), failing [#15588/F1] the no-mail-transport rider is SCOPED to the default posture with "expected '[auth] no_sign_in_account_at_boot: th…' to contain 'under the default 'invite_only' pos…'".
    • Leg B added the old sentence beside the new text. Result: the same single test red, on the negative pin "not to match /an 'open' or 'email_domain' posture …/i".
    • Leg C added the old remedy-(b) quantifier. Result: the same single test red, on "not to match /every posture other than 'invite_onl…/i".
    • After all three legs, the blob equals the HEAD blob (b0be40fa) and git diff HEAD is empty. The direction observed was red, as expected.
  • Lint, narrowed to the 4 touched .ts files: eslint --no-inline-config --format json linted 4 files with 0 errors and 0 warnings. eslint.config.mjs never enables type-aware linting (no parserOptions.project, no typed rules), so this diff cannot change a verdict on an untouched file. The repo-wide run belongs to CI.
  • Derived gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 64 commands over these 5 paths. --ran reconciled "64 derived, 62 run, 2 NOT-MEASURED, 0 UNRUN". All 62 that ran exited 0.
    • NOT MEASURED: pnpm check:dual-build-cjs-loads exited 3 with PREREQUISITE NOT MET, because it needs every package's dist/ and this tree built only the plugin-auth closure. Declared narrowing, applied to the one touched package: node --check dist/index.js exits 0, and require('./dist/index.js') loads 143 exports. The new text is present in dist/index.js and dist/index.mjs (1 each), and the old phrase in neither (0 each).
    • NOT MEASURED: pnpm check:type-check-debt exited 3 with PREREQUISITE NOT MET, because @objectstack/runtime, service-cluster and service-job have no built types here. Declared narrowing: the ledger's DEBT keys are cloud-connection, hono, observability and spec-monorepo, none of which depends on plugin-auth, and TEST_DEBT is empty. The only non-comment source change is the content of one string literal, so no type moves.
  • check:nul-bytes: OK. Control-byte self-scan over the 5 files: no hits.

Acceptance notes

Sweep, at 24b70859: lines naming email verification (email.?verification|requireEmailVerification|EMAIL_NOT_VERIFIED|REQUIRE_EMAIL_VERIFICATION) that also carry a forcing or quantifier word (forc|other than invite_only|every posture|permitting posture|widen). That gave 51 lines in 19 files, and every hit outside round 1's surface was read in context. In the files this round owns, all hits are fixed.

Stale or incomplete outside this round's surface. All are comments or frozen history; none is edited here.

  • packages/plugins/plugin-auth/src/audience-gate-test-support.ts:17: "open (and email_domain) force requireEmailVerification on". This is a docblock explaining why fixtures use the invitation lane. It is true for the undeclared fixture config but omits open's opt-out. No carrier.
  • packages/plugins/plugin-auth/src/admin-remove-user-gate-ordering.test.ts:135: "open would force email verification on". The same shape, in a test comment. No carrier.
  • packages/verify/src/harness.ts:778: "open and email_domain force requireEmailVerification on". The same shape, in a comment. No carrier.
  • packages/spec/src/migrations/entries/semantic/18.audience-posture-default-invite-only.ts:19, and its generated mirror packages/spec/src/migrations/registry.ts:6270: "accepts forced email verification". This is the v18 migration's reason text, accurate for that release. It is packages/spec history, not live advice.

Read and left, because each is correct: audience-posture.ts:221 (it says "unless noted", then notes the open exception); auth-manager.ts:1639 (it carries the #20389 exception); the runtime log at auth-manager.ts:4818 ("… when email verification is forced on" is a sufficient condition, not a rule statement); packages/spec/src/system/auth-config.zod.ts lines 408–419 and 588; content/docs/deployment/self-hosting.mdx:580 and its posture section; content/docs/deployment/environment-variables.mdx:84; and the audience-posture*.test.ts assertions, which pin the refusal messages as they stand.

auth-plugin.ts has no hit, so nothing reaches the file #20412 holds.


Generated by Claude Code

…-verification rule as shipped

The recovery advice said an 'open' or 'email_domain' posture forces email
verification on the invited login, while remedy (b) in the same message
conceded the 'open' deployment opt-out. The message now states the rule
once, as resolveEmailVerificationRequirement and assertAudienceConfig
enforce it: email_domain always on; open on unless the deployment
declared it off (a console-stored false is refused); invite_only follows
the declaration, off by default. Remedy (b) refers back to that rule.

The pin flips to the new text's conditional and the email_domain forced
case, with a negative pin on both old unconditional spellings, and a new
describe drives each clause against the manager. The file docblock, one
auth-manager.ts comment and the signup-existing-address-refusal.test.ts
docblock are restated the same way. Text and tests only.

Claude-Session: https://claude.ai/code/session_017B6YKCGu8CTY2KBWgwaHAs
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/plugin-auth, touching 4 documentable anchor(s).

2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/environment-variables.mdx (via email_domain (literal, a string literal in resolveNoSignInAccountReport))
  • content/docs/deployment/self-hosting.mdx (via email_domain (literal, a string literal in resolveNoSignInAccountReport), invite_only (literal, a string literal in resolveNoSignInAccountReport))

⛔ 2 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-3.mdx (via email_domain (literal, a string literal in resolveNoSignInAccountReport), invite_only (literal, a string literal in resolveNoSignInAccountReport))
  • content/docs/releases/v17/index.mdx (via invite_only (literal, a string literal in resolveNoSignInAccountReport))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 15 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json e01d3473053d2d43f5fca0db98b0409744695a5a → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 6dacb326ff05c5bd57ac70d739acdaf879f10f9a — the merge of head 7898a47de302e2d9838b0c4bfdb82ab459739bec into base e01d3473053d2d43f5fca0db98b0409744695a5a, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 6dacb326ff05c5bd57ac70d739acdaf879f10f9a && git checkout 6dacb326ff05c5bd57ac70d739acdaf879f10f9a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e01d3473053d2d43f5fca0db98b0409744695a5a 7898a47de302e2d9838b0c4bfdb82ab459739bec && git checkout -B drift-repro e01d3473053d2d43f5fca0db98b0409744695a5a && git merge --no-ff 7898a47de302e2d9838b0c4bfdb82ab459739bec

node scripts/docs-audit/affected-docs.mjs --json e01d3473053d2d43f5fca0db98b0409744695a5a

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs e01d3473053d2d43f5fca0db98b0409744695a5a → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 7898a47de302e2d9838b0c4bfdb82ab459739bec
Local-runs: none

Inputs: card #20413 body and all 8 comments (claims 5867222316/5868567572, reports 5867903998/5869246980, ACCEPTs 5867962277/5869268738, landing note 5868551954); PR #20434 body, file list and the three-dot diff against main (5 files, +153/−42 — identical whether taken at merge-base 24b70859 or against current origin/main e4d3f2ca); five reads of the check-runs on 7898a47d. Code read at the head via git show only. audience-posture.ts and auth-plugin.ts are byte-identical between 24b70859 and the head, so the rule the text states was judged against the code that ships with it.

① Derived judgments

Accept set — nothing moves: right. The only non-comment source change is the string literal returned by resolveNoSignInAccountReport in boot-sign-in-reachability.ts. auth-manager.ts changes one comment block (the #15587 uniqueness note near line 2295). Exports, the NO_SIGN_IN_ACCOUNT_AT_BOOT key, decideAudienceAdmission, resolveEmailVerificationRequirement, assertAudienceConfig, applyConfigPatch and the settings binding are untouched. No admission decision, default, or refused value changes.

Public surface — the shipped boot report, judged clause by clause against the head's code:

  1. "the INVITED login meets the same email-verification rule as any sign-up" — right. The hasPendingInvitation branch of decideAudienceAdmission returns only { admit: true, grantPermissionSet: false } (audience-posture.ts 465–468); nothing in it touches verification. The only rows born emailVerified: true are the walled-owner operator stamp (auth-manager.ts 7490–7491, gated by takeOwnerVerifiedStamp) and the NODE_ENV=development seeded admin (auth-plugin.ts 1972); an invitation-admitted sign-up reaches neither.
  2. "Under 'email_domain' verification is always ON" — right. resolveEmailVerificationRequirement returns true for email_domain regardless of the declaration (line 198); assertAudienceConfig refuses an explicit false from any declarant (296–302), so no accepted config can contradict it.
  3. "under 'open' it is ON unless the DEPLOYMENT has itself declared it off (emailAndPassword.requireEmailVerification: false, or OS_AUTH_REQUIRE_EMAIL_VERIFICATION=false — a false stored only through the settings console is refused there)" — right. Resolver: declared !== false (199). The constructor asserts with verificationDeclaredBy: 'deployment' (auth-manager.ts 1391–1392). applyConfigPatch defaults the declarant to deployment and keeps the standing opt-out unless a deployment patch re-declares it (4212–4224); the settings binding passes deployment only when the settings source for require_email_verification is env, else console (auth-plugin.ts 1706–1707); the env name derives as OS_AUTH_REQUIRE_EMAIL_VERIFICATION with source env, locked (settings-service.types.ts 381–382, settings-service.ts 1229/1317). A console false with no standing deployment opt-out is refused at audience-posture.ts 304–310 and the prior config keeps ruling; a console false beside a deployment opt-out is honoured — so "only" is the correct qualifier, not an over-claim.
  4. "under the default 'invite_only' posture it follows that same declaration and is OFF by default" — right. Resolver: declared ?? false; the verification checks in assertAudienceConfig sit inside the audiencePermitsSelfRegistration branch, so under invite_only any declarant's value applies. The sentence does not say the console can set it there, nor that it cannot; the docs page states it at the same precision ("follows auth.require_email_verification"). Not wrong, not harmful.
  5. "Wherever it is ON, the invited login is refused EMAIL_NOT_VERIFIED at its first sign-in until a mail transport delivers the link" — carried over from the old remedy (b), still pinned by the #15588/F1 describes (carve-out admits, wiring ON). Consistent.
  6. Remedy advice: "on a deployment without one, close the posture back to 'invite_only' BEFORE that person registers and leave verification at its default OFF" — correct and non-harmful. The carve-out short-circuits before the posture switch, so invite_only still admits the invited creation; with nothing declared the resolver wires OFF and the registration yields a session. The added "leave verification at its default OFF" is needed: a declared true still applies under invite_only. The advice is conditioned on "wherever it is ON", so an open deployment that already opted out is not told to close anything. It does not offer the louder alternative (opting out under open) — a safe omission, and the boot warning covers that path anyway.
  7. Remedy (b) now refers back ("that login meets the same verification rule stated above, so wherever it is ON …"). The self-contradiction is gone. Repo-wide grep at the head for the old spellings ("INVITED login too", "every posture other than 'invite_only'", "FORCES email verification ON unless", "third bullet below applies") hits only the new negative pins, the refusal-message regexes in audience-posture.test.ts, and one test comment (flagged in ③).
  8. The module docblock's invitation bullet restates the same rule and its "second bullet" cross-reference still lands on the hand-written-row bullet (the silencing transition) — right. The third bullet, untouched, already carried the open exception.
  9. auth-manager.ts comment (2295–2300) and signup-existing-address-refusal.test.ts docblock (30–33): "forces … on by default — always under email_domain, and under open unless the deployment declared it off" — comments only, accurate.

Pins. Every positive substring in the flipped #15588/F1 pin occurs in the head's concatenated literal (checked each, including the split "… and is " + "OFF by default, so no mail transport is needed either"); neither negative regex matches the new text. The new #20389 describe's four cases each follow from the code read: constructor open + false honoured (declarant deployment); console patch with no standing opt-out refused with the audience-posture.ts:306 message and getPublicConfig() still ON (config unchanged after the throw), deployment patch as control; email_domain + false throws the :298 message at construction; invite_only default OFF / declared ON. The helpers it uses (engineOver, wideningAudience, invitedSignUp, AUDIENCE_POSTURES, audiencePermitsSelfRegistration) exist in the file. The dev's three ablation legs each went red on the scoped test and restored to the HEAD blob — consistent with the pins as read. CI: all six Test Core shards concluded success on this head.

Docs alignment. content/docs/deployment/self-hosting.mdx "Email verification under each posture" (639–660) and environment-variables.mdx:84 state the identical three-posture rule and the console refusal; the message's long-form pointer still holds. self-hosting.mdx:580 keeps the "every posture other than invite_only" phrasing with the open parenthetical — correct, and outside this diff.

② Semver level

.changeset/20413-boot-report-verification-text.md: @objectstack/plugin-auth patch — right. The package publishes (publishConfig.access: public, no private), and the diff changes shipped runtime output (the report string lands in dist/), so skip-changeset would be wrong. No accept set widens or narrows and no export moves, so the line reading Clause-②: no (present at line start in both the changeset body and the PR body, with no arm) is the right declaration and is well-formed; Check Changeset is green on the head. The changeset prose restates the same rule and advice as the message — accurate, and it says "Text only: no admission decision, verification default or accepted value changes", which matches ①. This is the only changeset the PR adds; .changeset/auth-sso-boot-report-gate.md at the head is already on origin/main and is not this PR's. Round 1's @objectstack/service-settings patch landed separately in 24b70859.

③ Boundary flags

  • open_questions: [] — nothing to answer.
  • Dev deviation (test additions beyond the pin flip; managerWith optional argument) — inside the claimed file; each added pin is a behaviour the code read supports; three retitled tests now say "with nothing declared", which is the true condition. Right.
  • Dev deviation (advice qualifiers "on a deployment without one" and "leave verification at its default OFF") — judged in ① item 6. Right.
  • Dev deviation (gate narrowing: check:dual-build-cjs-loads, check:type-check-debt NOT MEASURED locally) — answered by CI on this head: check:dual-build-cjs-loads is hosted by ci.yml Build Core (line 2116) — success; check:type-check-debt by lint.yml Type Check · debt ledger (line 6296) — success. Closed.
  • Dev deviation (AGENTS.md trailer instead of the harness reminder's) — outside the contract; noted, no action.
  • Dev out-of-scope findings (4 comment-only locations) — read each at the head. audience-gate-test-support.ts:17, harness.ts:778 and admin-remove-user-gate-ordering.test.ts:135 explain why fixtures use the invitation lane and are true for the undeclared config they describe; the v18 migration reason text is release history. No operator-facing reach. Agree with the ACCEPT's acceptance-note disposition (carrier: none).
  • Reviewer flag, escalated to the seat: boot-sign-in-reachability.test.ts:505 (the #15588/N5 describe comment) still reads "The message's quantifier ("every posture other than 'invite_only'") is pinned elsewhere against the WIRING". That quantifier no longer exists in the message; the dev's stale-phrase count used the longer spelling with the opening parenthesis, so this bare form slipped. Comment only, in a file this PR owns; the N5 assertions themselves still hold (both widening postures and invite_only are named in the new text). Not a contract breach and not blocking — a one-line follow-up in the same file, or an acceptance-note entry (carrier: none). The seat decides.
  • Check-runs on 7898a47d at record time (2026-09-28T11:57:08Z): 29 success, 3 skipped (Build Docs, Console Pin Gate, Packed-tarball smoke — path/opt-in skips), 0 failed or cancelled, 2 in_progress: Lint & Repo Gates and the Test Core rollup (all six shards had concluded success). Honest reading: no red anywhere, two gates not yet concluded. Readiness waits on those two, as the ACCEPT's own condition already says; this verdict is on the contract, not on their timing.
  • Overlap: auth-plugin.ts untouched, so nothing here meets plugin-auth: one refused key in the auth settings pass drops every sibling setting, and says so only at warn #20412 / PR fix(plugin-auth): a refused auth setting no longer drops the settings saved with it #20429; the three-dot diff against current origin/main is the same 5 files.

Implemented-by: claude/issue-20413-boot-report-verification-text
Reviewed-by: session_017B6YKCGu8CTY2KBWgwaHAs

VERDICT: PASS

Rendered by an isolated contract-review subagent and adopted by the domain:services seat (#6021, session_017B6YKCGu8CTY2KBWgwaHAs) at 2026-09-28T12:03Z after a transcript check: 63 harness model stamps, all at CONTRACT_REVIEW_TIER, zero fallbacks; 29 Bash and 2 Read calls, zero GitHub writes. The seat's disposition of the reviewer flag: the stale quantifier in the :505 test comment is an Acceptance note (carrier: none). It is comment-only in a test, no operator reads it, and it does not start a push on its own.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 28, 2026 12:04
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit 87c37ae Sep 28, 2026
36 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20413-boot-report-verification-text branch September 28, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants