System Architecture
AHRI TRE is a governance-aware, provenance-first research environment. A Deployment’s Trusted runtime owns live datastore capabilities, authentication, Secret resolution, governed workflows, and content admission. User-side clients and the Web control plane reach those capabilities through authenticated interfaces.
The datastore combines two stores:
- PostgreSQL holds metadata, governance, access control, provenance, and domain records, as well as the DuckLake catalog.
- DuckDB and DuckLake manage analytical data in configured Lake storage, with
Arrow
RecordBatchas the in-memory tabular boundary, Parquet for persisted datasets, and Arrow IPC for tabular transfer.
Cross-store work uses explicit admission and compensating cleanup. A PostgreSQL transaction cannot atomically commit Lake files and metadata together.
This chapter describes the implemented runtime and Client parity architecture. The parity completion audit records the qualified CLI/C and Browser artifacts. The final section separates the broader Governed-compute design from those delivered capabilities.
Architecture Views
User View
Researchers, custodians, and automation use authenticated Sessions and Study context. Datastore entry, Study access, custodianship, DUO restrictions, and Asset risk classification remain distinct concerns. Discovery metadata does not grant access to protected content.
flowchart LR
user["Researcher / custodian / automation"]
browser["TRE Browser<br/>Discovery and access requests"]
client["CLI / language binding"]
session["Authenticated Trusted Session<br/>Execution profile and Current study"]
workflow["Governed application workflow"]
catalog["Catalogue and provenance<br/>Studies, Domains, Assets, semantic model"]
source["Source files / HTTPS / SQL / REDCap"]
assets["Governed Assets<br/>Datafiles and Datasets"]
disclosure["Authorized low-risk disclosure"]
destination["Explicit user-controlled copy"]
user --> browser
user --> client --> session --> workflow
browser --> catalog
source -->|authorized acquisition and ingest| workflow
workflow --> catalog
workflow --> assets
assets --> disclosure --> destination
System Integrator View
There are three separate entry paths: ordinary user Clients, the Browser’s Web control plane, and trusted operator administration. Their credentials and permissions are not interchangeable.
flowchart TB
subgraph clients["User-controlled clients"]
cli["CLI and automation"]
daemon["ahri-tred<br/>local lifecycle and Managed forwarding"]
wrappers["Python / Julia / R / other bindings"]
cabi["Stable C ABI"]
managed["Managed runtime<br/>Client Session context and HTTPS transport"]
cli --> daemon --> managed
cli -->|content and acquisition| managed
wrappers --> cabi --> managed
end
browser["TRE Browser<br/>separate TypeScript application"]
web["Web control plane<br/>OIDC, cookies, CSRF, HTTP projection"]
idp["ORCID / OIDC provider"]
operator["Trusted operator client"]
subgraph trusted["Deployment-scoped Trusted runtime"]
api["Authenticated interfaces<br/>user, Web service, local operator"]
sessions["Runtime logins and live Sessions"]
app["App-owned workflows<br/>governance, writers, disclosure"]
adapters["Metadata, Lake and source adapters"]
api --> sessions --> app --> adapters
api -->|scoped service / operator capability| app
end
pg["PostgreSQL<br/>TRE metadata and DuckLake catalog"]
lake["Lake storage<br/>Datafiles and Parquet"]
sources["External sources"]
browser --> web
web <-->|browser authentication| idp
web -->|mTLS service identity and scoped protocol| api
managed -->|Runtime credential over HTTPS| api
operator -->|protected local Unix socket| api
sessions <-->|server-owned OAuth lifecycle| idp
adapters --> pg
adapters --> lake
adapters --> sources
Web has no PostgreSQL or Lake credential, mount, direct adapter dependency, or deployed datastore route. Its readiness check authenticates to the Trusted runtime and checks capabilities. The user-side Managed runtime likewise has no TRE datastore or Lake authority. Client acquisition can access an external source using the user’s source credentials; that is separate from datastore execution. See ADR-0010 and ADR-0015.
Developer View: High-Level Layers
The four parity modules are behavioral boundaries within the existing crates. They concentrate shared decisions without requiring four new crates.
| Module | Current owner and responsibility |
|---|---|
| Client Session | ahri_tre_runtime::ClientSessionContext shares CLI/C selection, exact-reference binding, registry operations, profile preferences, and lifecycle-result interpretation. ahri_tre_session persists safe client context. |
| App-owned workflow | ahri_tre_app owns authorized selector resolution, semantic validation, governance, mutation sequencing, provenance, compensation, and safe results. |
| Trusted content-disclosure | An application workflow seam admits immutable inputs and authorization/risk snapshots; Trusted composition supplies live Session capabilities and delivers bounded content with durable evidence. |
| Parity qualification | Shared scenarios exercise installed CLI and exported C functions against real TRE services, with matching Browser companion checks and explicit artifact, configuration, and authority scope. This is a verification boundary, not a production executor. |
The decisions are ADRs 0020, 0021, 0022, and 0023.
flowchart TB
cli["CLI / local daemon"]
ffi["C ABI / language bindings"]
client["ClientSessionContext<br/>Managed transport and safe context"]
web["Web HTTP adapter<br/>service / visitor / custodian context"]
protocol["ahri_tre_protocol<br/>versioned DTOs, references, errors"]
runtime["Trusted runtime composition<br/>authenticate, retain capabilities, dispatch"]
app["ahri_tre_app<br/>workflow decisions and disclosure admission"]
domain["ahri_tre_types + ahri_tre_core<br/>records, policies, repository contracts"]
metadata["ahri_tre_pgmeta / runtime_pgmeta"]
lake["ahri_tre_lake / ahri_tre_tabular"]
sources["ahri_tre_sqlmeta / ahri_tre_redcap"]
cli --> client
ffi --> client
client -->|user protocol| runtime
web -->|service protocol| runtime
protocol -.-> client
protocol -.-> web
protocol -.-> runtime
runtime --> app
app --> domain
app --> metadata
app --> lake
app --> sources
The arrows show responsibility flow. Configuration, Secret capabilities, and runtime composition supply dependencies; workflows do not reopen configuration documents or Secret stores. The protocol crate contains serializable contracts and compatibility rules, with no workflow execution or datastore connections.
Developer View: Protocol Layer Detail
Ordinary JSON control-plane operations use protocol 2.0.0. The active Browser contract is v2 and shares canonical object references. Unsupported protocol majors fail before request-body decoding. Protocol, C ABI, library package, and content-frame versions are independent compatibility dimensions.
An ordinary CLI Session workflow follows:
CLI command
-> ProtocolRequestEnvelope
-> local daemon socket
-> shared ClientSessionContext / Managed transport
-> authenticated Trusted-runtime HTTPS interface
-> exact owner-scoped live Session
-> AppService workflow
-> safe protocol response
The daemon owns local process lifecycle and forwarding. Only daemon.version
and daemon.doctor use local public-protocol dispatch; private shutdown and
lifecycle frames remain adapter-local. Missing configuration, an unavailable
Trusted runtime, and unsupported remote operations fail without local datastore
execution. Automation uses the same trusted workflow authority, with explicit
Session and Study scope where required.
The C ABI route follows:
host-language wrapper
-> opaque C client / Session handle
-> shared ClientSessionContext / Managed transport
-> authenticated Trusted-runtime HTTPS interface
-> AppService workflow
-> result handle containing response JSON and optional content payload
CLI content/upload/acquisition adapters and C payload calls use separate bounded interfaces on the same Trusted HTTPS origin. They do not put binary content or source credentials into ordinary JSON envelopes. C handle ownership and CLI presentation remain adapter concerns. Full host-language packages live in separate repositories under ADR-0005.
Configuration, Secrets, and Authentication
ahri_tre_config owns versioned Application and Client document parsing,
validation, selection, and Effective configuration projection. Application
configuration belongs to trusted operators. A generated Client bootstrap
contains only schema version, Deployment identity, the canonical Trusted HTTPS
origin, and public CA trust. Execution profiles, datastore topology, policies,
and Secret references remain server-side.
ahri_tre_secrets owns Secret material, immutable Injected snapshots, and the
encrypted Managed-secret store. Configuration contains logical references and
declared Injected versions, never resolved material.
flowchart LR
application["Application configuration"]
config["ahri_tre_config<br/>validation and projection"]
effective["Effective configuration<br/>selected graph and fingerprint"]
bootstrap["TrustedRuntimeBootstrap<br/>immutable retained state"]
secrets["ahri_tre_secrets<br/>Injected snapshot / Managed store"]
capabilities["Resolved runtime and operation capabilities"]
clientdoc["Generated Client bootstrap<br/>Deployment, origin, public trust"]
application --> config --> effective --> bootstrap
config --> clientdoc
secrets -->|verified startup snapshots| bootstrap
bootstrap --> capabilities
secrets -->|newly authorized Managed-secret resolution| capabilities
Trusted bootstrap verifies the complete Managed store and retains Effective configuration, the Injected-secret snapshot, and startup-required Managed-secret snapshots before exposing listeners or authentication capabilities. Configuration and Injected changes require restart. A newly authorized operation may resolve its permitted Managed reference again; existing capabilities keep the material they opened. Configuration fingerprints describe non-secret configuration, not Secret values or mutable active Managed versions.
Runtime login is deployment-wide and precedes profile-specific Session opening. The Trusted runtime retains reusable upstream OAuth/OIDC artifacts as encrypted Managed secrets. Clients receive only a short-lived opaque Runtime client credential. Rotation, reauthentication, expiry, and logout preserve login-owner binding and revocation; they do not transfer a live capability to another user. A client-visible credential or reference is never a PostgreSQL credential.
| Authority | Permitted role |
|---|---|
| Runtime client credential | Authenticate one Runtime login; open and use its authorized Sessions. |
| Live Session | Retain the authenticated datastore capability, selected Execution profile, and Current study. |
| Web mTLS service identity | Invoke the explicit Browser service allowlist; it cannot become a Runtime user. |
| Browser visitor identity | Identify the requester from protected server-side Web session state. |
| Custodian Runtime credential plus matching Session | Establish the human datastore actor for custodial Browser actions, in addition to Web service authentication. |
| Protected local operator socket | Admit deployment administration independently of ordinary Runtime login. |
Web receives its own Effective service graph and authentication capabilities; it does not receive the Trusted runtime’s datastore graph or server private key. The operator handler resolves privileged dependencies inside Trusted authority. There is no user-client fallback to administration or infrastructure repair.
Version 1 uses one active Trusted runtime per Deployment. Administration uses
the fixed /run/ahri-tre/admin.sock Unix socket, protected by filesystem
permissions and kernel peer identity; a Runtime client credential cannot
authorize it. Durable Dataset coordination state is separate from disposable
trusted scratch, so replacing scratch does not erase writer ownership or
unresolved cleanup evidence.
Development tooling, Local TRE, and Integration fixtures have separate lifecycles and authority. Opening the development container starts tools only; the durable Local TRE deployment and disposable Integration services are started explicitly with separate networks, credentials, and storage. See the development environment guide.
Sessions and Public Identity
A live Session exists only while the Trusted runtime retains its capability.
The exact client reference is {deployment_id, runtime_login_id, session_id}.
A reused friendly name cannot redirect an old reference to a new Session.
Current study belongs to that live Session and is resolved and authorized by the
application; it is not an executable client-side default.
CLI invocations share safe registry state within one local user, Deployment, and Runtime login. Each constructed C client starts with an independent registry shared by its handles. List and close-all operate on the invoking registry, not every Session owned by the same human. Freeing a local C handle releases memory; explicit remote close ends the shared capability for all attached clients. A lost response never licenses transparent replay.
The client resolves an Execution profile once from an explicit choice, saved preference, or advertised configured default and sends the explicit choice to Trusted open. A failed choice does not fall back. Restart does not recreate live Sessions or their Current study. See the Client Session contract.
Public datastore object references use {datastore_id, kind, id}. Here
datastore_id is the durable Datastore UUID, not a configuration key or a
connection address. Dataset and Datafile references identify logical Assets;
an asset_version reference identifies an immutable revision. References carry
scope and type, but grant no access. Names remain convenience selectors:
ambiguous names and conflicting Study, Domain, type, or version constraints
fail explicitly. Permitted latest-version selections resolve once before
planning or admission. See
ADR-0025.
Workflow Ownership
Developer View: Application Layer Detail
ahri_tre_app owns the substantive Session and Browser use cases. Trusted
adapters authenticate callers, retain capabilities, validate transport framing,
and map requests and results. PostgreSQL adapters own statements, row decoding,
transactions, and persistence mechanics. The Lake adapter owns DuckDB,
container-visible Lake locations, trusted scratch, and physical cleanup.
The workflows cover catalogue, Study/Asset governance, semantic definitions and instances, mappings and links, dictionaries, provenance, archive-first deletion, acquisition, Dataset writers, and governed content. Semantic values and inferred dictionary content use the same disclosure rules as Dataset content; metadata read permission alone does not admit content-derived results. Browser Discovery uses its own restricted safe projections and cannot borrow analyst authority.
Study Access-request Workflow
Web validates its browser session and request-security context, then forwards
protocol intent over its authenticated service connection. Trusted validates
ready-Datastore scope and supplies narrow application ports through
ahri_tre_runtime_pgmeta:
- Discovery uses a read-only metadata authority.
- Requester submission, listing, detail, and withdrawal use a separate least-privilege access-request authority and the server-derived visitor.
- Custodial queue, approval, and rejection use the matching live custodian Session’s libpq OAuth connection and authenticated PostgreSQL actor.
For approval, the application preflights the pending request, provisions or reuses the requester’s workflow entry in that exact Datastore, then records the Study grant and approved decision through the authenticated metadata port. Trusted resolves the workflow-entry Secret at the newly authorized operation boundary. Web owns neither that Secret nor a database connection.
Workflow entry is an idempotent prerequisite, not a Study grant. If provisioning succeeds and the final decision fails, the entry remains for a safe retry; compensating deletion cannot prove that another authority does not use it. Submission and withdrawal grant neither Study access nor workflow entry.
Dataset Writers and Tracked Operations
All supported Dataset writers share durable Output reservations for the Datastore, Output study, and logical Dataset. They contend for the same target across users, Sessions, and name/reference selectors before version allocation or materialization.
flowchart LR
authorize["Resolve and authorize intent"]
reserve["Reserve logical Dataset<br/>persist attempt ownership"]
prepare["Prepare immutable sources<br/>materialize Lake output"]
admit["Atomic PostgreSQL admission<br/>metadata, provenance, latest version"]
success["Consume reservation<br/>return safe result"]
cleanup["Compensate known failed work"]
release["Release failed attempt's reservation"]
retain["Retain ownership<br/>until cleanup and executor exclusion are proven"]
authorize --> reserve --> prepare --> admit --> success
prepare -->|failure| cleanup
admit -->|known rollback| cleanup
admit -->|unknown commit outcome| retain
cleanup -->|incomplete or executor still active| retain
cleanup -->|complete and executor excluded| release
Final Dataset metadata and successful provenance commit together. Lake work remains outside that transaction. Unknown commit outcomes retain output and ownership; cleanup must not destroy possibly admitted data. A failed or expired operation alone does not make the target reusable. Successful admission consumes the reservation only when remaining work cannot mutate its committed target.
Managed Datafile-to-Dataset materialization has public Operation tracking, including admission idempotency, status, cancellation, history, and durable result readback. Start acceptance persists its reservation, attempt, pending Operation, and optional idempotency binding atomically; final admission records the typed result in the metadata transaction. Cancellation is cooperative and cannot retract a committed result. Restart interruption requires reconciliation and explicit new work, not automatic Session restoration or materialization replay. Other synchronous writers reuse reservation and compensation ownership without pretending to be detached Operations. See ADR-0018.
Source Acquisition and Governed Derivation
Clients may read an external source with their own authority and upload it, or securely delegate a bounded acquisition to the Trusted runtime. Destination Study authorization is independent of source authentication. A workstation path is opened by the client and never becomes a server path to reopen.
The implemented acquisition families include local files and Arrow/table uploads, HTTPS, client-local DuckDB/SQLite, client or Trusted PostgreSQL/MSSQL, and offline or live REDCap. Input formats and provider restrictions are defined by the upload, HTTPS, SQL source, and REDCap contracts.
User-supplied source credentials travel separately from public JSON and are retained only for that acquisition. They are discarded on completion, failure, cancellation, or expiry, with no Session credential cache or authenticated pool for later work. Named shared sources have separate configured grants and logical Secret references; ordinary Study access does not grant their credentials. Outbound policy, TLS verification, finite budgets, and parser limits apply before admission. TRE metadata credentials never substitute for source credentials.
Ordinary ingest requires explicit Asset risk classification. Low classification requires the owning Study’s custodian and justification; later versions must respect the logical Asset’s classification. Uploaded or client-produced content is not proof of a governed derivation.
dataset.transform is a bounded synchronous governed SQL writer. It resolves
all input dependencies and an independent Output Study, evaluates captured
immutable inputs in the restricted query worker, and admits high-risk output
through the shared writer. It returns safe identities and provenance, not rows
or derived counts. It is distinct from both external SQL acquisition and direct
low-risk query disclosure. See the
Dataset SQL transform contract.
Trusted Content Disclosure
The application resolves complete immutable inputs, including dependencies behind query views and aliases, checks authorization and risk, and captures the admission snapshot. Unknown dependencies, missing classification, unauthorized inputs, or any high-risk input prevent content disclosure to a user-controlled client.
Authorized low-risk content may be returned completely within finite service budgets; those budgets protect reliability rather than create a second disclosure grant. Dataset data, previews, exports, Datafile bytes, query results, and content-bearing semantic responses share this boundary.
Required admission/start evidence is durable before the first byte leaves Trusted control. The protected Governance Study’s append-only, non-content ledger records governance evidence. Delivery completion records outcomes and known rows/bytes without copying content. An unresolved older completion retains recovery state; each new disclosure still needs its own durable admission. Reclassification or revocation blocks new admissions but does not retroactively truncate an already admitted finite stream or recall an earlier client copy.
Trusted transport delivers framed payloads with identity, sequencing, digest, and terminal-evidence validation. EOF without a verified successful terminal is failure. CLI file destinations publish atomically only after verified completion; stdout may already contain partial bytes when a transfer fails. C results support bounded incremental reads or explicit bounded materialization, with independent result-buffer ownership. Managed buffering creates no implicit persistent cache. See the content transfer contract.
Lake locations, storage credentials, and trusted scratch stay inside the
trusted boundary. Clients identify returned copies as
low-risk / user-controlled; this notice is not another approval step. Legacy
unclassified Assets require the explicit preserving governance upgrade, which
classifies them high and records evidence while retaining safe metadata access.
Crate Boundaries
| Layer | Crates | Responsibility |
|---|---|---|
| Domain | ahri_tre_types, ahri_tre_core | Handle-free records, identifiers, value objects, policies, and repository contracts. |
| Application | ahri_tre_app | Workflow decisions, authorized selection, governance, provenance, writers, disclosure, and compensation. |
| Configuration | ahri_tre_config | Versioned documents, validation, selection, Effective graphs, fingerprints, and public Client projection. |
| Secrets | ahri_tre_secrets | Injected snapshots, encrypted Managed storage, authorized resolution, and acquisition-only source material. |
| Runtime state | ahri_tre_runtime, ahri_tre_session | Immutable bootstrap, retained authentication/capability state, Managed transport, shared Client Session behavior, and safe local context. |
| Trusted composition | ahri_tre_trusted_runtime, ahri_tre_runtime_pgmeta | Executable composition, authenticated dispatch, live Sessions, and narrow runtime-to-metadata capabilities. |
| Metadata | ahri_tre_pgmeta | PostgreSQL schema, queries, read models, transactions, admission, reservations, and governance persistence. |
| Authentication | ahri_tre_orcid, ahri_tre_libpq_oauth | OIDC contracts/exchange and the separate PostgreSQL libpq OAuth bridge. |
| Lake and tabular data | ahri_tre_lake, ahri_tre_tabular | DuckDB/DuckLake, storage and scratch mechanics, restricted evaluation, Arrow, Parquet, and IPC. |
| Sources | ahri_tre_sqlmeta, ahri_tre_redcap | External SQL and REDCap provider mechanics and metadata. |
| Public interfaces | ahri_tre_protocol, ahri_tre_cli, ahri_tre_daemon, ahri_tre_web, ahri_tre_ffi_c | Versioned contracts and thin command, local lifecycle, Browser HTTP, and C ownership adapters. |
| Cross-cutting policy | ahri_tre_security, ahri_tre_observability | Sensitive-material projection/redaction and closed, bounded operational event contracts. |
| Qualification | ahri_tre_bootstrap_acceptance, ahri_tre_remote_acceptance, ahri_tre_secret_acceptance, ahri_tre_dataset_acceptance | Executable and integration evidence for the composed boundaries. |
| Binding scaffolds | ahri_tre_python, ahri_tre_julia, ahri_tre_r | Transitional workspace scaffolds; host-language packages consume the C ABI from companion repositories. |
PostgreSQL OAuth retains libpq. The existing password-authenticated Browser
Discovery adapter may use Rust postgres, but remains behind
ahri_tre_pgmeta and is invoked from Trusted composition. Neither Web nor domain
types acquire a database backend through that exception.
Datastore Identity Binding
There is no central registry database. A datastore-local binding records its Datastore identity, generated durable UUID, owned physical stores, encryption policy, credential references, and lifecycle state. The Datastore identity is the PostgreSQL metadata database name; the Datastore configuration ID selects an Application declaration; the public Datastore identifier is the generated UUID. These values have different purposes.
An Execution profile selects one configured Datastore. Trusted constructs the Session plan from retained configuration, opens the selected metadata database, checks its binding and DuckLake state, and passes the resolved capability to application workflows. A client supplies profile intent, not a physical database or Lake profile. Creation, adoption, and storage maintenance remain privileged workflows. Lake locations come from Effective configuration and verified binding state and must be container-visible; host-side Restricted local references belong to deployment tooling.
Metadata Identity Ownership
Ordinary new persistent identifiers are datastore-owned. Creation requests describe the object; metadata adapters omit generated IDs and return the persisted record. PostgreSQL identity sequences and UUID defaults provide the identities. Dataset and Datafile subtype rows use the datastore-assigned Asset-version ID rather than another application-generated identity.
Fixtures, import/replay paths, reference seeds, natural keys such as DUO codes, composite joins, and temporary staging names are deliberate exceptions. Public Datastore-bound references encode existing identities without requiring a wholesale primary-key migration.
Diagnostics and Qualification
Operational diagnostics report bounded safe observations with acquisition time and evidence scope. A retained Session-open observation is historical evidence, not a fresh database or Lake probe. Correlation IDs connect requests and Operations without granting authority or replay rights. Operational events omit credentials, content, raw SQL, private paths, and arbitrary adapter errors. Their bounded best-effort delivery is separate from the durable evidence required for governance and disclosure. See Diagnostics and Observability.
The completed parity PRD qualifies the integrated workflows through the recorded installed Linux aarch64 CLI/C artifacts and matching protocol-v2 Browser companion. The inventory distinguishes ordinary-user, Browser, operator, local, and bounded transfer surfaces. Actual capability advertisement also reflects deployment configuration, including whether tracked operation execution is enabled.
This evidence does not qualify every native platform or deployment image. Release handoff, large/slow ingest resume, and the separately planned concurrent Asset-access hardening retain their own backlog and validation scope.
Target Architecture: Trusted Runtime and Governed Compute
The Trusted boundary, disclosure policy, shared writer ownership, protected Governance ledger, and bounded restricted SQL evaluation above are implemented. The broader Governed-compute system in ADR-0009 remains a distinct target: a general job scheduler, arbitrary pipeline workers in a separate trust zone, reviewed fixed transformations, and governed release/publication workflows are not implied by Client parity or the current private query worker.
flowchart LR
client["User-controlled Client / JupyterHub server"]
trusted["Trusted runtime<br/>authorize and admit governed work"]
worker["Governed compute worker<br/>isolated pipeline job"]
output["Declared governed outputs"]
release["Authorized Export / Repository transformation"]
external["Approved external destination"]
client -->|job intent| trusted
trusted -->|explicit inputs and short-lived Job capability| worker
worker --> output --> trusted
trusted --> release --> external
The accepted target gives workers explicit read-only inputs and private staging, without raw Lake mounts, datastore credentials, Managed secrets, or unrestricted network access. Arbitrary user pipelines produce high-risk outputs; a reviewed fixed trusted transformation may derive low-risk output only under its immutable input/output and risk rule. High-risk content leaves TRE control only through an authorized release workflow. A low-risk input does not weaken the boundary when another input is high risk.
JupyterHub is a user-side client environment. Its trusted identity broker may project a bounded Runtime credential into the user server, while upstream OAuth artifacts and datastore authority remain protected. Image publication and qualification are separate delivery gates. Pilot, test, staging, and production are separate Deployments with independently provisioned identities, Datastores, Lake storage, and Secrets; promoting immutable software does not promote data or credentials.