Skip to content

loadMetaFromDb object branch reads record.packageId from a snake_case row — always undefined, every object overlay registers under the 'sys_metadata' sentinel at boot #4636

Description

@os-zhuang

Found while implementing #4624 (PR #4635). Unassigned — nobody is on this. Recording only, per Prime Directive #10.

Evidence

loadMetaFromDb's object branch (packages/metadata-protocol/src/protocol.ts, ~line 8958 on current main) registers each hydrated object row with:

this.engine.registry.registerObject(
    { ...(data as Record<string, unknown>), _provenance: 'org' } as any,
    record.packageId || 'sys_metadata',
);

But engine.find('sys_metadata', ...) returns rows keyed by the object's snake_case field names — package_id, not packageId:

  • the sys_metadata object declares package_id (packages/metadata-core/src/objects/sys-metadata.object.ts);
  • SysMetadataRepository writes parentRowData.package_id = ... (sys-metadata-repository.ts ~386-388) and maps row.package_id → packageId explicitly when it wants camelCase (~784);
  • getMetaItems in the same file reads the same query's rows as r.package_id (~2588, ~2606).

So record.packageId is always undefined and the || 'sys_metadata' fallback always wins: every object overlay row — including rows genuinely bound to a package (package_id = 'app.<slug>' etc.) — registers into the SchemaRegistry under the 'sys_metadata' sentinel sourcePackage at boot, silently dropping its package binding.

Why it matters

The cloud#970 fix comment right above this line documents the intent: pass the row's real package id but stamp _provenance: 'org' so the tenant-authored row is not misread as code-shipped. Half of that intent is dead: the provenance stamp works, the package binding never arrives. Consequences of registering under the sentinel instead of the real package id include the sidebar package filter / provenance classification not seeing the boot-hydrated object as belonging to its package (the same concern the read-side hydration explicitly handles by surfacing record.package_id, ~2596-2609), and registry.getObject-side package bookkeeping diverging between "created this session" (write path, real id) and "restarted" (boot path, sentinel).

Suggested fix

Read (record as { package_id?: string | null }).package_id || 'sys_metadata' — matching every other consumer of this query's rows. Needs a pin test (boot-hydrate an object row with package_id set; assert the registry records the real package binding, and that cloud#970's _provenance: 'org' + editability still hold). Check registerObject's package bookkeeping for whether the sentinel-vs-real-id switch has any other observable effects before landing (i.e. confirm this does not resurrect the cloud#970 not_overridable trap — the _provenance: 'org' stamp is what guards it now).

Not fixed in #4635 because it is the object branch (out of that issue's scope) and changes boot-time registry state for object rows — it deserves its own pin test and review.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions