Files
fusion/packages/core
gsxdsm a048a619fc fix(core): resolve unbound project ids to a real partition or no filter
Six of the eight postgres-suite failures shared one root cause: writes
normalize project_id, reads did not. The fusion_assign_project_id trigger
(migration 0006) rewrites a blank project_id to the session's fusion.project_id
or '__legacy_unscoped__', but helpers reached as `layer.projectId ?? ""` then
filtered on the literal '' -- a value the database never stores. Every unbound
read missed rows it had just written.

AsyncDataLayer.projectId is optional by design (undefined = project-agnostic),
so `?? ""` is the bug: it turns "no scope" into a scope that matches nothing.

The resolution differs by what the rows are, and conflating them corrupts data:

- Data and analytics reads (usage events, agent runs, research runs) take
  projectScopeFor(): a bound id filters, an unbound one reads across projects.
  This matches the contract taskProjectScope already documents ("when undefined
  the scope filter is a no-op").
- __meta migration guards (project-identity stamps, agent-store markers) take
  projectPartitionId(): an unbound id resolves to the shared sentinel
  partition. projectScopeFor would be wrong here -- dropping the predicate lets
  an unbound getMetaValue return whichever project's marker it finds first, so
  on the shared cluster project A's "migration complete" marker would tell
  project B to skip a migration it never ran. upsertMetaValue already documented
  this: "the empty binding remains the explicit project-agnostic compatibility
  partition". Writing the sentinel explicitly also keeps the partition
  deterministic -- a blank write from a session carrying fusion.project_id would
  otherwise land in that project's stamp.

Names the sentinel (LEGACY_UNSCOPED_PROJECT_ID) instead of open-coding it, and
puts both helpers next to taskProjectScope so the convention has one home.

Fixes taskstore-remaining (24/24), project-identity (6/6), and
satellite-fusiondir-stores (16/16).

The remaining two failures are a different bug and are NOT addressed here: the
child tables research_run_events and experiment_session_records never declared
project_id in schema-as-code, though migration 0006 added the column and
rewrote their FKs to composite (project_id, parent_id). Drizzle therefore cannot
write the parent's partition, the trigger stamps '__legacy_unscoped__', and the
FK fails against a project-owned parent. That needs a schema-as-code change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 21:47:01 -07:00
..
2026-07-13 10:32:12 -07:00