DRQ · data residency quarantine

Verified resident pool (#184)

The active Worker is residency-pool, with the fixed ResidentObject namespace. Sydney and Melbourne gateways proxy to its guarded origin. Entry checks Cloudflare ingress, bearer authentication and the Worker's own Australian execution before reading a body or selecting an object. This cannot undo an offshore TLS handshake or distinguish an Australian direct caller from a gateway caller.

Allocate and use

Use the quarantine CLI to take a verified DO in the required city; its help lists credentials, identity, team, stack and binding arguments. The job interface accepts synthetic jobs only; never enqueue a real dataset or an application callback.

cd /Users/MN/GITHUB/comms-id/platform
/Users/MN/bin/pnpm quarantine --help

Bind residency-pool as a service, preserve the caller's cf metadata, and use its configured control credential. Select the taken name and its exact consumer identity explicitly:

import { createPool } from "@comms-id/data-residency/cloudflare/workers";
const pool = createPool(env.POOL, {
  name: env.TAKEN_OBJECT_NAME,
  consumer: { team: "example-team", stack: "example-stack", binding: "OBJECT" },
});
const authorised = new Request(request, {
  headers: { authorization: `Bearer ${env.POOL_CONTROL_TOKEN}` },
});
// Control operation after take; separate from each work request.
await pool.refresh(authorised);
const accepted = await pool.enqueue(authorised, [{ id: "stable-job-id", kind: "noop" }]);

HTTP uses POST /refresh with {name} and POST /work with {name, consumer, command}. Commands are enqueue (fixed synthetic kinds only), jobs and run. GET /health checks the entry, not an object's grant. The object checks its activation before storage and its local verified assignment before every job transaction and dispatch. Replies expose the source watermark and observation time. No allocation, reassignment or ledger query occurs on a work request.

Separate routing refresh and native alarms update the local grant. Source unavailability preserves an already verified taken grant without claiming fresh evidence; a recorded revocation refuses. Repeat the same object and job IDs after an unknown reply. Job execution is at least once, with bounded terminal history; consumer payloads, arbitrary callbacks and schedules are not supported by this host.

Fixed application dispatch

The host also has three explicit application paths: /asic/, /abn/ and /dfat/. Each selects a deployment-defined service binding, then the application selects its taken object. The object checks its exact team, stack and binding before forwarding to that application's private entrypoint. Each dispatch requires its own exact application assignment.

These calls are not jobs: the object does not store or queue application bodies, accept arbitrary destination URLs or execute caller-supplied callbacks. The receiving application checks its own execution location before accessing its verified R2 binding. DFAT additionally checks separate scoped consumer and operations identities. Deploy the application before adding its binding to the pool, then refresh the taken object's local assignment before use.

Deploy and read back

Deploy only merged main through the existing gate. During the S4 cutover the order is the resident entry, both gateway integration updates, then the old archive freeze; plans must contain updates only and keep all existing namespace IDs. Read back gateway configuration and authenticated /health through both gateways, exercise a taken object's synthetic job, and prove the old mutation routes refuse.

The declared origin remains public because the AWS HTTP proxies use it. Missing/foreign ingress refuses before authentication; Australian direct ingress still needs the credential and execution check. The entry has no preview URL. These checks do not prove storage replicas or trace-subrequest residency.

Legacy custody until S5

The old au-pool, Anchor, Registry, synthetic app and controls remain registered solely for readback and the exact owner-approved purge. Old HTTP and native job, scheduling, registry and audit-write paths refuse; old alarms do not dispatch or rearm. They are not aliases for the new pool. Do not remove their physical exports or bindings: that would delete namespaces before S5 approval.

AU_POOL_URL and the original POOL_TOKEN still address the historical receipt archive. Its reads use fresh AU activation checks and SELECT-only storage; hashes, original identities and lineage are preserved. The old daily runners refuse before network access, their workflow is unscheduled and the launchd example is disabled. PLAN 2 cancelled that schedule; explicit quarantine rechecks and local activation guards remain.