Skip to content

Audit: Add text/plain content negotiation #449

@nycomp

Description

@nycomp

Audit: Add text/plain Content Negotiation

Parent: #424 (Audit System)
Related: #427 (Routes - JSON only)

Overview

Add text/plain response format support to all audit GET endpoints for CLI-friendly output. Currently only application/json is supported.

Tasks

1. Content Negotiation Helper

  • Create Accept header parser utility
  • Handle Accept: application/json, text/plain, */*
  • Default to JSON for unspecified/invalid Accept headers

2. Text Response Formatters

GET /traces - Compact trace list:

trace abc123  142.5ms  OK   client:timetable-app  user:js
trace def456   15.8ms  FAIL client:—              user:—

--- more: cursor=2026-03-27T09:58:12.000Z ---

GET /traces/ - Waterfall format:

trace abc123  142.5ms  OK  client:timetable-app  user:js

+0.0ms    142.5ms  GET /api/v1/students           200
+0.1ms    15.2ms     POST /auth/token/validate     200
+18.0ms   98.3ms     GET /api/v1/db/query          200

GET /traces/search - Same as GET /traces

GET /health - Simple:

OK

Acceptance Criteria

  • Accept: application/json returns JSON (current behavior)
  • Accept: text/plain returns formatted text
  • Invalid/missing Accept header defaults to JSON
  • Content-Type header matches response format
  • Contract tests cover both formats

Implementation Notes

  • Text formatters should accept model objects (not resource dicts)
  • Reuse TraceSummary, TraceTree, TraceSpan models
  • Format strings using f-strings for maintainability
  • Status: "OK" (200-299), "FAIL" (500+), "ERR" (400-499)

References

  • PRD §5.3: Content Negotiation
  • PRD §6: Trace Reconstruction (waterfall format)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions