6 Commits

Author SHA1 Message Date
cesnimda ce76046a29 feat: complete release readiness work
- 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
2026-07-31 16:54:16 +02:00
cesnimda 93462b799c chore(ops): add deployment backups restore docs and health checks
CI and Deploy / test (push) Failing after 1m8s
CI and Deploy / deploy (push) Has been skipped
Closes the three operational blockers from the production readiness review.

deploy.sh now takes a database backup before it builds, stops or replaces
anything, and aborts the deploy if the backup fails — so no deploy proceeds
without a restore point. Dumps are gzipped and timestamped into
/opt/job-tracker/backups (override with BACKUP_DIR), so one deploy never
overwrites an earlier backup. Credentials come from the existing connection
string and travel via MYSQL_PWD, never on the command line, so they cannot reach
the process list or the deploy log. A dump that is empty or missing CREATE TABLE
is rejected, because a truncated file that looks like a restore point is worse
than none. SQLite deployments get their data volume tarred instead. Nothing is
ever deleted automatically; retention is documented as manual.

deploy/README.md documents backup creation, location, retention, database
restore, application rollback, and when to use which — restore and rollback kept
distinct, because a bad deploy usually needs only the rollback and restoring
would discard everything written since the dump.

Health checks now cover backend and frontend, which previously had none. GET
/health is anonymous, cheap, and deliberately does not touch the database: a
health check that queried MariaDB would restart a healthy backend whenever the
database blipped, and would hand out an unauthenticated way to probe database
availability. The backend image gains curl on the existing chromium apt layer,
since the aspnet runtime ships neither curl nor wget. frontend now waits for
backend to be healthy rather than merely started, because nginx proxies /api and
refuses to start when the upstream cannot be resolved.

Verified against real containers, no production data: backup from a seeded
MariaDB 11; restore into a clean MariaDB 11 with rows identical; bad credentials
and a missing connection string both abort non-zero and leave no partial file;
SQLite volume backup produces a readable archive; backend and frontend both
reach healthy; and a backend pointed at an unreachable database exits and is
reported unhealthy, so a broken deploy cannot present as a running stack.

Incidentally confirmed the earlier authorization work: with Auth:Require unset,
/health returns 200 while /api/jobapplications returns 401.

393 backend tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 17:49:31 +02:00
cesnimda 63e0300788 fix(deploy): retry publish after clearing NuGet caches on NU3008
CI and Deploy / test (pull_request) Failing after 2m9s
CI and Deploy / deploy (pull_request) Has been skipped
The prod deploy failed restoring a transitive package
(Microsoft.CodeAnalysis.Workspaces.Common) with NU3008 "package integrity check
failed / has changed since it was signed" — a transient corrupted download on the
build host, not a code change. Wrap the backend `dotnet publish` so that on any
failure it clears all NuGet caches and retries once, re-downloading the package
fresh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 21:51:29 +02:00
cesnimda b52371ea79 Fix backend deployment Playwright restore issue 2026-04-11 17:45:51 +02:00
cesnimda 7b9a97323e Fix backend Docker publish context 2026-04-02 12:49:49 +02:00
cesnimda 2e8a29b4d0 First Commit 2026-03-21 11:55:27 +01:00