Skip to content

feat(metadata): metadata-service registrations carry package provenance#1776

Merged
os-zhuang merged 1 commit into
mainfrom
feat-metadata-provenance-stamping
Jun 12, 2026
Merged

feat(metadata): metadata-service registrations carry package provenance#1776
os-zhuang merged 1 commit into
mainfrom
feat-metadata-provenance-stamping

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

Metadata registered through the metadata-service path had no provenance flags: loadMetadataFromService (objectql/src/plugin.ts) and MetadataFacade.register called registry.registerItem(type, item, keyField) without the 4th packageId param, so applyProtection never stamped _packageId/_provenance. GET /api/v1/meta/:type consumers (objectui NavigationSyncEffect, objectui PR #1668) could not tell package-shipped code-defined metadata from user-authored rows and fell back to the sys_ name-prefix heuristic — third-party plugin pages were misclassified as user-created.

Changes

  • packages/objectql/src/plugin.ts (loadMetadataFromService) and packages/objectql/src/metadata-facade.ts (register): pass through each item's own _packageId (stamped upstream by the metadata plugin's artifact loader). Never a synthetic id like 'metadata-service'isArtifactBacked() keys the two-tier write authorization (allowOrgOverride vs allowRuntimeCreate) off a truthy _packageId; a fake id would flip authorization for runtime-authored items. (The nearby bindHooks packageId: 'metadata-service' is an unbind-grouping label, not provenance.)
  • packages/metadata/src/plugin.ts: new MetadataPluginOptions.packageId — hosts running the filesystem scanner (eager mode, no artifactSource) can declare the owning package id (the project's defineStack manifest id); _loadFromFileSystem then stamps scanned items via the same applyProtection call the artifact path uses. Unset → behavior unchanged. Deliberately not auto-derived from package.json (npm name ≠ manifest id, and the value feeds write authorization).
  • Side benefit: synced artifact items now store under the same composite pkg:name registry key as the engine manifest path, deduplicating the previous bare+composite double entries.

Deliberately unchanged: the protocol.ts DB-hydration registerItem calls (loadMetaFromDb, getMetaItems hydration, overlay-delete refill) stay bare-key — ADR-0005 overlay precedence relies on the bare runtime row shadowing the composite package artifact entry.

Testing

  • New packages/objectql/src/metadata-facade.test.ts (passthrough / no synthetic stamping).
  • plugin.integration.test.ts: metadata-service sync preserves the stamped/unstamped distinction.
  • protocol-meta.test.ts: getMetaItems serves _packageId/_provenance for package-registered items, leaves user items clean.
  • packages/metadata/src/plugin.test.ts: FS-scanner stamping with/without the option; pre-existing _packageId not overwritten.
  • Full suites green: objectql 42 files / 561 tests, metadata 11 files / 249 tests.

🤖 Generated with Claude Code

The metadata-service sync path (loadMetadataFromService) and
MetadataFacade.register called registry.registerItem without the 4th
packageId param, so applyProtection never stamped _packageId /
_provenance on synced items — GET /api/v1/meta/:type consumers
(objectui NavigationSyncEffect, objectui PR #1668) could not tell
package-shipped code-defined metadata from user-authored rows and fell
back to the sys_ name-prefix heuristic, misclassifying third-party
plugin pages.

Fix: pass through each item's own _packageId (stamped upstream by the
metadata plugin's artifact loader). Never synthesize an id like
'metadata-service' — isArtifactBacked() keys two-tier write
authorization (allowOrgOverride vs allowRuntimeCreate) off a truthy
_packageId, so a fake id would flip authorization for runtime-authored
items. The nearby bindHooks packageId is an unbind-grouping label, not
provenance.

Deliberately unchanged: protocol.ts DB-hydration registerItem calls
(loadMetaFromDb / getMetaItems hydration / overlay-delete refill) stay
bare-key — ADR-0005 overlay precedence relies on the bare runtime row
shadowing the composite pkg:name artifact entry.

Also closes the filesystem-scanner gap: new MetadataPluginOptions
.packageId (the project's defineStack manifest id) lets hand-wired
kernels stamp scanned source-file metadata via the same applyProtection
call the artifact path uses. Unset → unchanged behavior; the option is
never guessed from package.json (npm name ≠ manifest id, and the value
feeds write authorization).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Building Building Preview, Comment Jun 12, 2026 9:18am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Jun 12, 2026
@os-zhuang
os-zhuang merged commit b10aa78 into main Jun 12, 2026
10 of 11 checks passed
@os-zhuang
os-zhuang deleted the feat-metadata-provenance-stamping branch June 12, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant