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
refactor(spec): remove unenforced agent visibility field (ADR-0056 D8, #1901) (#3216)
Agent `visibility` (global/organization/private) was declared but never
enforced: the chat-access evaluator excluded it and the agent list route did
not filter by it, so `private` never hid an agent. Per ADR-0049 / ADR-0056 D8
("design+enforce or remove"), a security-shaped field with no runtime consumer
is a liability — authors who set `private` believe they've restricted an agent
when they have not.
Correct enforcement is undesigned, not just unplumbed: agents have no owner
field (`agent.tenantId` was already removed in #2377) and the `EXTERNAL`
posture rung is never derived, so `organization` vs `global` is
runtime-indistinguishable. Unlike field-encryption (kept EXPERIMENTAL — stable
schema shape on a real roadmap), there is no shape worth preserving, so the
field is dropped rather than carried marked.
- Remove `visibility` from AgentSchema (`agent.zod.ts`) and the authoring form
(`agent.form.ts`); drop the default-value assertion in `agent.test.ts`.
- AgentSchema is not `.strict()`, so existing metadata still setting
`visibility` parses cleanly (unknown key stripped, not rejected).
- Liveness ledger: drop the `visibility` entry (`liveness/agent.json`).
- Authz-conformance matrix: move `agent-visibility` from experimental to
removed (ADR-0056 D10).
- Regenerate schema reference docs; update the authorization posture table.
Use `access` / `permissions` to restrict agent use — both enforced at the chat
route (#1884). Re-introduce `visibility` when the listing surface gains real
owner/org semantics; tracked in #1901.
Claude-Session: https://claude.ai/code/session_012gckUwoUMWvTWfGHFgWAob
Co-authored-by: Claude <noreply@anthropic.com>
| 3 · Environment composition / assignment | Platform-owned assignment records (`sys_user_position` etc.); anti-escalation; union semantics | ADR-0057 D4 |
212
212
| 4 · Runtime enforcement | The six-gate chain above; ~18 primitives enforced and CI-guarded | ADR-0056 D10 matrix |
213
-
| 5 · Production / enterprise | ADR-0056 D8 dispositions settled (2026-07): compliance configs, data masking, and the global RLSConfigwere **removed** (never enforced); field encryption stays honestly `[EXPERIMENTAL]` (roadmap); agent `visibility` is marked `[EXPERIMENTAL]` pending #1901. Enterprise authentication hardening staged per ADR-0069 | ADR-0049/0056 D8, ADR-0069 |
213
+
| 5 · Production / enterprise | ADR-0056 D8 dispositions settled (2026-07): compliance configs, data masking, the global RLSConfig, and agent `visibility`were **removed** (never enforced — for `visibility`, correct owner/org enforcement is undesigned, so it was dropped rather than carried; re-introduce under #1901); field encryption stays honestly `[EXPERIMENTAL]` (roadmap — stable schema shape). Enterprise authentication hardening staged per ADR-0069 | ADR-0049/0056 D8, ADR-0069 |
|**visibility**|`Enum<'global' \| 'organization' \| 'private'>`| ✅ |[EXPERIMENTAL — NOT ENFORCED, #1901] Intended listing scope. No runtime consumer yet; use access/permissions for real gating. |
// ── Experimental — declared, NOT enforced (ADR-0049/0056 D8) ───────────
155
155
{id: 'field-encryption',summary: 'at-rest field encryption',state: 'experimental',
156
156
note: 'no crypto provider reads the config; marked [EXPERIMENTAL] (D8). Deliberately KEPT (2026-07 D8 disposition): at-rest encryption is a real enterprise roadmap item with a stable schema shape — removing and re-adding would cost more (ADR-0087) than carrying it marked.'},
note: 'Intentionally NOT enforced — the chat-access evaluator excludes it (service-ai agent-access.ts) and the agent list route does not filter by it. Schema + authoring form carry EXPERIMENTAL banners (2026-07) so authors are told `private` does not hide the agent; `access`/`permissions` ARE enforced at the chat route (#1884). Enforce when the agent listing surface gains owner/org semantics — #1901.'},
159
157
160
158
// ── Removed — by ADR-0056 D8 "design+enforce or remove" (2026-07) ──────
note: 'REMOVED from spec (agent.zod.ts `visibility` deleted, #1901). Never enforced — the chat-access evaluator excluded it and the agent list route did not filter by it, so `private` never hid an agent. Unlike field-encryption it has NO stable schema shape to preserve: correct enforcement needs owner/org anchors that do not exist (agents carry no owner field; the `EXTERNAL` posture rung is never derived), so the semantics — not just the plumbing — are undesigned. Per D8 a security-shaped field that lies is dropped, not carried marked. `access`/`permissions` ARE enforced at the chat route (#1884); re-introduce `visibility` when the listing surface gains real owner/org semantics.'},
note: 'REMOVED from spec (system/compliance.zod.ts deleted). Compliance-grade config must never merely look live: a parsed-but-dead `gdpr:` block is a liability in an audit. A real compliance subsystem will be designed top-down (data-subject rights engine, retention enforcer) when scheduled.'},
163
163
{id: 'data-masking',summary: 'role-based data masking',state: 'removed',
"note": "intentionally NOT enforced — the chat-access evaluator excludes it and the GET /ai/agents list route does not filter by visibility. Needs owner/org semantics before it can gate listing."
{field: 'visibility',helpText: 'EXPERIMENTAL — not enforced yet (#1901): setting "private" does not hide the agent. Use Access / Permissions below for real gating.'},
57
56
{field: 'access',widget: 'string-tags',helpText: 'User IDs or role names who can chat with this agent'},
58
57
{field: 'permissions',widget: 'string-tags',helpText: 'Required permissions to use this agent'},
59
58
{field: 'guardrails',type: 'composite',helpText: 'Safety rules and content policies'},
0 commit comments