docs(adr): ADR-0028 metadata naming & namespace isolation + ADR-0029 kernel object ownership#1431
Merged
Merged
Conversation
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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
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
…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
…etup 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two Proposed design ADRs (docs-only, no code) addressing metadata naming conflicts as more marketplace packages get installed. Today only
objectis collision-protected — and by the wrong mechanism (hand-writtencrm_accountliteral prefix); the other ~23 metadata kinds collide silently (connectors literallylogger.warn('… replaced')then overwrite).Developed collaboratively; grounded in a codebase scan (with
file:linecitations) and mainstream-platform practice (Salesforce 2GP / ServiceNow scoped apps / Dataverse / VS Code / Kubernetes).ADR-0028 — Metadata Naming & Namespace Isolation
(namespace, type, name).crm.send_email/todo.send_emailstop colliding by construction.StorageNameMappingpass-through; the prefix becomes invisible to authors/AI (the concrete answer to the hallucination concern that motivated the literal prefix)./api/v1/data/{namespace}/{object}+ namespaced generated GraphQL/OData/SDK/MCP.app → kernelis legal.sys) — one well-known import (sys.user); ownership distributed (see ADR-0029).Breakage-controlled migration: per-package
namingMode: 'literal' | 'short'flag + idempotent dual-readresolveTableName+ never force-republishing sealed artifacts ⇒ no flag day; the only breaking step (P4) is per-package opt-in and codemod-driven (os migrate namespace).ADR-0029 — Kernel Object Ownership &
platform-objectsDecomposition (prerequisite)Carved out from 0028 because it is a distinct, lower-risk, template-transparent concern that 0028's D5/D6 depend on, and should ship first.
sys_*objects and behavior (fixing the monolith where plugins declarenamespace:'sys'but objects are defined centrally inplatform-objects).sysnamespace, single-owner-per-object (not per-namespace, not a monolith owner).dependencies/loadOrderinstead of centralization; decomposeplatform-objectsbehind a re-export facade.Sequencing
ADR-0029 (kernel ownership, template-transparent) → ADR-0028 P0–P1 (foundations + warn-only) can run in parallel → ADR-0028 P3–P4 (transport + authoring flip).
Open questions for reviewers
sys.uservssys:user).sys(vs domain-partitioned) — argued from the cross-reference graph (~60 lookups converge onsys_user/sys_organization).plugin-sharingvs a dedicatedplugin-rbac); base tier asplugin-identityvsplatform-objects-base.https://claude.ai/code/session_01Tv6F1Ub6bhCedrx3r8sZM4