The review stack
Orders the pass: correctness and security, then principles, then patterns, then tests and contracts, then style. You commit to this order in writing before you read a line of source — the header is already on the page.
The last two chapters handed you a way of reading code. You learned the five-layer review stack — correctness and security first, then principles, then patterns, then tests and contracts, then style — and you learned the four-part shape every review comment takes: a severity label, an observation, the principle or pattern it breaks named with its lesson ID, and a proposed action. Alongside that, the earlier documentation chapter gave you the Nygard ADR template — Status, Context, Decision, Consequences — and the three-test check for which decisions earn a record at all. This project is where you run both disciplines for real, against a running SaaS app that ships with a handful of deliberate review defects waiting for someone to read them properly.
There is no separate pull-request branch and no GitHub-style diff here. The “PR under review” is a new plan-overview surface bolted onto the invoices app you have grown across the course — a /plan page showing the org’s current entitlement, seats used, and a renewal countdown, with the entitlement read cached so the page doesn’t hammer the data layer. You read that surface and its supporting modules against the conventions the rest of the app already established — the authedAction wrapper, the tenantDb facade, the logAudit seam, the Temporal time primitive, the existing cached reads in src/lib/invoices/. The defects live in those /plan files. Your job is not to fix them — you change none of the audited source. The deliverable is two written artifacts: a review file completed with five file-and-line-anchored comments plus a summary and a verdict, and one architecture decision record capturing the single design choice the surface earns.
**blocking:** `src/app/(app)/plan/actions.ts` L18-36 — `updatePlanLabel` hand-rolls the session check, runs no role gate, and writes `org.planLabel` past the `tenantDb` facade (the `if (!session)` guard is also dead — `getSession()` never returns null).Principle/pattern: SaaS pattern #2 (lesson 2 of chapter 057 — `authedAction(role, schema, fn)`) + Principle #5 (use the named wrapper, don't hand-roll it).Action: wrap in `authedAction('admin', updatePlanLabelSchema, async (input, ctx) => { ... })` and route the write through `tenantDb(ctx.orgId).update.organizationPlanLabel(input.planLabel)`.This first lesson builds nothing and writes no comment. By the end you will have the audit target running on your machine, the /plan surface open in the browser, and the review file’s pass-order header acknowledged with a one-line note on where your pass begins — ready to write the first finding in the next lesson.
Everything below is a reflex the later lessons train properly; this list is the map, not the teaching.
There is almost nothing mechanical here — this is a reading-and-writing project, not a feature build. The “architecture” is the set of four disciplines you bring to bear, and one fixed target they all point at.
The review stack
Orders the pass: correctness and security, then principles, then patterns, then tests and contracts, then style. You commit to this order in writing before you read a line of source — the header is already on the page.
The principle-and-pattern map
The one-page cheatsheet from the review chapter, with each rule’s diff signature and lesson ID. Every comment you write cites it. Keep it open in a second tab the whole time.
The four-part comment template
The shape every finding takes — severity, observation, principle/pattern, action. It ships in the repo as reviews/template.md; read it once and write each comment to it.
The Nygard ADR scaffold
The shape the one recorded decision takes — Status, Context, Decision, Consequences. It ships pre-titled with four empty sections, waiting to be filled.
The load-bearing fact: the audit target — the running app’s /plan surface — never changes. You leave the source exactly as you found it; the fix you propose lives in the body of each comment, not in an edit. The only things that grow across this chapter are the two deliverable scaffolds you fill (reviews/chapter 104.md and the ADR) and the one-line row you append to the ADR index.
The starter is the full invoices app you already know, plus the new /plan surface and its supporting modules. Most of the tree is carried-over code you will not touch, so the annotations below mark only two things: the files the review walks — the /plan surface and its src/lib/plan/ modules — and the two deliverable files you fill. Everything bolded is your focus. There are no TODO comments anywhere in the source: this is a read-only target, and the only TODO markers live inside the two deliverable scaffolds, naming the lesson that fills each one.
Started at: line + a <!-- TODO(L2) --> marker; you fill the comments, summary, and verdict## sections + a <!-- TODO(L4) --> marker; you fill the sectionslogAudit(tx, event) — the audit seaminvoiceTags + orgPlanEntitlementTag'use cache' reads — the ADR’s precedentupdateTag mutation seams — the ADR’s precedentupdatePlanLabelSchemaBefore you go hunting for defects, spend the first pass calibrating your eye. Read the canonical helpers once — the authedAction wrapper, the logAudit seam, the tenantDb facade, the Temporal time primitive, and the existing cached reads in src/lib/invoices/queries.ts with their updateTag mutation seams in src/lib/invoices/actions.ts. These are the established surface every finding is measured against — a review asks “what was the convention, and where does this code go around it?” You are not auditing yet; you are learning what right looks like so the bypass jumps out when you read /plan in the next lesson. The technology behind each helper is owned by its origin chapter — the invalidation decision tree for the cached reads, the roles chapter for the wrapper and the audit log, the time chapter for Temporal — so read for the shape of the seam here, not the theory.
Each lesson produces one piece of the written deliverable, building from the modeled first comment to the full review to the ADR and a self-grade.
Lesson 2 — The auth bypass
Walks the first finding end-to-end — the plan-label mutation that hand-rolls its own session check instead of using the wrapper — as the worked example whose cadence every later comment copies.
Lesson 3 — Four more blocking findings
Surfaces the remaining four on your own — the side-effect import, the Date arithmetic, the derived-state effect, the missing audit-log write — then closes the review with the severity summary and a request-changes verdict.
Lesson 4 — ADR 0007
Runs the three-test inclusion check to find the one decision worth recording, writes the cache-decision ADR with a crisp Decision and an honest Consequences list, and self-grades both artifacts against the reference.
The brief names the bar the way a real review does: five is the floor, seven or eight is the experienced reach. Five blocking findings is the complete review. The surface also ships a couple of softer opportunities — a missing doc comment, a vague name, a structural choice worth praising — and catching those as well is the careful engineer’s pass, never a requirement. The discipline this chapter teaches is restraint as much as coverage: a review buried in twelve nits drowns its own signal, and the right mix of severities beats the highest comment count.
The audit target runs entirely on your machine with no external accounts and no environment variables — the app serves an in-memory store seeded at boot (src/server/store.ts), so nothing reaches a real database or third-party service. This lesson ends when the app is up, /plan is on screen, and the review file’s Started at: line carries your one-line note.
Get the starter codebase from the project repository, under Chapter 104/start/.
Install dependencies — this completes clean.
pnpm installBoot the app.
pnpm devOpen http://localhost:3000/plan. Read the surface, then open its source — src/app/(app)/plan/* and src/lib/plan/* — against the conventions you just calibrated on. There is no PR diff; the surface itself is the unit under review. The inspector at /inspector carries an identity switcher if you want to view a second org.
Open reviews/chapter 104.md. It already ships with the line Pass order: correctness/security → principles → patterns → tests/contracts → style, a blank Started at: line, and a <!-- TODO(L2) --> marker. Fill Started at: with a one-line note on where your pass begins. Read reviews/template.md once for the four-part comment shape, and keep the principle-and-pattern cheatsheet open in a second tab.
Expected result. The app runs at http://localhost:3000, the /plan surface is visible, and the review scaffold carries your Started at: note under the shipped pass-order header. No comment is written and no ADR is drafted — that begins in the next lesson.
That pass-order header is not decoration, and filling Started at: is not busywork. The starter ships the header so the disciplined reflex is on the page before you touch a line of source, and writing the Started at: note is the act of committing, in writing, to where the pass begins. A review reads top-down on the stack, not top-down on the file list — opening file one at line one and reading straight through is exactly the failure mode the review chapter warned against, and ignoring the shipped order is the first sign a review is about to drift into style commentary before it has checked whether the code is even correct.
One last thing on scope, so you know what kind of review this is. This is a principle-and-pattern review, not a full architectural rethink — the /plan surface is a handful of small files, well under the size threshold where you would reach for a “split this up” comment. It is not a style review: the formatter and linter already pass, so pnpm verify is green and there is nothing for you to flag on formatting. And it is not a security audit — that was a separate project — nor a re-implementation, since you edit no source. Test coverage is one layer of the review stack, but it is not a deliverable here; lesson-verification/ ships empty, and there is no automated checker for the written artifacts. Every check in this chapter is one you run by hand and tick off yourself, which is exactly how the reflex has to live once a real PR lands on your desk with no rubric attached.