AcmeTest maintainer
Use Platform3 Content, QTI, CASE, and Results identifiers directly. The adaptive composition is resumed with an opaque continuation token—not an AlphaTest run ID.
A cold integrator’s field-level contract for a stateless adaptive run: Content identity and the immutable QTI pool root are bound; start and simulation remain absent until QTI can resolve every pool member version with CASE/KC attribution. Once that owner seam opens, deliver the native Platform3 QTI item session, advance with an encrypted continuation, and read explicit KC gaps plus a mastery-scale result—without creating a second learner record.
Use Platform3 Content, QTI, CASE, and Results identifiers directly. The adaptive composition is resumed with an opaque continuation token—not an AlphaTest run ID.
AlphaTest’s engine store contains immutable selection policy and scale calibration records plus a 24-hour, payload-free idempotency control record. QTI, CASE, Content, Results, and Caliper retain every learner fact.
Required fields must be present. “Conditional” names the exact condition. Omitted optional values are absent, not null, unless the row explicitly permits null.
Clients must tolerate unknown response fields and enum values. A semantic break requires /v2. See ITD-020.
bank.read_adaptive_pool_manifest: Bank’s terminal operation manifest must provide the complete package-bound native member-version plus CASE/KC projection, and Mastery independently reconciles it to QTI. Platform3 calls use a server-held provisioned service profile whose configured tenant must equal the verified client claim. Production learner completion additionally awaits results.write_kc_components. No caller item array, Content member row, generic artifact scan, forwarded client JWT, copied pool, or local KC store may substitute. See binding status, manifest r7, and ITD-028–031.| Name | Type / location | Presence | Validation and meaning | Decision |
|---|---|---|---|---|
Authorization | header · string | Every endpoint | Bearer <JWT>. Signature, iss, aud, exp, sub, role, tenantId, and endpoint scope are verified. Tenant is never accepted elsewhere. | ITD-008 |
Idempotency-Key | header · string | Every POST; required and non-null | 1–255 characters. Its operation scope is verified tenant + HTTP method + canonical path + server HMAC of this key. Inside that scope, reuse with the same canonical request hash resumes and recomposes semantically; reuse with a different canonical request hash returns 409 idempotency-key-reused before upstream work. The same key on another endpoint or for another verified tenant is a separate scoped operation. | ITD-007 |
If-Match | header · strong entity-tag | Advance only | Must exactly equal the latest adaptive-run ETag. Weak tags and * do not identify the pinned response stream and are rejected. | ITD-006 |
ETag | response header · strong entity-tag | Start, inspect, and advance success | Opaque validator over token pins plus canonical token-named QTI attempts. Never parse it. | ITD-006 |
Deprecation | response header · Structured Field Date | Conditional: every response from a deprecated resource | RFC 9745 date in @<Unix-seconds> form announcing when that resource is or becomes deprecated. Its presence does not change response semantics. Treat it as a migration signal, continue handling the documented response, and consult the version-pinned docs; clients must not require this optional hint for correctness. | ITD-020 |
Sunset | response header · HTTP-date | Conditional: deprecated resource scheduled for removal | RFC 8594 HTTP-date announcing when the resource is expected to stop responding. When both headers occur, Sunset must not precede Deprecation. Migrate before this instant; removal or a semantic change is exposed on /v2, never silently applied to /v1. | ITD-020 |
| identifier | JSON string | Per field | Opaque, case-sensitive, non-empty upstream or immutable-version identifier. Preserve exactly; percent-encode when used as one path segment. The owning upstream defines its maximum length. | ITD-002, 020 |
| probability | JSON number | Per field | Finite decimal in the closed interval [0,1]. Calculation uses the calibration’s pinned precision; JSON never contains NaN or Infinity. | ITD-013 |
| timestamp | JSON string | Per field | RFC 3339 UTC instant. Calibration validity uses an inclusive validFrom and exclusive validUntil. | ITD-017 |
| Method + path | Scope | Request | Availability / success contract | Named failures |
|---|---|---|---|---|
| POST /v1/adaptive-runs | mastery:run | StartAdaptiveRunRequest; Idempotency-Key | MANDATORY SHIP · 201 AdaptiveRun + strong ETag, profile, receipt ID, and first real QTI item session; reads the terminal Bank operation manifest and independently reconciles its pool to QTI | 400, 401, 403, hidden 404, 409 idempotency-key-reused/adaptive-pool-version-drift/stream-conflict, 422, 424 upstream-unavailable, 502 qti-adaptive-pool-invalid |
| POST /v1/adaptive-runs:inspect | mastery:read | ContinuationRequest; Idempotency-Key | 200 AdaptiveRun + current strong ETag; rereads Content identity, QTI root/member projection/runtime, and CASE | 400, 401, 403, hidden 404, 409 idempotency-key-reused/adaptive-pool-version-drift/stream-conflict, 422, 424, 502 qti-adaptive-pool-invalid |
| POST /v1/adaptive-runs:advance | mastery:run | ContinuationRequest; Idempotency-Key + If-Match | 200 AdaptiveRun + new strong ETag; consumes scored QTI attempt and may offer one next session | 400, 401, 403, hidden 404, 409 idempotency-key-reused/adaptive-pool-version-drift/stream-conflict, 412 stream-conflict, 422, 424, 428, 502 qti-adaptive-pool-invalid |
| GET /v1/selection-policies/{policyId} | mastery:read | Exact path ID | RELEASABLE CONFIG · 200 SelectionPolicy | 400, 401, 403, hidden 404 |
| GET /v1/scale-calibrations/{calibrationId} | mastery:read | Exact path ID | RELEASABLE CONFIG · 200 ScaleCalibration | 400, 401, 403, hidden 404, 422 calibration-invalid |
| POST /v1/score-recovery-simulations | mastery:simulate | SimulationRequest; Idempotency-Key | MANDATORY SHIP · 200 synchronous ScoreRecoverySimulation with a complete owner-conformance trace and acknowledged Caliper evidence | 400, 401, 403, hidden 404, 409 idempotency-key-reused/adaptive-pool-version-drift, 413 simulation-limit-exceeded, 422, 424 upstream-unavailable, 502 qti-adaptive-pool-invalid |
owner_conformance uses synthetic facts only and requires the complete Bank→QTI→CASE/anchor→Caliper trace. production_learner additionally requires Results acknowledgement of the record and one component per CASE GUID. A learner stays finalizing until Results and Caliper acknowledge; conformance completion explicitly has no learner Results write. Inspect the remaining owner contracts.modifiedSince, webhook, or DELETE endpoints. Discover sessions in QTI/administration and results in Results. See ITD-004, ITD-005, and ITD-010.const inspected = await fetch(`${baseUrl}/v1/adaptive-runs:inspect`, {
method: "POST",
headers: {Authorization: `Bearer ${jwt}`, "Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID()},
body: JSON.stringify({continuationToken})
});
if (!inspected.ok) throw await inspected.json() as ProblemDetails;
const current = await inspected.json() as AdaptiveRun;
const etag = inspected.headers.get("etag")!;
// Deliver current.offeredItem.deliverySessionId in the existing QTI player.
// After QTI has scored that attempt:
const advanced = await fetch(`${baseUrl}/v1/adaptive-runs:advance`, {
method: "POST",
headers: {Authorization: `Bearer ${jwt}`, "Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(), "If-Match": etag},
body: JSON.stringify({continuationToken: current.continuationToken})
});
if (!advanced.ok) throw await advanced.json() as ProblemDetails;
const next = await advanced.json() as AdaptiveRun;
| Field | Type | Presence | Meaning / validation | Owner + provenance |
|---|---|---|---|---|
selectionPolicyId | identifier | Required | Exact immutable policy version; mutable aliases such as “latest” are invalid. | ENGINE ITD-016 |
scaleCalibrationId | identifier | Required | Exact immutable calibration version valid for the pool’s subject, grade coverage, and CASE framework. | ENGINE ITD-017 |
testSpecId | identifier | Required | Platform3 Content test_spec ID. The engine calls the bound tenant-scoped blueprint read, requires assessment_role=spec, and hashes the complete normalized projection. | CONTENT ITD-028, 024 |
testBankId | identifier | Required | Platform3 Content adaptive test_bank ID. Its bound identity read must match testSpecId, report membership_rule=qti_adaptive_selection, and return exactly zero Content members. | CONTENT ITD-028 |
bankOperationId | identifier | Required | Exact terminal same-tenant Bank generation operation. The engine reads GET /v1/bank-operations/{operationId}/manifest, requires its package root and non-empty ordered native member/CASE/KC projection, and reconciles it exactly to the immutable QTI root. A non-terminal, mismatched, incomplete, or ambiguous manifest fails closed. | BANK + QTI ITD-028 |
runMode | enum | Required | owner_conformance or production_learner. Conformance is synthetic-only and creates no Results learner fact. Both modes use the server-selected provisioned Platform3 service profile; caller credentials are never forwarded. | ENGINE ITD-030 |
resultsStudentId | identifier | Required only when runMode=production_learner; otherwise forbidden | Same-tenant Platform3 Results student reference used only for final durable write-back. It is encrypted inside the continuation and never stored by AlphaTest. | RESULTS ITD-001, 019 |
{
"selectionPolicyId": "policy-g5-math-v3",
"scaleCalibrationId": "cal-math-vertical-2026-01",
"testSpecId": "spec-tx-g5-math",
"testBankId": "bank-tx-g5-adaptive",
"bankOperationId": "bankop-01J...",
"runMode": "production_learner",
"resultsStudentId": "student-01HR..."
}
| Field | Type | Presence | Meaning / validation | Owner + provenance |
|---|---|---|---|---|
continuationToken | compact JWE string | Required, non-null | Opaque, non-empty A256GCM authenticated-encrypted token returned by the preceding start/advance. Never parse, log, place in a URL, or persist in analytics. It expires 24 hours after issue, renews on a valid advance, and cannot outlive seven days from start. A token with unknown/retired kid, invalid authentication tag, expiry, or wrong tenant is rejected. The architecture pins no client-enforced byte limit. | ENGINE ITD-002 |
| Field | Type | Presence | Meaning / validation | Owner + provenance |
|---|---|---|---|---|
testSpecId | identifier | Always | Exact Content blueprint ID supplied at start. | CONTENT ITD-028 |
testSpecHash | 64-char lowercase hex | Always | SHA-256 of the complete normalized projection from bound content.read_test_spec. Later drift is 409 stream-conflict. | COMPOSED ITD-016, 028 |
testBankId | identifier | Always | Exact Content adaptive bank ID supplied at start. | CONTENT ITD-028 |
testBankIdentityHash | 64-char lowercase hex | Always | SHA-256 of the bound Content bank identity projection: bank/spec IDs, role, qti_adaptive_selection, zero-member invariant, and update version. It is not a membership hash. | COMPOSED ITD-016, 028 |
bankOperationId | identifier | Always | Exact terminal same-tenant Bank operation supplied at start; binds the immutable evidence manifest used for this run. | BANK ITD-028 |
qtiPoolPackageId | identifier | Always | Immutable QTI package ID from the terminal Bank manifest root. | BANK + QTI ITD-028 |
qtiPoolArtifactId | identifier | Always | Native QTI assessment-test artifact pin from the Bank manifest, independently cross-checked against QTI. | BANK + QTI ITD-028 |
qtiPoolArtifactVersionId | identifier | Always | Immutable root version from the Bank manifest used for the independent QTI delivery-JSON read and member reconciliation. | BANK + QTI ITD-028 |
qtiPoolPackageHash | 64-char lowercase hex | Always | Bank-manifest package hash; two reads of the terminal manifest must agree before selection. | BANK ITD-028 |
qtiPoolEtag | strong entity-tag | Always | ETag returned for the exact immutable QTI root; any mismatch fails closed. | QTI ITD-028 |
resolvedPoolHash | 64-char lowercase hex | Always | SHA-256 over the Bank manifest root, QTI root version/ETag, and ordered reconciled tuples of member version, QTI identifier, canonical CASE GUIDs, and canonical KC GUIDs. A reread change is 409 adaptive-pool-version-drift. | COMPOSED ITD-016, 028 |
| Field | Type | Presence | Meaning / allowed values | Owner + provenance |
|---|---|---|---|---|
continuationToken | compact JWE string | Always | Opaque continuation for the next inspect/advance. A successful advance returns a renewed token; do not reuse its predecessor for a new semantic operation. | ENGINE ITD-002 |
continuationExpiresAt | timestamp | Always | Expiry of this returned token; at most 24 hours from issue and never beyond the run’s seven-day absolute lifetime. | ENGINE ITD-002 |
status | enum | Always | in_progress, finalizing, or completed. Unknown future values must be tolerated. Production completion requires QTI, Results components, and Caliper acknowledgement; conformance completion requires QTI and Caliper but forbids a learner Results write. | COMPOSED ITD-019, 031 |
runMode | enum | Always | owner_conformance or production_learner; echoes the non-interchangeable execution profile. Upstream authentication is always selected server-side from the verified tenant. | ENGINE ITD-030 |
selectionPolicyId | identifier | Always | Exact immutable policy pin. | ENGINE ITD-016 |
scaleCalibrationId | identifier | Always | Exact immutable calibration pin. | ENGINE ITD-016 |
executionPins | ExecutionPins | Always | Exact Content identity plus Bank-manifest and independently reconciled QTI pool/member pins authenticated inside the continuation and revalidated before every offer. | COMPOSED ITD-016, 028 |
offeredItem | OfferedItem or null | Always | Exactly one currently offered item while one is outstanding; null during finalization/completion or before a valid offer. | QTI ITD-015 |
kcClassifications | array<KcClassification> | Always | One entry per in-scope KC, sorted by caseCompetencyGuid for deterministic representation; may be empty before evidence. | COMPOSED ITD-014 |
scaleReportability | enum | Always | pending, reportable, or anchor_unavailable. pending means the run has not reached a publishable scale result. anchor_unavailable explicitly marks every returned KC posterior/classification as provisional and non-reportable; clients may use it for recovery UI but must not publish it as a mastery result. Unknown future values must be treated as non-reportable. | COMPOSED ITD-017 |
scale | ScaleResult or null | Always | Non-null if and only if scaleReportability=reportable. It is null for pending and anchor_unavailable. Anchor failure never produces an unanchored fallback score; kcClassifications remain structurally unchanged but are provisional when reportability is anchor_unavailable. | COMPOSED ITD-017 |
stopReason | enum or null | Always | Null while selection continues; otherwise classifications_complete, precision_target_met, max_items, or time_budget. Unknown future values must be tolerated. | COMPOSED ITD-015 |
remainingUncertainty | number ≥ 0 | Always | Calibration-defined aggregate posterior uncertainty, at pinned numeric precision. Meaning is identified by the calibration model family. | COMPOSED ITD-013 |
resultRecordRef | identifier | Completed production_learner only; forbidden in conformance | Acknowledged Platform3 Results result_record reference, with every per-KC component acknowledged. Absent—not null—otherwise. | RESULTS ITD-019 |
caliperEventRef | identifier | Completed only | Acknowledged upstream Caliper completion-event reference. Absent before acknowledgement. | CALIPER ITD-019 |
receiptId | identifier | Every successful 200/201 | Opaque reference to the redacted replayable trace. The receipt records service-profile selection, approved hosts, Bank/QTI reconciliation, operation IDs, statuses, request IDs, native versions, fixture versions, response hashes, and tenant-isolation probe outcomes; it never contains credentials, learner IDs, responses, or scores. | EVIDENCE ITD-031 |
HTTP/1.1 200 OK
ETag: "mrun-4f0c..."
Content-Type: application/json
{
"continuationToken": "eyJraWQiOiJtZS0yMDI2LTA3IiwiZW5jIjoiQTI1NkdDTSJ9...",
"continuationExpiresAt": "2026-07-16T15:30:00Z",
"status": "in_progress",
"runMode": "production_learner",
"selectionPolicyId": "policy-g5-math-v3",
"scaleCalibrationId": "cal-math-vertical-2026-01",
"executionPins": {"testSpecId":"spec-tx-g5-math","testSpecHash":"a3...64 hex","testBankId":"bank-tx-g5-adaptive","testBankIdentityHash":"b4...64 hex","bankOperationId":"bankop-01J...","qtiPoolPackageId":"pkg-01J...","qtiPoolArtifactId":"qti-pool-g5-math","qtiPoolArtifactVersionId":"45bf...","qtiPoolPackageHash":"c5...64 hex","qtiPoolEtag":"\"pool-45bf\"","resolvedPoolHash":"d6...64 hex"},
"offeredItem": {"deliverySessionId":"qti-session-7f23","artifactVersionId":"qti-artifact-v42","sequence":3},
"kcClassifications": [{"caseCompetencyGuid":"case-guid-1","caseFrameworkGuid":"framework-guid","caseMappingVersion":"2026-06","classification":"not_yet","posteriorProbability":0.62,"evidenceItemRefs":["qti-artifact-v11"]}],
"scaleReportability":"pending", "scale":null, "stopReason":null,
"remainingUncertainty":0.38,
"receiptId":"receipt-01K..."
}
200 with scaleReportability=anchor_unavailable, scale=null, and provisional kcClassifications. A bad, expired, unlicensed, or checksum-invalid calibration is instead 422 calibration-invalid. If an unavailable dependency prevents the operation from safely computing even provisional KCs, the endpoint returns 424 upstream-unavailable and no AdaptiveRun body. ITD-017, ITD-018.| Field | Type | Presence | Meaning / validation | Owner + provenance |
|---|---|---|---|---|
deliverySessionId | identifier | Always | Native same-tenant Platform3 QTI delivery-session ID for the selected immutable item. Pass it directly to the QTI player. | QTI ITD-018 |
artifactVersionId | identifier | Always | Immutable QTI member version selected from the Bank-manifest projection after exact QTI-root reconciliation; must equal the QTI session’s rootArtifactVersionId. | BANK + QTI ITD-028 |
sequence | integer ≥ 1 | Always | Offer sequence in this adaptive composition. Canonical replay orders by this value, then QTI attemptNumber, then attemptId. | COMPOSED ITD-016 |
No item body, answer key, candidate response, pseudonymous candidate ref, or locally generated delivery URL is returned. The existing QTI player delivers and scores this native session.
| Field | Type | Presence | Meaning / allowed values | Owner + provenance |
|---|---|---|---|---|
caseCompetencyGuid | identifier | Always | Live CASE GUID for the knowledge component. AlphaTest does not invent a label or replacement ID. | CASE ITD-014 |
caseFrameworkGuid | identifier | Always | Owning CASE framework GUID used to validate calibration compatibility. | CASE ITD-014 |
caseMappingVersion | identifier | Always | Immutable CASE/KC mapping version pinned for replay. | CASE ITD-016 |
classification | enum | Always | mastered, gap, or not_yet. not_yet means insufficient evidence, not failure. | COMPOSED ITD-014 |
posteriorProbability | probability | Always | Posterior probability of mastery under the pinned calibration—not a percentile or rank. | COMPOSED ITD-013 |
evidenceItemRefs | array<identifier> | Always | Unique QTI item IDs with scored outcomes contributing to this KC, sorted by canonical QTI sequence. Empty before evidence. | QTI ITD-014 |
| Field | Type | Presence | Meaning / validation | Owner + provenance |
|---|---|---|---|---|
scaleScore | finite number | Always | Mastery-scale score produced by the calibration’s monotonic vertical transform. It is RIT-like for crosswalk comparability, not an official NWEA RIT score. | COMPOSED ITD-017 |
standardError | number ≥ 0 | Always | Standard error in the same scale units as scaleScore. | COMPOSED ITD-017 |
scaleId | identifier | Always | Stable identifier for the vertical mastery scale shared by compatible calibration versions. Compare scores only when this identifier and the documented validity/limitations permit it. | ENGINE ITD-017 |
scaleCalibrationId | identifier | Always | Exact immutable calibration that defines the score. | ENGINE ITD-016, 017 |
anchor | object | Always present, non-null | Provenance descriptor containing non-null source, version, 64-character lowercase SHA-256 checksum, and non-empty licenseScope. It contains metadata only, never licensed anchor payloads or rank data. | ANCHOR ITD-017 |
validFrom | timestamp | Always | Inclusive beginning of the calibration validity interval used for this score. | ENGINE ITD-017 |
validUntil | timestamp | Always | Exclusive end of the calibration validity interval; strictly later than validFrom. | ENGINE ITD-017 |
limitations | array<string> | Always | Non-empty plain-language limits of the crosswalk and permitted interpretation. Never contains percentile/rank claims. | ENGINE ITD-017 |
| Field | Type | Presence | Meaning / allowed values | Owner + provenance |
|---|---|---|---|---|
id | identifier | Always | Immutable version identifier; never a mutable alias. | ENGINE ITD-016 |
visibility | enum | Always | tenant or system. Tenant policy is visible only to its verified tenant; system policy is published for authorized platform tenants. | ENGINE ITD-008 |
algorithm | constant | Always | constrained_information_gain for v1. Unknown future values must be tolerated on reads. | ENGINE ITD-015 |
kcCutScore | probability | Always | Mastery cut applied to each KC posterior. | ENGINE ITD-014 |
confidenceThreshold | probability | Always | Minimum posterior confidence required for mastered or gap; otherwise classification is not_yet. | ENGINE ITD-014 |
precisionTarget | number > 0 | Always | Maximum allowed aggregate posterior uncertainty for precision-based stopping, after coverage floors. | ENGINE ITD-015 |
maxItems | integer ≥ 1 | Always | Hard maximum offered items. | ENGINE ITD-015 |
timeBudgetSeconds | integer ≥ 1 or null | Always | Hard elapsed-time budget; null disables only this stopping rule. | ENGINE ITD-015 |
coverageFloors | array<CoverageFloor> | Always | Each entry has caseCompetencyGuid and integer minimumEvidenceItems ≥ 0. Unique by GUID; sorted by GUID. | ENGINE + CASE ITD-015 |
eligibilityRules | object | Always | Pinned constraints for blueprint/CASE coverage, accessibility, exposure, prior use, and pool membership. Keys are versioned with the policy and interpreted by its runtime version. | ENGINE ITD-015 |
checksum | string | Always | Lowercase hexadecimal SHA-256 of the canonical policy document (64 characters); supports replay comparison. | ENGINE ITD-016 |
| Field | Type | Presence | Meaning / validation | Owner + provenance |
|---|---|---|---|---|
id | identifier | Always | Immutable calibration version identifier. | ENGINE ITD-016 |
scaleId | identifier | Always | Stable vertical-scale identifier. Multiple immutable calibration versions may share it only when their published validity and limitations preserve score comparability. | ENGINE ITD-017 |
visibility | enum | Always | tenant or system; same authorization semantics as SelectionPolicy. | ENGINE ITD-008 |
modelFamily | string | Always | Versioned Bayesian estimator family. Client displays but does not interpret it. | ENGINE ITD-013 |
modelVersion | identifier | Always | Immutable model semantics/version. | ENGINE ITD-013, 016 |
numericPrecision | integer 1–15 | Always | Decimal significant-digit precision used by canonical numeric calculation and serialization. | ENGINE ITD-016 |
runtimeVersion | identifier | Always | Exact deterministic calculation runtime. | ENGINE ITD-016 |
caseFrameworkGuid | identifier | Always | Compatible CASE framework. | CASE ITD-014 |
caseMappingVersion | identifier | Always | Pinned KC relationship/mapping version. | CASE ITD-016 |
subject | string | Always | Canonical subject covered by the calibration; exact taxonomy comes from its anchor provenance. | ANCHOR ITD-017 |
gradeCoverage | array<string> | Always | Non-empty ordered grade labels supported by the anchor, including PK/college labels only when licensed and calibrated. | ANCHOR ITD-017 |
validFrom | timestamp | Always | Beginning of validity interval. | ENGINE ITD-017 |
validUntil | timestamp | Always | Exclusive end; must be later than validFrom. | ENGINE ITD-017 |
anchor | object | Always present, non-null | Always contains non-null source, version, 64-character lowercase SHA-256 checksum, and licenseScope. licenseScope describes the provenance/entitlement scope and is never absent or null, including for callers not entitled to restricted anchor material. Restricted parameters and payloads themselves are omitted for unentitled callers; no omitted field is represented as null. | ANCHOR ITD-017 |
recoveryTolerance | number ≥ 0 | Always | Maximum absolute mastery-scale error accepted by the known-mastery simulation for this calibration. | ENGINE ITD-021 |
limitations | array<string> | Always | Non-empty interpretation/crosswalk limitations. No percentile or rank claim. | ENGINE ITD-017 |
checksum | string | Always | 64-char lowercase SHA-256 of the canonical, entitlement-independent calibration descriptor. | ENGINE ITD-016 |
| Field | Type | Presence | Meaning / validation | Owner + provenance |
|---|---|---|---|---|
selectionPolicyId | identifier | Required | Exact immutable policy version. | ENGINE ITD-016 |
scaleCalibrationId | identifier | Required | Exact immutable calibration version. | ENGINE ITD-016, 017 |
testSpecId | identifier | Required | Platform3 Content blueprint used for every synthetic profile. | CONTENT ITD-028 |
testBankId | identifier | Required | Platform3 Content adaptive-bank identity; must be associated with testSpecId, use qti_adaptive_selection, and contain exactly zero Content members. | CONTENT ITD-028 |
bankOperationId | identifier | Required | Exact terminal same-tenant Bank operation whose manifest supplies the immutable package root and ordered native member/CASE/KC projection; the engine independently reconciles it to QTI before simulation. | BANK + QTI ITD-028 |
profiles | array<SyntheticProfile> | Required; 1–100 | Each profile has exactly a unique syntheticProfileId beginning synthetic: and a knownMastery object with 1–500 CASE-GUID keys mapped to probabilities. Real OneRoster, Results, or QTI candidate IDs are rejected. | SYNTHETIC ITD-021 |
| Field | Type | Presence | Meaning / allowed values | Owner + provenance |
|---|---|---|---|---|
profilesTotal | integer ≥ 1 | Always | Number of synthetic profiles accepted. | COMPOSED ITD-021 |
recoveryErrors | array<object> | Always | Exactly one per input profile, same order. Each has syntheticProfileId, finite knownScale, finite recoveredScale, and non-negative absoluteError. No learner identity. | COMPOSED ITD-021 |
tolerance | number ≥ 0 | Always | Exact recoveryTolerance from the pinned calibration. | ENGINE ITD-021 |
maxAbsoluteError | number ≥ 0 | Always | Maximum absoluteError across the returned matrix. | COMPOSED ITD-021 |
withinTolerance | boolean | Always | True iff every recovery error is ≤ tolerance. | COMPOSED ITD-021 |
executionPins | ExecutionPins | Always | Content identity plus Bank-manifest and reconciled QTI immutable root/member/KC hashes used for this deterministic matrix. | COMPOSED ITD-016, 028 |
receiptId | identifier | Always | Opaque reference to the complete redacted and replayable owner_conformance trace. | EVIDENCE ITD-031 |
eventIri | absolute IRI string | Always | Read-back-acknowledged Caliper conformance event; synthetic and non-learner. | CALIPER ITD-021 |
envelopeHash | 64-char lowercase hex | Always | SHA-256 of the acknowledged Caliper envelope; the immutable evidence receipt. | CALIPER ITD-021 |
| Field | Type | Presence | Meaning / validation | Provenance |
|---|---|---|---|---|
type | absolute URI string | Always | Stable documentation URI identifying the problem class. | ITD-009 |
title | string | Always | Short, stable human summary; do not branch program logic on it. | RFC 9457 |
status | integer 400–599 | Always | Matches HTTP status. | RFC 9457 |
detail | string | Always | Occurrence-specific, redacted explanation. | RFC 9457 |
instance | URI-reference string | Always | Opaque occurrence reference; contains no learner identifier. | RFC 9457 + ITD-012 |
code | kebab-case string | Always | Stable machine code from the error catalog. | ITD-009 |
requestId | identifier | Always | Redacted correlation reference subject to operational-log expiry. | ITD-012 |
retryable | boolean | Always | Whether the operation can succeed after the catalog’s stated recovery action, without changing business inputs. Key handling is code-specific: reuse the same key only for a transport/dependency retry of the same request; after a 412 stream-conflict, refetch and reconcile, then send the new If-Match with a fresh key because that is a new semantic advance. | ITD-022 |
invalidParams | array<object> | Validation only | Each entry: JSON Pointer name, stable reason, and message. Never echoes submitted values. | ITD-009 |
currentEtag | strong entity-tag | 412 only | Latest validator to use after refetch/reconciliation. | ITD-006 |
upstream | object | Dependency error only | service enum (platform3_auth, bank, content, qti, case, results, caliper, anchor) plus redacted operation and optional upstream requestId when a call was actually made. A pre-call profile mismatch has no upstream request ID. No host credential, token, payload, or learner data is exposed. | ITD-018, 030 |
HTTP/1.1 412 Precondition Failed
Content-Type: application/problem+json
{"type":"https://alphatest.example/problems/stream-conflict","title":"Adaptive stream changed","status":412,"detail":"Inspect the run before advancing again.","instance":"urn:request:01J...","code":"stream-conflict","requestId":"01J...","retryable":true,"currentEtag":"\"mrun-5a21...\""}
These are the only logical AlphaTest mastery-engine tables: two immutable append-only configuration registries and one short-lived, payload-free idempotency control table. Configuration creation/publishing is an internal calibrated release process—not a public v1 endpoint. Physical migration names may add a schema prefix but may not alter these field contracts.
selection_policies #| Column | SQL type | Nullability | Constraint / meaning | API mapping |
|---|---|---|---|---|
policy_id | text | NOT NULL | PK; non-empty immutable version ID. | SelectionPolicy.id |
tenant_id | text | NULL | Null iff visibility='system'; otherwise verified tenant owner. Never accepted from request body. | Authorization only; not exposed |
visibility | text | NOT NULL | CHECK in (tenant, system). | visibility |
algorithm | text | NOT NULL | v1 CHECK constrained_information_gain. | algorithm |
kc_cut_score | numeric | NOT NULL | CHECK 0…1. | kcCutScore |
confidence_threshold | numeric | NOT NULL | CHECK 0…1. | confidenceThreshold |
precision_target | numeric | NOT NULL | CHECK > 0. | precisionTarget |
max_items | integer | NOT NULL | CHECK ≥ 1. | maxItems |
time_budget_seconds | integer | NULL | CHECK ≥ 1 when present. | timeBudgetSeconds |
coverage_floors | jsonb | NOT NULL | Canonical array matching CoverageFloor; default []; unique/sorted GUIDs validated before insert. | coverageFloors |
eligibility_rules | jsonb | NOT NULL | Canonical versioned rule document; object, not null. | eligibilityRules |
checksum_sha256 | char(64) | NOT NULL | UNIQUE; CHECK lowercase hex. | checksum |
published_at | timestamptz | NOT NULL | Release audit metadata; not learner activity. | Not exposed in v1 |
Indexes: PK (policy_id); UNIQUE (checksum_sha256); partial lookup (tenant_id, policy_id) WHERE visibility = 'tenant'. FKs: none—CASE/Content/QTI references are deliberately not copied into policy rows. Mutation: INSERT-only; DB trigger rejects UPDATE. A corrected policy receives a new ID.
scale_calibrations #| Column | SQL type | Nullability | Constraint / meaning | API mapping |
|---|---|---|---|---|
calibration_id | text | NOT NULL | PK; non-empty immutable version ID. | ScaleCalibration.id |
scale_id | text | NOT NULL | Non-empty stable vertical-scale identifier; changing scale semantics requires a new value. | ScaleCalibration.scaleId and ScaleResult.scaleId |
tenant_id | text | NULL | Null iff system visibility; verified tenant otherwise. | Authorization only |
visibility | text | NOT NULL | CHECK in (tenant, system). | visibility |
model_family | text | NOT NULL | Non-empty Bayesian estimator family. | modelFamily |
model_version | text | NOT NULL | Immutable model semantics. | modelVersion |
model_parameters | jsonb | NOT NULL | Server-only priors + item/KC parameters + monotonic scale transform. Canonical, validated against model version; never returned wholesale. | Not exposed |
numeric_precision | smallint | NOT NULL | CHECK 1…15. | numericPrecision |
runtime_version | text | NOT NULL | Exact deterministic runtime version. | runtimeVersion |
case_framework_guid | text | NOT NULL | Opaque CASE GUID; validated live when used. | caseFrameworkGuid |
case_mapping_version | text | NOT NULL | Immutable mapping pin. | caseMappingVersion |
subject | text | NOT NULL | Non-empty anchor taxonomy value. | subject |
grade_coverage | jsonb | NOT NULL | Canonical non-empty unique string array. | gradeCoverage |
valid_from | timestamptz | NOT NULL | Inclusive validity start. | validFrom |
valid_until | timestamptz | NOT NULL | Exclusive validity end; CHECK later than start. | validUntil |
anchor_source | text | NOT NULL | Licensed source descriptor. | anchor.source |
anchor_version | text | NOT NULL | Exact immutable licensed anchor version. | anchor.version |
anchor_checksum_sha256 | char(64) | NOT NULL | Lowercase hex; verified before score publication. | anchor.checksum |
license_scope | text | NOT NULL · non-empty | Provenance/entitlement scope; never treated as endorsement. This metadata is not the restricted anchor parameter or payload. | Always exposed as non-null anchor.licenseScope; restricted anchor material is omitted when the caller lacks entitlement |
recovery_tolerance | numeric | NOT NULL | CHECK ≥ 0. | recoveryTolerance |
limitations | jsonb | NOT NULL | Canonical non-empty string array. | limitations |
checksum_sha256 | char(64) | NOT NULL | UNIQUE; canonical descriptor hash, lowercase hex. | checksum |
published_at | timestamptz | NOT NULL | Release audit metadata. | Not exposed in v1 |
Indexes: PK (calibration_id); UNIQUE (checksum_sha256); (scale_id, subject, valid_from, valid_until); partial (tenant_id, calibration_id) WHERE visibility = 'tenant'. FKs: none—CASE and anchor sources remain external and are validated on the wire. Mutation: INSERT-only; DB trigger rejects UPDATE. Invalid-row test: an empty scale ID, overlapping validity that claims incompatible scale semantics under one ID, invalid interval, bad checksum, empty provenance, or tenant/system visibility mismatch violates this contract.
| Column | SQL type | Nullability | Constraint / meaning | API mapping |
|---|---|---|---|---|
tenant_id | text | NOT NULL | Verified JWT tenant claim; non-empty. Part of the primary key and every server query. Never accepted from a header, path, or body. | Not exposed |
method | text | NOT NULL | Canonical uppercase HTTP method; CHECK method = 'POST' in v1. | Request method |
canonical_path | text | NOT NULL | One exact public POST path from the endpoint table; excludes origin, query, fragment, and tenant data. | Request path |
key_hmac | char(64) | NOT NULL | Lowercase-hex HMAC-SHA-256 of the 1–255 character Idempotency-Key under a server secret. The raw key is never persisted. | Not exposed |
canonical_request_hash | char(64) | NOT NULL | Lowercase SHA-256 of the endpoint’s canonical request representation. Equality permits resume/recomposition; mismatch produces 409 idempotency-key-reused before upstream work. | Not exposed |
operation_id | uuid | NOT NULL | Deterministic internal operation identity derived from scoped key plus request hash. It is not a run, learner, candidate, session, or result identifier. | Not exposed |
lifecycle_state | text | NOT NULL | Enum started, completed, or failed. Unknown values are invalid; state may move only started→completed or started→failed. | Drives semantic retry only |
terminal_status | smallint | NULL | Absent while started; required for completed/failed; CHECK 100–599. Records only HTTP status, never response data. | Controls semantic retry; not exposed |
created_at | timestamptz | NOT NULL | Server timestamp when conflict protection begins. | Not exposed |
updated_at | timestamptz | NOT NULL | Server timestamp; CHECK not earlier than created_at. | Not exposed |
expires_at | timestamptz | NOT NULL | Exactly created_at + interval '24 hours'; expired rows are unusable and purged. | Not exposed |
Indexes: PRIMARY KEY (tenant_id, method, canonical_path, key_hmac); UNIQUE (operation_id); purge index (expires_at). FKs: none. Mutation: one atomic insert-or-read before side effects; only the legal lifecycle transition, terminal_status, and updated_at may change. Access: server service role only; anon/public/browser roles have no SELECT/INSERT/UPDATE/DELETE. Invalid-row test: any raw key, payload/response column, learner/upstream identifier, bad hash, illegal state/status pairing, cross-tenant query, or row older than 24 hours violates this contract.
| Rule | Contract | Provenance |
|---|---|---|
| Idempotent DDL | CREATE TABLE IF NOT EXISTS; additive columns use ADD COLUMN IF NOT EXISTS. Constraints/indexes are named and existence-checked. | Shared datastore discipline |
| Single owner | Only mastery_engine migrates these three tables. Other modules consume public APIs, never create lookalike tables. | ITD-001, 007 |
| Mutation split | Published policy/calibration rows reject UPDATE; correction inserts a new immutable ID/checksum. Idempotency controls permit only the documented lifecycle transition and are hard-purged after 24 hours. No public DELETE endpoint exists. | ITD-007, 016, 020 |
| API-fronted access | Server credentials only; anonymous DB access is not a product path. Reads enforce tenant/system visibility after JWT verification. | ITD-008 |
| Never in any engine table or logs | System of record | How the API uses it |
|---|---|---|
| candidate / OneRoster sourcedId | OneRoster | No caller candidate ID is accepted. The engine derives per-offer pseudonymous QTI candidate refs in memory; they remain encrypted in the continuation and are never returned or stored locally. |
| QTI session, item response, answer value, item outcome | QTI | Read-through in memory; only opaque session/item refs appear on wire |
| mastery posterior, KC classification, scale score | Results for durable facts | Calculated in memory; acknowledged result reference returned |
| result_record / test_result_component payload | Results | Idempotent upstream write; no local copy |
| Caliper event payload | Caliper | Idempotent upstream write; redacted receipt ref only |
| bearer token, request body, upstream response body | Not retained | Redacted from operational logs |
| HTTP | code | When | retryable | Integrator action |
|---|---|---|---|---|
| 400 | invalid-request | Malformed JSON/path ID, unknown field, wrong type/range, learner-data field, or unsupported query parameter. | false | Correct fields using invalidParams. |
| 401 | authentication-required | Missing, malformed, expired, wrong-signature/issuer/audience JWT. | false | Mint a valid platform JWT. |
| 403 | insufficient-scope | Valid AlphaTest principal lacks endpoint scope. | false | Request the documented least-privilege AlphaTest scope. |
| 404 | resource-not-found | Absent resource or a resource owned by another tenant. Same response prevents enumeration. | false | Verify the upstream ID in the caller’s tenant. |
| 409 | idempotency-key-reused | Within the same verified tenant + HTTP method + canonical path + key-HMAC scope, the stored canonical request hash differs from the current canonical request hash. Cross-tenant or cross-path use of the same literal key is a separate scoped operation and does not trigger this error. | false | For an intentional new request in the same scope, use a new key. For a retry, send the original canonical request unchanged; an identical hash resumes and recomposes semantically. |
| 409 | stream-conflict | Content response hash drift, conflicting QTI outcomes, token/session mismatch, or an existing pseudonymous offer conflicts with the selected artifact. Start and advance may return it while composing; inspect may return it when its mandatory reread proves the continuation no longer identifies one coherent immutable stream. | false | After start or advance, call :inspect once with the latest continuation and do not overwrite upstream state. If :inspect itself returns this code, the conflict is terminal for that continuation: retain the problem requestId for support/audit, correct the upstream identity or version drift, and start a new run. Do not retry inspect or advance with the conflicted continuation. |
| 409 | adaptive-pool-version-drift | The reread immutable QTI root/member/KC projection no longer matches the token-pinned version, ETag, or resolvedPoolHash. | false | Stop the run; do not substitute a newer pool or generic artifact-list result. Start a new run only against a newly certified immutable version. |
| 412 | stream-conflict | If-Match does not equal the current strong ETag. | true | Call :inspect, reconcile, then advance with currentEtag and a fresh key because it is a new semantic operation. |
| 413 | simulation-limit-exceeded | Simulation has more than 100 profiles or any profile has more than 500 KC entries. | false | Split into bounded requests; do not send real learner profiles. |
| 422 | calibration-invalid | Missing/incompatible item or KC parameters, CASE framework mismatch, expired/unlicensed/bad-checksum anchor, or unsupported subject/grade. | false | Choose a valid immutable calibration or publish a corrected version. |
| 424 | upstream-unavailable | A required Bank manifest, provisioned same-tenant Platform3 service profile, Content/QTI/CASE/Results/Caliper/anchor binding, version, capability, or safe response is transiently unavailable. The released route never treats a missing owner contract as a permanent successful steady state. | true only for a transient safe read or idempotent write | Inspect upstream.service, upstream.operation, and the binding table. Retry only when true, reusing the same key for the identical request; never supply a credential, item list, or local substitute. |
| 424 | finalization-incomplete | A required finalization write/read-back was attempted but rejected or became unavailable. A safely composed run may instead return 200 status=finalizing while acknowledgement is pending. QTI session closure is never required. | true | Retry the identical advance with the same key only when instructed; otherwise inspect before a new semantic advance. |
| 428 | precondition-required | Advance omitted If-Match. | false | Call :inspect and send its strong ETag. |
| 502 | qti-adaptive-pool-invalid | The terminal Bank manifest or its independent QTI reconciliation failed: a root ref did not resolve exactly once, a member was outside the immutable graph, CASE/KC arrays were empty/non-canonical, package identity/hash disagreed, or repeat reads were unstable. | false | Preserve the request/receipt ID and report the owner-contract violation; never select from the partial projection. |
Problem type URI rule: type is the absolute, stable documentation URI for the matching catalog code; clients branch on code, not on title or detail. A type URI may gain documentation without changing its meaning. ITD-009.
424; a present-but-invalid QTI pool projection uses typed 502 qti-adaptive-pool-invalid; request/concurrency/calibration failures use their named types. Every unexpected 5xx still uses ProblemDetails with a redacted request ID and never leaks a stack, token, body, or upstream payload.Download upstream-bindings.json, the only executable upstream contract. Manifest mastery-engine-upstreams-2026-07-17-r7 has status bank_contract_blocks_architecture_journey_blocks_implementation: Content identity and QTI root reads are bound; Bank’s terminal manifest is the mandatory owner projection; provisioned Platform3 service JWT profiles are bound; Results component writes remain the production learner gap. ITD-028–031.
| Operation ID | Status | Published binding or required normalized contract | Release consequence |
|---|---|---|---|
platform3.provisioned_service_jwt | bound | Server-held approved base URLs plus PLATFORM3_TENANT and PLATFORM3_JWT. The verified AcmeTest tenant must equal the selected profile tenant before wire I/O; the client JWT is never forwarded. | Enables owner-backed conformance and learner flows for configured tenants; anonymous and bidirectional cross-tenant probes remain mandatory. |
content.read_test_spec | bound | GET /tenants/{tenantId}/alpha/content/items/{testSpecId}/blueprint; require role=spec and stable complete normalized hash. | Blueprint identity/constraints ship. |
content.validate_adaptive_bank_identity | bound | GET /tenants/{tenantId}/alpha/content/items/{testBankId}/bank-members; require bank/spec match, qti_adaptive_selection, and data=[]. | Bank identity ships; Content is explicitly not the adaptive member owner. |
qti.read_adaptive_pool_root | bound root only | GET /tenants/{tenantId}/qti/artifact-versions/{artifactVersionId}/delivery-json; require matching immutable version/ETag, assessment-test root, ordered refs, and stable repeat hash. | Real 200 receipt proves the QTI root seam, not selection readiness. |
bank.read_adaptive_pool_manifest | mandatory owner contract | GET /v1/bank-operations/{operationId}/manifest; terminal same-tenant evidence must contain root packageId, artifact/version, QTI identifier, package hash, and a non-empty ordered member projection with native artifact/version, package-scoped QTI identifier, and non-empty canonical CASE/KC GUID arrays. Repeat ETag/hash and independent QTI-root bijection must agree. | Positive redacted receipt blocks architecture; the full start-to-stop journey blocks implementation and later. Invalid=502, drift=409; absence is never permission to omit the route. |
qti.read_candidate_runtime | bound | GET /tenants/{tenantId}/qti/candidates/{candidateRef}/runtime-data; filter to token-named sessions and canonicalize attempts. | Scored-stream replay ships. |
qti.offer_selected_item | bound | POST /tenants/{tenantId}/qti/delivery-sessions; exact selected artifact, derived pseudonymous candidate, non-empty delivery snapshot. | Real QTI offers ship. |
qti.score_item_attempt | bound | AcmeTest player calls POST .../delivery-sessions/{deliverySessionId}/attempts; engine consumes durable outcome and processing trace. | Real QTI scoring boundary ships. |
case.resolve_mapping | bound | GET /ims/case/v1p1/CFItems/{sourcedId}; sourcedId and URI must match the pinned mapping. | Live KC identity ships. |
nweamap.verify_anchor | bound | GET /nweamap/v1/r90; exact table version/source point and non-null source ref. | Scale anchoring ships; no rank output. |
results.write_result_record | bound | POST /alpha/results/v1/result-records; acknowledgement echoes deterministic producer_result_id. | Base durable outcome ships. |
results.write_kc_components | upstream_gap | Requires atomic or idempotently attachable KC components containing Results record ID, CASE GUID, classification, posterior, evidence refs, policy version, and calibration version; response acknowledges every component ID/count. | Blocks mastery publication. |
caliper.emit_completion_or_simulation | bound | POST /caliper/v1p2/events; learner completion only after Results, simulation as non-learner conformance evidence. | Audit/synthetic evidence ships. |
caliper.read_evidence_ack | bound | GET /caliper/v1p2/events?eventIri={eventIri}; IRI/generated refs match the emitted receipt. | Immutable evidence acknowledgement ships. |
adaptivePool receipt plus independent QTI-root reconciliation (ITD-028). From implementation onward, start, inspect, advance, and score-recovery must ship and a replayable owner-backed start-to-stop journey must pass; a missing owner projection never authorizes absent routes, permanent 404/424 responses, or a configuration-only product (ITD-029). Production learner completion additionally requires results.write_kc_components. The suite proves own-tenant inspect and indistinguishable 404s for both cross-tenant continuation replays (ITD-030, ITD-031).| Fact family | Authoritative owner | AlphaTest behavior | Persistent locally? | Decision |
|---|---|---|---|---|
| Blueprint + adaptive bank identity | Platform3 Content test_spec / test_bank | Read bound blueprint and bank identity; require qti_adaptive_selection and exactly zero Content member rows. | No | ITD-028 |
| Adaptive pool root + immutable member versions | AlphaTest Bank provenance + Platform3 QTI package graph | Read the terminal Bank evidence manifest, require its complete package/member/CASE/KC projection, independently reconcile an exact ordered bijection to QTI, and hash the result in memory. | No | ITD-028 |
| Tenant-bound upstream credential | Platform3 operator provisioned service profile | Select server-held approved base URLs, PLATFORM3_TENANT, and PLATFORM3_JWT only when configured tenant equals the verified AcmeTest claim. Never forward or accept a caller credential. | Server configuration only; never learner data | ITD-030 |
| Delivery session, offered item, scored outcomes | Platform3 QTI | Read/command on wire; canonicalize in memory | No | ITD-002, 016 |
| Standard/KC GUID + relationships | Platform3 CASE | Resolve live; pin mapping version; return refs | No | ITD-014 |
| Selection/stopping/classification rules | AlphaTest mastery_engine | Immutable policy row | Yes, configuration only | ITD-015 |
| Model, scale transform, anchor provenance/tolerance | AlphaTest configuration + licensed anchor source | Immutable calibration row; verify anchor on wire | Yes, configuration only | ITD-017 |
| Idempotency conflict/retry coordination | AlphaTest mastery_engine | Store only scoped key HMAC, canonical request hash, deterministic operation ID, lifecycle/status, and timestamps; recompose responses from upstream owners | Yes, control metadata for exactly 24 hours | ITD-007 |
| Durable mastery / KC result components | Platform3 Results | Write idempotently; return acknowledged ref | No | ITD-019 |
| Completion event | Platform3 Caliper | Write idempotently; return acknowledged ref | No | ITD-010, 019 |
| Simulation evidence receipt | Platform3 Caliper | Write non-learner conformance event; read back event IRI and envelope hash | No | ITD-021 |