Operational Status & Gates
Two operational facts cut across every chapter and every pull request. So they don’t drift out of sync, they live here once — the other chapters link back rather than restating them.
CI gates — active on every push and PR
Section titled “CI gates — active on every push and PR”.github/workflows/ci.yml runs on every push to main and every pull request. It is the merge gate. Cloudflare Workers Builds deploys the worker independently on each push to main.
The jobs:
| Job | What it gates |
|---|---|
| typecheck / unit tests | pnpm --filter @brightblur/web check then test:unit. Lint, Knip and pnpm audit also run here but non-blocking (continue-on-error) — they surface backlogs (bri-284a lint, bri-edf9 dead code, bri-60d5 advisories) without gating merges. |
| mobile typecheck | tsc --noEmit across apps/mobile — the native app can no longer merge ungated. |
| build | The Cloudflare adapter build, model-checksum verification, and the scheduled-handler injection (bri-20cf) — all of which previously only failed at deploy time. |
| apply D1 migrations (production) | On push to main only, after verify + build are green: applies any pending migrations to production D1 (db:migrate:remote). Idempotent — prints “No migrations to apply!” and exits 0 when there’s nothing pending. |
Production dependency-audit residuals
Section titled “Production dependency-audit residuals”The 2026-07-13 dependency refresh reduced pnpm audit --prod from 18 findings
(8 high, 6 moderate, 4 low) to three findings (0 high, 2 moderate, 1 low). The
remaining packages cannot be upgraded through their parents’ supported version
ranges. They are retained without pnpm overrides for the following concrete
reasons:
| Advisory | Dependency path | Reachability and disposition |
|---|---|---|
GHSA-pxg6-pf52-xh8x (cookie 0.6.0, low) |
bits-ui → runed → @sveltejs/kit → cookie |
The flaw requires an attacker-controlled cookie name, path, or domain. Every BrightBlur cookies.set/cookies.delete call uses a source constant or literal for those fields; request data is used only as a cookie value. SvelteKit 2.69.2 still declares cookie@^0.6.0, so forcing 0.7 would cross its declared 0.x range. Track the SvelteKit parent instead. |
GHSA-qx2v-qp2m-jg93 (postcss 8.4.49, moderate) |
expo → @expo/metro-config → postcss |
This is native-app build tooling, not shipped runtime code. Exploitation requires attacker-controlled CSS to be stringified into an HTML <style> context; the mobile workspace has no CSS/PostCSS configuration or user-CSS input. Expo SDK 54 pins postcss@~8.4.32, so 8.5.10 is outside its supported range. Upgrade with a future Expo SDK rather than overriding Metro’s pin. |
GHSA-w5hq-g745-h8pq (uuid 7.0.3, moderate) |
expo → @expo/config-plugins → xcode → uuid |
This is iOS project-generation tooling, not shipped runtime code. The advisory affects the v3, v5, and v6 output-buffer APIs; xcode@3.0.1 calls only uuid.v4() and supplies no external output buffer. Its declared range is uuid@^7.0.3; forcing the patched 11.x major would be unsupported. Track the Expo/xcode parent instead. |
Re-run pnpm audit --prod on dependency changes. Any new finding, any high or
critical finding, or a changed path/usage that invalidates the reachability
analysis above must be investigated rather than accepted under this note.
The migration race still needs care
Section titled “The migration race still needs care”The migrate-prod job and Workers Builds start on the same push, in parallel. So a merge deploys code and applies schema roughly together, not in a guaranteed order:
-
Additive migrations (
CREATE TABLE,ADD COLUMN … NULL) are safe — new code may briefly see a missing table, then succeeds once migrations finish moments later. -
Destructive or required-
NOT NULLchanges are not safe to race. Apply them manually before merging:Terminal window cd apps/web && pnpm db:migrate:remotewrangler d1 migrations list brightblur --remote --env production # verify
Prefer additive migrations that an already-deployed older schema can tolerate — deploys are code-then-schema, the reverse of the safe expand/contract order.
The TFLite e2e gate — standing
Section titled “The TFLite e2e gate — standing”Permanent. This gate lives outside CI: the heavy upload e2e isn’t in the pipeline yet, so it’s on you to run it when the runtime changes.
Any change to apps/web/src/lib/image/tflite-runtime.ts or the worker bootstrap must be validated with the heavy upload e2e against a production build:
cd apps/web && pnpm build && npx playwright test upload.test.ts --project=chromium-heavypnpm check and pnpm test:unit cannot catch a regression here: the importScripts polyfill branch is unreachable from Vitest by design (an XMLHttpRequest guard keeps it off Node). This is how the June 2026 _malloc incident reached production. Recognition explains what the polyfill does; Conventions has the e2e harness prerequisites — the .dev.vars flags, port 4173, and the local db:migrate.