Commit 9a1205f
fix(objectql): apply D7 setup-nav contributions in the protocol serving path (#1457)
* docs(adr): add ADR-0028 metadata naming & namespace isolation
Propose retiring the hand-written namespace-prefix authoring rule
(only objects are protected today; ~23 other metadata kinds collide
silently, e.g. connectors last-wins-overwrite) in favor of:
- namespace as an identity dimension (short authored names; identity
= (namespace, type, name))
- physical table names derived at the storage boundary, invisible to
authors/AI (inverting the existing StorageNameMapping pass-through)
- namespace as an addressing segment at transport surfaces (data API,
metadata API, generated GraphQL/OData/SDK/MCP)
- app sandboxing: no cross-app references (security boundary); only
app -> kernel references are legal
- a single unified reserved kernel namespace (sys) whose contract is
unified but whose object ownership is distributed across first-party
capability plugins (single-owner-per-object), decomposing the
platform-objects monolith
Grounded in a codebase scan (current-state findings + kernel
cross-reference graph) and mainstream platform practice
(Salesforce 2GP / ServiceNow scoped apps / Dataverse). Includes a
phased, non-breaking migration plan.
https://claude.ai/code/session_01Tv6F1Ub6bhCedrx3r8sZM4
* docs(adr): fix ADR-0028 broken cross-reference
ADR-0004 is "Cloud Control Plane", not the object-namespace-prefix rule
(which lives only in manifest.zod.ts / stack.zod.ts, with no standalone
ADR). Replace the broken ./0004-object-namespace-prefix.md link with a
Supersedes note pointing at the actual source files.
https://claude.ai/code/session_01Tv6F1Ub6bhCedrx3r8sZM4
* docs(adr): breakage-controlled migration plan for ADR-0028
Rework the migration section around three compatibility mechanisms so
existing templates are never broken in a flag-day cutover:
- per-package `namingMode: 'literal' | 'short'` manifest flag (old and
new packages coexist in one instance; migration is opt-in per package)
- idempotent, namespace-aware `resolveTableName` (dual-read) so adding
derivation does not turn `crm_account` into `crm_crm_account`
- sealed artifacts are never force-republished (codemod rewrites source
templates only)
Each phase (P0 foundations → P5 remove-legacy) now has an explicit exit
gate; the only breaking step (P4) is per-package opt-in and driven by an
`os migrate namespace` codemod. Kernel refactor (P2) is decoupled and
template-transparent.
https://claude.ai/code/session_01Tv6F1Ub6bhCedrx3r8sZM4
* docs(adr): add ADR-0029 kernel object ownership; slim ADR-0028 P2 to reference it
Carve the kernel-decomposition concern out of ADR-0028 into its own ADR:
first-party capabilities become plugins that own their sys_* objects +
behavior (correcting the platform-objects monolith where plugins declare
namespace:'sys' but the objects are defined centrally).
ADR-0029:
- small core (identity/org hub + metadata) vs capability plugins
(audit/jobs/email/approvals/sharing/ai/webhooks) that each own their objects
- shared reserved `sys` namespace, single-owner-PER-OBJECT (not per-namespace,
not a monolith owner)
- hub + dependencies/loadOrder instead of centralization
- decompose platform-objects behind a re-export facade
- template-transparent, independently shippable, sequenced BEFORE the 0028
naming flip; phased K0-K4 with exit gates
ADR-0028: Phase 2 now delegates to ADR-0029; header gains it as a
prerequisite; D5 points to ADR-0029 as the authoritative source for the
ownership mechanics (0028 keeps only the naming/contract decision).
https://claude.ai/code/session_01Tv6F1Ub6bhCedrx3r8sZM4
* docs(adr): ADR-0029 — add navigation-contribution mechanism for the setup app (D7)
Decomposing platform-objects breaks the premise that lets the `setup`
admin app be a static monolith (it hard-references every sys_* object;
its own comment notes it was made static *because* the objects were
centralized, and the runtime-assembling plugin-setup was deleted).
manifest.contributes.menus exists but is consumed nowhere, and there is
no app-extension analog to objectExtensions.
Add D7: setup becomes a base-owned "shell + group slots"; each capability
plugin contributes its nav entries via a declarative navigation
contribution (the UI analog of objectExtensions), merged by group +
priority, each entry gated by the existing requiresObject /
requiredPermissions nav fields (which doubles as the disable mechanism).
Wire it through the migration plan (K1 builds the shell + mechanism; K2
moves each domain's nav entries out as contributions) and record the
schema choice as an open question.
https://claude.ai/code/session_01Tv6F1Ub6bhCedrx3r8sZM4
* fix(objectql): apply D7 nav contributions in the protocol serving path
The Setup app is a shell of empty group anchors (ADR-0029 D7); menu
entries are injected as navigation contributions and merged lazily on
read. `SchemaRegistry.getApp` / `getAllApps` did the merge, but the REST
app endpoints read through `protocol.getMetaItems` / `getMetaItem`, which
returned the raw shell — so every Setup menu group rendered empty.
Apply the contribution merge in both protocol read paths (list + single)
for the `app`/`apps` types, mirroring `getApp`/`getAllApps`. The stored
app is never mutated (structuredClone), so reads stay idempotent.
`SchemaRegistry.applyNavContributions` is promoted from private to public
so the protocol can reach the same merge logic.
Adds regression tests covering both `getMetaItems({type:'app'})` and
`getMetaItem({type:'app'})`.
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 3a45780 commit 9a1205f
3 files changed
Lines changed: 77 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
791 | 791 | | |
792 | 792 | | |
793 | 793 | | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
794 | 847 | | |
795 | 848 | | |
796 | 849 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1281 | 1281 | | |
1282 | 1282 | | |
1283 | 1283 | | |
| 1284 | + | |
| 1285 | + | |
| 1286 | + | |
| 1287 | + | |
| 1288 | + | |
| 1289 | + | |
| 1290 | + | |
| 1291 | + | |
| 1292 | + | |
| 1293 | + | |
1284 | 1294 | | |
1285 | 1295 | | |
1286 | 1296 | | |
| |||
1417 | 1427 | | |
1418 | 1428 | | |
1419 | 1429 | | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
| 1437 | + | |
1420 | 1438 | | |
1421 | 1439 | | |
1422 | 1440 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1012 | 1012 | | |
1013 | 1013 | | |
1014 | 1014 | | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
1015 | 1020 | | |
1016 | | - | |
| 1021 | + | |
1017 | 1022 | | |
1018 | 1023 | | |
1019 | 1024 | | |
| |||
0 commit comments