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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions