ce76046a29
- consolidate API ownership and remove dead vendor code - add Stripe billing, learning paths, and public CV hardening - add migration, recovery, security, audit, and browser gates
86 lines
6.0 KiB
Markdown
86 lines
6.0 KiB
Markdown
# Release checklist
|
|
|
|
> **Historical snapshot (2026-07-19).** The current release gate and external dependencies are
|
|
> documented in `.gitea/workflows/ci-deploy.yml`, `docs/implementation-roadmap.md`, and `BLOCKERS.md`.
|
|
|
|
> 2026-07-19. State of the build before the first production deployment after the Phase 4/5
|
|
> architecture changes. Companion to `deploy/first-production-deployment.md` (how to deploy),
|
|
> `docs/production-readiness-review.md` (what was audited) and
|
|
> `docs/phase-5-completion-report.md` (what was built and why).
|
|
|
|
## Completed architecture work
|
|
|
|
| Area | State |
|
|
|---|---|
|
|
| **Career Profile** | Single source of truth. Relational children with stable item keys; `ProfileJson` is a derived projection. Nothing downstream writes to it. |
|
|
| **CV Builder** | Data-driven theme engine — themes are data, not hardcoded templates. Eight themes; adding one is appending an object. Variants are lenses over the master profile, never copies. Autosave, version history, restore. |
|
|
| **Public CV** | `/cv/{slug}`, off by default, per-variant opt-in, unguessable slug, `noindex`. SPA deep-link routing fixed so direct navigation, refresh and shared links resolve. |
|
|
| **Application Workspace** | `/applications/{id}`: Overview, Checklist, Timeline, Analysis, Match, CV, Cover Letter, Documents, Interview Prep, Communication. Owns almost no data — it composes systems that already existed. |
|
|
| **AI integrations** | Suggestion-only. Every generation appends to `AiInteraction` (that history *is* the versioning). Interview generation now receives the analysis and match context. Nothing AI-driven writes to the profile, a variant, a cover letter or prep content without the user saving it. |
|
|
| **Interview preparation** | User-owned `InterviewPrepItem`, distinct from the two AI *caches* that regenerate. Six categories in one table. |
|
|
| **Production hardening** | Explicit `[Authorize]` on every controller with a reflection test; clean MariaDB initialization; database ownership documented; pre-deploy backups; restore and rollback docs; health checks on backend and frontend. |
|
|
|
|
## Local verification
|
|
|
|
| Check | Result |
|
|
|---|---|
|
|
| Backend tests (Release) | 393 passed |
|
|
| Frontend tests | 128 passed, 36 suites |
|
|
| TypeScript | clean |
|
|
| Frontend production build | clean |
|
|
| Docker images | backend and frontend build |
|
|
| Fresh empty MariaDB 11 | 42 tables, starts healthy |
|
|
| Populated MariaDB restart | idempotent, rows preserved |
|
|
| Existing SQLite dev database | upgraded 34 → 44 tables, rows preserved |
|
|
| Backup and restore | dump verified, restored into a clean database, rows identical |
|
|
|
|
## Unresolved external blocker
|
|
|
|
### CI runner — deployment is gated on this
|
|
|
|
CI is red for a reason **proven to be outside the repository**: commit `8f73548` changed a single
|
|
markdown file — no code, no test, no dependency, no workflow — and its test job failed in the same
|
|
duration band as every other run. A change that cannot affect compilation cannot fail a test job.
|
|
|
|
Consequence: **everything above is local verification.** Nothing has been proven in CI, and the
|
|
deployment pipeline will not promote a build until this is fixed.
|
|
|
|
Blocked on, and needing you:
|
|
|
|
- Job logs — the API returns 401 unauthenticated; a read-scoped Gitea token would unblock this
|
|
- `journalctl -u act_runner --since '2 hours ago'` on the runner host
|
|
- The act_runner container/service configuration
|
|
|
|
Full evidence: `docs/infrastructure/runner-investigation.md`.
|
|
|
|
## Known risks
|
|
|
|
| Risk | Severity | Notes |
|
|
|---|---|---|
|
|
| Production is many commits behind | High | The first deploy applies the whole Phase 4/5 change at once. Reconciler builds ~12 tables against real data for the first time. |
|
|
| Reconciler path unproven on your data | Medium | Verified on containers and on a real SQLite dev database — not on production. This is what the backup is for. |
|
|
| Production journey unwalked | Medium | The CI-gated local browser suite covers login, saved-job creation, Career Workspace, and public CV/PDF. The same authenticated and OAuth checks still require production credentials. |
|
|
| Rollback loses new-table data | Medium | A code rollback keeps everything. A *database restore* discards rows created since the dump. Keep the deploy window quiet. |
|
|
| Logging is structured JSON on stdout | Low | Compose retains three 10 MB files per service; aggregation remains deployment-owned. |
|
|
| No global exception handler | Low | Unhandled errors return a bare 500 with no correlation id. No stack leaks outside Development. |
|
|
| `ClientErrorsController` is anonymous | Low | By design — browser error reports must work before sign-in. Size-limited and truncated; stores nothing. |
|
|
| Prompt quality unmeasured | Low | Interview generation gets richer context; whether the questions are *better* is a judgement no test makes. |
|
|
|
|
## First deployment warnings
|
|
|
|
1. **Take a manual backup as well, and restore it once to a scratch database.** `deploy.sh` backs up
|
|
automatically, but the first deploy is the wrong time to discover a backup does not restore.
|
|
2. **Watch `docker compose logs -f backend` live.** `Database.Migrate()` throws on failure, so a schema
|
|
problem exits the container. The runbook lists the exact log lines that mean stop.
|
|
3. **`DATABASE_PROVIDER` defaults to `sqlite`.** If it goes missing from `.env`, the backend does not
|
|
quietly serve an empty database — it crashes with `no such table: INFORMATION_SCHEMA.TABLES`.
|
|
Loud, but confusing if you have not seen it before.
|
|
4. **The connection string resolves from inside the container.** `Server=127.0.0.1` means the backend
|
|
container, not the host.
|
|
5. **Empty new sections are expected.** Existing applications will show an empty Checklist, Timeline
|
|
and Interview Prep until used. The checklist seeds on first open. That is correct behaviour.
|
|
6. **Verify row counts before walking away.** Applications and companies must match the pre-deploy
|
|
numbers. This is the check that matters most.
|
|
7. **Do not restore the database for a code problem.** Roll the code back first; it is almost always
|
|
the whole fix, and it costs no data.
|