TECHNOLOGY / ACCESS / REVOCATION
Access Revoked. What Actually Stopped?
Access was revoked. Who is still in the meeting room?
Imagine a company disabling an account and cancelling an access card. The dashboard says Access Revoked. Then someone asks: “Where is the visitor now?” “In the meeting room.” “How?” “They entered before we revoked access.”
The company prevented another entry. It has not yet dealt with the person already inside. Connections have a similar distinction: denying the next login does not automatically end an existing session.
Grantweft is my small gateway for temporary access to a fixed TCP service. It uses individual mTLS certificates, separates requests from approval, and aborts existing connections when a grant expires or is revoked. It is a single-node MVP with explicit capacity and deployment limits.

I wanted to separate three questions often compressed into “access revoked”: can a new connection be established, has the existing connection ended, and is work already accepted by the backend still running? Each needs its own mechanism and completion evidence.
A recorded approval is not current permission to transfer data
Individual client certificates map to fixed principals and requester/approver roles. A requester cannot approve their own request. Access also targets a configured service ID and numeric address, rather than an arbitrary destination. mTLS establishes connection identity; usable access still requires a valid approval.
Revocation here targets a specific access grant. It does not disable the entire user account or revoke an mTLS certificate, and it does not automatically revoke other grants held by the same principal. Credential and identity lifecycle management are separate responsibilities.
SQLite retains requests, approval decisions, operation deduplication and audit records. A historical approval records a past decision. Current transfer permission also depends on the deadline, state and execution epoch. The deadline is frozen before approval commits, and a late storage completion must not revive retired authority.
Failure handling follows that distinction. Persistence errors put the service into DEGRADED and stop transfer and new authorization work. Restoring directory permissions alone does not revive old access. A pending approval/revocation revision conflict currently retires the whole service conservatively and requires operator attention. That sacrifices availability; it is not transparent race recovery.
Ending a session is not undoing an operation
Each tested TLS tunnel corresponds to one backend TCP session. Expiry or revocation aborts the transport. Tests check both denied new access with the retired grant and positive closure of a held tunnel, followed by zero idle sessions.
Closing a socket cannot retract bytes already passed to kernel buffers or guarantee cancellation of work the backend accepted. An application may even have completed the operation before its response is lost. A disconnected client cannot infer that the operation never happened.
Think of a manager revoking payment approval after the transfer has gone through. Updating the approval field records the new decision. It does not bring the money back. Authority and external effects need separate checks.
On narrow screens, scroll the table sideways to read all columns.
| The promise | What to establish | What it does not establish |
|---|---|---|
| Deny new access after revocation | Attempts with the original identity and retired grant are refused. | The existing session has ended. |
| End existing connections through the gateway | A held tunnel reaches EOF/reset and sessions return to zero. | Backend work already accepted has been cancelled. |
| Cancel or resolve accepted work | The backend implements and validates cancellation, transactions or compensation. | Closing the connection completed this work; Grantweft has not qualified that capability. |
There is an essential deployment condition: clients must not have another path to the backend. Gateway revocation cannot control a connection that bypasses it. Backend isolation and network configuration therefore belong in deployment acceptance, alongside the gateway’s internal state.
Restart: preserve history, obtain new authority
Startup invalidates all previous PENDING/ACTIVE grants before opening listeners. Sessions and grants do not survive a process or VM restart; clients must request access and obtain approval again. Preserving history and continuing current authority are different decisions.
This is a conservative choice for this MVP, with an operational cost. Restart interrupts access, so operators and approvers need a workable reauthorization procedure. It is not the only valid design for every access system. Continuing grants across restart would require a different expiry, revocation and recovery contract.
The package ships a systemd service. The gateway runs under a dedicated non-root account with no capabilities and a restricted writable state directory. READY means journal recovery and listener initialization completed. Authenticated status and a freshly approved application request still establish usable access. Host network and storage ordering require their own preparation.
Retained evidence: 51 checks and ten minutes of observation
This article uses the retained grantweft-closeout-review-v8 record; no product VM or hardware trial was rerun. Native macOS and installed Linux passed 51 identical checks each: 38 formal implementation/CLI/readiness checks and 13 observer/cleanup controls, with no failures, errors or skips. Calling all 51 product-feature tests would erase that distinction.
The record also includes seven storage/capacity/late-commit scenarios and the actual installed systemd lifecycle, including SIGKILL takeover, stopping and restart limiting. Two enabled-service normal VM reboot cases cover recovery and operator repair after readonly storage prevents startup. Before service activation, a read-only witness checks that the old ACTIVE/PENDING journal is unchanged, excluding shutdown cleanup as the explanation for boot recovery.
Forty cycles over 600.001 seconds alternate 20 explicit revocations and 20 natural expiries. Process identity, epoch and restart count remain unchanged. Every cycle requests and approves a fresh grant, performs twenty ordered 8-KiB roundtrips, and then checks tunnel closure, denied retired access and zero idle sessions.
Idle FD samples remain at 10. After five warmup cycles, sampled idle main-process RSS ranges from 26,412 to 28,188 KiB, approximately 25.8–27.5 MiB, and rises during the observation. These are not peaks or the combined memory costs of the VM, clients and backend. They do not establish leak freedom or a long-term plateau.
Ten minutes can reveal useful behavior. It cannot stand in for ten months. Otherwise, a new colleague arriving on time on day one would qualify as a complete long-term attendance study. The observation is real; the promise has outrun it.
The verifier rejects 133 corrupted reports. Those challenge the evidence checker; they are not 133 product incidents. Two failed attempts remain recorded: one fixture unintentionally made its loop backing device readonly, and another left a fresh verification grant active before the next scenario. Correcting the fixtures and rerunning does not turn those earlier failures into successes.
Finite history needs an operating plan
Retained grants grow from 14 to 54 against a configured limit of 96. Operation and audit rows each grow from 28 to 128 against limits of 512. Terminal records still consume capacity, and automatic garbage collection or rollover is not implemented. The ten-minute workload deliberately fits within finite budgets; it does not qualify indefinite operation. Plan capacity monitoring and maintenance without bypassing ownership checks by deleting the journal.
Normal VM reboot is not sudden power loss. Boot-zero-gap protection, actual suspend, physical-storage faults, long-term operation and arbitrary production networking remain unqualified. Hostile root/same-UID processes and a complete credential lifecycle are outside this qualification too.
Project source and documentation now use MIT. License adoption changed packaging metadata and notices, while the original VM measurements retain their qualified source fingerprint. For this article, I checked the retained verifier and metadata-only bridge: runtime modules, the service unit and validation tools remain unchanged. This was not a new VM trial of the MIT package.
Agree what “stop” means before deployment
I would agree with the service owner whether revocation must stop new connections, existing connections, or work already accepted by the backend. Who maintains identities and approval roles? Who restores usable access after restart or capacity exhaustion? If the backend outcome is uncertain, who queries it, cancels it or performs compensation?
Grantweft makes those boundaries more concrete. It cannot choose recovery semantics for every backend. Access Revoked establishes a change in authority. Connection closure and unresolved external effects still need their own evidence and an accountable handoff.