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
setup: the SSO Providers form cannot set the groups claim mapping, so IdP group mapping needs the vendor register door #31666
Filing gate: ② a follow-up the dev of #31658 (PR #31664) noted and the seat's ACCEPT names. ⛔ Not a claim.
Reader: triage sets the lane (the Setup form is metadata-driven; the field may live on the SSO provider object in plugin-auth / platform-objects, or in the console).
Dedupe (open AND closed): SSO Providers form groups → none.
reach: every operator who sets up SSO through Setup and wants IdP groups to grant permission sets (#30967 item 3, PR #31657).
class: b · type: Bug
Grade: left to triage (seat suggests p3).
The form can set (and show) the provider's groups claim name, written where the register door writes it.
Pins: a provider saved through the form with a groups claim grants its mapped set at sign-in; CONTROL: a provider saved without it signs users in as today.
Lane:domain:server. The Setup SSO Providers form is metadata-driven, and the groups-claim field belongs on the SSO provider object (plugin-auth / platform-objects), written where the register door writes it. If it turns out the form is hand-built console code, the claiming seat files a domain:ui half.
Claim: PM loop round 1 · #31666 · 2026-11-09T01:20Z · bug (p3; Setup SSO Providers form cannot set the groups claim mapping)
Session: session_01ADHkmPF1skfu2kx89BEXZi
Account: os-steve
Branch: claude/project-thread-d7w1a6 (the card thread's harness-pinned branch; platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-31666
Domain: domain:server
Seat: domain:server#1
File surface: the SSO provider object / form metadata in packages/plugins/plugin-auth/ or the platform objects package, the save path that writes a provider row, their tests, the SSO docs page, a changeset. ⛔ No ui/ edits; if the form is console code, stop and report (stop on breach; explain in the report)
Container & model: S/M, mode:thread, model: default tier, effort: high
Clause-②: yes (an authorable form field is added; restated from the measured shape if step 0 shows otherwise)
Metadata-protocol: none
Ruling-ref: none
Responsibility: #31657 (#30967 item 3) added the groups-claim grant and wired only the register door; the form was not in its surface
Thread-read: 6727639998
Premise: holds (per the card and PR #31664's docs: the groups claim is set only through POST /api/v1/auth/sso/register; re-measured as step 0)
Serial constraints cleared: no open seat-1 PR touches plugin-auth's SSO surface; #31719 (seat 2) is serve.ts, disjoint.
Order: standard order + server-seat1/31666-delta.md (project files).
{
"status": "done",
"branch": "claude/project-thread-d7w1a6",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31755",
"session": "session_01ADHkmQznRNHwfSHVJJUCj2",
"premise_still_valid": true,
"summary": "Step 0: the Setup > SSO Providers form is metadata (sys_sso_provider actions posting to plugin-auth /admin/sso/* bridges), not ui/ code. Per seat ruling A: Register SSO/SAML Provider gain a groups param stored at mapping.extraFields.groups (register-door shape), and two platform-admin actions Show/Edit Groups Claim post to new bridges get-groups-claim / set-groups-claim; edit merges into the stored mapping via the vendor update-provider, blank clears it, answers only {providerId, groupsClaim}. Fixed a pre-existing defect found on the way: the adapter update echo (vendor lockSSOProviderRow) lacked the client-secret read half, so any update-provider with oidcConfig on a sys_secret-backed OIDC provider was refused 400. #31657 grant logic untouched.",
"tests": "plugin-auth full suite (head 80a1f4cc minus the pin fix): 4431 passed, 10 skipped, 1 red = auth-route-ledger.conformance pin, fixed and re-run 10/10; touched suites earlier 101/101. platform-objects 120 files / 1933 tests green. Typecheck both packages exit 0. Ablations (VERDICT command-exit 1 each, restored, git diff HEAD empty): A1 gate removed from set-groups-claim -> 4 red (expected 200 to be 401/403); A2 vendor refusal body relayed -> no-leak pin red; A3 mapping added to show answer -> 2 red; A4 echo injection removed -> 3b and round trip red (400 clientSecret is required).",
"gates": "dispatch-gates --commands at 80a1f4cced: 108 commands, all run; 2 first exited 3 (prerequisite: check:skill-examples, check:dual-build-cjs-loads), re-run exit 0 after building client/client-react and ./packages/** under os-verify-lock (VERDICT command-exit 0); --ran reconcile: 108 derived, 108 run, 0 NOT-MEASURED, 0 UNRUN (DERIVED zero). pnpm lint (eslint --no-inline-config) on plugin-auth + platform-objects exit 0 (packages have no lint script; ran the root lint spelling over them). check:i18n, check:i18n-coverage, check:auth-mount-ledger, check-nul-bytes exit 0. CI not awaited.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "2 — mcp__github__issue_read x2 (reads only)",
"api_writes": "2 relay dispatches — pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /issues/31755/assignees) and this os-dev-report comment (post-stamped)",
"open_questions": [
{
"question": "New public route and action names (seat call): POST /api/v1/auth/admin/sso/get-groups-claim, POST /api/v1/auth/admin/sso/set-groups-claim; actions show_sso_groups_claim, edit_sso_groups_claim.",
"options": [
"A keep (follows /admin/sso/* and *_sso_* house spelling)",
"B rename"
],
"recommendation": "A, matches the sibling bridges and edit_sso_sign_in_options"
},
{
"question": "Cloud AuthProxyPlugin must mount the two new routes to serve them in cloud.",
"options": [
"A cloud card filed by the seat",
"B leave until cloud picks up plugin-auth"
],
"recommendation": "A, the form shows the actions there too"
}
],
"security_findings": "withheld",
"out_of_scope_findings": [
"class: b · reach: maintainer · evidence: ADR-0011 Not-assessed list does not name show_sso_groups_claim / edit_sso_groups_claim · dedupe words: ADR-0011 not assessed sso groups claim",
"carrier: seat · noted, not filed (governed surface)"
],
"files_changed": [
".changeset/31666-sso-form-groups-claim.md +17 -0",
"content/docs/permissions/sso.mdx +15 -3",
"packages/platform-objects/src/apps/translations/ar.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/ar.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/de.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/de.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/en.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/es-ES.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/fr.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/fr.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/ja-JP.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/ko.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/ko.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/pt-BR.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/pt-BR.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/ru.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/ru.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/apps/translations/zh-Hant.objects.generated.ts +39 -0",
"packages/platform-objects/src/apps/translations/zh-Hant.source-hashes.generated.ts +3 -0",
"packages/platform-objects/src/identity/sys-sso-provider.object.ts +64 -1",
"packages/platform-objects/src/platform-admin-affordance-standing.test.ts +2 -0",
"packages/platform-objects/src/platform-objects.test.ts +2 -0",
"packages/plugins/plugin-auth/src/admin-sso-bridge-gate.test.ts +80 -0",
"packages/plugins/plugin-auth/src/auth-plugin.ts +38 -1",
"packages/plugins/plugin-auth/src/auth-route-ledger.conformance.test.ts +9 -0",
"packages/plugins/plugin-auth/src/auth-route-ledger.ts +2 -0",
"packages/plugins/plugin-auth/src/objectql-adapter.ts +9 -0",
"packages/plugins/plugin-auth/src/register-sso-provider.test.ts +211 -1",
"packages/plugins/plugin-auth/src/register-sso-provider.ts +221 -4",
"packages/plugins/plugin-auth/src/sso-client-secret-at-rest.test.ts +38 -0",
"packages/plugins/plugin-auth/src/sso-oidc-refusal-cause.test.ts +150 -3"
],
"line_budget": "35 files, +1317 / -13 (human-merge threshold 3000: under). Source 7 files +366/-9 (register-sso-provider.ts +221, sys-sso-provider.object.ts +64, auth-plugin.ts +38, objectql-adapter.ts +9, route ledger +2, docs +15/-3, changeset +17); tests 7 files +492/-4; generated translation bundles 21 files +459.",
"deviations": [
"Gate loop hit the 10-min background limit after 61/108; the remaining 47 were run by a nohup runner, same commands, same head.",
"check:skill-examples and check:dual-build-cjs-loads first exited 3 (missing dist), re-run green after building; ran-final records the rerun exits.",
"Ablation A4 first attempt was a no-op (replacement text not unique) and A1 had a dry probe; both redone with unique anchors, real runs cited.",
"One commit first carried a model-named trailer; amended before push (never pushed).",
"Fixed a defect outside the delta text (adapter update echo) because the edit path cannot work without it; pinned by 3b and ablated.",
"pnpm lint: no per-package lint script; ran the root lint spelling (eslint --no-inline-config) over both packages."
]
}
Activity
objectstack-fleet commentedon Nov 8, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage:
domain:server· p3 ·pm:queue· 2026-11-08T21:53Z⛔ Not a claim.
domain:server. The Setup SSO Providers form is metadata-driven, and the groups-claim field belongs on the SSO provider object (plugin-auth / platform-objects), written where the register door writes it. If it turns out the form is hand-built console code, the claiming seat files adomain:uihalf.finding→ graded.Generated by Claude Code
objectstack-fleet commentedon Nov 9, 2026
domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi
Claim: PM loop round 1 · #31666 · 2026-11-09T01:20Z · bug (p3; Setup SSO Providers form cannot set the groups claim mapping)
Session:
session_01ADHkmPF1skfu2kx89BEXZiAccount:
os-steveBranch:
claude/project-thread-d7w1a6(the card thread's harness-pinned branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-31666Domain:
domain:serverSeat:
domain:server#1File surface: the SSO provider object / form metadata in
packages/plugins/plugin-auth/or the platform objects package, the save path that writes a provider row, their tests, the SSO docs page, a changeset. ⛔ Noui/edits; if the form is console code, stop and report (stop on breach; explain in the report)Container & model:
S/M,mode:thread,model: default tier,effort: highClause-②: yes (an authorable form field is added; restated from the measured shape if step 0 shows otherwise)
Metadata-protocol: none
Ruling-ref: none
Responsibility: #31657 (#30967 item 3) added the groups-claim grant and wired only the register door; the form was not in its surface
Thread-read: 6727639998
Premise: holds (per the card and PR #31664's docs: the groups claim is set only through
POST /api/v1/auth/sso/register; re-measured as step 0)Serial constraints cleared: no open seat-1 PR touches plugin-auth's SSO surface; #31719 (seat 2) is
serve.ts, disjoint.Order: standard order +
server-seat1/31666-delta.md(project files).objectstack-fleet commentedon Nov 9, 2026
domain:server#1 · os-steve · session_01ADHkmQznRNHwfSHVJJUCj2
os-dev-report
{ "status": "done", "branch": "claude/project-thread-d7w1a6", "pr": "https://github.com/objectstack-ai/objectstack/pull/31755", "session": "session_01ADHkmQznRNHwfSHVJJUCj2", "premise_still_valid": true, "summary": "Step 0: the Setup > SSO Providers form is metadata (sys_sso_provider actions posting to plugin-auth /admin/sso/* bridges), not ui/ code. Per seat ruling A: Register SSO/SAML Provider gain a groups param stored at mapping.extraFields.groups (register-door shape), and two platform-admin actions Show/Edit Groups Claim post to new bridges get-groups-claim / set-groups-claim; edit merges into the stored mapping via the vendor update-provider, blank clears it, answers only {providerId, groupsClaim}. Fixed a pre-existing defect found on the way: the adapter update echo (vendor lockSSOProviderRow) lacked the client-secret read half, so any update-provider with oidcConfig on a sys_secret-backed OIDC provider was refused 400. #31657 grant logic untouched.", "tests": "plugin-auth full suite (head 80a1f4cc minus the pin fix): 4431 passed, 10 skipped, 1 red = auth-route-ledger.conformance pin, fixed and re-run 10/10; touched suites earlier 101/101. platform-objects 120 files / 1933 tests green. Typecheck both packages exit 0. Ablations (VERDICT command-exit 1 each, restored, git diff HEAD empty): A1 gate removed from set-groups-claim -> 4 red (expected 200 to be 401/403); A2 vendor refusal body relayed -> no-leak pin red; A3 mapping added to show answer -> 2 red; A4 echo injection removed -> 3b and round trip red (400 clientSecret is required).", "gates": "dispatch-gates --commands at 80a1f4cced: 108 commands, all run; 2 first exited 3 (prerequisite: check:skill-examples, check:dual-build-cjs-loads), re-run exit 0 after building client/client-react and ./packages/** under os-verify-lock (VERDICT command-exit 0); --ran reconcile: 108 derived, 108 run, 0 NOT-MEASURED, 0 UNRUN (DERIVED zero). pnpm lint (eslint --no-inline-config) on plugin-auth + platform-objects exit 0 (packages have no lint script; ran the root lint spelling over them). check:i18n, check:i18n-coverage, check:auth-mount-ledger, check-nul-bytes exit 0. CI not awaited.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "2 — mcp__github__issue_read x2 (reads only)", "api_writes": "2 relay dispatches — pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /issues/31755/assignees) and this os-dev-report comment (post-stamped)", "open_questions": [ { "question": "New public route and action names (seat call): POST /api/v1/auth/admin/sso/get-groups-claim, POST /api/v1/auth/admin/sso/set-groups-claim; actions show_sso_groups_claim, edit_sso_groups_claim.", "options": [ "A keep (follows /admin/sso/* and *_sso_* house spelling)", "B rename" ], "recommendation": "A, matches the sibling bridges and edit_sso_sign_in_options" }, { "question": "Cloud AuthProxyPlugin must mount the two new routes to serve them in cloud.", "options": [ "A cloud card filed by the seat", "B leave until cloud picks up plugin-auth" ], "recommendation": "A, the form shows the actions there too" } ], "security_findings": "withheld", "out_of_scope_findings": [ "class: b · reach: maintainer · evidence: ADR-0011 Not-assessed list does not name show_sso_groups_claim / edit_sso_groups_claim · dedupe words: ADR-0011 not assessed sso groups claim", "carrier: seat · noted, not filed (governed surface)" ], "files_changed": [ ".changeset/31666-sso-form-groups-claim.md +17 -0", "content/docs/permissions/sso.mdx +15 -3", "packages/platform-objects/src/apps/translations/ar.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/ar.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/de.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/de.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/en.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/es-ES.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/es-ES.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/fr.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/fr.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/ja-JP.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/ja-JP.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/ko.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/ko.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/pt-BR.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/pt-BR.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/ru.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/ru.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/apps/translations/zh-Hant.objects.generated.ts +39 -0", "packages/platform-objects/src/apps/translations/zh-Hant.source-hashes.generated.ts +3 -0", "packages/platform-objects/src/identity/sys-sso-provider.object.ts +64 -1", "packages/platform-objects/src/platform-admin-affordance-standing.test.ts +2 -0", "packages/platform-objects/src/platform-objects.test.ts +2 -0", "packages/plugins/plugin-auth/src/admin-sso-bridge-gate.test.ts +80 -0", "packages/plugins/plugin-auth/src/auth-plugin.ts +38 -1", "packages/plugins/plugin-auth/src/auth-route-ledger.conformance.test.ts +9 -0", "packages/plugins/plugin-auth/src/auth-route-ledger.ts +2 -0", "packages/plugins/plugin-auth/src/objectql-adapter.ts +9 -0", "packages/plugins/plugin-auth/src/register-sso-provider.test.ts +211 -1", "packages/plugins/plugin-auth/src/register-sso-provider.ts +221 -4", "packages/plugins/plugin-auth/src/sso-client-secret-at-rest.test.ts +38 -0", "packages/plugins/plugin-auth/src/sso-oidc-refusal-cause.test.ts +150 -3" ], "line_budget": "35 files, +1317 / -13 (human-merge threshold 3000: under). Source 7 files +366/-9 (register-sso-provider.ts +221, sys-sso-provider.object.ts +64, auth-plugin.ts +38, objectql-adapter.ts +9, route ledger +2, docs +15/-3, changeset +17); tests 7 files +492/-4; generated translation bundles 21 files +459.", "deviations": [ "Gate loop hit the 10-min background limit after 61/108; the remaining 47 were run by a nohup runner, same commands, same head.", "check:skill-examples and check:dual-build-cjs-loads first exited 3 (missing dist), re-run green after building; ran-final records the rerun exits.", "Ablation A4 first attempt was a no-op (replacement text not unique) and A1 had a dry probe; both redone with unique anchors, real runs cited.", "One commit first carried a model-named trailer; amended before push (never pushed).", "Fixed a defect outside the delta text (adapter update echo) because the edit path cannot work without it; pinned by 3b and ablated.", "pnpm lint: no per-package lint script; ran the root lint spelling (eslint --no-inline-config) over both packages." ] }Stamped 2026-11-09T02:40Z.
Generated by Claude Code