Skip to content

[Decision] When a curated capability name is already held in the platform bucket, should the seeder keep declining — or adopt, backfill, or refuse the collision at authoring time? #8552

Description

@os-zhuang

Surfaced while reviewing #8470 / PR #8537. Not blocking that PR — it lands with the conservative behaviour and reports the collision loudly. This card is the policy question the PR deliberately declined to answer, and it is filed because the dev was right to decline it, not because anything is wrong with the fix.

The state the question is about

After #8537, the curated seeder looks up { name, managed_by: 'platform', organization_id: null } — the row the platform owns. If that matches nothing and the insert is then refused by the unique key, the platform's curated definition is missing from sys_capability installation-wide, and the seeder counts it (blockedCurated) and warns on every boot.

It declines to resolve the collision, for two stated reasons: adopting a differently-stamped row into the platform's identity would reverse #5876's ruling that "not provably ours" resolves to leave-it-alone, and backfilling a stamp is a data migration. Both are calls above the implementer's pay grade, so neither was made.

What was measured, not assumed

Two of the three non-platform provenances in that bucket are reachable, and one is ordinary rather than exotic:

  • managed_by: 'admin' — reachable and ordinary.organization_id auto-stamping lives in the enterprise @objectstack/organizations runtime, which is also what activates every walled posture. A deployment without it is single posture with no stamper, so every Setup-authored capability row lands in the NULL-organization bucket. That is the default community shape.
  • managed_by: 'package' — reachable via name promotion, with real instances.bootstrapDeclaredCapabilities refuses a name in PLATFORM_CAPABILITY_NAMES, but a package that declared a name before the platform curated it left a managed_by: 'package' row there. setup.write and manage_sharing were both added to the curated set after the fact.
  • no managed_by at all — NOT engine-reachable. The field is required: true with defaultValue: 'admin', and applyFieldDefaults resolves defaults on insert before the beforeInsert hooks, so an insert omitting it stores 'admin'. (The diagnostic still handles it, because a message must not assert what it cannot observe.)

Why this is a decision and not a follow-up bug

For the package case specifically, #8537changes the outcome on already-upgraded installations rather than only fixing a defect:

before #8537after #8537
installation where a package declared setup.write before it was curatedthe seeder found that row by { name }, took the update branch, and overwrote it with the platform copy — so the platform definition effectively existedthe scoped lookup matches nothing, the insert is refused, and the platform definition is absent installation-wide, with a warning every boot

Neither state is good. The new one is the one ADR-0066 D1 implies (do not clobber another author) and it is honest about itself, which is why it is the right thing to ship now. But whether it is the right long-term answer on the two deployment shapes above is a product call.

The options, stated without a recommendation

  1. Keep declining — the shipped behaviour. The platform definition stays absent on colliding installations; the operator sees a warning naming the blocking row's provenance and has to resolve it by hand.
  2. Adopt a platform-bucket row into the platform's identity when nothing else claims it. Reverses The back-compat capability derivation refreshes label/description on ANY existing sys_capability row, including admin-authored ones — the comment above it says the opposite #5876's "not provably ours → leave alone" for this specific bucket.
  3. Backfill the managed_by stamp for known-curated names in the NULL bucket. A data migration, and it decides on the operator's behalf that those rows were the platform's.
  4. Refuse the collision at authoring time — stop Setup from creating a sys_capability row whose name is in PLATFORM_CAPABILITY_NAMES, so the state cannot arise going forward. Does nothing for installations already carrying one, so it likely pairs with 1 or 3.

⛔ I am not answering this on the maintainer's behalf, and I have deliberately not ranked the options. I will note only that option 4 is the one that matches the standing principle recorded 2026-08-12 — "if the platform cannot honour a declaration, refuse it at the latest checkpoint that can see the whole picture, name the offending key path, and never answer 200" — because authoring a curated name in Setup is precisely a declaration the platform later cannot honour. Whether that principle should govern here is the question, not the answer.

Related

Filed unassigned by the domain:metadata PM seat.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions