feat: memory inspect — #6 Phase 3a (audit + tenant-scoped endpoint)#54
Merged
Conversation
Schema v4 adds memory_activity: every runtime-reported memory read/write with the adapter's verdict, keyed by installation/repo. record_memory_activity persists a batch; list_memory returns it newest-first narrowed to the caller's ApiScope — the durable basis for tenant-scoped memory inspect (Phase 3). Signed-off-by: Val Alexander <bunsthedev@gmail.com>
After validating the runtime's reported memory_used, the worker records every read/write to the durable audit — accepted, or rejected with the reason — so a tenant can later inspect what memory a familiar used on their repo. Row mapping is an extracted, unit-tested helper. Signed-off-by: Val Alexander <bunsthedev@gmail.com>
…dpoint (#6) Exposes recorded memory activity behind the #3 tenant boundary: token mode fails closed, a tenant sees only its own installation (optionally narrowed to repos), the service/open callers see all, and every read is audited — the same contract as /api/github/tasks. MemoryActivity gains Serialize for the JSON response; the route is registered in the server. Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds the “inspect” half of the memory governance contract by persisting an adapter-verdict audit trail for runtime-reported memory reads/writes and exposing it via a tenant-scoped API endpoint.
Changes:
- Persist per-task memory activity (reads + attempted writes) into a new
memory_activitytable (schema v4) and expose it viaStore::list_memory. - Record memory activity from the worker with
acceptedvsrejected:<reason>outcomes. - Add
GET /api/github/memorywith the same tenant-scoped auth boundary as/api/github/tasks, plus route tests.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/worker/src/memory.rs | Adds a unit test asserting audit rows include adapter verdicts. |
| crates/worker/src/lib.rs | Maps reported memory usage to audit rows and persists them during run_and_publish. |
| crates/webhook/src/routes.rs | Adds GET /api/github/memory endpoint + tenancy tests for scoping/fail-closed behavior. |
| crates/store/src/lib.rs | Bumps schema to v4, adds memory_activity storage/query APIs, migration, and tests. |
| crates/store/Cargo.toml | Adds serde dependency for MemoryActivity serialization. |
| crates/server/src/main.rs | Wires the new /api/github/memory route into the server router. |
| Cargo.lock | Locks the new serde dependency in the workspace. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+550
to
+557
| // Repository narrowing within the installation, when scoped. | ||
| let filtered = rows | ||
| .into_iter() | ||
| .filter(|r| match scope.as_ref().and_then(|s| s.repos.as_ref()) { | ||
| Some(repos) => repos.contains(&r.repo), | ||
| None => true, | ||
| }) | ||
| .collect(); |
Comment on lines
+715
to
+731
| conn.execute_batch( | ||
| r#" | ||
| CREATE TABLE memory_activity ( | ||
| id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
| at TEXT NOT NULL, | ||
| installation_id INTEGER NOT NULL, | ||
| repo TEXT NOT NULL, | ||
| task_id TEXT NOT NULL, | ||
| op TEXT NOT NULL, | ||
| target TEXT NOT NULL, | ||
| scope TEXT NOT NULL, | ||
| outcome TEXT NOT NULL | ||
| ); | ||
| CREATE INDEX memory_activity_scope | ||
| ON memory_activity(installation_id, repo); | ||
| "#, | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 3 of the memory governance contract (
docs/memory-contract.md), inspect half. Advances #6; does not close it — revoke is the deliberately-separated follow-up (see below).What this delivers
crates/store, schema v4): amemory_activitytable records every memory read/write the runtime reported, with the adapter's verdict (acceptedorrejected:<reason>), keyed by installation/repo.list_memoryreturns it newest-first, narrowed to the caller'sApiScope.GET /api/github/memory(crates/webhook+ server): tenant-scoped inspect behind the Add tenant-scoped task API authentication for CovenCave and hosted clients #3 auth boundary — token mode fails closed, a tenant sees only its own installation (optionally narrowed to repos), service/open callers see all, every read audited. Same contract as/api/github/tasks.This satisfies the "customers can inspect memory by installation and repository" half of the issue's acceptance criteria, and gives the security-relevant record of refused writes.
Why revoke is separated (not a shortcut)
Inspect is fully adapter-side. A meaningful revoke is not: the memory bytes live in coven-code, so revoke must prevent future use — a denial list the adapter carries in the
memory_policy(an additive brief field coven-code must honor) plusvalidate_memory_usedrefusing revoked reads. That's a bilateral contract change, so it belongs in its own PR (Phase 3b) coordinated with the coven-code side, alongsidedelete_on_uninstalland retention expiry. Deleting only the adapter's audit row would be a false revoke (memory still usable), so I deliberately did not ship that. Citation-on-status-comment is also deferred.Local gates:
cargo check --all-targets+cargo clippy --all-targets -- -D warnings+cargo test --all(192 passed, 0 failed).🤖 Generated with Claude Code