Skip to content

Commit f0d544c

Browse files
os-zhuangclaude
andauthored
docs(spec): mark feature-absent security props EXPERIMENTAL — Policy, SharingRule, flow runAs (ADR-0049) (#1902)
Completes the pre-MVP "stop the spec from promising what it doesn't enforce" sweep of the #1878 P0 cluster. These three name security boundaries but have no runtime enforcement and the underlying feature does not exist yet, so per ADR-0049 they are explicitly marked `[EXPERIMENTAL — not enforced]` rather than left silently dead. No behaviour change; enforcement is deferred to M2. - PolicySchema (#1882): not registered, no consumer; better-auth runs hardcoded defaults. Schema-level warning + name field annotated. - SharingRuleSchema (#1887): live engine uses a divergent `sys_sharing_rule` model; spec CEL `condition` is never compiled. Schema-level warning. - flow `runAs` (#1888): service-automation engine ignores it (no identity switch). Field annotated. Refs #1878 #1882 #1887 #1888 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fa152c9 commit f0d544c

3 files changed

Lines changed: 23 additions & 2 deletions

File tree

packages/spec/src/automation/flow.zod.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,11 @@ export const FlowSchema = lazySchema(() => z.object({
247247

248248
/** Execution Config */
249249
active: z.boolean().default(false).describe('Is active (Deprecated: use status)'),
250-
runAs: z.enum(['system', 'user']).default('user').describe('Execution context'),
250+
// ⚠️ EXPERIMENTAL — NOT ENFORCED (ADR-0049, #1888). The service-automation
251+
// engine ignores `runAs`: a flow declaring `runAs: system` does not elevate,
252+
// and `user` does not de-elevate — steps run as the triggering context's
253+
// identity regardless. Identity switching is tracked by #1888 (M2).
254+
runAs: z.enum(['system', 'user']).default('user').describe('[EXPERIMENTAL — not enforced] Execution context'),
251255

252256
/** Error Handling Strategy */
253257
errorHandling: z.object({

packages/spec/src/security/policy.zod.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,18 @@ export const AuditPolicySchema = lazySchema(() => z.object({
4646
/**
4747
* Security Policy Schema
4848
* "The Cloud Compliance Contract"
49+
*
50+
* ⚠️ EXPERIMENTAL — NOT ENFORCED (ADR-0049, #1882).
51+
* This schema is currently a no-op: it is not registered as a metadata type and
52+
* has no runtime consumer. Password complexity, session idle/absolute timeout,
53+
* `forceMfa`, the IP allow-list (`trustedRanges`/`vpnRequired`) and audit
54+
* retention/redaction are all parsed but enforced by nothing — `better-auth`
55+
* runs hardcoded defaults regardless. Authoring a policy here does NOT change
56+
* behaviour. Treat as a forward-looking contract only; do not rely on it for
57+
* compliance. Enforcement (or removal) is tracked by #1882 for M2.
4958
*/
5059
export const PolicySchema = lazySchema(() => z.object({
51-
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('Policy Name'),
60+
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('[EXPERIMENTAL — not enforced] Policy Name'),
5261

5362
password: PasswordPolicySchema.optional(),
5463
network: NetworkPolicySchema.optional(),

packages/spec/src/security/sharing.zod.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ export const OwnerSharingRuleSchema = lazySchema(() => BaseSharingRuleSchema.ext
9393

9494
/**
9595
* Master Sharing Rule Schema
96+
*
97+
* ⚠️ EXPERIMENTAL — NOT ENFORCED as authored (ADR-0049, #1887).
98+
* The live engine enforces a divergent runtime model (`sys_sharing_rule`: JSON
99+
* `criteria_json`, recipient enum `user`/`team`/`department`/`role`/`queue`).
100+
* This spec's CEL `condition` is never compiled (unparsable CEL degrades to
101+
* "match nothing"), and recipients such as `role_and_subordinates`/`guest` have
102+
* no runtime mapping. Authoring a rule via this schema does NOT grant access —
103+
* use `sys_sharing_rule` directly until reconciliation. Tracked by #1887 (M2).
96104
*/
97105
export const SharingRuleSchema = lazySchema(() => z.discriminatedUnion('type', [
98106
CriteriaSharingRuleSchema,

0 commit comments

Comments
 (0)