Venue maintenance recovery
Status: Active Last reviewed: 2026-09-07
The operator command keeps request bytes and receipts in a private local journal. An interrupted request can be reconciled against its original server identity; a lost reply does not justify creating another application. This command operates on the captured-hours contract in migrations 00616–00620. The collect command reads government hours for one prepared target. Deployment and provider activation remain separate release steps.
Runtime and configuration
Use Node 22.22 or newer, Linux, an ext4 filesystem and util-linux flock/findmnt. The run path must be absolute and its parent must already exist. Use a private, durable directory owned by the operator. Runs use mode 0700 and files use 0600; the journal rejects symlinks, extra hard links, replaced files and an active lock. Keep the complete run directory for recovery, including its permanent LOCK file. The lock is released by the kernel when the process exits; deleting that file is not a recovery step. An incomplete or corrupt run stops without new requests.
Supply configuration in the process environment:
SUPABASE_URLorEXPO_PUBLIC_SUPABASE_URL: the project origin. If both are supplied, they must match exactly.EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY: the preferred gateway key. The existingEXPO_PUBLIC_SUPABASE_ANON_KEYfallback accepts a legacy anon JWT.INGEST_TOKEN: the private operator token recognized by the endpoint.DATA_GO_KR_SERVICE_KEY: the government API key, used only bycollect.
The command does not search dotenv files or stored credentials. It rejects obvious secret/service-role gateway keys and sends no user-session Authorization header. Credentials belong in the supplied environment, never command arguments or run files. The deployed gateway remains responsible for gateway-key validation.
Commands
Run yarn venue:maintenance --help for the command names and overall bounds. Every operation below requires --run /absolute/path/to/run.
| Command | Scope and behavior |
|---|---|
prepare --venue-id UUID | Creates a new run for 1–50 explicit venues. Repeat the flag for each venue. Saves preparation only. |
refusal --venue-id UUID --reason REASON | Creates a new one-venue run recording requires_prepared_capture or requires_full_source_contract. Optional --input-ref-file PATH supplies bounded JSON. |
get --target-id UUID | Inspects one explicit target. A new run fixes its scope to that target; an existing run must already permit it. Each explicit invocation requests a fresh read. |
list | Creates or continues an inspection run, with --limit 1..5, --pages 1..10 and an optional --state. The default is one page of five rows. Filters and page size stay fixed for that run. |
resume | Reconciles saved, unresolved requests, applying the original request first when its completion is uncertain. It creates no new claim, application or page. |
collect --target-id UUID | Requires an existing run and one permitted prepared target. Fetches government hours and saves an immutable capture; it does not apply facts. |
apply | Reconciles earlier mutations, then claims and applies the run's permitted targets. Repeated --target-id UUID flags may narrow that scope. It requires an existing run. |
List results do not authorize application. To work on an already prepared server target without a local run, create an explicit get run for that target and then invoke collect, then apply on that run. A prepared target without captured evidence stays paused; the command cannot invent a capture or bypass a source-completeness gate.
Government collection reads at most eight pages of 1,000 rows each from the documented endpoint. Every page must have a successful provider code, the expected page identity/count and a stable reported total. Bodies are capped at 2 MiB and each fetch plus body read at 20 seconds. Provider calls consume the same ten-call budget as maintenance reads/writes; one call is reserved for the capture. Only one unambiguous identity with representable hours can become ready for apply. Missing or conflicting rows, partial pages and provider errors cannot clear facts, close venues or certify ownership. Paged reads never prove authoritative absence; the phase-one generation status remains unknown or incomplete, even when all reported pages were read. A no-match result uses incomplete/unknown_total to record that absence cannot be established.
The government response envelope was checked against a real one-row response on 2026-09-07. That probe establishes the wire format, not nationwide completeness. The legacy enrich-gov-std-hours.mjs command now exits paused with this runbook's replacement command; it cannot generate SQL or dispatch legacy writes.
Each invocation admits at most ten network calls and 90 seconds of work. Use --max-calls and --max-ms to reduce those limits; an existing run's limits cannot be raised. Every attempt, including a failed read, consumes the same budget. Network calls are bounded separately, and the command does not poll or sleep through retry backoff. Synchronous filesystem operations cannot be forcibly interrupted by the invocation deadline.
Reading outcomes and recovering interruptions
Stdout is one bounded JSON summary. Exit 0 means acknowledged, reconciled or help; exit 2 means paused work; exit 1 means failure. Preparation or read acknowledgement does not mean venue facts changed. applyReceiptCounts counts saved attempts, while target states describe the latest relevant local receipts. This is not a fresh server inventory query. Unknown journal state is returned as null.
After an interrupted invocation, use resume on the same run. The journal checks saved bytes, response bindings and event history, then sends only unresolved original requests. A saved successful response requires no network replay. For collect, interruption after saving the capture replays the original capture bytes and clocks, without fetching the provider again. If interrupted before a capture was saved, no capture request was sent; another explicit collect may fetch fresh evidence. An acknowledged incomplete/error/held capture stays immutable: investigate its receipt and prepare a new target for a later attempt. An unresolved application remains recoverable after its lease expires because the server may already have committed its original receipt.
A validated stale-lease rejection is recorded separately from success and pauses the invocation. A subsequent explicit apply can obtain a new claim. Once a specific claim is recorded as expired, clock rollback cannot revive it for new work. Other uncertain errors retain the original request for reconciliation.
For list inspection, resume only recovers an unresolved page. Another explicit list invocation advances the saved cursor. The exact timestamp and UUID cursor survive process restart without rounding. Changed filters need a new run.
Acceptance evidence and remaining venue work are recorded in the venue pipeline implementation audit.