diff --git a/.changeset/identity-liveness.md b/.changeset/identity-liveness.md new file mode 100644 index 0000000000..79a2d047e8 --- /dev/null +++ b/.changeset/identity-liveness.md @@ -0,0 +1,4 @@ +--- +--- + +chore(spec): extend the spec-liveness gate to the `identity` category. Governs `Role` (the one authorable RBAC type: `name`/`label`/`description` live, `parent` dead — org hierarchy uses `sys_department`, not `sys_role.parent`); the SCIM-protocol DTOs and better-auth runtime tables (User/Session/Account/…) are classified `internal`. Same audit as security; repo-internal tooling, no package version impact. diff --git a/packages/spec/liveness/identity.json b/packages/spec/liveness/identity.json new file mode 100644 index 0000000000..c26c883d6d --- /dev/null +++ b/packages/spec/liveness/identity.json @@ -0,0 +1,40 @@ +{ + "category": "identity", + "_note": "Liveness for authorable identity metadata. Same audit as security (docs/audits/2026-06-security-identity-property-liveness.md), which scoped identity to RoleSchema. The only author-written metadata type here is Role (RBAC). The rest are NOT authorable metadata: SCIM 2.0 provisioning protocol DTOs, better-auth runtime tables (User/Session/Account/VerificationToken/ApiKey), and org/membership primitives (Member/Organization/Invitation) managed by plugin-auth / better-auth / the org plugins — classified `internal`.", + "schemas": { + "Role": { + "props": { + "name": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:113", "note": "sys_role.name reused as a permission-set name for RBAC resolution." }, + "label": { "status": "live", "note": "display metadata (admin nav/forms, security-plugin.ts:153)." }, + "description": { "status": "live", "note": "display metadata." }, + "parent": { "status": "dead", "evidence": "no consumer (grep); org hierarchy walks sys_department.parent_department_id via department-graph.ts, not sys_role.parent", "note": "Role 'Reports To' rollup unimplemented — removal candidate (ADR-0049). label/description display-only." } + } + }, + "User": { "_schema": "internal", "_note": "better-auth runtime user table — not authorable metadata." }, + "Session": { "_schema": "internal", "_note": "better-auth runtime session table." }, + "Account": { "_schema": "internal", "_note": "better-auth runtime account/credential table." }, + "VerificationToken": { "_schema": "internal", "_note": "better-auth runtime verification token." }, + "ApiKey": { "_schema": "internal", "_note": "better-auth API key table." }, + "Member": { "_schema": "internal", "_note": "org membership primitive (org plugin), not author-written metadata." }, + "Organization": { "_schema": "internal", "_note": "org/tenant primitive (org plugin)." }, + "Invitation": { "_schema": "internal", "_note": "org invitation primitive (org plugin)." }, + "SCIMUser": { "_schema": "internal", "_note": "SCIM 2.0 provisioning protocol DTO." }, + "SCIMGroup": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMEnterpriseUser": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMName": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMEmail": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMPhoneNumber": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMAddress": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMMeta": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMGroupReference": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMMemberReference": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMListResponse": { "_schema": "internal", "_note": "SCIM 2.0 protocol response DTO." }, + "SCIMError": { "_schema": "internal", "_note": "SCIM 2.0 protocol error DTO." }, + "SCIMPatchOperation": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMPatchRequest": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMBulkOperation": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMBulkRequest": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMBulkResponse": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." }, + "SCIMBulkResponseOperation": { "_schema": "internal", "_note": "SCIM 2.0 protocol DTO." } + } +} diff --git a/packages/spec/scripts/liveness/check-liveness.mjs b/packages/spec/scripts/liveness/check-liveness.mjs index a59120388a..e4b7a2b0e4 100644 --- a/packages/spec/scripts/liveness/check-liveness.mjs +++ b/packages/spec/scripts/liveness/check-liveness.mjs @@ -38,7 +38,7 @@ const ledgerRoot = join(specRoot, 'liveness'); // Categories whose authorable schemas must be fully classified. Extend // highest-risk-first as each category's ledger is seeded from its audit. -const GOVERNED = ['security']; +const GOVERNED = ['security', 'identity']; const args = process.argv.slice(2); const asJson = args.includes('--json');