AlphaTest · Reports · Integrator API · Data dictionary

From score to evidence, without a shadow store.

The intended post-gate v1 wire contract for attempt reports, mastery gaps, readiness, owner-produced item analytics, per-source alignment proofs, and revision orders. Every field below has a type, null rule, validation rule, owner, and approved architecture citation.

Contract baseline · 24 July 2026 · JSON over /v1 · architecture-derived

Start here

Who

The AcmeTest maintainer already delivering Platform3 QTI attempts.

Job

Fetch attempt evidence, page candidate history, materialize safely, and consume audit-grade improvement receipts without computing a score or aggregate.

Boundary

Reports composes live Platform3 facts. It stores no attempt, score, roster, mastery state, item statistic, or cohort aggregate.

Release status: contracts specified; downstream execution is parked. Attempt detail and readiness require Gates C+D; candidate history also requires an authoritative index; cohort and equivalence require A+D; materialization requires B+C+D; improvement analysis and its receipts require F+D. Gate E requires immutable prerequisite receipts before the driver launches any implementation doer or production-success eval. A candidate returning 503 is safety evidence, not a shipped capability. This follows ITD-030, ITD-040, and the superseding pre-execution rule in ITD-041.
Global null, omission, and empty rule. Every field is non-null unless its row says “Yes.” Optional fields are omitted only when their section was not requested or is inapplicable and the enclosing schema explicitly permits omission. JSON null means “known absence” only where listed. [] means the section was requested and the authority returned zero rows. Unknown request fields and repeated scalar query parameters return 400. Clients must ignore additive response fields per ITD-015.

Exact post-gate wire examples

The commands are client-construction contracts for use only after their named gates pass; they do not claim the routes currently exist.

Fetch complete attempt evidence

curl --fail-with-body --get \
  "$REPORTS_BASE_URL/v1/attempt-reports/att_7F3k9" \
  -H "Authorization: Bearer $REPORTS_TOKEN" \
  -H "Accept: application/json" \
  --data-urlencode "view=evidence"
{
  "object":"attempt_report","attemptId":"att_7F3k9","qtiSessionId":"session_A92",
  "qtiTestId":"qti_form_math5_b","resultRecordId":"result_4821",
  "candidateSourcedId":"student_1042","administrationId":"admin_fall_2026",
  "contentTestSpecId":"spec_tx_math_5_gate_v3","testKind":"mastery_gate","status":"scored",
  "score":{"value":87,"minimum":0,"maximum":100,"unit":"percent","scaleVersion":null},
  "mastery":[{"kind":"standard","caseGuid":"case_tx_5_3a","parentCaseGuid":null,
    "state":"gap","estimate":0.71,"threshold":0.80,"uncertainty":0.04,
    "uncertaintyKind":"standard_error","policyId":"gate-policy-5","policyVersion":"3",
    "evidence":[{"qtiItemId":"item_301","qtiOutcomeId":"outcome_901",
      "resultComponentId":"component_77","contribution":-0.09,"observedAt":"2026-07-15T14:22:09Z"}]}],
  "gate":{"status":"fail","criteriaVersion":"3","achieved":0.71,"required":0.80,
    "gapCaseGuids":["case_tx_5_3a"],"coverageEvidenceId":"coverage_552"},
  "diagnostic":null,
  "sources":[
    {"service":"qti","resourceId":"att_7F3k9","observedAt":"2026-07-15T14:22:10Z","version":"qti-etag-19","status":"current"},
    {"service":"results","resourceId":"result_4821","observedAt":"2026-07-15T14:22:10Z","version":"result-v4","status":"current"},
    {"service":"content","resourceId":"spec_tx_math_5_gate_v3","observedAt":"2026-07-15T14:22:10Z","version":"3","status":"current"}],
  "omitted":["readiness"],"incompleteSections":[],"observedAt":"2026-07-15T14:22:10Z",
  "requestId":"req_N7h2","traceId":"trace_J5m8"
}

Exact schema: AttemptReport. diagnostic is null because the report is a mastery gate; readiness is omitted because it is a focused sub-resource.

Parse a complete adaptive-diagnostic report

Normative fixed synthetic fixture, not a released route. This body binds every DiagnosticDetail field to the evidence-bearing standard/KC map required by ITD-005 and ITD-007. Its opaque ids illustrate native Platform3 pass-through positions under ITD-003; they are not aliases or claims that these records exist. Use only after Gates C+D open.
curl --fail-with-body --get \
  "$REPORTS_BASE_URL/v1/attempt-reports/att_diag_8K2m" \
  -H "Authorization: Bearer $REPORTS_TOKEN" \
  -H "Accept: application/json" \
  --data-urlencode "view=evidence"
{
  "object":"attempt_report","attemptId":"att_diag_8K2m","qtiSessionId":"session_diag_D41",
  "qtiTestId":"qti_adaptive_math5_fall","resultRecordId":"result_diag_7102",
  "candidateSourcedId":"student_1042","administrationId":"admin_diag_fall_2026",
  "contentTestSpecId":"spec_math5_diagnostic_v2","testKind":"adaptive_diagnostic","status":"scored",
  "score":{"value":214.6,"minimum":null,"maximum":null,"unit":"mastery_scale","scaleVersion":"ams-math-2"},
  "mastery":[
    {"kind":"standard","caseGuid":"case_math5_num","parentCaseGuid":null,
      "state":"mastered","estimate":0.91,"threshold":0.80,"uncertainty":0.03,
      "uncertaintyKind":"standard_error","policyId":"adaptive-math5","policyVersion":"2",
      "evidence":[{"qtiItemId":"item_diag_101","qtiOutcomeId":"outcome_diag_501","resultComponentId":"component_diag_801","contribution":0.14,"observedAt":"2026-07-15T15:03:01Z"}]},
    {"kind":"knowledge_component","caseGuid":"case_math5_num_frac","parentCaseGuid":"case_math5_num",
      "state":"mastered","estimate":0.88,"threshold":0.80,"uncertainty":0.04,
      "uncertaintyKind":"standard_error","policyId":"adaptive-math5","policyVersion":"2",
      "evidence":[{"qtiItemId":"item_diag_102","qtiOutcomeId":"outcome_diag_502","resultComponentId":"component_diag_802","contribution":0.11,"observedAt":"2026-07-15T15:03:34Z"}]},
    {"kind":"standard","caseGuid":"case_math5_geo","parentCaseGuid":null,
      "state":"not_yet","estimate":0.72,"threshold":0.80,"uncertainty":0.05,
      "uncertaintyKind":"standard_error","policyId":"adaptive-math5","policyVersion":"2",
      "evidence":[{"qtiItemId":"item_diag_103","qtiOutcomeId":"outcome_diag_503","resultComponentId":"component_diag_803","contribution":-0.04,"observedAt":"2026-07-15T15:04:02Z"}]},
    {"kind":"knowledge_component","caseGuid":"case_math5_geo_volume","parentCaseGuid":"case_math5_geo",
      "state":"not_yet","estimate":0.69,"threshold":0.80,"uncertainty":0.06,
      "uncertaintyKind":"standard_error","policyId":"adaptive-math5","policyVersion":"2",
      "evidence":[{"qtiItemId":"item_diag_104","qtiOutcomeId":"outcome_diag_504","resultComponentId":"component_diag_804","contribution":-0.06,"observedAt":"2026-07-15T15:04:39Z"}]},
    {"kind":"standard","caseGuid":"case_math5_alg","parentCaseGuid":null,
      "state":"gap","estimate":0.43,"threshold":0.80,"uncertainty":0.04,
      "uncertaintyKind":"standard_error","policyId":"adaptive-math5","policyVersion":"2",
      "evidence":[{"qtiItemId":"item_diag_105","qtiOutcomeId":"outcome_diag_505","resultComponentId":"component_diag_805","contribution":-0.19,"observedAt":"2026-07-15T15:05:10Z"}]},
    {"kind":"knowledge_component","caseGuid":"case_math5_alg_patterns","parentCaseGuid":"case_math5_alg",
      "state":"gap","estimate":0.38,"threshold":0.80,"uncertainty":0.05,
      "uncertaintyKind":"standard_error","policyId":"adaptive-math5","policyVersion":"2",
      "evidence":[{"qtiItemId":"item_diag_106","qtiOutcomeId":"outcome_diag_506","resultComponentId":"component_diag_806","contribution":-0.22,"observedAt":"2026-07-15T15:05:42Z"}]}
  ],
  "gate":null,
  "diagnostic":{"scaleScore":214.6,"scaleVersion":"ams-math-2","calibrationVersion":"cal-2026-01",
    "standardError":2.7,"stoppingReason":"classifications_complete","administeredItemCount":24,"nweaNormsSet":null},
  "sources":[
    {"service":"qti","resourceId":"att_diag_8K2m","observedAt":"2026-07-15T15:06:00Z","version":"qti-etag-27","status":"current"},
    {"service":"results","resourceId":"result_diag_7102","observedAt":"2026-07-15T15:06:00Z","version":"result-v6","status":"current"},
    {"service":"content","resourceId":"spec_math5_diagnostic_v2","observedAt":"2026-07-15T15:06:00Z","version":"2","status":"current"},
    {"service":"case","resourceId":"case_math5","observedAt":"2026-07-15T15:06:00Z","version":"case-etag-44","status":"current"},
    {"service":"mastery_engine","resourceId":"run_diag_3301","observedAt":"2026-07-15T15:06:00Z","version":"ams-math-2/cal-2026-01","status":"current"},
    {"service":"oneroster","resourceId":"student_1042","observedAt":"2026-07-15T15:06:00Z","version":"oneroster-etag-18","status":"current"},
    {"service":"unknown","resourceId":"admin_diag_fall_2026","observedAt":"2026-07-15T15:06:00Z","version":"administration-v3","status":"current"}
  ],
  "omitted":["readiness"],"incompleteSections":[],"observedAt":"2026-07-15T15:06:00Z",
  "requestId":"req_diag_P4s8","traceId":"trace_diag_Q9t2"
}

How to read this fixture. gate is a known inapplicable value and therefore JSON null; nweaNormsSet is null because this fixture makes no MAP crosswalk. readiness is the only omitted section and is named in omitted; incompleteSections: [] says no requested enrichment failed. The six mastery rows contain both CASE entity kinds and all three required diagnostic classifications, each with a nonempty QTI/Results evidence chain. The score, classification policy, terminal reason, count, and versions are fixed synthetic pass-through values—not calculations by Reports. The seven receipts make the fixture’s consulted authorities explicit; service: unknown preserves the current SourceRef vocabulary for the Administration receipt instead of inventing an enum. Provenance: ITD-003, ITD-005, ITD-007, and ITD-012.

List candidate reports, then continue

curl --fail-with-body --get \
  "$REPORTS_BASE_URL/v1/candidates/student_1042/attempt-reports" \
  -H "Authorization: Bearer $REPORTS_TOKEN" \
  --data-urlencode "testKind=mastery_gate" \
  --data-urlencode "limit=2"
{
  "data":[],
  "nextCursor":"eyJvcGFxdWUiOiJjdXJzb3IifQ",
  "hasMore":true,
  "observedAt":"2026-07-15T14:22:10Z",
  "sources":[{"service":"results","resourceId":"student_1042","observedAt":"2026-07-15T14:22:10Z","version":"page-v8","status":"current"}]
}
curl --fail-with-body --get \
  "$REPORTS_BASE_URL/v1/candidates/student_1042/attempt-reports" \
  -H "Authorization: Bearer $REPORTS_TOKEN" \
  --data-urlencode "testKind=mastery_gate" \
  --data-urlencode "limit=2" \
  --data-urlencode "cursor=eyJvcGFxdWUiOiJjdXJzb3IifQ"

data: [] is valid: that page has zero authoritative rows. It does not mean omitted. A real row is the summary projection of AttemptReport.

Materialize idempotently

curl --fail-with-body \
  "$REPORTS_BASE_URL/v1/attempt-reports:materialize" -X POST \
  -H "Authorization: Bearer $REPORTS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: acmetest-att-7F3k9-v1" \
  --data '{"attemptId":"att_7F3k9","administrationId":"admin_fall_2026","view":"summary"}'
{"operationId":"op_93wK","report":{"object":"attempt_report","attemptId":"att_7F3k9","qtiSessionId":"session_A92","qtiTestId":"qti_form_math5_b","resultRecordId":"result_4821","candidateSourcedId":"student_1042","administrationId":"admin_fall_2026","contentTestSpecId":"spec_tx_math_5_gate_v3","testKind":"mastery_gate","status":"scored","score":{"value":87,"minimum":0,"maximum":100,"unit":"percent","scaleVersion":null},"mastery":[],"gate":{"status":"fail","criteriaVersion":"3","achieved":0.71,"required":0.80,"gapCaseGuids":["case_tx_5_3a"],"coverageEvidenceId":"coverage_552"},"diagnostic":null,"sources":[{"service":"results","resourceId":"result_4821","observedAt":"2026-07-15T14:22:10Z","version":"result-v4","status":"current"}],"omitted":["mastery","itemEvidence","readiness"],"incompleteSections":[],"observedAt":"2026-07-15T14:22:10Z","requestId":"req_R6v3","traceId":"trace_C1n7"}}

For 24 hours, an identical retry suppresses writes, preserves operationId, recomposes current Platform3 truth, and adds Idempotent-Replayed: true. A changed body with the same key is 409.

Handle failures by type and status

HTTP/1.1 409 Conflict
Content-Type: application/problem+json

{"type":"https://alphatest-andymontgomery-9773s-projects.vercel.app/reports/integrator_api/data_dictionary/problems/idempotency-conflict","title":"Idempotency key conflicts with an earlier request","status":409,"detail":"Use a new Idempotency-Key for a different request body.","instance":"/problems/occurrences/req_Z2d6","requestId":"req_Z2d6","traceId":"trace_M9p1","retryable":false,"dependency":null,"fieldErrors":null,"operationId":"op_93wK"}

All stable suffixes and recovery semantics are in the registry; each type URI dereferences.

Inspect one completed improvement run

Normative synthetic fixture, not a released route. This is the minimum complete response after Gates F+D open. Owner artifact references are opaque and are dereferenced live; the response contains no copied learner facts.
{
  "object":"improvement_run",
  "improvementRunId":"ir_2026_math5_0042",
  "administrationId":"admin_fall_2026",
  "contentTestSpecId":"spec_tx_math_5_gate_v3",
  "contentTestSpecVersion":"3",
  "status":"completed",
  "analysisPolicyId":"reports-item-policy",
  "analysisPolicyVersion":"4",
  "formulaVersion":"alignment-v1",
  "metricStatuses":[
    {"metric":"item_difficulty","status":"available","artifactRef":"analytics:item-form:af_881","reasonCode":null},
    {"metric":"item_discrimination","status":"available","artifactRef":"analytics:item-form:af_881","reasonCode":null},
    {"metric":"distractor_distribution","status":"unavailable","artifactRef":null,"reasonCode":"owner_artifact_missing"},
    {"metric":"form_summary","status":"available","artifactRef":"analytics:item-form:af_882","reasonCode":null}
  ],
  "namedSourceCount":2,
  "alignmentRecordCount":2,
  "revisionOrderCount":1,
  "blockedOrderCount":0,
  "omissions":["distractor_distribution"],
  "receipt":{"mediaType":"application/zip","sha256":"946cf2f5d3e0a611b87e17fc1bf93fe663d82b99ae6bc5204d0c95efb3c2d91a","downloadUrl":"https://receipts.alphatest.example/r/ir_2026_math5_0042?sig=opaque","expiresAt":"2026-07-24T16:15:00Z"},
  "createdAt":"2026-07-24T15:00:00Z",
  "completedAt":"2026-07-24T15:14:03Z",
  "requestId":"req_improve_42",
  "traceId":"trace_improve_42"
}

Exact schemas: ImprovementRun, MetricStatus, and ReceiptLink. An unavailable independent metric is named in both metricStatuses and omissions; it does not authorize private Reports math. Completion is valid because all named sources have alignment records and every tripped order is acknowledged or explicitly blocked, as required by ITD-040.

Dependency gates: no fabricated upstreams

Gate A — Analytics contracts. Cohort and equivalence success is blocked until production Analytics publishes versioned class/school-grade per-standard mastery rollups and form-equivalence evidence with population, suppression, formula/method, interval, tolerance, decision, and receipts. Reports never computes either privately. ITD-009, ITD-010.
Gate B — Results + Caliper materialization. Blocked until versioned result_record/test_result_components writes, conditional/idempotent behavior, matching Caliper profile, exact read-back, and a duplicate-free forced partial-failure replay are proven. No local outbox containing learning facts and no guessed body. ITD-032.
Gate C — exact attempt composition. The authenticated ?qtiAttemptId= lookup primitive is confirmed, but its published contract does not yet return the dereferenceable candidate, Administration, QTI session/test/item outcomes, Content test_spec, test kind, gate decision, KC/mastery, and component evidence required for a report. Runtime-only collection fields, producer-id guessing, canonical-response parsing, tenant scans, partial reports, and local correlation tables are forbidden substitutes. ITD-028.
Gate D — coherent runtime and two-tenant proof. One immutable runtime must serve all three test kinds and two production-signed principals must prove anonymous 401, same-tenant success, bidirectional non-enumerating 404, and cache/idempotency/trace isolation. ITD-029, ITD-031.
Gate E — pre-execution eligibility. Specification work may proceed, but the driver must park each implementation cell before launching its doer or production-success eval until a signed prerequisite manifest dereferences the applicable B/C/D receipts; adaptive diagnostics additionally require the production-learner Mastery Engine receipt, cohort/equivalence require A, and improvement-loop work requires F. Stubs, sandbox payloads, public token mints, permanent 503s, and predetermined failing evals do not open the gate. ITD-041, ITD-034.
Gate F — improvement-loop owner contracts. Improvement analysis stays closed until authenticated Analytics/Caliper artifacts expose the exact item/form grain in ITD-036, Content exposes immutable crosswalk inputs for the ITD-037 formula, and Bank plus Blueprint expose authenticated, idempotent, same-tenant receiver commands with accepted/replayed/cross-tenant receipts. Missing independent metrics become unavailable; missing receivers become blocked_upstream. Reports never substitutes local analytics, edits owner resources, or marks an undelivered order complete. Release also requires the production acceptance chain in ITD-040.

Wire conventions and scalars

NameType / rangeMeaning and validationOwner · provenance
Platform3 referencestring, 1–255 UTF-8 bytesOpaque, case-sensitive pass-through; whitespace rejected; no UUID/prefix assumption.Upstream · ITD-003
InstantRFC 3339 UTC stringTerminal Z; fractional seconds accepted; offsets and leap seconds rejected.Reports normalization · ITD-012
Proportionnumber, 0–1 inclusiveFinite JSON number, at most six fractional digits.Blueprint/Analytics pass-through · ITD-010/011
Countinteger, 0–2,147,483,647Non-negative snapshot count, never inferred from an omitted array.Upstream · ITD-009
AuthorizationBearer JWTRequired claims: sub, tenantId, iat, exp, role, and reports:read or reports:write. studentIds/schoolSourcedIds/classSourcedIds narrow access.Reports · ITD-021/024
Idempotency-Key1–255 visible ASCIIRequired for materialize and improvement analyze; no whitespace/control chars; tenant+method+path scope; 24-hour replay retention.Reports · ITD-020/038
Idempotent-Replayedresponse tokentrue when writes were suppressed and live truth recomposed; absence means false.Reports · ITD-020

Canonical response resources

AttemptReport DEFERRED · C+D

FieldTypeNull?Meaning / validationOwner · provenance
objectenumNoAlways attempt_report.Reports · ITD-004
attemptIdPlatform3 refNoExact QTI attempt id; equals path value.QTI · ITD-003
qtiSessionIdPlatform3 refYesNull only if authoritative contract has no separate session ref.QTI · ITD-004
qtiTestIdPlatform3 refNoAdministered QTI test/form.QTI · ITD-003
resultRecordIdPlatform3 refNoSettled Results record read back after write-through.Results · ITD-002
candidateSourcedIdPlatform3 refNoOneRoster candidate, intersected with JWT claims.OneRoster · ITD-003/014
administrationIdPlatform3 refNoAdministration glue id; not a roster/attempt alias.Administration · ITD-004
contentTestSpecIdPlatform3 refNoContent test_spec governing criteria and crosswalk.Content · ITD-003
testKindenumNomastery_gate|adaptive_diagnostic|formative|unknown; unknown response-only.Content · ITD-008/015
statusenumNoscored|indeterminate|unknown. An attempt without the settled Results fact required to construct this resource returns the pinned dependency-incomplete problem (503), so an unscored state is never projected as an AttemptReport.Results/QTI · ITD-002/023
scoreScoreNoSettled upstream score; never recomputed.Results · ITD-001
masteryMasteryRow[], max 5,000NoUnique by kind+caseGuid. Empty and named in omitted when projection excludes it.Results/CASE · ITD-005
gateGateDecisionYesRequired for mastery_gate; null otherwise. Missing criteria yields indeterminate object.Results/Content · ITD-006
diagnosticDiagnosticDetailYesRequired for adaptive_diagnostic; null otherwise.Mastery engine/Results · ITD-007
sourcesSourceRef[], 1–32NoReceipt for every consulted upstream; required failure returns 503.Reports · ITD-012
omittedunique enum[]NoValues: mastery, itemEvidence, readiness; projection omissions only.Reports · ITD-004
incompleteSectionsProblemDetails[]NoOptional enrichment failures; empty means complete.Reports · ITD-012
observedAtInstantNoLive composition completion time.Reports · ITD-012
requestId, traceIdstring, 1–128NoBoundary/distributed correlation; no learning facts.Reports · ITD-013

Score

FieldType / nullRule
valuefinite number · noSettled upstream value.
minimum, maximumfinite number · yesNull only for unbounded scale; when present minimum ≤ value ≤ maximum.
unitenum · nopoints, percent, mastery_scale, unknown.
scaleVersionstring 1–128 · yesRequired for mastery_scale; otherwise null only if source has no version.

SourceRef

FieldType/nullRule
serviceenum/noqti, results, analytics, content, case, oneroster, caliper, mastery_engine, bank, blueprint, unknown.
resourceIdPlatform3 ref/noNative upstream id.
observedAtInstant/noTime this request observed source.
versionstring 1–255/yesETag/version; null only when upstream supplies neither.
statusenum/nocurrent, stale, unavailable, unknown; required sources must be current.

The common receipt fields derive from ITD-012; Bank and Blueprint receiver receipts are required by ITD-038.

Mastery and item evidence

MasteryRow

FieldTypeNull?Rule / owner
kindenumNostandard or knowledge_component · CASE/Results.
caseGuidPlatform3 refNoLive-dereferenceable CASE GUID.
parentCaseGuidPlatform3 refYesRequired for child KC when parent exists; null for root standard.
stateenumNomastered, not_yet, gap, insufficient_evidence, unknown.
estimate, thresholdfinite numberNoUpstream estimate and applied policy threshold; no default.
uncertaintynumber ≥0NoMagnitude interpreted by uncertaintyKind.
uncertaintyKindenumNostandard_error, interval_half_width, policy_margin, unknown.
policyId, policyVersionstring 1–255NoImmutable Results/blueprint policy identity.
evidenceItemEvidence[], 1–500NoAt least one contribution; empty invalid.

Every row and field is the evidence-bearing contract pinned by ITD-005; values pass through Results, QTI, CASE, or the mastery engine as named.

ItemEvidence

FieldTypeNull?Rule / owner
qtiItemIdPlatform3 refNoAdministered item id, not copied content · QTI.
qtiOutcomeIdPlatform3 refNoScored item outcome · QTI.
resultComponentIdPlatform3 refYesNull only until Gate B exposes a stable Results component id.
contributionfinite numberNoSigned policy contribution; Reports does not compute it.
observedAtInstantNoAuthoritative outcome time.

Test-kind and audit resources

GateDecision

FieldType/nullRule
statusenum/nopass, fail, indeterminate, unknown; Results-owned.
criteriaVersionstring/noImmutable Content criteria.
achievedfinite number/yesNull only when indeterminate has no valid measurement.
requiredfinite number/noBlueprint threshold; absence forces an indeterminate problem.
gapCaseGuidsunique refs[]/noComplete on fail, empty on pass, possibly nonempty when indeterminate.
coverageEvidenceIdPlatform3 ref/yesNull forces indeterminate.

ITD-006.

DiagnosticDetail

FieldType/nullRule
scaleScorefinite number/noRIT-like mastery score, not NWEA-issued.
scaleVersion, calibrationVersionstring/noImmutable versions.
standardErrornumber ≥0/noScore uncertainty.
stoppingReasonenum/noclassifications_complete, precision_target_met, max_items, time_budget, unknown.
administeredItemCountinteger ≥1/noQTI count.
nweaNormsSetstring/yesRequired only for a MAP crosswalk.

ITD-007 requires the terminal reason; the allowed values are a reviewed pass-through from the approved Mastery Engine AdaptiveRun source binding.

ReadinessReport DEFERRED · C+D

PathType/nullRule · owner
attemptIdPlatform3 ref/noQTI attempt.
entriesarray 1–100/noUnique sourceTest+sourceVersion.
entries[].decisionenum/noprojected_pass, not_ready, indeterminate, unknown.
sourceTest, sourceVersion, crosswalkVersionstring/noNamed test/publication and immutable blueprint crosswalk.
coverageFractionproportion/noMust equal 1 for projected_pass.
dokDominanceenum/nosatisfied, not_satisfied, indeterminate; satisfied required to project pass.
qualifyingBlueprintSlotIdsunique refs[]/noNonempty for projected_pass.
decisionRuleId, decisionRuleVersionstring/noNamed versioned rule.
limitationsstring[], max 50/noEach 1–500 chars; empty only when none.
sourcesSourceRef[], 1–32/noResults/Content/blueprint receipts.

ITD-011.

EquivalenceReport DEFERRED · A+D

FieldType/nullRule · owner
qtiTestId, comparisonQtiTestIdsref + unique refs[]/noSubject/compared QTI forms.
contentTestSpecIdref/noShared Content blueprint.
coverageMatch, dokMatchboolean/noBlueprint evidence.
sampleSizesobject<formId,count>/noExactly one Analytics count per form.
method, analysisVersionstring/noNamed Analytics method/version.
statistic, confidenceInterval.lower/upper, tolerancefinite numbers/nolower ≤ statistic ≤ upper; tolerance ≥0.
decisionenum/noequivalent, not_equivalent, insufficient_evidence, unknown.
evidenceArtifactUrlHTTPS URL/yesNull only for insufficient evidence.
sourcesSourceRef[], 1–32/noQTI/Analytics/Content/blueprint receipts.

ITD-010.

CohortReport minimum DEFERRED · A+D

FieldType/nullRule
scope.typeenum/noclass or school_grade; matching sourcedIds/OneRoster grade required.
rollupId, formulaVersionref + string/noNative Analytics identity/formula.
asOfInstant/noAnalytics snapshot.
populationCountcount/noPopulation under Analytics definition.
suppression.statusenum/nonot_suppressed, suppressed, unknown; suppressed exposes no derivable values.
sourceSourceRef/noAnalytics receipt.

ITD-009. This is a post-gate outbound obligation, not a fabricated mapping.

Improvement-loop resources DEFERRED · F+D

Exact intended wire schema, not a claim of availability. These resources compose Analytics, Caliper, Content, Bank, and Blueprint owner contracts. Gate F remains closed. Fields labeled “owner pass-through” may be populated only from the named authenticated artifact; unavailable owner fields are never calculated locally.

ImprovementRun

FieldTypeNull?Meaning / validationOwner · provenance
objectenumNoAlways improvement_run.Reports · ITD-040
improvementRunIdstring 1–255NoOpaque AlphaTest workflow id; immutable in tenant.Reports engine · ITD-039
administrationIdPlatform3 refNoExact scored administration analyzed; equals command path.Administration · ITD-038
contentTestSpecId, contentTestSpecVersionref + stringNoImmutable Content blueprint and version used by every alignment row.Content · ITD-037/038
statusenumNoqueued|analyzing|completed|completed_with_omissions|blocked_upstream|failed|unknown. completed is legal only when ITD-040 acceptance invariants hold.Reports engine · ITD-039/040
analysisPolicyId, analysisPolicyVersionstring 1–255NoReleased threshold-policy identity; immutable for the run.Reports policy · ITD-038
formulaVersionstring 1–255NoAlignment formula version; currently alignment-v1.Reports policy · ITD-037
metricStatusesMetricStatus[], exactly 4NoExactly one row for each required item/form metric; unavailable metrics remain present.Analytics/Caliper composition · ITD-036
namedSourceCountCountNoNumber of named source tests in the immutable blueprint crosswalk.Content · ITD-037/040
alignmentRecordCountCountNoMust equal namedSourceCount before completed.Reports composition · ITD-040
revisionOrderCount, blockedOrderCountCountNoTotal tripped orders and subset explicitly blocked upstream; counts derive from workflow state, never learner facts.Reports engine · ITD-039/040
omissionsunique enum[], max 8NoAny unavailable metric names; values: item_difficulty|item_discrimination|distractor_distribution|form_summary|predicted_actual.Reports · ITD-036/037
receiptReceiptLinkYesRequired for completed/completed_with_omissions; null while nonterminal or if evidence dereference fails closed.Reports evidence surface · ITD-040
createdAt, completedAtInstantcompletedAt onlycompletedAt required exactly for terminal states and not before createdAt.Reports engine · ITD-039
requestId, traceIdstring 1–128NoBoundary and distributed trace correlation.Reports · ITD-013

MetricStatus

FieldType/nullRule
metricenum/noitem_difficulty|item_discrimination|distractor_distribution|form_summary; exactly one of each per run.
statusenum/noavailable|unavailable|suppressed|stale|unknown. Only available may trigger an order.
artifactRefPlatform3 ref/yesImmutable Analytics/Caliper artifact id; required for available or suppressed, null for unavailable.
populationCount, sampleCountCount/yesOwner-produced counts; required when available, null when unavailable or disclosure is suppressed.
suppressionStatusenum/nonot_suppressed|suppressed|unknown.
suppressionRulestring 1–255/yesRequired when suppressed; otherwise null.
analysisWindow.start, .endInstant/yesBoth present or both null; start ≤ end; required when available.
formulaVersionstring 1–255/yesOwner formula; required when available or suppressed.
reasonCodeenum/yesNull when available; otherwise owner_artifact_missing|owner_field_missing|suppressed|stale|receiver_unavailable|unknown.

All metric values, counts, suppression rules, windows, and formula versions are owner pass-throughs required by ITD-036.

AlignmentReport

FieldType/nullRule / owner
improvementRunId, sourceKeyref + string/noRun id and URL-safe immutable key unique in the run · Reports/Content.
sourceAssessment, sourceVersionstring 1–255/noNamed external assessment and immutable publication version · Content.
contentTestSpecId, contentTestSpecVersionref + string/noTarget blueprint identity · Content.
crosswalkHash64 lowercase hex/noSHA-256 of immutable complete crosswalk input · Content.
formulaVersionstring/noalignment-v1 for the pinned formula.
numerator, denominatorfinite number/noBoth ≥0; denominator >0. Missing, ambiguous, stale, or lower-DOK rows add zero to numerator but retain weight in denominator.
alignmentPercentnumber 0–100/no100 × numerator / denominator, rounded to six fractional digits only for transport.
contributionsAlignmentContribution[], 1–10,000/noExactly one row for every source requirement; sum of weightedContribution equals numerator and sum of weight equals denominator.
predictedActualPredictedActualComparison/yesPresent only from an authenticated Analytics external-score artifact; null is explicit and does not alter structural alignment.
limitationsstring[], max 100/noEach 1–500 chars; names missing, ambiguous, stale, lower-DOK, or suppressed evidence.
receiptReceiptLink/noContent-addressed immutable bundle for this named source.

AlignmentContribution

FieldType/nullRule
sourceRequirementIdPlatform3 ref/noExact source requirement; unique in report.
caseGuidPlatform3 ref/yesMapped CASE GUID; null when no unambiguous mapping exists.
blueprintSlotIdPlatform3 ref/yesMapped target slot; null makes coverage 0.
weightfinite number >0/noSource blueprint point/item weight; never defaulted or dropped.
coverage, rigorinteger 0 or 1/noCoverage is 1 only for a valid mapping; rigor is 1 only when target DOK ≥ source DOK.
sourceDok, targetDokinteger 1–4; target nullableSource and mapped target DOK; target null when uncovered.
weightedContributionfinite number ≥0/noExactly weight × coverage × rigor.
reasonCodeenum/yesNull only for full contribution; otherwise missing_mapping|ambiguous_mapping|stale_mapping|lower_dok|unknown.

The zero-penalizing formula and complete contribution ledger are normative in ITD-037.

PredictedActualComparison

FieldType/nullRule
artifactRefPlatform3 ref/noImmutable Analytics external-score comparison artifact.
populationCountCount/noOwner-defined eligible population.
suppressionStatus, suppressionRuleenum + string/second nullableStatus is not_suppressed|suppressed|unknown; rule required when suppressed.
method, analysisVersionstring/noNamed Analytics method and immutable version.
predictedPassCount, actualPassCount, agreementCountCount/yesRequired when not suppressed; each ≤ populationCount. Null together when suppressed.
observedAgreementProportion/yesRequired when not suppressed and equals agreementCount/populationCount; null when suppressed.

This is a separate Analytics-owned comparison; it is never blended into the structural score. ITD-037.

RevisionOrder

FieldType/nullRule / owner
revisionOrderIdstring 1–255/noDeterministic id from tenant + target + native subject ids + policy/version + evidence digest · Reports.
improvementRunId, administrationIdrefs/noOwning run and native administration · Reports/Administration.
targetModuleenum/nobank|blueprint.
requestedActionenum/noregenerate_item|rotate_item|review_miskey|tag_distractor|apply_calibration_delta|repair_crosswalk; must be valid for target.
qtiItemId, qtiFormId, qtiTestIdPlatform3 refs/yesNative QTI subjects; the policy declares which are required for each action.
contentTestSpecId, contentTestSpecVersionref + string/noImmutable governing blueprint · Content.
caseGuids, sourceKeysunique string[], max 1,000/noCASE/source-test subjects; empty only when action does not address one.
reasonCodesunique enum[], 1–20/nolow_discrimination|difficulty_out_of_band|dead_distractor|untagged_distractor|miskey_evidence|readiness_tolerance_breach|blueprint_coverage_defect|blueprint_rigor_defect.
observedMetric.name, .value, .unitstring + finite number + enum/noOwner metric and unit proportion|count|points|percent.
threshold.operator, .valueenum + finite number/noOperator lt|lte|gt|gte|outside; deterministic comparison must be true.
analysisPolicyId, analysisPolicyVersionstring/noReleased trigger policy.
evidenceRefsSourceRef[], 1–32/noImmutable Analytics/Caliper/Content receipts; no copied metrics.
statusenum/nopending|accepted|replayed|blocked_upstream|rejected|superseded|unknown. Accepted/replayed require targetReceipt.
targetReceiptSourceRef/yesBank/Blueprint acknowledgement; null only before acknowledgement or when blocked.
supersedesRevisionOrderIdstring/yesSame-tenant prior order; null if none.
createdAt, updatedAtInstant/noLifecycle timestamps; updatedAt ≥ createdAt.

Every subject, threshold, action, target, and acknowledgement field is required by ITD-038; workflow-only persistence is constrained by ITD-039.

RevisionOrderPage

FieldType/nullRule
dataRevisionOrder[], no0–100 rows belonging to the path run and verified tenant.
nextCursorstring 1–2048/yesOpaque tenant/auth/run/filter-bound cursor; null at end.
hasMoreboolean/noExactly nextCursor != null.
observedAtInstant/noComposition time.
FieldType/nullRule
mediaTypeenum/noapplication/zip|application/json.
sha25664 lowercase hex/noDigest of immutable receipt bytes.
downloadUrlHTTPS URL/noShort-lived, tenant-authorized URL; contains no credential in the JSON other than the opaque expiring signature.
expiresAtInstant/noStrictly after response observedAt; clients must re-fetch metadata after expiry.

Bundles contain owner artifact references, per-source contributions, versions, threshold decisions, order lifecycle, receiver receipts, omissions, and digest—never credentials or learner facts. ITD-040.

Writes, filters, and paging

MaterializeAttemptRequest DEFERRED · B+C+D

FieldTypeRequiredRule
attemptIdPlatform3 refYesScored QTI attempt in verified tenant/scope · ITD-002.
administrationIdPlatform3 refYesMust correlate; mismatch is safe validation failure · ITD-004.
viewenumNosummary default, standards, evidence; response projection only.

AnalyzeImprovementRequest DEFERRED · F+D

InputTypeRequiredRule
administrationId pathPlatform3 refYesOne scored administration in the verified tenant and caller scope.
Idempotency-Key header1–255 visible ASCIIYesTenant+method+concrete path scoped; deterministic replay returns the same run id and current representation.
request bodynoneNoMust be absent or zero bytes. Policy and formula are server-released configuration, not caller-selected inputs; a nonempty body returns validation 400.

The path grain, mandatory idempotency, and versioned policy requirement are fixed by ITD-016 and ITD-038. No caller policy field is invented.

AttemptReportPage DEFERRED · C+D + index

FieldType/nullRule
dataAttemptReport[], no0–100 summary rows; candidate matches path.
nextCursorstring 1–2048/yesOpaque, tenant/auth/filter-bound; null at end.
hasMoreboolean/noExactly nextCursor != null.
observedAtInstant/noPage composition time.
sourcesSourceRef[]/noResults and identity receipts.

Allowlisted query

QueryAppliesType/defaultValidation
viewattempt detail/materializeenum/summarysummary, standards, evidence.
qtiTestIdcandidate listref/omittedExact native QTI test-id match. This is the wire name for the testId filter concept in ITD-035; testId itself is unsupported because ITD-003 forbids aliases.
testKindcandidate listenum/omittedmastery_gate, adaptive_diagnostic, formative; matched against authoritative Results→Content data, never caller or fixture labels.
statuscandidate listenum/omittedscored or indeterminate; exact match.
statusrevision-order listenum/omittedExact RevisionOrder status; response-only unknown cannot be requested.
targetModulerevision-order listenum/omittedbank or blueprint.
modifiedSincecandidate listInstant/omittedInclusive Results modification lower bound.
sortcandidate listenum/-modifiedAtOnly -modifiedAt; attemptId ascending tie-break.
limitcandidate or revision-order listinteger/251–100; no sign, decimal, whitespace, repeat.
cursorcandidate or revision-order listopaque/omittedBinds tenant, authorization fingerprint, resource id, normalized filters, sort, and limit. Changed, expired, tampered, or wrong-principal cursors return validation 400.

Every returned row satisfies every supplied filter after authorization. No match returns 200, data: [], nextCursor: null, and hasMore: false. Any unknown query name—including testId—returns the typed unsupported-parameter 400; it is never ignored. Alignment detail and ImprovementRun detail accept no query parameters.

Native ids: ITD-003; query and paging rules: ITD-018; list release gate: ITD-027; server-enforced filter invariants and cursor binding: ITD-035; improvement list shape: ITD-040.

Problem details and failures

ProblemDetails

FieldType/nullRule
typeabsolute HTTPS URI/noStable, dereferenceable URI.
titlestring 1–120/noStable summary; do not branch on text.
statusinteger 400–599/noEquals HTTP status.
detailstring 1–1000/noNo cross-tenant existence or upstream body.
instanceURI-reference/noOccurrence id, never tenant-data route.
requestId, traceIdstring/noCorrelation.
retryableboolean/noWhether identical retry may succeed.
dependencySourceRef service enum/yesNon-null for dependency failures.
fieldErrorsarray max 100/yesEach: JSON Pointer pointer, stable code, safe message; null outside validation.
operationIdOperation id/yesNon-null after materialization orchestration begins.

Stable problem registry

Type suffixStatusRetry?When
authentication-required401NoMissing/expired/invalid JWT.
authorization-denied403NoValid token lacks permission scope.
not-found404NoMissing or outside claims; identical detail.
validation400NoMalformed or invalid known field, query, or header; fieldErrors identifies each location.
unsupported-parameter400NoUnknown query parameter or unsupported sort; fieldErrors points to the rejected name.
idempotency-conflict409NoSame key, different request.
source-version-conflict409YesAuthoritative versions fail to converge.
dependency-unavailable503YesRequired service unavailable/gate closed.
dependency-incomplete503YesRequired settled fact absent, including an attempt with no settled Results record.
internal-error500YesUnexpected safe boundary failure.

The base nine symbolic types and RFC 9457 envelope are pinned by ITD-023; unsupported-parameter is added by ITD-035; missing settled facts follow ITD-002.

Persistence boundary

API-fronted workflow state only. Attempts, responses, scores, result records, mastery state, student identity, distractor counts, item statistics, and cohort aggregates are never stored by Reports. Planned tables contain idempotency and improvement-workflow control metadata only; they are not created until their named release gates pass. Every primary key, foreign key, query, and index begins with tenant_id. Service-role credentials remain server-side; anonymous browser access is denied. ITD-001, ITD-026, ITD-039.

reports.operation_control NOT CREATED UNTIL B+C

ColumnPostgreSQL/nullConstraint/indexMeaning
tenant_idtext/nopart of PK/every indexVerified JWT tenant only.
methodtext/nocheck POSTCanonical operation.
canonical_pathtext/nocheck /v1/attempt-reports:materializeNo query/body.
key_hashbytea/no32 bytes; composite PKSHA-256; raw key never stored.
request_hashbytea/no32 bytesCanonical request hash.
operation_idtext/nounique in tenantRetry correlation.
lifecycle_statetext/noenum checkstarted, results_written, caliper_emitted, completed, failed.
downstream_key_hashesjsonb/noservice→SHA-256No raw keys/learning ids.
terminal_status_codesmallint/yes200 or 4xx/5xxNull before terminal; no body.
created_at, updated_at, expires_attimestamptz/noexpiry index; expires +24hHard retention.

Retention: delete at 24 hours. Indexes: composite primary key (tenant_id,method,canonical_path,key_hash), unique (tenant_id,operation_id), and (tenant_id,expires_at). Owner: Reports attempt-write control per ITD-020/024/026.

reports.improvement_run_control NOT CREATED UNTIL F+D

ColumnPostgreSQL/nullConstraint/indexMeaning
tenant_idtext/noPK prefix/every indexVerified JWT tenant only.
improvement_run_idtext/noPK with tenant_idOpaque run id.
administration_idtext/nounique (tenant, administration, policy version)Native Administration ref, not copied administration data.
content_test_spec_id, content_test_spec_versiontext/nolookup index with tenantNative immutable Content refs.
analysis_policy_id, analysis_policy_version, formula_versiontext/nononempty checksImmutable policy identifiers.
lifecycle_statustext/noenum checkqueued, analyzing, completed, completed_with_omissions, blocked_upstream, failed.
idempotency_key_hash, request_hashbytea/no32 bytes; unique (tenant,key hash)Raw key/body never stored.
metric_status_refsjsonb/noschema check; max 4Metric name/status plus immutable owner artifact refs only; no metric values/counts.
named_source_keysjsonb/noarray of unique stringsComplete immutable named-source key set, no crosswalk copy.
omission_codesjsonb/noenum-array checkExplicit unavailable metrics.
receipt_sha256, receipt_object_refbytea + text/yesboth null or both non-null; digest 32 bytesContent address and server-side object ref; no signed URL persisted.
created_at, updated_at, completed_attimestamptz; completed nullabletenant lifecycle indexWorkflow timestamps; completed_at only terminal.

Primary key (tenant_id,improvement_run_id). Unique (tenant_id,idempotency_key_hash). Indexes (tenant_id,administration_id,created_at desc) and (tenant_id,lifecycle_status,updated_at). No retention period is invented: deletion follows the privacy/retention policy when it is released, and the table cannot ship before that policy is pinned. Owner: Reports engine control state only, ITD-039.

reports.alignment_receipt_control NOT CREATED UNTIL F+D

ColumnPostgreSQL/nullConstraint/indexMeaning
tenant_id, improvement_run_idtext/nocomposite FK to improvement_run_controlTenant-safe owning run.
source_keytext/noPK suffixImmutable named-source key.
source_assessment, source_versiontext/nononempty checksNamed external test identity.
crosswalk_hashbytea/no32 bytesContent-owned crosswalk digest, not copied rows.
formula_versiontext/nononemptyApplied structural formula.
receipt_sha256, receipt_object_refbytea + text/nodigest 32 bytesImmutable bundle address and server-side ref; per-requirement contributions live in the receipt, not this table.
predicted_actual_artifact_reftext/yesnative Analytics refNull when no authenticated external-score artifact exists.
created_attimestamptz/notenant/run indexReceipt creation time.

Primary key (tenant_id,improvement_run_id,source_key). This table stores proof pointers, not crosswalk contributions, scores, or aggregate values. Owner: Reports evidence-control state under ITD-037/039/040.

reports.revision_order_control NOT CREATED UNTIL F+D

ColumnPostgreSQL/nullConstraint/indexMeaning
tenant_id, improvement_run_idtext/nocomposite FK to improvement_run_controlTenant-safe owning run.
revision_order_idtext/noPK suffixDeterministic order id.
target_module, requested_actiontext/nocompatible-enum checkBank/Blueprint target and allowed action.
native_subject_refsjsonb/noschema checkQTI/Content/CASE/source ids only; no copied objects.
reason_codesjsonb/nononempty enum arrayDeterministic trigger reasons.
policy_version, formula_versiontext/nononemptyImmutable decision versions.
threshold_comparisonjsonb/noname/operator/value/unit schemaObserved value and released threshold only; no student facts.
evidence_refsjsonb/nononempty SourceRef-shaped arrayImmutable owner evidence pointers.
lifecycle_statustext/noenum checkpending, accepted, replayed, blocked_upstream, rejected, superseded.
delivery_attemptsinteger/no≥0Receiver attempt counter.
target_receipt_refjsonb/yesSourceRef shapeBank/Blueprint acknowledgement only.
supersedes_revision_order_idtext/yessame-tenant FKPrior workflow order; null if none.
created_at, updated_attimestamptz/notenant/status indexLifecycle timestamps.

Primary key (tenant_id,improvement_run_id,revision_order_id). Indexes (tenant_id,target_module,lifecycle_status,updated_at) and (tenant_id,improvement_run_id,created_at). Owner: Reports workflow control; receiver resources remain Bank/Blueprint-owned, ITD-038/039.

Ephemeral cache, not a table

HTTP bytes only, maximum 30 seconds, keyed by tenant hash + authorization fingerprint + canonical request + source validators. Never persisted or reused across authorization fingerprints.

Endpoint contracts

EndpointInput / post-gate successScopeEndpoint-specific failuresProvenance
GET/v1/attempt-reports/{attemptId}ref + view; 200 AttemptReportreports:read + candidate intersectionNot released C+D; then validation 400, not-found 404, source-version-conflict 409, dependency-unavailable or dependency-incomplete 503ITD-004/023/028
GET/v1/candidates/{candidateSourcedId}/attempt-reportsallowlisted query; 200 AttemptReportPagereports:read + candidate claimNot released C+D+index; then validation or unsupported-parameter 400, not-found 404, dependency-unavailable or dependency-incomplete 503ITD-018/027/028/035
GET/v1/classes/{classSourcedId}/cohort-reportref; 200 CohortReportreports:read + class claim + OneRosterNot released A+D; then not-found 404, dependency-unavailable or dependency-incomplete 503; never local aggregateITD-009/023
GET/v1/schools/{schoolSourcedId}/grades/{grade}/cohort-reportschool ref + OneRoster grade; 200 CohortReportreports:read + school claim + OneRosterNot released A+D; then 400 unknown gradeITD-009
GET/v1/forms/{qtiTestId}/equivalenceref; 200 EquivalenceReportreports:read + authorized formNot released A+D; then 404,503ITD-010
GET/v1/attempt-reports/{attemptId}/readinessref; 200 ReadinessReportreports:read + candidate claimNot released C+D; then not-found 404, source-version-conflict 409, dependency-unavailable or dependency-incomplete 503ITD-011/023/028
POST/v1/attempt-reports:materializeJSON body + key; 200 operationId+AttemptReportreports:write + candidate/adminNot released B+C+D; then validation 400, not-found 404, idempotency-conflict or source-version-conflict 409, dependency-unavailable or dependency-incomplete 503ITD-002/020/023/028/032
POST/v1/administrations/{administrationId}/improvement-runs:analyzeNo body + Idempotency-Key; 200 ImprovementRun; replay adds Idempotent-Replayedreports:write + administration claimNot released F+D; then validation 400, not-found 404, idempotency-conflict or source-version-conflict 409, dependency-unavailable or dependency-incomplete 503ITD-016/020/038/040
GET/v1/improvement-runs/{improvementRunId}ref; 200 ImprovementRunreports:read + run tenant/admin scopeNot released F+D; then not-found 404; dependency-unavailable/incomplete 503 when required evidence refs do not dereferenceITD-039/040
GET/v1/improvement-runs/{improvementRunId}/alignment-reports/{sourceKey}refs; 200 AlignmentReportreports:read + run tenant/admin scopeNot released F+D; then validation 400, not-found 404, source-version-conflict 409, dependency-unavailable/incomplete 503ITD-037/040
GET/v1/improvement-runs/{improvementRunId}/revision-ordersallowlisted query; 200 RevisionOrderPagereports:read + run tenant/admin scopeNot released F+D; then validation or unsupported-parameter 400, not-found 404, dependency-unavailable/incomplete 503ITD-038/040

Authentication-required 401, authorization-denied 403, and internal-error 500 apply to every route. A missing id and the same id outside verified tenant/claims both return the identical non-enumerating 404. Success uses application/json; errors use application/problem+json. No endpoint accepts a tenant selector. Payload-size and unsupported-media-type behavior remain uncommitted and therefore are not invented here.