Skip to content

ADR-0048 follow-up: package-scoped metadata overlays (env-wide overlay can't disambiguate same-name collisions) #1824

Description

@xuyushun441-sys

Context

ADR-0048 (package-id as route/identity key) landed across #1810, #1813, #1816, #1819, #1822 (+ objectui #1708, #1711). Single-item reads (?package=), the Studio editor, and the runtime render surface (dashboard/report/page/doc via prefer-local) now resolve same-name collisions to the correct package — for pure-artifact items (the marketplace default).

The remaining gap

A package-less, env-wide customization overlay (a sys_metadata row with package_id NULL) for a name that collides across two installed packages is inherently ambiguous and cannot be disambiguated today.

Root cause is schema-level: sys_metadata has a UNIQUE index on (type, name, organization_id) (idx_sys_metadata_overlay_active / …_draft), not including package_id. So:

  • At most ONE active overlay row can exist per (type, name, org).
  • restoreMetadataFromDb rehydrates that row under the bare registry key (no package), where it takes ADR-0005 overlay precedence over BOTH packages' composite artifacts.
  • A getMetaItem(type, name, packageId) whose overlay query misses the scoped package_id falls back to the package-less row and serves the same overlay for every package.

Concretely: showcase ships page/home, studio ships page/home; an admin customizes one → the env overlay shadows both, and ?package= can't tell them apart.

Proposed direction (needs an ADR / design decision)

Make overlays package-aware:

  • Add package_id to the overlay uniqueness key: UNIQUE(type, name, organization_id, package_id) (migration + backfill).
  • saveMetaItem binds the overlay to the edited item's owning package (the Studio editor already threads ?package= since docs(references): regenerate flow reference for the map node type #1711 — the write path needs to persist it).
  • restoreMetadataFromDb registers package-bound overlays under the composite key, not bare.
  • protocol.getMetaItem / getMetaItemLayered overlay queries already prefer package_id-scoped rows (ADR-0048); the package-less fallback should only apply to genuinely package-less (legacy/global) overlays.

Open questions

  • Migration story for existing package-less overlay rows (treat as global? attribute to first-match package? leave as-is with a lint?).
  • Should a package-less overlay still be allowed (an intentional "apply to all same-named items" escape hatch), or is every overlay now package-bound?
  • Interaction with org-scoped vs env-wide precedence (ADR-0005).

Acceptance

Out of scope: pure-artifact collisions (already fixed in #1822).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions