Files
Grant 7a1c70ab9b Add onboarding doc-test harness
Disposable rig that runs the global onboarding-tester agent against the
developer SDK-integration journey: boots a fresh keysat fixture, mints a
merchant-onboard scoped key, serves keysat-docs as the published corpus,
scaffolds a pristine Next.js/TS proof-of-work, and has the agent gate it
docs-only. Stage 1 (no payments) reached completed-clean over three runs;
see onboarding-harness/STAGE1-RESULT.md. Stage 2 (regtest buyer-pays) is
gated on the agent-payment-connect scope work.
2026-06-16 22:48:09 -05:00

58 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Shared config + helpers for the Keysat onboarding harness.
# Sourced by the stage scripts; not run directly.
set -euo pipefail
HARNESS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# onboarding-harness/ -> licensing-service-startos/ -> workspace root
WORKSPACE="$(cd "$HARNESS_DIR/../.." && pwd)"
DAEMON_DIR="$WORKSPACE/licensing-service-startos/licensing-service"
DAEMON_BIN="$DAEMON_DIR/target/release/keysat"
DOCS_DIR="$WORKSPACE/keysat-docs"
TEMPLATE_DIR="$HARNESS_DIR/sandbox-template"
# Per-run scratch lives under runs/ (gitignored). The agent's sandbox copy
# lives under /tmp/onboarding-tester/ per the onboarding-tester guide.
RUNS_DIR="$HARNESS_DIR/runs"
SANDBOX_BASE="/tmp/onboarding-tester"
# The active run's state file is pointed to by runs/current.
CURRENT_LINK="$RUNS_DIR/current"
log() { printf '\033[1;34m[harness]\033[0m %s\n' "$*" >&2; }
ok() { printf '\033[1;32m[ ok ]\033[0m %s\n' "$*" >&2; }
warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*" >&2; }
die() { printf '\033[1;31m[fail]\033[0m %s\n' "$*" >&2; exit 1; }
# state_set KEY VALUE — append/update a KEY=VALUE line in the run state file.
# Not concurrency-safe (uses a fixed temp suffix); the stages call it serially.
state_set() {
local f="$1" k="$2" v="$3"
touch "$f"
# strip any existing line for this key, then append
grep -v "^${k}=" "$f" > "$f.tmp" 2>/dev/null || true
mv "$f.tmp" "$f"
printf '%s=%s\n' "$k" "$v" >> "$f"
}
# state_get FILE KEY
state_get() { grep "^${2}=" "$1" | head -1 | cut -d= -f2-; }
# free_port — echo an unused TCP port on 127.0.0.1.
free_port() {
node -e 'const s=require("net").createServer();s.listen(0,"127.0.0.1",()=>{console.log(s.address().port);s.close();});'
}
# wait_http URL TRIES — poll until URL returns 2xx/3xx, or die.
wait_http() {
local url="$1" tries="${2:-50}" i
for i in $(seq 1 "$tries"); do
if curl -fsS -o /dev/null "$url" 2>/dev/null; then return 0; fi
sleep 0.2
done
return 1
}
require() { command -v "$1" >/dev/null 2>&1 || die "missing required tool: $1"; }