Skip to content

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

Description

@objectstack-fleet

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.

Who acts on it:

The rule, as ruled

Q4 (6039049826) → A:

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.
  • 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 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)

  1. 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.
  2. The ADR-0048 §3.4 narrowing, as a dated note. This is Tier H: it needs the maintainer's approval.
  3. 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)

Dedupe: MCP search_issues, repo-scoped.

Dedupe words: security catalog shared name refusal · permission set name collision install · ADR-0048 3.4 narrowing


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:engineenhancementNew feature or requestpriority:p1High: required for production / M2target:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions