Skip to main content

Release 1 architecture baseline and decisions

This explanation gives the Enterprise Architecture Board a fundamentals-first view of AeroSim Release 1. It complements the C1 System Context, C2 Container view, per-container C3 Component views, the item-level Board report, and the delivery-readiness architecture and handover chain.

Architecture status​

Verdict: conditionally accepted Architecture boundary; not release approval. The Architecture owner accepted ADR-0001 and ADR-0002 and conditionally accepted KDD-R1-01 through KDD-R1-03. KDD-R1-04 and KDD-R1-05 were returned, and KDD-R1-06 remains open. Separately, 33 of 34 Release 1 Features remain Proposed. This page does not approve Scope, residual operational risk, implementation admission, release, promotion, UAT, or product acceptance.

Evidence layerEvidence referenceMeaning
Canonical documentationc4db84b8f888acddfc0b05c30eb4ac0467d0bd14Scope, requirements, ADRs, Tasks, C4 views, and lifecycle records reviewed by this baseline
Integrated application source7e7d557291c9b15a8b97e8ef587e3faa91c5bf03Current application default used to verify implemented structure
Development deploymentsource 7e7d557291c9b15a8b97e8ef587e3faa91c5bf03; GitOps fb5469900a93a607c2767342912d9b95cd09bc98Synced/Healthy development tuple recorded by the Board packet evidence snapshot
Production deploymentsource dbba4a186a02cb4567c64f1c3400d38556aa1a25; GitOps 5a440bbe62b4d284b8b8ce81c2afeb79a974f762Synced/Healthy production tuple recorded by the Board packet evidence snapshot
Board packet evidence basePR #369 source head 69bf11a18c870684ffe6ac0ca2a6c42dafef4842Starting packet for this revision; reviewers must freeze the current PR head because this row is not the candidate's self-identity

The development and production deployment tuples differ. Evidence from one tuple cannot prove another. Any source, image, chart, GitOps revision, environment or required journey change invalidates prior candidate UAT evidence. A rendered-template change also invalidates the tuple.

Release 1 outcome and boundary​

Release 1 is intended to provide one authenticated browser-based free-flight product slice:

  1. a governed engineering, build, artifact, and deployment foundation;
  2. Keycloak sign-in, pilot identity linkage, preferences, progress, and resumable activity;
  3. believable and repeatable aircraft/world behaviour;
  4. deliberate aircraft, world, conditions, controls, and camera configuration;
  5. a complete launch, fly, pause, recover, finish, abort, retry, and restart loop; and
  6. a controlled, traceable, and reversible release path.

Release 1 does not establish guided-training progression, advanced post-flight analysis, or later-release geometry/CI improvements merely because related proposed requirements exist in the repository. The release allocation remains the authority for membership.

Owned system boundary​

Owned elementResponsibilityExplicitly not owned
Web ApplicationBrowser session, pre-flight, world bootstrap, deterministic fixed-step simulation, rendering, controls, recovery, outcomes, and API clientsIdentity-provider administration, public TLS termination, Kubernetes orchestration
API ServiceToken validation, pilot-owned HTTP persistence, health endpoints, and an authenticated fail-closed Socket.IO scaffoldBrowser physics, browser-bundled catalogues, direct public certificate lifecycle
Pilot Data StoreDurable pilot linkage, camera preference, resumable progress, outcomes, and attempt fields within progress recordsCredentials, identity-provider records, direct browser access
Documentation SiteGoverned product, architecture, delivery, and engineering evidenceRuntime availability of the flight product

Keycloak, Gitea, Harbor, Osgiliath, Kubernetes, Argo CD/GitOps, External Secrets, and Project Pages are external platform dependencies. They remain outside the AeroSim product boundary even when AeroSim depends on their contracts.

Architecture drivers​

DriverRequired system responseCurrent evidenceDecision state
Pilot isolationEvery protected read, write, and live connection resolves to one authenticated Keycloak subject; cross-pilot access is deniedAPI identity guard, Prisma ownership checks, isolation testsImplemented; lifecycle and fine-grained authorization policy not approved
Deterministic flightEquivalent governed initial state and timed input produce bounded-equivalent authoritative state; rendering cannot become a second authorityBrowser-local 60 Hz fixed step and deterministic testsADR-0001 accepted with explicit residual conditions
Configuration integrityLaunch uses one complete, revision-bound aircraft/world/conditions/controls/camera tuple and rejects stale or mismatched referencesPre-flight and launch validation, catalogue and session testsADR-0002 accepted with release-coupled catalogue conditions
Persistence integrityA terminal attempt is not presented as saved until transactional persistence succeedsAPI/Prisma transaction and failure tests; debrief/progress withholdingImplemented; retention, deletion, recovery and audit policy not approved
Supply-chain integritySource, images, chart, rendered templates, GitOps and release evidence bind to immutable identitiesExact-head CI, digests, chart/template provenance, GitOps selectionImplemented controls; one releasable tuple and promotion decision still open
SecurityNo local passwords, browser administrative secrets, direct database access, or unvalidated protected requestsAuthorization Code with PKCE, JWT/JWKS validation, External Secrets, network policy testsImplemented controls; session lifecycle, rotation and incident policy not approved
ReliabilityInvalid configuration, world, asset, frame, persistence and deployment states fail closed with an owned recovery pathTyped diagnostics, readiness/liveness, rollback and mismatch checksPartial; SLO, RTO, RPO, restore and capacity decisions not approved
OperabilityOperators can detect, diagnose, contain, restore and prove one exact candidateHealth endpoints, CI/GitOps evidence and rollback recordsPartial; production observability and recovery objectives remain open

End-to-end system flows​

Sign-in and session​

  1. The browser starts OIDC/OAuth 2.0 Authorization Code with PKCE against Keycloak.
  2. The Web Application holds the application session and sends the access token to protected AeroSim HTTP boundaries. The exposed Socket.IO route authenticates tokens but has no active Web client in the Release 1 flight path.
  3. The API validates issuer, audience, signature, expiry, and claims through Keycloak JWKS before attaching the subject context.
  4. Invalid, expired, wrong-issuer, or absent credentials fail closed. Health endpoints remain outside the pilot identity guard and disclose no pilot data.

Pre-flight and launch​

  1. The API returns the authenticated pilot profile and preferences; governed aircraft, world, and condition catalogues are compiled into the Web Application.
  2. The pilot selects aircraft, world, conditions, controls, and camera.
  3. The Web Application binds the selection to the active application/catalogue revision and rejects missing, disabled, stale, or incompatible references.
  4. World bootstrap validates terrain, physics profile, assets, collision/world-space contracts, and camera anchors before exposing a ready session.

Flight and outcome​

  1. Input is converted into bounded typed control state.
  2. One browser-local, fixed-step flight authority advances forces, wind, collision, boundaries, recovery, and attempt state.
  3. Rendering and presentation consume the authoritative frame; they do not mutate authoritative simulation state.
  4. Completion, failure, and abort retain one attempt identity and explicit terminal semantics; retry follows the governed retry contract, while a deliberate restart creates a new provenance-linked attempt identity.
  5. Persistence failure retains terminal attempt identity but withholds a saved debrief and progress checkpoint until the write succeeds.

Delivery and runtime​

  1. Gitea Actions validates exact source and publishes immutable Web/API images and a versioned chart to Harbor.
  2. The GitOps repository selects exact image/chart identities and supplies environment-specific configuration.
  3. Argo CD reconciles the declared state into Kubernetes.
  4. Osgiliath terminates public TLS and forwards trusted HTTP to Kubernetes Ingress.
  5. Ingress routes HTTP / to the Web Application and HTTP /api and /socket.io with WebSocket upgrade to the API Service.
  6. Runtime acceptance and UAT must bind to one frozen source/image/chart/template/GitOps/environment tuple.

Data ownership and lifecycle​

Data classAuthoritative owner/storeAccess ruleIntegrity/failure ruleGovernance state
Keycloak identityIdentity platformAeroSim receives subject/claims only; no local passwordInvalid identity fails before protected processingJoiner/mover/leaver, MFA, recovery and privileged administration not approved
Pilot linkage/profileAPI Service / PostgreSQLSame authenticated subject onlyUnique linkage and transactional updatesClassification, retention, export and deletion not approved
PreferencesAPI Service / PostgreSQLSame authenticated subject; supported values onlyInvalid values rejected; last valid value restoredRetention and deletion not approved
Resumable progressAPI Service / PostgreSQLSame authenticated subjectOnly actually resumable activity is exposedInvalidation exists; retention and deletion not approved
Attempt data and outcomeAPI Service / PostgreSQL progress recordsSame authenticated subjectAttempt/configuration lineage retained; failed writes are not presented as savedRetention, deletion and audit policy not approved
Operational logs/CI evidenceDelivery and Operations systemsOperational identities onlyMust not contain secrets or unnecessary pilot dataRetention, disposal and audit access not approved

The browser never receives database credentials and never connects directly to PostgreSQL. Only the API's Prisma adapter may access the Pilot Data Store.

Integration contracts and failure semantics​

BoundaryContractOrdering/idempotencyFail-closed behaviour
Browser ↔ KeycloakOIDC/OAuth 2.0 Authorization Code with PKCEOne intended-route restoration after a valid sessionReject invalid state, nonce, issuer, audience, signature, expiry or callback
Browser ↔ API HTTPHTTPS/JSON through public proxy; internal route is HTTP /apiWrites use validated identity and record semantics; repeated profile resolution is idempotentValidation, identity, ownership, persistence and conflict errors remain distinct
Ingress ↔ API socket scaffoldHTTP/WebSocket upgrade through /socket.io; no active Web clientHandshake authenticates and typed payloads validate, but production injects no flight-command forwarderReject unauthenticated/invalid payloads and return COMMAND_FORWARDER_UNAVAILABLE for valid flight commands
API ↔ PostgreSQLPrisma over PostgreSQL inside the namespace NetworkPolicy boundaryTransactional pilot-owned writes and reproducible migrationsRoll back failed transactions; no partial saved outcome/progress claim; transport encryption is not assumed
GitOps ↔ runtimeImmutable image/chart/template/GitOps tupleReconciliation is declarative; candidate identity must match reviewed evidenceReject mutable tags, missing digests, mismatched tuple, or absent approval
Osgiliath ↔ IngressTrusted internal HTTP after public TLS terminationReverse-proxy and WebSocket upgrade preserve route intentADR-0004 records the accepted boundary; residual internal-hop risk remains visible

Security and trust model​

Trust zones​

Pilot browser
→ public HTTPS/WSS and Osgiliath TLS boundary
→ Kubernetes Ingress
→ Web Application / API Service namespace
→ Pilot Data Store

Keycloak → external identity trust
Gitea / Harbor / GitOps / External Secrets → delivery and workload-supply trust

Required controls​

  • Keycloak is the only user-authentication path; AeroSim has no registration, password store, or local sign-in fallback.
  • Protected HTTP and Socket.IO operations require a validated identity and subject-scoped authorization.
  • The API is the only application path to PostgreSQL.
  • Secret values arrive through the platform's External Secrets contract and are not stored in browser code, Git, Helm values, logs, or architecture artifacts.
  • Runtime artifacts use immutable digests; chart/template/GitOps identities are part of the candidate evidence.
  • Public TLS terminates at Osgiliath under accepted ADR-0004; the internal HTTP hop remains a consciously visible trust-boundary risk.
  • The reviewed PostgreSQL StatefulSet and application selection establish NetworkPolicy-restricted access but do not establish database TLS; the Board must require encryption or explicitly accept and bound the internal transport risk.
  • Asset intake must preserve provenance, licensing, validation, and runtime-budget evidence.

The current model does not yet define approved token/session lifetimes, revocation/logout, signing-key rollover, secrets rotation, compromise response, rate limits, abuse controls, data classification, privacy retention, or auditable security-event requirements.

Reliability and operability​

ConcernExisting mechanismRequired measurable closure
Liveness/readinessWeb and API health endpoints; probes bypass pilot auth and expose no pilot dataDefine detection time, alert owner, dependency criteria, and false-positive budget
Simulation stabilityFixed 60 Hz step, bounded catch-up, finite-state guards, typed diagnosticsApprove supported browser/device envelope and quantitative frame/step budgets
World/asset failureInitialization cancellation, resource disposal, manifest/world-space validationDefine retryability, user recovery, telemetry and incident threshold per failure class
Persistence failureTransaction rollback and withheld saved stateApprove retry/idempotency policy, operator alerting, data-loss objective and reconciliation process
Database recoveryDurable PostgreSQL and reproducible Prisma migrationsApprove backup cadence, encryption, retention, restore test, RTO and RPO; no recovery claim before evidence
Deployment rollbackImmutable candidate identities, GitOps history and rollback evidenceApprove rollback trigger, authority, maximum restoration time and post-rollback verification
CapacityBrowser/runtime resource checks and Kubernetes resource configurationDefine supported concurrency, namespace limits, saturation indicators and load-test evidence
ObservabilityHealth checks, CI evidence and typed application diagnosticsDefine logs, metrics, traces, correlation IDs, dashboards, alerts, retention and personal-data handling
Environment freshnessExact tuple and evidence-invalidation ruleFreeze one tuple, rerun all required journeys, prohibit evidence mixing, and publish durable UAT_PASSED

RTO and RPO are deliberately not invented here: they are not approved. The Board must select objectives before Architecture can claim a recoverable service.

Architecture decision register​

DecisionRecommendationStatus and authority neededAcceptance evidence
KDD-R1-01 — Flight authorityBrowser-local deterministic fixed-step flight authority; API and public Socket.IO scaffold are not physics authoritiesAccepted with conditions by Architecture owner; ADR-0001 acceptedPreserve 60 Hz fixed step, five-step bounded catch-up, invalid-state fail-closed behavior, deterministic tests and supported-device envelope; no server-authoritative anti-tamper claim
KDD-R1-02 — Configuration authorityStatic browser-bundled governed catalogues plus source-revision-bound immutable launch snapshotsAccepted with conditions by Architecture owner; ADR-0002 acceptedReject or reconfirm stale/disabled/unknown changes; catalogue changes require a new build/release and invalidate prior confirmation; dynamic catalogues remain deferred
KDD-R1-03 — Identity/session boundaryKeycloak Authorization Code with PKCE, API JWT/JWKS validation and subject-scoped pilot authorizationConditionally accepted by Architecture owner; closure conditions remain openRecord and verify lifetime, refresh, logout/revocation, rollover, admission/deprovisioning, and Socket.IO origin/token-age/quota/payload policy
KDD-R1-04 — Data lifecycle and recoveryAPI-owned pilot persistence is established, but lifecycle and recovery policy are incompleteReturned — not decision-readyProduct/Data/Security policy, least-privilege roles, retention, deletion/export, backup/restore, RTO/RPO and PostgreSQL TLS decision required
KDD-R1-05 — Operability and service objectivesObjective categories are established; numeric targets and evidence are absentReturned — not decision-readyOperations-owned SLO, capacity, observability, recovery and incident objectives plus validation evidence required
KDD-R1-06 — Release evidence boundaryOne immutable tuple, authenticated journeys, promotion authority, runtime verification and post-release acceptance remain mandatoryArchitecture concurrence; open for UAT, Releases and RootAtSkicExact tuple manifest, durable UAT_PASSED, promotion event, dependency-aware readiness, Argo/runtime readback, rollback and acceptance events

ADR-0004 already accepts public TLS termination at Osgiliath, optional in-cluster chart TLS, and HTTP for the trusted Osgiliath-to-Ingress hop. Any change to that boundary requires a superseding ADR.

The Architecture owner recorded these dispositions on 2026-09-25 against merged evidence baseline 0faea543943f893601fdc90c9a64f0b566cd0d80. The attributable decision is Discord message 1552955532271296534. The decision does not approve Scope, implementation, UAT, promotion, release, residual operational risk, or human product acceptance.

Risks and required closure evidence​

RiskWhy it mattersRequired owner action
R-SEC-03 — Data lifecycle absentPersonal pilot/profile/progress/outcome data has no approved classification, retention, deletion/export or legal/operational ownershipProduct data owner and Security define policy; Architecture binds it to stores, APIs and evidence
R-SEC-04 — Recovery unprovenDatabase durability is not the same as a verified restore; service recovery cannot be claimedOperations/Data owner approve backup, restore, RTO/RPO and produce restore evidence
R-SEC-05 — Secrets lifecycle incompleteExternal Secrets prevents repository storage but does not define rotation or compromise responseGondor platform and Security record rotation cadence, emergency revocation and proof
R-SEC-06 — Database transport encryption unprovenThe reviewed PostgreSQL manifests and connection selection do not establish TLS for the API-to-database hopSecurity, Operations and Architecture enable verified PostgreSQL TLS or explicitly accept the bounded namespace risk with conditions
R-SEC-07 — Database runtime privilege is too broadThe same PostgreSQL owner/bootstrap credential is used to initialize the database and serve ordinary API requestsCreate separate owner, migration, and least-privilege runtime roles; rotate the shared credential and prove negative access boundaries
R-SEC-08 — Identity admission policy undefinedAny audience-valid Keycloak subject can provision a pilot because roles, groups, scopes, and deprovisioning are not part of authorizationDecide whether every realm user is admitted or enforce an explicit entitlement claim and lifecycle policy
R-SEC-09 — Socket scaffold lacks abuse boundsThe exposed route authenticates only at handshake and has no approved origin, token-age, connection, event-rate, queue, or payload policyEither remove the inactive public surface or define and verify expiry, origin, quota, backpressure, payload, timeout, and audit controls
R-ARC-01 — Flight-authority residualsADR-0001 accepts browser-local authority; client variance, tampering, replay provenance and unsupported-device behaviour remain bounded residualsPreserve the accepted KDD-R1-01 conditions; require a superseding decision for server-authoritative or competitive behaviour
R-ARC-02 — Configuration-authority residualsADR-0002 accepts static browser-bundled catalogues; updates remain release-coupled and dynamic authority is deferredPreserve the accepted KDD-R1-02 conditions; require a superseding decision for dynamic catalogues
R-REL-02 — Environment evidence divergedDevelopment/integrated source and production use different immutable tuples; prior UAT cannot prove either new candidateUAT/Releases classify the delta, freeze one tuple, rerun required journeys and forbid mixed evidence
R-REL-03 — Release health checks can miss database failureRelease verification uses unconditional /api/health while dependency-aware /health/ready returns failure when PostgreSQL is unavailableMake dependency-aware readiness a release gate and prove database loss removes the API from service and blocks UAT
R-REL-04 — Single failure domainWeb, API, PostgreSQL, and NFS-backed storage each use one active instance/path with no accepted availability objectiveSet the availability target, add required redundancy or explicitly accept downtime, and test node/pod/database/storage failures
R-OBS-01 — No production observability contractHealth, logs, CI and Argo evidence exist, but metrics, traces, correlation, alerts, retention, responders, and incident objectives are not approvedDefine SLIs/SLOs, telemetry and audit fields, dashboards, alerts, owners, retention, redaction, MTTD, acknowledgement, and game-day evidence
R-SUP-01 — Chart digest is not deployment enforcementArgo CD selects the chart by mutable version while a digest annotation/policy records but does not cryptographically bind the fetched chartEnforce registry immutability plus digest readback or a digest-bound/signed chart and verify it before reconciliation
R-GOV-01 — Lifecycle authority contradiction33 Proposed Features have extensive completed Task evidence, which can be mistaken for authorized architecture or accepted product scopeScope and Architecture issue exact item decisions or conservatively reconcile unauthorized work

Board completion rule​

The architecture becomes decision-ready only when each decision above has an exact disposition, owner, conditions, date, evidence, and affected artifacts; every blocking risk has closure or explicit residual-risk acceptance; C4, ADR, requirement, runtime and deployment records agree; and release evidence binds to one immutable tuple. A green build, packet-completeness PASS, implementation, deployment health, or silence is not a substitute for those decisions.