Files
HiveGrid-Wireframes/hivegrid-cloud/docs/improvement-plan/OPERATOR-CHECKLIST.md
T

16 KiB
Raw Blame History

OPERATOR-CHECKLIST

READINESS_AUTHORITY: authoritative operator readiness checklist. This is the canonical readiness source for operator-pending actions, live env flips, and deploy/operator closeout. Historical phase trackers such as docs/improvement-plan/PROGRESS.md and unresolved-risk registers such as docs/improvement-plan/BLOCKERS.md are supporting inputs only.

Living master list of all operator-pending actions across the project. Aggregates the "code-complete, X-pending" caveats from PROGRESS.md, the open items in BLOCKERS.md, and the Deviations sections of individual phase-docs.

Last regenerated: 2026-05-29 (operator/live-state reconciliation; B-008 closed, B-012 tracked only as operator-owned hardening risk).

Re-generate by walking every "in_progress (… pending)" row in PROGRESS.md + every ## Active Blockers and ## Unresolved Risks entry in BLOCKERS.md + verifying against the live Coolify-API state. Each row carries:

  • WHAT — the operator-side action
  • WHY — what's blocked / what flips to green when done
  • TIME — wall-clock estimate
  • BLOCKS — the affected task IDs

Bucket snapshot

Bucket Open Closed / parked Next action
A — Quick wins 2 10 A6 + A9 after Stripe Meter exists; A7/#51 is backlogged, not an active CDN item
B — Medium 4 4 B1 Stripe Meter, B4 Lighthouse login secrets, B6 canonical native Capacitor regeneration, or B8 runner Docker address-pool hardening
C — Long-running 3 0 External procurement / app-store / Authentik production migration
D — Polish sprints 7 3 #19/D7, TOTP/D8, and #76/D3 are closed; remaining work is code sprint backlog

A — Quick wins (5–15 min each, mostly Coolify env-flips)

These are env-var changes via the Coolify UI or coolify env-update API. No new infrastructure required. Each one moves a task from in_progress (code-complete, env-flip-pending) → completed.

Status 2026-05-28: Live verification showed most A-items are already flipped. Rows marked ✅ are verified live; rows marked ⏳ remain open; rows marked 🅿 are intentionally parked/backlogged and not active operator work. B-008 is closed; B-012 is mitigated today and remains only as operator-owned Docker address-pool hardening.

# Action Status Why Time Blocks
A1 Set METRICS_TOKEN + METRICS_ENABLED=true on web/api/worker ✅ live (/metrics 200) Activates /metrics endpoints → Grafana dashboards stop showing "no data" — #35
A2 Set OTEL_EXPORTER_OTLP_ENDPOINT=https://sentry.boiler.saas-ctrl.com/api/<project>/integration/otlp per app (api=2, worker=3, web=4) ✅ live; per-project paths corrected and api/worker restarted, browser endpoint delivered via A11 Traces start flowing into Sentry; closes B-005 last-mile — #33
A3 Set MEILI_URL=http://boilerplate-meilisearch:7700 + MEILI_MASTER_KEY on web/api/worker ✅ live Activates FTS hot-paths (CRM contacts + rows search) — was silent SQL fallback — #48
A4 Set DATABASE_URL on web/api/worker to pgbouncer pool ✅ live (DATABASE_URL via pgbouncer, DIRECT_URL to raw pg) Pool pressure removed from primary; #40 closed — #40
A5 Set SENTRY_AUTH_TOKEN Gitea Actions secret + Coolify env ✅ live on web/api plus worker-group apps using the worker DSN/env convention; Gitea secret set Enables sourcemap upload + release-finalize in CI; closes #32 smoke gap — #32
A6 Set Stripe-Meter aiOverageStripeMeterId on first overage-enabled tenant + optional STRIPE_AI_OVERAGE_METER_EVENT_NAME=ai-overage env if deviating from the default ⏳ pending (blocked on B1) Activates Phase-3 Stripe overage reporter cron once worker bootstrap registers runAICostStripeReportCron 10 min #54 follow-up
A7 CDN env flip (ASSET_CDN_URL + provider secret) 🅿 backlogged with #51 — no active CDN rollout. Origin in Nürnberg + DACH audience + existing Cloudflare proxy is enough until international latency, large media traffic, or origin bandwidth pressure appears. Would enable CDN serving for built assets if #51 is reactivated — #51
A8 Set Authentik OIDC client envs on web ✅ live as AUTHENTIK_ISSUER_URL + AUTHENTIK_ADMIN_{CLIENT_ID,CLIENT_SECRET,REDIRECT_URI} — note: the original deploy on 2026-05-18 set them as OIDC_AUTHENTIK_* which is the WRONG namespace (code reads AUTHENTIK_ADMIN_* per apps/web/app/modules/admin-sso/client.server.ts:38-49). Corrected on 2026-05-19 via Coolify-API POST + DELETE of the 8 dead OIDC_AUTHENTIK_* rows. Smoke: /auth/admin/login 302s to Authentik with full PKCE/state/nonce chain. Unblocks Authentik admin SSO login — #81, #82
A9 Set AI_OVERAGE_SUBMISSION_ENABLED=true on worker container ⏳ pending (paired with A6) Enables Stripe-Meter overage reporter cron once tenants are configured 2 min #54 follow-up
A10 Flip worker SENTRY_DSN + restart worker container ✅ live as per-app DSN: SENTRY_DSN_API, SENTRY_DSN_WEB, SENTRY_DSN_WORKER (code reads these per apps/web/app/sentry.server.ts:48); apps/api/src/sentry.ts and apps/worker/src/sentry.ts mirror the convention Activates Sentry capture; closes #30 staging-smoke — #30
A11 Browser-side Sentry + OTel — VITE_* build-arg wiring ✅ live — Dockerfile patch (commit 8ca98efb) + deploy.yml --build-arg (commit 218e5bd4) + Gitea repo secrets VITE_SENTRY_DSN_WEB / VITE_SENTRY_ENVIRONMENT / VITE_OTEL_EXPORTER_OTLP_ENDPOINT. Bundle verification on the redeployed image shows DSN-hash 1d3d4089 and OTel endpoint /api/4/integration/otlp inlined into entry.client-zyydvz2o.js. Coolify build_pack is dockerimage (not Dockerfile), so VITE_* must be passed at CI build time, not via Coolify env-flips. — #30 (web), #33 (browser-OTel)
A12 Restart api+worker containers to pick up corrected OTEL endpoint values ✅ done 2026-05-19 — explicit redeploys triggered via Coolify /api/v1/deploy?uuid=…; verified inside running containers: worker OTEL_EXPORTER_OTLP_ENDPOINT=https://sentry.boiler.saas-ctrl.com/api/3/integration/otlp, api still /api/2/integration/otlp, web /api/4/integration/otlp. per-project Sentry routing now correct — #33

B — Medium (1–2 hrs each, requires external setup but bounded)

# Action Why Time Blocks
B1 Stripe Meter setup (production) — in Stripe Dashboard create a Meter named ai_overage_cents, event name ai-overage, default aggregation sum, customer mapping by stripe_customer_id. Document the meter ID in docs/ops/stripe-meters-migration.md. Then set the default through /admin/settings/pricing/ai-overage or, for tenant overrides, merge { "aiOverageStripeMeterId": "<meter id>" } into Tenant.aiQuotaOverrideJson; do not reference retired subscription-item fields. Required by Stripe SDK 19 — legacy subscriptionItems.createUsageRecord API was removed; without the meter the overage reporter throws on every call 1 hr #28 follow-up, #54
B2 CDN pull-zone provisioning 🅿 backlogged with #51; not active operator work until CDN is reactivated — #51
B3 First bcrypt-user login on staging — completed 2026-05-24; login as the staging admin rehashed the legacy bcrypt hash to argon2 and verified the #28 dual-mode path #28 closeout done done none
B4 Lighthouse-CI session cookie rotation — code prep is committed: .github/.gitea Lighthouse workflows run scripts/rotate-lighthouse-session-cookie.mjs before LHCI and fall back to the existing LIGHTHOUSE_SESSION_COOKIE during rollout. Operator remaining: set repo Actions secrets LIGHTHOUSE_LOGIN_EMAIL and LIGHTHOUSE_LOGIN_PASSWORD from ~/.cli-tokens/lighthouse-bot-staging, then trigger lighthouse.yml manually and confirm the log says Minted Lighthouse session cookie RJ_session. Local API write could not be completed from this machine because git.tool-ctrl.de HTTPS/SSH timed out. Lighthouse-CI mints a fresh cookie per run instead of depending on session TTL 10 min #75 hardening
B5 Coolify disk-pressure alert (B-008) — completed 2026-05-24; Coolify Discord webhook activated and disk trigger enabled B-008 prevention done done none
B6 Capacitor native builds — run npx cap add ios && npx cap add android from a Mac with Xcode + Android Studio installed, then commit the platform-specific files Required before mobile binaries can be built; staging dev-server already works 2 hr #65
B7 Tenant-snapshot staging verification — completed 2026-05-25; staging real-tenant snapshot was verified, the User-global restore gap was closed by Task G, and round-trip restore into fresh pgvector DBs passed 365/365 tests #44 closeout done done none
B8 Gitea runner Docker address-pool hardening — B-012 is mitigated today, but the permanent fix is still operator-owned: enlarge Docker default-address-pools on homeserver and add a prune cron for orphaned GITEA-ACTIONS-TASK-* networks Prevents future CI/deploy outages from Docker network exhaustion; not an active code closeout blocker 30 min + maintenance window CI/deploy reliability

C — Long-running (multi-day external dependencies)

# Action Why Time Blocks
C1 B-006 — External WASM-sandbox security review (audit-ready 2026-05-19) — RFP, vendor decision matrix (top pick: Cure53), threat-model, attack-surface, internal-findings + audit-package script all landed. Operator next step: (1) run scripts/build-plugin-audit-package.sh from repo root; (2) email the resulting artifacts/plugin-audit/<date>/*.tar.gz to Cure53 per docs/security/plugin-audit-rfp.md § 9 (alternates: Trail of Bits / NCC Group / SySS / secfault). 3–5 day pen-test + report, ~15–25 k EUR. After report receipt: file findings under docs/improvement-plan/06-plugin-system/security-findings/F-NNN-….md, fix Critical/High, request re-test, sign off via docs/security/plugin-runtime-signoff.md. Resolved internally during audit-readiness prep: F-015 Critical (worker bootstrap unwired) closed by commit cbac8d3d — handlers.ts now dispatches to handlePluginInvokeJob and fails-loud if pluginInvokeDeps is missing. F-005 Phase A + Phase B closed — install path rejects publisher keys outside PLUGIN_TRUSTED_PUBLIC_KEYS, signedBy/key mismatches, missing binaries, and verifyPluginSignature failures before creating the Plugin row. F-010 + F-017 closed by the self-audit pass. Required before Phase 06 production rollout (staging unblocked) 2–4 wk wall-time Phase 06 prod-rollout
C2 Mobile App Store submission — Apple Developer Program account ($99/yr), Google Play Console ($25 one-time). App Store screenshots, privacy nutrition labels, content rating, age gates. iOS TestFlight + Play Console internal-test track first Required to ship the Capacitor app to end users 1–2 wk (mostly waiting on Apple review) #65 closeout
C3 Authentik production migration — current Authentik runs on staging compose. Operator must promote to a dedicated host (Coolify or separate VPS), regenerate secrets, run blueprints, migrate the Toolctrl Groups/Policies/Admin Panel OIDC config Required before #81/#82 can flip from in_progress → completed for prod 3–5 days #81, #82 prod

D — Polish-sprints (own-able multi-day code work, separate from prod-deploy items)

These are explicitly "deferred sub-sprints" — code-complete enough to unblock dependent work but with a follow-up sprint scoped.

# Action Why Time Blocks
D1 #72 i18n migration sprint — hardcoded UI/response extraction floor is now 0/0/0 (jsx-text, user-facing-prop-literal, user-facing-response-literal). Remaining work is the larger namespace split, locale breadth, and Playwright locale-switch proof. pnpm run verify:hardcoded-strings is clean; #72 closeout still needs the legacy translations.json split, additional locale namespaces/coverage, and an approved staging E2E locale flow. 2–4 days #72 closeout
D2 #73 WCAG audit fix-sprint — work through packages/ui-app/test-setup/axe.ts violation backlog. Currently infrastructure-shipped, fix-sprint deferred A11y compliance bar 5–7 days #73 closeout
D3 #76 test-coverage sprint — completed 2026-05-29. pnpm run verify:test-coverage passes with the current per-module gates, and docs/testing/coverage-sprint-backlog.md has no positive sprint-gap rows. Future work is gate maintenance and opportunistic ratcheting, not #76 closeout. Coverage observability + regression guard done none
D4 Phase-06 plugin extraction sprint — foundation + audit-readiness shipped. Settings iframe/CSP/postMessage foundation is shipped; remaining deferred: marketplace, hot-reload, output-hooks, 13 more hook-points, global crash-counter, and external-audit follow-up after C1. Closed internal findings F-005, F-010, F-015, and F-017 are not remaining sprint work; see C1 and docs/security/plugin-internal-findings.md for the historical finding record. Plugin ecosystem features 2–3 wk #59 closeout
D5 Phase-08 Storybook a11y/visual-regression — 21/20 stories shipped, a11y/visual-regression/test-runner deferred Storybook coverage matrix 1 wk #67/#68/#69 closeout
D6 AV-Layer1 + AV-Layer2 sprints — staging-deployed, no-upload-yet (#16) + core-complete (#17). Need first real upload to verify EICAR detection end-to-end + container scanner E2E test Validates AV pipeline against live traffic 1–2 wk #16, #17 closeout
D7 Magic-link reset mail worker — completed 2026-05-25. B-014 resolved by persistent Coolify worker applications for general, mail, import, webhook, and plugin; mail drains toolctrl.email without manual one-off containers #19 closed done none
D8 TOTP live MFA E2E — completed 2026-05-24: enrollment, TOTP challenge, recovery-code challenge, and disable cleanup passed on staging #26 closed done none
D9 Subscription-cache + idempotency + session migration — 5 of 6 stores migrated to shared-store (#38); session migration is deferred, and MCP remains load-balancer/config work rather than an app-store migration. #38 closeout 1 wk #38
D10 AI-cost call-site sweep beyond core 3 — chatbot is already wired; any new model invocations should pick up costContext proactively Coverage of the AI-cost outbox 2–3 days follow-up

Re-generation procedure

# 1. Re-count PROGRESS.md statuses
grep '^| ' docs/improvement-plan/PROGRESS.md \
  | awk -F'|' '{gsub(/^ *| *$/, "", $4); print $4}' \
  | grep -v '^Status' \
  | awk '
      BEGIN { c = ip = p = bl = 0 }
      /^completed/ { c++ }
      /^in_progress/ { ip++ }
      /^pending/ { p++ }
      /^backlog/ { bl++ }
      END { print "completed="c, "in_progress="ip, "pending="p, "backlog="bl }
    '

# 2. Extract operator-pending caveats
grep -oE 'in_progress \([^)]*pending[^)]*\)' docs/improvement-plan/PROGRESS.md \
  | sort -u

# 3. List active blockers and unresolved risks
sed -n '/^## Active Blockers/,/^## Resolved/p' docs/improvement-plan/BLOCKERS.md \
  | grep -E '^### B-'

When all active items in sections A + B clear, core non-plugin deploy/operator readiness is green. Parked CDN rows A7/B2/#51 are deliberate backlog and must not be counted as completed CDN rollout. B-008 is already closed by operator disk-pressure alerting, while B-012 remains operator-owned runner host hardening rather than code work. Section C still contains production-rollout gates with external dependencies, including third-party plugin execution signoff; release readiness must also be checked against docs/production-checklist.md. Section D remains an engineering backlog that no longer contains the Magic-Link mail-worker blocker.