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
This commit is contained in:
cesnimda
2026-07-31 16:54:16 +02:00
parent a23c3dfc97
commit ce76046a29
1634 changed files with 6889 additions and 135429 deletions
+37 -42
View File
@@ -1,6 +1,6 @@
# Jobjakt — Implementation Roadmap
Date: 2026-07-17 · **Updated after Phase 0** (see `docs/phase-0-foundation-report.md`)
Date: 2026-07-31 · **Reconciled after the technical-debt pass**
Companion to `docs/application-discovery-report.md`. Every task below traces to a verified finding there.
> **Phase 0 is complete.** Architecture docs restored, **AI sidecar locked down to backend-only and verified live**, pipeline expanded beyond `Applied` (10 stages, 3 board groups), `Job` entity introduced. Phase 1 below has been re-scoped against the *actual* architecture rather than the assumptions the original plan carried. Product decisions from 2026-07-17 are folded in throughout.
@@ -17,7 +17,7 @@ Companion to `docs/application-discovery-report.md`. Every task below traces to
Priority: `P0` blocker · `P1` high · `P2` medium · `P3` later
Difficulty: `XS` <½day · `S` ~1day · `M` 24days · `L` ~12wk · `XL` 2wk+
**Ordering principle:** the guide names "Excellent Job Tracking" and "Excellent Application Workflow" as goals #1 and #2. Phase 1 exists because the data model currently cannot represent goal #2 at all. Nothing in Phases 37 is worth building before that is true.
**Current state:** Phases 07 are repository-complete. Opening registration, activating Stripe, and deploying the release require operator configuration/access. See `BLOCKERS.md`.
---
@@ -29,7 +29,7 @@ Original tasks 1.1, 1.2, 1.3 (backend half), 1.5, 1.7, 1.8, 1.9, 1.10 are comple
---
## Phase 1 — Critical fixes (re-scoped after Phase 0)
## Phase 1 — Critical fixes ✅ CODE COMPLETE
Goal: finish surfacing the pre-application workflow in the UI, and close the security findings that need an operator.
@@ -42,8 +42,8 @@ Goal: finish surfacing the pre-application workflow in the UI, and close the sec
| 1.5 | ✅ **DONE (2026-07-30)** — startup rejects wildcard CORS origins when credentialed requests are enabled. | **P1** | **XS** | none | Unsafe configuration now fails closed. |
| 1.6 | ✅ **DONE** — the dead `careerView` prop/tab is gone; the implemented CV Builder has its own routed workspace. | **P1** | **XS** | none | No dead navigation remains. |
| 1.7 | ✅ **DONE** — onboarding reads structured career-profile collections with raw CV text only as fallback. | **P2** | **XS** | none | Parsed profiles are recognized correctly. |
| 1.8 | ✅ **DONE** — full frontend suite is green (142 tests on 2026-07-30). | **P1** | **S** | none | CI has a clean regression baseline. |
| 1.9 | **Decide what to do with the `feature/career-workspace` branch.***Investigated 2026-07-17 — see below.* The orphan tables are not an abandoned prototype: they are the local footprint of **10 unmerged commits** (local + `origin`, last touched 2026-07-12) containing working, tested code and 1,100 lines of research/strategy. All 7 tables are **empty** in dev, so there is no data to migrate. Branch is **29 commits behind main**. | **P0** | **M** | none | **Blocks Phases 3 and 4 from being planned honestly.** Re-deriving this work would waste weeks; ignoring it leaves a rebase debt that grows every day main moves. See `docs/career-workspace-branch-assessment.md`. |
| 1.8 | ✅ **DONE** — full frontend suite is green (145 tests on 2026-07-31). | **P1** | **S** | none | CI has a clean regression baseline. |
| 1.9 | **DONE** — the useful Career Workspace design/code was recovered and superseded by the completed Phase 3/4 implementation. The old branch is historical and is not a merge target. | **P0** | **M** | none | No longer blocks later phases. See `docs/career-workspace-branch-assessment.md` for the original assessment. |
| 1.10 | ✅ **DONE (2026-07-30)** — restored EF identity metadata for the two orphan migrations as safe no-op history markers and brought the development database fully current. | **P2** | **S** | none | The idempotent reconciler remains the schema owner for those legacy columns; EF migration history is now complete with no pending migrations. |
**Phase 1 exit:** a user can save a job they have not applied to, walk the wizard, prepare materials, and *then* mark it applied — visibly, in the UI. CI is green.
@@ -189,39 +189,35 @@ Goal: commercialise. Last, per the guide's "do not over-engineer before needed.
| # | Task | Priority | Difficulty | Dependencies | Expected value |
|---|---|---|---|---|---|
| 7.1 | **IMPLEMENTED; configuration required** — password signup and sign-in use Cloudflare Turnstile with mandatory server-side Siteverify validation when keys are configured. Registration remains closed until `AUTH_ALLOW_REGISTRATION=true` and production widget keys are supplied. | **P2** | **M** | 2.4, 7.3 | Safe code path is ready without silently opening public registration. |
| 7.1 | **IMPLEMENTED AND CONFIGURED; browser verification required** — password signup and sign-in use Cloudflare Turnstile with mandatory server-side Siteverify validation. Production reports registration and Turnstile enabled; a real signup still needs interactive verification. | **P2** | **M** | 2.4, 7.3 | The code and configuration are active without weakening abuse controls. |
| 7.2 | **DONE (2026-07-30)** — existing Identity roles are the plan model: `Premium` (and `Admin`) receives `advancedAi`, `premiumThemes`, `automation`, `analytics`, and 5 GB storage capabilities; free accounts receive core features and 250 MB. `/auth/me` exposes plan and entitlements. | **P3** | **M** | none | Reuses the existing role system and avoids a second billing-state table before Stripe exists. |
| 7.3 | **DONE (2026-07-30)** — existing AI interaction metering now enforces monthly generation limits: 25 for free accounts and 250 for Premium/Admin. Usage responses expose the active plan and limit. | **P3** | **M** | 5.2, 7.2 | Cost-bearing AI now has a clear monthly ceiling before registration opens. |
| 7.4 | **DONE (2026-07-30)** — attachment uploads enforce total per-user storage entitlements (250 MB free, 5 GB Premium/Admin) in addition to the existing 10 MB per-file cap. | **P3** | **S** | 7.2 | Storage limits match the exposed capability model. |
| 7.5 | **Stripe billing** | **P3** | **L** | 7.2 | Still blocked on **Stripe keys** — the only remaining hard blocker. Tiers are now decided. |
| 7.6 | ✅ **DONE (2026-07-30)** — public CV (`/cv/{guid}`), privacy-first random links, revoke/rotate sharing | **P3** | **M** | 3.4, 4.2 | Anonymous rendering is isolated behind an explicit public flag, served with `noindex`, and revoked links cannot be restored accidentally. |
| 7.5 | **IMPLEMENTED; configuration required (2026-07-31)** — hosted subscription Checkout, customer portal, signed subscription webhooks, persisted Stripe state, and idempotent Premium-role provisioning. | **P3** | **L** | 7.2 | Activation needs the operator-created monthly price, portal, webhook registration, and three deployment secrets in `BLOCKERS.md`. |
| 7.6 | ✅ **DONE (2026-07-31)** — public CV (`/cv/{guid}`), privacy-first random links, revoke/rotate sharing, recruiter PDF download | **P3** | **M** | 3.4, 4.2 | Anonymous rendering is isolated behind an explicit public flag, served with `noindex`; revoked links cannot be restored accidentally, and rate-limited PDF export uses the same visibility check. |
| 7.7 | ✅ **DONE (2026-07-30)** — three free CV themes plus five Premium themes, enforced by account entitlement and clearly locked in the picker | **P3** | **S** | 4.3, 7.2 | Existing Premium-theme CVs remain editable and exportable after downgrade so user data is never held hostage. |
| 7.8 | **DONE (2026-07-30)** — CI runs NuGet transitive vulnerability reporting and a production-only npm audit. The npm audit reports the existing no-fix advisory baseline without blocking unrelated deploys. | **P2** | **S** | none | Vulnerable dependencies are now visible before deployment. |
| 7.8 | **DONE (2026-07-31)** — CI runs NuGet transitive vulnerability reporting and blocks high/critical npm findings across production and test/browser tooling. The documented React Router baseline is moderate. | **P2** | **S** | none | Vulnerable dependencies are visible and high-severity regressions stop deployment. |
| 7.9 | ✅ **DONE (2026-07-30)** — per-user monthly AI token ceilings (100k free, 1M Premium/Admin) enforced alongside generation limits and exposed in usage totals | **P3** | **S** | 5.2, 7.2 | Existing metering is the single accounting source; paid-provider spend now has both request and token ceilings. |
---
## Maintenance milestone — Technical-debt reduction ✅ DONE (2026-07-31)
Removed the dead 232 MB vendor snapshot and transitional link-compilation project; consolidated API
source ownership; added Problem Details, traceable structured logs, trusted proxy handling, durable CV
queue restart recovery, CV artifact cleanup, PDF retention, and warning-free frontend tests; replaced
placeholder docs and reconciled stale architecture records. Remaining conditional debt and its trigger
conditions are tracked in `docs/architecture/technical-debt.md`.
---
## Critical path
```
[Phase 0 DONE] pipeline stages · DateApplied nullable · Job entity · sidecar secured · docs restored
All implementation dependencies through Phase 6 are closed. The remaining release path is:
1.1 Prospect stages in UI ── 1.2 Wizard target (finishes the workflow users can see)
1.8 Fix red CI (independent — do first; everything lands on this baseline)
1.4 Rotate DP keys · 1.5 CORS fix (independent security)
1.9 Orphan tables ── informs 3.1
`production key rotation → backup/restore rehearsal → deploy/smoke test → registration verification`
2.1 Split profile/career ── 2.2 Decompose ProfilePage ── 3.3 Career Workspace
└─ 3.4 Profile ≠ Master CV ──┬─ 4.1 CvTheme model ── 4.2 Renderer ──┬─ 4.3 Themes
│ ├─ 4.5 Customise tab
│ └─ 4.6 Live preview ── 4.7 Export
└─ 4.4 Content tab
4.9 Reactive Resume research ── must precede 4.1
6.6 Market as data ── 6.3 Official APIs
5.2 AI metering ── 7.3 Quotas ── 7.1 Open registration
```
**Two things now gate everything:** `3.4` (profile ≠ CV) and `4.1` (themes as data). The third — the workflow — was unblocked by Phase 0; only its UI surface (1.1) remains.
Stripe code is complete; activation can follow once the product, monthly price, portal, webhook, and credentials exist.
---
@@ -230,13 +226,14 @@ Goal: commercialise. Last, per the guide's "do not over-engineer before needed.
| Phase | Rough size | Note |
|---|---|---|
| 0 — Foundation | **done** | Delivered 2026-07-17. |
| 1 — Critical fixes | ~35 days | Shrunk: Phase 0 absorbed most of it. Mostly UI surfacing + two operator tasks. |
| 2 — UX | ~23 wk | 2.5 (data layer) is the multiplier. |
| 3 — Career Workspace | ~23 wk | Grew slightly: relational profile (3.1) is now L, not a coin-flip. |
| 4 — CV Builder | **~46 wk** | The big one. Do not underestimate because a tab exists. |
| 5 — AI | ~1 wk | Shrunk: 5.1 is a docs fix, not an abstraction build. |
| 6 — Job discovery | ~23 wk | Shrunk: no scraping, and (a) is mostly built. The extension (6.2) carries most of the value. |
| 7 — SaaS | ~34 wk | Tiers decided; needs Stripe keys. |
| 1 — Critical fixes | **code complete** | DataProtection rotation remains an operator task. |
| 2 — UX | **done** | Delivered 2026-07-30. |
| 3 — Career Workspace | **done** | Delivered 2026-07-30. |
| 4 — CV Builder | **done** | Delivered 2026-07-30; public PDF completed 2026-07-31. |
| 5 — AI | **done** | Metering and quotas included. |
| 6 — Job discovery | **done** | Official NAV feed plus reviewed save flow. |
| 7 — SaaS | **operationally blocked** | Remote CI, Stripe activation, and interactive production signup/OAuth verification remain. |
| Maintenance — Technical debt | **done** | Conditional future debt remains trigger-based, not current blocking work. |
---
@@ -255,14 +252,12 @@ All six of the original blocking questions are answered. Recorded here so they a
## Remaining blockers
Only two things now block work, and both need you rather than a decision:
The authoritative list is `BLOCKERS.md`. Repository implementation is currently blocked only by
external systems, credentials/configuration, or production access: remote CI, Stripe activation, production signup/OAuth verification,
DataProtection key rotation, production verification/deployment, and the production-backed legacy
job/application cutover. Job-specific learning paths are implemented, and portfolio content stays in public CVs.
1. **Stripe keys** (gates 7.5). Tiers are decided; the integration needs credentials.
2. **DataProtection key rotation** (task 1.4). Needs an operator with production access.
## Open questions raised by Phase 0
## Open questions raised *by* Phase 0
Not product decisions — engineering findings that need a call before the phase they touch:
1. **Orphan DB tables** (task 1.9). The dev database carries `CareerProfiles`, `CareerProfileVersions`, `CvVariants`, `CvVersions`, `TailoredApplications`, `InterviewPrepNotes`, `AiWorkspaceNotes` — in no model, no migration. An abandoned Career Workspace attempt. **Was there a previous design worth recovering, or is this dead weight to drop?** Answer before Phase 3 re-treads the same ground.
2. **Kanban column count** (task 1.1). The pipeline now has 9 stages; the board is built for 6. Do the three Prospect stages get their own columns, collapse into one "Not applied" column, or sit behind a toggle? A UI decision, needed to finish Phase 1.
None remain. Career Workspace data was recovered into the relational model and the Kanban groups
prospect stages explicitly.