Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@dagrejs/dagre": "^3.0.0",
"@hookform/resolvers": "^5.4.0",
"@monaco-editor/react": "^4.7.0",
"@node-saml/node-saml": "^5.1.0",
"@octokit/rest": "^22.0.1",
"@prisma/adapter-pg": "^7.8.0",
"@prisma/client": "^7.8.0",
Expand Down
141 changes: 136 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions prisma/migrations/20260608050000_org_saml_settings/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- Per-org SAML SSO settings (CL-3). Mirrors the existing per-org OIDC
-- columns on OrganizationSettings and coexists with OIDC + local auth.
--
-- All columns are additive:
-- * samlEnabled / samlEnforced — NOT NULL, DEFAULT false, so every
-- existing row keeps SAML off and local/OIDC auth unchanged.
-- * samlIdpEntityId / samlIdpSsoUrl / samlIdpCert / samlGroupAttribute
-- — nullable TEXT, NULL until an org admin configures its IdP.
--
-- `samlIdpCert` holds the IdP's PUBLIC signing certificate (PEM). It is a
-- public credential — unlike `oidcClientSecret` it is NOT encrypted at rest.
-- Group→team reconciliation reuses the shared `oidcTeamMappings` mechanism,
-- keyed by the assertion attribute named in `samlGroupAttribute`.
--
-- OrganizationSettings already carries RLS (organizationId-scoped); adding
-- columns does not change the row-level policy, so no RLS block is needed.
--
-- Rollback:
-- ALTER TABLE "OrganizationSettings"
-- DROP COLUMN "samlEnabled",
-- DROP COLUMN "samlIdpEntityId",
-- DROP COLUMN "samlIdpSsoUrl",
-- DROP COLUMN "samlIdpCert",
-- DROP COLUMN "samlEnforced",
-- DROP COLUMN "samlGroupAttribute";

ALTER TABLE "OrganizationSettings"
ADD COLUMN "samlEnabled" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "samlIdpEntityId" TEXT,
ADD COLUMN "samlIdpSsoUrl" TEXT,
ADD COLUMN "samlIdpCert" TEXT,
ADD COLUMN "samlEnforced" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "samlGroupAttribute" TEXT;

COMMENT ON COLUMN "OrganizationSettings"."samlIdpCert" IS
'IdP public signing certificate (PEM). Public credential — stored in plaintext, never encrypted.';
COMMENT ON COLUMN "OrganizationSettings"."samlEnforced" IS
'When TRUE and SAML is fully configured, local credential login is disabled for the org (SAML SSO is mandatory).';
14 changes: 14 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ model OrganizationSettings {
oidcTeamMappings String?
oidcDefaultTeamId String?

// SAML SSO (per-org; mirrors the OIDC block above). Coexists with OIDC
// and local auth. `samlIdpCert` is the IdP's PUBLIC signing certificate,
// so — unlike `oidcClientSecret` — it is stored in plaintext and never
// encrypted. Group→team reconciliation reuses the shared
// `oidcTeamMappings` mechanism, keyed by the assertion attribute named in
// `samlGroupAttribute`. `samlEnforced` disables local credential login
// for the org once SAML is fully configured (see src/auth.ts).
samlEnabled Boolean @default(false)
samlIdpEntityId String?
samlIdpSsoUrl String?
samlIdpCert String?
samlEnforced Boolean @default(false)
samlGroupAttribute String?

// Fleet tuning (moved from SystemSettings)
fleetPollIntervalMs Int @default(15000)
fleetUnhealthyThreshold Int @default(3)
Expand Down
Loading
Loading