* feat(continuum): K-Cont-4 — Cloudflare Worker source + tofu wiring for lease witness (#1101) Implements the server side of the Cloudflare KV lease-witness pattern that K-Cont-3's CFKVClient (in core/controllers/continuum/internal/ witness/cloudflarekv/) speaks to. The Worker fronts a Cloudflare Workers KV namespace with read-then-CAS-write semantics enforced via the If-Match header — exact contract per K-Cont-3 #1158 report (item d) and the canonical-seams "Cloudflare KV Worker contract" entry. Routes: GET /lease/<slot-url-encoded> → 200 + LeaseState | 404 | 401 PUT /lease/<slot> → 200 + LeaseState | 412 + state | 401 DELETE /lease/<slot> → 204 | 412 | 401 All 7 K-Cont-3 trap behaviors verified by 46 vitest tests: 1. If-Match: 0 = first-acquire-on-empty-slot 2. Generation increments unconditionally (incl. Release) 3. 412 includes current state body 4. TTL eviction is server-authoritative in stamping (Worker doesn't auto-evict — controller's IsHeldBy decides) 5. X-Holder mismatch on DELETE returns 412 (stale region can't evict new primary) 6. Bearer token validation against env-bound allow-list 7. Optional X-Lease-Slot header logged for KV granularity Files: products/continuum/cloudflare-worker/{package.json, tsconfig.json, wrangler.toml, vitest.config.ts, .eslintrc.cjs, .gitignore, DESIGN.md, src/{index,auth,kv,types}.ts, src/handlers/{get,put,delete}.ts, test/{handlers,contract,env.d}.ts} infra/cloudflare-worker-leases/{versions,variables,main,outputs}.tf + README.md .github/workflows/cloudflare-worker-leases-build.yaml (event-driven, NO cron — push-on-paths + PR + workflow_dispatch) Tests: 46/46 vitest pass (handlers 37 + contract 9). ESLint clean. tsc --noEmit clean. wrangler deploy --dry-run produces 9.47 KiB bundle. Per the brief: tofu module ships ready for operator action — no auto-deploy. Operator runbook in DESIGN.md §"Operator runbook — deploy a new Sovereign". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(continuum/cf-worker-tofu): K-Cont-4 — adopt CF v5 inline secret_text binding (was v4 separate resource) `tofu validate` failed on `cloudflare_workers_secret` — that resource was REMOVED in cloudflare/cloudflare v5 (it consolidated into the inline `bindings = [...]` array on `cloudflare_workers_script` with `type = "secret_text"`). Same security guarantee — encrypted at rest in CF, never visible via dashboard read API once written. `tofu fmt` also wanted versions.tf alignment + the .terraform.lock.hcl pinning the resolved cloudflare/cloudflare v5.19.1 (mirrors infra/hetzner/ which commits its lock file). Per Inviolable Principle #5 the bearer token value still flows from TF_VAR_bearer_tokens_csv extracted at apply time from a K8s SealedSecret — never inlined here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: hatiyildiz <hati.yildiz@openova.io> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| .terraform.lock.hcl | ||
| main.tf | ||
| outputs.tf | ||
| README.md | ||
| variables.tf | ||
| versions.tf | ||
infra/cloudflare-worker-leases/ — OpenTofu module for the Continuum lease-witness Worker
Slice K-Cont-4 of EPIC-6 (#1101). Deploys the Worker source from products/continuum/cloudflare-worker/ to Cloudflare alongside its KV namespace and env-bound bearer-token allow-list.
Inputs
| Variable | Required | Description |
|---|---|---|
cloudflare_account_id |
yes | 32-char hex. Read from CF dashboard. |
cloudflare_api_token |
yes (sensitive) | API token with Workers Scripts: Edit + Workers KV Storage: Edit. |
bearer_tokens_csv |
yes (sensitive) | Comma-separated allow-list of bearer tokens. Source: per-Sovereign SealedSecret. |
worker_name |
no (default openova-continuum-lease-witness) |
Worker script name (becomes part of the URL). |
kv_namespace_title |
no (default openova-continuum-leases) |
KV namespace display title. |
log_level |
no (default info) |
One of error / info / debug. |
worker_script_path |
no (default ../../products/continuum/cloudflare-worker/dist/index.js) |
Path to the bundled Worker JS. Run npm run build:dryrun in the worker dir first. |
Outputs
| Output | Use for |
|---|---|
worker_url |
Paste into Continuum CR spec.leaseClient.config.baseURL. |
kv_namespace_id |
Ad-hoc wrangler kv:key list introspection. |
worker_name |
Deployed Worker script name. |
Operator runbook
-
Build the Worker bundle:
cd ../../products/continuum/cloudflare-worker npm install && npm run build:dryrunThis produces
dist/index.js(the bundled Worker script). -
Extract bearer tokens from the per-Sovereign SealedSecret:
kubectl --kubeconfig <sov-kubeconfig> get secret -n catalyst-system \ continuum-cf-witness-tokens -o jsonpath='{.data.token}' | base64 -dFor rotation, prepare a
<new>,<old>CSV. -
Apply:
cd ../infra/cloudflare-worker-leases tofu init TF_VAR_cloudflare_account_id=<acct> \ TF_VAR_cloudflare_api_token=<token> \ TF_VAR_bearer_tokens_csv='<csv>' \ tofu apply -
Wire the Continuum CR with the
worker_urloutput. The catalyst-controllers reconciler picks up the change on next reconcile (~30s); verify viakubectl logs -n catalyst-controllers continuum-controller-*.
Why no cloudflare_workers_route?
The Worker's default *.workers.dev URL is sufficient for the controller's HTTPS calls. A custom hostname (e.g. lease.openova.io) would require zone setup outside this module. Operators wanting a custom domain set spec.leaseClient.config.baseURL directly to the custom hostname AFTER setting up the route in the CF dashboard or a sibling tofu module.
What this module does NOT do
- Doesn't deploy automatically. Per the K-Cont-4 brief,
tofu applyis operator-run. CI only verifiestofu validate+tofu fmt -check. - Doesn't manage the SealedSecret. That's a
clusters/<sov>/...overlay artifact; the operator extracts plaintext to feed this module'sbearer_tokens_csvvar. - Doesn't tear down on Continuum CR deletion. Worker + KV outlive the CR (they may serve other CRs). Manual
tofu destroywhen retiring a Sovereign.