---
id: 10292
title: 'P1: Content Provenance Tracking — authoredBy edges + 8-tier trust taxonomy on Memory Core'
state: CLOSED
labels:
  - enhancement
  - ai
  - architecture
assignees:
  - neo-gpt
createdAt: '2026-04-24T11:13:08Z'
updatedAt: '2026-06-07T17:21:03Z'
githubUrl: 'https://github.com/neomjs/neo/issues/10292'
author: neo-opus-ada
commentsCount: 5
parentIssue: 10291
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy: []
blocking: []
closedAt: '2026-05-26T01:05:05Z'
---
# P1: Content Provenance Tracking — authoredBy edges + 8-tier trust taxonomy on Memory Core

## Context

Sub-ticket of Epic #10291 — Organism Self-Defense substrate for cloud-phase `#9999` deployment. First blocker primitive (P1 per Discussion #10289); foundation layer all other primitives depend on.

Ideation source: Discussion #10289 — §1 Content Provenance Tracking. Cloud-phase blocker sequencing per #10289 OQ 10: P1 ships before P6a/P6b and P2.

## The Problem

Every piece of content an agent consumes currently carries no explicit provenance label. Memory Core queries return content without distinguishing `AGENTS.md` system mandate from peer-trusted-agent A2A from external-contributor ticket body. The agent treats all retrieved content with equal authority, which is incorrect once external agents enter the substrate (cloud-phase).



### 2026 Industry-Standard Alignment

Mitigates **OWASP ASI06 Memory & Context Poisoning** per the 2026 OWASP Top 10 for Agentic Applications. Implements the "Architecting for Memory Integrity" principle — authoritative author-provenance tracking at the ingestion boundary prevents retroactive memory-poisoning attacks where malicious content enters Memory Core without trust-tier attribution. Write-time provenance stamping is the defense; query-time tier filtering is the query-path consumer.

## The Architectural Reality

- `ai/mcp/server/memory-core/services/GraphService.mjs` — node schema + edge creation
- `ai/mcp/server/memory-core/services/MemoryService.mjs` + `SessionService.mjs` — memory/summary ingestion write paths
- `ai/mcp/server/memory-core/services/MailboxService.mjs` — A2A message ingestion
- `ai/mcp/server/memory-core/managers/StorageRouter.mjs` — query-path enforcement for tier filtering
- ChromaDB metadata schema — vector embeddings need matching provenance metadata for semantic-search tier filtering

## The Fix

**1. 8-tier trust taxonomy** (per Discussion #10289 §1):
- `system` (AGENTS.md / AGENTS_STARTUP.md)
- `repo-trusted` (skill files)
- `owner` (session owner input)
- `self` (current session prior thoughts)
- `peer-trusted` (other `@neo-*` agents via A2A)
- `internal-authored` (ticket/PR from swarm-internal agent)
- `external` (ticket/PR/comment from external contributor)
- `unclassified` (unknown authoring agent — defaults to external-tier)

**2. `authoredBy` edges on every Memory Core node** at write time:
- MEMORY nodes get `AUTHORED_BY → AgentIdentity` edge stamped from `RequestContextService.getAgentIdentityNodeId()`
- SESSION summary nodes carry the session owner's identity
- MESSAGE nodes already carry `SENT_BY` (per `#10139` mailbox work) — reused as provenance signal

**3. `trustTier` field on AgentIdentity nodes** — enum value from the 8-tier taxonomy. System agents / repo-trusted sources get highest tier; unclassified-by-default on identity creation.

**4. Query-path tier filtering**:
- `query_raw_memories`, `ask_knowledge_base`, `query_summaries` gain optional `minTrustTier` parameter
- `get_context_frontier` weights results by trust tier (Retrospective daemon already uses edge weights)
- Default behavior: tier info available in results but not filtered — callers opt-in to filtering

## Acceptance Criteria

- [ ] `AgentIdentity` nodes gain `trustTier` property (enum: the 8 tiers above).
- [ ] Memory Core write paths (memory, summary, mailbox, graph upsert) stamp `AUTHORED_BY` edges from current RequestContextService identity.
- [ ] Query tools accept optional `minTrustTier` parameter; when omitted, return all tiers with tier info in results.
- [ ] Playwright test coverage: write as each tier, query with minTrustTier filter, assert correct subset returned.
- [ ] Migration strategy documented for existing Memory Core content (Out-of-Scope below confirms forward-looking only, but document the decision).
- [ ] Downstream consumers (`get_context_frontier`, Retrospective daemon) updated to weight results by trust tier.

## Out of Scope

- **Retroactive provenance assignment** to existing Memory Core content (per Epic #10291 Out of Scope) — forward-looking only.
- **Cryptographic signing of provenance** — this ticket establishes structural tier labels; cryptographic guarantees are a separate concern (OQ 1 in Discussion #10289).
- **Cross-tenant provenance** (multi-tenant-aware tier computation) — handled by the `#10016` multi-tenant sub-epic; this ticket assumes single-tenant substrate per write.

## Avoided Traps

- **Inventing a new property name for provenance** — rejected. `authoredBy` edge + `trustTier` on AgentIdentity reuses existing graph vocabulary from `#10144`. No new substrate.
- **Filtering by default in query paths** — rejected. Would break existing consumers that expect all content. Opt-in filter via `minTrustTier`.
- **Storing tier on every node directly** — rejected as denormalized. Tier lives on AgentIdentity; nodes carry `AUTHORED_BY` edge; queries traverse.

## Related

- Parent Epic: #10291
- Discussion: #10289 §1 Content Provenance Tracking
- Identity substrate: `#10144` (AgentIdentity node type), `#10145` (OAuth2 MCP auth), `#10146` (cross-tenant permission edges)
- Multi-tenant sub-epic: `#10016`

Origin Session ID: `b02bd06c-a2cb-4aff-8af1-c4f2643c91be`

Retrieval Hint: `"content provenance tracking trust tier authoredBy edge memory core 8-tier taxonomy OWASP ASI06 memory integrity write-time ingestion"`

## Timeline

- 2026-04-24T11:13:09Z @neo-opus-ada added the `enhancement` label
- 2026-04-24T11:13:09Z @neo-opus-ada added the `ai` label
- 2026-04-24T11:13:09Z @neo-opus-ada added the `architecture` label
- 2026-04-24T11:15:11Z @neo-opus-ada added parent issue #10291
- 2026-05-25T06:01:17Z @neo-gpt cross-referenced by #10291
### @neo-gpt - 2026-05-25T06:01:46Z

## Ticket Intake - accepted for first implementation slice

Live V-B-A on 2026-05-25:
- Parent epic #10291 now has GPT epic-review: https://github.com/neomjs/neo/issues/10291#issuecomment-4531930761
- Current source has AgentIdentity roots, RequestContextService identity binding, Mailbox `SENT_BY`, and KB `originAgentIdentity` tenant stamping.
- Current source does **not** have executable general `AUTHORED_BY` Memory Core edges or an AgentIdentity `trustTier` taxonomy; `rg AUTHORED_BY|authoredBy|trustTier` only finds docs/comments for the Memory Core path.
- #10292 is therefore still a live cloud-phase blocker, not already resolved.

### Classification

`valid-as-written`, but too broad for a single PR. I am taking the first narrow slice under #10292 and will use partial-PR close-target discipline (`Refs #10292`, not `Resolves #10292`) until all ACs are complete.

### Slice 1 scope

Forward-only write-side provenance foundation:
- add stable AgentIdentity trust-tier taxonomy fields to the seeded identity roots;
- stamp `AUTHORED_BY` graph edges for newly written Memory Core artifacts where current RequestContextService identity is available;
- preserve existing single-tenant / unresolved-identity fallthrough;
- add unit coverage for edge stamping and fallback.

### Contract Ledger - slice 1

| Surface | Current reality | Slice-1 change | Consumers | Verification |
|---|---|---|---|---|
| AgentIdentity node properties | capability metadata exists, no trust taxonomy | add stable `trustTier` values to seeded identities | Graph traversal, future query filters | identity-root/unit assertions |
| MemoryService.addMemory graph node | stores scalar `agentIdentity` / `userId`, no provenance edge | add `AUTHORED_BY` edge when identity resolves | Memory Core graph, future provenance filtering | unit test with request context |
| Session summary graph node | summary node links to frontier only | add `AUTHORED_BY` edge when summary owner identity resolves | session graph consumers, frontier weighting follow-up | unit test / focused existing summary coverage if feasible |
| Mailbox messages | already use `SENT_BY` as authorship signal | no duplicate `AUTHORED_BY` in slice 1 | mailbox consumers | existing mailbox tests remain authoritative |

### Guardrails

- Current-path reconciliation: use `ai/services/memory-core/*` and `ai/mcp/server/shared/services/*`, not stale issue-body paths.
- Most-restrictive-source policy from the 2026-04-28 #10291 comment is accepted as a follow-on requirement: derived/summarized content must not launder lower-trust source material into a higher trust tier. If it does not fit slice 1 cleanly, I will file or document the residual before PR open.

lane-state: in-progress (#10292 slice 1, parallel to Claude #11791).


- 2026-05-25T06:02:13Z @neo-gpt assigned to @neo-gpt
- 2026-05-25T06:12:32Z @neo-opus-ada cross-referenced by PR #11952
- 2026-05-25T06:17:40Z @neo-gpt cross-referenced by PR #11953
- 2026-05-25T06:51:43Z @tobiu referenced in commit `9385e62` - "feat(memory-core): stamp raw-memory provenance (#10292) (#11953)

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
### @neo-gpt - 2026-05-25T14:13:38Z

## V-B-A refresh — 2026-05-25T14:14Z

Re-checked #10292 after PR #11953 merged.

### Verified delivered slice

- PR #11953 is merged: https://github.com/neomjs/neo/pull/11953
- `origin/dev` contains `9385e62e1 feat(memory-core): stamp raw-memory provenance (#10292) (#11953)`.
- Current source exposes the trust taxonomy in `ai/graph/identityRoots.mjs`:
  - `TRUST_TIERS`
  - `TRUST_TIER_ORDER`
  - seeded `trustTier` values on AgentIdentity roots.
- `MemoryService.addMemory()` now writes canonical `agentIdentity` metadata and emits `AGENT_MEMORY -AUTHORED_BY-> AgentIdentity` when `RequestContextService` resolves a real identity.
- Focused test coverage exists in `test/playwright/unit/ai/services/memory-core/MemoryService.Schema.spec.mjs` for the taxonomy, `AUTHORED_BY` edge, and unresolved-identity fallthrough.

### Remaining #10292 AC surface

Still open in current source:

- `SummaryService.mjs` has request-context user handling, but no summary-node `AUTHORED_BY` stamping yet.
- `query_raw_memories` / `query_summaries` tool paths do not expose `minTrustTier`.
- `get_context_frontier` does not yet weight results by trust tier.
- Migration strategy / forward-only decision is documented in PR #11953 prose, but not yet as durable operator-facing docs for the full #10292 rollout.
- The parent #10291 most-restrictive-source policy is still a design constraint for derived/summarized content: summaries must not launder lower-trust source material into the summarizing agent's higher trust tier.

### Routing recommendation

Keep #10292 open. Treat PR #11953 as **slice 1 complete**, not closeout.

Next highest-ROI slice: **summary provenance + no-laundering policy** before query filtering. Reason: query filtering and frontier weighting need summaries to carry trustworthy authorship/source-tier semantics first; otherwise summary retrieval can become the bypass path for lower-trust source content.

Suggested next PR close-target discipline: `Refs #10292`, not `Resolves #10292`, until all remaining ACs above are covered.

lane-state: next-lane candidate (#10292 slice 2 — SummaryService provenance + most-restrictive-source policy)


- 2026-05-25T14:34:04Z @neo-gpt cross-referenced by PR #11979
- 2026-05-25T14:42:48Z @neo-gpt cross-referenced by PR #11980
- 2026-05-25T15:45:23Z @neo-gpt referenced in commit `bb8c336` - "fix(memory-core): move summary provenance helper into class (#10292)"
- 2026-05-25T15:47:25Z @neo-gpt referenced in commit `73831cd` - "fix(memory-core): move raw trust helpers into class (#10292)"
- 2026-05-25T16:00:44Z @neo-gpt referenced in commit `460950f` - "fix(memory-core): move summary metadata helper into class (#10292)"
- 2026-05-25T16:16:33Z @tobiu referenced in commit `a0d2fe7` - "feat(memory-core): stamp summary provenance (#10292) (#11979)

* feat(memory-core): stamp summary provenance (#10292)

* fix(memory-core): move summary provenance helper into class (#10292)

* fix(memory-core): move summary metadata helper into class (#10292)

---------

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-05-25T16:18:26Z @tobiu referenced in commit `0eb3c1c` - "feat(memory-core): filter raw memories by trust tier (#10292) (#11980)

* feat(memory-core): filter raw memories by trust tier (#10292)

* fix(memory-core): move raw trust helpers into class (#10292)

---------

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-05-25T22:38:49Z @neo-gpt cross-referenced by PR #12000
- 2026-05-25T22:56:41Z @tobiu referenced in commit `ea19428` - "feat(memory-core): filter summary queries by trust tier (#10292) (#12000)

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
### @neo-gpt - 2026-05-25T22:58:12Z

## V-B-A refresh - PR #12000 merged

Re-checked #10292 after PR #12000 merged.

### Verified delivered slice

- PR #12000 is merged: https://github.com/neomjs/neo/pull/12000
- Merge commit: `ea194288917f7cd4da3c3a7df3c2e5793dbaed0f`
- Delivered surface: `query_summaries({minTrustTier})` now has the same trust-tier filter shape as the already-merged raw-memory query path.
- `openapi.yaml` exposes additive summary provenance fields and optional `minTrustTier` on `QuerySummariesRequest`.
- Focused coverage landed in `SummaryService.TenantIsolation.spec.mjs`; PR CI was green and cross-family approved before merge.

### Remaining #10292 AC surface

Keep #10292 open. Remaining visible scope:

- `get_context_frontier` trust-tier weighting / result ranking.
- Durable forward-only migration / existing-content decision docs for the full #10292 rollout.
- Final AC reconciliation after the frontier weighting slice lands.

### Routing recommendation

Next highest-ROI slice: `get_context_frontier` trust-tier weighting, because raw memories and summaries now both carry/filter provenance but the frontier composition path can still ignore trust tier during ranking.

Close-target discipline remains `Refs #10292`, not `Resolves #10292`, until the remaining AC surface is covered.


- 2026-05-25T23:18:05Z @neo-gpt cross-referenced by PR #12002
- 2026-05-25T23:43:02Z @tobiu referenced in commit `b197501` - "feat(memory-core): weight frontier contexts by trust tier (#10292) (#12002)

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
### @neo-gpt - 2026-05-26T00:52:25Z

## V-B-A refresh - after PR #12002 merge

Re-checked #10292 against live `origin/dev` after PR #12002 merged.

### Verified delivered surface

- PR #12002 is merged: https://github.com/neomjs/neo/pull/12002
- Merge commit: `23084f46789dd6e6bfcb2a0f9fea61efa73fdf93`
- `MemoryService.getContextFrontier()` now projects summary `trustTier`, `trustWeight`, and `weightedScore`, and ranks hydrated semantic contexts by trust-adjusted score.
- `origin/dev` contains the earlier #10292 slices for:
  - `TRUST_TIERS` / `TRUST_TIER_ORDER` and seeded `AgentIdentity.properties.trustTier`
  - raw-memory `agentIdentity` metadata + `AUTHORED_BY` edge stamping
  - summary `sourceTrustTier` / `provenancePolicy: most-restrictive-source` metadata + summary `AUTHORED_BY` edge stamping
  - `query_raw_memories({minTrustTier})` and `query_summaries({minTrustTier})` filtering and provenance fields
  - frontier trust-tier weighting

### Remaining reconciliation before close

Keep #10292 open for now. Two ticket-body reconciliation points remain live:

1. **Knowledge Base `ask_knowledge_base({minTrustTier})` is not implemented on `origin/dev`.** Live grep shows `minTrustTier` only in Memory Core raw/summaries paths; KB `ask_knowledge_base` has no trust-tier input. If KB provenance is still part of #10292, this is the remaining implementation lane. If KB provenance belongs to a separate KB-source trust model, the #10292 body should be narrowed explicitly before close.
2. **Migration strategy is partially documented, but not as a #10292 closeout note.** `learn/agentos/tooling/MultiTenantMigrationGuide.md` documents no back-fill / lazy-tag-on-read for tenant-era data, but #10292 still needs final closeout language that existing pre-provenance Memory Core content defaults to `unclassified` rather than receiving retroactive authorship.

### Routing recommendation

Do **not** close #10292 yet. The next concrete decision is whether the KB `ask_knowledge_base` trust-tier bullet remains in-scope. If yes, implement that as the final code slice. If no, post the explicit out-of-scope/narrowing rationale and then close with the forward-only migration note.

lane-state: next-lane candidate (#10292 final reconciliation; no new ticket filed).

### @neo-gpt - 2026-05-26T01:05:05Z

## Final reconciliation - closing as completed

Live V-B-A after the #12002 merge shows the Memory Core #10292 contract is complete on `origin/dev`:

- `AgentIdentity.properties.trustTier` exists via `TRUST_TIERS` / `TRUST_TIER_ORDER`.
- Raw memories stamp request-bound `agentIdentity` metadata and `AUTHORED_BY` graph edges.
- Session summaries stamp `sourceTrustTier`, `sourceAgentIdentities`, `provenancePolicy: most-restrictive-source`, and summary `AUTHORED_BY` edges.
- `query_raw_memories({minTrustTier})` and `query_summaries({minTrustTier})` validate/filter trust tiers and return provenance fields.
- `get_context_frontier` now projects and ranks by `trustTier`, `trustWeight`, and `weightedScore` after PR #12002.
- Existing/pre-provenance content is forward-only: no retroactive authorship assignment; unresolved or pre-provenance rows resolve to `unclassified`. This is aligned with the no-back-fill migration posture documented in `learn/agentos/tooling/MultiTenantMigrationGuide.md`.

The original body also named `ask_knowledge_base({minTrustTier})`. I am treating that as stale/wrong-surface wording for this ticket, not a remaining #10292 blocker: the Knowledge Base substrate uses tenant/repo/path provenance (`tenantId`, `repoSlug`, `rootKind`, `sourcePath`, curated `neo-shared` corpus), not Memory Core `AUTHORED_BY` / AgentIdentity trust-tier provenance. Adding `minTrustTier` to KB here would conflate two provenance models. If KB source trust needs a filter later, it should be shaped against KB source identity, not Memory Core authorship.

No new ticket filed. Closing #10292 as completed for the Memory Core content-provenance scope.

- 2026-05-26T01:05:05Z @neo-gpt closed this issue
- 2026-05-26T04:04:57Z @neo-gpt cross-referenced by #10293

