{"id":52091333,"url":"https://github.com/aether-lang-dev/aeo","last_synced_at":"2026-08-04T06:01:29.307Z","repository":{"id":366135532,"uuid":"1275036819","full_name":"aether-lang-dev/aeo","owner":"aether-lang-dev","description":"Infrastructure orchestrator — stand up and tear down a dependency-ordered tree of FreeBSD jails/bhyve and Linux containers/VMs from one Aether pseudo-declarative composition.","archived":false,"fork":false,"pushed_at":"2026-07-27T06:41:16.000Z","size":1815,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-31T20:21:57.270Z","etag":null,"topics":["aether","bhyve","capsicum","containers","dsl","freebsd","infrastructure","jails","linux","orchestration"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aether-lang-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null,"disclosure":null}},"created_at":"2026-06-20T07:03:03.000Z","updated_at":"2026-07-31T17:28:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aether-lang-dev/aeo","commit_stats":null,"previous_names":["aether-lang-org/aeo","aether-lang-dev/aeo"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/aether-lang-dev/aeo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aether-lang-dev%2Faeo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aether-lang-dev%2Faeo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aether-lang-dev%2Faeo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aether-lang-dev%2Faeo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aether-lang-dev","download_url":"https://codeload.github.com/aether-lang-dev/aeo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aether-lang-dev%2Faeo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36263568,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-08-04T02:00:06.901Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aether","bhyve","capsicum","containers","dsl","freebsd","infrastructure","jails","linux","orchestration"],"created_at":"2026-08-04T06:01:28.821Z","updated_at":"2026-08-04T06:01:29.269Z","avatar_url":"https://github.com/aether-lang-dev.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aeo\n\n**Infrastructure orchestrator** — stand up and tear down a deliberate tree of\nVMs and containers (FreeBSD jails + bhyve, Linux containers/LXC + KVM) from a\nsingle Aether composition, with dependency-ordered bring-up gated on health,\nreverse-order teardown that *verifies* disappearance, per-node **confinement**\n(cgroups / cap-drop / network policy on Linux; rctl / jail boundary on FreeBSD),\n**image attestation** (verify-before-boot, fail-closed), and a **tamper-evident\naudit trail**.\n\n## Why aeo?\n\n**The problem**: Modern infrastructure needs to be both **declared** (reproducible,\nversion-controlled, diff'able) and **live** (responsive to health, capable of\nrolling updates, safe to tear down). Terraform declares; Kubernetes runs live.\naeo does both from the same file.\n\n**The promise**: A single `.ae` composition declares a tree of nodes, their\ndependencies, health checks, containment policy, and attestation requirements.\n`aeo up` brings it all up in parallel (respecting dependencies), health-gated.\n`aeo watch` keeps it coherent. `aeo down` tears it down in reverse, verifying\neach node is gone. No drift, no config creep, auditable at every step.\n\n**The security story**: Every node runs confined (cap-drop, network-deny-default,\nresource caps). Images are attested (SHA-256 verified before boot, wrong digests\nrefused). The audit log is tamper-evident (hash-chained). Secrets stay ciphertext\nin state/logs and decrypt only at use (fail-closed on tampering or wrong key).\n\n**Portable**: Works on Linux (podman/docker, LXC, KVM), macOS (Docker Desktop),\nand FreeBSD (jails, bhyve). Same composition, different drivers — no rewrites.\n\n```\naeo up       compose.ae      # bring the tree up, dependency-ordered, gated on health\naeo status   compose.ae      # per-node state + confinement/attestation posture (--json too)\naeo down     compose.ae      # tear down in reverse order, verifying each node is gone\naeo dry-run  compose.ae      # validate + print the plan, touch nothing\naeo check    compose.ae      # run the composition's declared check() specs, NO deploy (CI/anywhere)\naeo smoke    compose.ae      # deploy + run smoke() specs, leave the tree STANDING\naeo suite    compose.ae      # deploy + run suite() specs, then TEAR DOWN (the CI shape)\naeo audit    compose.ae      # verify the hash-chained audit trail\naeo cutover  compose.ae node  # zero-downtime blue-green: green up + confined + health-gated, alias-swap, retire blue\naeo reconcile compose.ae      # one-shot drift check: live probes vs the composition (exit 1 on drift); --converge to fix\naeo watch    compose.ae       # reconcile on a loop (default 30s) — aeo's life between up and down; --converge to act\naeo apply-node compose.ae node # small blast radius: re-render ONE node, apply only its delta, touch nothing else\naeo extract                   # reality-\u003ecode: walk live containers, print a composition (attest() pre-filled); \u003e file.ae\naeo inventory [compose.ae]    # the live walk as a table; with a composition, a \"declared? yes/no\" column\naeo pasta    compose.ae on   # rootless source-IP fidelity: switch the port forwarder to pasta (see docs/linux-host-setup.md)\n# aeo up hands the tree to a resident aeo-supervisord BY DEFAULT (down/status ask it); --no-supervisor = today's fire-and-exit\n# also: snapshot | rollback | backup | prune | exec | restart  (per-node lifecycle ops)\n```\n\nThe composition file is a **pure declaration** (no `main`, no self-test scaffold) —\n`aeo` is the executor, exactly as `aeb \u003ctarget\u003e.build.ae` runs a build declaration.\nA composition declares its OWN verification with first-class `check()`/`smoke()`/\n`suite()` verbs that name external aeocha specs; `aeo \u003cphase\u003e compose.ae` runs them.\n\naeo is **not** a build system and **not** an aeb SDK. It is a third sibling to\n[`aether`](https://github.com/aether-lang-org/aether) (the language) and\n[`aeb`](https://github.com/aether-lang-org/aeb) (the build runner). aeo is\n*built by* aeb and can shell *to* aeb at runtime, across a plain artifact + CLI\nseam. Its DSL philosophy is inherited from the ecosystem — **config IS code**,\nclosure-with-setters, no YAML — applied to live infrastructure. Its containment\nthinking traces back to [The Principles of\nContainment](https://paulhammant.com/2016/12/14/principles-of-containment/) (see\n[below](#principles-of-containment)).\n\n\u003e Status: **working v0, with a live-proven containment story.** Host probe,\n\u003e drivers for Linux (podman/docker, LXC, KVM) and FreeBSD (jail, bhyve), an\n\u003e actor-based runtime, the compose DSL, host-gating fast-fail, and the `aeo`\n\u003e front-door are implemented and verified end-to-end on real infrastructure. All\n\u003e **six containment axes are now live-proven** — Linux container confinement (a\n\u003e fork-bomb refused by `--pids-limit`, a `deny_egress` node with no network),\n\u003e image attestation (a mismatched digest refused at boot), a tamper-evident audit\n\u003e trail (an edited log caught), the FreeBSD jail boundary, rctl resource caps, and\n\u003e **FreeBSD pf inter-VM delivery** — the last was long the one red axis (blamed on\n\u003e an `if_bridge` bug) but was root-caused to GhostBSD's default-enabled `ipfw`\n\u003e eating bridged packets, not pf; with ipfw off the guest bridge path, pf's\n\u003e deny-default + whitelist bites (whitelisted flow completes, non-whitelisted\n\u003e blocked), and aeo now detects + handles the ipfw conflict on `up`\n\u003e (`docs/if_bridge-pf-delivery-bug.md`). Beyond containment, aeo has grown a life\n\u003e *between* `up` and `down` — reconcile/watch, apply-node, extract/inventory, a\n\u003e `policy{}` block, and a resident **aeo-supervisor** that holds this-boot's trees\n\u003e (`docs/aeo-supervisor.md`). See [`aeo-design.md`](./aeo-design.md) for the full\n\u003e design, [`TODO.md`](./TODO.md) for the honest what's-proven-vs-modeled scorecard,\n\u003e and [`LLM.md`](./LLM.md) for the Aether constraints navigated.\n\n## Try it in 60 seconds\n\nAll you need is the [`ae` toolchain](https://github.com/aether-lang-org/aether)\nand **any container engine — podman or Docker, on Linux or macOS** (container\nkinds are engine-gated, not OS-gated):\n\n```sh\nexport AEO_HOME=/path/to/aeo\nae build $AEO_HOME/bin/aeo.ae -o ~/.local/bin/aeo --lib $AEO_HOME/lib\n\naeo doctor                                    # what can THIS host run?\ndocker build -t localhost/aeo-examples/silly-add:latest \\\n    $AEO_HOME/examples/silly_addition_app/    # the demo app image (podman works too)\naeo up examples/silly_addition_containers.ae  # redis ◄ app, dependency-ordered,\n                                              # health-gated, level-parallel\ncurl http://localhost:8080/add/40/2           # -\u003e 42 (the app, live)\naeo status examples/silly_addition_containers.ae   # states + attestation posture\naeo exec  examples/silly_addition_containers.ae db \"redis-cli ping\"\naeo down  examples/silly_addition_containers.ae    # reverse levels, disappearance VERIFIED\n```\n\nRepeat invocations are fast — the front door content-hashes its inputs (compose\n+ lib/ + toolchain) and skips the rebuild when nothing changed (`AEO_REBUILD=1`\nforces). `aeo doctor` reports which kinds this host can execute and what's\nmissing for the rest; `aeo secrets` seals values (tokens, creds) so they stay\nciphertext everywhere aeo holds state and decrypt only at use, fail-closed.\n\n## Features at a glance\n\n| Feature | aeo | Kubernetes | Docker Compose | Terraform |\n|---------|-----|------------|-----------------|-----------|\n| **Declare infrastructure** | ✅ | ✅ | ✅ | ✅ |\n| **Health-gated bring-up** | ✅ | ✅ | ⚠️ basic | ❌ |\n| **Verify teardown** (nodes actually gone) | ✅ | ✅ | ❌ | ❌ |\n| **Per-node confinement** (cap-drop, rctl, netpolicy) | ✅ | ✅ | ⚠️ limited | ❌ |\n| **Image attestation** (verify before boot, fail-closed) | ✅ | ⚠️ admission control | ❌ | ❌ |\n| **Tamper-evident audit trail** | ✅ | ⚠️ event log | ❌ | ❌ |\n| **Runtime reconcile/watch** | ✅ | ✅ | ❌ | ❌ |\n| **Zero-downtime cutover** (blue-green) | ✅ (aeo cutover) | ✅ | ❌ | ❌ |\n| **No YAML** (config IS code) | ✅ | ❌ | ❌ | ✅ |\n| **VM + container substrate** (same file) | ✅ | ❌ | ❌ | ✅ |\n| **Multi-OS** (Linux, macOS, FreeBSD) | ✅ | ⚠️ Linux-first | ✅ | ✅ |\n| **Portable driver model** (docker/podman/lxc/bhyve/jail) | ✅ | ❌ | ⚠️ engine only | ✅ |\n\n\u003e Full landscape comparison — how aeo relates to cloud provisioners, config\n\u003e management, cluster orchestrators, and where it draws its boundaries on purpose:\n\u003e **[`docs/core/aeo-vs-iac-landscape.md`](docs/core/aeo-vs-iac-landscape.md)**.\n\n## The one-line distinction\n\n| | does | invocation |\n|---|---|---|\n| **aeb** | build the tree (static DAG of artifacts) | `aeb target:name` |\n| **aeo** | stand the tree up and keep it coherent (live lifecycle) | `aeo up compose.ae` |\n\naeb is *declare-then-schedule* — its DAG is static text, `build.dep()` is a\nruntime no-op. aeo is *imperative-runtime* — `vm(a).wait_for_it_to_be_up()` is\na live handle that blocks on liveness; ordering is by **health**, not by\nartifact existence. aeo is the runtime-lifecycle layer aeb deliberately refuses\nto have. If aeo ever needs build-graph work, it shells out to aeb.\n\n## Design principles\n\n**Config IS code.** The composition is pure Aether — control flow, env lookups,\nconditionals — not YAML. Derive a database password from a secret key, select\ncontainer kinds based on host capabilities, loop over a fleet of nodes. This is\nfeature, not a bug.\n\n**Declare, then execute.** The composition is data (a pure declaration of the\nresource tree). The runner is the executor. They're separate concerns. Same\ncomposition can be checked (dry-run), smoke-tested (deploy + test + keep), or\nfully tested (deploy + test + tear down).\n\n**Health-gated, not schedule-gated.** Bring-up waits for **health**, not just\n\"container started\". A node is ready when *you* say it's ready (via the health\ncheck). Teardown verifies disappearance, not just \"stop signal sent\".\n\n**Portable.** Same composition runs on Linux (podman/docker/LXC/KVM) and FreeBSD\n(jail/bhyve) without rewrites. Drivers are isolated; the DSL is substrate-agnostic.\n\n**Confined by default.** Every node runs with a cap-drop floor and network-deny\ndefault. Confinement is *declared* (you set the high-water mark), not\nbolted-on post-hoc.\n\n**Auditable.** Every step — build, bring-up, health, teardown — is logged. The\naudit trail is tamper-evident (hash-chained). Secrets stay ciphertext and\ndecrypt only at use.\n\n## Common patterns\n\n**Microservices architecture** (the 60-second demo). Database tier (Redis/Postgres)\n← application tier (Node/Python) ← reverse proxy. Health checks at each layer.\nConfinement: app has network access to DB only; reverse proxy allows only port 80/443.\n\n**Distributed system testing.** Spin up N nodes (broker, replicas, clients),\ndeclare confinement (this replica can reach only these others), run your chaos\ntests, tear down. Composition is the test harness. `aeo check` validates the\ntopology; `aeo smoke` deploys + tests + leaves it running; `aeo suite` deploys\n+ tests + tears down. Same file, different phases.\n\n**Live infrastructure (permanent)** with `aeo watch --converge`. Declare your\nnodes once. aeo watches for drift (a crashed container, a failed health check),\nreconciles automatically, and logs every action. Manual fixes and drift creep\nbecome impossible.\n\n**Blue-green deployments.** Declare version A (blue). Run `aeo up blue.ae`.\nLater, declare version B (green) with `aeo cutover blue.ae app-tier`. aeo brings\nup green in parallel, health-gates it, swaps the alias, retires blue. Zero\ndowntime, atomic.\n\n**Compliance + audit.** Every node confined by default. Image digests attested.\nAudit trail tamper-evident. `aeo audit` verifies the chain end-to-end. Meets\nregulatory requirements without extra tooling.\n\n## A composition\n\nA composition is an ordinary Aether module that declares a resource tree by\ncalling the compose DSL. It exposes `aeo_orchestration()`, which the front-door\nruns before bring-up. **config IS code**: the file is real Aether — control\nflow, env lookups, conditionals — around the declarations.\n\n```aether\nimport compose (system, container)\nimport compose (image, health, depends, within, every)\n\nexports ( aeo_orchestration )\n\naeo_orchestration() {\n    system(\"web\") {\n        health_retry() {                // health-timing knobs for the tree (see below)\n            every(500ms)                // interval between probes\n            up_within(30s)              // bring-up: retry health this long\n            down_within(10s)            // teardown: wait this long for \"gone\"\n        }\n\n        // Tier 1: database\n        db = container(\"db\") {\n            image(\"docker.io/library/postgres:16\")\n            health(\"pg_isready\")\n        }\n\n        // Tier 2: app — depends on db, so db comes up (and is healthy) first\n        app = container(\"app\") {\n            image(\"docker.io/library/myapp:latest\")\n            health(\"curl -fsS http://localhost:8080/healthz\")\n            depends(db)\n        }\n    }\n}\n```\n\nThe **kind is the verb** — `container(name) { ... }`, `jail(name) { ... }` — and\nthe opener returns a **handle** you can bind (`db = container(\"db\") { ... }`) and\npass to `depends(db)`, so a typo'd dependency is a compile error rather than a\nsilent bad string. The bare-name setters inside configure that resource (its\nname flows in as the block's context, so you don't repeat it). This is Aether's\ntrailing-block builder DSL: the call site reads like config, but the body is\nfull Aether (control flow, env lookups, conditionals). See\n[`docs/closures-and-builder-dsl.md`](https://github.com/aether-lang-org/aether/blob/main/docs/closures-and-builder-dsl.md)\nin the language repo for the mechanism.\n\nTwo import lines, the standard ecosystem idiom (cf. aeb's `import bash (script,\njobs, env)`): the openers (`container`, `jail`, …) and the block setters\n(`image`, `health`, …).\n\n`aeo up` brings `db` up and blocks until its health check passes before\nstarting `app`; `aeo down` stops `app` before the `db` it depends on. The\noperator writes the tree once; direction is aeo's job.\n\nKind verbs: `container` / `lxc` / `kvm_vm` / `bwrap` / `nspawn` / `firecracker` /\n`kata` (Linux), `jail` / `bhyve_vm` / `freebsd_vm` (FreeBSD). `container` is the one OCI\napp-container kind; which **engine** realizes it is the `engine()` property, not a\nseparate kind — `engine(\"podman\"|\"docker\"|\"wslc\"|\"wsl_podman\")`, system-scope\nfloat + per-node override, auto-resolving per host (Linux → podman → docker;\nWindows → wslc / podman-in-WSL). So a Linux container and a Windows-hosted one are\nthe *same* declaration, differing by one engine string. `bwrap` is the lightest\ntier — an unprivileged bubblewrap sandbox (no root, no host setup); `nspawn` is a\nsystemd-nspawn system container (the systemd-native LXC peer); `firecracker` is a\nminimal-device-model microVM (the \"smaller VM\" peer of full KVM, live-proven boot\n+ persist + teardown); `kata` boots an OCI container image *inside* a lightweight\nmicroVM (its own guest kernel — VM-grade isolation with the container API, via\ncontainerd's Kata shim-v2; live-proven, guest kernel ≠ host). Block setters (one arg\nper call — Aether is fixed-arity),\ngrouped by what they declare:\n\n- **identity / lifecycle:** `image`, `command`, `entrypoint`, `dockerfile`,\n  `health`, `depends`, `dataset`, `ip`, `env`, `expose`, `engine` (which OCI\n  engine realizes a `container`; floats system-scope, auto per host)\n- **health timing** (FluentSelenium-style duration literals), grouped in a\n  `health_retry() { … }` block: `up_within(30s)` = retry-until-up window,\n  `every(500ms)` = probe interval, `down_within(10s)` = retry-until-*gone* on\n  teardown. (The loose form `within(30s) every(500ms) without(10s)` still works;\n  `health_interval`/`health_budget` int forms remain.)\n- **confinement** — `limit{}` caps (`limit_mem`, `limit_maxproc`, `limit_cpu`,\n  `limit_openfiles`) and `constrain{}` (`grant_fd`, `egress`, `ingress`,\n  `ingress_from`, `deny_egress`, `deny_ingress`). The *same* grammar renders to\n  rctl/Capsicum/pf on FreeBSD and cgroups/seccomp/network on Linux —\n  substrate-portable confinement.\n- **supply chain:** `attest(\"sha256:…\")` — pin a node's expected image digest;\n  aeo verifies it before boot and refuses on mismatch.\n- **device claims:** `gpu(\"shared\"|\"exclusive\")` (+ optional `gpu_device(pin)`) —\n  names the *contract* (container/lxc SHARE a GPU; a VM takes it EXCLUSIVELY via\n  VFIO), and `aeo check` enforces the allocation (exclusive ∩ anything on one\n  device fails; kind-mismatches fail). At `up` aeo probes `/etc/cdi` and prefers\n  the structured CDI selector (`--device intel.com/gpu=all` — the full\n  card+render+by-path bundle), falling back to the raw DRI device-map\n  (`--device /dev/dri`) when no spec is present. Both proven live on a podman-6\n  Intel N100. (See [`examples/cdi/`](./examples/cdi/) for a ready CDI spec.)\n- **VM sizing:** `cpus`, `memory`, `nic`; **image recipes:** `from`, `install`,\n  `systemd_unit`, `realize_as`, …\n- **reconcile policy:** `policy(node){ reprobe_every(15s) on_drift(\"converge\")\n  reattest_every(24h) }` — per-node data that `aeo watch`/`reconcile` reads;\n  `on_drift` defaults to `\"alert\"` (never silently mutate).\n\n`depends` accepts either a handle (`depends(db)`) or a name string\n(`depends(\"db\")`) — handles are typo-checked, the string form is there for\nreferences you don't have a binding for. (`resource(name, kind) { ... }` remains\nas a general escape hatch.) See [`examples/`](./examples/) for twelve\ncompositions with the same `db ◄ app` shape across every substrate — the\nsubstrate grid (read one, diff against another). Each example is a **pure\ndeclaration** that names its own `check()`/`smoke()`/`suite()` verification specs;\n`aeo \u003cphase\u003e \u003cexample\u003e.ae` executes it.\n\n## Performance\n\naeo is fast because it **parallelizes aggressively** and **caches wisely**.\n\n**Bring-up**: Level-parallel orchestration (topological sort respecting both\n`depends()` and containment edges). All nodes at the same level boot in parallel.\nHealth polls are batched (one OS `ps` per engine for all host containers, not per\nnode). A 2-node demo brings up in ~2-3s; a 9-node DAG in ~15s.\n\n**Build cache**: The front door content-hashes the entire closure (compose + all\nlib files + toolchain version) and caches the compiled binary. Repeated `aeo\nstatus` on an unchanged composition: 3.2s (first run, compile) → 0.26s (cache\nhit, 12.5× speedup).\n\n**Teardown**: Reverse-topology, level-parallel. Nodes at the same level halt\nconcurrently. Tear-down of a 15-node cluster with uncooperative containers\n(ignore SIGTERM) dropped from 15.6s (serial) to 6.3s (parallel) by batching stops\nper engine and giving one grace period per level, not per node.\n\n**Status probing**: A single `ps` per distinct engine (docker/podman/lxc/etc)\nreports all host-visible containers, not one probe per node. On a 9-node tree:\n~0.3s (batched) vs ~2.7s (one per node).\n\n**Secrets**: O(n) encryption/decryption (HMAC-SHA256 labeled derivation + PRF-CTR\nkeystream on `std.strbuilder`) instead of O(n²) string concat. Native keygen\n(no subprocess).\n\nSee [`TODO.md`](./TODO.md) for detailed measurements and [`aeo-design.md`](./aeo-design.md)\nfor the architecture.\n\n## Running it\n\naeo compiles your composition into a supervised runner and executes it. Point\n`AEO_HOME` at the aeo tree, then:\n\n```\nexport AEO_HOME=/path/to/aeo\nae build $AEO_HOME/bin/aeo.ae -o ~/.local/bin/aeo --lib $AEO_HOME/lib\naeo up examples/silly_addition_containers.ae\n```\n\nThe front-door (Decision 1B — native Aether, no bash trampoline) assembles a\nbuild dir, `ae build`s the composition, and runs it under `os.run_supervised`\n(own process group + signal forwarding + group reap). Resources are modeled as\nAether actors (Decision 2A) with a `down → booting → up` state machine and a\nself-driven, `up_within`-bounded health-poll loop.\n\nOn an immutable host (e.g. a Fedora-atomic box) where `ae` isn't on the runtime\nPATH, aeo builds the composition inside a toolchain container via an `ae`\ncontainer-shim — see [`docs/build-in-container.md`](./docs/build-in-container.md).\nThe Linux substrates (containers, KVM, LXC) are all live-proven this way.\n\n## Host adaptation \u0026 fast-fail\n\naeo adapts to whether the host is BSD or Linux and **fast-fails before touching\nany resource** when a composition can't run here:\n\n- A `kind` the host can't execute (a `jail` on Linux, a `container` on BSD) is\n  a loud error at composition-evaluation time, not a silent no-op three nodes\n  deep.\n- A `depends()` on an undeclared resource (or itself) is caught the same way.\n- Capsicum/Casper enforcement consumes Aether's `std.capsicum` /\n  `std.casper` `available()` contract (merged from `feat/freebsd-sandbox-parity`)\n  rather than reinventing host detection — the host probe reports\n  `family=bsd, capsicum=yes` on FreeBSD and `family=linux, capsicum=no` on\n  Linux.\n\n`aeo dry-run` runs all of this validation and prints the resolved bring-up plan\nwithout starting anything — the operator's pre-flight.\n\n## Principles of containment\n\naeo is, at heart, an exercise in\n[The Principles of Containment](https://paulhammant.com/2016/12/14/principles-of-containment/):\nthe container sees and drives the contained; the contained only suspects it is\ncontained and cannot casually reach back unless the container configured it to;\nand this should nest, restricting further at each boundary without the contained\nknowing its depth. An honest scorecard of how aeo measures up today:\n\n| Principle | aeo fit |\n|---|---|\n| Container sees the contained, drives it | **Strong** — aeo holds live handles and runs `up` / health-gated wait / `down` (teardown *verifies* the node is gone, not just flips a flag). |\n| Contained can't casually reach the container | **Strong, control *and* data plane.** Control: a resource has no handle back to aeo. Data: `constrain{}` renders to a real deny-default — on Linux, `deny_egress` puts a node on `--network none` (no namespace — proven: it can't phone home); peer-only egress lands it on an `--internal` network (reaches its declared peer, not the internet); on FreeBSD the same grammar targets pf. |\n| Reach out only where configured | **Strong** — the `image`/`command`/`env`/`expose`/`egress`/`ingress` setters _are_ the explicit, declared I/O surface; anything not declared is denied. |\n| Don't starve the host | **Strong (live)** — `limit{}` renders to cgroup caps on Linux (`--memory`, `--pids-limit`: a fork-bomb is *refused*, proven) and rctl on FreeBSD (live on a jail). |\n| Trust only what you pinned | **Strong (live)** — `attest(\"sha256:…\")` verifies a node's image digest before boot, **fail-closed**: a mismatched/poisoned image is refused (proven), and the verdict is recorded in the audit trail. |\n| Observe, tamper-evidently | **Strong (live)** — every confinement/attestation decision is written to a hash-chained audit log; `aeo audit` verifies the chain (an edited entry is caught, proven). |\n| Authority injected, not constructed (DI) | **Strong** — the composition receives its authority to spawn from the front-door, it does not build it. Constructor injection (the [PicoContainer](https://picocontainer.com/) principle) applied to live infrastructure. |\n| **Nestable; restrict at each boundary, depth-agnostic** | **Partial** — the grammar nests (`bhyve_vm(\"x\") { container(\"app\") { … } }`), `get_host` records the containment, the preflight gates a nested resource against its guest substrate, and the nest **executes** (a container inside a bhyve/KVM VM is built+run in the guest — see the `*_podman` demos). What's not yet built is *recursive depth-agnostic* nesting — see below. |\n\nSo aeo is a faithful realization of the post's **directionality and injection**\nprinciples — arguably more so than some of the post's own exhibits, because\nAether's native capability model closes the \"subvert IoC from within\" hole the\npost laments in the DOM. The **isolation** principles — don't-reach-out,\ndon't-starve, trust-what-you-pinned, observe — are now *enforced and live-proven*\non Linux (cgroups / cap-drop / `--internal` networks / digest attestation /\naudit), from one substrate-portable grammar that also targets FreeBSD's\nrctl/Capsicum/pf. Its **nesting** — the principle the post treats as defining —\nexecutes one level (container-in-VM), but the *recursive, depth-agnostic* form is\nstill ahead. Closing that is **aeo-agent** (`docs/aeo-agent.md`): rather than aeo\nreaching _through_ a boundary (ssh-ing in — the directionality the post calls a\ndisaster), the container hands its contained an agent, and that agent carries\norchestration deeper — receiving the instructions for its node and everything\nbelow it, and in turn handing instructions to _its_ children's agents. Same\nactor protocol at every level, so no node knows its depth — exactly the post's\n\"further restricted without knowledge of its nesting depth.\" That build takes aeo\nfrom \"the principles, live on one level\" to \"the post, recursively implemented.\"\n\n## Layout\n\n```\nbin/aeo.ae            the front-door CLI (codegen + supervised run + subcommands)\nlib/aeo/runner.ae     the fixed runner: the resource actor + bring-up/teardown engine\nlib/compose/          the operator-facing compose DSL (config IS code)\nlib/driver_linux/     podman/docker backend (build/run/probe + the confinement flags)\nlib/driver_lxc/       real LXC system-container backend (lxc-create/start/attach)\nlib/driver_bwrap/     unprivileged bubblewrap sandbox backend (rootless; pidfile-tracked)\nlib/driver_nspawn/    systemd-nspawn system-container backend (machined-managed; self-sudo)\nlib/driver_firecracker/  Firecracker microVM backend (config-file boot; pidfile-tracked)\nlib/driver_kata/      Kata Containers backend — an OCI image in a microVM (nerdctl + containerd kata shim-v2)\nlib/driver_vm/        KVM/qemu (Linux) + bhyve (FreeBSD) VM backend\nlib/driver_bsd/       FreeBSD jail backend (jail/jexec/jls over a ZFS dataset)\nlib/driver_stub/      fail-loud arm for unsupported host/kind\nlib/confine_linux/    Linux confinement renderer: limit{}/constrain{} → cgroup/seccomp/net flags\nlib/rctl/  lib/pf/     FreeBSD confinement: rctl resource caps + pf network policy\nlib/attest/           image attestation (verify-before-boot, fail-closed; 3 greppable states)\nlib/audit/            tamper-evident hash-chained audit trail (`aeo audit`)\nlib/secrets/          sealed values (`aeo secrets`): ciphertext-throughout, decrypt-at-boundary\nlib/snapshot/  lib/snapshot_linux/   lifecycle ops: ZFS (jail/bhyve) + podman/qemu-img/lxc\nlib/host/             host-profile probe + capsicum/casper gating\nlib/ipam/  lib/images/  IP allocation + the golden-image recipe/realizer\nlib/resource/         the actor↔main state bridge\nlib/driver_windows/  lib/driver_wslc/   Windows OCI engines (podman-in-WSL2 / MSFT's native wslc.exe)\nexamples/             the substrate grid — twelve `db ◄ app` compositions (see examples/README.md)\nexamples/checks/      the per-example check()/smoke()/suite() aeocha specs\nlib/reconcile/        desired-vs-actual property diff (drift detection under `aeo watch`/`reconcile`)\nlib/extract/          reality-\u003ecode emitter (`aeo extract`/`inventory` — live containers to a composition)\nlib/supervisor/       the in-memory tree registry the aeo-supervisord daemon holds (this-boot's trees)\nbin/aeo-supervisord   resident holder of this-boot's trees; `aeo up` adopts by default (`--no-supervisor` opts out)\nbin/aeo-supervisor-install.sh  install aeo-supervisord as a boot service per init (systemd/OpenRC/rc.d, Restart=no)\ntest/                 ~37 specs (fluent-aeocha style): driver/confinement/attest/audit/lifecycle/gpu/pasta/reconcile/policy/extract/conformance/ipfw/supervisor/kata + real-jail\ntest/conformance-behavioral.sh  the live driver-conformance lifecycle (create-\u003eprobe-\u003econfine-\u003estop-\u003everify-gone) per substrate\n```\n\n## What aeo is NOT\n\nNot a build (it `pkg install`s / pulls images, it doesn't compile — shell out to\naeb for that). Not multi-host by default (every node is local unless a future\n`host(...)` control-plane form is used). Not YAML — the composition *is* the\nconfig, full Aether underneath. Don't add a config-file parser; expose setters.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faether-lang-dev%2Faeo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faether-lang-dev%2Faeo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faether-lang-dev%2Faeo/lists"}