Something went wrong. Try again.
Identities for entities did.bot
agent llm did
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224#!/usr/bin/env bash# The policy dashboard against real servers: a didbot-pds to be governed, the# operator's own PDS, the built site, and both halves of the scenario run# against them. The operator's PDS is the stand-in crates/didbot/tests/scenarios# runs, because an operator's records live in a repository somebody else hosts# and a didbot server only reads.## What runs here that nothing else runs:## 1. crates/didbot-swarm/tests/policy_rollout.rs -- an operator claims the# server, a policy and a binding are deployed with one applyWrites, and# the operator nudges the server and watches a write that policy refuses# be refused by the policy's own reason. Needs the servers; skips without# them.# 2. policy-site/tests/e2e-policy.mjs -- the built page in a real Chrome. It# signs in to the operator's PDS and makes that deploy, then compares the# digest its own wasm computes over the two records with the digest the# governed server published. Needs Chrome; skips without it.## Opt-in, not a commit hook: it compiles, starts servers, and wants a browser.# scripts/ci.sh runs it when DIDBOT_E2E=1.## Usage: scripts/test-policy-e2e.shset -euo pipefail
cd "$(dirname "$0")/.."
if [ "$#" -ne 0 ]; then echo "usage: $0" >&2 exit 2fi
# shellcheck source=scripts/dev-pidfile.sh. scripts/dev-pidfile.sh
say() { printf '\n\033[1m=== %s ===\033[0m\n' "$1" >&2; }
WORK="$(mktemp -d "${TMPDIR:-/tmp}/didbot-policy-e2e.XXXXXX")"# One stable place for the page's screenshots, overwritten each run, so the# evidence outlives the working directory below.SHOTS="${DIDBOT_E2E_SHOTS:-${TMPDIR:-/tmp}/didbot-policy-e2e-shots}"PIDS=()
# Every child is killed on the way out, however this ends: a failed assertion# leaves two servers and a Vite process behind otherwise, and the next run# picks different ports and leaves two more. Each is started under `setsid`, so# signalling the negative pid reaches the whole group -- `npm run preview` is a# wrapper around the process that actually holds the port.cleanup() { local status=$? for pid in ${PIDS[@]+"${PIDS[@]}"}; do kill -TERM "-$pid" 2>/dev/null || kill -TERM "$pid" 2>/dev/null || true done for pid in ${PIDS[@]+"${PIDS[@]}"}; do wait "$pid" 2>/dev/null || true done # A server that answers SIGTERM by draining, inside a process that goes on # after it -- the stand-in's test does -- outlives the group leader that # was waited on above. Whatever of the group is left goes now. for pid in ${PIDS[@]+"${PIDS[@]}"}; do kill -KILL "-$pid" 2>/dev/null || true done forget_pid policy-e2e-governed "${GOVERNED_PORT:-0}" if [ "$status" -ne 0 ]; then echo "test-policy-e2e: failed; logs are in $WORK" >&2 else rm -rf "$WORK" fi exit "$status"}trap cleanup EXIT INT TERM
# A port nobody chose: the kernel hands one out and we take the number. Two# runs at once, or a run alongside a dev stack on 3000, never collide.free_port() { python3 - <<'PY'import sockets = socket.socket()s.bind(("127.0.0.1", 0))print(s.getsockname()[1])s.close()PY}
# Waits for a server to answer /health, naming it if it never does.await_health() { local name="$1" base="$2" log="$3" waited=0 while ! curl -sf --cacert "$CA" "$base/health" >/dev/null 2>&1; do waited=$((waited + 1)) if [ "$waited" -gt 200 ]; then echo "test-policy-e2e: $name never answered at $base" >&2 tail -30 "$log" >&2 return 1 fi sleep 0.25 done}
export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$PWD/target}"
# One certificate authority for this run, in the working directory: every# server signs from it and every client here trusts it. Not the machine's# own (scripts/dev-profile.sh) so a run leaves nothing behind.CA_DIR="$WORK/local-ca"CA="$CA_DIR/ca.pem"export DIDBOT_EXTRA_CA_CERTS="$CA"# The stand-in signs from the same authority; see `local_ca` in# crates/didbot/tests/scenarios.rs.export DIDBOT_LOCAL_CA="$CA_DIR"
say "build: didbot-pds, the operator's stand-in PDS and the test that drives them"cargo build --quiet -p didbot-serve --bin didbot-pdscargo build --quiet --tests -p didbot-swarmcargo test --quiet --no-run -p didbot --test scenariosPDS="$CARGO_TARGET_DIR/debug/didbot-pds"
say "build: policy-site/dist, the page and the wasm it checks with"scripts/build-policy-site.sh
OPERATOR_PORT="$(free_port)"GOVERNED_PORT="$(free_port)"SITE_PORT="$(free_port)"# The operator is `did:web:operator.localhost` and not the stand-in's usual# `did:web:localhost%3A<port>`: the atproto libraries the page signs in with# read a DID on bare `localhost` over plain http.OPERATOR_HOST=operator.localhostGOVERNED_URL="https://govzone.localhost:$GOVERNED_PORT"SITE_URL="http://127.0.0.1:$SITE_PORT"# A did:web carries no port, so resolving one means 443 -- and one machine# has one of those. Each zone says where it answers, and every tool here# resolves accordingly.export DIDBOT_RESOLVE_PORTS="$OPERATOR_HOST=$OPERATOR_PORT,govzone.localhost=$GOVERNED_PORT"
say "the operator's own PDS"# The scenarios' stand-in, left running: its PDS, and an OpenID Connect issuer# and a token mint this run does not use, each on a port nobody chose.NEWCOMER_CONFIG="$WORK/operator-config" \NEWCOMER_HUMAN_HOST="$OPERATOR_HOST" \NEWCOMER_HUMAN_PORT="$OPERATOR_PORT" \NEWCOMER_ISSUER_PORT="$(free_port)" \NEWCOMER_MINT_PORT="$(free_port)" \ setsid cargo test --quiet -p didbot --test scenarios the_stand_ins_by_hand \ -- --ignored --nocapture >"$WORK/operator.log" 2>&1 &PIDS+=($!)waited=0until grep -q '^human ' "$WORK/operator.log" 2>/dev/null; do waited=$((waited + 1)) if [ "$waited" -gt 400 ]; then echo "test-policy-e2e: the operator's PDS never started" >&2 tail -30 "$WORK/operator.log" >&2 exit 1 fi sleep 0.25done# `human <did> at <origin>`read -r _ OPERATOR_DID _ OPERATOR_URL <<EOF$(grep '^human ' "$WORK/operator.log")EOFecho "operator: $OPERATOR_DID at $OPERATOR_URL" >&2# Only now: the stand-in has just made the authority, and node warns about a# file that is not there yet on every start before this.export NODE_EXTRA_CA_CERTS="$CA"
say "the governed server on $GOVERNED_PORT, operated by that account"claim_port policy-e2e-governed "$GOVERNED_PORT" didbot-pdsDIDBOT_PDS_DATA= NO_COLOR=1 setsid "$PDS" \ --port "$GOVERNED_PORT" --zone govzone.localhost --tls-ca "$CA_DIR" \ --operator "$OPERATOR_DID" \ >"$WORK/governed.log" 2>&1 &PIDS+=($!)record_pid policy-e2e-governed "$GOVERNED_PORT" "$!"await_health "the governed server" "$GOVERNED_URL" "$WORK/governed.log"
say "the site on $SITE_PORT"# `vite preview` and not a plain file server: it serves dist/ with the deployed# CSP and runs infra/policy-site/viewer-request.js over every path, so a route# like /rollouts resolves the way CloudFront resolves it. 127.0.0.1 and not# localhost, because the atproto loopback client redirects to the former.setsid npm --prefix policy-site run preview -- --port "$SITE_PORT" --strictPort \ >"$WORK/site.log" 2>&1 &PIDS+=($!)waited=0while ! curl -sf "$SITE_URL/" >/dev/null 2>&1; do waited=$((waited + 1)) if [ "$waited" -gt 200 ]; then echo "test-policy-e2e: the site never answered at $SITE_URL" >&2 tail -30 "$WORK/site.log" >&2 exit 1 fi sleep 0.25done
say "the scenario: claim, deploy through the page, roll out, enforce"# The two halves run at once and meet in $HANDOFF: the Rust half claims the# server and writes the post the policy will refuse, the page signs in and# deploys, and the Rust half then watches it enforced. With no browser the# page says so there, and the Rust half deploys the same batch itself.HANDOFF="$WORK/handoff"mkdir -p "$HANDOFF"DIDBOT_E2E_OPERATOR_URL="$OPERATOR_URL" \DIDBOT_E2E_GOVERNED_URL="$GOVERNED_URL" \DIDBOT_E2E_OPERATOR_DID="$OPERATOR_DID" \DIDBOT_E2E_HANDOFF="$HANDOFF" \DIDBOT_E2E_OUT="$WORK/deployed.json" \ setsid cargo test --quiet -p didbot-swarm --test policy_rollout -- --nocapture &ROLLOUT=$!PIDS+=("$ROLLOUT")
# What the browser is told instead of DIDBOT_RESOLVE_PORTS, which it cannot# read: a did:web resolves on 443, and these two zones are not there.RESOLVER_RULES="MAP $OPERATOR_HOST:443 127.0.0.1:$OPERATOR_PORT,MAP govzone.localhost:443 127.0.0.1:$GOVERNED_PORT"
DIDBOT_E2E_SITE_URL="$SITE_URL" \DIDBOT_E2E_HANDOFF="$HANDOFF" \DIDBOT_E2E_DEPLOYED="$WORK/deployed.json" \DIDBOT_E2E_SHOTS="$SHOTS" \DIDBOT_E2E_CA="$CA" \DIDBOT_E2E_RESOLVE="$RESOLVER_RULES" \ node --test policy-site/tests/e2e-policy.mjswait "$ROLLOUT"
say "done"echo "screenshots: $SHOTS" >&2