Only Institute / Knowledge

Follow your curiosity.

AI sends your question and public excerpts to PrimeSwarm.

Try agent memory, governance, or a project name.

All Publications
article

The Gate Is a Running Service Now — DGV v0.4.0

Verified identity, signed policies, fail-closed partitions, and signed revocation gossip — measured, not asserted

Grigori Korotkikh 2026-09-16 12 min
DGVEnforcement GateRevocationT0/T1A2ARelease
Only Institute — The Gate Is a Running Service Now — DGV v0.4.0

The Gate Is a Running Service Now — DGV v0.4.0

For most of this year, DGV was a specification with a verifier: 89 test cards, a reproducible build, and a public claims registry. Necessary work — but a spec only proves that a system can be checked. It does not sit in front of anything.

Update: sealed A2A transport and token delegation have since shipped — see the follow-up note. The "No A2A payload confidentiality" non-claim below no longer stands.

That changed. dgv-gate is a live Axum/Rust enforcement service that now sits between an AI agent and the action it is about to take. It is running, it is integrated into a real product, and every claim below is a test you can execute.

The core idea: T₀ ≠ T₁

The design principle the whole gate is built around:

Permission to act is not continuing authority to act.

An agent proposes an action at time T₀ — a tool call, a write, a spend. The gate evaluates identity, revocation status, policy, budget, and justification, then issues a one-use token bound to the exact action and parameter hash. At time T₁ — execution — the gate re-checks everything, including whether the caller was revoked in the meantime.

This is not academic. In the live Minuta CRM integration, we revoked a caller after it received a valid token and before it executed. The write never ran. The denial produced a signed receipt. That is the entire thesis demonstrated in one sentence: a decision made earlier is evidence about the past, not authority for the future.

What shipped

Verified identity — no more self-declared agents

Before this update, an agent announced itself with a string. Now the gate verifies JWTs — HS256 shared-secret for development, RS256/JWKS for production key rotation, and OIDC discovery via DGV_OIDC_ISSUER. The sub claim becomes the actor. A revoked employee's agent cannot rename itself back into existence.

Algorithm confusion is pinned out: a gate configured for JWKS mode rejects HS256 tokens outright. JWKS responses are TTL-cached, and an unknown kid triggers exactly one forced refetch — enough to follow rotation, not enough to become a fetch-per-request liability.

Signed, versioned, reversible policies

Every governance policy is Ed25519-signed at write time and verified on load — a tampered policy is rejected, not silently trusted. Policies keep full version history, and a single call rolls back to any prior version. Two enforcement knobs live on the policy itself: min_approvals (how many verified human signatures a token needs) and min_justification_length (no one-word justifications for high-risk writes).

The approval workflow is real

POST /approve/:token_id records an approval bound to the verified approver identity — the body's approver_id field can no longer be forged when JWT is configured. At T₁, the gate counts stored approvals against the policy's requirement. Insufficient approvals means the token is refused, and the denial receipt states exactly how many approvals were required versus received.

Fail-closed under partition — this one was a bug we found and fixed

Here is the honest part. While building Phase 8 we found that revocation checks used .ok().flatten() — a database error was silently converted into "not revoked." A network partition would have allowed everything. That is precisely the failure mode this whole system exists to prevent.

Now DGV_PARTITION_POLICY=fail_closed is the default: if the gate cannot verify continuing authority, it denies — at T₀, at T₁, and on both A2A revocation checks. fail_open still exists as an explicit, logged, development-only opt-in. And a gate that cannot reach Postgres at startup now boots degraded (health reports disconnected) and self-heals via background migration retry when the database returns — instead of crash-looping.

Signed revocation gossip — propagation, not consensus

Disconnected nodes can still learn about revocations. POST /revocations/gossip accepts Ed25519-signed revocation records verified against a configured trust set (DGV_GOSSIP_KEYS); locally-originated revocations broadcast to DGV_PEERS. Received gossip is never re-gossiped — one hop, no storms — and a monotonicity guard means a stale record cannot overwrite a newer one.

Measured: ~60 ms node-to-node on the test rig. Forged gossip is rejected. Stale gossip is rejected. Gossip to a node with no trust set is rejected.

And the honest boundary, stated plainly in the audit package: this is authenticated propagation, not consensus. Two nodes partitioned from each other and the store can diverge. GET /revocations/digest — a SHA-256 over canonically sorted revocation entries — makes that divergence detectable. Resolving it requires a quorum protocol we have not built and do not claim.

Circuit breakers and A2A envelopes

Callers report tool execution outcomes to /tool-health/report; after a configurable threshold of consecutive failures the gate stops authorizing that tool until it recovers or a human resets it. Per-tool isolation — one broken tool does not freeze the system.

For agent-to-agent communication, /a2a/send verifies Ed25519-signed envelopes against admin-provisioned keys — agents cannot self-register. Replay protection is enforced two ways (envelope_id primary key plus (sender, nonce) uniqueness), expiry and clock skew are checked, and both parties' revocation status is verified before a gate-signed delivery receipt is issued. Payloads never transit the gate — hashes only.

Operational depth

Prometheus metrics at /metrics, structured JSON logging via DGV_LOG_FORMAT=json, deep health checks (storage connectivity, key status, JWT mode, partition policy, uptime), graceful shutdown on SIGTERM, CORS control, admin authentication on privileged endpoints, and full OpenAPI documentation.

Framework integrations — verified against the real packages

  • LangChain: GovernedTool wrapper plus govern_all_tools, which wraps an entire tool list so every call in a full agent executor run goes through govern + execute.
  • CrewAI: the adapter is verified end-to-end against the real crewai package (v1.15.21) — which mattered, because the first version was silently broken against real CrewAI's pydantic BaseTool. We restructured it and now test against the installed package.
  • Python: dgv-sdk (pure Python, zero dependencies) and dgv-python (PyO3 bindings) both build into wheels that install and import cleanly. PyPI publication is configured; pushing is a credentials step, not an engineering one.

The live proof: Minuta CRM

The strongest evidence is that the gate governs a product we actually run. Eighteen Minuta CRM tools — every record write and every credit-spending enrichment call — route through governed(). Caller identity comes from the verified CRM session, not the tool's own declaration. Signed governance evidence rides inside the tool result, which means it lands in the CRM's existing audit stream for free. When DGV_GATE_URL is unset the tools pass through ungoverned; when the gate is configured but unreachable, the calls fail closed. Both behaviors are tested — 223 agent tests pass, plus two live integration tests against a running gate.

The numbers, as measured

MetricValueHow
Integration checks210+ passingtest_gate*.py, SDK, revocation, network suites
Gossip revocation propagation~60 msTwo live gates, separate SQLite stores
Shared-store revocation visibility~4 msTwo live gates, one SQLite file (same-host lower bound)
Test cards89/89Differential suite, real native implementations
Gate endpoints27OpenAPI-documented

What this does not establish

We publish non-claims because they are the difference between evidence and marketing:

  • No consensus protocol. Gossip is authenticated propagation. Quorum-based revocation consensus is future work and is labeled as such.
  • No third-party audit. The verifier source is open and AUDIT_PACKAGE.md documents what is computed versus simulated — an independent audit remains required.
  • No A2A payload confidentiality. Superseded: dgv-sealed-v1 now encrypts A2A payloads end-to-end (X25519 ECDH + AEAD through a zero-knowledge relay). What remains open: post-quantum crypto, forward secrecy, and traffic-analysis resistance.
  • No in-gate semantic analysis. Justification quality is delegated to an external verifier webhook; the gate enforces its verdict but performs no LLM reasoning itself.
  • Per-instance circuit breakers. Breaker state lives in memory per gate instance; distributed breaker state is future work.
  • Passing our tests is not certification. It is reproducible evidence that the code does what the tests say.

Where to look

Everything above runs from a git clone:

  • Repository: only-dgv-verifier
  • test_revocation_network.py — the Phase 8 suite: gossip, forgery, staleness, divergence, partition behavior, latency
  • test_a2a_transport.py — sealed-transport suite: ECDH roundtrip, delivery, ciphertext-swap detection, forged signatures
  • test_delegation.py — delegation suite: monotonic decay, depth cap, cascade revocation, grantee binding
  • AUDIT_PACKAGE.md — the claims matrix and the non-claims list
  • OWASP_AGENTIC_TOP10.md — coverage against the agentic threat model
  • openapi.yaml — every endpoint, every schema

The next milestones are consensus-grade revocation and an independent third-party audit. Until then: evidence, not adjectives.


Back to Publications

Published by Only Institute