Module 4 · Authentication and security

Lesson 23 — Secrets, rate limiting and GDPR

Secret management, request limits and personal-data protection.

Published
In this lesson
  1. Exercise 1 — Token bucket with and without atomicity
  2. Exercise 2 — Secrets in your repo
  3. Exercise 3 — GDPR rights in your API
  4. Exercise 4 — Minimal audit log
  5. Exercise 5 — Minimization
  6. Submit

Redis + your project. Don't look at solutions.md before submitting.

Exercise 1 — Token bucket with and without atomicity

  1. Implement allow(key, capacity, refill) with HGETALL/HSET as in the lesson. Demonstrate the race: 20 concurrent threads requesting with capacity=5: how many get through? (5 should get through; note how many actually did).
  2. Fix it with a Lua script (or django-ratelimit): repeat the test. Now exactly 5?
  3. Configure TicketFlow's real limits: login 5/min per user+IP, checkout 10/min per user, public API 60/min per IP. Where would you return 429 and which header do you send?

Exercise 2 — Secrets in your repo

  1. Run trufflehog or git-secrets (or gitleaks) over your history: did anything show up? (05 cleaned up; verify).
  2. Simulate the gateway key rotation: write the step-by-step runbook with dual rotation (accept two keys → switch from old to new → revoke old) and which code enables it (a setting with a list of valid keys).
  3. Where would GATEWAY_SECRET live in your ideal deployment (cloud/vault/orchestrator env) and why not in the Docker image?

Exercise 3 — GDPR rights in your API

  1. GET /api/me/export/: JSON with the authenticated user's profile + reservations + payments (only their own, obviously). What shape would you give it: one giant JSON or a job with download? Justify with the expected volume.
  2. DELETE /api/me/ → anonymization: email → f"{uuid}@anonymized", name → "Deleted user", account state → DELETED, without deleting reservations/payments. Implement at least the model and the transaction (10: atomic).
  3. What happens to their MFA, their tokens and their organizer membership when anonymizing? Enumerate and decide.

Exercise 4 — Minimal audit log

  1. An append-only AuditLog(actor, action, object_type, object_id, before JSONB, after JSONB, created_at) model. Write the audit(user, "role.change", user_obj, before, after) helper.
  2. Wire it to 21's role change (staff endpoint) and to the refund. How do you guarantee append-only (no UPDATE/DELETE from the app)? (DB permissions or a signal that prevents it).
  3. Query: "who changed roles in March": write the query that would answer it during an incident.

Exercise 5 — Minimization

  1. Audit your User/Reservation model: which field is superfluous or should be optional? Propose its removal with a migration (11) and justify it with Art. 5 (minimization).
  2. Write the retention policy: how long do expired PENDING ones, reset tokens and access logs live? Propose the purge job (31's cron).

Submit

Paste the count of threads that got through (before/after), the rotation runbook and the anonymization. This closes the security module; next Lesson 24 — SOLID and dependency injection.