Skip to content

CURATED_CAPABILITY_LABELS has drifted from PLATFORM_CAPABILITIES — manage_sharing silently loses its localized label #6285

Description

@yinlianghui-tw

Found while taking the measurement for #5899 (see PR #6284 for the full population). Filed unassigned as an observation, for PM triage. Not fixed there — out of that card's scope.

The defect

packages/fields/src/widgets/CapabilityMultiSelectField.tsx:82:

/** * objectui#2600 B5 — the curated platform capabilities are a FIXED, known set * … * (Mirrors @objectstack/spec/security `PLATFORM_CAPABILITIES`.) */constCURATED_CAPABILITY_LABELS=newSet(['manage_users','manage_org_users','manage_metadata','manage_platform_settings','setup_access','setup_write','studio_access',]);

It is used at line 157:

constnorm=name.replace(/\./g,'_');if(CURATED_CAPABILITY_LABELS.has(norm))returnt(`capability.label.${norm}`);returnbyName.get(name)?.label||name;

The Set has 7 members. @objectstack/spec@17.2.0's PLATFORM_CAPABILITIES has 8:

manage_users manage_org_users manage_metadata manage_platform_settings
setup.access setup.write studio.access manage_sharing

Normalized (dots → underscores, which is what labelFor does), the difference is exactly one member: manage_sharing is missing from the local Set. The dotted-vs-underscore spellings are not drift — that transform is deliberate and performed at the call site.

Consequence: manage_sharing falls through to byName.get(name)?.label, i.e. the English label the sys_capability registry serves, and is never localized — while the seven capabilities beside it in the same picker are. That is the exact class the Mirrors comment was written to guard against.

Why nothing caught it

scripts/check-spec-symbol-derivation.mjs rule 2 exists to flag precisely this — a declaration whose doc comment claims spec alignment with no compile-time tie behind it. It could not see this one: both of its scanners skip non-exported declarations, and CURATED_CAPABILITY_LABELS is module-local. That hole is #5899's subject; with the export filter relaxed, this declaration is one of only two additional rule-2 findings in the whole tree, and the only one with measured drift.

Fix shape (not prescribing — this needs the same judgement #5899 does)

Derive the set from the spec instead of restating it, e.g. build it from PLATFORM_CAPABILITIES.map(c => c.name.replace(/\./g, '_')). That both closes today's gap and makes the next spec addition arrive automatically — and it retires the unbacked claim at the same time. If a curated subset is genuinely wanted (i.e. some platform capability should deliberately keep its registry label), that intent needs writing down, because the comment currently says the opposite.

Measured on a76b18cf2 against @objectstack/spec@17.2.0.

Related: #5899 (the instrument hole that hid it), PR #6284 (the census).

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions