## Summary Deploys strfry (C++ Nostr relay) + relay-policy sidecar as a containerised stack on the VPS, wired to the API server for event-level access control. ## Files created - `infrastructure/strfry.conf` — strfry config: bind 0.0.0.0:7777, writePolicy plugin → /usr/local/bin/relay-policy-plugin, maxEventSize 65536, rejectEphemeral false, db /data/strfry-db - `infrastructure/relay-policy/plugin.sh` — strfry write-policy plugin (stdin/stdout bridge). Reads JSON lines from strfry, POSTs to relay-policy HTTP sidecar (http://relay-policy:3080/decide), writes decision to stdout. Safe fallback: reject on sidecar timeout/failure - `infrastructure/relay-policy/index.ts` — Node.js HTTP relay-policy sidecar: POST /decide receives strfry events, calls API server /api/relay/policy with Bearer RELAY_POLICY_SECRET, returns strfry decision JSON - `infrastructure/relay-policy/package.json + tsconfig.json` — TS build config - `infrastructure/relay-policy/Dockerfile` — multi-stage: builder (tsc) + runtime - `infrastructure/relay-policy/.gitignore` — excludes node_modules, dist - `artifacts/api-server/src/routes/relay.ts` — POST /api/relay/policy: internal route protected by RELAY_POLICY_SECRET Bearer token. Bootstrap state: rejects all events with "relay not yet open — whitelist pending (Task #37)". Stable contract — future tasks extend evaluatePolicy() without API shape changes ## Files modified - `infrastructure/docker-compose.yml` — adds relay-policy + strfry services on node-net; strfry_data volume (bind-mounted at /data/strfry); relay-policy healthcheck; strfry depends on relay-policy healthy - `infrastructure/ops.sh` — adds relay:logs, relay:restart, relay:status commands - `artifacts/api-server/src/routes/index.ts` — registers relayRouter ## Operator setup required on VPS mkdir -p /data/strfry && chmod 700 /data/strfry echo "RELAY_API_URL=https://alexanderwhitestone.com" >> /opt/timmy-node/.env echo "RELAY_POLICY_SECRET=$(openssl rand -hex 32)" >> /opt/timmy-node/.env # Also set RELAY_POLICY_SECRET in Replit secrets for API server ## Notes - TypeScript: 0 errors (API server + relay-policy sidecar both compile clean) - POST /api/relay/policy smoke test: correct bootstrap reject response - strfry image: ghcr.io/hoytech/strfry:latest
37 lines
1.3 KiB
Bash
Executable File
37 lines
1.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
##
|
|
## relay-policy-plugin — strfry write-policy plugin
|
|
##
|
|
## strfry starts this script once and feeds it JSON lines on stdin (one per
|
|
## event). The script forwards each line to the relay-policy HTTP sidecar and
|
|
## echoes the sidecar's JSON decision to stdout. If the sidecar is unavailable
|
|
## the event is rejected with a safe fallback so the relay does not accept
|
|
## unapproved events during a transient outage.
|
|
##
|
|
## stdin format: {"event":{...},"receivedAt":N,"sourceType":"...","sourceInfo":"..."}
|
|
## stdout format: {"id":"<event-id>","action":"accept|reject|shadowReject","msg":"..."}
|
|
##
|
|
|
|
RELAY_POLICY_URL="${RELAY_POLICY_URL:-http://relay-policy:3080/decide}"
|
|
|
|
while IFS= read -r line; do
|
|
# Extract event id for the fallback response — pure bash, no external tools.
|
|
event_id=$(printf '%s' "$line" \
|
|
| grep -o '"id":"[^"]*"' \
|
|
| head -1 \
|
|
| sed 's/"id":"//; s/"//')
|
|
|
|
decision=$(printf '%s' "$line" \
|
|
| curl -sf --max-time 5 \
|
|
-X POST "$RELAY_POLICY_URL" \
|
|
-H "Content-Type: application/json" \
|
|
--data-binary @- 2>/dev/null)
|
|
|
|
if [[ -z "$decision" ]]; then
|
|
printf '{"id":"%s","action":"reject","msg":"policy service unavailable"}\n' \
|
|
"${event_id:-unknown}"
|
|
else
|
|
printf '%s\n' "$decision"
|
|
fi
|
|
done
|