Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,41 @@ name: Deploy Lighthouse to Cloudflare

on:
workflow_dispatch:
push:
branches:
- main

jobs:
gate:
if: github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[deploy lighthouse]')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run typecheck
- run: npm test
concurrency:
group: lighthouse-production
cancel-in-progress: false

jobs:
deploy:
needs: gate
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- name: Require an explicit main-branch dispatch
shell: bash
run: |
if [ "$GITHUB_REF" != "refs/heads/main" ]; then
echo "Production deployment must be dispatched from main."
exit 1
fi
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
- run: npm ci
- name: Deploy Worker while preserving provisioned secrets
- run: npm run typecheck
- run: npm test
- name: Deploy Worker while preserving provisioned variables and secrets
id: production_deploy
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --keep-vars --strict
- name: Record the active deployment receipt
if: ${{ always() && steps.production_deploy.outcome != 'skipped' }}
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy
command: deployments status --json
12 changes: 9 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ Authority sources in descending order:
## Owner Approval and Operational Safety

- Do not commit unless Jamie/the user explicitly approves.
- Do not push or merge unless Jamie/the user explicitly approves. This repository is connected to Cloudflare Workers Builds: the 1.29.3 review-branch push uploaded a preview Worker version, and a push to the Cloudflare-configured production branch may promote an active deployment independently of the checked-in GitHub Actions gate.
- Do not deploy, run `wrangler deploy`, apply D1 migrations, rotate secrets, perform destructive operations, or publish releases unless Jamie/the user explicitly approves.
- Do not push or merge unless Jamie/the user explicitly approves. Git publication is an external mutation: branch pushes can upload Worker versions and create preview URLs even when they do not change active traffic.
- External release-control receipt: on 2026-08-26, the Cloudflare Workers Builds production Deploy command was changed from `npx wrangler deploy` to `npx wrangler versions upload`; durable readback after reload confirmed that both Deploy and Version commands are exactly `npx wrangler versions upload`. No build, upload, or deployment was invoked.
- Cloudflare Workers Builds is authorized only to upload versions and previews. The checked-in manual, main-only, validated, serialized, receipted GitHub workflow is the sole authorized production-promotion path. If the external command becomes inaccessible or differs from the verified value, stop and report `BLOCKED BEFORE MERGE`.
- Do not dispatch the production workflow, run `wrangler deploy`, run `wrangler rollback`, apply D1 migrations, rotate or remove secrets, alter routes/custom domains, change observability, perform destructive operations, or publish releases unless Jamie/the user explicitly approves that action. Direct `wrangler deploy` is not an authorized alternate promotion path.
- `npm run release:upload` and `wrangler versions upload` are non-promoting but not zero-mutation; they require explicit publication approval.
- Any Cloudflare Workers Builds configuration change requires explicit external-change approval and a read-only verification receipt before relying on it.
- When code depends on a D1 schema change, a migration requires explicit approval and remote verification before any Worker deployment.
- Do not print or commit secret values.
- Cross-repository contracts with Agent Smith, BUS Core, buscore-site, or the leads database must be documented when touched.
Expand All @@ -44,13 +48,15 @@ For any Lighthouse alert, WATCH, analytics question, report failure, service-hea
4. If the approved endpoint, credential source, account context, or tool access is missing, report `ACCESS_BLOCKED`. Do not improvise an endpoint, credential, direct SQL query, or alternate service.
5. Do not fan out across every endpoint. Start with supplied evidence; when live access is approved, use the stored-data `GET /report?view=ceo` diagnostic first and narrow from there.

Canonical Cloudflare identity: account `eb1a8dd5723031d94e57642e3eaaebda`, Worker `buscore-lighthouse`, primary D1 binding `DB` at database ID `e46f2daa-7e97-45a3-9bf0-49003a42850c` named `lighthouse`, and Production Custom Domain `lighthouse.buscore.ca`. An empty Worker Routes list is expected for this Custom Domain. If another account context lacks the Worker, correct the account rather than diagnosing an outage.

Operational constraints:

- `GET /report?view=source_health` is ingestion-integrity evidence, not service-probe truth.
- `WATCH` is not synonymous with outage; Agent Smith owns WATCH/ALERT/UNAVAILABLE wording, while Lighthouse owns facts and availability.
- The current `ADMIN_TOKEN` is broad: it protects report reads and the mutating `POST /campaign`, `POST /notes`, and `POST /report/snapshot` routes. Possession does not authorize writes.
- Many GET/HEAD surfaces change evidence. Bare/fleet/site reports refresh stored traffic; report failures can increment errors; artifact HEAD records raw/HEAD truth; update, redirect, artifact, telemetry, and admin-write routes are not passive probes.
- Git publication is not zero-mutation. The 1.29.3 review-branch push triggered Cloudflare Workers Builds, uploaded a Worker preview version, and created preview URLs; future non-production behavior depends on external integration settings. The checked-in workflow's release gate does not govern that separate integration; treat a merge or production-branch push as potentially production-deploying until the Cloudflare build settings are explicitly verified.
- Git publication is not zero-mutation. The 1.29.3 `main` merge proved that the former Workers Builds production command could promote active traffic independently of the checked-in gate. Durable readback on 2026-08-26 confirmed that both non-production and production publication now use `npx wrangler versions upload`. Pushes still create version or preview state, while active production promotion is reserved for the explicitly approved manual GitHub workflow. Any future external-setting drift reinstates `BLOCKED BEFORE MERGE`.
- Lighthouse, Agent Smith, BUS Core, buscore-site, and tgc-site are separate failure domains. Do not infer a cross-service outage from one unavailable layer.

---
Expand Down
18 changes: 16 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
# Changelog

## [1.29.4] - 2026-08-26

- Recorded the owner-approved read-only Cloudflare audit showing that Workers Builds build `793715ef-6123-4d98-a4a7-797634d07812`, sourced from merged `main` commit `59231d09084d0fa4db71012b6f29550886c5b605`, automatically ran `npx wrangler deploy` and promoted Worker version `ba611ac1-653d-47a2-a465-a85f4124b6b6` to 100% of production traffic.
- Verified `lighthouse.buscore.ca` as an active Production Custom Domain rather than a Worker Route, verified the active `5 0 * * *` cron, and reconciled the deployed D1 and R2 binding identities.
- Pinned Wrangler to Cloudflare account `eb1a8dd5723031d94e57642e3eaaebda` and corrected the primary D1 metadata name from `buscore-lighthouse` to the control-plane name `lighthouse` while preserving binding `DB` and database ID `e46f2daa-7e97-45a3-9bf0-49003a42850c`.
- Removed the ambiguous direct `deploy` package command and added explicit `release:upload`, `release:status`, and `release:history` commands. No direct production-deploy script is provided; production promotion must pass through the validated workflow, which preserves dashboard-managed variables, enables Wrangler strict mode, and returns a machine-readable deployment receipt. Package repository metadata now points to `True-Good-Craft/lighthouse`.
- Made `.github/workflows/deploy.yml` manual-dispatch only, main-only, non-cancelling and serialized, with dependency installation, typechecking, the full test suite, strict production deployment, and an active-deployment JSON receipt in that order. The receipt is attempted whenever the deploy step ran, including an uncertain reported failure; it remains skipped when validation prevents deployment. The workflow relies on the pinned account rather than a second account-ID secret.
- Added deterministic release-control tests covering the pinned Cloudflare identity, D1 metadata, sole manual trigger, main guard, validation/deployment order, serialization, variable preservation, strict deployment, explicit operator commands, and canonical repository metadata.
- Added a rollback-safe operator procedure that requires an explicitly approved immutable version ID, preserves Wrangler's interactive confirmation, verifies the resulting traffic assignment by JSON status receipt, and keeps Git, settings, secrets, domains, D1, and migrations as separate rollback domains.
- Made standalone setup fail safer and more reproducibly: Node.js `20.18.1` or newer is required by the lockfile, dependency installation uses `npm ci`, new environments require an explicit non-production Wrangler configuration, migration examples use the stable `DB` binding, and new-environment migration/secret commands cannot silently inherit the pinned production target.
- Completed the mandatory external release-control prerequisite on 2026-08-26: changed the Cloudflare Workers Builds production Deploy command from `npx wrangler deploy` to `npx wrangler versions upload`, then reloaded the control plane and confirmed that both Deploy and Version commands are exactly `npx wrangler versions upload`. The approved dashboard action was limited to saving this configuration field and re-reading it; no build, upload, or deployment control was invoked.
- Recorded remaining operational gaps: persistent Worker logs and traces are disabled; the unused legacy secret names `DISCORD_WEBHOOK_URL` and `PRICE_GUARD_KEY` remain attached pending a separately approved decision; the GitHub deployment-token path is not proven by repository text; Cloudflare still displays the redirecting historical repository name `True-Good-Craft/buscore-lighthouse`; and the current lockfile install reports one low- and five high-severity npm audit findings whose production relevance and remediation have not yet been assessed. No automatic audit fix is authorized by this bundle.
- No Worker source, endpoint, response contract, auth behavior, storage schema or semantics, retention, schedule, ingestion, report metric, runtime integration, secret value, D1 resource, R2 bucket, custom-domain attachment, migration, or active production traffic changed in this local bundle. Production remains Worker version `ba611ac1-653d-47a2-a465-a85f4124b6b6` until a separately approved deployment occurs.

## [1.29.3] - 2026-08-26

- Added `OPERATIONS.md` as the canonical Lighthouse access and diagnostic runbook, including ownership boundaries, resource and credential maps, a morning-triage sequence, source/probe interpretation, and standard incident output.
- Routed agents and operators through the SOT and runbook before live access, with an explicit `ACCESS_BLOCKED` outcome when approved endpoint, credential, account, or tool access is unavailable.
- Documented that the shared `ADMIN_TOKEN` is broad and protects both report reads and administrative writes.
- Classified report, manifest, update, redirect, artifact, telemetry, scheduled, D1, deployment, and administrative surfaces by their possible evidence/state side effects.
- Recorded the separately connected Cloudflare Workers Builds path: publishing the review branch automatically uploaded preview Worker version `33f4db25-9faf-435d-a83e-83d7d1c17eac` and created version/branch preview URLs. The Cloudflare check classified the upload as a preview and did not report an active-production promotion; active-production state was not independently control-plane verified. The checked-in GitHub Actions release gate does not govern this integration, so a merge remains potentially production-deploying until the Cloudflare production-branch and deploy-command settings are explicitly verified or the owner accepts that consequence.
- Recorded the separately connected Cloudflare Workers Builds path: publishing the review branch automatically uploaded preview Worker version `33f4db25-9faf-435d-a83e-83d7d1c17eac` and created version/branch preview URLs. The Cloudflare check classified the upload as a preview and did not report an active-production promotion; active-production state was not independently control-plane verified. The checked-in GitHub Actions release gate did not govern this integration, so at that time a merge remained potentially production-deploying until the Cloudflare production-branch and deploy-command settings were explicitly verified or the owner accepted that consequence.
- Marked the Phase 2, Phase 3, and policy-alignment documents as scoped historical or policy references rather than current operations authority.
- Reconciled cross-repository producer baselines to released BUS Core `1.4.2` and the merged buscore-site `1.4.2` release sync while retaining Agent Smith `0.25.2` as shipped authority; recorded the unresolved BUS Core restore/import signal authority drift rather than legitimizing it.
- Added the explicit owner-approved documentation-only bundle exception: code may be omitted only when runtime and contract behavior do not change; SOT, changelog, package, and lockfile remain mandatory, and dummy code changes are forbidden.
Expand All @@ -28,7 +42,7 @@
- Enforced the TGC privacy contract at ingestion by storing only coarse `small`/`medium`/`large` viewport buckets and event-specific sanitized values for the bounded TGC allowlist. For rolling producer compatibility, exact lowercase `WIDTHxHEIGHT` remains accepted and is immediately bucketed by width before persistence.
- Reconciled the SOT and operator policies with standardized-event storage, keyed minute HMAC rate identifiers, CEO use of the optional leads database, the TGC 90-day raw-retention exception, current report families, BUS Core's no-installation-ID product contract, and TGC's active bounded Layer-5 extension.
- Ignored the repository-local npm cache used by repeatable verification so dependency checks do not dirty release worktrees.
- No schema change or D1 migration was required for 1.29.1. Worker 1.29.1 was deployed on `2026-08-09T16:41:20.004814Z` as Cloudflare Version ID `ee320e1a-9ceb-4d88-a848-fd7ae0e9e3bc` after typecheck, 162 tests, a Wrangler dry run, and confirmation that no remote migration was pending. The owner-approved release used the authenticated local Wrangler session because the repository currently has no Cloudflare credential secrets configured for GitHub Actions; no secret value was changed.
- No schema change or D1 migration was required for 1.29.1. Worker 1.29.1 was deployed on `2026-08-09T16:41:20.004814Z` as Cloudflare Version ID `ee320e1a-9ceb-4d88-a848-fd7ae0e9e3bc` after typecheck, 162 tests, a Wrangler dry run, and confirmation that no remote migration was pending. The owner-approved release used the authenticated local Wrangler session; at that time, no Cloudflare credential secret was configured for the checked-in GitHub Actions deployment path, and no secret value changed. Current deployment-token availability remains unverified by the 1.29.4 local bundle.

## [1.29.0] - 2026-08-09

Expand Down
Loading