Getting Started
Run the AXIS stack locally and complete the evaluation drill: health, safe read, blocked write, approval round-trip and evidence verification.
Prerequisites
- Docker with Docker Compose (standard stack) — or Rust toolchain + PostgreSQL for a direct run.
- Ports
6543(AXIS),5432(PostgreSQL),3000(Control Plane) free. - curl for the API drills.
1 · Start the stack
git clone https://github.com/your-org/axis.git # or your local checkout
cd axis
docker compose up --build
Wait until all containers are healthy, then verify:
curl -sS http://localhost:6543/health
# {"status":"ok","version":"0.6.0","uptime_seconds":N}
curl -sS http://localhost:6543/policy/status
# {"loaded":true,"policy_version":"prod_main@1.0.0",...}
2 · First safe read
curl -sS -X POST http://localhost:6543/query \
-H "Content-Type: application/json" \
-d '{
"actor": "demo-ops",
"app": "demo-read",
"tenant": "acme",
"role": "app_ops",
"host": "localhost",
"env": "staging",
"sql": "SELECT 1 AS ok"
}'
Expected: 200 with decision: "ALLOW", execution_state: "success", rows: [{ok: 1}] and policy_version. Safe reads default to ALLOW.
3 · Watch a write get blocked
curl -sS -X POST http://localhost:6543/query \
-H "Content-Type: application/json" \
-d '{
"actor": "demo-ops",
"app": "demo-batch",
"tenant": "acme",
"role": "app_ops",
"host": "localhost",
"env": "prod",
"sql": "DELETE FROM accounts"
}'
Expected: 403 with decision: "BLOCK" and a reason code. The statement never reaches PostgreSQL — check with psql that the rows are still there.
4 · Approval round-trip
Submit a write that policy marks REQUIRE_APPROVAL (for example DDL or a guarded batch update):
curl -sS -X POST http://localhost:6543/query \
-H "Content-Type: application/json" \
-d '{
"actor": "demo-ops",
"app": "demo-batch",
"tenant": "acme",
"role": "app_ops",
"host": "localhost",
"env": "prod",
"sql": "UPDATE accounts SET status = '\''active'\'' WHERE id = 42"
}'
Expected: 202 with decision: "REQUIRE_APPROVAL" and an approval_id. The write has not executed. Now approve it as the operator:
export AXIS_OPERATOR_TOKEN=your_token # must match the stack configuration
curl -sS -X POST http://localhost:6543/approvals/<approval_id>/resolve \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AXIS_OPERATOR_TOKEN" \
-d '{"decision": "approve", "note": "verified in drill"}'
Approval is consent, not execution. Retry the original request with the same approval_id to execute:
curl -sS -X POST http://localhost:6543/query \
-H "Content-Type: application/json" \
-d '{
"actor": "demo-ops",
"app": "demo-batch",
"tenant": "acme",
"role": "app_ops",
"host": "localhost",
"env": "prod",
"sql": "UPDATE accounts SET status = '\''active'\'' WHERE id = 42",
"approval_id": "<approval_id>"
}'
Expected: 200 with execution evidence. Also try resolving as reject or waiting past the TTL (300 s) — the retry must fail with a structured error and never execute.
5 · Verify evidence
curl -sS http://localhost:6543/evidence/verify
# {"status":"ok",...}
curl -sS http://localhost:6543/audit
# decision/execution events with event_hash and previous_hash
Every action above is in the audit WAL with a hash chain; /evidence/verify recomputes and links every hash.
6 · Control Plane
Open http://localhost:3000 for the operator dashboard: health, runtime stats, logs, approvals, policy status and audit. Real mode reads live endpoints; mock mode is explicit demo-only.
Next steps
- Installation — prerequisites and alternatives (cargo run, Control Plane frontend).
- Configuration — every environment variable and default.
- Operating Modes — shadow → approval_first → enforce rollout.
- Pilot — acceptance criteria and operator checklist.
Run the whole drill in shadow mode first, then switch to enforce: the decisions are identical, only the enforcement changes.