Skip to content

metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334

Description

@objectstack-fleet

QA-source: #21330 · studio-authoring.view-authoring-live · outside the item's clauses (found while driving it and platform-core.metadata-authoring-roundtrip)

What fails

A runtime view container whose list names no key expands to <object>.default. Saved under any name — in a writable package or as an org overlay — for an object another package ships, that expansion overwrites the packaged <object>.default on the object door, with no diagnostic, a wrong _packageId, and a by-name read that disagrees.

Reproduction (stock showcase on 17.6.0 617f25f8, admin)

  1. Baseline: GET /api/v1/meta/view?object=showcase_task → showcase_task.default label "All Tasks", _packageId: com.example.showcase, 7 columns.
  2. POST /api/v1/packages {"manifest":{"id":"com.example.repairassets","name":"Repair assets","version":"0.1.0","type":"app","namespace":"repair"}} → 201.
  3. PUT /api/v1/meta/view/os_qa_shadow_probe?mode=draft&package=com.example.repairassets {"name":"os_qa_shadow_probe","object":"showcase_task","list":{"type":"grid","columns":["title","status"]}} → 200.
  4. POST /api/v1/packages/com.example.repairassets/publish-drafts → 200, outcome: published, probes.issues: [].
  5. GET /api/v1/meta/view?object=showcase_task → showcase_task.default now has label "showcase_task.default", 2 columns, still stamped _packageId: com.example.showcase, isDefault: true. The console's Task list default tab becomes this view (with a column the object lacks, the tab shows "This view's query was rejected").
  6. GET /api/v1/meta/view/showcase_task.default → still "All Tasks", 7 columns — the two read doors disagree.
  7. DELETE /api/v1/meta/view/os_qa_shadow_probe → the list read returns to "All Tasks".
  8. The same happens with no ?package= (an org-scoped PUT /api/v1/meta/view/os_qa_shadow_probe2).
  9. Control: the sanctioned override PUT /api/v1/meta/view/showcase_task.default → both reads agree.

Reproduced on two fresh boots by the runner and three times by an independent verifier.

Mechanism

  • expandViewContainerWithDiagnostics (packages/spec/src/ui/view.zod.ts) names a bare list <object>.default; uniqueViewName de-duplicates only within the one container.
  • getMetaItems (packages/metadata-protocol/src/protocol.ts) then sets every overlay's expansion by name over the merged items, bypassing the package-aware overlay merge that runs just before it; expandRuntimeViewContainer appears to copy the shadowed artifact's protection / _packageId onto the item.
  • The by-name read never expands containers, so it keeps the packaged item.

Expected

ADR-0005 keeps overlays name-keyed; ADR-0126 rules out silent override. Either the expansion takes a name that does not collide (seed the de-dup with existing names), or the save / publish is refused or flagged with a collision diagnostic. Independently, the two read doors must agree and the expanded item must carry its own package.

Scope

Not an authorization issue: authoring the container needs manage_metadata (or manage_org_presentation org-scoped), and that caller can already override showcase_task.default by name. It is a silent, reversible integrity defect. Severity (verifier): medium. Owning repo: objectstack.

Full run evidence: #21330.


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

No one assigned

    Labels

    area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingdomain:enginepriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions