You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
GET /auth/config serves nine features keys the spec does not declare, and nothing pins the feature registry to the schema #29473
Filing gate: ① an out-of-scope finding (class b, carrier: the seat) that the #29344 dev reported and the seat's contract review confirmed on PR #29455's head 0d814466 (record 6581701011). ⛔ Not a claim. No grade: triage sets it.
What was measured
PR #29455 declares features.sso on AuthFeaturesConfigSchema (packages/spec/src/api/auth-endpoints.zod.ts), the response schema of GET /api/v1/auth/config. The same response carries nine more features keys the server serves (plugin-auth getPublicConfig(), auth-manager.ts) that the schema does not declare. A client that parses the response through GetAuthConfigResponseSchema loses them, because a plain object schema strips unknown keys:
booleans, all classified in PUBLIC_AUTH_FEATURES (packages/spec/src/kernel/public-auth-features.ts): multiOrgEnabled, degradedTenancy, oidcProvider, deviceAuthorization, admin
non-flag values, all listed in PUBLIC_AUTH_CONFIG_NON_FLAG_KEYS: tenancyPosture, audiencePosture, termsUrl, privacyUrl
deviceAuthorization has a live reader (ui/apps/console/src/pages/auth/DeviceAuthPage.tsx:77). Also undeclared, at the top level of GetAuthConfigResponseSchema: devSeedAdmin (auth-manager.ts:4634, dev-only).
No pin ties the registry or the non-flag list to the schema's keys. The three existing pins are: plugin-auth public-feature-registry.test.ts (served keys ≡ registry), platform-objects feature-gate guard (registry ≡ gates), and spec public-auth-features.test.ts (the registry's names). So a key can be served, classified and read while the contract never declares it, which is how sso (#29344) and cloudManaged (#25292) each needed their own card.
Add one pin in packages/spec that every key in PUBLIC_AUTH_FEATURES and PUBLIC_AUTH_CONFIG_NON_FLAG_KEYS is a declared key of AuthFeaturesConfigSchema (retired keys excepted), so the next served key cannot be left undeclared.
Reader who acts: the packages/spec api-schema owner (domain:spec). Land after PR #29455, which touches the same schema.
Also seen, for the ui lane, prose only: ui/packages/auth/src/types.ts:284-289 documents features.sso as "wired; when falsy the /sign-in/sso route isn't mounted", but the served value is "usable", so a served false can mean "wired, no provider yet" with the route mounted. The type (sso?: boolean) is right.
Read fresh. GET /auth/config serves nine features keys the spec does not declare, and nothing pins the feature registry to the schema. Declaring them is a protocol addition, p1 by standing ruling, the same pattern as spec: declare features.sso on the auth config response, which is served and read but never declared #29344. The names are already served; record the list for the maintainer's nod before merge. A pin joining the registry to the schema is a test, not a gate.
Claim: PM loop round 3 · 2026-11-02T18:28Z
Session: session_01JQwxbahe4v7GBD94QeSnir (seat); dev = card thread session_01JQwxbaRoocSDkgqwRAGseR
Account: os-warren
Branch: claude/project-thread-cxjusk
Worktree: the card thread's own checkout of objectstack-ai/objectstack
Domain: domain:spec
Seat: domain:spec#3
File surface: packages/spec/src/api/auth-endpoints.zod.ts (AuthFeaturesConfigSchema, and GetAuthConfigResponseSchema only for devSeedAdmin), one spec test pinning the registry keys as declared, the regenerated schema / reference / api-surface artifacts, root .changeset/; ⛔ not ui/**, ⛔ not packages/spec/src/api/protocol.zod.ts (frozen by server seat 5 until 06:00 UTC on 3 November) (stop on breach; explain in the report)
Container & model: M, mode:thread (platform exception: the seat container pushes only its mailbox branch), model: TIER_DEFAULT (build; the widening is reviewed at CONTRACT_REVIEW_TIER), effort: xhigh asked for p1; the thread runs at the project's default effort because the coordinator cannot set it per thread
Clause-②: yes
Metadata-protocol: none (a wire response, not authorable metadata; the card proposed added, the dev confirms against AGENTS.md Post-Task Checklist step 3 and the PR body says why)
Responsibility: n/a — not a defect card
Thread-read: 6583289246
Premise: holds (read on origin/main390bd2ae: PR #29455 merged, AuthFeaturesConfigSchema at auth-endpoints.zod.ts ~L228 declares sso but not the nine served keys the card lists)
Serial constraints cleared: PR #29455 (same schema) merged; no other open PR touches auth-endpoints.zod.ts, read over every open non-mailbox PR this patrol.
Draft PR #29583 at head d68dd29f. The nine served features keys are declared on AuthFeaturesConfigSchema, one spec test pins the registry plus the non-flag list to the schema's declared keys (retired tombstones excepted), and devSeedAdmin is ruled out as dev-only. Declared Metadata-protocol: added, not the claim's none: the level-axis gate refuses none because this diff moves packages/spec/authorable-surface/api.json (measured, see deviations).
{
"issue": 29473,
"status": "done",
"branch": "claude/project-thread-cxjusk",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29583",
"session": "session_01JQwxbaRoocSDkgqwRAGseR",
"premise_still_valid": true,
"summary": "AuthFeaturesConfigSchema (packages/spec/src/api/auth-endpoints.zod.ts) gains nine optional keys with producer-accurate describes and no defaults: booleans multiOrgEnabled, degradedTenancy, oidcProvider, deviceAuthorization, admin; values tenancyPosture (TenancyPostureSchema), audiencePosture (AUDIENCE_POSTURES), termsUrl and privacyUrl (plain strings, as the producer serves the trimmed env value unvalidated). devSeedAdmin is not declared: plugin-auth serves it only under NODE_ENV=development and it carries the seeded admin's email and password; its one reader (console LoginPage) casts the raw response; the reason sits in a TSDoc block on GetAuthConfigResponseSchema. New test block in auth-endpoints.test.ts (38 cases) holds declared keys minus PUBLIC_AUTH_FEATURES_NOT_ADVERTISED equal to PUBLIC_AUTH_FEATURE_NAMES plus PUBLIC_AUTH_CONFIG_NON_FLAG_KEYS, both directions. Producer read on origin/main 390bd2ae: getPublicConfig() features literal serves exactly those 17 keys. The nine names and the devSeedAdmin ruling are listed in the PR's maintainer summary for Warren's nod.",
"tests": "At d68dd29f: pnpm --filter @objectstack/spec test VERDICT 0, Test Files 799 passed (799), Tests 23700 passed, 1 todo; pnpm --filter @objectstack/spec typecheck VERDICT 0 (tsc, check:scripts-typecheck, check:test-typecheck). At 7d5a57a6 (pre-merge): spec test 794 files / 23587 tests passed; turbo build of @objectstack/client closure then @objectstack/client typecheck VERDICT 0; reverse probe in packages/client typing AuthFeaturesConfig: valid new keys exit 0, deviceAuthorization 'yes' refused TS2322 exit 2, probe deleted. Ablation via scripts/ablation-replace.mjs: deviceAuthorization renamed to deviceAuthorizationAblated (anchor 1 to 0, blob b237957a to 595c0b73), auth-endpoints.test.ts exit 1 with 3 failed (set-equality pin, that flag's boolean case, whole-response parse); restored, blob equals HEAD b237957a, git diff HEAD empty. Scoped eslint over the two changed .ts files exit 0; check-nul-bytes exit 0.",
"gates": "At d68dd29f after merging origin/main 208d3e2e and turbo build of packages/** (VERDICT 0, 78 tasks): dispatch-gates --commands 103 derived, all 103 exit 0 (stdin closed, exit captured before any pipe); dispatch-gates --ran: 103 run, 0 NOT-MEASURED, 0 UNRUN. At 7d5a57a6 three first exited 3 (prerequisite) and passed once inputs existed: check-plugin-teardown-shape --self-test (after fetching fixture commit 621a4876), check:skill-examples (after building client-react), check:dual-build-cjs-loads (after building every package). Offline with the PR body: check-changeset-no-major --event exit 0 under added, exit 1 under none (authorable-surface baseline moved); check-partof-closing-keyword exit 0. check:generated exit 0 (14 artifacts current) after gen:docs. Local-only: check:skill-frame-freshness exit 0; check:dev-prereqs exit 1, machine state only (35 of 106 packages, ui among them, unbuilt here). CI check-runs: in_progress at report time, read by the seat.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay repository_dispatch carrying pr_create (PR #29583, 13597 bytes sent and stored identical); post-stamped comment on #29473 (this report). git push is not a REST write.",
"open_questions": [
{ "question": "devSeedAdmin: keep it undeclared (dev-only) or declare it on GetAuthConfigResponseSchema?", "options": ["A keep undeclared: a published contract would advertise a credential-bearing field no production deployment serves; the one reader never parses through the schema", "B declare an optional { email, password } object with a dev-only describe"], "recommendation": "A, because declaring it adds a password field to the generated public reference and buys no reader" }
],
"deviations": [
"Metadata-protocol: the claim recorded none; the PR and changeset declare added. AGENTS.md Post-Task Checklist step 3 calls a new key added, and packages/spec/authorable-surface/ records this response schema (api/AuthFeaturesConfig rows, the sso row landed under added). Measured: check-changeset-no-major --base origin/main --event exits 1 under none (Moved: packages/spec/authorable-surface/api.json) and 0 under added. The seat's go-ahead message said to declare what step 3 says.",
"Clause-②: the claim line reads yes; the PR and changeset read yes (widening), as the dispatch order spelled it.",
"Labels: none sent. The order named none, the diff publishes (no skip-changeset), and the relay refuses an empty labels array, so the key was omitted.",
"PR body: the harness attribution comment is line 1 and Fixes #29473 line 3; the PR template's headings are folded into the os-dev order (What changes, Why, Tests, Acceptance notes, Verification, Human Minimum)."
],
"body_amendments": "none",
"security_findings": "none",
"out_of_scope_findings": [
"carrier: ui lane (the card's own prose-only note) · ui/packages/auth/src/types.ts lines 284 to 289 describe features.sso as wired while the served value is usable; the same hand-written mirror is where the nine new keys would be typed for the console · noted, not filed"
]
}
closed completed by Fixes #29473; no other closing keyword in the body
State change: pm:dispatched removed from #29473 (a stay-behind tail of the stood-down seat). Delivered: AuthFeaturesConfigSchema declares the nine served features keys, and a set-equality pin holds the feature registry to the schema; devSeedAdmin stays undeclared (Warren's approval, PR comment 6591810483).
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p1 ·
domain:spec·pm:queue· 2026-11-02T17:07Z⛔ Not a claim.
GET /auth/configserves ninefeatureskeys the spec does not declare, and nothing pins the feature registry to the schema. Declaring them is a protocol addition, p1 by standing ruling, the same pattern as spec: declarefeatures.ssoon the auth config response, which is served and read but never declared #29344. The names are already served; record the list for the maintainer's nod before merge. A pin joining the registry to the schema is a test, not a gate.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir
Claim: PM loop round 3 · 2026-11-02T18:28Z
Session:
session_01JQwxbahe4v7GBD94QeSnir(seat); dev = card threadsession_01JQwxbaRoocSDkgqwRAGseRAccount:
os-warrenBranch:
claude/project-thread-cxjuskWorktree: the card thread's own checkout of
objectstack-ai/objectstackDomain:
domain:specSeat:
domain:spec#3File surface:
packages/spec/src/api/auth-endpoints.zod.ts(AuthFeaturesConfigSchema, andGetAuthConfigResponseSchemaonly fordevSeedAdmin), one spec test pinning the registry keys as declared, the regenerated schema / reference / api-surface artifacts, root.changeset/; ⛔ notui/**, ⛔ notpackages/spec/src/api/protocol.zod.ts(frozen by server seat 5 until 06:00 UTC on 3 November) (stop on breach; explain in the report)Container & model:
M,mode:thread(platform exception: the seat container pushes only its mailbox branch),model: TIER_DEFAULT(build; the widening is reviewed atCONTRACT_REVIEW_TIER),effort: xhighasked for p1; the thread runs at the project's default effort because the coordinator cannot set it per threadClause-②: yes
Metadata-protocol: none (a wire response, not authorable metadata; the card proposed
added, the dev confirms against AGENTS.md Post-Task Checklist step 3 and the PR body says why)Responsibility: n/a — not a defect card
Thread-read: 6583289246
Premise: holds (read on
origin/main390bd2ae: PR #29455 merged,AuthFeaturesConfigSchemaatauth-endpoints.zod.ts~L228 declaresssobut not the nine served keys the card lists)Serial constraints cleared: PR #29455 (same schema) merged; no other open PR touches
auth-endpoints.zod.ts, read over every open non-mailbox PR this patrol.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#3 · os-warren · session_01JQwxbaRoocSDkgqwRAGseR
os-dev-report
Draft PR #29583 at head
d68dd29f. The nine servedfeatureskeys are declared onAuthFeaturesConfigSchema, one spec test pins the registry plus the non-flag list to the schema's declared keys (retired tombstones excepted), anddevSeedAdminis ruled out as dev-only. DeclaredMetadata-protocol: added, not the claim'snone: the level-axis gate refusesnonebecause this diff movespackages/spec/authorable-surface/api.json(measured, seedeviations).{ "issue": 29473, "status": "done", "branch": "claude/project-thread-cxjusk", "pr": "https://github.com/objectstack-ai/objectstack/pull/29583", "session": "session_01JQwxbaRoocSDkgqwRAGseR", "premise_still_valid": true, "summary": "AuthFeaturesConfigSchema (packages/spec/src/api/auth-endpoints.zod.ts) gains nine optional keys with producer-accurate describes and no defaults: booleans multiOrgEnabled, degradedTenancy, oidcProvider, deviceAuthorization, admin; values tenancyPosture (TenancyPostureSchema), audiencePosture (AUDIENCE_POSTURES), termsUrl and privacyUrl (plain strings, as the producer serves the trimmed env value unvalidated). devSeedAdmin is not declared: plugin-auth serves it only under NODE_ENV=development and it carries the seeded admin's email and password; its one reader (console LoginPage) casts the raw response; the reason sits in a TSDoc block on GetAuthConfigResponseSchema. New test block in auth-endpoints.test.ts (38 cases) holds declared keys minus PUBLIC_AUTH_FEATURES_NOT_ADVERTISED equal to PUBLIC_AUTH_FEATURE_NAMES plus PUBLIC_AUTH_CONFIG_NON_FLAG_KEYS, both directions. Producer read on origin/main 390bd2ae: getPublicConfig() features literal serves exactly those 17 keys. The nine names and the devSeedAdmin ruling are listed in the PR's maintainer summary for Warren's nod.", "tests": "At d68dd29f: pnpm --filter @objectstack/spec test VERDICT 0, Test Files 799 passed (799), Tests 23700 passed, 1 todo; pnpm --filter @objectstack/spec typecheck VERDICT 0 (tsc, check:scripts-typecheck, check:test-typecheck). At 7d5a57a6 (pre-merge): spec test 794 files / 23587 tests passed; turbo build of @objectstack/client closure then @objectstack/client typecheck VERDICT 0; reverse probe in packages/client typing AuthFeaturesConfig: valid new keys exit 0, deviceAuthorization 'yes' refused TS2322 exit 2, probe deleted. Ablation via scripts/ablation-replace.mjs: deviceAuthorization renamed to deviceAuthorizationAblated (anchor 1 to 0, blob b237957a to 595c0b73), auth-endpoints.test.ts exit 1 with 3 failed (set-equality pin, that flag's boolean case, whole-response parse); restored, blob equals HEAD b237957a, git diff HEAD empty. Scoped eslint over the two changed .ts files exit 0; check-nul-bytes exit 0.", "gates": "At d68dd29f after merging origin/main 208d3e2e and turbo build of packages/** (VERDICT 0, 78 tasks): dispatch-gates --commands 103 derived, all 103 exit 0 (stdin closed, exit captured before any pipe); dispatch-gates --ran: 103 run, 0 NOT-MEASURED, 0 UNRUN. At 7d5a57a6 three first exited 3 (prerequisite) and passed once inputs existed: check-plugin-teardown-shape --self-test (after fetching fixture commit 621a4876), check:skill-examples (after building client-react), check:dual-build-cjs-loads (after building every package). Offline with the PR body: check-changeset-no-major --event exit 0 under added, exit 1 under none (authorable-surface baseline moved); check-partof-closing-keyword exit 0. check:generated exit 0 (14 artifacts current) after gen:docs. Local-only: check:skill-frame-freshness exit 0; check:dev-prereqs exit 1, machine state only (35 of 106 packages, ui among them, unbuilt here). CI check-runs: in_progress at report time, read by the seat.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — fleet-write relay repository_dispatch carrying pr_create (PR #29583, 13597 bytes sent and stored identical); post-stamped comment on #29473 (this report). git push is not a REST write.", "open_questions": [ { "question": "devSeedAdmin: keep it undeclared (dev-only) or declare it on GetAuthConfigResponseSchema?", "options": ["A keep undeclared: a published contract would advertise a credential-bearing field no production deployment serves; the one reader never parses through the schema", "B declare an optional { email, password } object with a dev-only describe"], "recommendation": "A, because declaring it adds a password field to the generated public reference and buys no reader" } ], "deviations": [ "Metadata-protocol: the claim recorded none; the PR and changeset declare added. AGENTS.md Post-Task Checklist step 3 calls a new key added, and packages/spec/authorable-surface/ records this response schema (api/AuthFeaturesConfig rows, the sso row landed under added). Measured: check-changeset-no-major --base origin/main --event exits 1 under none (Moved: packages/spec/authorable-surface/api.json) and 0 under added. The seat's go-ahead message said to declare what step 3 says.", "Clause-②: the claim line reads yes; the PR and changeset read yes (widening), as the dispatch order spelled it.", "Labels: none sent. The order named none, the diff publishes (no skip-changeset), and the relay refuses an empty labels array, so the key was omitted.", "PR body: the harness attribution comment is line 1 and Fixes #29473 line 3; the PR template's headings are folded into the os-dev order (What changes, Why, Tests, Acceptance notes, Verification, Human Minimum)." ], "body_amendments": "none", "security_findings": "none", "out_of_scope_findings": [ "carrier: ui lane (the card's own prose-only note) · ui/packages/auth/src/types.ts lines 284 to 289 describe features.sso as wired while the served value is usable; the same hand-written mirror is where the nine new keys would be typed for the console · noted, not filed" ] }objectstack-fleet commentedon Nov 3, 2026
domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir
Landed · 2026-11-03T01:11Z
4b06a54aonmaincompletedbyFixes #29473; no other closing keyword in the bodyState change:
pm:dispatchedremoved from #29473 (a stay-behind tail of the stood-down seat). Delivered:AuthFeaturesConfigSchemadeclares the nine servedfeatureskeys, and a set-equality pin holds the feature registry to the schema;devSeedAdminstays undeclared (Warren's approval, PR comment 6591810483).Generated by Claude Code