Skip to content

[P0] Metadata property liveness audit: ~half of all spec properties are dead; a cluster of security props is parsed-but-unenforced #1878

Description

@xuyushun441-sys

Summary

A protocol-level audit of every metadata type cross-referenced each schema property's spec definition against its actual consumers (file:line) in the runtime + renderers, to determine (1) does it take effect? and (2) is it necessary/reasonable? Liveness = code consumption, not browser observation.

Result: roughly half of all metadata properties are DEAD — defined in the protocol but read by neither the runtime nor the renderers, so authoring them is a silent no-op. The full evidence (17 per-type reports + cross-type synthesis, each with file:line) is in PR #1864docs/audits/ (README.md is the index).

This issue is the umbrella; the checklists below are scoped so they can be split into separate issues/ADRs.


🔴 P0 — Parsed-but-UNENFORCED security props (latent access-control gaps)

Properties that imply a security boundary but enforce nothing. Either enforce or remove — shipping them as-is is a compliance/security liability.

  • PolicySchema is 100% dead — password complexity, session idle/absolute timeout, forceMfa, IP allow-list (trustedRanges/vpnRequired), audit retention/redaction all parsed, none enforced; not even registered as a metadata type. better-auth (auth-manager.ts:458) runs hardcoded defaults instead → false sense of compliance.
  • Permission lifecycle ops ungatedallowTransfer / allowRestore / allowPurge omitted from OPERATION_TO_PERMISSION (permission-evaluator.ts:8-16); ownership transfer, undelete, and hard-delete/GDPR purge are not gated by RBAC.
  • Agent access control is a no-opagent.permissions / visibility / access never enforced; the chat route hardcodes ['ai:chat','ai:agents'] (agent-routes.ts:109). "Who can chat with this agent" enforces nothing.
  • Flow runAs never switches execution identity (service-automation engine ignores it) — a flow declaring runAs: system does not elevate/de-elevate.
  • Object apiEnabled / apiMethods not enforced by REST — an object cannot actually be hidden from the API via these flags.
  • Action disabled (CEL form) silently ignored — renderers read a non-spec enabled (action-button.tsx:56); the predicate form of disabled has zero consumers.
  • Role parent dead (team-graph.ts:27 does not walk it) — the documented "managers see subordinates' data" rollup is unimplemented.
  • SharingRuleSchema disconnected from the live engine — runtime enforces a divergent sys_sharing_rule model (JSON criteria_json, recipient enum user/team/department/role/queue); the spec's CEL condition + role_and_subordinates/guest recipients are never compiled (unparsable CEL → "match nothing").

🔴 P1 — Finish the ADR-0021 analytics migration

Spec moved to dataset+values/dimensions, but renderers/Studio still read the removed legacy shape:

  • Chart view variant dead-on-arrivalListView.tsx:1413 / ObjectView.tsx:754 read legacy xAxisField/yAxisFields/aggregation; spec exposes dataset/dimensions/values → a spec-compliant chart renders nothing.
  • Dashboard renderer + Studio WidgetConfigPanel still author/read legacy object/categoryField/valueField/aggregate while dashboard.zod.ts:153 declares dataset+values required → Studio emits widgets the spec rejects.
  • Report chart dead on the dataset path; ReportColumnSchema/ReportGroupingSchema/ReportChartSchema are obsolete type-only re-exports.
  • (Same debt that invalidated the showcase dashboard/report seeds.)

🟠 P2 — Spec hygiene

  • Naming drift → silent no-ops: field maxLength/minLength/referenceFilters/maxRating; page type→pageType & label→title & visibility; dashboard title vs label; app reads accentColor/badgeVariant/separator not declared in spec; flow http vs deprecated http_request (Studio authors the alias); skill requiredPermissions vs permissions; agent knowledge.{topics→sources}; webhook object→object_name/isActive→active.
  • Write-only / disconnected metadata: tool metadata is a one-way projection (can't author a working tool as metadata — no implementation/handler field, no executor loads it); EmailTemplateSchema is registered but the runtime reads a differently-shaped sys_email_template; the spec-bridge page/dashboard bridges are orphaned (their exclusive props dead).
  • Aspirational config (rich spec, zero runtime) — prune or mark experimental: field enhanced-type configs (barcode/qr/slider/rating/color/location) + governance (encryption/masking/audit/dataQuality); object enable/versioning/partitioning/cdc/softDelete/search; agent autonomy (memory/guardrails/structuredOutput/lifecycle, except planning.maxIterations); tool outputSchema; job retryPolicy/timeout; theme spacing/breakpoints/logo/rtl/density; translation messageFormat:'icu' (no ICU engine), supportedLocales, cache; PortalSchema (entire — not registered, no route, no renderer).
  • Renderer reads UNDECLARED props (inverse drift) — dashboard component/data/rowField/columnField; view ObjectView form-adapter keys; app accentColor/badgeVariant/separator. These break a strict Schema.parse().
  • Designer authoring gaps (live prop, no Studio editor) — dataset filter/format/derived/dateGranularity; skill triggerConditions (the activation-critical field); flow notify (absent from the static palette).

Healthiest vs worst (from the audit)

  • Healthiest (near-total liveness): hook, validation.
  • Worst: policy (100% dead), portal (100% dead), tool (write-only).

Evidence + per-property recommendations: PR #1864, docs/audits/*.md.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationpriority:p0Critical: blocker, must ship before MVPsecurity

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions