|
1 | 1 | { |
2 | 2 | "category": "security", |
3 | | - "_note": "Liveness classification for authorable security metadata. Seeded from docs/audits/2026-06-security-identity-property-liveness.md (file:line evidence) plus targeted greps for schemas the audit did not cover. Statuses: live | experimental | planned | dead | (schema-level) internal. 'dead' = parsed, no runtime consumer → enforce-or-remove (security ADR). Security-critical: a 'dead' boundary prop = false compliance.", |
| 3 | + "_note": "Liveness classification for authorable security metadata. Seeded from docs/audits/2026-06-security-identity-property-liveness.md (file:line evidence) + greps, reconciled with ADR-0049 dispositions. Where the spec `.describe()` already carries an `[EXPERIMENTAL — not enforced]` marker, that drives the status and the prop is omitted here (marker is the source of truth). This ledger carries: live+evidence, dead-with-no-roadmap (removal candidates), internal exemptions, and sub-object refs that have no per-prop marker. Statuses: live | experimental | planned | dead | (schema-level) internal.", |
4 | 4 | "schemas": { |
5 | 5 | "ObjectPermission": { |
| 6 | + "_note": "allowTransfer/allowRestore/allowPurge are marker-driven (experimental, ADR-0049 #1883) — destructive ops not in OPERATION_TO_PERMISSION; PermissionEvaluator now fails CLOSED for them (permission-evaluator.ts:27,45-51).", |
6 | 7 | "props": { |
7 | 8 | "allowCreate": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:8" }, |
8 | 9 | "allowRead": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:8" }, |
9 | 10 | "allowEdit": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:8" }, |
10 | 11 | "allowDelete": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:8" }, |
11 | | - "viewAllRecords": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts" }, |
12 | | - "modifyAllRecords": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts" }, |
13 | | - "allowTransfer": { "status": "dead", "evidence": "permission-evaluator.ts:8-16 (absent from OPERATION_TO_PERMISSION)", "note": "destructive op (ownership transfer) NOT gated by RBAC — enforce-or-remove. Spec marks experimental." }, |
14 | | - "allowRestore": { "status": "dead", "evidence": "permission-evaluator.ts:8-16 (absent)", "note": "undelete NOT gated — enforce-or-remove." }, |
15 | | - "allowPurge": { "status": "dead", "evidence": "permission-evaluator.ts:8-16 (absent)", "note": "hard-delete/GDPR purge NOT gated — enforce-or-remove." } |
| 12 | + "viewAllRecords": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:64" }, |
| 13 | + "modifyAllRecords": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:60" } |
16 | 14 | } |
17 | 15 | }, |
18 | 16 | "FieldPermission": { |
|
23 | 21 | }, |
24 | 22 | "PermissionSet": { |
25 | 23 | "props": { |
26 | | - "name": { "status": "live", "evidence": "permission-evaluator.ts", "note": "registration/assignment key." }, |
| 24 | + "name": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts", "note": "registration/assignment key." }, |
27 | 25 | "label": { "status": "live", "note": "display metadata (admin forms), not a security boundary." }, |
28 | 26 | "objects": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts:8" }, |
29 | 27 | "fields": { "status": "live", "evidence": "packages/plugins/plugin-security/src/permission-evaluator.ts" }, |
30 | 28 | "rowLevelSecurity": { "status": "live", "evidence": "packages/plugins/plugin-security/src/rls-compiler.ts", "note": "enforced on find + analytics raw-SQL." }, |
31 | | - "systemPermissions": { "status": "live", "evidence": "packages/plugins/plugin-hono-server/src/hono-plugin.ts", "note": "PARTIAL — enforced only for app-entry/nav visibility, NOT as a general capability gate (e.g. manage_users unchecked in data path)." }, |
32 | | - "tabPermissions": { "status": "live", "note": "PARTIAL — only 'hidden' is read; default_on/default_off ignored; UI-only, not a boundary." }, |
33 | | - "isProfile": { "status": "dead", "evidence": "audit: profile-vs-permset never gates anything", "note": "enforce-or-remove." }, |
34 | | - "contextVariables": { "status": "dead", "evidence": "rls-compiler.ts never reads it", "note": "RLS uses only current_user.* built-ins; doc claim of runtime evaluation is false." } |
| 29 | + "systemPermissions": { "status": "live", "evidence": "packages/plugins/plugin-hono-server/src/hono-plugin.ts", "note": "PARTIAL — enforced only for app-entry/nav visibility, NOT a general capability gate." }, |
| 30 | + "tabPermissions": { "status": "live", "note": "PARTIAL — only 'hidden' is read; default_on/default_off ignored; UI-only." }, |
| 31 | + "isProfile": { "status": "dead", "evidence": "audit: profile-vs-permset never gates anything", "note": "enforce-or-remove (ADR-0049)." }, |
| 32 | + "contextVariables": { "status": "dead", "evidence": "rls-compiler.ts never reads it", "note": "RLS uses only current_user.* built-ins." } |
35 | 33 | } |
36 | 34 | }, |
37 | 35 | "RowLevelSecurityPolicy": { |
|
50 | 48 | } |
51 | 49 | }, |
52 | 50 | "Policy": { |
53 | | - "_note": "PolicySchema is 100% DEAD — not even registered as a metadata type; better-auth runs its own hardcoded config (packages/plugins/plugin-auth/src/index.ts). Authoring a compliance Policy = false compliance.", |
| 51 | + "_note": "PolicySchema is 100% DEAD but roadmapped (ADR-0049 #1882) → marked experimental. Per-prop markers in policy.zod.ts drive name/isDefault/assignedProfiles; the sub-object refs below carry no per-prop describe(), so they're classified here.", |
54 | 52 | "props": { |
55 | | - "name": { "status": "experimental", "evidence": "spec describe(): [EXPERIMENTAL — not enforced]" }, |
56 | | - "password": { "status": "dead", "evidence": "auth: better-auth hardcoded scrypt/session", "note": "false compliance — enforce or remove." }, |
57 | | - "network": { "status": "dead", "evidence": "no consumer", "note": "IP allow-list/VPN unenforced." }, |
58 | | - "session": { "status": "dead", "evidence": "auth: better-auth hardcoded session", "note": "idle/absolute timeout + forceMfa unenforced." }, |
59 | | - "audit": { "status": "dead", "evidence": "no consumer", "note": "retention/redaction unenforced." }, |
60 | | - "isDefault": { "status": "dead", "evidence": "no consumer" }, |
61 | | - "assignedProfiles": { "status": "dead", "evidence": "no consumer" } |
| 53 | + "password": { "status": "experimental", "evidence": "policy.zod.ts (PasswordPolicySchema all marked); better-auth hardcoded" }, |
| 54 | + "network": { "status": "experimental", "evidence": "policy.zod.ts (NetworkPolicySchema all marked)" }, |
| 55 | + "session": { "status": "experimental", "evidence": "policy.zod.ts (SessionPolicySchema all marked); forceMfa unenforced" }, |
| 56 | + "audit": { "status": "experimental", "evidence": "policy.zod.ts (AuditPolicySchema all marked)" } |
62 | 57 | } |
63 | 58 | }, |
64 | | - "PasswordPolicy": { "_schema": "dead", "_note": "Policy.password subtree — better-auth hardcoded; unenforced. enforce-or-remove.", "props": {} }, |
65 | | - "SessionPolicy": { "_schema": "dead", "_note": "Policy.session subtree — idle/absoluteTimeout/forceMfa all unenforced; better-auth hardcoded. forceMfa=true is a silent no-op (false compliance).", "props": {} }, |
66 | | - "NetworkPolicy": { "_schema": "dead", "_note": "Policy.network subtree — trustedRanges/blockUnknown/vpnRequired unenforced.", "props": {} }, |
67 | | - "AuditPolicy": { "_schema": "dead", "_note": "Policy.audit subtree — logRetentionDays/sensitiveFields/captureRead unenforced.", "props": {} }, |
68 | | - "OwnerSharingRule": { "_schema": "dead", "_note": "Spec SharingRule has NO runtime consumer; runtime enforces a divergent sys_sharing_rule model (packages/plugins/plugin-sharing/src/sharing-plugin.ts). Authoring the spec rule has no effect — reconcile to one contract.", "props": {} }, |
69 | | - "RLSConfig": { "_schema": "dead", "_note": "No runtime consumer (grep). RLS enforcement reads RowLevelSecurityPolicy via rls-compiler.ts, not this config object.", "props": {} }, |
70 | | - "RLSAuditConfig": { "_schema": "dead", "_note": "No runtime consumer (grep).", "props": {} }, |
71 | | - "Territory": { "_schema": "dead", "_note": "Salesforce-style territory management — no runtime consumer (grep).", "props": {} }, |
72 | | - "TerritoryModel": { "_schema": "dead", "_note": "No runtime consumer (grep).", "props": {} }, |
| 59 | + "OwnerSharingRule": { "_schema": "experimental", "_note": "ADR-0049 #1887: spec SharingRule disconnected from the live sys_sharing_rule engine (packages/plugins/plugin-sharing/src/sharing-plugin.ts); marked experimental pending reconciliation (M2). Schema-level JSDoc in sharing.zod.ts.", "props": {} }, |
| 60 | + "RLSConfig": { "_schema": "dead", "_note": "No runtime consumer (grep). RLS reads RowLevelSecurityPolicy via rls-compiler.ts, not this config. Removal candidate (no roadmap).", "props": {} }, |
| 61 | + "RLSAuditConfig": { "_schema": "dead", "_note": "No runtime consumer (grep). Removal candidate.", "props": {} }, |
| 62 | + "Territory": { "_schema": "dead", "_note": "Salesforce-style territory mgmt — no runtime consumer (grep). Removal candidate (no roadmap).", "props": {} }, |
| 63 | + "TerritoryModel": { "_schema": "dead", "_note": "No runtime consumer (grep). Removal candidate.", "props": {} }, |
73 | 64 | "RLSEvaluationResult": { "_schema": "internal", "_note": "RLS runtime evaluation result — not authorable metadata." }, |
74 | 65 | "RLSAuditEvent": { "_schema": "internal", "_note": "RLS runtime audit event — not authorable metadata." }, |
75 | 66 | "RLSUserContext": { "_schema": "internal", "_note": "RLS runtime user context — not authorable metadata." } |
|
0 commit comments