Control Panel Specifications
Status Workflow
draft → ready-for-review → under-review → published. Off-ramps and audit log per transition.
Complete
Every Founder File walks through a strict 6-state lifecycle. Transitions are server-enforced, audit-logged, and surface in the CP as colour-coded badges + action buttons. The Form preview at the bottom shows the status bar + actions strip that sits on every Edit screen.
The 6 states
draft (default on create)
- Purpose — Initial state. Editor builds up the file content over hours / days. Not visible publicly. No constraints on incomplete fields — Admin can save half-filled rows.
- DB type — `Status = 'draft'`. Set by INSERT default on Create. Re-set by Restore-from-archive and by Withdraw-from-review.
- Validation — Allowed actions: edit any field, Archive (soft delete), Submit for review (only when trilingual completeness gate passes). QC test: try Submit on a half-filled file → server returns HTTP 422 listing the missing fields per language.
ready-for-review (transient)
- Purpose — Marker that the editor finished and a reviewer should pick the file up. Lives between Submit (by editor) and Pickup (by reviewer). Typically only a few minutes — long-running ready-for-review = team-process problem.
- DB type — `Status = 'ready-for-review'`. Set when the trilingual gate passes on Submit. Cleared the moment a reviewer opens the file (sets to `under-review`).
- Validation — Allowed actions: edit (auto-reverts to draft), Pickup-for-review (auto-runs on the reviewer's first open). QC test: editor submits → status shows `ready-for-review`; another editor opens it and edits → status reverts to `draft` and the original submitter sees a toast.
under-review (locked)
- Purpose — A reviewer with `files.publish` permission has the file. The file is read-only for everyone EXCEPT this reviewer (and Editorial Lead). The reviewer reads the content, checks the PDFs, then approves or rejects.
- DB type — `Status = 'under-review'`. The reviewer is tracked separately in `FounderFileAuditLog` (eventType='review-picked-up', actorId=reviewer). No reviewer column on the file itself — multiple reviewers can swap.
- Validation — Reviewer actions: Approve (→ published), Reject (→ needs-updates with mandatory comment ≥ 20 chars), Withdraw (→ draft, no comment needed). QC tests: try Approve without `files.publish` permission → HTTP 403; try Reject with empty comment → HTTP 422; while in under-review, any non-reviewer attempting to edit gets HTTP 409 with "File is locked under review".
published (public)
- Purpose — The file is live on the public site. Anyone can download it (subject to consent gating). This is the only state visible on `/founder-files/*` routes.
- DB type — `Status = 'published'`. UPDATE also stamps `PublishedAt = GETUTCDATE()` ONLY if this is the first publish (previous PublishedAt was NULL).
- Validation — Allowed actions: edit any editable field (auto-flips to `needs-updates`, see Update spec), Archive. NO direct edit-and-stay-published path. QC test: change Title on a published file → Status badge immediately reflects `needs-updates` and the public page goes 410 within 30 seconds.
needs-updates (rejected or auto-flipped)
- Purpose — Two paths reach here: (1) reviewer Rejects with comments, (2) auto-flip from `published` when an editable field changes. The editor reads the comment (or knows what they just edited), fixes, and re-submits.
- DB type — `Status = 'needs-updates'`. PublishedAt stays as-is. LastUpdatedAt bumps to current UTC on every save in this state.
- Validation — Allowed: edit any field, Archive, Submit for review (subject to trilingual gate). QC tests: a reviewer's Reject comment must surface as a yellow banner at the top of the Edit screen; the banner is dismissible only after Submit, not before.
archived (soft-deleted)
- Purpose — End state for soft-deletion. File hidden publicly, no edits allowed, Restore window of 90 days. See the dedicated Archive spec for the full lifecycle.
- DB type — `Status = 'archived'`, `ArchivedAt = GETUTCDATE()`, `ArchivedBy = @adminId`. No DELETE statement.
- Validation — Allowed: Restore (only within 90 days). All edit endpoints return HTTP 410 Gone with `code: FILE_ARCHIVED`. QC test: hit `PATCH /admin/founder-files/{slug}` on an archived file → expect 410 + restorable-until date.
Transition matrix
Forward (normal flow)
- draft → ready-for-review (editor Submit)
- ready-for-review → under-review (reviewer Pickup)
- under-review → published (reviewer Approve)
- needs-updates → ready-for-review (editor Re-Submit after fix)
Backward / sideways
- ready-for-review → draft (editor edits or Withdraw)
- under-review → draft (reviewer Withdraw)
- under-review → needs-updates (reviewer Reject)
- published → needs-updates (auto on any editable-field change)
- draft / needs-updates / published → archived (Admin Archive)
- archived → draft (Admin Restore, only within 90 days)
Form preview — Status bar + action buttons (varies per status)
The status bar lives at the top of every Edit screen. Buttons change based on the current Status. Below: the four most common states a reviewer sees.
