Development

  1. Toolchain
  2. Tests
    1. Red-team checks
  3. Guards worth knowing about
  4. Releases
    1. One-time setup before the first release
    2. Repository secrets
  5. Documentation

Toolchain

Python: uv + ruff. Frontend: bun. Warden: cargo.

make setup           # uv sync --extra server
make test            # every suite CI runs: python × 3 + cargo
make lint            # ruff · uv lock --check · clippy · tsc · eslint

The unit suite is designed to run without Docker or Kubernetes — the runners no-op their container calls — so it is fast and CI-safe.

Tests

Each suite discovers its own test_* functions (tests/_runner.py), so writing a test is enough to make it run. There is no registration list to forget.

uv run python tests/test_unit.py          # control plane, ~90 tests
uv run python tests/test_sdk.py           # SDK, offline via httpx MockTransport
uv run python tests/test_worker_rewind.py # worker rewind/reconnect robustness
cargo test --manifest-path warden/Cargo.toml

Red-team checks

These need a built sandbox image, so they are not in the unit CI. Run them before a deploy:

make redteam          # sandbox isolation boundary
make redteam-pinhole  # the firewall opens exactly one endpoint (the Warden pinhole)
make redteam-conceal  # no environment tells, combined CA store

Guards worth knowing about

Several tests exist to stop a specific class of drift rather than to check a behaviour. If one fails, it is telling you a duplicate has reappeared:

  • test_harness_surfaces_are_one_schema — the harness field set across the dataclass, the API body, the agent PATCH model and web/lib/types.ts. It parses the TypeScript, because the console has no Python to import.
  • test_tool_catalog_is_single_source — the tool/skill catalog is served from terracore/toolset.py, not re-listed in the console.
  • test_stores_are_owner_only — every durable JSON store is written 0600.
  • test_warden_mandatory — no config knob can produce an unmediated sandbox, and the Pod manifest builder has no form that omits the sidecar.

Releases

Releases are automated from Conventional Commits on main:

Commit prefix Effect
fix: patch release
feat: minor release
feat!: / BREAKING CHANGE: footer major release
chore:, docs:, refactor:, test:, ci: no release

semantic-release derives the version, runs scripts/bump-version.sh to stamp it into pyproject.toml, sdk/pyproject.toml and warden/Cargo.toml, commits, tags, and publishes the GitHub release. Only then do the three Docker images and the SDK wheel build — so a published artifact always corresponds to a tag.

One-time setup before the first release

These are console settings, not code. Each one fails a job with a message that does not obviously name it, so do all three before the first push to main:

  1. Baseline tag. semantic-release computes the next version from git tags and ignores the version in pyproject.toml. With no tags it starts at 1.0.0, not at your manifest version. Tag the first commit before releasing:
    git tag v0.1.0 <first-commit-sha> && git push origin v0.1.0
    

    The release workflow now refuses to run without a v* tag rather than silently publishing a major.

  2. PyPI trusted publisher. Create a pending publisher at https://pypi.org/manage/account/publishing/ — project terrarium-python, owner OAISP, repository terrarium, workflow release.yml, environment publish and release (this string must match the environment: in the workflow’s sdk job exactly). It must exist before the first upload; otherwise the OIDC exchange 403s and the job fails with a permissions error rather than “you have not configured this”.

  3. GitHub Pages. Settings → Pages → Source: GitHub Actions. Until then actions/configure-pages fails and the Docs workflow is red.

Repository secrets

Secret Used by
DOCKERHUB_USERNAME / DOCKERHUB_TOKEN pushing the three images
(none for PyPI) the SDK publishes via OIDC trusted publishing

PyPI trusted publishing needs a one-time configuration on the terrarium-python PyPI project: owner OAISP, repository terrarium, workflow release.yml, environment pypi. The distribution is terrarium-python; the import package stays terrarium.

Documentation

This site is Jekyll + Just the Docs, built from docs/ by GitHub Actions on every push to main.

cd docs && bundle install && bundle exec jekyll serve