Developer Guide
Developers adding TRE features or fixing bugs use one non-root VS Code development-tool container over the authoritative host checkout. Opening the editor starts no PostgreSQL, Lake, Trusted runtime, Web, Browser, OIDC, or Integration workload.
The complete operating, platform, migration, command, diagnostic, and recovery reference is README-dev-env.md.
Understand the three scopes
The development environment deliberately separates editing, disposable integration testing, and durable product evaluation:
| Scope | Purpose | Entry point | Retention |
|---|---|---|---|
| Development-tool container | Edit, build, lint, test, build documentation, and debug Rust. | Run ./dev-env doctor, then open with VS Code Dev Containers. | Rebuildable; Cargo output is disposable. |
| Integration fixture | Run tests against isolated PostgreSQL and Lake services. | ./dev-env integration run | Removed after success; retained with a run ID after failure. |
| Local TRE | Exercise the product topology, Browser, Web, deterministic OIDC, and durable Datastores. | ./dev-env local up | Survives local down, Docker restart, and host reboot until guarded reset. |
Opening VS Code starts only the first scope. The development container has no Docker socket, service credential, database authority, or Trusted-runtime authority. Run Local and Integration lifecycle commands from a host terminal; run Cargo and mdBook commands in the development-container terminal.
Start
- Install a supported native Docker Engine with Compose v2, VS Code, and the Dev Containers extension.
- On WSL2, keep the checkout in the distribution filesystem and open it through WSL integration. Native Linux and macOS use their host checkout.
- Run
./dev-env doctorin a host terminal. - Choose Dev Containers: Rebuild and Reopen in Container.
- Confirm host and container Git HEAD, branch, remotes, staged changes, and unstaged changes match.
The checkout is bind-mounted at /workspaces/ahri-tre-rs; it is not cloned
inside the container and there is no separate Git metadata volume. A commit,
branch change, staged file, or generated file is therefore the same object on
the host and in the container. Stop and investigate if these checks differ:
git rev-parse HEAD
git symbolic-ref --quiet --short HEAD || printf 'detached\n'
git remote -v
git status --short --branch
git diff --cached --stat
git diff --stat
GitHub credentials and commit signing remain host-owned. The container may use VS Code’s supported HTTPS-helper or SSH-agent forwarding, but it receives no private key, credential store, GPG agent, GitHub CLI state, or Docker socket. If forwarding is unavailable, make authenticated Git operations and signed commits from a host terminal against this same checkout.
Validate a change
Run the standard loop inside the container as the mapped non-root user:
cargo fmt --all
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace
mdbook test docs/book
mdbook build docs/book
The default test suite is non-live. It does not require PostgreSQL, a Lake,
OAuth, ORCID, or Managed-secret authority. Build output is placed beneath
/tmp/ahri-tre-rs-target in the container.
Run Integration tests
Run live adapter behavior from a host terminal through the disposable fixture:
./dev-env integration run
./dev-env integration run -- -p ahri_tre_pgmeta
The runner proves verified PostgreSQL TLS and a writable container-visible Lake before tests. It is a test runner, not governed compute. Diagnose retained failures only with the run ID printed by the command:
./dev-env integration status int-<id>
./dev-env integration logs int-<id>
./dev-env integration logs int-<id> runner
./dev-env integration shell int-<id>
./dev-env integration reset int-<id>
integration reset previews the exact owned fixture and requires its run ID
as confirmation. Do not diagnose or remove fixtures with copied container IDs,
raw Compose, or direct volume deletion.
Exercise Local TRE
Use Local TRE only when a change requires the durable non-production product topology:
./dev-env local up
./dev-env local status
./dev-env local test smoke
./dev-env local test e2e
./dev-env local down
local up builds or verifies immutable artifacts, validates the retained
foundation, starts PostgreSQL and the Trusted runtime, reconciles configured
Datastores through the protected administration socket, and starts the Web and
Browser path. Repeating it validates and reuses retained state. It does not
mount this checkout, Cargo output, a Docker socket, or a toolchain into the
long-running workloads.
local status prints the checkout-scoped environment identifier, selected
profile, active root/store slot, declared versions, service health, and
loopback Browser and Trusted-runtime client origins without printing
credentials or Restricted local references. local down stops workloads and removes
temporary capability projections but retains PostgreSQL, Lake, configuration,
trust, and Secret state. After a reboot, run local up again; Local services
do not restart automatically.
For the configuration/Secrets cutover, local status reports exactly one of
no state change, service rebuild, or guarded reset. Ticket 21 does not change
the development-tool image, so it does not require rebuilding or reopening VS
Code. Use local up for the reported Local rebuild, or local reset followed
by local up for pre-cutover retained state; do not operate the topology with
raw Compose.
To rotate the Local Managed-secret root, run:
./dev-env local rotate-root
./dev-env local up
The first command revokes temporary database exposure, stops all services, and
stages into a distinct empty identity and store pair. It atomically selects the
new pair, reconstructs the active mount topology, then runs secrets verify --all as the post-cutover startup gate and leaves services stopped. A recovery
marker blocks local up if that sequence is interrupted; rerun
rotate-root to resume. Long-running workloads never receive the next
identity or staging-store mounts.
Use only the supported service selectors when inspecting redacted logs:
./dev-env local logs
./dev-env local logs trusted-runtime
./dev-env local logs --follow web
To rebuild one backend workload after a source change:
./dev-env local rebuild trusted-runtime
./dev-env local rebuild web
To test a companion TRE Browser checkout without mounting or retaining its Restricted local reference:
./dev-env local browser rebuild --source /path/to/ahri-tre-web
The command builds an immutable Browser image, verifies its compatibility, and records only the companion Git revision.
Use synthetic demo data
Ordinary local up leaves the durable development Datastore empty and
does not create the separately declared demo Datastore. Create or recreate
only the reviewed synthetic demo with:
./dev-env local seed demo
Reseeding replaces only the demo’s versioned Dataset tables. It does not alter the development or research Datastores.
Exercise real ORCID sandbox interoperability
The default Local profile uses deterministic test identities. Real ORCID
sandbox interoperability is an explicit, human-only profile. Register exactly
https://127.0.0.1:8443/auth/orcid/callback with the sandbox client and put
the three required values in the owner-only file outside the checkout described
in the development-environment reference.
Then run from a host terminal:
./dev-env local up --profile orcid-sandbox
./dev-env local test orcid-sandbox
./dev-env local down
Only one sandbox checkout can use fixed port 8443. local down returns the
deployment to the deterministic default profile and removes the projected
capabilities without changing the contributor-owned credential file. Never
paste authorization codes, tokens, cookies, ORCID identities, credentials, or
credential paths into logs or evidence.
Inspect Local PostgreSQL
Database access is closed by default. For a temporary, read-only DBeaver diagnostic endpoint:
./dev-env local trust export
./dev-env local db expose
./dev-env local db status
./dev-env local db unexpose
trust export writes only the public Local CA to the ignored
.dev-env/local-ca.crt. Configure DBeaver with the host, dynamic loopback
port, role, CA, and password-file location printed by db expose; use SSL
verify-full and keep hostname verification enabled. The password itself is
never printed. Always run db unexpose when finished. local down also
attempts the same revocation.
Recover and clean up
Start diagnosis with:
./dev-env doctor
./dev-env local status
./dev-env local logs <service>
Correct the named prerequisite or phase and rerun the same high-level command.
The lifecycle is designed to reconcile partial startup safely. Do not edit
.dev-env, copy a Docker ID into a repair command, invoke the underlying
Compose files, or copy volumes.
Remove disposable Cargo output without touching Local or Integration state:
./dev-env clean artifacts
To irreversibly remove the current checkout’s entire Local TRE, run
./dev-env local reset. It first previews the owned resources, verifies their
labels and network membership, and requires the full Local identifier as
confirmation. It fails closed on ambiguous or mismatched ownership.
The most common host remedies are:
- move a WSL2 checkout from
/mnt/<drive>into the distribution filesystem; - start Docker and install or enable the Compose v2 plugin;
- free port 8443 before using the ORCID sandbox profile;
- rebuild and reopen the development container after changing its definition, Git credential helper, or SSH agent; and
- use the exact retained Integration run ID or Local service name printed by the failing command.
Boundaries
Read the relevant crate README before changing code and preserve the ownership
rules in AGENTS.md. Do not reopen configuration or Secret stores from
workflow code, leak Restricted local references into runtime code, mount source into Local TRE,
or operate supported lifecycle state with raw Compose. Local TRE has no
production-isolation, backup, observability-platform, RustFS, or
governed-compute guarantee. Docker Engine or Docker Desktop with Compose v2 and
native linux/amd64 or linux/arm64 containers is the qualified runtime;
Podman, Rancher Desktop, Kubernetes, rootless variants, and architecture
emulation are not qualified by this development environment.