Repository navigation
Description
Filed by the triage seat (session session_019kDRpB7D2XzVzkaLp57T5D, R+90) while grading #14349 and #14350. Same family as #14350, different surface: that card covers the internal QA checklist's quotation of the --seed-admin flag sentence; this one covers the customer-facing published documentation for a public, unauthenticated endpoint.
⭐ #14374 is the same finding, filed independently 18 minutes later by the domain:services PM seat from its in-seat Clause-② review of PR #14352 (non-blocking follow-up 4). Converged here as the single dispatch entry; its two additions are folded in below.
The measured drift
content/docs/permissions/authentication.mdx defines the endpoint's semantics in two places, and both state the population question:
- line 251 (
### First-run bootstrap status): "GET /api/v1/auth/bootstrap-statusanswers one question — does this environment have any user yet?" - line 1075 (the endpoint index): "Public, unauthenticated first-run probe:
{ "hasOwner": boolean }, telling a client whether this environment has any user yet"
Both are false as of PR #14352 (#14157), now landed. Re-verified on origin/main @ 5c9e40a:
packages/plugins/plugin-auth/src/auth-plugin.ts:2025is nowreturn c.json({ hasOwner: !(await this.authManager!.hasBootstrapWindow()) });— the unfiltereddataEngine.count('sys_user', {})is gone.packages/plugins/plugin-auth/src/auth-manager.ts:4148—hasBootstrapWindow()delegates toisBootstrapCreation(), which is keyed onisHumanUserRow.
⇒ The two questions diverge on a real population: a database carrying only the legacy usr_system service row answered hasOwner: true under the documented sentence and answers hasOwner: false now. That is exactly the population where the console and the admission gate used to disagree, which is what #14157 set out to fix.
Why this is p2 where #14350 is p3
This is a published page about a public endpoint with an SDK method (client.auth.bootstrapStatus()), and the sentence is the endpoint's definition, not a passing mention. A customer who routes on hasOwner — which is exactly what the page tells them it is for ("a routing signal") — is integrating against the documented question. #14350's drift is a quotation inside an internal QA checklist read only by the checklist author.
Fix
Re-state both sentences from the handler's own behaviour. The wording the reviewing seat asked for, and which matches the code: bootstrap-status reports whether the admission gate's bootstrap window is open — no human user yet; service rows do not count.
Two things worth getting right rather than paraphrasing:
- The surrounding prose is still correct — do not rewrite the section. Public/unauthenticated by design, boolean-only, drives the Console's
/loginvs/setupchoice: all unchanged. The fails-open sentence is also still true and was checked rather than assumed:isBootstrapCreation()returnsfalsewhen no engine is wired, sohasOwneris!false=true, and a no-engine composition still reads as bootstrapped exactly as documented. Only the question moves. - Name what the new predicate excludes. "Has a bootstrap window" is the honest phrasing and is what the admission gate agrees with; "has any user" is what it stops being.
Grade: documentation · priority:p2 · domain:devx (content/docs/**) · type Task · pm:queue.
Size/model suggestion: XS, sonnet — two sentences.
Refs: #14157 / PR #14352 (the change) · #14374 (the duplicate, converged here) · #14350 (the QA-checklist twin) · #14349 (the posture question over the same predicate family — ⛔ not this card's to answer).
Generated by Claude Code
Activity
content/docs/permissions/authentication.mdxdescribesbootstrap-statusas "any user yet" — imprecise once PR #14352 makes the route answer from the admission gate's predicate #14374 as a duplicate of this issueclaude commentedon Sep 2, 2026
Claim: session
session_01WLJQhde67SeTccsmnBVarV(domain:devx execution seat, seat post #6023) — R1 wave 7 (concurrency raised to 5 by the maintainer, 2026-09-02 「并发加到五」).claude/issue-14357-bootstrap-status-docs-window../objectstack-14357(dedicated per-task worktree, offorigin/main)domain:devx(content/docs/**, hand-authored page — no generated-file banner at the file head, re-verified onorigin/mainf35821044)content/docs/permissions/authentication.mdxonly — the two sentences at:251("does this environment have any user yet?") and:1075(endpoint index, "whether this environment has any user yet"), both still present; handler premise re-verified:packages/plugins/plugin-auth/src/auth-plugin.ts:2025return c.json({ hasOwner: !(await this.authManager!.hasBootstrapWindow()) });. ⛔ No code touched; ⛔docs/qa/platform-checklist/**is platform-checklist quotes the old --seed-admin contract sentence verbatim, and #14157 changes it #14350's surface, not this card's.sonnet("two sentences"); tier readout fromscripts/pm/dispatch-gates.mjs --tier content/docs/permissions/authentication.mdx: "no path-derived mandate — floor sonnet · default opus · ceiling fable".maybeSeedDevAdmingates on "any sys_user row", but runs atkernel:ready— so any app that seeds people permanently loses theobjectstack devlogin #14157), already landed.content/docs/permissions/**.Generated by Claude Code
claude commentedon Sep 2, 2026
os-dev-report
{ "issue": 14357, "status": "done", "branch": "claude/issue-14357-bootstrap-status-docs-window", "pr": "https://github.com/objectstack-ai/objectstack/pull/14429", "premise_still_valid": true, "summary": "Restated both drift sites in content/docs/permissions/authentication.mdx (line 251 First-run bootstrap status prose, line 1075 endpoint index) to say bootstrap-status reports whether the admission gate's bootstrap window is open -- no human user yet, service rows such as usr_system do not count -- matching the handler (auth-plugin.ts:2025 hasBootstrapWindow(), auth-manager.ts:4148, keyed on isHumanUserRow). Verified exactly the two 'any user' hits existed pre-edit and zero remain post-edit. Left the rest of the section (public/unauthenticated, boolean-only, /login vs /setup routing, fails-open) untouched as instructed.", "tests": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/permissions/authentication.mdx derived 30 families (22 pnpm, 8 direct node). All 30 run under scripts/pm/os-verify-lock.sh (some required building prerequisite packages first: @objectstack/spec, @objectstack/formula, @objectstack/lint, @objectstack/client-react -- their check:docs / check:skill-examples / check:doc-formula-expressions / check:doc-security-posture gates refuse PREREQUISITE NOT MET otherwise). 29/30 RAN-PASS (all printed their own PASS/checkmark verdict line, exit 0, captured pre-pipe): check-ci-filter-parity, check-cross-package-test-inputs (node+pnpm), check-doc-frontmatter, check-doc-route-spelling, check-docs-section-name, check-section-landing-index, check-shard-attestation, check:doc-formula-expressions, check:doc-security-posture, spec check:docs, check:empty-state, check:liveness, check:skill-examples, check:strictness-ledger, check:variant-docs, check:yaml-examples, check:corpus-claim-drift, check:doc-anchors, check:doc-authoring, check:docs-audit-scope, check:docs-redirects, check:docs-single-h1, check:merge-driver, check:published-readme-links, check:react-page-adapter-contract, check:role-word, check:skill-identifier-liveness, check:vendor-version-stamps. 1 NOT-MEASURED: node scripts/check-test-completeness.mjs exits 3 (PREREQUISITE NOT MET) when run with no argument locally -- it needs a saved `turbo run test` log that only CI produces; its own printed guidance says record this as NOT-MEASURED, not a finding. Reconciled with `dispatch-gates.mjs --ran ran.list`: '30 derived, 29 run, 1 NOT-MEASURED, 0 UNRUN'. pnpm changeset status: no changeset needed (docs-only, zero package changes) -- skip-changeset label applied to PR #14429 and read back confirmed present. Head sha at gate time: 6e4304343 (git rev-parse --short HEAD, matches the pushed branch tip).", "mcp_calls": 0, "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
claude commentedon Sep 2, 2026
ACCEPT — #14357 landed. PR #14429 merged to
mainas365a740a8via the merge queue (auto-merge armed after the CI watcher read GREEN; theauto_merge: null/mergeable_state: unknownreading while queued is the PR mid-queue, not disarmed).Close-out probes executed on
origin/main(fresh fetch, throwaway worktree — not the shared checkout;365a740a8confirmed as an ancestor oforigin/mainata98b61b3e):content/docs/permissions/authentication.mdx:251now reads the bootstrap question as "does this environment have no human user yet?" — the wording the card asked for, so the docs no longer describe the bootstrap gate as "any user".bootstrap-statusreads 3 hits, so the grep is live.pm:dispatchedstripped in this same step (type / priority /domain:devxkept — ownership is not state).Seat:
session_01WLJQhde67SeTccsmnBVarV(domain:devx, #6023).Generated by Claude Code