Implements Feature 03 task 4 (6472c90d). Done-condition: every non-GET/HEAD/OPTIONS request under /api/v1 requires X-MealQuest-CSRF equal to the session csrf_token (constant-time), else 403 {"error":{"code":"csrf"}}; GET /api/v1/me returns {name, email, household:{label:"Our kitchen"}, csrfToken}; tests cover missing/wrong/right header and GET needing none; quality floor passes.
Evidence (developer-run): gofmt empty; go vet clean; go test -race all packages pass; CGO_ENABLED=0 build ok; end-to-end with the real SessionManager+SQLite: /me 200 with token, no/wrong CSRF 403, correct token passes to routing. Note: RequireSession now stores the session (WithSession) so CSRF can compare; F04 settings branch must use this when rebased.
Implements Feature 03 task 4 (6472c90d). Done-condition: every non-GET/HEAD/OPTIONS request under /api/v1 requires X-MealQuest-CSRF equal to the session csrf_token (constant-time), else 403 {"error":{"code":"csrf"}}; GET /api/v1/me returns {name, email, household:{label:"Our kitchen"}, csrfToken}; tests cover missing/wrong/right header and GET needing none; quality floor passes.
Evidence (developer-run): gofmt empty; go vet clean; go test -race all packages pass; CGO_ENABLED=0 build ok; end-to-end with the real SessionManager+SQLite: /me 200 with token, no/wrong CSRF 403, correct token passes to routing. Note: RequireSession now stores the session (WithSession) so CSRF can compare; F04 settings branch must use this when rebased.
RequireSession now stores the validated session in the request context
(auth.WithSession / auth.SessionFrom); auth.ActorFrom derives the actor
from it, so there is one context value.
Every /api/v1 request other than GET, HEAD and OPTIONS must carry
X-MealQuest-CSRF equal to the session's csrf_token (constant-time
compare), else 403 {"error":{"code":"csrf"}}. The check runs after
RequireSession, so unauthenticated requests still get 401. A session
with no token is a 500, never a match against a missing header.
GET /api/v1/me returns {name, email, household: {label: "Our kitchen"},
csrfToken} with Cache-Control: no-store.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
{"verdict":"APPROVED","reviewed_sha":"15cc3c5ce4383798ee1db5d07e8c86117e6770e9","summary":"The diff meets the CSRF and GET /api/v1/me requirements. Production-router tests cover missing, wrong, and correct tokens, requests without a CSRF header for exempt methods, and 401 before 403. No token leakage or new dependency was found. gofmt -l ., go vet ./..., and go test -race -count=1 ./... passed.","findings":[]}
Posted unaltered by review_agent. This is transport, not a second review.
## Independent review — Codex `gpt-6-sol`, reasoning high
Verdict: **APPROVED**
Reviewed SHA: `15cc3c5ce4383798ee1db5d07e8c86117e6770e9`
```json
{
"verdict": "APPROVED",
"reviewed_sha": "15cc3c5ce4383798ee1db5d07e8c86117e6770e9",
"summary": "The diff meets the CSRF and GET /api/v1/me requirements. Production-router tests cover missing, wrong, and correct tokens, requests without a CSRF header for exempt methods, and 401 before 403. No token leakage or new dependency was found. gofmt -l ., go vet ./..., and go test -race -count=1 ./... passed.",
"findings": []
}
```
---
Posted unaltered by `review_agent`. This is transport, not a second review.
approver_agent
merged commit 36b975ff5b into feature/9c4eba48-9a49-4b73-a85f-a4bc19eb4062-authentik-oidc-sessions2026-10-03 10:51:27 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements Feature 03 task 4 (6472c90d). Done-condition: every non-GET/HEAD/OPTIONS request under /api/v1 requires X-MealQuest-CSRF equal to the session csrf_token (constant-time), else 403 {"error":{"code":"csrf"}}; GET /api/v1/me returns {name, email, household:{label:"Our kitchen"}, csrfToken}; tests cover missing/wrong/right header and GET needing none; quality floor passes.
Evidence (developer-run): gofmt empty; go vet clean; go test -race all packages pass; CGO_ENABLED=0 build ok; end-to-end with the real SessionManager+SQLite: /me 200 with token, no/wrong CSRF 403, correct token passes to routing. Note: RequireSession now stores the session (WithSession) so CSRF can compare; F04 settings branch must use this when rebased.
RequireSession now stores the validated session in the request context (auth.WithSession / auth.SessionFrom); auth.ActorFrom derives the actor from it, so there is one context value. Every /api/v1 request other than GET, HEAD and OPTIONS must carry X-MealQuest-CSRF equal to the session's csrf_token (constant-time compare), else 403 {"error":{"code":"csrf"}}. The check runs after RequireSession, so unauthenticated requests still get 401. A session with no token is a 500, never a match against a missing header. GET /api/v1/me returns {name, email, household: {label: "Our kitchen"}, csrfToken} with Cache-Control: no-store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Independent review — Codex
gpt-6-sol, reasoning highVerdict: APPROVED
Reviewed SHA:
15cc3c5ce4383798ee1db5d07e8c86117e6770e9Posted unaltered by
review_agent. This is transport, not a second review.