Story 1444: Functions Domain Spans
The functions broker and workers already had trace propagation plumbing. This Story adds the missing PRAMAAN domain spans from the pramaan-docs ADR-124 registry, using only the shared manual_span helper so the ADOT-owned provider remains the only tracing system.
Span Boundaries
| Span | Kind | Call site |
|---|---|---|
functions.agent_queue.enqueue | INTERNAL | WebSocket broker wraps accepted SQS enqueue work. |
functions.agent_queue.process_record | CONSUMER | Existing clerk worker SQS record span remains in place. |
functions.agent_invoke.build | INTERNAL | Existing broker envelope and trace-carrier build span remains in place. |
functions.agent_invoke.call | INTERNAL | Clerk worker wraps the actual AgentCore runtime invoke call. |
functions.projection_relay.batch | CONSUMER | Existing projection relay batch span keeps stored trace-context links. |
functions.ws_push.deliver | CLIENT | Existing ws_pusher delivery span extracts the Lambda payload trace context. |
functions.error_response.build | INTERNAL | WebSocket broker errors and shared FastAPI domain errors wrap response construction. |
Semconv Check
Standard keys: http.response.status_code messaging.system messaging.operation.name messaging.operation.type messaging.destination.name messaging.batch.message_count Custom PRAMAAN product keys: firm_id run_id form_id matter_id agent.key event.type
Guardrails
No product module calls raw tracer APIs or constructs a TracerProvider. The helper owns SpanKind, rejects span names outside the closed enum, and accepts only current standard telemetry keys plus approved PRAMAAN product dimensions.
firm_id stays a span attribute only. The patch does not add baggage writes, content capture, prompt text, matter text, filenames, or provider payloads.
Verification
uv run pytest tests/unit/shared/observability/test_manual_span.py tests/unit/test_router_ws.py tests/unit/clerk_worker/test_handler.py tests/unit/clerk_worker/test_runner.py tests/unit/ws_pusher/test_handler.py tests/unit/test_projection_outbox.py tests/integration/test_error_response_envelope.py -q uv run ruff check src/app_api/router_ws.py src/clerk_worker/runner.py src/shared/errors/http_handler.py src/shared/observability/manual_span.py tests/unit/shared/observability/test_manual_span.py tests/unit/test_router_ws.py tests/unit/clerk_worker/test_runner.py tests/integration/test_error_response_envelope.py uv run mypy --follow-imports=silent --ignore-missing-imports src/app_api/router_ws.py src/clerk_worker/runner.py src/shared/errors/http_handler.py src/shared/observability/manual_span.py bash .github/scripts/observability-guardrail-check.sh git diff --check
Recall: Story 1444 names only PRAMAAN workflow boundaries, not every function, and routes every manual span through the shared helper with registry names and explicit span kinds.