README
¶
Wardyn Sample Workspaces
Watch — Add a workspace (~4:00)
This directory is a catalog of small, self-contained workspaces that let an
operator exercise every major Wardyn governance control without writing code.
Each subdirectory is a minimal but runnable project paired with a TASK.md
that gives the exact task text for the agent, the wardyn run command to
issue, and the observable PASS criteria.
How to use this catalog
Option A — point a run at a git host.
Push a workspace subdirectory to a repository, then pass it as --repo. The
dispatcher records the slug as audit metadata and the agent launcher
shallow-clones it into the sandbox workspace (~/work/<name>) through the
governed egress proxy before the task runs.
Under the demo policy that clone is brokered, not direct: the policy carries
a github_token grant, so agent-run rewrites https://github.com/<org>/<repo>
to http://wardyn-proxy:3128/wardyn/gh/<org>/<repo> (git insteadOf) and the
proxy mints the repo-scoped installation token server-side. The repo, not the
domain, is the unit of trust — which is why github.com is deliberately absent
from demo.json's allowed_domains. A stock demo therefore needs both an
approval (the grant is requires_approval: true) and a configured GitHub App;
without them the broker 403s/502s, the clone fails non-fatally, and the run
proceeds with an empty ~/work. Use Option B or C for a walkthrough that needs
neither.
Re-adding
github.comtodemo.jsonwould not help: theinsteadOfrewrite happens before the egress allowlist is ever consulted, so the request never reachesgithub.com. Only a policy with nogithub_tokengrant dials it directly — see scenario 6's inline policy, which is keyless on purpose.
Option B — supply the task text directly.
The exact task text in each TASK.md is crafted so that even an empty
~/work directory is a meaningful test of the governance control. Omit
--repo or pass any slug as a label; the governed behavior under test does not
depend on the workspace files being present.
Option C — API-key-free probe.
Run examples/workspaces/probes.sh against a live sandbox (any RUNNING run)
to exercise every egress control with raw curl and wardyn-git-helper
calls. No Anthropic key needed.
Prerequisites
# Start the stack, then build the agent images:
make setup
make agent-images
export WARDYN_URL=http://localhost:8080
The demo policy (examples/policies/demo.json) allowlists exactly one domain —
proxy.golang.org — plus an approval-gated read-only github_token grant, and
sets first_use_approval: "deny_with_review". Git egress goes through the
broker as described above. That is the policy in force for all scenarios below
unless noted otherwise (scenario 6 supplies its own inline policy).
Running a scenario
Every scenario is the same command with a different --repo and --task; the
escaped --task string in each TASK.md is the exact task text, so copy
the command as printed.
wardyn run \
--agent claude-code \
--repo <org>/<repo> \
--task "<task text from the scenario's TASK.md>"
Each TASK.md names the audit events to look for. To read them from the CLI
instead of the UI: wardyn run list for run state, wardyn audit <run-id> for
every event of a run.
Scenario catalog
| # | Directory | Wardyn control exercised | Expected observable outcome |
|---|---|---|---|
| 1 | benign/ |
Full happy path: recording, attributed audit, clean egress | Run reaches RUNNING; wardyn audit shows run.exec success; Replay tab has a session; no pending approvals |
| 2 | exfil-attempt/ |
L2 egress deny / first-use PENDING for an unlisted domain | egress.deny or egress.pending (the held request that raises the egress_domain approval) for webhook.example.com; no bytes leave the sandbox; request body is never forwarded |
| 3 | metadata-probe/ |
Builtin private-IP unconditional deny (invariant 3) | egress.deny with rule_source=builtin:private-ip; HTTP 403 returned to the agent; no approval queue entry (the block is unconditional — approval cannot override it) |
| 4 | needs-approval/ |
First-use approval queue: PENDING -> APPROVED or DENIED | Approval entry with kind=egress_domain for example.com visible in the UI Approvals tab; approving unlocks subsequent requests; denying produces egress.deny |
| 5 | github-push/ |
Brokered git credential chain: credential ApprovalRequest -> approve -> time-limited token (or fail-closed without a GitHub App); the token is handed to wardyn-git-helper and never enters the sandbox env |
a PENDING kind=credential approval in the Approvals tab (the raise itself is not a separate audit event); on approval the broker runs the mint path and writes credential.mint with outcome=success (or outcome=failure if no GitHub App is configured — the fail-closed path is the expected PASS for a stock demo) |
| 6 | long-running/ |
Lifecycle reaper auto-stop | Run advances to STOPPED after auto_stop_after_sec; audit event run.autostop is emitted; the sandbox container is removed |
| 7 | demo-node/ |
All three egress verdicts in one run, alongside real work | node --test passes and the run has a real diff; example.com is held then approved (egress.pending → approval.decide approved → egress.allow); 169.254.169.254 is denied with rule_source=builtin:private-ip and raises no approval |
Scenario 7 is the one the demo recording drives (scripts/record-demo.sh); it is
Node rather than Python because the claude-code agent image ships Node but no
pytest. It is also the only scenario meant to be copied before use — the
recording script materializes it at a scratch path and git inits it, so the
agent's edits never land in this repo.
Workspace source layout
Each workspace contains:
- Source files — minimal but runnable (a few files, no generated artifacts).
TASK.md— the wardyn run command (whose--taskstring is the exact task text), what to watch, and the PASS criteria.
No workspace contains secrets or credentials of any kind.
Probe script
probes.sh is a standalone bash library of docker exec one-liners that
drive each control directly inside a live sandbox. It requires a RUNNING
container whose name or id is passed as SANDBOX_REF and exercises every
control with raw network calls — no Anthropic key, no Claude required.
# The kill-switch probe defaults WARDYN_ADMIN_TOKEN to demo-admin-token —
# export it only if your stack uses a different token.
SANDBOX_REF=wardyn-agent-<run-id> bash examples/workspaces/probes.sh
Directories
¶
| Path | Synopsis |
|---|---|
|
Package main is a trivial Go program used as the github-push workspace.
|
Package main is a trivial Go program used as the github-push workspace. |