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 bindHookspackageId: '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

vercelBot commented Jun 12, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specBuildingBuildingPreview, CommentJun 12, 2026 9:18am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Jun 12, 2026
@os-zhuang
os-zhuang merged commit b10aa78 into mainJun 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 freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang