LearnNewsExamplesServices
Frontmatter
id12473
titleteam memorySharing excludes the untagged summary commons → empty team summary reads
stateClosed
labels
bugairegression
assignees[]
createdAtJun 4, 2026, 4:43 AM
updatedAtJun 4, 2026, 10:17 AM
githubUrlhttps://github.com/neomjs/neo/issues/12473
authorneo-opus-grace
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 4, 2026, 10:17 AM

team memorySharing excludes the untagged summary commons → empty team summary reads

neo-opus-grace
neo-opus-grace commented on Jun 4, 2026, 4:43 AM

Context

query_summaries / list_summaries returned empty under the team memorySharing policy — the intended repo default per the cloud-deployment access work (operator: "OUR own and the repo default should be team based access"). Memory-mining over session summaries was 100% non-functional on the team default.

Surfaced while investigating #12450 (the "query_summaries empty" symptom ticket): the operator's redirect ("explore if access related → team vs private") isolated this as a distinct root cause from #12450's documented Chroma vector-corruption (its Layers 1–2). This is the access-policy layer (Layer 3).

Root cause (V-B-A'd)

Session summaries carry no userId metadata (untagged legacy-commons — the summary writer does not tag userId, unlike raw-memory writes). But the team read applied where:{userId:'shared'}, which matched none of the untagged records → empty. Only legacy (no DB-where + JS post-filter passing untagged) returned them. With team as the intended default, every summary query read empty. query_raw_memories is unaffected (raw writes DO tag userId).

The Fix (delivered in PR #12470)

Make team additive like legacy — caller-owned + 'shared' + untagged commons — via the existing over-fetch + JS post-filter path; drop the restrictive {userId:'shared'} DB-where. private stays strict (own-only). Applied to querySummaries + listSummaries in SummaryService.mjs. The JS post-filter is mandatory for additive policies (else other tenants' private records leak) — kept consistent via an additivePolicy flag.

Contract Ledger

Target Surface Source of Authority Behavior Fallback Evidence
query_summaries / list_summaries (memorySharing:'team') SummaryService.mjs querySummaries/listSummaries additive: own + 'shared' + untagged commons; no restrictive DB-where JS post-filter excludes other-tenant private SummaryService.TenantIsolation.spec.mjs:363 (16/16)
memorySharing:'private' same strict own-only {userId} DB-where private contract test

Acceptance Criteria

  • team summary reads return caller-owned + 'shared' + untagged commons (not the empty {userId:'shared'} filter). (PR #12470)
  • Other-tenant private summaries excluded from team/legacy reads via the JS post-filter. (codified test, incl. the cross-tenant assertion)
  • private stays strict own-only. (unchanged + tested)
  • (post-merge) After Memory Core restart, query_summaries(memorySharing:'team') returns non-empty for the commons.

Scope

Access-policy only. NOT the Chroma HNSW corruption / injectQueryReRanker observability / healthcheck-canary work — those remain on #12450 (Layers 1–2).

Refs #12450 (symptom ticket; this is its access-policy Layer 3).

Origin Session ID: 3ecb40bf-bfef-40b1-8693-a8aae5afa1b7 Authored by Claude Opus 4.8 (Claude Code), /lead-role.

tobiu referenced in commit 3628ce1 - "fix(memory-core): team summary reads include the untagged commons (#12473) (#12470) on Jun 4, 2026, 10:17 AM
tobiu closed this issue on Jun 4, 2026, 10:17 AM