{
  "surface": "platform",
  "deliverable": "architecture",
  "title": "TimeBack Platform Architecture",
  "generatedAt": "2026-06-25T23:30:00Z",
  "architectureRule": "Platform-wide decisions are cross-module truth. Modules inherit these ITDs unless a later platform review explicitly changes them.",
  "upstreamArtifacts": [
    {
      "id": "qti-1edtech-architecture",
      "title": "QTI 1EdTech Architecture",
      "kind": "approved-upstream",
      "url": "https://platform3-avjryotuw-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/1edtech/architecture",
      "promotedEvidence": "24 ITDs, including tenant boundary, security boundary, hosted docs, conformance evidence, and learner-data privacy."
    },
    {
      "id": "qti-1edtech-data-dictionary",
      "title": "QTI 1EdTech Data Dictionary",
      "kind": "approved-upstream",
      "url": "https://platform3-198nmblg3-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/1edtech/data_dictionary",
      "promotedEvidence": "13 qti.* tables and 127 fields with provenance, invalid-value guidance, and stable anchors."
    },
    {
      "id": "qti-1edtech-customer-website",
      "title": "QTI 1EdTech Customer Website",
      "kind": "approved-upstream",
      "url": "https://platform3-fscem3woq-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/1edtech/customer_website",
      "promotedEvidence": "Top-level Authentication and Errors, inline endpoint schemas, idempotency, ETag, If-Match, and Problem responses."
    },
    {
      "id": "qti-1edtech-implementation",
      "title": "QTI 1EdTech Implementation",
      "kind": "approved-upstream",
      "url": null,
      "localPath": "loop/qti/artifacts/1edtech/implementation",
      "promotedEvidence": "Runnable Node package, real conformance runner after rollback, self-contained OpenAPI refs, privacy tests, and migration comments."
    },
    {
      "id": "qti-1edtech-surface-qc",
      "title": "QTI 1EdTech Surface QC",
      "kind": "approved-upstream",
      "url": "https://platform3-a3ocfthbe-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/1edtech/surface_qc",
      "promotedEvidence": "Release-gate report that caught the fake conformance-run path and required rollback to implementation."
    },
    {
      "id": "qti-alpha-architecture",
      "title": "QTI Alpha Architecture",
      "kind": "approved-upstream",
      "url": "https://platform3-1vrj6jl06-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/alpha/architecture",
      "promotedEvidence": "14 Alpha ITDs requiring every cut, restriction, rename, and extension to map back to 1EdTech truth."
    },
    {
      "id": "qti-alpha-data-dictionary",
      "title": "QTI Alpha Data Dictionary",
      "kind": "approved-upstream",
      "url": "https://platform3-jbpj9pddg-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/alpha/data_dictionary",
      "promotedEvidence": "9 public Alpha objects and 84 public fields over the same qti.* persistence model."
    },
    {
      "id": "qti-alpha-customer-website",
      "title": "QTI Alpha Customer Website",
      "kind": "approved-upstream",
      "url": "https://platform3-c21wx9sw2-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/alpha/customer_website",
      "promotedEvidence": "Plain-language API docs for teachers, students, parents, and app-builder LLMs, including trust status and public cuts."
    },
    {
      "id": "qti-alpha-implementation",
      "title": "QTI Alpha Implementation",
      "kind": "approved-upstream",
      "url": null,
      "localPath": "loop/qti/artifacts/alpha/implementation",
      "promotedEvidence": "Facade over the approved 1EdTech implementation, with tests closing public response-shape drift."
    },
    {
      "id": "qti-alpha-surface-qc",
      "title": "QTI Alpha Surface QC",
      "kind": "approved-upstream",
      "url": "https://platform3-n05whnkii-andymontgomery-9773s-projects.vercel.app",
      "localPath": "loop/qti/artifacts/alpha/surface_qc",
      "promotedEvidence": "QC report proving Alpha stayed a facade, inherited privacy/conformance tests, and kept trust status read-only."
    }
  ],
  "platformItDs": [
    {
      "id": "pitd-001-source-authority-self-containment",
      "number": "PITD-001",
      "title": "Source Authority And Self-Containment",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Repository",
      "decision": "The platform3 working tree is the only product authority. Every third-party standard, SDK, example corpus, benchmark snapshot, generated trace, migration, loop state file, and approved artifact needed to regenerate or review the platform must live inside the repository or be recorded as a hosted canonical URL produced by the loop.",
      "downstreamRules": [
        "Every module architecture must list relevant vendor/<source> files read and explain what was adapted or rebuilt.",
        "No implementation may import code or data from a sibling checkout, user home directory, or untracked symlink.",
        "If a public standard is needed, pin it under vendor/<source> with a manifest, retrieval date, source URL, and validation notes."
      ],
      "traceTo": [
        "loop/DECISIONS.md",
        "vendor/qti-spec-bundle/MANIFEST.md",
        "qti-1edtech-architecture"
      ]
    },
    {
      "id": "pitd-002-module-schema-boundaries",
      "number": "PITD-002",
      "title": "Module Schemas And Shared Platform Schema",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Persistence",
      "decision": "Each standards module owns a Postgres schema named for the module, such as qti.*, oneroster.*, and caliper.*. Cross-module platform concepts live in platform.* and are referenced by module tables rather than duplicated.",
      "downstreamRules": [
        "Module-specific content, runtime, conformance, and standards projection tables remain in the module schema.",
        "Shared tenant, idempotency, and audit tables live in platform.*.",
        "A module may create a compatibility view only when reconciling an earlier approved artifact such as qti.tenant."
      ],
      "traceTo": [
        "qti-1edtech-data-dictionary",
        "qti-alpha-surface-qc",
        "pitd-003-shared-tenant-model"
      ]
    },
    {
      "id": "pitd-003-shared-tenant-model",
      "number": "PITD-003",
      "title": "Shared Tenant Model",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Persistence",
      "decision": "platform.tenant is the platform-wide tenant table. Module tables that need tenant scope reference platform.tenant.tenant_id. The prior qti.tenant table is treated as the QTI predecessor pattern and must be reconciled by a later platform data dictionary and implementation step through migration, compatibility view, or documented rollback target.",
      "downstreamRules": [
        "platform.tenant fields must include tenant_id, tenant_key, display_name, status, metadata, created_at, and updated_at unless the data dictionary proves a simpler shape.",
        "Every tenant-scoped route must carry a tenant or workspace path value that resolves to platform.tenant.",
        "QTI reconciliation must be explicit: either migrate qti.tenant into platform.tenant, expose qti.tenant as a compatibility view, or recommend rollback to the earliest QTI deliverable that still hardcodes the old table."
      ],
      "traceTo": [
        "qti-1edtech-architecture#itd-008-tenant-boundary",
        "qti-alpha-customer-website",
        "pitd-005-auth-tenant-scope"
      ]
    },
    {
      "id": "pitd-004-shared-supabase-postgresql",
      "number": "PITD-004",
      "title": "Shared Supabase PostgreSQL",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Persistence",
      "decision": "The platform3 Supabase PostgreSQL database is the shared persistence substrate for every module and every surface. Module implementations may use repositories or facades, but durable state lives in Postgres and must be documented in the data dictionary before implementation depends on it.",
      "downstreamRules": [
        "Secrets stay in .env.local and never in loop artifacts, logs, prompts, summaries, or generated docs.",
        "Service-role operations are implementation concerns and must not bypass architecture, dictionary, and customer-site contracts.",
        "Shared platform.* tables are created before module tables that reference them."
      ],
      "traceTo": [
        "loop/DECISIONS.md",
        "qti-1edtech-architecture#itd-003-shared-supabase-postgresql"
      ]
    },
    {
      "id": "pitd-005-auth-tenant-scope",
      "number": "PITD-005",
      "title": "Authentication, Authorization, And Tenant Scope",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Security",
      "decision": "Every customer API uses signed Bearer JWTs. Tenant-scoped routes compare the route tenant or workspace value with the JWT tenant claim used by that owning API. Public /dev/mint only mints tenantId=demo tokens; generic production tenant and end-user onboarding uses an audited protected token-exchange route after tenant provisioning. For each explicitly allowlisted first-party bridge, the canonical route tenant UUID selects one strict redirect/post-login/logout tuple before exact Host and Origin validation. Apps reverse-proxy only their exact auth paths on their own origin, keeping sessions host-only and SameSite without app secrets or cross-site cookies. session-token keeps binding, session, and audit on canonical platform.tenant.tenant_id, then signs that row's existing unique tenant_key for downstream People & Orgs and Results; there is no universal repository adapter or second mapping authority. Service-role authority is explicit, narrow, audited, and never inferred from a missing user token.",
      "downstreamRules": [
        "Required JWT claims are iss, sub, iat, exp, tenant_id for tenant routes, and roles or scopes for privileged operations.",
        "Real-tenant end-user tokens come from POST /platform/tenants/{tenantId}/token-exchanges, authorized by a same-tenant issuer or platform service token with platform:token:issue; /dev/mint remains demo-only.",
        "PLATFORM_TIMEBACK_TENANT_ROUTES_JSON is a strict canonical-tenant UUID allowlist; invalid JSON, unknown fields, duplicate tenants, mixed origins, callback mismatches, and unlisted tenants fail before storage, and Host/Origin never select configuration.",
        "Each allowlisted end-user JWT carries current student, parent/guardian, or guide role/roles, module scopes, exact person/student relationship claims, iat, and exp; personIds contains authorized students only, and refresh/logout happen at the Platform session bridge rather than through app-owned refresh tokens.",
        "Legacy single-tenant redirect/post-login/logout variables retain their behavior only when the allowlist variable is absent.",
        "Deployed/Postgres TimeBack auth requires PLATFORM_JWT_SIGNING_SECRET and has no source-known fallback secret.",
        "A real-tenant consumer handoff must include the stable module base URL, the matching JWT, and the tenant header value when the module requires X-Timeback-Tenant; Platform3-local operator tokens alone are not sufficient for a deployed consumer.",
        "The service role may run cross-tenant maintenance only through named operations with audit rows and redacted logs.",
        "401 means missing or invalid authentication; 403 means authenticated but not authorized for the tenant, role, or operation."
      ],
      "traceTo": [
        "qti-1edtech-customer-website",
        "qti-alpha-customer-website",
        "pitd-009-audit-log"
      ]
    },
    {
      "id": "pitd-006-http-envelope-and-errors",
      "number": "PITD-006",
      "title": "HTTP Envelope, Status, And Problem Errors",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API",
      "decision": "Every module uses a consistent HTTP contract: successful responses return typed JSON objects or no body for 204; asynchronous accepted work returns 202 with a trackable resource; errors use a redacted Problem object with stable code, status, title, detail, requestId, traceId, and optional fieldErrors.",
      "downstreamRules": [
        "Document status codes 200, 201, 202, 204, 400, 401, 403, 404, 409, 412, 428, and 5xx when a module uses them.",
        "Problem.detail must be safe for the caller and must not include JWTs, headers, access tokens, raw package bytes, direct learner PII, IP addresses, or user agents.",
        "Every customer website must include top-level Authentication and Errors sections and inline request/response schemas per endpoint."
      ],
      "traceTo": [
        "qti-1edtech-customer-website",
        "qti-alpha-customer-website",
        "pitd-008-privacy-pii-student-data"
      ]
    },
    {
      "id": "pitd-007-idempotency-and-concurrency",
      "number": "PITD-007",
      "title": "Idempotency And Optimistic Concurrency",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API",
      "decision": "The platform owns idempotency in platform.idempotency_key for retryable create, upload, import, export-job, and asynchronous command operations. Resource-changing updates that can overwrite user work require validators such as ETag and If-Match.",
      "downstreamRules": [
        "Idempotency scope is tenant_id, module, surface, method, route template, operation id, idempotency key, and request hash.",
        "Same key and same request returns the original outcome; same key and different request returns 409.",
        "Missing If-Match on a required update returns 428; stale or conflicting state returns 409; failed preconditions may return 412 when the module documents that condition."
      ],
      "traceTo": [
        "qti-1edtech-architecture#itd-010-idempotency",
        "qti-1edtech-customer-website",
        "platform.idempotency_key"
      ]
    },
    {
      "id": "pitd-008-privacy-pii-student-data",
      "number": "PITD-008",
      "title": "Student Data Privacy And PII Handling",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Privacy",
      "decision": "Student-facing runtime data uses tenant-scoped pseudonymous learner references at API and persistence boundaries. Direct learner or parent PII is not accepted in learner reference fields, processing traces, logs, audit metadata, generated standards XML, or Problem details.",
      "downstreamRules": [
        "Learner reference fields must be UUID-shaped or a stricter platform-approved opaque identifier and must reject names, emails, phone numbers, SIS IDs, raw JWT subjects, auth tokens, and contact details.",
        "Reusable content records and learner runtime records must have separate lifecycle and deletion semantics.",
        "Logs, audit rows, traces, Problems, and conformance evidence must store hashes, ids, or summaries instead of raw learner PII."
      ],
      "traceTo": [
        "qti-1edtech-architecture#itd-024-candidate-learner-data-privacy",
        "qti-alpha-architecture#alpha-itd-010-student-ref-privacy-language"
      ]
    },
    {
      "id": "pitd-009-audit-log",
      "number": "PITD-009",
      "title": "Cross-Module Audit Log",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Operations",
      "decision": "platform.audit_log is the shared append-only record of customer-visible writes, privileged reads, learner-runtime deletion, conformance/trust changes, authz denials, and administrative maintenance. Module tables remain source of record; the audit log is the platform's tamper-evident narrative of who did what, where, and with what outcome.",
      "downstreamRules": [
        "Required fields include audit_log_id, tenant_id, module, surface, operation_id, actor_subject, actor_roles, resource_type, resource_id, action, outcome, http_status, request_id, trace_id, idempotency_key_id, occurred_at, and redacted_metadata.",
        "Do not store raw request bodies, tokens, learner names, emails, or package bytes in audit metadata.",
        "Every service-role operation must write audit rows whether it succeeds or fails authorization."
      ],
      "traceTo": [
        "pitd-005-auth-tenant-scope",
        "pitd-008-privacy-pii-student-data",
        "platform.audit_log"
      ]
    },
    {
      "id": "pitd-010-observability-and-slos",
      "number": "PITD-010",
      "title": "Observability, Metrics, And SLOs",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Operations",
      "decision": "Every module emits structured logs, metrics, traces, and release evidence using shared field names. Platform-level SLOs are defined for API availability, latency, error rates, conformance/trust freshness, and privacy/security incidents; module SLOs may be stricter but not looser without an ITD.",
      "downstreamRules": [
        "Structured logs must include timestamp, level, service, module, surface, operation_id, tenant_id or tenant hash, request_id, trace_id, actor_subject hash, status_code, latency_ms, outcome, error_code, and redaction_status.",
        "Minimum metrics include request_count, request_latency, error_count by code, authz_denied_count, idempotency_replay_count, validation_reject_count, privacy_reject_count, audit_write_failure_count, and conformance_freshness_seconds where applicable.",
        "Default SLO targets are 99.5 percent monthly availability for customer APIs, p95 read latency under 500 ms excluding large exports, p95 write latency under 2 s excluding documented asynchronous work, and zero tolerated confirmed PII leaks in logs or Problems."
      ],
      "traceTo": [
        "qti-1edtech-surface-qc",
        "pitd-009-audit-log",
        "pitd-016-conformance-and-trust-evidence"
      ]
    },
    {
      "id": "pitd-011-hosted-docs-identity",
      "number": "PITD-011",
      "title": "Hosted Documentation Identity",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Docs",
      "decision": "Documentation deliverables are static hosted HTML sites deployed by the driver to the Vercel project platform3. A deliverable's canonical URL is the hierarchical master-alias path /{module}/{surface}/{deliverable}/, and the underlying Vercel deploy URL is recorded separately as deploy_url in loop state.",
      "downstreamRules": [
        "Doers build OUT_DIR/site and set canonical_url to null; the driver deploys, fetches unauthenticated 2xx, writes deploy_url, and patches canonical_url to the hierarchical master-alias URL.",
        "Deployment Protection must remain off for public documentation deliverables.",
        "Every section that downstream artifacts cite must have a stable hash anchor, and the master site's vercel.json must rewrite that canonical path to the current deploy URL."
      ],
      "traceTo": [
        "loop/DECISIONS.md",
        "qti-1edtech-architecture#itd-023-hosted-docs",
        "qti-alpha-surface-qc"
      ]
    },
    {
      "id": "pitd-012-eval-policy-quality-gates",
      "number": "PITD-012",
      "title": "Evals, Benchmarks, And Quality Gates",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Loop",
      "decision": "Every deliverable is judged by two separate evals: a pass/fail customer eval against a named fetchable benchmark and a binary failure-named scoring rubric. The driver advances only after the reviewer returns approved with customer eval yes, rubric pass, and no cross-artifact contradiction.",
      "downstreamRules": [
        "The customer eval prompt must name one persona, one job-to-be-done, and one live or pinned benchmark.",
        "Rubrics must have 3 to 10 non-overlapping binary failure categories, one critical category, and quote-anchored applied failures.",
        "If a benchmark is missing from loop/context/benchmarks/index.json, the reviewer proposes a fetchable benchmark and the supervisor promotes it once."
      ],
      "traceTo": [
        "loop/context/evals.md",
        "loop/context/benchmarks/index.json",
        "qti-1edtech-customer-website",
        "qti-1edtech-surface-qc"
      ]
    },
    {
      "id": "pitd-013-loop-execution-durable-state",
      "number": "PITD-013",
      "title": "Sequential Loop Execution And Durable State",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Loop",
      "decision": "The loop uses one sequential driver per module. Codex does the build, the driver deploys documentation sites, Claude reviews, and the driver advances, retries, rolls back, regenerates the master site, and commits approval state. Durable memory lives in loop files, not live chat context.",
      "downstreamRules": [
        "Commit loop context, state, transcript, issues, and eval definitions/results; do not commit runtime logs.",
        "Doers may not fabricate canonical URLs or run Vercel deployment from inside the sandbox.",
        "Reviewer rollback goes to the earliest flawed deliverable, including earlier QTI deliverables when platform truth intentionally supersedes them."
      ],
      "traceTo": [
        "loop/driver.sh",
        "loop/platform/state.json",
        "qti-1edtech-surface-qc"
      ]
    },
    {
      "id": "pitd-014-data-dictionary-provenance",
      "number": "PITD-014",
      "title": "Data Dictionary Provenance Contract",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Docs",
      "decision": "Every data dictionary entry documents meaning, shape, lifecycle, constraints, allowed values, invalid values, examples, relationships, and provenance. A field is labeled pass-through, gap fill, cut, restrict, rename, or extend and links to the ITD that authorizes that label.",
      "downstreamRules": [
        "Anchor format must be stable and predictable: table anchors for platform.tenant use table-platform-tenant; field anchors use field-platform-tenant-tenant-id.",
        "Allowed values must explain behavior, not restate names.",
        "Invalid-value guidance is required for IDs, references, enums, JSON objects, learner-data fields, and every status lifecycle."
      ],
      "traceTo": [
        "qti-1edtech-data-dictionary",
        "qti-alpha-data-dictionary",
        "loop/context/benchmarks/data_dictionary.html"
      ]
    },
    {
      "id": "pitd-015-surface-model-and-derivation",
      "number": "PITD-015",
      "title": "Surface Model And Derivation Order",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Product",
      "decision": "Standards modules expose two API/documentation surfaces over shared persistence: an expert standards surface that follows the standard exactly, and an Alpha surface that may only cut, restrict, rename, or extend for students, parents, teachers, and app-builder LLMs. Architecture precedes data dictionary, customer website precedes implementation, and implementation derives from all three.",
      "downstreamRules": [
        "Alpha changes must be exactly one of cut, restrict, rename, or extend, with alternatives and tradeoffs.",
        "The customer website is the implementation specification and must not be skipped.",
        "Implementation may expose no behavior that lacks architecture, data dictionary, and customer website provenance."
      ],
      "traceTo": [
        "loop/context/timeback-platform-brainlift.md",
        "qti-alpha-architecture",
        "qti-alpha-surface-qc"
      ]
    },
    {
      "id": "pitd-016-conformance-and-trust-evidence",
      "number": "PITD-016",
      "title": "Conformance And Trust Evidence",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Release",
      "decision": "Standards modules that claim conformance must execute real local or vendored conformance evidence and persist granular results. Public Alpha surfaces expose trust status as read-only customer information; release tooling and expert surfaces own mutation of conformance runs.",
      "downstreamRules": [
        "Conformance runs must record profile, source bundle hash, runner version, started_at, finished_at, status, summary, and per-assertion details in the module schema unless platform data dictionary later promotes a shared shape.",
        "A missing bundle, runner error, or failed assertion cannot produce a passed status.",
        "Alpha trust-status endpoints are read-only and must link to the approved surface QC URL."
      ],
      "traceTo": [
        "qti-1edtech-surface-qc",
        "qti-alpha-surface-qc",
        "pitd-012-eval-policy-quality-gates"
      ]
    },
    {
      "id": "pitd-017-migrations-and-ddl-discipline",
      "number": "PITD-017",
      "title": "Migrations And DDL Discipline",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Persistence",
      "decision": "Database changes use forward-only migrations with comments, indexes, foreign keys, check constraints, and tests that compare implementation DDL to the approved data dictionary. Destructive changes require an explicit rollback/re-delivery path through the earliest affected deliverable.",
      "downstreamRules": [
        "Every table and non-obvious field needs a SQL comment derived from the data dictionary.",
        "Status values, type labels, learner reference shape, and redaction-sensitive JSON fields require check constraints or documented validation boundaries.",
        "Implementation tests must fail when a published table, field, enum, or critical index is missing."
      ],
      "traceTo": [
        "qti-1edtech-implementation",
        "qti-alpha-implementation",
        "pitd-014-data-dictionary-provenance"
      ]
    },
    {
      "id": "pitd-018-ai-maintainability-contracts",
      "number": "PITD-018",
      "title": "AI-Maintainable Implementation Contracts",
      "Status": "active",
      "Date": "2026-05-21",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Implementation",
      "decision": "Shared libraries and module implementations must be small, contract-tested, dependency-light, and accompanied by runnable examples so AI agents can safely extend them without rediscovering platform rules.",
      "downstreamRules": [
        "The platform implementation deliverable must include JWT verifier, tenant scoper, audit logger, Problem builder, idempotency middleware, and platform.* migration helper.",
        "Every shared library must include a consumer example showing a mock module importing it.",
        "Tests must cover customer website promises, not just internal helper behavior."
      ],
      "traceTo": [
        "qti-1edtech-implementation",
        "qti-alpha-implementation",
        "pitd-005-auth-tenant-scope",
        "pitd-006-http-envelope-and-errors"
      ]
    },
    {
      "id": "pitd-019-route-scoped-cors-preflight",
      "number": "PITD-019",
      "title": "Route-Scoped CORS Preflight",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API",
      "decision": "The platform CORS contract is open-origin and route-scoped: responses set Access-Control-Allow-Origin: *, and OPTIONS preflight returns Access-Control-Allow-Methods containing only the methods served by the matched route plus OPTIONS. A route that serves only GET advertises GET, OPTIONS; a route that serves only POST advertises POST, OPTIONS.",
      "downstreamRules": [
        "Every implementation must define route metadata used by the shared routeCorsMethods helper or an equivalent platform-reviewed adapter.",
        "OPTIONS for a matched route must include exactly the route's served methods plus OPTIONS, ordered GET, POST, PUT, PATCH, DELETE, OPTIONS where present.",
        "Unknown routes may answer OPTIONS only, but must not advertise methods whose runtime handlers would return 404 or 405."
      ],
      "traceTo": [
        "2026-05-26-008",
        "loop/platform/artifacts/1edtech/implementation/impl/src/http/cors.mjs",
        "loop/platform/artifacts/1edtech/implementation/impl/README.md"
      ]
    },
    {
      "id": "pitd-020-api-axis-write-granularity",
      "number": "PITD-020",
      "title": "API Axis: Write Granularity",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Platform administrative writes are per-resource commands only. Bulk import/export write flows belong to standards modules when their source spec requires them; the platform substrate does not add a second bulk-write primitive.",
      "downstreamRules": [
        "Platform tenant creation, detail reads, audit inspection, idempotency inspection, and module catalog operations use resource endpoints.",
        "A module may expose bulk endpoints only when its own architecture pins that standard-specific write model.",
        "CORS Allow-Methods must reflect the actual per-resource or bulk route, not a platform-wide write superset.",
        "Rejected/deferred alternative re-open trigger: Re-open only if three integrators in 90 days need a platform-level batch administrative operation that cannot be expressed as module-owned import/export jobs."
      ],
      "traceTo": [
        "pitd-002-module-schema-boundaries",
        "pitd-007-idempotency-and-concurrency",
        "pitd-019-route-scoped-cors-preflight",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-021-api-axis-read-shape",
      "number": "PITD-021",
      "title": "API Axis: Read Shape",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Platform administrative reads use list plus detail plus narrow sub-collections: module catalog list/detail, tenant detail, tenant audit-log sub-collection, and tenant idempotency-key detail.",
      "downstreamRules": [
        "Every list endpoint must document the matching detail endpoint unless the architecture explicitly defers detail reads with a trigger.",
        "Sub-collections are allowed only for operational facts owned by the parent resource, such as tenant audit-log entries.",
        "Customer websites must show list/detail/sub-collection examples in the same endpoint family.",
        "Rejected/deferred alternative re-open trigger: Re-open for graph-style expansions only after three integrators in 90 days need the same cross-resource projection and the projection cannot be handled by linked detail URLs."
      ],
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-009-audit-log",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-022-api-axis-query-model",
      "number": "PITD-022",
      "title": "API Axis: Query Model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Platform list and sub-collection endpoints support documented filters, stable sort keys, limit-based paging with opaque cursors when result size can exceed one page, and modifiedSince where the collection is an append-like operational log. Ad hoc query parameters are not accepted.",
      "downstreamRules": [
        "Every accepted query parameter must be named in the customer website and validated by implementation tests.",
        "Cursor tokens are opaque to clients and scoped to tenant, route, filter, sort, and principal visibility.",
        "modifiedSince is allowed only on collections whose ordering and clock semantics are documented.",
        "Rejected/deferred alternative re-open trigger: Re-open for arbitrary expression filters only if three integrators in 90 days need the same unsupported predicate and it cannot be represented by a named filter."
      ],
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-010-observability-and-slos",
        "pitd-014-data-dictionary-provenance",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-023-api-axis-concurrency-model",
      "number": "PITD-023",
      "title": "API Axis: Concurrency Model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Resource-changing updates that can overwrite customer work require per-resource validators, exposed as ETag and enforced with If-Match. Missing required validators return 428; stale validators return 412 or the documented 409 conflict shape.",
      "downstreamRules": [
        "Every update endpoint must state whether If-Match is required, optional, or not applicable.",
        "ETag values must change when the customer-visible resource representation changes.",
        "Bulk/import jobs may use job-level validators only when the module architecture pins why per-resource validators do not apply.",
        "Rejected/deferred alternative re-open trigger: Re-open for server-side locks only if optimistic validators cannot prevent a documented repeated lost-update workflow for three integrators in 90 days."
      ],
      "traceTo": [
        "pitd-007-idempotency-and-concurrency",
        "qti-1edtech-customer-website",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-024-api-axis-idempotency-model",
      "number": "PITD-024",
      "title": "API Axis: Idempotency Model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Retryable writes use Idempotency-Key, persisted in platform.idempotency_key with request hash, response replay metadata, tenant, module, surface, method, route template, and operation id.",
      "downstreamRules": [
        "Same key and same canonical request hash returns the original outcome.",
        "Same key and different canonical request hash returns 409 with a typed Problem.",
        "Customer websites must identify which operations require Idempotency-Key and which do not.",
        "Rejected/deferred alternative re-open trigger: Re-open for idempotency-less writes only when the operation is mathematically side-effect-free or the architecture proves duplicate execution is harmless."
      ],
      "traceTo": [
        "pitd-007-idempotency-and-concurrency",
        "platform.idempotency_key",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-025-api-axis-auth-shape",
      "number": "PITD-025",
      "title": "API Axis: Auth Shape",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Platform APIs use Bearer JWTs with tenantId, role or roles, scopes, and allowlisted domain-scoped claims. Public /dev/mint is demo-only. Generic production end-user tokens use the protected tenant-token exchange. An explicitly allowlisted first-party bridge selects an exact same-origin redirect/post-login/logout tuple by canonical route tenant UUID before Host/Origin validation; multiple apps can therefore share one Platform deployment while reverse-proxying only their exact auth paths and keeping host-only SameSite cookies. session-token keeps binding, session, and audit records on the canonical UUID, then signs the tenant row's existing unique tenant_key for downstream People & Orgs and Results. Invalid, duplicate, mismatched, or unlisted configuration fails closed before storage; no Host-derived routing, cross-site cookie, app secret, or second deployment is introduced. Human tokens carry exact person/student relationship claims only: personIds contains authorized students, never the parent or guide actor, and placeIds, schoolIds, classIds, and candidateRef are absent. Shared platform middleware enforces tenant/role/scope and passes exact claims through to the owning module.",
      "downstreamRules": [
        "tenantId is required for tenant-scoped routes and must match the route tenant.",
        "Privileged operations must name the role or scope that authorizes them.",
        "POST /dev/mint?tenantId=demo is the only public mint helper; non-demo tenant ids must be rejected.",
        "Production end-user JWTs are issued through POST /platform/tenants/{tenantId}/token-exchanges by a same-tenant issuer or platform service token with platform:token:issue authority.",
        "PLATFORM_TIMEBACK_TENANT_ROUTES_JSON lists each first-party tenant and exact URI tuple; the route tenant UUID selects the tuple and Host/Origin only validate it.",
        "Each app reverse-proxies only its own tenant's exact auth paths so cookies remain same-origin; the app receives no Platform signing secret.",
        "Legacy single-tenant redirect/post-login/logout variables retain their exact behavior only when the allowlist is absent.",
        "A deployed consumer handoff is complete only when the consumer receives the stable module base URL, the matching real-tenant JWT, and the tenant header value when that module requires X-Timeback-Tenant; an operator or reviewer JWT that remains only in Platform3 local env is not a durable consumer path.",
        "Module-specific domain claims must be documented by that module and cannot be required by shared platform middleware.",
        "Rejected/deferred alternative re-open trigger: Re-open platform-wide domain claims only after two modules independently require the same claim with the same semantics."
      ],
      "traceTo": [
        "pitd-005-auth-tenant-scope",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-026-api-axis-eventing-model",
      "number": "PITD-026",
      "title": "API Axis: Eventing Model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: The platform eventing model is poll plus modifiedSince for append-like operational collections. Webhooks are explicitly deferred until repeated integrator demand proves polling is the blocker.",
      "downstreamRules": [
        "Append-like collections that support modifiedSince must define clock source, inclusivity, and pagination interaction.",
        "Modules must not add webhooks without an architecture ITD, data dictionary entries, customer website docs, implementation tests, and surface QC replay evidence.",
        "Audit and conformance/trust collections are the first platform collections eligible for modifiedSince.",
        "Rejected/deferred alternative re-open trigger: Re-open webhooks when three integrators in 90 days report that polling prevents their documented job or when p95 freshness above five minutes blocks a committed workflow."
      ],
      "traceTo": [
        "pitd-009-audit-log",
        "pitd-010-observability-and-slos",
        "pitd-016-conformance-and-trust-evidence",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-027-api-axis-error-envelope",
      "number": "PITD-027",
      "title": "API Axis: Error Envelope",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Every surface uses typed RFC 7807 Problem Details with stable, dereferenceable type URIs under the master Platform3 problem catalog at https://platform3-andymontgomery-9773s-projects.vercel.app/problems/*, a stable code, requestId, traceId, and optional fieldErrors.",
      "downstreamRules": [
        "Problem detail must be safe to show to the caller and must not include secrets or direct learner PII.",
        "Every documented 4xx and 5xx path must name its Problem code and status.",
        "requestId and traceId must be returned in the error body or headers and logged with the same values.",
        "Rejected/deferred alternative re-open trigger: Re-open only if a required external standard mandates a conflicting error shape and the module architecture proves an adapter cannot preserve typed Problem semantics."
      ],
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-008-privacy-pii-student-data",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-028-api-axis-tenant-routing",
      "number": "PITD-028",
      "title": "API Axis: Tenant Routing",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Tenant scope is carried in the URL for tenant resources and independently enforced from the JWT tenantId claim. Tenant headers are not accepted as the routing source of truth.",
      "downstreamRules": [
        "Tenant-scoped paths must name the tenant or workspace segment and compare it to JWT tenantId.",
        "Mismatched path and JWT tenant returns 403, not 404, unless the module architecture explicitly chooses not-found cloaking for a sensitive resource.",
        "Public demo minting is restricted to tenantId=demo; real tenant end-user tokens are issued through the protected tenant token-exchange route after tenant provisioning.",
        "Rejected/deferred alternative re-open trigger: Re-open tenant headers only if an external conformance suite requires them and an adapter cannot map them to URL plus JWT enforcement."
      ],
      "traceTo": [
        "pitd-003-shared-tenant-model",
        "pitd-005-auth-tenant-scope",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-029-api-axis-conformance-evidence",
      "number": "PITD-029",
      "title": "API Axis: Conformance Evidence",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Conformance and trust claims require executed evidence: vendored or local spec-runner output, recorded bundle/source hashes, runner version, assertion results, and release-gate links. External certification is a future supplement, not a substitute for local evidence.",
      "downstreamRules": [
        "Every passed conformance claim must link to executed evidence and the source bundle hash.",
        "Missing runner, missing bundle, failed assertion, or unparseable output cannot produce passed status.",
        "Surface QC must probe evidence, not just read a boolean trust field.",
        "Rejected/deferred alternative re-open trigger: Re-open external certification as a required gate when a paying integrator or procurement process requires a named external certification before launch."
      ],
      "traceTo": [
        "pitd-016-conformance-and-trust-evidence",
        "qti-1edtech-surface-qc",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-030-api-axis-privacy-retention",
      "number": "PITD-030",
      "title": "API Axis: Privacy / Retention",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Student and learner data follow GDPR-style minimization and deletion semantics: pseudonymous learner references at boundaries, redacted logs/problems/audit metadata, separate reusable-content versus learner-runtime lifecycle, and documented deletion paths for learner-derived state.",
      "downstreamRules": [
        "Learner reference fields must reject direct names, emails, phone numbers, SIS IDs, tokens, and raw auth subjects.",
        "Deletion paths must distinguish reusable educational content from learner runtime or outcome state.",
        "Audit and observability data must store redacted ids, hashes, or summaries instead of raw learner PII.",
        "Rejected/deferred alternative re-open trigger: Re-open retention periods only when a legal, district, or standard-specific requirement imposes a concrete retention value the platform cannot satisfy with current minimization rules."
      ],
      "traceTo": [
        "pitd-008-privacy-pii-student-data",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-031-api-axis-list-endpoints",
      "number": "PITD-031",
      "title": "API Axis: List Endpoints",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "API Axis",
      "decision": "SHIP: Every platform collection that can be read by an integrator exposes a list endpoint with documented filters and paging. Write-and-remember is rejected for platform administrative resources.",
      "downstreamRules": [
        "Every data dictionary collection marked customer-readable must have a documented list endpoint unless architecture explicitly defers it.",
        "List responses return typed JSON with data arrays and pagination links when more pages exist.",
        "Write-only resources require an architecture deferral with a concrete repeat-customer trigger.",
        "Rejected/deferred alternative re-open trigger: Re-open write-and-remember only for high-risk resources where listing itself would leak sensitive information and the architecture pins the support recovery path."
      ],
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-014-data-dictionary-provenance",
        "loop/context/loop-brainlift.md#decision-axes-per-deliverable-type"
      ]
    },
    {
      "id": "pitd-032-incept-producer-surface",
      "number": "PITD-032",
      "title": "Incept Producer Surface",
      "Status": "active",
      "Date": "2026-06-25",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "category": "Producer Surface",
      "decision": "SHIP: Incept is a first-class Platform3 upstream producer surface. Its governed incept schema preserves generation, evaluation, model, source, quality, repair, promotion, deployment, and issue-link provenance; generated student-facing artifacts materialize as canonical Content/QTI rows or explicit reconciliation errors; consumer-facing progress/status reads are exposed through Platform3 API/view paths with normal auth, tenant scope, audit, data-dictionary coverage, non-service-role readback, and governed trafficClass values.",
      "downstreamRules": [
        "The Platform3 data dictionary must cover every field and projection rule for the listed incept tables and views.",
        "Implementation must expose or read-register Incept objects through Platform3-native API/view paths with tenant enforcement, normal JWT/scopes, audit rows, documented idempotency on write paths, and a non-service-role consumer credential path.",
        "No generated student-facing artifact may exist only as Incept ledger JSON; it must have canonical Content/QTI materialization or an explicit reconciliation error.",
        "Incept progress projections must be reproducible from ledger rows and projection checkpoints, and raw DB plus data dictionary must converge with API/view reads.",
        "Incept producer events must expose governed trafficClass values: customer, goal-run, and self-test. Headline Accuracy counts only customer; owner-directed materialization and repair traffic writes goal-run; loop, reviewer, CI, and smoke-test traffic writes self-test.",
        "Incept docs and skill packs must name the Platform3 API/view path as preferred and direct database access as deprecated bootstrap only.",
        "public.incept_generation_runs is legacy/bootstrap compatibility only; no additional durable public.incept_* tables may be added."
      ],
      "traceTo": [
        "loop/context/incept-platform3-surface-decision.md",
        "loop/triage/inbound/2026-06-25-issue-148.md",
        "loop/triage/decisions.yaml#2026-06-25-012",
        "platform_incept_producer_surface",
        "GitHub #148"
      ]
    }
  ],
  "sharedTables": {
    "platform.tenant": "pitd-003-shared-tenant-model",
    "platform.idempotency_key": "pitd-007-idempotency-and-concurrency",
    "platform.audit_log": "pitd-009-audit-log"
  },
  "httpStatusPolicy": {
    "200": {
      "name": "OK",
      "meaning": "Successful read or command that returns a completed resource."
    },
    "201": {
      "name": "Created",
      "meaning": "Synchronous create that returns the newly created resource."
    },
    "202": {
      "name": "Accepted",
      "meaning": "Import, conformance, export-job, or other accepted work that may complete asynchronously."
    },
    "204": {
      "name": "No Content",
      "meaning": "Successful deletion or command with no response body."
    },
    "400": {
      "name": "Bad Request",
      "meaning": "Malformed JSON, invalid field shape, invalid pseudonymous learner ref, unsupported profile, or validation problem documented as caller-fixable."
    },
    "401": {
      "name": "Unauthorized",
      "meaning": "Missing, malformed, expired, untrusted, or unsigned Bearer JWT."
    },
    "403": {
      "name": "Forbidden",
      "meaning": "Authenticated principal lacks tenant, role, scope, service-role, or operation authorization."
    },
    "404": {
      "name": "Not Found",
      "meaning": "Resource is absent or not visible inside the authenticated tenant scope."
    },
    "409": {
      "name": "Conflict",
      "meaning": "Idempotency conflict, stale version state, duplicate unique key, or conflicting lifecycle transition."
    },
    "412": {
      "name": "Precondition Failed",
      "meaning": "A documented conditional request precondition evaluates false."
    },
    "428": {
      "name": "Precondition Required",
      "meaning": "A mutation that requires If-Match or equivalent precondition omitted it."
    },
    "5xx": {
      "name": "Server Error",
      "meaning": "Unexpected platform, dependency, conformance-runner, or release-blocking server failure."
    }
  },
  "apiDecisionAxes": [
    {
      "axis": "write granularity",
      "status": "SHIP",
      "decision": "Platform administrative writes are per-resource commands only. Bulk import/export write flows belong to standards modules when their source spec requires them; the platform substrate does not add a second bulk-write primitive.",
      "itd": "pitd-020-api-axis-write-granularity",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "bulk-only",
        "per-resource only",
        "both bulk and per-resource on the platform surface"
      ],
      "downstreamRules": [
        "Platform tenant creation, detail reads, audit inspection, idempotency inspection, and module catalog operations use resource endpoints.",
        "A module may expose bulk endpoints only when its own architecture pins that standard-specific write model.",
        "CORS Allow-Methods must reflect the actual per-resource or bulk route, not a platform-wide write superset."
      ],
      "reopenTrigger": "Re-open only if three integrators in 90 days need a platform-level batch administrative operation that cannot be expressed as module-owned import/export jobs.",
      "traceTo": [
        "pitd-002-module-schema-boundaries",
        "pitd-007-idempotency-and-concurrency",
        "pitd-019-route-scoped-cors-preflight"
      ]
    },
    {
      "axis": "read shape",
      "status": "SHIP",
      "decision": "Platform administrative reads use list plus detail plus narrow sub-collections: module catalog list/detail, tenant detail, tenant audit-log sub-collection, and tenant idempotency-key detail.",
      "itd": "pitd-021-api-axis-read-shape",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "list-only",
        "list plus detail",
        "list plus detail plus sub-collections"
      ],
      "downstreamRules": [
        "Every list endpoint must document the matching detail endpoint unless the architecture explicitly defers detail reads with a trigger.",
        "Sub-collections are allowed only for operational facts owned by the parent resource, such as tenant audit-log entries.",
        "Customer websites must show list/detail/sub-collection examples in the same endpoint family."
      ],
      "reopenTrigger": "Re-open for graph-style expansions only after three integrators in 90 days need the same cross-resource projection and the projection cannot be handled by linked detail URLs.",
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-009-audit-log"
      ]
    },
    {
      "axis": "query model",
      "status": "SHIP",
      "decision": "Platform list and sub-collection endpoints support documented filters, stable sort keys, limit-based paging with opaque cursors when result size can exceed one page, and modifiedSince where the collection is an append-like operational log. Ad hoc query parameters are not accepted.",
      "itd": "pitd-022-api-axis-query-model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "none",
        "filter and sort only",
        "filter plus paging plus cursor, with modifiedSince on append-like logs"
      ],
      "downstreamRules": [
        "Every accepted query parameter must be named in the customer website and validated by implementation tests.",
        "Cursor tokens are opaque to clients and scoped to tenant, route, filter, sort, and principal visibility.",
        "modifiedSince is allowed only on collections whose ordering and clock semantics are documented."
      ],
      "reopenTrigger": "Re-open for arbitrary expression filters only if three integrators in 90 days need the same unsupported predicate and it cannot be represented by a named filter.",
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-010-observability-and-slos",
        "pitd-014-data-dictionary-provenance"
      ]
    },
    {
      "axis": "concurrency model",
      "status": "SHIP",
      "decision": "Resource-changing updates that can overwrite customer work require per-resource validators, exposed as ETag and enforced with If-Match. Missing required validators return 428; stale validators return 412 or the documented 409 conflict shape.",
      "itd": "pitd-023-api-axis-concurrency-model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "none",
        "If-Match per resource",
        "bulk-only concurrency tokens"
      ],
      "downstreamRules": [
        "Every update endpoint must state whether If-Match is required, optional, or not applicable.",
        "ETag values must change when the customer-visible resource representation changes.",
        "Bulk/import jobs may use job-level validators only when the module architecture pins why per-resource validators do not apply."
      ],
      "reopenTrigger": "Re-open for server-side locks only if optimistic validators cannot prevent a documented repeated lost-update workflow for three integrators in 90 days.",
      "traceTo": [
        "pitd-007-idempotency-and-concurrency",
        "qti-1edtech-customer-website"
      ]
    },
    {
      "axis": "idempotency model",
      "status": "SHIP",
      "decision": "Retryable writes use Idempotency-Key, persisted in platform.idempotency_key with request hash, response replay metadata, tenant, module, surface, method, route template, and operation id.",
      "itd": "pitd-024-api-axis-idempotency-model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "none",
        "Idempotency-Key on writes",
        "Natural unique constraints only"
      ],
      "downstreamRules": [
        "Same key and same canonical request hash returns the original outcome.",
        "Same key and different canonical request hash returns 409 with a typed Problem.",
        "Customer websites must identify which operations require Idempotency-Key and which do not."
      ],
      "reopenTrigger": "Re-open for idempotency-less writes only when the operation is mathematically side-effect-free or the architecture proves duplicate execution is harmless.",
      "traceTo": [
        "pitd-007-idempotency-and-concurrency",
        "platform.idempotency_key"
      ]
    },
    {
      "axis": "auth shape",
      "status": "SHIP",
      "decision": "Platform APIs use Bearer JWTs with tenantId, role or roles, scopes, and allowlisted domain-scoped claims. Public /dev/mint is demo-only. Generic production end-user tokens use the protected tenant-token exchange. An explicitly allowlisted first-party bridge selects an exact same-origin redirect/post-login/logout tuple by canonical route tenant UUID before Host/Origin validation; multiple apps can share one Platform deployment while keeping host-only SameSite cookies. session-token keeps binding, session, and audit records on the canonical UUID, then signs the tenant row's existing unique tenant_key for downstream People & Orgs and Results. Invalid, duplicate, mismatched, or unlisted configuration fails closed before storage; Host never selects configuration. Human tokens carry exact person/student relationship claims only: personIds contains authorized students, never the parent or guide actor, and placeIds, schoolIds, classIds, and candidateRef are absent. Shared platform middleware enforces tenant/role/scope and passes exact claims through to the owning module.",
      "itd": "pitd-025-api-axis-auth-shape",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "role-only",
        "role plus scopes",
        "scoped domain claims on every token",
        "public real-tenant token minting",
        "Host-derived callback routing",
        "cross-site session cookies",
        "one Platform deployment per end-user tenant"
      ],
      "downstreamRules": [
        "tenantId is required for tenant-scoped routes and must match the route tenant.",
        "Privileged operations must name the role or scope that authorizes them.",
        "POST /dev/mint?tenantId=demo is the only public mint helper; non-demo tenant ids must be rejected.",
        "Production end-user JWTs are issued through POST /platform/tenants/{tenantId}/token-exchanges by a same-tenant issuer or platform service token with platform:token:issue authority.",
        "PLATFORM_TIMEBACK_TENANT_ROUTES_JSON lists each first-party tenant and exact URI tuple; the route tenant UUID selects the tuple and Host/Origin only validate it.",
        "Each app reverse-proxies only its own tenant's exact auth paths so cookies remain same-origin; the app receives no Platform signing secret.",
        "Legacy single-tenant redirect/post-login/logout variables retain their exact behavior only when the allowlist is absent.",
        "A deployed consumer handoff is complete only when the consumer receives the stable module base URL, the matching real-tenant JWT, and the tenant header value when that module requires X-Timeback-Tenant; an operator or reviewer JWT that remains only in Platform3 local env is not a durable consumer path.",
        "Module-specific domain claims must be documented by that module and cannot be required by shared platform middleware."
      ],
      "reopenTrigger": "Re-open platform-wide domain claims only after two modules independently require the same claim with the same semantics.",
      "traceTo": [
        "pitd-005-auth-tenant-scope"
      ]
    },
    {
      "axis": "eventing model",
      "status": "SHIP",
      "decision": "The platform eventing model is poll plus modifiedSince for append-like operational collections. Webhooks are explicitly deferred until repeated integrator demand proves polling is the blocker.",
      "itd": "pitd-026-api-axis-eventing-model",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "poll-only",
        "poll plus modifiedSince",
        "webhooks"
      ],
      "downstreamRules": [
        "Append-like collections that support modifiedSince must define clock source, inclusivity, and pagination interaction.",
        "Modules must not add webhooks without an architecture ITD, data dictionary entries, customer website docs, implementation tests, and surface QC replay evidence.",
        "Audit and conformance/trust collections are the first platform collections eligible for modifiedSince."
      ],
      "reopenTrigger": "Re-open webhooks when three integrators in 90 days report that polling prevents their documented job or when p95 freshness above five minutes blocks a committed workflow.",
      "traceTo": [
        "pitd-009-audit-log",
        "pitd-010-observability-and-slos",
        "pitd-016-conformance-and-trust-evidence"
      ]
    },
    {
      "axis": "error envelope",
      "status": "SHIP",
      "decision": "Every surface uses typed RFC 7807 Problem Details with stable, dereferenceable type URIs under the master Platform3 problem catalog at https://platform3-andymontgomery-9773s-projects.vercel.app/problems/*, a stable code, requestId, traceId, and optional fieldErrors.",
      "itd": "pitd-027-api-axis-error-envelope",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "none",
        "plain RFC 7807",
        "typed RFC 7807 with stable URIs"
      ],
      "downstreamRules": [
        "Problem detail must be safe to show to the caller and must not include secrets or direct learner PII.",
        "Every documented 4xx and 5xx path must name its Problem code and status.",
        "requestId and traceId must be returned in the error body or headers and logged with the same values."
      ],
      "reopenTrigger": "Re-open only if a required external standard mandates a conflicting error shape and the module architecture proves an adapter cannot preserve typed Problem semantics.",
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-008-privacy-pii-student-data"
      ]
    },
    {
      "axis": "tenant routing",
      "status": "SHIP",
      "decision": "Tenant scope is carried in the URL for tenant resources and independently enforced from the JWT tenantId claim. Tenant headers are not accepted as the routing source of truth.",
      "itd": "pitd-028-api-axis-tenant-routing",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "tenant in URL",
        "tenant in header",
        "tenant in JWT only"
      ],
      "downstreamRules": [
        "Tenant-scoped paths must name the tenant or workspace segment and compare it to JWT tenantId.",
        "Mismatched path and JWT tenant returns 403, not 404, unless the module architecture explicitly chooses not-found cloaking for a sensitive resource.",
        "Public demo minting is restricted to tenantId=demo; real tenant end-user tokens are issued through the protected tenant token-exchange route after tenant provisioning."
      ],
      "reopenTrigger": "Re-open tenant headers only if an external conformance suite requires them and an adapter cannot map them to URL plus JWT enforcement.",
      "traceTo": [
        "pitd-003-shared-tenant-model",
        "pitd-005-auth-tenant-scope"
      ]
    },
    {
      "axis": "conformance evidence",
      "status": "SHIP",
      "decision": "Conformance and trust claims require executed evidence: vendored or local spec-runner output, recorded bundle/source hashes, runner version, assertion results, and release-gate links. External certification is a future supplement, not a substitute for local evidence.",
      "itd": "pitd-029-api-axis-conformance-evidence",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "none",
        "spec-runner",
        "external certification only"
      ],
      "downstreamRules": [
        "Every passed conformance claim must link to executed evidence and the source bundle hash.",
        "Missing runner, missing bundle, failed assertion, or unparseable output cannot produce passed status.",
        "Surface QC must probe evidence, not just read a boolean trust field."
      ],
      "reopenTrigger": "Re-open external certification as a required gate when a paying integrator or procurement process requires a named external certification before launch.",
      "traceTo": [
        "pitd-016-conformance-and-trust-evidence",
        "qti-1edtech-surface-qc"
      ]
    },
    {
      "axis": "privacy / retention",
      "status": "SHIP",
      "decision": "Student and learner data follow GDPR-style minimization and deletion semantics: pseudonymous learner references at boundaries, redacted logs/problems/audit metadata, separate reusable-content versus learner-runtime lifecycle, and documented deletion paths for learner-derived state.",
      "itd": "pitd-030-api-axis-privacy-retention",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "none",
        "DELETE per spec only",
        "GDPR-style minimization and retention"
      ],
      "downstreamRules": [
        "Learner reference fields must reject direct names, emails, phone numbers, SIS IDs, tokens, and raw auth subjects.",
        "Deletion paths must distinguish reusable educational content from learner runtime or outcome state.",
        "Audit and observability data must store redacted ids, hashes, or summaries instead of raw learner PII."
      ],
      "reopenTrigger": "Re-open retention periods only when a legal, district, or standard-specific requirement imposes a concrete retention value the platform cannot satisfy with current minimization rules.",
      "traceTo": [
        "pitd-008-privacy-pii-student-data"
      ]
    },
    {
      "axis": "list endpoints",
      "status": "SHIP",
      "decision": "Every platform collection that can be read by an integrator exposes a list endpoint with documented filters and paging. Write-and-remember is rejected for platform administrative resources.",
      "itd": "pitd-031-api-axis-list-endpoints",
      "Status": "active",
      "Date": "2026-05-27",
      "Author": "platform3-loop",
      "supersedes": "none",
      "superseded_by": "none",
      "alternatives": [
        "one per collection",
        "write-and-remember",
        "admin-only lists hidden from customer docs"
      ],
      "downstreamRules": [
        "Every data dictionary collection marked customer-readable must have a documented list endpoint unless architecture explicitly defers it.",
        "List responses return typed JSON with data arrays and pagination links when more pages exist.",
        "Write-only resources require an architecture deferral with a concrete repeat-customer trigger."
      ],
      "reopenTrigger": "Re-open write-and-remember only for high-risk resources where listing itself would leak sensitive information and the architecture pins the support recovery path.",
      "traceTo": [
        "pitd-006-http-envelope-and-errors",
        "pitd-014-data-dictionary-provenance"
      ]
    }
  ],
  "requiredModuleContracts": [
    "Use platform.tenant for tenant scope and never create a new per-module tenant table unless a rollback-approved compatibility bridge requires it.",
    "Keep module-specific standards data in the module schema and shared operational facts in platform.*.",
    "Register producer schemas such as incept as governed producer surfaces before any consumer app treats their rows as a product contract.",
    "Include top-level Authentication and Errors sections in every customer website.",
    "Use Problem errors and redact learner PII, secrets, raw package bytes, headers, IP addresses, and user agents.",
    "Require Idempotency-Key for documented retryable create/import/upload/async operations.",
    "Require If-Match or equivalent validators for lost-update-sensitive writes.",
    "Compute Access-Control-Allow-Methods from the matched route and advertise only the served methods plus OPTIONS.",
    "Pin the 12 API decision axes in architecture before downstream data dictionaries, customer websites, implementations, or surface QC claim conformance.",
    "Write platform.audit_log rows for writes, privileged reads, service-role operations, learner-runtime deletion, conformance/trust mutations, and authz denials.",
    "For deployed consumer handoffs, provide the stable <MODULE>_BASE_URL, matching <MODULE>_REVIEWER_JWT or consumer JWT, and <MODULE>_REVIEWER_TENANT when a module requires X-Timeback-Tenant; verify from the consumer side before closing cutover issues.",
    "Emit structured logs and metrics using platform field names and SLO dimensions.",
    "Run customer eval and rubric before advancing; roll back to the earliest flawed deliverable when a later artifact exposes a real contradiction.",
    "Build static hosted docs under OUT_DIR/site and let the driver deploy and patch canonical_url."
  ],
  "qtiPromotions": [
    {
      "source": "qti.* schema ownership",
      "promotion": "Module schemas are mandatory for every standards module.",
      "itd": "pitd-002-module-schema-boundaries"
    },
    {
      "source": "qti.tenant",
      "promotion": "Promoted to platform.tenant; QTI requires explicit reconciliation.",
      "itd": "pitd-003-shared-tenant-model"
    },
    {
      "source": "Bearer JWT and tenant claim matching",
      "promotion": "Shared platform auth and tenant scoping contract.",
      "itd": "pitd-005-auth-tenant-scope"
    },
    {
      "source": "Top-level Authentication and Errors sections",
      "promotion": "Required in every customer website.",
      "itd": "pitd-006-http-envelope-and-errors"
    },
    {
      "source": "Route-scoped CORS correction",
      "promotion": "Open-origin CORS advertises only matched route methods plus OPTIONS.",
      "itd": "pitd-019-route-scoped-cors-preflight"
    },
    {
      "source": "Idempotency-Key and If-Match",
      "promotion": "Shared retry and optimistic concurrency policy.",
      "itd": "pitd-007-idempotency-and-concurrency"
    },
    {
      "source": "candidate_ref / studentRef privacy",
      "promotion": "General student-data privacy policy for all modules.",
      "itd": "pitd-008-privacy-pii-student-data"
    },
    {
      "source": "Conformance runner rollback",
      "promotion": "Conformance claims require real evidence, not fabricated status.",
      "itd": "pitd-016-conformance-and-trust-evidence"
    },
    {
      "source": "Alpha cut/restrict/rename/extend pattern",
      "promotion": "Required divergence vocabulary for every Alpha surface.",
      "itd": "pitd-015-surface-model-and-derivation"
    },
    {
      "source": "Vercel driver-deployed hosted docs",
      "promotion": "Shared documentation identity and master index policy.",
      "itd": "pitd-011-hosted-docs-identity"
    },
    {
      "source": "Customer eval plus scoring rubric",
      "promotion": "Platform-wide quality gate and rollback discipline.",
      "itd": "pitd-012-eval-policy-quality-gates"
    }
  ],
  "qtiReconciliations": [
    {
      "source": "qti.tenant",
      "platformDecision": "platform.tenant is the cross-module tenant truth.",
      "requiredResolution": "Platform data dictionary and implementation must define migration, compatibility view, or rollback target before claiming full platform/QTI conformance."
    },
    {
      "source": "qti.content_package.idempotency_key",
      "platformDecision": "platform.idempotency_key is the shared retry ledger.",
      "requiredResolution": "QTI package rows may keep a package-specific key copy, but shared middleware owns replay/conflict behavior for future modules."
    }
  ],
  "producerSurfaces": {
    "incept": {
      "owner": "platform",
      "kind": "upstream producer surface",
      "decision": "pitd-032-incept-producer-surface",
      "legacyPublicCompatibility": [
        "public.incept_generation_runs"
      ],
      "deprecatedBootstrapPath": "direct SUPABASE_DB_URL reads from Incept apps",
      "governedObjects": [
        "incept.incept_event_ledger",
        "incept.incept_loop_runs",
        "incept.incept_event_artifacts",
        "incept.incept_quality_bars",
        "incept.incept_model_grid_evidence",
        "incept.incept_customer_feedback",
        "incept.incept_repair_attempts",
        "incept.incept_promotion_decisions",
        "incept.incept_external_issue_links",
        "incept.incept_deployments",
        "incept.incept_projection_checkpoints",
        "incept.incept_regeneration_event_timeline_v",
        "incept.incept_progress_projection_input_v",
        "incept.incept_quality_grid_fact_v",
        "incept.incept_model_grid_latest_v",
        "incept.incept_customer_feedback_status_v",
        "incept.incept_layer_health_v",
        "incept.incept_promotion_timeline_v"
      ]
    }
  }
}
