FTM402 · Examination paper
120 minutes · written · open book (notes) · no internet · 40 marks · pass 20
Section A — name the layer and the first command (20 marks, 10 × 2)
Section titled “Section A — name the layer and the first command (20 marks, 10 × 2)”For each symptom, name the layer and the single first command you would run.
musicians.stagingresolves but nothing answers.- A deploy reported success, but the old behaviour is still live.
- Login on a PR preview bounces back to the login page.
nix develop .#backendfails with a hash mismatch.- A
psqlconnection as the app fails withPeer authentication failed. - A page is correct locally, stale in the browser after deploy.
- Grafana is silent while users report errors.
- A migration fails with
permission deniedonCREATE EXTENSION. - A unit exits 1 immediately after a config change.
- A query that was fast last week now takes 4 s.
Section B — incident (12 marks)
Section titled “Section B — incident (12 marks)”Transcript:
14:02:11 ftm-backend ERROR could not obtain connection from pool14:02:11 ftm-backend ERROR psycopg_pool.PoolTimeout14:09:40 ftm-worker ERROR Peer authentication failed for user "postgres"14:15:02 grafana ALERT BackendErrorRate firing (5m)14:21:00 deploy rollback initiated -> generation 4114:22:30 grafana ALERT resolvedState: the two distinct faults, which one caused the user-visible symptom, what the rollback did and did not fix, and the check that would have caught the second fault before it reached prod. (4 × 3)
Section C — security review (8 marks, 4 × 2)
Section titled “Section C — security review (8 marks, 4 × 2)”Name the class and the fix for each.
- A log line contains the full DSN with credentials.
- An endpoint returns another band’s enquiry when the id is changed.
- A page sets
Cache-Control: publicand reads the session. - A webhook handler accepts POSTs without verifying a signature.
Marking guide
Section titled “Marking guide”| Section | Marks |
|---|---|
| A | 2 each: 1 layer, 1 command |
| B | 3 each |
| C | 2 each |
| Total | 40 |
Pass 20/40. Distinction 28. Section A must score at least 12 — layer identification is the module.
Expected answers:
- 1 nginx/upstream,
curl -ithenjournalctl -u nginx - 2 systemd unit not restarted,
systemctl status <unit>/ checkrestartIfChanged - 3 preview Redis session missing,
ss -ltnin the container / check the session port - 4 Nix deps hash,
nix build .#backendand read the expected hash - 5 Postgres peer auth,
psql "…"as the service user / checkPGUSERin the unit env - 6 CDN cache,
curl -ito seeage/cache headers, then purge by key - 7 alerting gap, check the rule and
for:duration ingrafana-alerting/ - 8 superuser-only DDL in a migration, move it to
postStart; check the role - 9 systemd,
journalctl -u <unit> -b -p err - 10 Postgres plan,
EXPLAIN (ANALYZE, BUFFERS)/pg_stat_activity - B two faults: connection-pool exhaustion (user-visible) and worker peer-auth
failure. The rollback restored the pool behaviour but did not fix the worker’s
DSN. The check: assert the worker’s effective
PGUSER/DSN at deploy time, and a smoke job per deploy. - C 1 secret in logs → redact at source; 2 IDOR → object-level authorisation;
3 cache leak →
private/no-store; 4 unverified webhook → signature check with the shared secret, constant-time compare.