Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

ScopePurposeEntry pointRetention
Development-tool containerEdit, 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 fixtureRun tests against isolated PostgreSQL and Lake services../dev-env integration runRemoved after success; retained with a run ID after failure.
Local TREExercise the product topology, Browser, Web, deterministic OIDC, and durable Datastores../dev-env local upSurvives 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

  1. Install a supported native Docker Engine with Compose v2, VS Code, and the Dev Containers extension.
  2. On WSL2, keep the checkout in the distribution filesystem and open it through WSL integration. Native Linux and macOS use their host checkout.
  3. Run ./dev-env doctor in a host terminal.
  4. Choose Dev Containers: Rebuild and Reopen in Container.
  5. 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.