feat(vault): deletion deny-list store + Mark/Filter RPCs (#73)#75
Draft
jh-lee-cryptolab wants to merge 1 commit into
Draft
feat(vault): deletion deny-list store + Mark/Filter RPCs (#73)#75jh-lee-cryptolab wants to merge 1 commit into
jh-lee-cryptolab wants to merge 1 commit into
Conversation
Logical-delete SSOT for organizational memory. enVector has no per-vector delete (only delete_index), so deletions are recorded as a per-index deny-list of stable item_ids. Vault stores the deny-list; clients (rune-mcp) consult it and filter out deleted hits. Vault never talks to enVector and never filters scores itself. - denylist.Store: file-backed, debounce-persisted, per-index set + monotonic version. MarkDeleted unions ids (idempotent, bumps version); FilterDeleted returns the deleted subset of candidates at O(candidates), independent of total deny-list size. - gRPC: MarkDeleted (write, scope mark_deleted) and FilterDeleted (read, scope filter_deleted, granted to admin+member for the recall path). item_ids are uint64 to match enVector's stable item_id. - Wiring: TokensConfig.deny_list_file (optional, defaults to deny_list.yml beside tokens_file); loaded and shut down in the daemon. - Register both RPCs in the validation interceptor's method set + token-safety switch, with a ServiceDesc-derived test guarding future RPCs from omission. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 tasks
Contributor
Author
Storage scaling noteThe deny-list is a single file-backed YAML (per-index sets of Confirmed sufficient up to ~100k entries with the single-file design — no embedded DB needed at this scale:
The only inefficiency is rewriting the whole file on each persist, but deletes are infrequent (low write QPS) and debounce absorbs bursts, so it is not felt in practice. Embedded DB (issue open question) is deferred — it only matters when writes are frequent AND volume reaches hundreds-of-thousands+. If that day comes, cheap next steps are per-index files ( |
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.
Context
Memories cannot be hard-deleted: enVector v1.2.2 has no per-vector delete (only
delete_index). So we delete logically — Vault keeps a per-index deny-list of deleteditem_ids and serves it. Clients filter. Vault side of #73.TL;DR
Vault stores a per-index deny-list of deleted
item_ids; clients consult it and drop deleted hits.Summary
flowchart LR C[rune-mcp client] -- "MarkDeleted(ids)" --> V C -- "FilterDeleted(candidates)" --> V V[(Vault deny-list<br/>SSOT, per index)] -- "deleted subset" --> C V -. "never talks to" .-x E[enVector]denylist.Store— file-backed, debounce-persisted. Per index: a set ofitem_ids + a monotonicversion.MarkDeleted(write) — unions ids into the deny-list. Idempotent; bumpsversion.FilterDeleted(read) — returns the deleted subset of the given candidates. Cost is O(candidates), independent of total deny-list size.mark_deleted(admin only),filter_deleted(admin + member, because recall needs it).item_idisuint64— matches enVector's stable logical id (see Test plan for the stability check).tokens.deny_list_file, optional; defaults todeny_list.ymlnext totokens_file. No change needed for existing deployments.ServiceDesc-derived test so a future RPC cannot silently skip the check.Alternatives
(shard, row)— rejected. Physical position moves on compaction;item_idis the stable logical id.versionfield leaves room for a future sync RPC.Test plan
mise run checkgreen (gofmt + vet + race tests)mark_deleted), mark→filter round-trip, memberfilter_deletedallowedServiceDesc-derived completeness guard forvaultMethodsitem_idstability verified against es2-msa v1.2.2 —item_idis an auto-increment PK; merge updates onlyshard_id(index_shardmap.goupdateShardMapTable); no reindex/rebuild/counter-reset exists in the backend. The deny-list key is safe.