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
plugin-auth: warn about SSO providers whose stored domain list holds an entry that names no domain #33313
Since #33267, POST /sso/register and POST /sso/update-provider refuse a domain entry that is not a bare host name (a URL, a port, a path). A sys_sso_provider row saved before that rule may still hold such an entry (https://acme.com). It is not rewritten, and every rule that reads the list through the one parse (ssoDomainEntryHosts in packages/plugins/plugin-auth/src/sso-account-at-proven-domain.ts: the SSO account rule and SCIM adoption) now reads it as naming no domain. Nothing tells the operator: the provider looks configured, but no address is on its proven domain.
What to do
Make the narrowing visible for stored rows: for example a one-time boot warning (or a Setup notice) naming each provider whose domain list holds an entry ssoDomainEntryNotBare would refuse, with the fix stated in content/docs/permissions/sso.mdx (send the bare host names as domain to POST /api/v1/auth/sso/update-provider, then verify the domain again). Reads only; no row is rewritten.
Acceptance
A provider stored with https://acme.com produces one warning naming the provider id and the entry; a provider with only bare entries produces none (CONTROL).
Claim: server area-lease pilot (#33059), area A1 (auth and identity), dispatched by seat domain:server#5 · p3 · executed by an os-dev subagent of the area A1 thread · posted at 2026-11-14T21:16Z
Session: session_016WV4d1NJYFGVi2FRztyBNo (area A1 thread)
Account: os-elon-musk
Branch: claude/area-A1-33313
Domain: domain:server
File surface: packages/plugins/plugin-auth/src (a read-only boot diagnostic over stored sys_sso_provider domain lists, beside sso-account-at-proven-domain.ts), its test, the stored-rows note in content/docs/permissions/sso.mdx, a changeset.
{
"issue": 33313,
"status": "done",
"branch": "claude/area-A1-33313",
"pr": "https://github.com/objectstack-ai/objectstack/pull/33477",
"session": "session_016WV4d1NJYFGVi2FRztyBNo",
"premise_still_valid": true,
"summary": "Added a read-only boot report in plugin-auth (new sso-stored-domain-entries.ts, wired as a kernel:ready hook beside the legacy SSO client-secret sweep). It reads provider_id and domain of every stored sys_sso_provider once, as the system, and logs one warn per provider whose domain list holds an entry the register/edit refusal refuses, naming the provider id, the entries and the fix. It writes no row and never throws into boot. The predicate behind ssoDomainEntryNotBare is lifted into ssoDomainEntriesNotBare so the refusal and the report share it; the refusal's shape and text are unchanged. sso.mdx already stated the fix (update-provider, then verify again), so the doc edit is two sentences in that paragraph saying the boot log names each such provider. The changeset is a patch.",
"tests": "New sso-stored-domain-entries.test.ts, 9 cases: https://acme.com gives exactly 1 warn naming acme-okta and the entry; bare-only CONTROL gives 0 warns and the rows were read; a mixed list names only the offending entries; a one-predicate table matches ssoDomainEntryNotBare; no stored row changes (0 insert/update/delete, rows deep-equal, read carries context.isSystem); no engine, no find, unregistered object or failed read give no throw and no warn; plugin start plus kernel:ready gives 1 warn, CONTROL 0, and no engine boots. Full plugin-auth suite on head 44b6033089 under the lock: VERDICT command-exit 0, Test Files 274 passed (274), Tests 5301 passed | 10 skipped. Ablation via scripts/ablation-replace.mjs: (1) warn call no-op'd, anchor 1->0, blob 1b78d465c5ab->6ddef6556248, Tests 4 failed | 5 passed (9) (CONTROL and no-engine stay green), restored blob==HEAD and git diff HEAD empty; (2) the plugin hook call no-op'd, anchor 1->0, blob 131c0b801ab5->135919eee65e, Tests 1 failed | 8 passed (the wiring case), restored blob==HEAD. The test imports src by relative path, so no dist leg.",
"gates": "On head 44b6033089, exit captured before any pipe: plugin-auth build of the closure plus typecheck (tsc, examples, check:test-typecheck OK) gave 0; eslint --no-inline-config on the 4 changed files gave 0; check:engine-double-contract 0 (the first run was 1 on findOne, fixed by dropping findOne/count from the double), startup-registry-verdict 0, durability-log-level 0, doc-authoring 0, nul-bytes 0, issue-citations 0, system-context-census 0, test-source-alias 0, cross-package-test-inputs 0, check-empty-changeset 0, check-changeset-no-major 0, check-adr-0087-registration 0. On the pre-merge head 109639b884 these also gave 0: optional-error-sink, logger-receiver-detach, settings-bind-window, init-service-contract, objectql-double-limit, where-matcher, doc-anchors, doc-frontmatter, docs-single-h1, role-word, closed-ceremony-text, undeclared-dep-imports, auth-mount-ledger, error-status-conformance, route-envelope, tier-file-adoption, and node check-plugin-teardown-shape. check:query-options-erasure timed out locally at 280s (exit 124): NOT MEASURED locally, CI runs it as Lint scoped query-options erasure. dispatch-gates --ran: 106 derived, 32 run, 74 UNRUN. This is a declared narrowing: the unrun families run in CI Lint & Repo Gates. PR check-runs were in_progress when this report was written (Type Check, Lint, Check Changeset and others), with no conclusions read.",
"dogfood_battery": "n/a: the PR title has no ! and there is no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "3: git push (branch, not REST); pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls plus POST /issues/33477/assignees); os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/33313/comments)",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Nov 14, 2026
triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH
Path: none
Triage: audit of a pre-labeled card · p3 confirmed · 2026-11-14T16:51Z
⛔ Not a claim.
Area: A1
objectstack-fleet commentedon Nov 14, 2026
domain:server#5 · os-elon-musk · session_016WV4d1NJYFGVi2FRztyBNo
Claim: server area-lease pilot (#33059), area A1 (auth and identity), dispatched by seat
domain:server#5· p3 · executed by anos-devsubagent of the area A1 thread · posted at 2026-11-14T21:16ZSession:
session_016WV4d1NJYFGVi2FRztyBNo(area A1 thread)Account:
os-elon-muskBranch:
claude/area-A1-33313Domain:
domain:serverFile surface:
packages/plugins/plugin-auth/src(a read-only boot diagnostic over storedsys_sso_providerdomain lists, besidesso-account-at-proven-domain.ts), its test, the stored-rows note incontent/docs/permissions/sso.mdx, a changeset.objectstack-fleet commentedon Nov 14, 2026
domain:server#5 · os-elon-musk · session_016WV4d1NJYFGVi2FRztyBNo
os-dev-report
{ "issue": 33313, "status": "done", "branch": "claude/area-A1-33313", "pr": "https://github.com/objectstack-ai/objectstack/pull/33477", "session": "session_016WV4d1NJYFGVi2FRztyBNo", "premise_still_valid": true, "summary": "Added a read-only boot report in plugin-auth (new sso-stored-domain-entries.ts, wired as a kernel:ready hook beside the legacy SSO client-secret sweep). It reads provider_id and domain of every stored sys_sso_provider once, as the system, and logs one warn per provider whose domain list holds an entry the register/edit refusal refuses, naming the provider id, the entries and the fix. It writes no row and never throws into boot. The predicate behind ssoDomainEntryNotBare is lifted into ssoDomainEntriesNotBare so the refusal and the report share it; the refusal's shape and text are unchanged. sso.mdx already stated the fix (update-provider, then verify again), so the doc edit is two sentences in that paragraph saying the boot log names each such provider. The changeset is a patch.", "tests": "New sso-stored-domain-entries.test.ts, 9 cases: https://acme.com gives exactly 1 warn naming acme-okta and the entry; bare-only CONTROL gives 0 warns and the rows were read; a mixed list names only the offending entries; a one-predicate table matches ssoDomainEntryNotBare; no stored row changes (0 insert/update/delete, rows deep-equal, read carries context.isSystem); no engine, no find, unregistered object or failed read give no throw and no warn; plugin start plus kernel:ready gives 1 warn, CONTROL 0, and no engine boots. Full plugin-auth suite on head 44b6033089 under the lock: VERDICT command-exit 0, Test Files 274 passed (274), Tests 5301 passed | 10 skipped. Ablation via scripts/ablation-replace.mjs: (1) warn call no-op'd, anchor 1->0, blob 1b78d465c5ab->6ddef6556248, Tests 4 failed | 5 passed (9) (CONTROL and no-engine stay green), restored blob==HEAD and git diff HEAD empty; (2) the plugin hook call no-op'd, anchor 1->0, blob 131c0b801ab5->135919eee65e, Tests 1 failed | 8 passed (the wiring case), restored blob==HEAD. The test imports src by relative path, so no dist leg.", "gates": "On head 44b6033089, exit captured before any pipe: plugin-auth build of the closure plus typecheck (tsc, examples, check:test-typecheck OK) gave 0; eslint --no-inline-config on the 4 changed files gave 0; check:engine-double-contract 0 (the first run was 1 on findOne, fixed by dropping findOne/count from the double), startup-registry-verdict 0, durability-log-level 0, doc-authoring 0, nul-bytes 0, issue-citations 0, system-context-census 0, test-source-alias 0, cross-package-test-inputs 0, check-empty-changeset 0, check-changeset-no-major 0, check-adr-0087-registration 0. On the pre-merge head 109639b884 these also gave 0: optional-error-sink, logger-receiver-detach, settings-bind-window, init-service-contract, objectql-double-limit, where-matcher, doc-anchors, doc-frontmatter, docs-single-h1, role-word, closed-ceremony-text, undeclared-dep-imports, auth-mount-ledger, error-status-conformance, route-envelope, tier-file-adoption, and node check-plugin-teardown-shape. check:query-options-erasure timed out locally at 280s (exit 124): NOT MEASURED locally, CI runs it as Lint scoped query-options erasure. dispatch-gates --ran: 106 derived, 32 run, 74 UNRUN. This is a declared narrowing: the unrun families run in CI Lint & Repo Gates. PR check-runs were in_progress when this report was written (Type Check, Lint, Check Changeset and others), with no conclusions read.", "dogfood_battery": "n/a: the PR title has no ! and there is no (narrowing) arm", "mcp_calls": "0", "api_writes": "3: git push (branch, not REST); pr_create via fleet-write relay (POST /repos/objectstack-ai/objectstack/pulls plus POST /issues/33477/assignees); os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/33313/comments)", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [] }