Skip to content

Memory track: right-to-be-forgotten workflow for scoped memory - #40

Open
harinikshan wants to merge 4 commits into
theschoolofai:mainfrom
harinikshan:feature/memory-forgetting-workflow
Open

harinikshan wants to merge 4 commits into
theschoolofai:mainfrom
harinikshan:feature/memory-forgetting-workflow

Conversation

@harinikshan

Copy link
Copy Markdown

Summary

  • Adds a forget operation to MemoryStore: a scope- and role-checked tombstone (status='forgotten') with an audited actor/reason, exposed via S13Runtime.forget_fact and POST /v1/agent/memory/forget.
  • recall() now permanently excludes forgotten records, even under include_history=True — distinct from ordinary supersede/expiry, which remain visible in history.
  • Adds an adversarial test proving a same-tenant, different-user forget attempt is denied; the branch history keeps the failing-before / passing-after commits separate and reproducible.
  • Full write-up (capability, exact requests, ordered trace, evidence/provenance, the adversarial attack + fix, and reproduction commands), plus Part 1 floor reproduction and an honestly-reported recall scope limitation, is in the new README section: "Session 13 submission: memory forgetting workflow (right-to-be-forgotten)".

Test plan

  • uv run ruff check . — clean
  • uv run pytest -q — 50 passed (44 baseline + 6 new)
  • cd ../S13Proof && uv sync && uv run pytest -q — 3 passed
  • uv run python run_a2a_proof.py (in S13Proof) — official A2A wait/resume proof still completes
  • Adversarial test captured failing (PermissionDenied not raised) before the fix, passing after

🤖 Generated with Claude Code

Hari and others added 4 commits September 15, 2026 16:07
Adds MemoryStore.forget: a scope- and role-checked tombstone that marks a
record 'forgotten', writes an audited reason/actor, and is idempotent on
retry. recall() now permanently excludes forgotten records even under
include_history=True, distinct from ordinary supersede/expiry. Exposes it
through S13Runtime.forget_fact and POST /v1/agent/memory/forget.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_assert_forget_allowed only checks tenant_id for non-operator principals, so
any agent/user in the same tenant can currently forget another user's
private memory. This test captures that exploit and is expected to fail
until the next commit tightens the check. Confirmed failing locally:

    FAILED test_forget_cannot_be_used_to_erase_another_users_memory_in_the_same_tenant
    AssertionError: PermissionDenied not raised

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_assert_forget_allowed compared only tenant_id for agent/user principals,
letting any caller inside a tenant forget another user's private memory.
Now a non-operator principal must match the record's full MemoryScope
(tenant, project, user, agent, run) exactly. Operators/system are still
tenant-bound but need no narrower match.

The adversarial test added in the previous commit now passes:

    test_forget_cannot_be_used_to_erase_another_users_memory_in_the_same_tenant PASSED

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Documents Part 1 (baseline reproduction across four cases plus the honest
recall-scope limitation the trace exposed), and Part 2/3 (the
right-to-be-forgotten capability, its exact API requests, ordered proof
trace, evidence/provenance, and the adversarial cross-user forget attack
with its before/after test output).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant