Skip to content

Commit d612500

Browse files
os-zhuangclaude
andcommitted
docs(audit): cross-type synthesis + index (README)
Ties 21 schemas into 7 cross-cutting patterns, priority-ordered: (1) parsed- but-unenforced security props (policy/permission-lifecycle/agent-access/flow- runAs/object-apiEnabled/action-disabled) = latent access-control gaps; (2) ADR-0021 analytics migration debt; (3) naming drift silent no-ops; (4) aspirational config; (5) write-only/disconnected metadata; (6) renderer reads undeclared props; (7) designer authoring gaps. Suggests 3 ADRs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 749be7d commit d612500

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

docs/audits/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Metadata Property Liveness & Necessity Audit
2+
3+
A protocol-level audit of **every ObjectStack metadata type**: for each schema property, cross-reference its spec definition against its **actual consumers** (`file:line`) in the runtime and renderers, to answer two questions in order — **(1) does the property take effect?** and **(2) is it necessary / reasonable?**
4+
5+
Liveness is judged by **code consumption**, not browser observation (an unreactive UI can't distinguish "dead property" from "data didn't trigger it"). "DEAD" = parsed but read by no non-spec/non-test consumer → a **silent no-op** for authors.
6+
7+
## Per-type reports
8+
| Type | Doc | Health |
9+
|---|---|---|
10+
| field | `2026-06-fieldschema-property-liveness.md` | ~half dead |
11+
| object | `2026-06-objectschema-property-liveness.md` | ~half dead |
12+
| view | `2026-06-viewschema-property-liveness.md` | list-family healthy; chart/form-variants broken |
13+
| app | `2026-06-appschema-property-liveness.md` | nav core healthy; aspirational tail |
14+
| page | `2026-06-pageschema-property-liveness.md` | drift breaks layouts |
15+
| dashboard | `2026-06-dashboardschema-property-liveness.md` | ADR-0021 half-done |
16+
| report | `2026-06-reportschema-property-liveness.md` | dataset live; chart dead |
17+
| dataset | `2026-06-datasetschema-property-liveness.md` | live; Studio under-covers |
18+
| action | `2026-06-actionschema-property-liveness.md` | disabled-CEL ignored; form/shortcut dead |
19+
| flow | `2026-06-flowschema-property-liveness.md` | enum out of sync; runAs unenforced |
20+
| agent | `2026-06-agentschema-property-liveness.md` | autonomy + access-control aspirational |
21+
| tool | `2026-06-toolschema-property-liveness.md` | **write-only metadata** |
22+
| skill | `2026-06-skillschema-property-liveness.md` | triggerPhrases display-only |
23+
| hook | `2026-06-hookschema-property-liveness.md` | **healthy** (near-total) |
24+
| validation | `2026-06-validationschema-property-liveness.md` | **healthy** (all 6 types enforced) |
25+
| security/identity (role, permission, policy, sharing) | `2026-06-security-identity-property-liveness.md` | **policy 100% dead** |
26+
| system/integration (email/i18n/theme/job/webhook/portal) | `2026-06-system-integration-property-liveness.md` | email + portal dead |
27+
28+
## Cross-cutting patterns (in priority order)
29+
30+
### 1. 🔴 Parsed-but-UNENFORCED security props (latent access-control gaps)
31+
The most serious cluster — properties that imply a security boundary but enforce nothing:
32+
- **PolicySchema** — 100% dead (password complexity, session timeout, `forceMfa`, IP allow-list, audit retention); not even registered. better-auth's hardcoded defaults govern. **False compliance.**
33+
- **Permission `allowTransfer`/`allowRestore`/`allowPurge`** — destructive ops (transfer, undelete, GDPR purge) not gated by RBAC.
34+
- **Agent `permissions`/`visibility`/`access`** — "who can chat with this agent" is a no-op (route hardcodes `['ai:chat','ai:agents']`).
35+
- **Flow `runAs`** — never switches execution identity.
36+
- **Object `apiEnabled`/`apiMethods`** — not enforced by REST (object can't be hidden from the API).
37+
- **Action `disabled`** (CEL form) — silently ignored (renderer reads non-spec `enabled`).
38+
- **Role `parent`** / **SharingRuleSchema** — manager rollup & spec sharing rules disconnected from the live engine.
39+
40+
### 2. 🔴 ADR-0021 analytics migration debt
41+
Spec moved to `dataset`+`values`/`dimensions`, but: the **chart view variant** + **dashboard renderer + Studio WidgetConfigPanel** still read the *removed* legacy `object/valueField/categoryField/aggregate` shape; **report `chart`** is dead; `ReportColumn`/`ReportGrouping` are obsolete re-exports. (Same debt that invalidated the showcase dashboard/report seeds.)
42+
43+
### 3. 🟠 Naming drift → silent no-ops (spec key ≠ consumed key)
44+
field `maxLength`/`minLength`/`referenceFilters`/`maxRating`; page `type``pageType` & `label``title` & `visibility`; dashboard `title` vs `label`; app `accentColor`/`badgeVariant`/`separator` (renderer reads, **not in spec**); action `disabled``enabled`; flow `http` vs `http_request`; skill `requiredPermissions` vs `permissions`; agent `knowledge.{topics→sources}`; webhook `object``object_name`, `isActive``active`.
45+
46+
### 4. 🟠 Aspirational config (rich spec, zero runtime) — prune or mark `experimental`
47+
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); tool `outputSchema`; job `retryPolicy`/`timeout`; theme rtl/density/touchTarget; translation `messageFormat:'icu'` (no ICU engine); **portal (entire)**; webhook non-HMAC auth.
48+
49+
### 5. 🟠 Write-only / disconnected metadata (type implies authorability it lacks)
50+
**tool** (write-only projection — can't author a working tool as metadata); **EmailTemplateSchema** (registered, but runtime reads differently-shaped `sys_email_template`); **SharingRuleSchema** (runtime uses `sys_sharing_rule`); **spec-bridge** page/dashboard bridges orphaned (their exclusive props dead).
51+
52+
### 6. Inverse drift — renderer depends on UNDECLARED props
53+
dashboard `component`/`data`/`rowField`/`columnField`; view `ObjectView` form-adapter keys; app `accentColor`/`badgeVariant`/`separator`. These break a strict `Schema.parse()`.
54+
55+
### 7. Designer authoring gaps (live prop, no Studio editor)
56+
dataset `filter`/`format`/`derived`/`dateGranularity`; skill `triggerConditions` (the activation-critical field); flow `notify` (absent from static palette).
57+
58+
## Healthiest vs worst
59+
- **Healthiest** (near-total liveness, model schemas): **hook**, **validation**.
60+
- **Worst**: **policy** (100% dead), **portal** (100% dead), **tool** (write-only).
61+
62+
## Suggested ADRs
63+
1. **Security enforcement** (cluster #1) — highest priority; either enforce or remove every parsed-but-unenforced security prop.
64+
2. **Finish ADR-0021** (cluster #2) — migrate chart/dashboard/report renderers + Studio off the legacy inline shape.
65+
3. **Spec hygiene** (clusters #3#7) — normalize naming drift, prune aspirational config, reconcile write-only/disconnected types, declare the undeclared-but-read props, close designer authoring gaps.

0 commit comments

Comments
 (0)