AlphaTest · Administration · Integrator API · Data dictionary

Every field has one meaning, one owner, and one way to fail.

Use this reference to implement assign → launch → QTI state → Results write-back without guessing. It defines every shipped v1 request, response, query, header, persisted column, enum, validation rule, and endpoint error. Platform3-native identifiers remain opaque pass-throughs; learner, attempt, session, outcome, score, and mastery facts stay in their owning systems.

Contract baseline · 20 July 2026 · JSON over API-relative /v1 · durable dictionary route /reference · derived only from the approved administration architecture

Start here

The AcmeTest maintainer can generate a typed client from these definitions without learning AlphaTest internals. Read the Administration resource, choose one target variant, then follow the create endpoint. Candidate delivery state is composed live from OneRoster and QTI; it is never a local copy.

Who

The engineer maintaining AcmeTest, already using a Platform3 QTI player and OneRoster identities.

Job

Wire assignment, window-gated delivery launch, polling, retakes, close, and verified Results write-back in one afternoon.

Identifier rule

All Platform3 IDs are opaque UTF-8 strings. Store and compare them byte-for-byte; never parse prefixes or infer ownership.

Null rule

Fields are non-null unless their row explicitly says nullable. An omitted optional field differs from a JSON null, which is rejected unless explicitly allowed.

System-of-record key: AlphaTest glue is locally persisted; OneRoster pass-through, QTI pass-through, Content pass-through, and Results pass-through are read or carried without redefining them. Close stores only retry/reconciliation references—never outcome or score bodies. A fixed mastery gate is accepted only after the authoritative Content bank/spec/member predicate in fixed-gate assignability passes. The provenance column links every local rule to an approved Architecture ITD.
Current fixed-bank availability: Bank generation is fail-closed today. POST /v1/bank-generations for same_blueprint_fixed_forms returns typed 424 dependency_contract_unavailable before admission and creates no operation until an owner-backed receipt proves all six assignability predicates below and a same-tenant Administration create accepts the returned native IDs. The future 202 Administration create schema remains normative, but a client must not treat a Bank ready/assignable flag as sufficient evidence. Retained same-tenant evidence explains the gate: Bank operation bop_37Q999HAPF1PRK8H2FGCWFZRHH reported ready/assignable for bank f937d471-d97f-4fca-83c8-8a2faf98bf0b, while authoritative Content returned status=draft, is_mastery_gate=false, membership_rule=null, and spec_id=null; Administration therefore rejected the native IDs before roster, persistence, or session effects. See the approved Bank dictionary and ITD-037.

Fixed-gate client branching while Bank is closed

These outcomes occur at different ownership boundaries and are not interchangeable. Preserve each surface’s exact code; do not normalize Bank’s underscore-delimited code into an Administration code.

Call and responseMachine meaningEffect boundaryTyped-client actionProvenance
Bank generation → 424 dependency_contract_unavailableThe fixed-form producer lacks the complete owner-backed certification receipt. This is the only expected fixed-generation outcome today.No Bank operation is admitted; do not call Administration with locally inferred IDs.Surface the dependency gap and retain the original generation request for a later retry. Do not poll an operation because none exists.Bank ITD-016 · Administration ITD-037
Administration create → 422 test-not-assignableAuthoritative Content/QTI resources were reachable, but the first predicate in the deterministic validation order failed.No Administration row, OneRoster lookup, or QTI session effect.Treat the supplied native IDs as unusable; do not retry unchanged. Use detail for diagnosis and branch on code.ITD-009 · ITD-037
Administration create → 424 content-unavailable or 424 qti-unavailableThe authoritative predicate could not be evaluated; this is not evidence that a predicate was false.No Administration row, OneRoster lookup, or QTI session effect.Retry the same logical create with the same Idempotency-Key after the dependency recovers.ITD-006 · ITD-024 · ITD-037
Administration create → 202 + LocationAll pre-effect validation passed and the administration plus its retry-safe provisioning intent is durable.Provisioning may continue asynchronously; poll the returned resource.Follow Location; never synthesize the administration ID or infer completion from acceptance.ITD-014 · ITD-037

Find a schema

Typed-client surface at a glance

This map is an index over the normative schemas below, not a second contract. Each method name links to its exact HTTP row; each input and output links to the complete field dictionary. A client should decode every non-2xx response as ProblemDetails and branch on its stable code.

interface AdministrationClient {
  create(input: CreateAdministration, idempotencyKey: string): Promise<Created<Administration>>;
  provision(id: string, input: {}, idempotencyKey: string): Promise<Accepted<Administration>>;
  list(query?: AdministrationListQuery): Promise<Page<Administration>>;
  get(id: string, options?: { include?: "candidates" }): Promise<Entity<Administration>>;
  patch(id: string, input: PatchAdministration, ifMatch: string): Promise<Entity<Administration>>;
  candidates(id: string, query?: CandidateListQuery): Promise<Page<CandidateDelivery>>;
  launch(id: string, candidateSourcedId: string, idempotencyKey: string): Promise<LaunchReceipt>;
  advance(id: string, candidateSourcedId: string, input: {}, idempotencyKey: string): Promise<CandidateDelivery>;
  retake(id: string, input: CreateRetake, idempotencyKey: string): Promise<Accepted<CandidateDelivery>>;
  close(id: string, input: {}, idempotencyKey: string): Promise<Accepted<Administration>>;
}

type Created<T> = { status: 202; body: T; location: string; idempotentReplayed: boolean };
type Accepted<T> = { status: 202; body: T; idempotentReplayed: boolean };
type Entity<T> = { status: 200; body: T; etag: string };
type Page<T> = { data: T[]; nextCursor: string | null; hasMore: boolean; requestId: string };
Client methodHTTP contractInput dictionarySuccess dictionaryConcurrency / replay
createPOST /v1/administrationsCreateAdministrationAdministration, 202 + LocationIdempotency-Key
provisionPOST /v1/administrations/{id}/provisionStrict {}Administration, 202Idempotency-Key; retries failed bindings only
listGET /v1/administrationsAdministrationListQueryPage<Administration>, 200Opaque cursor; no write precondition
getGET /v1/administrations/{id}includeAdministration, 200 + ETagRetain the strong ETag for PATCH
patchPATCH /v1/administrations/{id}PatchAdministrationAdministration, 200 + new ETagIf-Match
candidatesGET …/candidatesCandidateListQueryPage<CandidateDelivery>, 200Opaque cursor; live QTI state
launchPOST …/{candidateSourcedId}/launchNo body or queryLaunchReceipt, 200Idempotency-Key; always send
advancePOST …/{candidateSourcedId}/advanceStrict {}CandidateDelivery, 200Idempotency-Key; adaptive only
retakePOST …/retakesCreateRetakeCandidateDelivery, 202Idempotency-Key
closePOST …/closeStrict {}Administration in closing, 202Idempotency-Key; poll detail to scored
Wrapper semantics: Created.location is required for create; Accepted deliberately has no location member for provision, retake, or close. idempotentReplayed is true only when the response carries literal Idempotent-Replayed: true. The wire response body is the linked resource itself—these wrappers describe status and headers in a typed transport layer; they are not JSON envelope fields. Provenance: ITD-005, 006, 014, 030, 031.

Wire conventions and scalar types

Base URL and path notation: this dictionary writes endpoint templates as API-root-relative /v1/… paths. At the product origin, authenticated API traffic lives below /api, so the complete wire URL is https://alphatest-administration.vercel.app/api/v1/…. For example, POST /v1/administrations below means POST https://alphatest-administration.vercel.app/api/v1/administrations. Documentation remains unauthenticated at /, /architecture, and this durable dictionary route, /reference. Provenance: ITD-023, ITD-027.
ConceptWire type and rangeRulesProvenance
AlphaTest IDstring, 1–255 bytesOpaque, case-sensitive, immutable. Returned by the service; clients must not synthesize it. Opacity is pinned by the approved HTTP contract; the 1–255-byte validation bound is this dictionary’s wire refinement.Architecture HTTP contract
Platform3 referencestring, 1–255 bytesOpaque byte-for-byte pass-through. No prefix, UUID, or URL assumption. Blank and surrounding whitespace are invalid.ITD-001, 035
Instantstring(date-time)RFC 3339 UTC with terminal Z; fractional seconds accepted and normalized. Offsets other than Z, local times, and leap seconds are rejected.ITD-031
Duration secondsinteger, 60–86,400Whole seconds only. AlphaTest stores this as nominal scheduling/audit policy; QTI does not enforce it in v1.ITD-031
Time multipliernumberThe only accepted v1 value is the semantic no-op 1. Any other value requires an upstream QTI capability that is not currently available.ITD-018
Countinteger, ≥0Non-negative JSON integer. Counts are snapshots of the response composition, not locally durable learner facts.ITD-016
Request IDstring, 1–128 bytesOpaque correlation value generated at the boundary and propagated upstream. Contains no learner identifiers.ITD-025

HTTP headers

HeaderRequiredMeaning and validationFailureProvenance
AuthorizationEvery endpointBearer <JWT>; verified HS256 claims: sub, role, tenantId, iat, exp. The role grants a maximum permission set; optional scope, school, and class claims can only narrow it. A valid five-claim token does not need scope.401 authentication-required or 403 insufficient-scopeITD-007
Content-TypeRequests with bodyapplication/json; optional media-type parameters are ignored. Invalid JSON is not field validation.415 unsupported-media-type or 400 malformed-jsonITD-009
Idempotency-KeyCreate, provision-resume, first launch, adaptive advance, retake, and closeString, 1–255 visible ASCII characters, no leading/trailing whitespace; scoped to verified tenant + method + concrete path for 24 hours. Always send it on launch. Provision and adaptive operations retain deterministic per-candidate child keys so partial fan-out can resume without duplicates. Launch authorization is evaluated before receipt lookup.400 missing-idempotency-key or 409 idempotency-key-reusedITD-006, 031, 034
If-MatchPATCHExact strong ETag last returned by detail. Weak tags and * are rejected.428 precondition-required or 412 etag-mismatchITD-005
X-Timeback-TenantNoDiagnostic assertion only. If supplied, must exactly equal the verified JWT tenantId; it never selects a tenant.403 tenant-mismatchITD-010

Response headers

HeaderPresent onWire type / allowed valuesMeaningProvenance
LocationSuccessful createabsolute-path reference, non-nullCanonical wire path /api/v1/administrations/{id} for the accepted resource. Endpoint templates elsewhere omit the product-origin /api mount as defined in Base URL and path notation.ITD-014, 027
ETagSuccessful detail and patchOpaque strong entity-tag, non-nullQuote and send byte-for-byte as the next If-Match; never parse the version from it.ITD-005
Idempotent-ReplayedStored effectful-POST replay; stored launch replay only while launch-authorizedLiteral true; otherwise absentThe status and body are the original response for the same scoped key and identical semantic request. This covers create, provision, advance, retake, and close. Launch is the exception: outside [opensAt, closesAt), window denial wins and the header is absent.ITD-006, 031
Retry-After429 or retryable 503 when a retry time is knownHTTP-date or non-negative decimal delay-seconds; otherwise absentEarliest safe retry boundary; clients must still check retryable and preserve idempotency.ITD-024
Content-TypeEvery response with a bodyapplication/json on success; application/problem+json on non-2xxSelects the success resource or ProblemDetails decoder.ITD-009
Allow405 onlyComma-separated HTTP methods; non-nullExact shipped methods for the matched path, including POST on provision, launch, advance, retake, and close actions.ITD-002, 009
Idempotency equality: after strict validation, hash the canonical semantic JSON object: object keys sorted lexicographically at every depth, arrays kept in request order, strings compared byte-for-byte, and JSON numbers normalized to their validated value. Whitespace and object-key order therefore do not change a request; array order and any field value do. Duplicate object keys are rejected as 400 malformed-json. Provenance: ITD-006.

JWT claim dictionary

Token ownership: AlphaTest verifies Platform JWTs; it does not issue production credentials and exposes no public token-mint endpoint. Obtain a signed tenant token through the Platform3 environment already used by the integrating application, then send it as Authorization: Bearer <JWT>. Reviewer/demo token bootstrap is deployment tooling, not a production API contract. This prevents a cold client from searching for an AlphaTest login or credential resource that does not exist. Provenance: ITD-007.
ClaimType / rangeRequired / nullableMeaning and validationProvenance
substring, 1–255 bytesRequired; never nullOpaque Platform principal identifier.ITD-007
rolenon-empty string, ≤120 bytesRequired; never nullLooks up the maximum administration permission set below. Unknown values authenticate but grant no administration permission.ITD-007
tenantIdstring, 1–255 bytesRequired; never nullAuthoritative opaque tenant route. It is never overridden by a header or path.ITD-007, 010
iatinteger NumericDate secondsRequired; never nullJWT issued-at instant; a token issued in the future beyond verifier clock tolerance is invalid.ITD-007
expinteger NumericDate secondsRequired; never nullMust be later than iat and later than verifier time.ITD-007
scopespace-delimited string, 1–1,024 bytesOptional; null rejectedIntersection-only permission narrowing. Each token is one of the five exact permission strings below; duplicates have no effect; unknown tokens grant nothing.ITD-007
schoolSourcedIdsarray of 1–1,000 unique Platform3 referencesOptional; null rejectedNarrows target access to these OneRoster schools; empty arrays are rejected rather than interpreted as unrestricted.ITD-007
classSourcedIdsarray of 1–1,000 unique Platform3 referencesOptional; null rejectedNarrows target access to these OneRoster classes; empty arrays are rejected rather than interpreted as unrestricted.ITD-007

Role-derived permissions

JWT roleMaximum permissionsOptional scope behaviorResource constraintsProvenance
integratoradministrations:read, administrations:write, administrations:read_sensitive, administrations:deliver, administrations:closeIf absent, the full role maximum applies. If present as a space-delimited string, the effective set is its intersection with the role maximum; unknown permissions grant nothing.Optional schoolSourcedIds and classSourcedIds arrays, each 1–1,000 unique Platform3 references, narrow reads/writes.ITD-007
revieweradministrations:read, administrations:write, administrations:read_sensitive, administrations:deliver, administrations:closeSame narrowing rule; a standard five-claim reviewer token receives the role maximum.Same optional narrowing arrays.ITD-007
Any other non-empty stringNone in administration v1.A scope claim cannot add permission.Constraints cannot add permission.ITD-007
Evolution rule: clients must ignore unknown response fields and unknown future enum values they do not act on. Requests reject unknown fields so misspellings cannot silently alter an administration. Semantic breaks require a new path major.

Response resource schemas

Administration

The tenant-scoped orchestration resource. It contains policy and provisioning metadata, not roster members, responses, scores, or mastery.

JSON fieldTypeNullableMeaning / allowed values / validationOwner + provenance
idAlphaTest IDNoImmutable administration identifier.AlphaTest glue · ITD-014
objectstring enumNoAlways administration; this literal response discriminator is the dictionary refinement for the v1 resource exposed under the path-major contract.AlphaTest glue · ITD-023
statusstring enumNoprovisioning, provisioning_with_errors, scheduled, open, window_ended, closing, scored, or close_failed. This is orchestration lifecycle, not candidate state. scored requires fixed-form Results verification or, for adaptive diagnostics, completed mastery-engine runs with acknowledged Results KC components.AlphaTest glue · ITD-014, 034, 036
testTestRefNoImmutable Content/QTI identity and required test-kind selector. A fixed mastery-gate identity is persisted only after authoritative Content and QTI validation succeeds.Content/QTI pass-through · ITD-032, 035, 037
adaptiveConfigAdaptiveConfigSummaryConditional; never nullPresent only for adaptive_diagnostic. Echoes immutable non-learner execution pins; resultsStudentBindings is never echoed.AlphaTest glue · ITD-032, 033
targetTargetSummaryNoImmutable target kind. Explicit candidate IDs are never echoed or durably retained as a local membership list.OneRoster/QTI pass-through · ITD-015, 026
windowWindowNoAlphaTest withholds the delivery session reference outside this window. QTI does not terminate an already revealed session.AlphaTest glue · ITD-031
timingTimingConditional; never nullPresent for fixed-form kinds only and omitted for adaptive diagnostics. Fixed duration is nominal metadata, not QTI-enforced; adaptive stopping belongs to mastery_engine.AlphaTest/mastery_engine boundary · ITD-031, 033
retakesRetakePolicyNoAttempt policy plus kind-specific fixed-form rotation or adaptive fresh-run semantics.AlphaTest glue · ITD-017, 034
accommodationsAccommodationsNoAlways the normalized semantic no-op in v1. It is not a claim that QTI applies accommodations.AlphaTest glue · ITD-018
candidateCountsCandidateCountsNoComposed from per-binding QTI reads. Can lag while provisioning; asOf makes staleness explicit.QTI pass-through · ITD-008, 016
provisioningProvisioningProgressNoBounded Content/OneRoster/QTI or mastery-engine provisioning progress. Partial success is retained and failed candidates are resumable.AlphaTest glue + upstream refs · ITD-014, 024, 034
closeCloseProgressConditional; never nullPresent only in closing, close_failed, or scored; omitted earlier. Counts describe reconciliation progress, never score values.AlphaTest reconciliation glue · ITD-030
candidatesCandidateDelivery array, 0–100Conditional; never nullPresent only when detail is requested with include=candidates; otherwise omitted. If more than 100 bindings exist, the request returns 422 candidates-page-required instead of truncating.QTI/OneRoster composition · ITD-003, 007
versioninteger ≥1NoMonotonic version of mutable AlphaTest-owned policy; basis of strong ETag. Upstream-only runtime changes do not increment it.AlphaTest glue · ITD-005
createdAtInstantNoWhen the local resource became durable.AlphaTest glue · ITD-014
modifiedAtInstantNoLatest local lifecycle, policy, or provisioning change; list ordering and modifiedSince compare this value.AlphaTest glue · ITD-004
requestIdRequest IDNoCorrelation for this read, not the create request.AlphaTest glue · ITD-025

TestRef

FieldTypeNullableMeaning / validationOwner + provenance
qtiTestIdPlatform3 reference, 1–255 bytesConditional; never nullRequired for mastery_gate and formative; forbidden for adaptive_diagnostic, whose native QTI offers are created by mastery_engine. For a mastery gate this is the requested native fixed-form test-bank reference: Content must resolve it to the exact ordered member set, and every member’s immutable QTI artifact version must dereference before create has any effect.Content/QTI pass-through · ITD-032, 033, 037
contentTestSpecIdPlatform3 reference, 1–255 bytesNoRequested Content test_spec reference. It must describe the supplied test kind. For mastery_gate, it must equal the authoritative bank’s non-null spec_id byte-for-byte.Content pass-through · ITD-001, 037
testKindstring enumNoExactly mastery_gate, adaptive_diagnostic, or formative. Required and never inferred; all three use the same administration resource.AlphaTest selector · ITD-032
Fixed mastery-gate assignability · ITD-037: before local persistence and before any OneRoster or QTI effect, read contentTestSpecId and the Content bank identified by qtiTestId in the verified JWT tenant. Accept only when all six predicates hold: bank status=published; is_mastery_gate=true; membership_rule=same_blueprint_fixed_forms; bank spec_id exactly equals contentTestSpecId; the ordered member set is non-empty and exactly the set returned by Content; and every member’s immutable QTI artifact version dereferences. A Bank operation’s ready or assignable flag is correlation evidence only. A reachable authoritative resource that violates any predicate returns 422 test-not-assignable with no persistence, roster lookup, or QTI effect. Failure to obtain or validate an authoritative Content/QTI response returns the owning retryable 424 content-unavailable or 424 qti-unavailable, never a fabricated predicate result.

ITD-037 · Content owns bank/spec/membership facts; QTI owns immutable artifact versions; AlphaTest stores only the accepted opaque references.

TargetSummary

The response is deliberately smaller than the create input. Durable membership comes from QTI sessions; OneRoster remains identity authority.

Variant / fieldTypeNullableMeaning / validationOwner + provenance
typestring enumNoclass or candidate_list.AlphaTest glue · ITD-026
oneRosterSourcedIdPlatform3 referenceNo*Present and required only for class; absent for candidate_list. Live tenant authorization is required.OneRoster pass-through · ITD-015
resolvedCandidateCountinteger ≥0NoNumber of durable candidate-attempt bindings established by provisioning. It is neither an embedded roster nor a count of locally owned attempts.AlphaTest binding count · ITD-015, 026

AdaptiveConfigInput and AdaptiveConfigSummary

Required only when test.testKind=adaptive_diagnostic and forbidden for fixed-form kinds. All identifiers are opaque UTF-8 strings, 1–255 bytes, non-null. The input binding set is validated before persistence or any upstream effect; the response summary omits learner bindings.

FieldTypeInput / outputValidation and meaningOwner + provenance
selectionPolicyIdPlatform3 referenceRequired / echoedExact immutable mastery-engine selection-policy version; aliases such as latest are invalid.mastery_engine pass-through · ITD-032
scaleCalibrationIdPlatform3 referenceRequired / echoedExact immutable scale calibration valid for the referenced test spec and bank.mastery_engine pass-through · ITD-032
testBankIdPlatform3 Content referenceRequired / echoedAdaptive Content test_bank associated with test.contentTestSpecId.Content/mastery_engine pass-through · ITD-032, 035
bankOperationIdAlphaTest Bank referenceRequired / echoedExact terminal same-tenant bank operation whose manifest pins the native adaptive pool.Bank/mastery_engine pass-through · ITD-032, 035
runModestring literalRequired / echoedExactly production_learner. Administration does not expose owner-conformance runs.mastery_engine pass-through · ITD-032
resultsStudentBindingsResultsStudentBinding array, 1–1,000Required / omittedMust contain exactly one entry for every resolved OneRoster candidate and no others. Missing, extra, duplicate, unknown, or cross-tenant entries return 422 adaptive-capability-required before persistence or effects.Caller input validated through OneRoster + Results · ITD-032, 033

ResultsStudentBinding

FieldTypeNullableMeaning / validationOwner + provenance
candidateSourcedIdOneRoster reference, 1–255 bytesNoMust match one resolved target candidate exactly; unique within the array.OneRoster pass-through · ITD-032
resultsStudentIdResults reference, 1–255 bytesNoExisting same-tenant Results learner reference. Administration validates but never infers it from OneRoster.Results pass-through · ITD-032, 033

Window

FieldTypeRule
opensAtInstantNon-null; must be earlier than closesAt. Before this instant, launch returns 403 launch-not-open without revealing a session reference, including an otherwise-identical replay of a previously stored launch receipt.
closesAtInstantNon-null; must be after opensAt. At or after this instant, launch returns 410 launch-window-ended without Idempotent-Replayed or a stored receipt, including an otherwise-identical replay. QTI does not terminate an already revealed session.

Launch replay precedence: ITD-031 authorization is evaluated before ITD-006 idempotency receipt lookup. Only an authorized request inside [opensAt, closesAt) may replay the original LaunchReceipt; outside the window, the 403/410 denial wins and no deliverySessionRef is revealed. A denied replay does not delete or extend the stored 24-hour receipt.

AlphaTest launch policy · ITD-006 × ITD-031

Timing

FieldTypeRule
timeLimitSecondsinteger 60–86,400Non-null nominal duration metadata. Returned in LaunchReceipt with runtimeEnforced:false; QTI does not enforce or terminate delivery from this value in v1.

AlphaTest nominal policy · ITD-031

RetakePolicy

FieldTypeRule
maxAttemptsinteger 1–10Non-null total attempts including first. 1 disables retakes.
parallelFormRotationstring enumdifferent_form_required for mastery gates, not_required for formative, or not_applicable for adaptive diagnostics. Adaptive retakes start a new mastery run and continuation; they never reuse the expired run.

AlphaTest glue · ITD-017, 032, 034

Accommodations

V1 has exactly one representable value: {"default":{"timeMultiplier":1},"candidateOverrides":[]}. The create field may be omitted, in which case that value is returned. Any non-default multiplier, any candidate override, null, extra field, or alternate shape returns 422 qti-accommodation-capability-required. This object is policy-shape compatibility only; QTI does not apply an accommodation.

PathTypeNullableOnly allowed v1 valueOwner + provenance
defaultobjectNoExactly {"timeMultiplier":1}.AlphaTest no-op policy · ITD-018
default.timeMultipliernumberNoLiteral numeric value 1.AlphaTest no-op policy · ITD-018
candidateOverridesarrayNoExactly an empty array.AlphaTest no-op policy · ITD-018

CandidateCounts

FieldTypeNullableMeaningOwner
notStartedinteger ≥0NoFixed QTI sessions or adaptive offers not yet launched.QTI/mastery_engine composed
inProgressinteger ≥0NoStarted fixed attempt or adaptive run in progress.QTI/mastery_engine composed
submittedinteger ≥0NoFixed submission awaiting score, or adaptive finalizing with no offer.QTI/mastery_engine composed
scoredinteger ≥0NoFixed QTI score or adaptive completed output with acknowledged Results KC components.QTI/mastery_engine/Results composed
totalinteger ≥0NoSum of the four states.QTI derived
asOfInstantNoCompletion time of the QTI read used for these counts.AlphaTest composition

ITD-016; never persisted as durable evidence.

ProvisioningProgress

FieldTypeNullableMeaning / allowed valuesOwner + provenance
statusstring enumNorunning, complete, or with_errors. This covers target resolution and per-candidate fixed QTI-session or adaptive mastery-run provisioning.AlphaTest glue · ITD-014, 034
requestedinteger ≥0NoEligible candidate count resolved live from OneRoster for this provisioning run; count only, never a roster snapshot.OneRoster-derived operational metadata · ITD-015
pendinginteger ≥0NoResolved candidates whose fixed QTI binding or adaptive mastery-run binding is not yet durable.AlphaTest orchestration metadata · ITD-024, 034
failedinteger ≥0NoResolved candidates whose latest provisioning attempt failed; retained for targeted resume and never folded into pending.AlphaTest orchestration metadata · ITD-024, 034
succeededinteger ≥0NoImmutable candidate-attempt bindings created and verified. Invariant: pending + failed + succeeded = requested.AlphaTest binding count · ITD-015
errorsProvisioningError array, 0–100NoCurrent diagnostics: {dependency,code,retryable,occurredAt}. Dependency is exactly content, oneroster, qti, results, or mastery_engine; code is 1–120 bytes; retryable is boolean; occurredAt is an Instant. No upstream body, continuation, or learner identifier is returned.Privacy-safe local metadata · ITD-009, 025, 034
lastAttemptAtInstantYesnull before the first upstream attempt; otherwise the latest bounded provisioning attempt.AlphaTest glue · ITD-024

CloseProgress

Operational reconciliation counts only. The API never returns or stores the QTI score body here.

FieldTypeNullableMeaning / invariantOwner + provenance
submittedAttemptsinteger ≥0NoLatest launched attempts eligible for close: fixed QTI submitted/scored attempts or adaptive attempts already composed as scored.QTI/mastery_engine-derived count · ITD-030, 036
verifiedResultsinteger ≥0NoFixed attempts with exact Results read-back plus adaptive attempts whose completed inspect reports acknowledged Results KC components and a dereferenceable result reference.Results/mastery_engine-derived count · ITD-030, 036
failedinteger ≥0NoAttempts whose latest QTI read, Results create, or exact verification failed. Invariant: verifiedResults + failed ≤ submittedAttempts.AlphaTest reconciliation metadata · ITD-024, 030
lastAttemptAtInstantYesnull only before asynchronous reconciliation begins; otherwise latest close worker attempt.AlphaTest glue · ITD-024

CandidateDelivery

Returned only from the candidates subcollection or include=candidates. The caller’s effective permissions must include administrations:read_sensitive. Every row is composed from the immutable binding, current QTI runtime data, and a live OneRoster identity reference. The raw delivery session is intentionally absent; only the launch action may reveal it.

FieldTypeNullableMeaning / validationOwner + provenance
oneRosterSourcedIdPlatform3 referenceNoCandidate identity reference; no name, email, or demographics.OneRoster pass-through · ITD-015
statestring enumNonot_started, in_progress, submitted, or scored. Fixed forms derive it from QTI. Adaptive composition maps pre-launch offer→not_started, mastery-engine in_progress→in_progress, finalizing without offer→submitted, and completed with reportable output plus acknowledged Results KC components→scored.QTI/mastery_engine composition · ITD-016, 036
attemptNumberinteger 1–10NoQTI attempt ordinal for this candidate and administration.QTI pass-through · ITD-017
qtiFormIdPlatform3 referenceConditional; never nullPresent for fixed-form attempts only; omitted for adaptive diagnostics because each current native QTI offer is revealed only as deliverySessionRef by launch.QTI pass-through · ITD-017, 033
adaptiveRunRefmastery_engine referenceConditional; never nullPresent only for adaptive diagnostics. Opaque run reference used for support and inspect correlation; continuation token and ETag are never returned.mastery_engine pass-through · ITD-033
launchEligibilitystring enumNoeligible, not_open, window_ended, or administration_closed. A hint computed at response time; the launch endpoint reauthorizes.AlphaTest glue · ITD-031, 030
resultRecordRefPlatform3 referenceConditional; never nullPresent after fixed-form exact Results read-back or adaptive completion reports acknowledged Results KC components. It is a reference, never a score, scale value, KC map, or result body.Results pass-through · ITD-030, 036

LaunchReceipt

Returned only by the candidate launch action after current authorization succeeds.

FieldTypeNullableMeaningOwner + provenance
administrationIdAlphaTest IDNoAdministration being launched.AlphaTest glue · ITD-014
oneRosterSourcedIdPlatform3 referenceNoCandidate path identity, repeated for correlation.OneRoster pass-through · ITD-015
deliverySessionRefPlatform3 referenceNoOpaque QTI player session reference; revealed only while the window is open and the administration accepts launches.QTI pass-through · ITD-011, 031
timeLimitSecondsinteger 60–86,400Conditional; never nullPresent for fixed-form kinds only; omitted for adaptive diagnostics.AlphaTest glue · ITD-031
runtimeEnforcedboolean literalConditional; never nullPresent with timeLimitSeconds and always false; omitted for adaptive diagnostics.Capability declaration · ITD-031
requestIdRequest IDNoBoundary correlation for this authorization.AlphaTest glue · ITD-025

Collection envelopes

FieldTypeNullableMeaning
dataarrayNoAdministration or CandidateDelivery resources. Empty array is valid.
nextCursorstring 1–1,024YesOpaque, request-shape-bound continuation; null when no next page. Do not parse or reuse with different filters/order.
hasMorebooleanNoWhether nextCursor can continue.
requestIdRequest IDNoBoundary correlation for this page.

ITD-003, 004, 013

Write request schemas

CreateAdministration

Unknown fields and JSON null are rejected. Required and forbidden fields are selected solely by test.testKind. Pre-effect validation is atomic: any invalid test predicate, unauthorized target, or invalid adaptive Results binding rejects the whole request. For a fixed mastery gate, test assignability is checked before persistence, OneRoster resolution, or QTI effects.

FieldTypeRequiredValidationTrace
testTestRefYescontentTestSpecId and testKind are always required. qtiTestId is required for fixed kinds and forbidden for adaptive. Immutable after create. A mastery gate must satisfy the complete authoritative assignability predicate; no Bank workflow flag substitutes for Content/QTI read-back.ITD-032, 033, 037
targetTargetInputYesExactly one discriminated variant.ITD-026
adaptiveConfigAdaptiveConfigInputConditionalRequired exactly for adaptive_diagnostic; forbidden for fixed kinds. The Results binding set must equal the live resolved candidate set before effects.ITD-032
windowWindowYesopensAt < closesAt; AlphaTest enforces it when revealing a QTI session reference.ITD-031
timingTimingRequired for fixed kinds; forbidden for adaptiveFixed-form nominal metadata only; adaptive stopping policy belongs to mastery_engine and is never restated as a local duration.ITD-031, 033
retakesRetakePolicyYesMust be compatible with test kind and available bank/form policy.ITD-017
accommodationsAccommodationsNoIf absent, normalizes to the documented no-op. If present, must equal it exactly; every non-default request returns 422 qti-accommodation-capability-required.ITD-018

ResumeProvisioning

POST /v1/administrations/{id}/provision has an exact empty JSON object body {}, no query parameters, and requires Idempotency-Key. It retries only candidate attempts whose current provisioning state is failed and reuses each original deterministic child key. It never restarts successful QTI sessions or mastery runs. Success is 202 Administration; no failed candidates is a safe 202 no-op. Unknown fields or null return 400 validation-failed.

ITD-006, 024, 034

AdvanceCandidate

POST /v1/administrations/{id}/candidates/{candidateSourcedId}/advance is valid only for an adaptive candidate attempt after QTI has scored the current offer. Its strict request body is {}; candidate identity, opaque continuation, and current strong mastery-engine ETag come from the tenant-scoped binding, never from the caller. Idempotency-Key is required. Administration calls mastery_engine :advance, then atomically replaces the stored continuation token, ETag, expiry, and current offered QTI session. Success is 200 CandidateDelivery. A dependency failure returns 424 mastery-engine-unavailable without changing the binding; expiry returns 409 adaptive-continuation-expired and requires a policy-permitted retake. Fixed-form use returns 409 administration-state-conflict.

ITD-006, 033, 034

TargetInput

VariantRequired fieldsForbidden fieldsValidation
type: "class"oneRosterSourcedId: Platform3 referenceoneRosterCandidateSourcedIdsClass must exist, be active, belong to tenant and caller constraints, and resolve to at least one eligible active candidate.
type: "candidate_list"oneRosterCandidateSourcedIds: array of 1–1,000 Platform3 referencesoneRosterSourcedIdEvery ID unique, active, tenant-authorized, and allowed by caller constraints. No partial acceptance; list is not retained after the idempotency body expires.

OneRoster resolution + QTI membership · ITD-015, 026

PatchAdministration

Merge-patch semantics are not used. The body is a strict JSON object containing one or more of the fields below; nested objects replace that policy section in full. JSON null and unknown fields are rejected. test, target, status, identifiers, counts, provisioning, and close progress are immutable. PATCH changes AlphaTest policy only and never claims to mutate QTI policy. Every PATCH field is guarded by the same authoritative-state rule: if any bound candidate has left QTI not_started, the whole request returns 409 administration-state-conflict and changes nothing.

FieldTypeRequiredValidation
windowWindowNoFull object; subject to the all-candidates-not_started guard. A window_ended, closing, close_failed, or scored administration cannot be reopened.
timingTimingNoFull nominal-metadata object; subject to the all-candidates-not_started guard.
retakesRetakePolicyNoFull object; subject to the all-candidates-not_started guard and cannot reduce maxAttempts below an existing QTI attempt count.
accommodationsAccommodationsNoOnly the exact no-op object is accepted; any non-default value returns 422 qti-accommodation-capability-required.

ITD-005, 018, 031

CreateRetake

FieldTypeRequiredValidation
oneRosterSourcedIdPlatform3 reference, 1–255 bytesYesMust identify a same-tenant bound candidate. No other fields are allowed. The administration must be open. For a fixed-form attempt, the latest authoritative QTI state must be submitted or scored. For an adaptive attempt, the latest composed state must be submitted, scored, or its advance must have returned the typed 409 adaptive-continuation-expired. Every other combination returns 409 administration-state-conflict.

Composed guard — documented ITD-034 extension to ITD-017: ITD-017 supplies the submitted/scored base guard and fixed-form semantics; ITD-034 expressly adds the expired-continuation disjunct for adaptive diagnostics. Fixed forms: after the state guard, maxAttempts or eligible mastery-gate inventory exhaustion returns 409 parallel-forms-exhausted; success creates the deterministic next fixed attempt. Adaptive: policy exhaustion returns 409 retake-policy-exhausted; success—including after typed continuation expiry—starts attemptNumber+1 through mastery_engine with the original immutable pins, validated Results identity, a new child key, and a fresh continuation. The expired continuation is never reused. Success for either kind is 202 CandidateDelivery.

ITD-017, with the adaptive expiry rule from ITD-034

LaunchCandidate

The launch action has no request body and therefore no request Content-Type. Candidate identity comes only from the path. Send Idempotency-Key on every call; the first successful reveal records the receipt. An identical replay returns the same LaunchReceipt only while the request is currently inside [opensAt, closesAt).

ITD-006 × ITD-031 precedence: launch authorization runs before idempotency receipt lookup. Before opensAt, an identical replay returns 403 launch-not-open; at or after closesAt, it returns 410 launch-window-ended. Both denials omit Idempotent-Replayed and never reveal the stored deliverySessionRef. Query parameters and JSON bodies are rejected as 400 validation-failed.

ITD-006 × ITD-031; see launch replay precedence.

CloseAdministration

The strict JSON request body is exactly {}; unknown fields and null are rejected. Close first stops new launch and retake authorization. Any launched fixed attempt lacking submission, or any launched adaptive attempt not yet scored under the four-state composition, returns 409 close-not-ready with no receipt. Otherwise success is 202 Administration in closing.

Fixed forms: for each eligible attempt, AlphaTest reads QTI outcomeState.SCORE, reads subject from Content, writes one Results record through POST /alpha/results/v1/result-records, and exact-reads it back through GET /alpha/results/v1/result-records?qtiAttemptId={qtiAttemptId}. The write and the settled read-back must agree byte-for-byte on administration_id, qti_attempt_id, qti_session_id, qti_test_id, qti_artifact_version_id, content_test_spec_id, test_kind, and subject. Exactly one settled record may resolve. Adaptive: AlphaTest inspect-verifies that mastery_engine reports completed with reportable scale output and acknowledged Results KC components, then retains only the upstream result reference; it never copies score, KC map, mastery, continuation content, or Results body.

Credential boundary: QTI, Content, and Results calls use only server-side provisioned PLATFORM3_TENANT and PLATFORM3_JWT. Neither credential is accepted in this request body, returned to the client, or persisted in reconciliation rows. Deterministic child keys and the original client idempotency key make partial close resumable. scored requires every fixed Results write or adaptive Results acknowledgement to verify and failed=0.

ITD-006, 030, 036

Collection query dictionary

QueryEndpointsType / defaultValidation and semanticsTrace
statusAdministrationsenum; absentExact one-value match from Administration status enum.ITD-004
testKindAdministrationsenum; absentExact one-value match.ITD-004
qtiTestIdAdministrationsstring; absentExact opaque byte match; URL-encoded once.ITD-004
targetSourcedIdAdministrationsPlatform3 reference; absentExact, case-sensitive sourcedId match by target type: for class, compare only administrations.class_sourced_id; for candidate_list, match when at least one immutable binding has candidate_sourced_id equal to the supplied value. It never searches names, emails, QTI candidate refs, or session refs. Results are administrations, de-duplicated even when multiple attempts exist for that candidate.ITD-004, 026
modifiedSinceAdministrations onlyInstant; absentInclusive lower bound. Presence selects sync order modifiedAt,id ascending; absence selects browse order descending. Candidate modifiedSince is deferred until QTI exposes a monotonic runtime cursor.ITD-004
stateCandidatescandidate state; absentExact QTI-derived state match. Paging still advances over every examined immutable binding, including rows removed by this live-state filter.ITD-004, 016
cursorBoth listsopaque string; absent1–1,024 bytes; mutually exclusive with changing any filter from the request that issued it. Administration cursors carry the pinned modified_at,id position. Candidate cursors carry the last examined binding position created_at,candidate_sourced_id,attempt_number ascending; this is the concrete storage key behind ITD-004’s logical createdAt,id ordering. Advancement uses examined bindings even when state filters a row out.ITD-004
limitBoth listsinteger 1–100; 25Decimal integer; no leading sign or fraction.ITD-004
includeDetail onlyenum; absentOnly candidates. Requires the sensitive-read permission and is rejected when resolved candidate count exceeds 100; use subcollection paging instead.ITD-003, 007

Error envelope and catalog

ProblemDetails

Every non-2xx response uses Content-Type: application/problem+json. Upstream bodies and credentials are never passed through.

FieldTypeNullableMeaning
typeHTTPS URINoStable documentation URI: https://alphatest-administration.vercel.app/problems/{code}. This is a data-dictionary refinement of ITD-009’s typed RFC 9457 contract and a required durable public route for every later bundle at this module origin; see route durability.
titlestring 1–120NoStable human summary; clients branch on code, not title.
statusinteger 400–599NoMatches HTTP status.
detailstring 1–2,000NoRequest-specific explanation with no secrets or upstream body. For test-not-assignable, it MUST truthfully name the first failed predicate in the deterministic order documented in assignability failure detail; it must not describe a different predicate merely because several failed.
instancestring URI-referenceNoRequest path plus opaque occurrence reference.
codekebab-case stringNoStable machine code from catalog below.
requestIdRequest IDNoSupport/upstream correlation.
retryablebooleanNoWhether the same logical operation may succeed later. It does not waive idempotency/precondition rules.
errorsFieldError array, 0–100NoRequest field/query failures; empty for non-field errors.
dependencystring enumConditional; never nullPresent on shipped v1 424 responses only, as exactly one of content, oneroster, qti, results, or mastery_engine; omitted on every non-424 response. Caliper and report materialization are not close dependencies.

ITD-009, 025

FieldError

FieldTypeNullableMeaning / allowed valuesProvenance
pointerJSON Pointer string, 1–1,024 bytesNoRequest body location (for example /target/type) or query location prefixed /query/.ITD-009
codestring enumNorequired, unknown-field, invalid-type, invalid-format, invalid-enum, out-of-range, duplicate, or conflict.ITD-009
messagestring, 1–500 bytesNoSafe human explanation; clients branch on code.ITD-009, 025

Stable error codes

HTTP / codeApplies toWhenRetryable
400 malformed-jsonBody endpointsBody is not valid JSON.No
400 validation-failedCreate, provision, patch, launch, advance, retake, close, listsOne or more typed field/query/path rules fail; see errors.No
400 missing-idempotency-keyCreate, provision, first launch, adaptive advance, retake, closeRequired header absent or invalid; clients should always send it on launch.No
401 authentication-requiredAll shipped endpointsBearer JWT absent, invalid, expired, or missing required claims.No
403 insufficient-scopeAll shipped endpointsValid principal’s role-derived, optionally narrowed permission set lacks the endpoint permission.No
403 tenant-mismatchAll shipped endpointsOptional tenant header differs from JWT tenant.No
403 target-not-authorizedCreateClass or candidate falls outside tenant or resource constraints.No
403 launch-not-openLaunchCurrent time is before opensAt; launch authorization precedes replay lookup, so even an identical stored replay omits Idempotent-Replayed and reveals no delivery session reference.Yes, at opensAt
404 route-not-foundUnknown paths outside the published endpoint matrixNo shipped v1 route matches.No
405 method-not-allowedKnown path with unsupported methodPath exists but method is outside its endpoint contract; response includes Allow.No
404 administration-not-foundDetail, patch, candidates, provision, launch, advance, retake, closeDocumented divergence/mapping from ITD-034: this endpoint-specific code is the Administration API rendering of the pinned generic resource-not-found. It means no tenant-scoped administration exists; the same status, code, title, and detail are returned for another tenant’s ID. See ITD-034.No
404 candidate-not-foundLaunch, advance, retakeDocumented divergence/mapping from ITD-034: this endpoint-specific code is the candidate-binding rendering of the pinned generic resource-not-found. It means the candidate is not bound to this administration; another tenant’s binding yields the same status, code, title, and detail. See ITD-034.No
409 idempotency-key-reusedCreate, provision, launch, advance, retake, closeSame scoped key, different canonical request semantics.No
409 administration-state-conflictPatch, launch, advance, retakePATCH cannot mutate current state; launch is closed by closing/close_failed/scored; or retake is outside open. A fixed-form retake also conflicts unless the latest authoritative QTI state is submitted or scored. An adaptive retake conflicts unless the latest composed state is submitted or scored, or advance returned typed adaptive-continuation-expired. No new effect occurs. See ITD-017 and the adaptive extension in ITD-034.No
409 close-not-readyCloseA launched fixed attempt is incomplete, or a launched adaptive attempt has not reached owner-verified scored state. The request is not accepted.Yes, after submission
409 parallel-forms-exhaustedFixed-form retakeAfter the state guard, fixed-form maxAttempts or eligible mastery-gate form inventory is exhausted. Adaptive policy exhaustion uses retake-policy-exhausted.No
410 launch-window-endedLaunchCurrent time is at or after closesAt; launch authorization precedes replay lookup, so even an identical stored replay omits Idempotent-Replayed and reveals no delivery session reference.No
412 etag-mismatchPatchStrong tag is stale.Yes, after GET and review
415 unsupported-media-typeBody endpointsContent-Type is not JSON.No
422 test-not-assignableCreateAn authoritative, reachable fixed-test resource fails its declared relationship. For a mastery gate this means any ITD-037 predicate fails: bank is not published, is not marked mastery-gate, has a membership rule other than same_blueprint_fixed_forms, has a null/different spec_id, has an empty or mismatched ordered member set, or contains a member whose immutable QTI version does not exist. Returned before persistence, OneRoster, or QTI effects. Upstream transport/invalid-response failures use 424 instead.No
422 target-emptyCreateClass resolves to zero eligible candidates.No
422 target-invalidCreateOne or more candidates missing, inactive, duplicate, or invalid; whole request rejected.No
422 qti-accommodation-capability-requiredCreate, patchRequest differs from the v1 semantic no-op.No
422 candidates-page-requiredDetail with include=candidatesMore than 100 bindings; use candidates subcollection.No
422 adaptive-capability-requiredCreateAdaptive configuration or exact candidate-to-Results binding set is missing, duplicate, extra, cross-tenant, or invalid; rejected before persistence or upstream effects.No
409 adaptive-continuation-expiredAdvanceThe bound opaque mastery-engine continuation expired. While the administration remains open and maxAttempts permits another attempt, this typed result satisfies the adaptive CreateRetake state guard; the retake starts a fresh run and continuation and never reuses the expired token. See the base guard in ITD-017 and adaptive expiry rule in ITD-034.No
409 retake-policy-exhaustedAdaptive retakeThe declared maxAttempts policy permits no new adaptive run.No
409 candidate-not-provisionedLaunch, advanceThe candidate binding has not completed provisioning; retry failed provisioning first.Yes, after provision
424 content-unavailableCreate/read/closeContent cannot return a valid authoritative test-spec, bank, membership, or required close-subject response. This is dependency unavailability, not a reachable bank’s predicate mismatch.Yes
424 roster-unavailableCreate/candidate readsOneRoster cannot resolve target or live identity.Yes
424 qti-unavailableCreate/read/patch/launch/retake/closeQTI cannot dereference a required immutable bank-member version or create/read the required session, state, attempt history, or score outcome.Yes
424 mastery-engine-unavailableProvision, advance, adaptive retake, adaptive closeA real mastery-engine call was attempted but transport, 5xx, or owner response validation failed; the prior binding remains retryable.Yes
424 results-unavailableClose before acceptanceResults cannot safely accept or verify writes. Failures after 202 appear as close_failed, not a second HTTP response.Yes
428 precondition-requiredPatchIf-Match missing or weak.No
429 rate-limitedAll shipped endpointsBoundary pressure limit; honor Retry-After. ITD-024Yes
503 service-unavailableAll shipped endpointsAlphaTest itself cannot safely accept or read, distinct from an upstream 424.Yes

test-not-assignable detail selection

The stable machine branch remains code=test-not-assignable; detail is diagnostic and reports exactly one observed predicate. Evaluate in this order and stop at the first mismatch: status=published, is_mastery_gate=true, membership_rule=same_blueprint_fixed_forms, spec_id=contentTestSpecId, non-empty exact ordered membership, then dereferenceability of every immutable QTI version. For example, a bank with status=draft and is_mastery_gate=false reports that its status is draft and published is required; it must not claim the mastery-gate flag was the selected failure. Safe observed enum/boolean/null values may appear; upstream bodies, titles, and learner data may not. If an authoritative response cannot be validated, return the owning 424 instead of inventing a failed predicate.

ITD-009, 025, 037

Persistence dictionary

API-fronted security invariant: these tables are never exposed to browsers. Service-role credentials stay server-side; every primary key, foreign key, unique constraint, lookup, update, and join begins with tenant_id derived from the verified JWT. Anonymous requests are rejected before database access.

Migrations are idempotent. Names below define ownership and constraints for the later implementation; SQL types use PostgreSQL. AlphaTest owns only these glue tables. It does not create roster, QTI session/attempt/response, Results, mastery, or score tables.

Migration ledger

Migration IDOwned objectsRe-run contractProvenance
administration_001_coreadministrations and its tenant-first indexes/checksCREATE TABLE/INDEX IF NOT EXISTS; columns added with ADD COLUMN IF NOT EXISTS; constraint definitions verified before serving.ITD-001, 010, 014
administration_002_bindingsadministration_candidate_bindingsIdempotent create; tenant-scoped FK/unique definitions verified; never backfilled from copied roster/session bodies.ITD-015
administration_003_operationsadministration_idempotency_receipts, administration_provisioning_errorsIdempotent create; 24-hour receipt purge index; no migration stores upstream bodies beyond the receipt replay window. No accommodation table exists while v1 accepts only the semantic no-op.ITD-006, 012, 018, 024
administration_004_close_reconciliationadministration_close_reconciliationsIdempotent create; tenant-scoped FK/unique definitions verified. Adds only attempt/result correlation and retry metadata; never outcome, score, Results body, or Caliper event.ITD-001, 006, 030
administration_005_adaptiveAdaptive columns on administrations/administration_candidate_bindings; administration_adaptive_close_reconciliationsIdempotent column/table/index creation. CHECK constraints enforce fixed/adaptive disjointness; migration never derives continuations, learner bindings, or mastery facts from local data.ITD-015, 032036

administrations — owner: administration module

ColumnPostgres typeNullConstraint / meaningAPI trace
tenant_idtextNoVerified JWT tenant; first member of PK/uniques/indexes.Never returned; tenant routing
idtextNoPK (tenant_id,id); opaque 1–255 bytes.id
statustextNoCHECK Administration status enum.status
qti_test_idtextYesOpaque 1–255-byte requested fixed-test/bank reference; required for fixed-form kinds and null for adaptive. A mastery-gate value is inserted only after ITD-037 Content bank/member and QTI immutable-version validation succeeds. Member metadata is not copied locally.qtiTestId · ITD-037
content_test_spec_idtextNoOpaque Content reference, 1–255 bytes. For mastery gates the accepted bank’s spec_id must have matched before insert; the Content object is not copied.contentTestSpecId · ITD-037
test_kindtextNoCHECK mastery_gate|formative|adaptive_diagnostic.testKind
target_typetextNoCHECK class|candidate_list.target.type
class_sourced_idtextYesRequired only for class; CHECK discriminant. No candidate-list request array is retained; membership is represented only by immutable bindings below.oneRosterSourcedId
opens_attimestamptzNoCHECK opens_at < closes_at; authoritative lower bound for AlphaTest launch authorization. Before it, no QTI session reference is revealed.opensAt
closes_attimestamptzNoAuthoritative upper bound for AlphaTest launch authorization. At or after it, no QTI session reference is revealed; it does not terminate a session already disclosed.closesAt
time_limit_secondsintegerYesCHECK 60–86,400 when non-null; required for fixed kinds and null for adaptive.timeLimitSeconds
max_attemptssmallintNoCHECK 1–10.maxAttempts
parallel_form_rotationtextNoCHECK policy enum and kind compatibility.parallelFormRotation
versionbigintNoDEFAULT 1; increments on successful policy mutation.version/ETag
provisioning_statustextNoCHECK running|complete|with_errors.provisioning.status
provisioning_requestedintegerNoCHECK ≥0; OneRoster-derived count only.requested
provisioning_pendingintegerNoCHECK ≥0 and requested = pending + failed + succeeded.pending
provisioning_failedintegerNoCHECK ≥0.failed
provisioning_succeededintegerNoCHECK ≥0.succeeded
provisioning_last_attempt_attimestamptzYesNull before first upstream attempt.lastAttemptAt
created_attimestamptzNoDatabase clock at insert.createdAt
modified_attimestamptzNoUpdated on local lifecycle, policy, or provisioning mutation.modifiedAt

Adaptive-only columns

ColumnPostgres typeNullConstraint / meaningAPI trace
selection_policy_idtextYesRequired for adaptive; null for fixed. Opaque immutable execution pin.selectionPolicyId
scale_calibration_idtextYesRequired for adaptive; null for fixed.scaleCalibrationId
test_bank_idtextYesRequired for adaptive; null for fixed. Content bank reference only.testBankId
bank_operation_idtextYesRequired for adaptive; null for fixed. Terminal Bank operation reference only.bankOperationId
adaptive_run_modetextYesAdaptive CHECK literal production_learner; null for fixed.runMode

Kind constraint: adaptive rows require all five adaptive columns and null qti_test_id/time_limit_seconds; fixed rows require those two fixed columns and null all five adaptive columns. Indexes: (tenant_id, modified_at DESC, id DESC); (tenant_id, modified_at ASC, id ASC); (tenant_id,status,modified_at DESC,id DESC); (tenant_id,test_kind,modified_at DESC,id DESC); partial (tenant_id,qti_test_id,modified_at DESC,id DESC); (tenant_id,class_sourced_id,modified_at DESC,id DESC). No global unscoped index is used for API reads. Provenance: ITD-032, 033.

administration_candidate_bindings — owner: administration module

Immutable correlation glue only; it makes an administration enumerable without copying an upstream roster or QTI session body.

ColumnPostgres typeNullConstraint / meaningAPI trace
tenant_idtextNoVerified JWT tenant; first member of every key and lookup.Never returned; tenant routing
administration_idtextNoTenant-scoped FK to administrations.Administration.id
candidate_sourced_idtextNoOpaque OneRoster reference, 1–255 bytes; no identity body. Unique with tenant, administration, and attempt number.oneRosterSourcedId
attempt_numbersmallintNoQTI ordinal, CHECK 1–10; not a locally advanced attempt history.attemptNumber
qti_candidate_reftextYesOpaque QTI candidate correlation, 1–255 bytes; never exposed as identity.QTI pass-through · ITD-015
qti_session_reftextYesCurrent opaque QTI session reference; fixed for static attempts, atomically replaced after adaptive advance, and null while adaptive finalizes.deliverySessionRef
selected_form_reftextYesOpaque fixed-form QTI reference; required for fixed attempts and null for adaptive.qtiFormId
results_student_idtextYesAdaptive-only same-tenant opaque Results learner reference; null for fixed attempts. No learner profile.resultsStudentId
adaptive_run_reftextYesAdaptive-only opaque mastery-engine run reference; null for fixed attempts.adaptiveRunRef
continuation_tokentextYesAdaptive-only opaque compact JWE. Server-only; never parsed, logged, or returned. Replaced atomically with the ETag, expiry, and current offer.ITD-033
continuation_etagtextYesAdaptive-only strong mastery-engine ETag; null for fixed attempts.ITD-033
continuation_expires_attimestamptzYesAdaptive-only owner-declared token expiry; null for fixed attempts and non-null for an active adaptive binding. At or after this instant, advance returns typed 409 adaptive-continuation-expired; while the administration remains open and policy permits another attempt, that typed expiry satisfies the adaptive retake state guard and starts a fresh run. The expired token is never reused.ITD-034
creation_receipt_reftextNoOpaque fixed QTI-session or adaptive mastery-run creation receipt, 1–255 bytes, used to verify—not reconstruct—the upstream write.QTI/mastery_engine pass-through · ITD-015, 033
created_attimestamptzNoBinding durability instant; immutable after insert. Candidate enumeration orders this first.ITD-004, 015

Primary key / logical binding id: (tenant_id, administration_id, candidate_sourced_id, attempt_number). Candidate pages order by created_at, candidate_sourced_id, attempt_number ascending. Required paging index: (tenant_id, administration_id, created_at ASC, candidate_sourced_id ASC, attempt_number ASC). Partial uniques: non-null (tenant_id,qti_session_ref) and non-null (tenant_id,adaptive_run_ref). Fixed attempts require QTI candidate/session/form refs and null adaptive fields; adaptive attempts require Results student, run, continuation, ETag, and expiry while active, and null selected form. No identity profile, session body, response, posterior, score, KC map, mastery state, attempt body, or Results body is stored. Provenance: ITD-001, 015, 033, 034.

administration_idempotency_receipts — owner: administration module

ColumnTypeNullConstraint / meaning
tenant_idtextNoFirst key member.
methodtextNoCHECK POST.
pathtextNoCanonical route template plus resource ID where applicable.
key_hashbyteaNoSHA-256 of key; raw key not retained. Unique (tenant_id,method,path,key_hash).
request_hashbyteaNoSHA-256 of canonical request semantics.
response_statussmallintNoOriginal HTTP status.
response_bodyjsonbNoOriginal response needed for exact replay; access limited to server.
created_attimestamptzNoReceipt creation.
expires_attimestamptzNoExactly 24 hours after creation; purge index on expires_at. Candidate-list request bodies disappear with this row.

ITD-006, 012, 026

administration_provisioning_errors — owner: administration module

ColumnTypeNullConstraint / meaning
tenant_idtextNoVerified tenant; first key member.
administration_idtextNoTenant-scoped FK to administrations.
candidate_sourced_idtextNoOpaque OneRoster reference identifying the failed candidate for targeted resume; no identity profile.
attempt_numbersmallintNoCHECK 1–10; identifies the failed child effect.
dependencytextNoCHECK content|oneroster|qti|results|mastery_engine.
codetextNoStable catalog code, 1–120 bytes; no upstream body.
retryablebooleanNoWhether bounded provisioning may safely retry with the original child key.
occurred_attimestamptzNoLatest occurrence instant.

Primary key (tenant_id,administration_id,candidate_sourced_id,attempt_number,dependency,code). This is minimum retry metadata, not a roster or attempt body. The public progress array redacts candidate ID; the provision worker uses it only to resume failed bindings. Provenance: ITD-014, 024, 034.

administration_close_reconciliations — owner: administration module

One row per launched latest QTI attempt. This is retry correlation, not an attempt, outcome, or result store.

ColumnPostgres typeNullConstraint / meaningAPI trace
tenant_idtextNoVerified JWT tenant; first member of every key.Never returned · tenant routing
administration_idtextNoTenant-scoped FK to administrations.Administration.id
qti_attempt_idtextNoOpaque QTI attempt reference, 1–255 bytes; not an attempt body. Primary key with tenant and administration.QTI pass-through · ITD-030
result_record_reftextYesNull until exact Results read-back verifies one record; then immutable opaque reference. No result components or score.resultRecordRef
child_key_hashbyteaNoSHA-256 of deterministic tenant + administration + QTI attempt child key; raw key is not retained. Unique per tenant and attempt.ITD-006, 030
statustextNoCHECK pending|written|verified|failed. written is not completion until exact read-back.CloseProgress
failure_dependencytextYesNull unless status is failed; then CHECK content|qti|results.ProblemDetails.dependency
failure_codetextYesNull unless failed; stable catalog code, 1–120 bytes. No upstream body.error catalog
last_attempt_attimestamptzYesNull before worker attempt; otherwise latest reconciliation attempt.lastAttemptAt
verified_attimestamptzYesSet only with status=verified after exact read-back; otherwise null.resultRecordRef presence

Primary key: (tenant_id, administration_id, qti_attempt_id). Unique: (tenant_id, qti_attempt_id), (tenant_id, child_key_hash). Every query/join is tenant-first. No QTI outcome, response, score, mastery, Results body, component, or Caliper payload is stored. Provenance: ITD-001, 006, 030.

administration_adaptive_close_reconciliations — owner: administration module

One row per launched latest adaptive attempt. It records inspect/reference verification only; it never stores the scale output or KC components.

ColumnPostgres typeNullConstraint / meaningAPI trace
tenant_idtextNoVerified tenant; first member of every key.tenant routing
administration_idtextNoTenant-scoped FK to administrations.Administration.id
candidate_sourced_idtextNoOpaque OneRoster reference; no profile.oneRosterSourcedId
attempt_numbersmallintNoCHECK 1–10; matches the bound adaptive attempt.attemptNumber
adaptive_run_reftextNoOpaque mastery-engine run reference.adaptiveRunRef
result_record_reftextYesNull until inspect confirms completed reportable output and acknowledged Results KC components; then immutable. No Results body.resultRecordRef
statustextNoCHECK pending|verified|failed.CloseProgress
failure_codetextYesRequired only when failed; stable catalog code, 1–120 bytes, with no owner body.error catalog
last_attempt_attimestamptzYesNull before inspect; otherwise latest reconciliation attempt.lastAttemptAt
verified_attimestamptzYesSet only with status verified.resultRecordRef presence

Primary key: (tenant_id,administration_id,candidate_sourced_id,attempt_number). Unique: (tenant_id,adaptive_run_ref). Every query is tenant-first. No continuation content, QTI response, scale score, posterior, KC map, mastery classification, Results body, or Caliper payload is stored. Provenance: ITD-036.

Endpoint contract matrix

Path parameters

ParameterEndpointsType / nullabilityValidation and meaningProvenance
{id}Detail, patch, candidates, provision, launch, advance, retake, closeAlphaTest ID, 1–255 decoded bytes; non-nullExactly one percent-encoded path segment. Compared as an opaque, case-sensitive ID inside the verified tenant. A well-formed ID absent from this tenant—including another tenant’s ID—returns the same 404 administration-not-found.ITD-010, 023
{candidateSourcedId}Launch and advancePlatform3 reference, 1–255 decoded bytes; non-nullExactly one percent-encoded path segment. Must match an immutable binding in this tenant and administration; missing and cross-tenant bindings both return 404 candidate-not-found.ITD-010, 015, 034
EndpointInputSuccess contractEffective permissionEndpoint-specific errors
POST /v1/administrationsCreateAdministration; JSON; idempotency required. For mastery gates, Content bank/spec/member and immutable QTI-version checks run before persistence or roster/session effects.202 Administration, Location: /api/v1/administrations/{id}; replay adds Idempotent-Replayed: trueadministrations:writetest-not-assignable for a reachable predicate mismatch; content-unavailable/qti-unavailable for dependency failure; target errors, qti-accommodation-capability-required, adaptive-capability-required, and other owning dependency 424s
POST /v1/administrations/{id}/provisionStrict {}; JSON; idempotency required202 Administration; retries failed candidate attempts only with original child keysadministrations:writeadministration-not-found, idempotency-key-reused, QTI or mastery-engine 424
GET /v1/administrationscollection queries200 Administration page; no candidate/session refsadministrations:readvalidation-failed, rate-limited
GET /v1/administrations/{id}Optional include=candidates200 Administration with conditional candidates member; strong ETag; included candidates require sensitive permission and ≤100 rowsadministrations:read; plus administrations:read_sensitive for includeadministration-not-found, insufficient-scope, candidates-page-required, dependency 424 if requested composition cannot be completed
PATCH /v1/administrations/{id}PatchAdministration; JSON; strong If-Match200 Administration + new strong ETagadministrations:writeprecondition-required, etag-mismatch, administration-state-conflict, qti-accommodation-capability-required, qti-unavailable (dependency 424)
GET /v1/administrations/{id}/candidatesstate, cursor, limit; no modifiedSince in v1200 CandidateDelivery page composed live, ordered by immutable binding created_at,candidate_sourced_id,attempt_number ascending (the concrete createdAt,id key)administrations:read_sensitiveadministration-not-found, insufficient-scope, QTI/OneRoster 424s
POST /v1/administrations/{id}/candidates/{candidateSourcedId}/launchNo body or query; LaunchCandidate; send idempotency key. Window authorization runs before replay lookup.200 LaunchReceipt only inside [opensAt, closesAt); outside-window replays return 403/410 without a session referenceadministrations:deliverlaunch-not-open, launch-window-ended, administration-state-conflict, candidate-not-found, candidate-not-provisioned, qti-unavailable
POST /v1/administrations/{id}/candidates/{candidateSourcedId}/advanceAdaptive only; strict {}; JSON; idempotency required200 CandidateDelivery after atomic continuation/ETag/offer replacementadministrations:delivercandidate-not-provisioned, adaptive-continuation-expired, administration-state-conflict, mastery-engine-unavailable
POST /v1/administrations/{id}/retakesCreateRetake; JSON; idempotency required202 CandidateDelivery for a fixed rotated form or fresh adaptive mastery runadministrations:writeadministration-state-conflict, fixed parallel-forms-exhausted, adaptive retake-policy-exhausted, QTI/mastery-engine 424s
POST /v1/administrations/{id}/closeStrict {} body; JSON; idempotency required202 Administration with status=closing and CloseProgress; poll detail until scored or retryable close_failedadministrations:closeadministration-not-found, close-not-ready, and Content/QTI/Results/mastery-engine dependency 424s
Retry rule: honor Retry-After on 429/503 and retry only when retryable=true. Reuse the same idempotency key for uncertainty about one request; use a new key only for a new logical operation. For PATCH, refetch and intentionally reapply after 412. Provenance: ITD-024 (pressure/backoff), ITD-006 (idempotent replay), ITD-005 (ETag recovery).

Traceability and gap detectability

PromiseDictionary evidenceAuthoritative ownerInvalid/misaligned value is detectable when…
Class or explicit candidate listTargetInput, TargetSummaryOneRoster identities; QTI delivery membershipDiscriminant, size, uniqueness, active status, tenant/scoped authorization, or atomicity fails.
Every test-kind selector is explicittestKind, AdaptiveConfig, RetakePolicyContent/QTI/mastery_engine + AlphaTest policyUnknown kinds fail validation; fixed mismatches fail assignment; adaptive missing or misbound inputs fail pre-effect with adaptive-capability-required; a successful adaptive implementation additionally requires ITD-035 owner-backed release evidence.
Only an authoritative fixed mastery gate is assignablecurrent Bank 424 posture, six-part assignability predicate, typed mismatch, pre-effect create orderContent bank/spec/membership + QTI immutable artifact versions; AlphaTest validates, never copiesToday, fixed Bank generation is closed before admission with typed 424. After certification opens it, any returned bank that is draft, not a mastery gate, has the wrong membership rule/spec/member set, or contains an undereferenceable immutable member still fails Administration create with pre-effect 422. Bank workflow flags cannot make the check pass.
Window-authorized launchable sessionsLaunchReceipt, launch endpointAlphaTest launch authorization + QTI runtimeReference is revealed outside the window, appears in a list/detail response, or does not dereference in live QTI.
Four runtime states across every test kindstate, CandidateCountsQTI for fixed; mastery_engine + QTI + Results for adaptiveValue falls outside the enum, fixed state cannot trace to QTI, or adaptive state violates ITD-036’s explicit mapping.
Close verifies one authoritative result per attemptCloseAdministration, CloseProgress, resultRecordRef, fixed and adaptive reconciliation tablesQTI/Results for fixed; mastery_engine/Results for adaptive; AlphaTest retry glue onlyscored appears before every owner verification, retry can duplicate a fact, a reference is absent, or AlphaTest stores score, KC, mastery, or outcome bodies.
No shadow platformPersistence dictionaryAlphaTest glue onlyA local schema stores candidates, sessions, attempts, responses, scores, mastery, or copied upstream bodies.
Tenant isolationJWT, tenant-first keysVerified platform identityAny query/join omits tenant, anonymous access reaches storage, or another tenant’s ID is distinguishable from missing.
Stable public provenanceThis dictionary at the durable /reference route (also rendered at root in this bundle) plus the byte-identical approved architecture snapshotOne public module originRoot, /architecture, or /reference is auth-walled, displaced, or any cited ITD fragment fails to resolve. ITD-027
Stable problem documentationEvery ProblemDetails type dereferences at /problems/{code} to the matching stable error-catalog rowAdministration data-dictionary contract, refining typed RFC 9457 from ITD-009Any emitted problem type is auth-walled, returns non-2xx, resolves to a different code, or a later customer-website/implementation bundle omits the /problems/:code rewrite and catalog-link behavior. Unlike root, /architecture, and /reference, this durability requirement is a dictionary refinement rather than a route named by ITD-027.

Deliberate v1 gaps (not silent omissions)

Benchmark and source

This dictionary uses the same cold-integrator virtues as Stripe’s API reference—predictable resources, explicit objects, standard HTTP behavior, authentication, and per-operation clarity—while adding field-level nullability, upstream ownership, persistence mapping, and Architecture-ITD provenance required by AlphaTest. The only normative source is the approved administration architecture; no vendor bundle exists in this repository.