Platform3 · Canonical architecture

Applications Alpha Architecture

This page is rendered directly from the committed architecture decisions. Each stable section anchor is part of the public traceability contract.

Source-bound decision record

11 committed decisions · applications/alpha Source generated 2026-07-16T17:00:00Z

#appitd-000-module-boundary-and-owners

Applications owns third party caller governance, not people or platform mechanics

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A teacher, student, integrator, or their LLM must be able to identify the external application behind every Alpha call without mistaking that application for the human using it, the publisher that owns it, the school tenant it may access, or the Platform service that authenticated it.

Context

The Brainlift creates Applications as the seventh Alpha core module. Platform already owns shared JWT validation, tenant routing, idempotency, and audit storage; People & Orgs owns people and school organizations, including a person's credential for an external learning app. No existing owner governs a third-party application's own identity, lifecycle, scopes, clients, and attribution when it calls Alpha.

Decision

Applications owns publisher registration, application identity and lifecycle, per-tenant application grants, auth-client metadata keyed by application, and the contract that stamps each external Alpha request with application_id and auth_client_id. Platform remains the owner of authentication mechanics, tenants, idempotency, and audit-log persistence. People & Orgs remains the owner of humans, school organizations, and alpha.app_credential. Domain modules remain the owners of the data an application reads or writes.

Alternatives and tradeoffs

  • Represent an application as a People & Orgs user or organization — Benefit: Reuses existing roster identity endpoints and avoids a new module. — Cost: Conflates software callers with people or schools, gives application lifecycle and scope the wrong owner, and makes historical attribution depend on mutable roster facts.
  • Put the registry, clients, grants, and audit records directly in Platform — Benefit: Keeps all security-adjacent records in one module. — Cost: Turns Platform's shared mechanics into a business registry and removes the plain-language Applications boundary app builders need.
  • Let every domain module register and identify its own callers — Benefit: Each module can tune onboarding and scopes independently. — Cost: Creates duplicate application identities and credentials, and one cross-module request can no longer have one authoritative actor.

Why this is simplest

One module owns the business identity of the caller while the already-shared Platform layer continues to execute authentication and audit mechanics. Every other module only references application_id; none needs a second registry.

Rationale and consequences

Applications is the single business owner for third-party software callers; Platform executes cross-cutting mechanics, People & Orgs owns people, and domain modules own domain data. This is the smallest boundary that leaves one identity and one audit actor per call.

Downstream rules

  • The Applications data dictionary defines application_id as a third-party software caller id and auth_client_id as the client used for the request.
  • The People & Orgs app_credential object is excluded from Applications endpoints and schema; Applications auth_client is excluded from People & Orgs person APIs.
  • Shared auth, tenant routing, idempotency, and audit schemas are referenced as Platform-owned prerequisites, never copied.
  • Every domain write attributed to an application retains its domain owner and uses the Applications actor reference only as provenance.

Trace

  • Applications module-placement table
  • alpha.publisher
  • alpha.application
  • alpha.application_tenant_grant
  • alpha.auth_client
  • Platform audit-log application_id/auth_client_id actor stamp
  • surface-QC ownership collision check
#appitd-001-extend-only-object-model

Applications is an extend only Alpha registry with references to canonical owners

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

An app builder needs four plain objects that can be read without understanding 1EdTech, while an operator must prove the module did not create a second roster, tenant store, secret store, or copy of domain data.

Context

No 1EdTech object represents a third-party application calling the Alpha surface, so rename/cut/restrict views and an alias map would be fictional. Applications is a legitimate Alpha extend under the Brainlift storage carve-out.

Decision

Applications stores exactly four authoritative Alpha extension object families: publisher, application, application_tenant_grant, and auth_client. Publisher may carry an optional foreign-key reference to a canonical People & Orgs organization when the publisher is also a known organization; application_tenant_grant references a Platform tenant; auth_client references one application. Referenced owner fields are read through their owners and never copied into Applications. This module publishes no 1EdTech alias map.

Alternatives and tradeoffs

  • Model Applications as Alpha views over OneRoster users, orgs, and metadata — Benefit: Uses the usual Alpha rename path with no new tables. — Cost: There is no source object with application lifecycle, tenant grants, caller clients, or request attribution; the view would invent semantics and overload roster identities.
  • Store tenant, publisher organization, and domain snapshots beside each application — Benefit: Makes each application row self-contained and cheap to render. — Cost: Creates mutable copies of canonical facts, stale authorization context, and cross-module collisions in the shared database.
  • Put scopes, clients, publishers, and tenant access in one JSON application row — Benefit: Minimizes table count and initial migrations. — Cost: Hides governed value spaces, weakens foreign keys and uniqueness, and makes rotation/concurrency/audit changes rewrite unrelated state.

Why this is simplest

Four normalized extension objects match the four independent lifecycles: publisher ownership, application governance, tenant authorization, and credential rotation. Foreign keys preserve one canonical owner everywhere else.

Rationale and consequences

Applications has no 1EdTech base. Four normalized Alpha extension objects plus owner references are the smallest typed model that does not duplicate another module's facts.

Downstream rules

  • The data dictionary defines every field and allowed value on the four object families before implementation writes them.
  • Schema migrations create only alpha.publisher, alpha.application, alpha.application_tenant_grant, and alpha.auth_client plus read views derived from those owned rows.
  • Cross-owner links are foreign keys or stable references; copied canonical fields fail module-placement QC.
  • Generated docs state 'Alpha extend; no 1EdTech source' instead of fabricating alias provenance.

Trace

  • Applications data-dictionary object inventory
  • Applications storage migration
  • no-alias-map assertion
  • shared-schema ownership collision probe
  • surface-QC storage gate
#appitd-002-lifecycle-and-environment-isolation

Lifecycle gates capability and sandbox is a real isolation boundary

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A student or teacher must never expose production school data merely because a developer reused a client id or an application name from a sandbox, and an operator must be able to answer exactly what each lifecycle state can do.

Context

The design seed fixes five lifecycle values but does not by itself make sandbox isolation physical. Platform tenant routing is the canonical isolation mechanism; an id prefix or boolean checked only by the application would be a second, weaker tenancy primitive.

Decision

application.lifecycle_state is the governed enum draft | sandbox | active | suspended | retired. draft is metadata-only. sandbox may use only sandbox auth clients and grants whose referenced Platform tenant is classified sandbox. active may use sandbox clients and separately provisioned production clients, but production access still requires an explicit active tenant grant. suspended denies every data call while preserving metadata and prior attribution; an authorized operator may transition it back to sandbox or active only after the corresponding environment, client, and grant checks pass again. retired is terminal, denies every call, revokes every client and grant, and preserves historical identity. A sandbox client or grant is never promoted or reused for production: production requires a distinct client and grant bound to a production tenant.

Alternatives and tradeoffs

  • Use application-id or row-id prefixes inside one shared tenant to mark sandbox data — Benefit: Avoids provisioning separate tenant boundaries and keeps demo data together. — Cost: Relies on naming convention rather than tenant isolation, so one missed filter exposes production data.
  • Promote the same sandbox client and grant into production — Benefit: Makes go-live a single state flip with no credential handoff. — Cost: A leaked development credential becomes a production credential and historical audit cannot distinguish environments.
  • Treat suspended and retired as ordinary labels without runtime effect — Benefit: Leaves access control entirely in Platform token expiry. — Cost: The application registry lies about capability and cannot immediately stop a compromised caller.

Why this is simplest

The existing Platform tenant boundary already isolates data. Applications only adds a small state machine and requires separate environment-bound clients/grants; no second sandbox mechanism is invented.

Rationale and consequences

Lifecycle is enforceable governance, and sandbox isolation delegates to the one existing tenant primitive. Separate production credentials prevent a state flip from escalating a development secret.

Downstream rules

  • The data dictionary publishes the five lifecycle values, allowed transitions, capability matrix, and terminal-retired rule.
  • The implementation rejects sandbox-client/production-tenant and production-client/sandbox-grant mismatches before any domain read or write.
  • Promotion provisions a distinct production client and tenant grant; it never mutates a sandbox credential into production.
  • Negative tests prove draft, suspended, and retired applications cannot call domain endpoints.

Trace

  • alpha.application.lifecycle_state
  • auth_client.environment
  • application_tenant_grant.environment
  • Platform tenant classification reference
  • lifecycle transition validator
  • sandbox-to-production denial probe
#appitd-003-tenant-grants-and-effective-scopes

Tenant grants are explicit and effective scopes are an intersection

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A school must be able to approve the smallest capability set for one application without granting that application the same access at every tenant or letting a broader client/token silently expand the approval.

Context

Application-declared scopes describe intended capability, but tenant authorization and client issuance have separate lifecycles. Treating any one of them as authoritative allows over-broad access or forces one global grant across schools.

Decision

application.declared_scopes is the registered maximum capability requested by the publisher. application_tenant_grant records the scopes one Platform tenant approved for one application and environment. auth_client.allowed_scopes is a subset issued to one client. A request token asks for a subset. The effective scope set is the intersection of declared scopes, the active tenant grant, the active auth client's allowed scopes, and token scopes; an absent, expired, suspended, or mismatched layer denies the request. Scope identifiers and implication rules are Platform policy values referenced by Applications, not free text or module-local aliases.

Alternatives and tradeoffs

  • Use application.declared_scopes as the authorization grant for every tenant — Benefit: One scope list is easy to explain and cache. — Cost: A publisher's request becomes approval and every school receives the same access.
  • Put all authorization in the JWT and keep no tenant grant — Benefit: Runtime validation is stateless and needs no Applications lookup. — Cost: There is no durable school approval record, revocation waits for token expiry, and a token can outlive application state.
  • Union application, grant, client, and token scopes — Benefit: Any approved layer can enable a capability and configuration is forgiving. — Cost: A broad client or token escalates beyond the tenant's approval; least privilege disappears.

Why this is simplest

A four-way set intersection is one deterministic rule that lets every owner narrow access and no owner widen another's grant. It reuses the Platform scope registry instead of creating Applications-specific spellings.

Rationale and consequences

Requested capability, school approval, client issuance, and token request are different facts. Intersecting them is the smallest fail-closed authorization rule.

Downstream rules

  • The data dictionary defines declared_scopes, granted_scopes, allowed_scopes, and token scopes as arrays of canonical Platform scope ids with subset constraints.
  • Grant uniqueness is application_id + tenant_id + environment; concurrent replacement uses the API concurrency decision.
  • Authorization fails closed when no active matching grant exists, even when a JWT signature is valid.
  • Conformance tests exercise every single-layer narrowing case and prove effective scopes equal the set intersection.

Trace

  • alpha.application.declared_scopes
  • alpha.application_tenant_grant.granted_scopes
  • alpha.auth_client.allowed_scopes
  • Platform scope registry
  • effective-scope authorization middleware
  • least-privilege matrix probe
#appitd-004-auth-clients-and-secret-boundary

Auth clients store references and rotation state; Platform brokers secret material

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

An app builder needs a client id and a safe credential handoff, while a student, school operator, log reader, or ordinary API consumer must never be able to recover either secret material or its vault locator.

Context

The design seed requires auth_client rows keyed by application and a secret_ref rather than inline secrets. Platform already owns authentication and signing mechanics; Applications must govern client identity and rotation without becoming another vault or token issuer.

Decision

Each auth_client belongs to exactly one application and one environment and stores client_id, allowed_scopes, status, secret_ref, created_at, last_rotated_at, expires_at, and revoked_at as typed metadata defined by the data dictionary. Secret material exists only in the Platform-approved vault/auth broker. On create or rotate, that broker may perform a one-time out-of-band handoff; ordinary Applications item/list responses expose client_id, environment, scopes, status, and rotation timestamps but never secret material or secret_ref. Logs, Problems, generated examples, audit metadata, and exports also redact both. Sandbox and production always use distinct clients.

Alternatives and tradeoffs

  • Store the plaintext client secret in auth_client — Benefit: Makes verification and credential recovery straightforward. — Cost: Turns the shared database and every backup/read path into a credential store and makes compromise recoverable as plaintext.
  • Return secret_ref to authorized operators as the safe public value — Benefit: Lets operators inspect and debug vault configuration. — Cost: Leaks security topology and gives ordinary clients a reusable locator that only the auth broker needs.
  • Reuse People & Orgs alpha.app_credential for caller clients — Benefit: Reuses an existing vault-reference table and redaction contract. — Cost: Keys a software caller credential to a person and external app instead of a registered Platform3 application, destroying both ownership boundaries.

Why this is simplest

Applications stores only the metadata needed to govern a client; the existing Platform auth broker owns issuance and validation, and one redaction rule covers every ordinary output.

Rationale and consequences

The business registry needs client status, scopes, and rotation evidence, not secret material. Reusing Platform's broker avoids a second security implementation.

Downstream rules

  • The data dictionary labels secret_ref internal/write-protected and excludes it from every ordinary response schema.
  • Only the Platform auth broker role may create or change secret_ref; Applications admin APIs request provisioning/rotation but do not accept plaintext secret input.
  • Every serializer, Problem mapper, logger, fixture, export, and generated example has a negative secret/secret_ref assertion.
  • Client-id uniqueness and rotation concurrency are enforced without exposing prior secret material.

Trace

  • alpha.auth_client
  • Platform auth-broker provisioning adapter
  • auth-client response schemas
  • secret redaction probe
  • credential rotation/revocation audit checks
#appitd-005-request-attribution-and-audit

Every external Alpha request has one registered application actor

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A family, school, operator, or incident responder must be able to answer which registered application and client performed any external read or write without reconstructing identity from a free-form user agent, token subject, or domain-row field.

Context

Attribution is cross-cutting request evidence, not a learning event and not a second Applications event stream. Platform already stores audit records and domain modules may store business provenance when their dictionaries require it.

Decision

Before domain handling, Platform authentication resolves the presented client to one active auth_client and application, applies lifecycle/grant/scope checks, and writes application_id and auth_client_id into the Platform-owned audit record alongside tenant, request, subject, action, outcome, and correlation identifiers. Every externally authenticated Alpha read and write requires those actor ids; internal platform jobs use their separately governed service actor type and may not impersonate an application. Applications defines and resolves the actor references but stores no duplicate access log. A domain owner may reference application_id as business provenance only when its own data dictionary declares that field and meaning.

Alternatives and tradeoffs

  • Infer the application later from user-agent, IP address, or token subject text — Benefit: Requires no schema change in the audit path. — Cost: Identity is ambiguous and mutable, shared infrastructure collapses callers, and failed requests may have no attributable domain row.
  • Write a second Applications access-event table — Benefit: Keeps app-centric history near the registry and permits custom retention. — Cost: Duplicates Platform audit evidence, can disagree on outcomes, and mistakes access for a Caliper/business event.
  • Stamp only successful domain writes — Benefit: Reduces audit volume and puts provenance on lasting rows. — Cost: Loses reads, denied attempts, failures, and operations that do not create a domain row.

Why this is simplest

Resolve one actor during the existing auth step and add two typed references to the existing audit record. This covers every outcome and leaves storage with its canonical Platform owner.

Rationale and consequences

Attribution belongs on the existing audit path and must cover all outcomes. Applications supplies identity resolution; Platform keeps the one durable audit record.

Downstream rules

  • The auth context exposes immutable application_id and auth_client_id values to Platform audit and authorized domain provenance adapters.
  • Audit completeness tests cover successful reads, successful writes, validation errors, authorization denials, idempotent replays, and server failures.
  • No Applications migration or endpoint creates a second request-log or Caliper event table.
  • Domain schemas may not add application provenance by convention; their owning dictionaries must trace it explicitly to this actor contract.

Trace

  • Platform auth context
  • Platform audit-log actor fields
  • Applications actor resolver
  • audit completeness matrix
  • module-placement event-vs-audit check
#appitd-006-publisher-org-and-tenant-separation

Publisher, organization, tenant, application, and human stay separate

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A school and an app vendor must each retain their own identity even when one company publishes many apps, one app serves many tenants, or an internal team is both a known organization and a publisher.

Context

People & Orgs organizations describe roster places and legal/school groupings; Platform tenants are isolation boundaries; publishers are parties accountable for applications. These can relate, but none is a safe identifier for the others.

Decision

publisher is an Applications-owned governance party with a stable publisher_id, governed status, public governance display_name, and optional people_org_ref when the same party has a canonical People & Orgs organization. display_name names the publisher in app governance and is not asserted to copy or mirror the linked organization's canonical name. application belongs to one publisher and has its own stable application_id. Tenant access exists only through application_tenant_grant referencing a Platform tenant. Publisher and application rows never imply tenant access, and an organization or tenant link never creates an application or grant. Human operator identities remain People & Orgs/Platform admin subjects referenced by audit, not publisher or application rows.

Alternatives and tradeoffs

  • Use a People & Orgs org id as publisher_id — Benefit: Eliminates a publisher table for known vendors and internal teams. — Cost: Excludes publishers outside the school roster model and makes app-governance status mutate a roster object.
  • Use tenant_id as publisher_id and application owner — Benefit: Makes tenant isolation and ownership the same relationship. — Cost: Cannot model one vendor across tenants, makes a customer the publisher of vendor software, and grants access by identity.
  • Treat the human registrar as the publisher/application identity — Benefit: Every app has an accountable person with no separate party registry. — Cost: Access and ownership break when staff change, and software calls become indistinguishable from human actions.

Why this is simplest

Five small identities each answer one question: who published it, which app is it, which data boundary is requested, which software client called, and which human administered it. Optional references connect them without equivalence.

Rationale and consequences

Identity, ownership, isolation, software authentication, and human administration change independently. References preserve relationships without collapsing owners.

Downstream rules

  • The data dictionary states the non-equivalence of publisher_id, people_org_ref, tenant_id, application_id, auth_client_id, and human subject id.
  • Foreign-key display expansions are read-time joins to owner APIs/views and are not persisted copies.
  • Registration and tenant-grant endpoints are separate writes with separate authorization.
  • Module-placement QC rejects a publisher modeled as an org alias, an app modeled as a user, or a grant inferred from ownership.

Trace

  • alpha.publisher
  • alpha.application.publisher_id
  • alpha.publisher.people_org_ref
  • alpha.application_tenant_grant.tenant_id
  • registration/grant endpoint separation
  • identity non-equivalence QC
#appitd-007-revocation-retirement-and-retention

Revocation removes capability without erasing attribution

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A school must be able to stop a compromised or departed application immediately while a family, auditor, or incident responder can still resolve the application behind historical reads and writes.

Context

Hard deletion makes old audit references meaningless, while merely labeling an application retired can leave working clients and grants. Vault retention and Platform audit retention have separate owners from Applications registry retention.

Decision

Applications has no public hard-delete for publishers, applications, tenant grants, or auth clients once referenced. Revocation sets typed status/timestamps and is effective immediately in authorization. Retirement is terminal, revokes all clients and grants transactionally, asks the Platform auth broker to destroy or disable usable secret material under Platform secret-retention policy, and retains non-secret registry metadata for as long as Platform audit records may reference it. Platform owns audit retention; Applications owns resolvable actor metadata. A mistaken registration with no clients, grants, or audit references may be voided only through an audited operator repair defined by the data dictionary, never ordinary DELETE.

Alternatives and tradeoffs

  • Hard-delete an application and cascade its clients and grants — Benefit: Minimizes retained metadata and gives a familiar delete operation. — Cost: Breaks historical audit references and can hide which caller accessed student data.
  • Retain all clients and secrets after retirement for possible restoration — Benefit: Makes accidental retirement reversible and preserves forensic material. — Cost: Leaves usable credentials for a caller the registry says is terminally retired.
  • Let token expiry eventually enforce revocation — Benefit: Avoids an authorization lookup or revocation cache invalidation. — Cost: A compromised client remains active until expiry and lifecycle state is not authoritative.

Why this is simplest

Status and timestamps disable capability immediately while stable non-secret ids keep one audit story. Secret material and audit records stay with their existing Platform owners.

Rationale and consequences

Capability and evidence have opposite deletion needs. Immediate revocation plus durable non-secret identity satisfies both without a second audit or vault policy.

Downstream rules

  • DELETE is absent from ordinary Applications endpoint catalogs for referenced registry objects.
  • Retirement performs one atomic capability shutdown across application, clients, and grants and emits a Platform audit record.
  • Authorization checks current revocation/lifecycle state even when a presented token has not expired.
  • Retention documentation separates Applications actor-metadata retention, Platform audit retention, and Platform vault secret destruction.

Trace

  • application retirement transaction
  • auth-client and tenant-grant revocation fields
  • Platform auth-broker destruction request
  • Platform audit retention reference
  • no-public-delete endpoint assertion
  • post-retirement denial probe
#appitd-008-source-registration-and-reconciliation

Registration is authoritative; legacy caller ids are evidence, not identities

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A migration operator must preserve the real caller behind historical client_app_id/application_id evidence without inventing a publisher or granting access from an opaque string found on a domain row.

Context

Production source-shaped records already carry caller-like identifiers in several systems, but those fields are attribution evidence, not a governed application registry. Treating every observed string as a registered application would authorize typos, test clients, and retired systems.

Decision

New identity originates only in an audited Applications registration or a named server-side migration adapter over an authoritative legacy auth/client registry documented by the Applications data dictionary. Domain-row client_app_id/application_id values and access logs may reconcile to a registered application/client by an explicit source-key mapping, but they never mint publishers, applications, grants, or credentials. Unknown, duplicate, or conflicting source ids produce typed reconciliation errors for operator resolution. The caller submits source-shaped records; Applications performs mapping server-side and retains source system, source key, import id, and decision provenance without copying domain payloads.

Alternatives and tradeoffs

  • Auto-register every distinct client_app_id observed on a domain row — Benefit: Produces complete apparent coverage with no operator mapping work. — Cost: Turns ungoverned strings, test ids, and typos into trusted software identities and cannot recover publisher, scopes, or credentials.
  • Require the migration caller to normalize and deduplicate applications before import — Benefit: Keeps the Applications API small and moves messy source logic out of Platform3. — Cost: Leaks platform-owned identity rules into every migration/skill and makes provenance irreproducible.
  • Discard historical caller ids that do not match a newly registered client — Benefit: Keeps the registry clean and avoids unresolved rows. — Cost: Silently destroys attribution evidence and prevents closed-loop reconciliation.

Why this is simplest

One governed registration path and one server-side adapter preserve authority. Everything else is a mapping or a loud reconciliation error, so no heuristic becomes identity.

Rationale and consequences

Observed ids prove that a source emitted a value; they do not prove application identity or authorization. Server-side registration/mapping preserves both source fidelity and governance.

Downstream rules

  • The data dictionary names each accepted source registry/table and exact source-key mapping before an adapter ships.
  • Bulk import accepts source-shaped records, is idempotent by source system + source key + import id, and returns typed per-row outcomes.
  • Unknown/duplicate/conflicting identities are non-2xx adapter/reconciliation Problems, never successful empty imports.
  • The skill pack contains no client-id parser, dedup table, publisher guess, or scope inference.

Trace

  • Applications source-adapter inventory
  • application source-key mapping
  • source import provenance
  • typed reconciliation Problems
  • migration closed-loop actor-count reconciliation
  • skill-pack leak check
#appitd-100-api-contract-axes

All twelve Applications API axes are pinned

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A cold app-builder LLM and a security reviewer need one predictable Alpha REST contract; neither can safely fill concurrency, pagination, authorization, error, or privacy gaps with local conventions.

Context

The Brainlift requires every architecture to pin 12 recurring API decisions. Applications inherits Platform mechanics where possible, but still must say how those mechanics apply to registry and authorization resources.

Decision

Applications ships the twelve-axis contract below. Every SHIP behavior is generated into the data dictionary and endpoint catalog. A DEFER is allowed only where the axis entry names a concrete re-open trigger; deferred behavior is absent rather than partially implemented.

Alternatives and tradeoffs

  • Let the implementation choose each API behavior when it reaches the endpoint — Benefit: Avoids premature design and lets code follow framework defaults. — Cost: Creates untraceable semantics, inconsistent security behavior, and a data dictionary that merely documents accidental code.
  • Invent Applications-specific envelopes, pagination, tokens, audit, and idempotency — Benefit: Optimizes the registry API without inherited constraints. — Cost: Creates a second Platform contract and makes a cold app builder learn unique mechanics for one module.
  • Ship only registration CRUD and defer security/conformance axes — Benefit: Delivers visible registry functionality sooner. — Cost: The first production caller would define authorization, isolation, errors, and evidence ad hoc.

Why this is simplest

Eleven axes reuse one Platform convention; Applications adds only its lifecycle, grant, scope, client, and attribution predicates. One structured table makes every inherited and module-specific decision visible.

Rationale and consequences

Pinning all axes once prevents downstream code from becoming an accidental source of business/security behavior and maximizes reuse of Platform mechanics.

Downstream rules

  • The data dictionary and customer website render all twelve axes with their disposition and exact contract.
  • The implementation endpoint catalog maps every route to the applicable axis behavior and inherited Platform primitive.
  • Surface QC fails on a missing axis, an undocumented divergence, or a DEFER without its named trigger.
  • The skill pack teaches one Alpha REST convention and contains no Applications-only retry, pagination, auth, or error adapter.

Trace

  • Applications API-axis table
  • Applications endpoint catalog
  • Platform convention references
  • HTTP contract tests
  • deployed conformance smoke
  • skill-pack leak check
#appitd-101-conformance-and-customer-pass

The customer pass is a denied crossing and complete attribution proof

AcceptedOwner: TimeBack Platform ArchitectureDate: 2026-07-16

Audience constraint

A school cannot accept an application registry because its happy-path CRUD works; it needs proof that wrong-state, wrong-client, wrong-scope, wrong-tenant, and secret-recovery attempts fail before student data moves, while every allowed/denied call remains attributable.

Context

Security boundaries often pass their own positive examples while one missing predicate permits cross-tenant or over-scope access. The architecture eval requires objective negative evidence and a real consumer path rather than an implementation-authored expected-value loop.

Decision

Applications passes only when an independent harness registers one publisher and application, provisions separate sandbox and production clients/grants, and proves: sandbox credentials cannot reach production; no client can exceed the four-way effective-scope intersection; draft/suspended/retired calls fail closed; ordinary reads/logs/Problems contain neither secret nor secret_ref; every allowed and denied external read/write has the same application_id/auth_client_id in Platform audit; tenant A cannot enumerate tenant B grants/clients; ETag/idempotency/error contracts hold; and source reconciliation refuses unknown ids. The integration consumer then onboards with the Alpha docs alone and completes one sandbox read and one explicitly granted production read without direct DB, service-role, local scope logic, or client-id guessing.

Alternatives and tradeoffs

  • Accept green CRUD tests and code review as the architecture proof — Benefit: Runs quickly without security fixtures or deployed tenants. — Cost: Does not exercise tenant crossings, stale credentials, scope escalation, redaction, or real audit evidence.
  • Use only service-role deployed smoke — Benefit: Avoids provisioning reviewer clients and grants and reduces auth flakiness. — Cost: Bypasses exactly the application lifecycle, grant, scope, and tenant boundary the module exists to enforce.
  • Let the implementation generate both expected and observed conformance answers — Benefit: Keeps tests near code and simplifies fixtures. — Cost: A shared wrong assumption produces a self-consistent false green.

Why this is simplest

One small two-environment/two-tenant matrix exercises every load-bearing predicate and a real onboarding path. It reuses Platform audit and auth evidence instead of inventing a security score.

Rationale and consequences

The customer risk is an unauthorized crossing or untraceable call, not a failed registry form. The pass test directly proves those boundaries with non-service-role identities.

Downstream rules

  • Surface QC publishes every named positive/negative cell, its request identity, expected status, observed status, audit correlation, and re-run command.
  • Deployed smoke uses ordinary application/admin credentials and canonical tenant routing, never service role for the customer path.
  • Integration stores no domain data and does not implement scope intersection, sandbox filtering, secret redaction, or client-id mapping.
  • The architecture-anchor probe proves every appitd anchor on the unauthenticated canonical page after publication.

Trace

  • Applications conformance matrix
  • Applications deployed smoke
  • Platform audit readback
  • Applications integration onboarding app
  • Applications skill-pack leak check
  • architecture-anchor-probe.mjs --module applications --surface alpha