Skip to content

Commit 0af0854

Browse files
joslatclaude
andcommitted
release prep: v1.1.0 -- isolation policy, guaranteed MAF owner scoping, trust boundary, recall/extraction fixes
Bumps Directory.Build.props to 1.1.0 and finalizes the CHANGELOG entry covering the 5 merged PRs since 1.0.3: #105 (#100, isolation policy), #107 (#90, MemoryOwnerScopingAgent), #108 (#92 Phase 1, trust boundary for recalled memory), #109 (#87, RecallOptions wiring), #110 (#89, persist/extract from the complete turn). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 4c11fed commit 0af0854

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [1.1.0] - 2026-07-15
10+
11+
### Added
12+
13+
- **`IMemoryIsolationPolicy` — a library-wide strict multi-tenant isolation mode (#100).** A new central
14+
policy abstraction with three modes via `MemoryOptions.Isolation.Mode`: `SingleTenant` (default,
15+
today's exact backward-compatible behavior), `WarnOnUnscoped` (structured log when a tenant-facing call
16+
resolves unscoped), and `StrictMultiTenant` (throws `MemoryOwnerScopeRequiredException` before any
17+
Neo4j call when no owner scope is present, instead of silently falling back to global/shared). Wired
18+
into the primary recall/extraction/reasoning Core services and 6 MCP entry points
19+
(`memory_entities`/`memory_preferences`/`memory_conversations`/`memory_context`/`memory_invalidate`/
20+
`memory_supersede`). Several other MCP tools that accept a `userId` are not yet gated by this toggle —
21+
a disclosed, tracked follow-up, not silently dropped (see `docs/getting-started.md` and
22+
`docs/security/threat-model.md` TT-01/TT-02 for the exact coverage boundary).
23+
- **`MemoryOwnerScopingAgent` / `AIAgent.WithMemoryOwnerScoping(...)` — guaranteed owner scoping across
24+
the complete MAF invocation (#90).** Wrapping an agent with `.WithMemoryOwnerScoping(serviceProvider)`
25+
guarantees the owner scope spans passive recall, the model call, the full tool-calling loop, and
26+
automatic persistence as one unbroken async chain — closing a real gap where `Neo4jMemoryContextProvider`'s
27+
own pre-run hook could not, on its own, guarantee a value it set survived into tool calls that run after
28+
it returns (the hook suspends on real I/O, breaking `AsyncLocal` propagation). Replaces manually
29+
wrapping every `agent.RunAsync(...)` call in `ownerContext.BeginOwnerScope(userId)`. Also adds
30+
`AgentSessionMemoryExtensions.GetMemoryIdentity(...)` (single-source-of-truth session-identity reader)
31+
and `IWritableMemoryStoreContext.BeginStoreScope(...)` (mirrors the existing `BeginOwnerScope`).
32+
- **A minimal trust boundary for recalled memory rendered into MAF context (#92, Phase 1 of a larger
33+
issue).** Recalled entities/facts/preferences/reasoning-traces/GraphRAG content is no longer injected as
34+
a raw, unrestricted system message: each block is now delimited and angle-bracket-escaped
35+
(`<recalled_memory category="...">...</recalled_memory>`), and the default context prefix explicitly
36+
tells the model this content is untrusted reference data, not instructions to follow. This defeats
37+
boundary forgery specifically; it does not (yet) detect general instruction-like content or cover
38+
recalled conversation history — the full #92 issue (trust metadata, an admission policy, configurable
39+
message roles, instruction-like-content detection) remains open.
40+
41+
### Fixed
42+
43+
- **Native MAF recall ignored configured `RecallOptions` (#87).** `Neo4jMemoryContextProvider` built its
44+
`RecallRequest` without assigning `.Options`, so a customized `MinSimilarityScore`, per-section limit,
45+
or `BlendMode` had no effect on automatic recall even though it worked correctly for a direct
46+
`IMemoryService.RecallAsync` call. Configured retrieval tuning now reaches native recall; a configured
47+
`RecallOptions.Scope` is explicitly never allowed to override the invocation's authenticated owner.
48+
- **Automatic extraction only saw the assistant's response, never the user's request (#89).** A turn like
49+
"User: I prefer window seats. / Assistant: Got it." previously only ran extraction over "Got it." — a
50+
user-stated preference was invisible unless the assistant repeated it. Extraction now considers the
51+
complete turn. `Neo4jChatHistoryProvider` (which already persisted both request and response messages)
52+
gained full-provenance extraction from both at no new risk. `Neo4jMemoryContextProvider` deliberately
53+
does not start persisting request messages as new `:Message` nodes (there is no idempotency mechanism to
54+
avoid duplicating what a chat-history provider/store may already persist) — captured facts/preferences
55+
are correct, but their provenance link to the literal source message is best-effort in that path, not
56+
guaranteed; documented, not silently accepted.
57+
958
## [1.0.3] - 2026-07-14
1059

1160
### Fixed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
and never leaks into non-published projects. Per-package Description/PackageTags live in each
3333
.csproj. NuGet package IDs default to the (already de-Neo4j-renamed) project names. -->
3434
<PropertyGroup Condition="$(MSBuildProjectName.StartsWith('AgentMemory')) and !$(MSBuildProjectName.Contains('.Tests')) and !$(MSBuildProjectName.Contains('.Sample'))">
35-
<Version>1.0.3</Version>
35+
<Version>1.1.0</Version>
3636
<Authors>Jose Luis Latorre Millas</Authors>
3737
<Company>Jose Luis Latorre Millas</Company>
3838
<Product>AgentMemory for .NET</Product>

0 commit comments

Comments
 (0)