Skip to content

feat(editor): add per-request access audit middleware - #530

Open
rot1024 wants to merge 1 commit into
mainfrom
feat/editor-access-audit-log
Open

feat(editor): add per-request access audit middleware#530
rot1024 wants to merge 1 commit into
mainfrom
feat/editor-access-audit-log

Conversation

@rot1024

@rot1024 rot1024 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds accessAuditMiddleware to editor-api that emits one structured JSON line per authenticated request (prefixed with editor_access_audit ). Runs after attachOpMiddleware, so both the JWT AuthInfo (sub / email / name) and the DB-resolved user (id / email / name) are already available.
  • Adds Config.AccessAudit (env REEARTH_ACCESSAUDIT, default true) so the middleware can be disabled without a code change.
  • Emitted fields: ts, sub, user_id, email, name, method, path, status, latency_ms, remote_ip, ua, request_id, referer, auth (jwt / mock). Never logs the Authorization header or the raw JWT.
  • Skips unauthenticated / static / published / pprof paths (/api/ping, /api/published/…, /api/published_data/…, /p/…, /assets/…, /favicon…, /debug/pprof, /health, /robots.txt).

Test plan

  • go build ./... in editor/server passes
  • go vet ./internal/app/... clean
  • gofmt clean on changed files
  • go test ./internal/app/... -run TestAccessAudit: 5/5 pass
    • Disabled: no line emitted
    • Unauthenticated: no line emitted
    • Excluded paths: no line emitted
    • Authenticated: full record emitted; DB email wins over JWT email
    • JWT-only fallback: sub / email / name from AuthInfo
  • go test ./internal/app/config/...: pass with new field
  • Manual verification in dev (post-merge): a Cloud Logging query for textPayload:"editor_access_audit " should show one line per authenticated Editor request; Authorization should not appear anywhere.

Copilot AI review requested due to automatic review settings July 23, 2026 09:53
@rot1024 rot1024 changed the title feat(editor/server): add per-request access audit middleware feat(editor): add per-request access audit middleware Jul 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds lightweight per-request access audit logging to the Editor API server so authenticated usage can be counted/aggregated downstream (Cloud Logging → BigQuery) without modifying the Editor web/client.

Changes:

  • Introduces accessAuditMiddleware to emit one structured JSON audit line per authenticated request, with path-based exclusions for noisy/unauth endpoints.
  • Adds Config.AccessAudit (env REEARTH_ACCESSAUDIT, default true) to allow disabling audit logging without code changes.
  • Adds unit tests validating enabled/disabled behavior, excluded paths, and JWT/DB attribute precedence.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
editor/server/internal/app/config/config.go Adds AccessAudit config flag (default true) to toggle middleware.
editor/server/internal/app/app.go Registers accessAuditMiddleware after auth/op resolution middleware.
editor/server/internal/app/access_audit.go Implements the audit middleware and structured record format.
editor/server/internal/app/access_audit_test.go Adds tests to validate audit emission and skipping rules.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +96 to +106
rec := accessAuditRecord{
Ts: start.UTC().Format(time.RFC3339Nano),
Method: c.Request().Method,
Path: path,
Status: c.Response().Status,
LatencyMS: latency.Milliseconds(),
RemoteIP: c.RealIP(),
UserAgent: c.Request().UserAgent(),
RequestID: c.Response().Header().Get(echo.HeaderXRequestID),
Referer: c.Request().Referer(),
}
UserAgent string `json:"ua,omitempty"`
RequestID string `json:"request_id,omitempty"`
Referer string `json:"referer,omitempty"`
AuthMethod string `json:"auth,omitempty"` // "jwt" | "mock" | "debug"
Comment on lines +25 to +31
// disable color codes so the plain substring match works reliably
_ = os.Setenv("NO_COLOR", "1")
buf := &bytes.Buffer{}
log.SetOutput(buf)
t.Cleanup(func() {
log.SetOutput(os.Stdout)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants