0 / 91
Week 12 · Day 80 of 91

Design architecture and data model

AI-Assisted Capstone: Build Without Vibe Coding

Objective

Choose the simplest structure that satisfies the requirements.

AI is an advanced instrument or junior collaborator: it expands throughput, but the engineer still defines requirements, verifies measurements, and signs off on safety.

  • system boundaries
  • schema and relationships
  • API contract
  • security assumptions

Why this matters

You have behaviour written down. Today you decide the shape of the thing that will produce it: which programs exist, which tables hold what, what each endpoint promises, and what you are assuming about trust. Do this on paper and tomorrow's code is transcription. Skip it and you get a schema invented one column at a time by whoever — or whatever — is typing at the moment.

By the end of the hour you have an architecture packet: four short sections, every choice justified by a requirement rather than by taste.

What an architecture decision is actually based on

There is one rule for today, and it decides every question you will face: choose the simplest structure that satisfies the requirements. Simplest means fewest moving parts that still meet the spec — not fewest lines, not most clever.

A choice is justified when you can name all four of these:

  1. The requirement it serves — a specific acceptance criterion from yesterday.
  2. The constraint it respects — your time, your skills, your deployment target.
  3. The risk it manages — what goes wrong if you choose otherwise.
  4. The maintenance cost you accept — what you will have to keep working forever after.

"It is what modern apps use", "the framework list is impressive", and "the AI suggested it" are not on that list. Neither is novelty. Every extra service, library, or table is a thing that can break at 11pm on Day 89, and you are the person who will be awake.

Fewest components that meet the spec

A design review does not ask whether the circuit is exciting. It asks whether each part is required, what happens at the limits, and who repairs it in the field. A junior adds an op-amp because it might be useful; a reviewer asks which specification line demands it. Apply the same question to every table and every dependency: which acceptance criterion fails without this?

System boundaries

A boundary is a place where the system changes machine, process, or trust. You mapped these on Day 1; now you draw your own. For a capstone built on this course the picture is short:

[ Browser: React app ]
        |  HTTP + JSON        <-- trust boundary: everything left of here is user-controlled
[ Server: Express API ]
        |  SQL
[ Database: PostgreSQL ]

Three boxes, two boundaries. Write beside each arrow what crosses it — not "data", but the actual shape: "POST /api/calibrations with a JSON body", "INSERT with parameters".

The upper boundary is the trust boundary, and it is the one that matters. Everything above it runs on a machine the user controls and can modify. Validation in the browser is a convenience for honest users; validation on the server is the only kind that exists. If your diagram does not mark where that line sits, you cannot reason about security at all.

Resist adding boxes. A cache, a queue, a second service, a separate admin app — each one is a new boundary, and boundaries are where bugs live. Add one only when a written requirement fails without it.

Schema and relationships

Your schema is the tables, their columns, and the rules the database itself enforces. Design it from the nouns in your spec, not from the screens.

For the calibration tracker the nouns are instruments and calibrations, and one instrument has many calibrations. That is a one-to-many relationship, and it is expressed by putting a foreign key — a column pointing at another table's primary key — on the many side:

CREATE TABLE instruments (
  id            SERIAL PRIMARY KEY,
  asset_tag     TEXT NOT NULL UNIQUE,
  model         TEXT NOT NULL,
  interval_days INTEGER NOT NULL CHECK (interval_days > 0)
);

CREATE TABLE calibrations (
  id            SERIAL PRIMARY KEY,
  instrument_id INTEGER NOT NULL REFERENCES instruments(id) ON DELETE CASCADE,
  calibrated_on DATE NOT NULL,
  technician    TEXT NOT NULL,
  notes         TEXT
);

CREATE INDEX calibrations_instrument_id_idx ON calibrations (instrument_id);

Read what each constraint buys you, because each traces to a criterion from Day 79. NOT NULL makes "required" true even if a bug bypasses your validation. UNIQUE on asset_tag makes duplicate instruments impossible rather than unlikely. REFERENCES makes a calibration for a non-existent instrument a database error, which is why yesterday's 404 criterion can be trusted. CHECK rejects a zero or negative interval. The index makes "all calibrations for instrument 7" fast once the table grows.

The building, not the furniture

Constraints are load-bearing walls: awkward to move later, and the reason the floor holds. Code validation is furniture — easy to rearrange, and it protects nothing when someone else walks in through another door. Put the rules that must always hold in the walls.

Two habits worth keeping: derive values rather than storing them when they are cheap to compute (the next due date is calibrated_on + interval_days, so do not store it and risk it going stale), and do not create a table for something you can only justify with "we might need it".

The API contract

The API contract is the promise the server makes to the browser: for each route, the method, the path, what goes in, what comes back, and which status codes are possible. Write it as a table before writing any handler.

Method Path Body in Success Failure
GET /api/instruments 200 array of instruments 500
GET /api/instruments/:id/calibrations 200 array, newest first 404 unknown instrument
POST /api/instruments/:id/calibrations { calibratedOn, technician, notes? } 201 created record 400 invalid body, 404 unknown instrument

The failure column is the one beginners leave blank, and it is the one the frontend needs most — Day 79's criteria about empty dates and missing instruments live entirely in that column. Fill it in and the error handling writes itself; leave it out and every failure becomes a surprise.

Keep the contract next to the schema in the same document, because they constrain each other: a 404 is only reliable because of the foreign key, and 201 is only meaningful because the insert either fully happened or did not.

Security assumptions

Write your assumptions as plain sentences, because an assumption you never wrote down is one you cannot check. Three lines is enough for a capstone:

- Single trusted user on a local network. No accounts in v1 (see non-goals).
- The API validates every field again on the server, regardless of browser validation.
- No personal data beyond a technician name; nothing sensitive is logged.

The second line is not optional and applies to every project regardless of size, for the reason the diagram already showed: the browser is on the user's machine. If a later requirement adds accounts, this section is where "who may read whose data" gets decided — and it gets decided before the code, because retrofitting ownership checks is how real systems leak.

Reviewer mode — after the packet is drafted

Today's AI mode is reviewer. You bring the finished packet and ask for defects, and a useful review returns specific actionable findings with evidence — the table, the column, the missing status code — not praise and not a rewrite.

"Critique this design for premature complexity, missing constraints, and unclear ownership of data."

Judge every finding yourself against the four justifications above. If a suggestion adds a service or a table that no acceptance criterion needs, decline it in writing. Declining well is the skill.

Walkthrough: the traceability check

This is the step that catches over-design, and it takes five minutes. Open your spec beside your schema and go line by line.

  1. For each table, name the acceptance criterion that fails without it. The calibrations table is required by criterion 1 of Story 1. No criterion? Cut the table.
  2. For each column, do the same. notes is optional in the spec, so it stays nullable.
  3. For each endpoint, name the story it serves. Delete anything serving none — "we will need it later" is next week's decision, made with better information.
  4. Go the other way: for each acceptance criterion, point at the table, endpoint, and screen that will satisfy it. A criterion with nothing pointing at it is a gap you would have found on Day 84.

Checkpoint

Every table, column, and endpoint traces to a criterion, and every criterion traces to a table, endpoint, and screen. If both directions hold, your design is exactly the size of your spec.

Your turn

Write docs/architecture.md. Diagrams can be photographed from paper and committed as an image.

  1. Draw the boundary diagram: your boxes, the arrows, and what crosses each arrow. Mark the trust boundary explicitly and write beside it "user controls everything on this side".
  2. Write the schema as real CREATE TABLE statements, with NOT NULL, UNIQUE, REFERENCES, and CHECK wherever a spec line demands them. Aim for three tables or fewer.
  3. Beside each constraint, add a comment naming the criterion it enforces.
  4. Write the API contract table with a filled-in failure column for every route.
  5. Write the security assumptions as three to five plain sentences.
  6. Run the traceability check in both directions and record what you cut. Cutting something today is a success, not a failure.
  7. Run the reviewer prompt, decide on each finding in writing, then commit: docs: architecture packet for capstone.

You are done when

You can point at any box, table, or endpoint and say the requirement, the constraint, the risk, and the maintenance cost in one breath.

Common pitfalls

  • Designing from screens. Screens change weekly; the data model does not. Model the nouns and their relationships, then decide what the screens read.
  • Storing what you can derive. A stored "next due date" is a second source of truth that will eventually disagree with the first. Compute it.
  • Leaving the failure column empty. Undesigned errors become whatever the framework happens to return, and your frontend cannot react to a surprise.
  • Adding a service because it sounds professional. Every box is a boundary, a deploy step, and a thing that can be down. Justify or cut.

Verify it yourself

Open today's reference, OpenAI's Codex CLI documentation, and look at what it says about giving the agent context about a project's structure.

  1. Does the documentation suggest describing architecture and conventions to the agent up front? Note where your packet would go and what you would still need to add.
  2. Find anything about restricting what the agent may change. Which parts of your design — schema, contract, assumptions — should the agent never alter without you? Write that list.

Keep that list. Tomorrow you turn it into the repository instructions the agent actually reads.

The hour

  1. 0–5 min Recall

    Without notes, state yesterday’s main idea and one unresolved question.

  2. 5–20 min Learn

    Read only the listed concept notes and official reference sections needed today.

  3. 20–48 min Build

    Draw the architecture, design tables, and list endpoints/screens before coding.

  4. 48–55 min Explain and verify

    Run the result, inspect evidence, and explain the data/control flow in your own words.

  5. 55–60 min Quiz and commit

    Complete the quiz, record one lesson, and commit the verified change when applicable.

What to hand in

Deliverable

A reviewed architecture packet with justified choices.

Working with AI today

AI as skeptical reviewer

Provide existing work and ask for concrete defects, risks, missing tests, and unsupported assumptions—not praise.

Critique this design for premature complexity, missing constraints, and unclear ownership of data.

References

End-of-day quiz

Q1 What should architecture decisions be based on?
Q2 Which result best proves today’s work is complete?
Q3 What should an AI code review primarily produce?

Explain-back gate

Pass the quiz above to unlock completion.

Quiz + explain-back checks required.