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

Quickstart — eltanin run

This walks through the exact ALLOW and DENY journeys MVP 1.0 supports for eltanin run, on bare-metal Linux or macOS. Every command below is exercised, byte-for-byte, by the canonical Product E2E scenario E2E-F-M1-008-controlled-launch-v1 (crates/eltanin-cli/tests/canonical_e2e.rs, tests/docs_sync.rs pins this page to it), on both platforms — if a command here ever drifted from what that test actually runs, CI would fail. See docs/qa/e2e/F-M1-008-controlled-launch.md for the full evidence record this scenario produces.

Platform: bare-metal Linux, or Apple Silicon macOS (F-M1-010, HORO-1013 — see README.md). Backend: FakeBackend — this Quickstart proves the authorization path end to end; it is not GPU hardware enforcement evidence (that is F-M1-002/F-M1-007’s, gated on bare-metal NVIDIA hardware, and remains the sole device-level enforcement basis — see docs/product/SECURITY_MODEL.md’s E2/E3 distinction). On macOS specifically, this proves managed controlled-launch authorization, never device-level Metal enforcement — no Metal/GPU guard exists or is claimed here. Do not run as root — the policy below denies uid 0 outright (see step 2), so a root shell will always get the DENY journey, never ALLOW.

What this proves, and what it does not

MVP 1.0 can authorize eltanin run based on the connecting caller’s uid/gid, launcher path, process ancestry, and cgroup — the identity dimensions SO_PEERCRED and /proc let the agent observe directly and independently of what the caller claims. It cannot, in MVP 1.0, authorize based on the identity of the workload binary you pass after --: by the time that binary exists as a process, authorization has already happened. See CLI_CONTRACT.md for the full statement of this limitation and POLICY_EXAMPLES.md for why the policy below only ever conditions on uid, never on executable_path.

1. Write a profile

eltanin run --profile <name> resolves <name> to a (resource, action) pair via a JSON document under $ELTANIN_PROFILE_DIR (or $XDG_CONFIG_HOME/eltanin/profiles, or $HOME/.config/eltanin/profiles). Create the directory, then ~/.config/eltanin/profiles/gpu.json:

mkdir -p ~/.config/eltanin/profiles
{
  "version": 1,
  "payload": {
    "resource": {
      "vendor": "fake",
      "kind": "gpu",
      "local_id": "gpu-0"
    },
    "action": "compute"
  }
}

A profile is a client-side convenience alias only — it never reaches the agent as a distinct concept; the agent sees the same (resource, action) any client could send directly.

2. Write a policy and start the agent

Take the eltanin run policy example and replace 1000 in the allow-alice-via-eltanin-run rule with your own uid (id -u). Save it as policy.json.

eltanin-agentd refuses to bind its socket directly into a world-writable directory like a bare /tmp, so create a private subdirectory for it first:

mkdir -m 0700 -p /tmp/eltanin

Then start the agent in one terminal:

ELTANIN_AGENT_SOCKET=/tmp/eltanin/agent.sock \
ELTANIN_AGENT_SOCKET_MODE=0600 \
ELTANIN_AGENT_POLICY=policy.json \
ELTANIN_AGENT_LEASE_TTL_SECS=60 \
eltanin-agentd

Optionally, add ELTANIN_AUDIT_LOG=/tmp/eltanin/audit.ndjson to get a real audit trail you can query with eltanin-explain (step 4) — without it, the agent logs to stderr only.

3. Run a workload

In another terminal, with the agent from step 2 still running:

ELTANIN_AGENT_SOCKET=/tmp/eltanin/agent.sock \
ELTANIN_PROFILE_DIR=~/.config/eltanin/profiles \
eltanin run --profile gpu -- echo authorized-compute-ok

If your uid matches the policy’s allow-alice-via-eltanin-run rule (step 2), this prints authorized-compute-ok and exits 0 — the workload’s own exit status, passed through verbatim. eltanin run requested a lease, the agent observed your uid via SO_PEERCRED, matched the allow rule, and only then spawned echo.

4. The DENY journey

Run the exact same command as a caller the policy doesn’t name (a different uid, or edit policy.json to allow a uid that isn’t yours) and it instead:

  • exits 77 (“denied by policy”);
  • never runs the workload at all — there is no point in the launch sequence between requesting the lease (S4) and spawning the workload (S6) for anything else to happen, so a denied request cannot leave any trace of the workload having run;
  • prints a message on stderr naming the denial and the next action: eltanin-explain --pid <the eltanin process's own pid>.

That eltanin-explain invocation reads whatever ELTANIN_AUDIT_LOG you set in step 2:

eltanin-explain --log /tmp/eltanin/audit.ndjson --pid <pid from the stderr message above>

and prints the full decision record for that denial — the same evidence docs/qa/e2e/F-M1-008-controlled-launch.md cites as Track B evidence for F-M1-009 (local audit & explain).

Troubleshooting

SymptomLikely cause
exit 69eltanin-agentd isn’t running, or ELTANIN_AGENT_SOCKET doesn’t match between the two commands.
exit 78the profile name doesn’t resolve — check ELTANIN_PROFILE_DIR and that <name>.json exists there.
exit 74the governed execution context could not be established (MVP 1.0’s context is a no-op today, so this is unexpected — check the error message).
eltanin-agentd refuses to start, naming its socket’s parent directorythat directory is world/group-writable; create a private one (mkdir -m 0700 ...) and point ELTANIN_AGENT_SOCKET inside it.

Running a real GPU workload on Apple Silicon

Step 3 above uses echo so this journey runs on any platform. To run the exact same ALLOW/DENY journey against a real Metal GPU compute workload on physical Apple Silicon hardware instead of echo, see APPLE_SILICON_FIXTURE.md (F-M1-010, HORO-1014) — including what that evidence proves and does not prove.