Homework

Homework — prove the schema can't drift

Prove the "no drift" claim yourself. This is the homework that makes the lesson stick.

  1. Add a column with a new migration. Migrations are append-only — you don't edit an applied one, you add the next. Create db/migrations/00002_user_name.sql:

    -- +goose Up
    ALTER TABLE users ADD COLUMN full_name TEXT NOT NULL DEFAULT '';
    -- +goose Down
    ALTER TABLE users DROP COLUMN full_name;
    
  2. Regenerate — and touch no Go.

    sqlc generate
    

    Open internal/db/models.go. The User struct grew a FullName string field on its own — because sqlc re-read the schema (now two migrations) and the struct is a function of it. You edited zero Go by hand.

  3. Now feel the drift protection bite. Write a query that selects the new column — -- name: GetUserName :one\nSELECT full_name FROM users WHERE id = $1; — then misspell it as full_name. Run sqlc generate:

    error: column "full_name" does not exist
    

    The typo is caught at generate time, against the real schema — not at runtime, in production, on a user's request. That's the whole promise, demonstrated: the generated code cannot describe a table that doesn't exist. Fix the typo, regenerate, and it's clean.

  4. Restart and re-migrate. go run ./cmd/signflow — the log shows OK 00002_user_name.sql applying. Your live database now has the column; a fresh deploy would apply both migrations from scratch.

Where this is going. You have a users table with a password_hash column that nothing fills yet. Lesson 4 starts the auth phase: registration with bcrypt password hashing, and server-side sessions — a session row in Postgres, an opaque ID in an HttpOnly cookie. It's the first time SignFlow knows who you are — and the beginning of the answer to a question the Pica mobile app answered differently: sessions, not JWT. Lesson 14 is the whole argument for why.