diff --git a/doc/DEVELOPING.md b/doc/DEVELOPING.md index 320c2f4c..831af15f 100644 --- a/doc/DEVELOPING.md +++ b/doc/DEVELOPING.md @@ -235,6 +235,11 @@ What it validates: - board approval + one-time API key claim semantics - callback delivery on wakeup to a dockerized OpenClaw-style webhook receiver +Required permissions: + +- This script performs board-governed actions (create invite, approve join, wakeup another agent). +- In authenticated mode, run with board auth via `PAPERCLIP_AUTH_HEADER` or `PAPERCLIP_COOKIE`. + Optional auth flags (for authenticated mode): - `PAPERCLIP_AUTH_HEADER` (for example `Bearer ...`) diff --git a/docs/guides/openclaw-docker-setup.md b/docs/guides/openclaw-docker-setup.md index c816bd66..5812be1b 100644 --- a/docs/guides/openclaw-docker-setup.md +++ b/docs/guides/openclaw-docker-setup.md @@ -20,6 +20,11 @@ The harness automates: By default, this uses a preconfigured Docker receiver image (`docker/openclaw-smoke`) so the run is deterministic and requires no manual OpenClaw config edits. +Permissions note: + +- The harness performs board-governed actions (invite creation, join approval, wakeup of the new agent). +- In authenticated mode, provide board/operator auth or the run exits early with an explicit permissions error. + ### Authenticated mode If your Paperclip deployment is `authenticated`, provide auth context: diff --git a/scripts/smoke/openclaw-join.sh b/scripts/smoke/openclaw-join.sh index b073f2c3..d5da01c2 100755 --- a/scripts/smoke/openclaw-join.sh +++ b/scripts/smoke/openclaw-join.sh @@ -43,6 +43,21 @@ fail() { exit 1 } +fail_board_auth_required() { + local operation="$1" + echo "$RESPONSE_BODY" >&2 + cat >&2 <\" + PAPERCLIP_COOKIE=\"\" + +Current auth context appears insufficient (HTTP ${RESPONSE_CODE}). +EOF + exit 1 +} + cleanup() { if [[ "$STARTED_CONTAINER" == "1" ]]; then docker rm -f "$SMOKE_CONTAINER_NAME" >/dev/null 2>&1 || true @@ -147,6 +162,9 @@ fi log "creating agent-only invite for company ${COMPANY_ID}" INVITE_PAYLOAD="$(jq -nc '{allowedJoinTypes:"agent",expiresInHours:24}')" api_request "POST" "/companies/${COMPANY_ID}/invites" "$INVITE_PAYLOAD" +if [[ "$RESPONSE_CODE" == "401" || "$RESPONSE_CODE" == "403" ]]; then + fail_board_auth_required "Invite creation" +fi assert_status "201" INVITE_TOKEN="$(assert_json_has_string '.token')" INVITE_ID="$(assert_json_has_string '.id')" @@ -192,6 +210,9 @@ fi log "approving join request ${JOIN_REQUEST_ID}" api_request "POST" "/companies/${COMPANY_ID}/join-requests/${JOIN_REQUEST_ID}/approve" "{}" +if [[ "$RESPONSE_CODE" == "401" || "$RESPONSE_CODE" == "403" ]]; then + fail_board_auth_required "Join approval" +fi assert_status "200" CREATED_AGENT_ID="$(assert_json_has_string '.createdAgentId')" @@ -221,6 +242,9 @@ fi log "triggering wakeup for newly created OpenClaw agent" WAKE_PAYLOAD='{"source":"on_demand","triggerDetail":"manual","reason":"openclaw_smoke"}' api_request "POST" "/agents/${CREATED_AGENT_ID}/wakeup" "$WAKE_PAYLOAD" +if [[ "$RESPONSE_CODE" == "401" || "$RESPONSE_CODE" == "403" ]]; then + fail_board_auth_required "Agent wakeup" +fi assert_status "202" RUN_ID="$(jq -r '.id // empty' <<<"$RESPONSE_BODY")" if [[ -z "$RUN_ID" ]]; then