* 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>
103 lines
3.5 KiB
YAML
103 lines
3.5 KiB
YAML
name: cloudflare-worker-leases — build + test + lint
|
|
|
|
# Slice K-Cont-4 of EPIC-6 (#1101). Verifies the OpenOva Continuum
|
|
# lease-witness Worker source at `products/continuum/cloudflare-worker/`
|
|
# and the OpenTofu module at `infra/cloudflare-worker-leases/`.
|
|
#
|
|
# Per CLAUDE.md "every workflow MUST be event-driven, NEVER scheduled":
|
|
# this workflow is push-on-merge + pull-request-on-touch + manual
|
|
# dispatch. NO cron triggers.
|
|
#
|
|
# This workflow does NOT auto-deploy the Worker. Per the K-Cont-4 brief
|
|
# "DO NOT auto-deploy — operator manually runs tofu apply for the lease
|
|
# witness deploy". The `wrangler deploy --dry-run` step verifies the
|
|
# Worker compiles + bundles correctly without writing to Cloudflare.
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'products/continuum/cloudflare-worker/**'
|
|
- 'infra/cloudflare-worker-leases/**'
|
|
- '.github/workflows/cloudflare-worker-leases-build.yaml'
|
|
pull_request:
|
|
paths:
|
|
- 'products/continuum/cloudflare-worker/**'
|
|
- 'infra/cloudflare-worker-leases/**'
|
|
- '.github/workflows/cloudflare-worker-leases-build.yaml'
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
worker-test:
|
|
name: Worker — npm ci + test + lint + build:dryrun
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
defaults:
|
|
run:
|
|
working-directory: products/continuum/cloudflare-worker
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
# Node 20 is the LTS that matches @cloudflare/workers-types
|
|
# 4.20240909+ tooling. Pin minor to keep CI deterministic.
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
cache-dependency-path: products/continuum/cloudflare-worker/package-lock.json
|
|
|
|
- name: npm ci (clean install from lockfile)
|
|
run: npm ci
|
|
|
|
- name: ESLint
|
|
run: npm run lint
|
|
|
|
- name: TypeScript typecheck
|
|
run: npm run typecheck
|
|
|
|
- name: Vitest — handler + contract suites
|
|
# @cloudflare/vitest-pool-workers spawns a per-test workerd
|
|
# runtime with in-memory KV. No network, no CF account needed.
|
|
run: npm test
|
|
|
|
- name: Wrangler build dry-run
|
|
# `wrangler deploy --dry-run --outdir=dist` compiles + bundles
|
|
# the Worker WITHOUT pushing to Cloudflare. Catches syntax
|
|
# errors, missing imports, oversized bundles. The `dist/`
|
|
# output is what `infra/cloudflare-worker-leases/main.tf`
|
|
# reads as the script content at apply time.
|
|
run: npm run build:dryrun
|
|
|
|
tofu-validate:
|
|
name: OpenTofu — fmt + validate
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
defaults:
|
|
run:
|
|
working-directory: infra/cloudflare-worker-leases
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install OpenTofu
|
|
uses: opentofu/setup-opentofu@v1
|
|
with:
|
|
# Match infra/hetzner/'s pin (see infra/hetzner/.github/workflows/
|
|
# infra-hetzner-tofu.yaml). Bump in lockstep.
|
|
tofu_version: 1.8.5
|
|
|
|
- name: tofu init (backend=false — module-local checks only)
|
|
run: tofu init -backend=false
|
|
|
|
- name: tofu fmt -check
|
|
run: tofu fmt -check -recursive
|
|
|
|
- name: tofu validate
|
|
# `validate` requires `init` to have downloaded the cloudflare
|
|
# provider plugin (above). Validates HCL syntax + provider
|
|
# schema conformance — won't catch runtime issues like a wrong
|
|
# account_id but catches every authoring error.
|
|
run: tofu validate
|