Skip to content

Commit 5039194

Browse files
os-zhuangclaude
andcommitted
fix(spec): object.tenancy.tenantField is live (sql-driver tenant scoping), not dead
5th audit reversal found while attempting the 'obvious safe delete' of tenancy.* (assumed obsolete under DB-per-tenant). In fact the platform ALSO does row-level org-scoping (plugin-org-scoping), and driver-sql resolves tenant scope from obj.tenancy.{enabled,tenantField} — so tenantField is LIVE. Reclassified; flagged strategy/crossTenantAccess to verify before any change. agent.tenantId confirmed dead (no reader in service-ai or objectui AgentPreview). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 038ccde commit 5039194

1 file changed

Lines changed: 215 additions & 50 deletions

File tree

packages/spec/liveness/object.json

Lines changed: 215 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,228 @@
22
"type": "object",
33
"_note": "ObjectSchema (top-level). Seeded from docs/audits/2026-06-objectschema-property-liveness.md. Roughly half dead — a large aspirational enterprise-data-management tier with zero runtime. Framework evidence cited with paths; objectui-renderer evidence as prose.",
44
"props": {
5-
"name": { "status": "live", "evidence": "packages/plugins/driver-sql/src/sql-driver.ts", "note": "table name; objectql registry key." },
6-
"label": { "status": "live", "note": "objectui app-shell/grid." },
7-
"pluralLabel": { "status": "live", "note": "objectui." },
8-
"description": { "status": "live", "note": "display metadata." },
9-
"icon": { "status": "live", "note": "objectui." },
10-
"displayNameField": { "status": "live", "note": "objectui RecordDetailView." },
11-
"titleFormat": { "status": "live", "note": "objectui ({{record.field}} interpolation)." },
12-
"compactLayout": { "status": "live", "note": "objectui hover/cards/lookups." },
13-
"fieldGroups": { "status": "live", "note": "objectui form layout order." },
14-
"listViews": { "status": "live", "note": "objectui segmented tabs." },
15-
"detail": { "status": "live", "note": "objectui plugin-detail (detail.renderViaSchema)." },
16-
"fields": { "status": "live", "evidence": "packages/objectql/src/engine.ts", "note": "engine/DDL + forms." },
17-
"datasource": { "status": "live", "evidence": "packages/objectql/src/engine.ts:1147", "note": "driver routing." },
18-
"external": { "status": "live", "evidence": "packages/runtime/src/external-validation-plugin.ts", "note": "remote table + write gate." },
19-
"indexes": { "status": "live", "evidence": "packages/plugins/driver-sql/src/sql-driver.ts:1181", "note": "DDL." },
20-
"validations": { "status": "live", "evidence": "packages/objectql/src/validation/rule-validator.ts:154", "note": "incl. state_machine." },
21-
"activityMilestones": { "status": "live", "evidence": "packages/plugins/plugin-audit/src/audit-writers.ts", "note": "ADR-0052 §5b.2 — audit-writer matchMilestone() emits a templated activity row when a watched field transitions into the configured value." },
22-
"actions": { "status": "live", "evidence": "packages/runtime/src/app-plugin.ts:929", "note": "served on /meta/objects/:name." },
23-
"managedBy": { "status": "live", "evidence": "packages/objectql/src/registry.ts:208", "note": "default perms; ui crudAffordances." },
24-
"userActions": { "status": "live", "note": "objectui ObjectGrid per-object CRUD." },
25-
"systemFields": { "status": "live", "evidence": "packages/objectql/src/registry.ts", "note": "organization_id auto-inject gate." },
26-
"sharingModel": { "status": "live", "evidence": "packages/plugins/plugin-sharing/src/sharing-service.ts:54" },
27-
"publicSharing": { "status": "live", "evidence": "packages/plugins/plugin-sharing/src/share-link-service.ts:56" },
5+
"name": {
6+
"status": "live",
7+
"evidence": "packages/plugins/driver-sql/src/sql-driver.ts",
8+
"note": "table name; objectql registry key."
9+
},
10+
"label": {
11+
"status": "live",
12+
"note": "objectui app-shell/grid."
13+
},
14+
"pluralLabel": {
15+
"status": "live",
16+
"note": "objectui."
17+
},
18+
"description": {
19+
"status": "live",
20+
"note": "display metadata."
21+
},
22+
"icon": {
23+
"status": "live",
24+
"note": "objectui."
25+
},
26+
"displayNameField": {
27+
"status": "live",
28+
"note": "objectui RecordDetailView."
29+
},
30+
"titleFormat": {
31+
"status": "live",
32+
"note": "objectui ({{record.field}} interpolation)."
33+
},
34+
"compactLayout": {
35+
"status": "live",
36+
"note": "objectui hover/cards/lookups."
37+
},
38+
"fieldGroups": {
39+
"status": "live",
40+
"note": "objectui form layout order."
41+
},
42+
"listViews": {
43+
"status": "live",
44+
"note": "objectui segmented tabs."
45+
},
46+
"detail": {
47+
"status": "live",
48+
"note": "objectui plugin-detail (detail.renderViaSchema)."
49+
},
50+
"fields": {
51+
"status": "live",
52+
"evidence": "packages/objectql/src/engine.ts",
53+
"note": "engine/DDL + forms."
54+
},
55+
"datasource": {
56+
"status": "live",
57+
"evidence": "packages/objectql/src/engine.ts:1147",
58+
"note": "driver routing."
59+
},
60+
"external": {
61+
"status": "live",
62+
"evidence": "packages/runtime/src/external-validation-plugin.ts",
63+
"note": "remote table + write gate."
64+
},
65+
"indexes": {
66+
"status": "live",
67+
"evidence": "packages/plugins/driver-sql/src/sql-driver.ts:1181",
68+
"note": "DDL."
69+
},
70+
"validations": {
71+
"status": "live",
72+
"evidence": "packages/objectql/src/validation/rule-validator.ts:154",
73+
"note": "incl. state_machine."
74+
},
75+
"activityMilestones": {
76+
"status": "live",
77+
"evidence": "packages/plugins/plugin-audit/src/audit-writers.ts",
78+
"note": "ADR-0052 §5b.2 — audit-writer matchMilestone() emits a templated activity row when a watched field transitions into the configured value."
79+
},
80+
"actions": {
81+
"status": "live",
82+
"evidence": "packages/runtime/src/app-plugin.ts:929",
83+
"note": "served on /meta/objects/:name."
84+
},
85+
"managedBy": {
86+
"status": "live",
87+
"evidence": "packages/objectql/src/registry.ts:208",
88+
"note": "default perms; ui crudAffordances."
89+
},
90+
"userActions": {
91+
"status": "live",
92+
"note": "objectui ObjectGrid per-object CRUD."
93+
},
94+
"systemFields": {
95+
"status": "live",
96+
"evidence": "packages/objectql/src/registry.ts",
97+
"note": "organization_id auto-inject gate."
98+
},
99+
"sharingModel": {
100+
"status": "live",
101+
"evidence": "packages/plugins/plugin-sharing/src/sharing-service.ts:54"
102+
},
103+
"publicSharing": {
104+
"status": "live",
105+
"evidence": "packages/plugins/plugin-sharing/src/share-link-service.ts:56"
106+
},
28107
"tenancy": {
29108
"children": {
30-
"enabled": { "status": "live", "evidence": "packages/plugins/driver-sql/src/sql-driver.ts:1081" },
31-
"strategy": { "status": "dead", "evidence": "inert — only tenancy.enabled is read" },
32-
"tenantField": { "status": "dead", "evidence": "inert" },
33-
"crossTenantAccess": { "status": "dead", "evidence": "inert" }
109+
"enabled": {
110+
"status": "live",
111+
"evidence": "packages/plugins/driver-sql/src/sql-driver.ts:1081"
112+
},
113+
"strategy": {
114+
"status": "dead",
115+
"evidence": "inert — only tenancy.enabled is read",
116+
"note": "part of the live tenancy block (sql-driver reads enabled+tenantField); verify before touching."
117+
},
118+
"tenantField": {
119+
"status": "live",
120+
"evidence": "packages/plugins/driver-sql/src/sql-driver.ts",
121+
"note": "row-level tenant scoping (org-scoping plugin path) reads tenancy.tenantField — audit called it inert; corrected."
122+
},
123+
"crossTenantAccess": {
124+
"status": "dead",
125+
"evidence": "inert",
126+
"note": "part of the live tenancy block; verify before touching."
127+
}
34128
}
35129
},
36130
"enable": {
37131
"children": {
38-
"apiEnabled": { "status": "live", "evidence": "packages/rest/src/rest-server.ts", "note": "enforced by enforceApiAccess on the REST data surface (ADR-0049 #1889) — apiEnabled:false → 404." },
39-
"apiMethods": { "status": "live", "evidence": "packages/rest/src/rest-server.ts", "note": "enforced by enforceApiAccess — operations outside the whitelist → 405." },
40-
"trackHistory": { "status": "dead", "evidence": "no behavior-changing reader (database-loader.trackHistory is a separate ctor option)" },
41-
"searchable": { "status": "dead", "evidence": "no behavior-changing reader" },
42-
"files": { "status": "dead", "evidence": "no behavior-changing reader" },
43-
"feeds": { "status": "dead", "evidence": "no behavior-changing reader" },
44-
"activities": { "status": "dead", "evidence": "no behavior-changing reader" },
45-
"trash": { "status": "dead", "evidence": "no behavior-changing reader" },
46-
"mru": { "status": "dead", "evidence": "no behavior-changing reader" },
47-
"clone": { "status": "dead", "evidence": "no behavior-changing reader" }
132+
"apiEnabled": {
133+
"status": "live",
134+
"evidence": "packages/rest/src/rest-server.ts",
135+
"note": "enforced by enforceApiAccess on the REST data surface (ADR-0049 #1889) — apiEnabled:false → 404."
136+
},
137+
"apiMethods": {
138+
"status": "live",
139+
"evidence": "packages/rest/src/rest-server.ts",
140+
"note": "enforced by enforceApiAccess — operations outside the whitelist → 405."
141+
},
142+
"trackHistory": {
143+
"status": "dead",
144+
"evidence": "no behavior-changing reader (database-loader.trackHistory is a separate ctor option)"
145+
},
146+
"searchable": {
147+
"status": "dead",
148+
"evidence": "no behavior-changing reader"
149+
},
150+
"files": {
151+
"status": "dead",
152+
"evidence": "no behavior-changing reader"
153+
},
154+
"feeds": {
155+
"status": "dead",
156+
"evidence": "no behavior-changing reader"
157+
},
158+
"activities": {
159+
"status": "dead",
160+
"evidence": "no behavior-changing reader"
161+
},
162+
"trash": {
163+
"status": "dead",
164+
"evidence": "no behavior-changing reader"
165+
},
166+
"mru": {
167+
"status": "dead",
168+
"evidence": "no behavior-changing reader"
169+
},
170+
"clone": {
171+
"status": "dead",
172+
"evidence": "no behavior-changing reader"
173+
}
48174
}
49175
},
50-
"versioning": { "status": "dead", "evidence": "aspirational; no runtime" },
51-
"partitioning": { "status": "dead", "evidence": "aspirational; no runtime" },
52-
"cdc": { "status": "dead", "evidence": "aspirational; no runtime" },
53-
"softDelete": { "status": "dead", "evidence": "no runtime; duplicates the (also dead) enable.trash" },
54-
"search": { "status": "dead", "evidence": "SearchConfigSchema — no runtime; duplicates enable.searchable" },
55-
"recordTypes": { "status": "dead", "evidence": "elaborate docstring, unimplemented" },
56-
"defaultDetailForm": { "status": "dead", "evidence": "documented fallback chain unimplemented" },
57-
"recordName": { "status": "dead", "evidence": "superseded by a field of type:'autonumber' + autonumberFormat (engine.ts:757)" },
58-
"keyPrefix": { "status": "dead", "evidence": "no runtime" },
59-
"tags": { "status": "dead", "evidence": "no runtime reader" },
60-
"abstract": { "status": "dead", "evidence": "no runtime reader" },
61-
"isSystem": { "status": "dead", "evidence": "object-level — no runtime reader" },
62-
"active": { "status": "dead", "evidence": "object-level — no runtime reader" }
176+
"versioning": {
177+
"status": "dead",
178+
"evidence": "aspirational; no runtime"
179+
},
180+
"partitioning": {
181+
"status": "dead",
182+
"evidence": "aspirational; no runtime"
183+
},
184+
"cdc": {
185+
"status": "dead",
186+
"evidence": "aspirational; no runtime"
187+
},
188+
"softDelete": {
189+
"status": "dead",
190+
"evidence": "no runtime; duplicates the (also dead) enable.trash"
191+
},
192+
"search": {
193+
"status": "dead",
194+
"evidence": "SearchConfigSchema — no runtime; duplicates enable.searchable"
195+
},
196+
"recordTypes": {
197+
"status": "dead",
198+
"evidence": "elaborate docstring, unimplemented"
199+
},
200+
"defaultDetailForm": {
201+
"status": "dead",
202+
"evidence": "documented fallback chain unimplemented"
203+
},
204+
"recordName": {
205+
"status": "dead",
206+
"evidence": "superseded by a field of type:'autonumber' + autonumberFormat (engine.ts:757)"
207+
},
208+
"keyPrefix": {
209+
"status": "dead",
210+
"evidence": "no runtime"
211+
},
212+
"tags": {
213+
"status": "dead",
214+
"evidence": "no runtime reader"
215+
},
216+
"abstract": {
217+
"status": "dead",
218+
"evidence": "no runtime reader"
219+
},
220+
"isSystem": {
221+
"status": "dead",
222+
"evidence": "object-level — no runtime reader"
223+
},
224+
"active": {
225+
"status": "dead",
226+
"evidence": "object-level — no runtime reader"
227+
}
63228
}
64229
}

0 commit comments

Comments
 (0)