Skip to content
Chapter 104Lesson 1

Project overview

The last two chapters gave you two disciplines: the five-layer review stack with its four-part comment shape, and the Nygard ADR template for the decisions worth recording. This project is where you run both for real, against a running SaaS app seeded with deliberate review defects.

There is no pull-request branch and no diff here. The “PR under review” is a new /plan surface added to the invoices app you have built across the course — a page showing the org’s current entitlement, seats used, and a renewal countdown. You read it and its supporting modules against the conventions the rest of the app already follows, and the defects live in those /plan files. You fix nothing: you change none of the audited source. Instead you produce two written artifacts — a review file with five file-and-line-anchored comments plus a summary and a verdict, and one architecture decision record for the single design choice the surface earns.

The plan overview signed in as the Acme admin — the current plan, the seat counter, and the renewal countdown, each in its own card.

This first lesson writes no comment. By the end you will have the audit target running, 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 next.

Each item below is a reflex the later lessons teach in full; here you just exercise it.

  • Run the surface through the five-layer review stack in stack order — correctness and security first, style last — not top-to-bottom down the file.
  • Write each comment in the four-part anatomy: severity, observation, the principle or pattern with its lesson ID, and the action.
  • Draw the blocking-versus-suggesting line, and check every security-relevant mutation against the canonical audit-log catalog instead of trusting a write that “looks fine.”
  • Apply the three-test check to decide what earns an ADR, then write one in the Nygard shape: a single declarative Decision and a Consequences list that names the costs, not just the wins.
  • Self-grade your review and ADR against the reference, and turn the misses into a sharper checklist for the next PR.

This is a reading-and-writing project, not a feature build. The architecture is four disciplines and the 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 that order in writing before reading a line of source — the header is already on the page.

The principle-and-pattern map

The one-page cheatsheet from the review chapter, each rule tagged with its diff signature and lesson ID. Every comment cites it, so keep it open in a second tab.

The four-part comment template

The shape every finding takes — severity, observation, principle/pattern, action. It ships as reviews/template.md; read it once, then 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 to fill.

The audit target — the running app’s /plan surface — never changes: your proposed fixes live in the body of each comment, never in an edit. What grows is the work you produce — the two deliverable scaffolds (reviews/chapter 104.md and the ADR) and the one-line row you append to the ADR index.

The starter is the 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. The bolded files are your focus: the files the review walks — the /plan surface and its src/lib/plan/ modules — and the two deliverables you fill. The source carries no TODO comments; it is a read-only target. The only TODO markers live in the two deliverable scaffolds, naming the lesson that fills each.

  • Directoryreviews/
    • chapter 104.md SCAFFOLD — pass-order header + a blank Started at: line + a <!-- TODO(L2) --> marker; you fill the comments, summary, and verdict
    • template.md the four-part comment shape — read it once
  • Directorydocs/
    • Directoryadr/
      • 0007-cache-entitlement-reads-with-cacheTag.md SCAFFOLD — Nygard title + four empty ## sections + a <!-- TODO(L4) --> marker; you fill the sections
      • README.md the ADR index — intro plus rows 0001–0006; you append the 0007 row in the last lesson
  • Directorysrc/
    • Directoryapp/
      • Directory(app)/
        • Directoryinvoices/ the carried-over list and edit surface — untouched
        • Directoryplan/
          • page.tsx the new server-component surface — the unit under review
          • seat-usage.tsx the seat-counter Client Component
          • actions.ts the plan-label mutation
          • loading.tsx
      • Directoryinspector/ the cache inspector carried from the caching project
    • Directorylib/
      • authed-action.ts the canonical Server-Action wrapper — the seam the surface is read against
      • audit-log.ts logAudit(tx, event) — the audit seam
      • tenant-db.ts the org-scoped facade for reads and writes
      • temporal.ts the Temporal time primitive
      • Directorycache/
        • tags.ts invoiceTags + orgPlanEntitlementTag
        • profiles.ts, log.ts
      • Directoryinvoices/
        • queries.ts the existing 'use cache' reads — the ADR’s precedent
        • actions.ts the existing updateTag mutation seams — the ADR’s precedent
      • Directoryplan/
        • get-plan-entitlement.ts the cached entitlement read — the ADR’s subject
        • renewal-countdown.ts the renewal time math
        • schemas.ts updatePlanLabelSchema
      • Directoryanalytics/
        • page-view-tracker.ts a module that runs a side effect on import
    • Directoryserver/
      • jobs/summary-recompute.ts the background-job invalidation seam
  • Directorylesson-verification/ ships empty — there is no automated checker this chapter

Spend the first pass calibrating your eye, before you hunt for defects. 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 convention every finding is measured against. Learn what right looks like here so the bypass jumps out when you read /plan in the next lesson.

Each lesson produces one piece of the written deliverable, building from the first worked 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 — the worked example every later comment follows.

Lesson 3 — Four more blocking findings

You find the remaining four — the side-effect import, the Date arithmetic, the derived-state effect, the missing audit-log write — then close 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 clear Decision and an honest Consequences list, and self-grades both artifacts against the reference.

The brief sets the bar: five is the floor, seven or eight is the experienced reach. Five blocking findings is a complete review. The surface also ships softer opportunities — a missing doc comment, a vague name, a choice worth praising — that are optional, not required. Restraint matters as much as coverage: the right mix of severities beats the highest comment count.

The audit target runs entirely on your machine: no accounts, no environment variables, just an in-memory store seeded at boot (src/server/store.ts), so nothing reaches a database or third-party service. You’re done when the app is up, /plan is on screen, and the review file’s Started at: line carries your note.

  1. Get the starter codebase from the project repository, under Chapter 104/start/.

  2. Install dependencies.

    Terminal window
    pnpm install
  3. Boot the app.

    Terminal window
    pnpm dev
  4. Open http://localhost:3000/plan. Read the surface, then read 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 has an identity switcher if you want to view a second org.

  5. Open reviews/chapter 104.md. It 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, /plan is visible, and your Started at: note sits under the shipped pass-order header. No comment, no ADR yet — that begins in the next lesson.

The pass-order header keeps the disciplined order on the page before you touch a line of source. A review reads top-down on the stack, not down the file list: opening file one at line one and reading straight through is the failure mode that drifts into style commentary before checking whether the code is even correct.

This is a principle-and-pattern review. It is not a style review (the linter and formatter already pass, so pnpm verify is green), not a security audit (a separate project), and not a re-implementation, since you edit no source. Every check here is one you run and tick off by hand, exactly as you would when a real PR lands with no rubric attached.