Building a Write-Side Custody gate in Go
AI memory systems spend most of their design budget on retrieval. Which vector database? How should we ch...
For further actions, you may consider blocking this person and/or reporting abuse
The separate sourceType parameter is the strongest choice here. One failure I’d test next is provenance loss before the gate: a redirect, proxy, or retrieved snippet copied into a new object can make vendor marketing arrive looking “internal.” I would have the classifier return both the source type and a replayable evidence handle—URL, content hash, and collector—and make the gate deny when that evidence cannot be reproduced. Then the ledger records what the custody layer actually observed, not only the verdict.
Yes, that's a good failure case. Moving
sourceTypeoutsideProposedWriteprevents the writer from self-classifying, but it doesn't prove that provenance survived the path to the classifier. If vendor content gets copied through an internal proxy and arrives stripped of origin,SourceInternalcould still be confidently wrong.I like the evidence-handle idea, although I'd probably distinguish replayable from verifiable because some sources won't remain reproducible forever. Origin URI, content digest, collector identity, retrieval time, redirects/transformations, and perhaps the raw retrieval receipt could give custody something independently inspectable rather than another label to trust.
That suggests the stronger invariant is not merely "the agent doesn't supply
sourceType." It's "source classification must be derived from witnessed provenance."And agreed on the ledger: it should preserve what custody actually observed, including the evidence supporting the classification, rather than retroactively recording what we hoped happened upstream.
Witnessed provenanceis the better invariant. If an intermediate transformation cannot produce its own custody receipt,SourceInternalshould not survive that hop; the result should fall back to unknown. I also agree that replayable and verifiable are different—the source may disappear, but the hash, collector, redirect chain, and timestamp should still let someone check what the classifier saw at the time.Yes, I like the downgrade-to-unknown rule a lot. Provenance shouldn't be inherited merely because an upstream artifact once had it. If a transformation can't preserve or produce evidence for the classification, the downstream artifact shouldn't get to carry that classification forward by assumption.
That also gives
unknownan important role: it isn't necessarily a failure state. It's the honest state when the custody chain can no longer support the stronger claim.And your replayable/verifiable distinction is useful. A receipt may let us reconstruct exactly what the classifier observed at the time even when the original source is no longer available for independent re-evaluation. Those are different guarantees, and the receipt shouldn't imply the stronger one when it can only provide the former.
This is a really interesting way to frame the problem. I especially like the distinction between storage and admission: once questionable information has entered durable memory, retrieval is already too late to fix the trust decision.
The part about the agent not being allowed to assert facts about the runtime also resonates strongly with how I think about AI systems: provenance shouldn't be something the model gets to declare about itself. The boundary has to come from something that can independently observe and enforce it.
I'm working through a very similar problem from the other side, around RAG pipelines, AI governance, and adversarial verification — particularly how to prove that a security invariant is actually enforced rather than just represented in prompts, rules, or tests.
I'll definitely take a closer look at the Go implementation. If you're interested in the other side of this problem, feel free to check out my work as well. 🔐
Exactly. "Represented as a rule" and "independently enforced as an invariant" are very different claims. That's part of why I wanted the example to be executable rather than leaving Write-Side Custody as an architectural diagram. I'll take a look at what you're doing on the adversarial-verification side too. Thanks!
The right default is capability scoping: give an agent the narrowest write permission that can complete the current task, then require explicit escalation for broader impact. That is more reliable than hoping a prompt remains cautious forever.
The ledger also needs the identity of the policy that produced the verdict, not only the reason. Store an immutable policy version or hash plus the evaluated source classification; replaying an old write against the current policy answers a different question. A useful negative control is the same proposed write under two policy versions producing distinguishable ledger records even when both verdicts are DENY.
Agreed.
reasonexplains the verdict but doesn't establish which governance state produced it. I'd want the durable evidence to include the policy identity/version or digest, the evaluated source classification, and ideally how that policy version was obtained.Your negative control is particularly good. If policy v7 and v8 both produce
DENY, storing only the verdict and reason can make the two events look equivalent even though they were governed by different evidence. The ledger needs to preserve that distinction.And yes, replay needs two modes that shouldn't be confused: "reconstruct the decision under the policy that governed then" versus "evaluate the same proposed write under the policy that governs now." Those answer different questions. The first is forensic; the second is re-evaluation.
Ken, custody is the right place to put that boundary, and the invariant you arrived at with joinwell52 is stronger than the post itself: source classification has to be derived from witnessed provenance rather than asserted. What I would push on is the tense. Everything in the gate is witnessed at admission, and nothing re-witnesses afterwards.
A vendor certificate expires. A person leaves the role that made their write a policy. A policy version supersedes the one that produced an ALLOW. In each case the ledger entry stays exactly as true as it was, and the record it admitted stays exactly as authoritative as it was, because authority was checked once and never again. Custody that runs only at t0 is a bearer token with no expiry.
That gap is not yours alone, and I have a count for it. Six practitioners independently asked me for a required field naming who may revoke a promoted record, and two of those six said they do not model authority at all: they record who closed a decision, not whether that person was allowed to. So the rung nobody builds is the one going down.
The smaller point is the ledger entry itself. It records a verdict on one write and carries no pointer to what that write replaces. Supersession then has to be inferred later by comparing records against each other, which is the same postponement your post argues against on the admission side.
On the language question I have nothing useful. The invariant looks orthogonal to the runtime to me, but I have not built it in Rust and would rather say that than guess.
Yes, I think the tense is exactly where the architecture needs more precision. Admission can establish that a write was authorized and admissible at t0; it cannot establish that the authority supporting that write remains valid indefinitely.
I wouldn't necessarily make the write-side gate itself responsible for continuously re-witnessing every admitted record, but I do think custody has to preserve enough about the authority and dependencies behind the admission for later revalidation or revocation to be possible. Otherwise, as you say, we've converted “authorized when admitted” into “authorized forever.”
Your revocation-field observation is especially interesting. I'm thinking admission needs to capture not only who/what authorized an assertion, but the authority's lifecycle semantics: what can supersede it, what can revoke it, what dependency would make it stale, and perhaps whether it requires periodic or event-driven revalidation. Different authorities may have very different rules there.
And I agree on the supersession pointer. If the system already knows at admission that this write supersedes, corrects, or invalidates another record, postponing that relationship until retrieval throws away information we had at the strongest possible moment. The relationship should be admitted and custodied with the write rather than rediscovered later.
That connects to another discussion I've been having here: some relationships really won't be known until read time, but those should remain explicitly derived relationships. A witnessed supersession established at admission and a supersession inferred six months later by retrieval shouldn't become epistemically identical just because both eventually produce an edge called
supersedes.And agreed on the language point. I'm becoming more and more convinced the useful experiment isn't whether Go/Rust/Python changes the invariant, but whether the invariant survives implementation cleanly across runtimes.
The key issue is separating “can write” from “is authorized to write here.” Agents need scoped capabilities, not just approval prompts. Otherwise the guardrail is mostly trust.
Exactly. An approval prompt answers something like “may this action proceed?” but that isn't the same as establishing what authority the agent possesses in the first place.
I think the stronger model is scoped capability: this actor may perform this class of write, against this resource or namespace, under these constraints. The custody boundary then evaluates the proposed write against that authority rather than treating possession of a write mechanism as permission to use it everywhere.
That distinction becomes especially important as agents gain broader tool access. “Can invoke the write tool” should never silently collapse into “is authorized to write this state.”