You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(objectql,metadata,runtime)!: refuse a package whose position, permission set or capability name is already held by an installed package, the environment catalog or a built-in (ruling Q4 = A on #15196; narrows ADR-0048 §3.4) #22135
Filing gate: ③ a task the maintainer assigned directly. On #15196 the maintainer answered 「15196 Q3 A Q4 A」 (ruling record 6050490870, written by the director seat). The record's execution line says: "the seat files the install-time refusal as its own card (with the ADR-0048 §3.4 narrowing note, Tier H, the maintainer's approval) and S1's same-name test locks 'refuse'". This is that card.
The three security catalog types (positions, permission sets, capabilities) each hold one namespace per deployment. Installing or registering a package whose position, permission set or capability bears a name an installed package, the environment catalog or a built-in already holds is refused, the error naming both holders. ADR-0048 §3.4's retirement of the cross-package throw is narrowed to leave these three types out: an assignment carries a bare name with no package context, so for the security catalog a shared name is a real ambiguity, not the disambiguable one §3.4 describes for UI metadata.
Not taken:
B: assignments carrying package + name.
C: resolution by registration order.
Where today's behaviour is (read on origin/main)
ADR-0048 §3.4 (docs/adr/0048-cross-package-metadata-collision.md near :244) retired the per-item cross-package throw. Two packages coexist on one bare name, and prefer-local resolution (getItem(type, name, currentPackageId?)) picks between them.
A by-name security read has no current package, so a shared name resolves by registration order or by whichever package stored an override.
The doors a package's positions, permission sets and capabilities register through:
AppPlugin's security-metadata registrar (packages/runtime/src/app-plugin.ts near :1007, metadata.registerInMemory over positions / permissions / capabilities);
the artifact door (packages/metadata/src/plugin.ts, ARTIFACT_FIELD_TO_TYPE near :122, its loop near :1162);
package install in SchemaRegistry (packages/objectql/src/registry.ts). The ADR-0048 Phase 1 namespace gate already lives there: NamespaceConflictError near :1501, which answers 422 with an ADR-0112 envelope. It is the nearest sibling for the new refusal's shape.
Built-in holders:
the platform permission sets that plugin-security puts on its manifest as permissions (security-plugin.ts near :1448);
The current pin: S1's shared-name pin (P1.2, PR feat(core): one by-name read of the security catalog (ADR-0131 C2, stage S1) #22091) pins today's answer (the registry's precedence for a name two packages ship). It lives in packages/objectql/src/protocol-boot-hydration-scoped.test.ts. S1's unit file packages/core/src/security/security-catalog.test.ts (near :16) points to it under a file name that does not exist (security-catalog-shared-name.test.ts). Correct that pointer in the same change.
What to build (direction; the claiming seat's order is the spec)
The refusal at every door above, for the three types only. It names both holders (incoming package, and the installed package, environment catalog or built-in that holds the name). It carries an ADR-0112 envelope (code + status), so the wire answers a 4xx, not 500. Same-package re-registration (idempotent reload) stays allowed, as ADR-0048 §3.4 keeps it.
The ADR-0048 §3.4 narrowing, as a dated note. This is Tier H: it needs the maintainer's approval.
S1's P1.2 flips from pinning today's answer to pinning the refusal, with its ablation.
Measure first
Every door a package's item of these types can arrive through: boot, hot install, POST /api/v1/packages, the artifact door. Name any door beyond the three above.
Every in-repo package and example, for a name this rule would now refuse. The ruling's chat reading was that app-crm and app-showcase do not collide today. A collision would now fail a boot, so it must be found before the refusal ships.
What the ruling does not cover: an environment-catalog save over a package-held name (ADR-0005 overlay precedence). Report what happens today; ⛔ do not change it without a ruling.
OS_METADATA_COLLISION=warn downgrades the namespace gate. The ruling says "refused" and names no downgrade, so by default it does not apply here. If the build finds a reason it should, that is an open_question on this card, not a choice.
Sequencing (the domain:services seat 2's call for #15196)
Filing gate: ③ a task the maintainer assigned directly. On #15196 the maintainer answered 「15196 Q3 A Q4 A」 (ruling record
6050490870, written by the director seat). The record's execution line says: "the seat files the install-time refusal as its own card (with the ADR-0048 §3.4 narrowing note, Tier H, the maintainer's approval) and S1's same-name test locks 'refuse'". This is that card.domain:servicesseat 2 (seat post [PM seat] domain:services · seat 2 — ⏳ vacant #21118),session_01WMQprn46CND82KmY8sZWBu, for triage.Who acts on it:
domain:servicesseat 2 reads it for feat(core,objectql,plugin-security,plugin-sharing): the catalog is read from the registry; assignment tables reference it by name (ADR-0131 D2/D3/D4) #15196's sequence (see "Sequencing" below).The rule, as ruled
Q4 (
6039049826) → A:Not taken:
package + name.Where today's behaviour is (read on
origin/main)docs/adr/0048-cross-package-metadata-collision.mdnear:244) retired the per-item cross-package throw. Two packages coexist on one bare name, and prefer-local resolution (getItem(type, name, currentPackageId?)) picks between them.6038897018): a list-then-first-wins reader keeps the first item per name.AppPlugin's security-metadata registrar (packages/runtime/src/app-plugin.tsnear:1007,metadata.registerInMemoryoverpositions/permissions/capabilities);packages/metadata/src/plugin.ts,ARTIFACT_FIELD_TO_TYPEnear:122, its loop near:1162);SchemaRegistry(packages/objectql/src/registry.ts). The ADR-0048 Phase 1 namespace gate already lives there:NamespaceConflictErrornear:1501, which answers422with an ADR-0112 envelope. It is the nearest sibling for the new refusal's shape.plugin-securityputs on its manifest aspermissions(security-plugin.tsnear:1448);packages/objectql/src/protocol-boot-hydration-scoped.test.ts. S1's unit filepackages/core/src/security/security-catalog.test.ts(near:16) points to it under a file name that does not exist (security-catalog-shared-name.test.ts). Correct that pointer in the same change.What to build (direction; the claiming seat's order is the spec)
code+status), so the wire answers a 4xx, not500. Same-package re-registration (idempotent reload) stays allowed, as ADR-0048 §3.4 keeps it.Measure first
POST /api/v1/packages, the artifact door. Name any door beyond the three above.app-crmandapp-showcasedo not collide today. A collision would now fail a boot, so it must be found before the refusal ships.OS_METADATA_COLLISION=warndowngrades the namespace gate. The ruling says "refused" and names no downgrade, so by default it does not apply here. If the build finds a reason it should, that is anopen_questionon this card, not a choice.Sequencing (the
domain:servicesseat 2's call for #15196)Dedupe: MCP
search_issues, repo-scoped.sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206, refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 and Epic: packaged-metadata customization (ADR-0126) — flows first, v17 line #12150, and none of them is this. That feat(core,objectql,plugin-security,plugin-sharing): the catalog is read from the registry; assignment tables reference it by name (ADR-0131 D2/D3/D4) #15196 itself comes back is the positive control.Dedupe words:
security catalog shared name refusal·permission set name collision install·ADR-0048 3.4 narrowingGenerated by Claude Code