# Blockers

Updated: 2026-08-31

## Stripe billing

- **Blocked:** Activating roadmap item 7.5 in production.
- **Why:** Hosted Checkout, customer-portal sessions, signed subscription webhooks, persisted billing state, Pro-role provisioning and a mock lifecycle regression are implemented. The Stripe recurring price, portal, webhook registration and production credentials must be configured outside the repository.
- **Required:** Configure the Pro recurring price, enable the Stripe customer portal, register `/api/billing/webhook` for `customer.subscription.created`, `customer.subscription.updated`, and `customer.subscription.deleted`, then supply `STRIPE_SECRET_KEY`, the recurring `price_...` value in the legacy-named `STRIPE_PRICE_PREMIUM` setting, and `STRIPE_WEBHOOK_SECRET` through the deployment environment. Do not place secret values in source control or chat.
- **Recommended:** One monthly Pro price first; add annual billing only after the monthly flow is operating.
- **Current access check:** Production has test-mode secret and webhook values, but `STRIPE_PRICE_PREMIUM` currently contains a `prod_...` Product ID. Checkout requires the recurring `price_...` Price ID; the server now treats the wrong identifier type as disabled rather than calling Stripe. The publishable key is not used by hosted Checkout. Local fake-gateway coverage proves active → expired → canceled/replayed role transitions without losing non-AI data (V-185).
- **Runbook:** Follow `docs/operations/stripe-activation.md`, completing test mode before creating or installing live-mode values.

## Public registration verification

- **Blocked:** Completing a real-browser production signup check.
- **Why:** The 2026-07-31 anonymous production check confirms `allowRegistration=true`, `turnstileEnabled=true`, and Google sign-in enabled. Completing Turnstile and creating a disposable account requires an interactive production browser session.
- **Required:** Register one disposable account through Turnstile, verify email/sign-in/rate-limit behavior, then remove the account if it is not needed.
- **Recommended:** Monitor Turnstile and rate-limit failures during the first public rollout; keep email verification required.
- **Current status:** Production returns `allowRegistration=true`, `turnstileEnabled=true`, `googleEnabled=true`, and `microsoftEnabled=false`. A registration request without a Turnstile token is rejected with HTTP 400. SMTP is configured and enabled. The operator reports `AUTH_REQUIRE_EMAIL_VERIFICATION` is now enabled; the disposable interactive signup is still required to prove the deployed behavior end to end.

## Production verification and deployment

- **Blocked:** Authenticated production smoke tests, backup restore verification against real data, OAuth-provider checks, and deployment.
- **Why:** Read-only host access is available, but authenticated smoke, port/network closure, complete backup restore, provider checks and deployment require credentials and/or operator-authorized production mutations.
- **Required:** After the current pull request passes CI and is approved, follow `docs/release-candidate-review.md` and `docs/release-checklist.md` on the production host. Confirm the admin-only version badge matches the deployed commit, then run the authenticated application workspace, Career, CV, attachment, email-verification and rollback checks.
- **Recommended:** Verify backup/restore before deployment, then exercise login, existing application counts, Career Workspace, public CV refresh/download, AI, and attachments in order.
- **Current access check:** Read-only SSH access is confirmed. All four JobTracker containers are healthy with zero observed restarts, but root free space is now 36 GiB (83% used). The production checkout is at `de937d25dc5e` / app version `157` and has an unreviewed mode-only change to `deploy/deploy.sh`. No production change or deployment was attempted.
- **Current status:** On 2026-08-31 the anonymous public liveness endpoint `https://jobs.cesnimda.uk/health` returned HTTP 200 with version `276`, and the Gitea host returned HTTP 200; the earlier public 502 is no longer present. Anonymous `https://jobs.cesnimda.uk/api/health` returned HTTP 401 as expected for an authenticated API route. This proves the proxy/frontend liveness path only, not authenticated application behavior or database readiness. Gitea run 696 failed after repeated truncated Playwright downloads and then a runner-level exit 139 before any test assertion; the workflow now installs through the lockfile CLI and retries only that transient process failure without hiding real test failures. Current remote CI, backup/restore, authenticated smoke and rollback still require operator-controlled environments. Read-only PROD-001 inventory found the JobTracker Ollama and frontend published on all host interfaces, the newest gzip-valid MariaDB backup dated 2026-08-02, no observed scheduled JobTracker backup, and no owner-file/key/tombstone recovery bundle. Close these rollout gates before deployment; see `docs/production/production-ai-hardware-assessment.md`.

## Account deletion retention and restore policy

- **Blocked:** Enabling SEC-009 self-service deletion in production and declaring backup erasure complete.
- **Why:** The readable export and idempotent live-data deletion coordinator are implemented behind an explicit disabled gate. Repository code cannot truthfully choose legal retention periods, backup expiry, provider obligations or the tombstone lifetime needed to prevent restoration from resurrecting an erased account. Production inventory confirms current backups are database-only and no protected tombstone volume is deployed yet; the release branch now defines the separate volume and retryable authenticated sidecar-cache purge.
- **Required:** Decide retention periods for operational backups, audit/security records and deletion tombstones; identify any legal hold/export obligations; approve the restore behavior for deleted identities.
- **Recommended:** Keep production self-service and admin deletion disabled. Decide retention, deploy/protect the configured tombstone volume, build a complete DB/files/keys backup set, then use a disposable account to prove remote-provider cleanup, sidecar purge across restart and restored-backup tombstone replay before staged activation.

## Legacy job/application column cutover

- **Blocked:** Removing the opportunity columns duplicated between `JobApplication` and `Job`.
- **Why:** The compatibility dual-write protects existing production rows and older clients. The release branch now backfills missing opportunities on startup, synchronizes both creation paths, and leaves all legacy columns intact. Dropping columns still requires production validation and an observation release.
- **Required:** After deployment, run the read-only report in `docs/operations/job-opportunity-cutover.md` against production and a restored backup, then confirm that backward API compatibility is no longer required.
- **Recommended:** Use an expand/contract release: first stop legacy reads after a verified backfill, observe one release, then drop the duplicate columns in the following migration.
