From 7baaec7db6e1ac841bbfaa1482bda596bd8eb2af Mon Sep 17 00:00:00 2001 From: vansin Date: Sun, 28 Jun 2026 08:40:35 +0800 Subject: [PATCH] =?UTF-8?q?fix(#268):=20align=20qa-*=20test=20from=5Fsessi?= =?UTF-8?q?on=20with=20ntok-bound=20alias=20=E2=80=94=20restore=2013/13=20?= =?UTF-8?q?L1=20green?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After #265 cleared the safe-rm.sh cascade, 4 L1 contract tests surfaced as failing with one shared signature: {"ok":false, "error":"from_session_identity_mismatch", "message":"network token from_session does not match token-bound node alias"} Root cause: bf564fb (#203 fix, 2026-05-28) tightened the server-side check so that an NTOK request's `from_session` must match the alias the NTOK is bound to. Four qa-* tests pre-date that fix and still send the wrong value: | test | NTOK bound to | was | now | |---------------------------------------------|---------------------|------------------|----------------------| | qa-hub-09-task-state-machine | agent-09 | "admin" | "agent-09" | | qa-hub-06b-cross-user-isolation | alice-agent | "alice" | "alice-agent" | | qa-dash-08-cross-account-views | alice-secret-agent | "alice" | "alice-secret-agent" | | qa-dash-10-incremental-poll | dash10-agent | "admin" | "dash10-agent" | Verified real isolation contract still intact: ran patched qa-hub-06b and all 11 PINs PASS — bob still gets 403/400 on every cross-tenant probe (networks list / tasks list / status / messages / direct IDOR / inject / mint). The #203 identity check has been silently doing its job throughout; these tests were just sending nonsense values that the cascade hid. Also fixed `[[ -n "$TASK_ID" ]]` null-guard in qa-dash-08: `jq -r .message_id` emits the literal string "null" when the field is missing, so `-n null` is true and the test would proceed with TASK_ID="null", causing send_reply to fail with garbage in_reply_to and the failure to be mis-attributed. Tightened to `[[ -n "$TASK_ID" && "$TASK_ID" != "null" ]]` so the assertion fails at the actual point of breakage. Local verification — all 4 cases now PASS in Docker: qa-hub-09-task-state-machine → PASS (replied/failed/cancelled + terminal no-op) qa-hub-06b-cross-user-isolation → PASS (all 11 isolation PINs incl. IDOR/inject/mint) qa-dash-08-cross-account-views → PASS (nodes/stats/completions/tasks/tokens/task_events) qa-dash-10-incremental-poll → PASS (since= filter on both endpoints + format gap pinned) After this merges, main `anet QA (v0)` should be 13/13 PASS — first green since 826c8a7 (12 days, 133 commits). Out of scope: a broader null-guard hygiene sweep across other tests (`jq -r .field` returns "null") — recorded against #268 as a follow-up hygiene task, not gated on this PR. Refs: #268 (4 L1 fails surfaced after #265), #265 (cascade fix), #257 --- tests/qa-dash-08-cross-account-views/run.sh | 4 ++-- tests/qa-dash-10-incremental-poll/run.sh | 2 +- tests/qa-hub-06b-cross-user-isolation/run.sh | 2 +- tests/qa-hub-09-task-state-machine/run.sh | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/qa-dash-08-cross-account-views/run.sh b/tests/qa-dash-08-cross-account-views/run.sh index ad8406c2..9d00ce65 100644 --- a/tests/qa-dash-08-cross-account-views/run.sh +++ b/tests/qa-dash-08-cross-account-views/run.sh @@ -86,9 +86,9 @@ mcp_call "$ALICE_NTOK" "report_status" "$ARG" | jq -e '.ok == true' >/dev/null \ || { echo "FAIL: alice report_status"; exit 1; } # dispatch + reply (so /api/completions gets a row) ARG=$(jq -nc --arg net "$ALICE_NET" \ - '{alias:"alice-secret-agent",task:"alice-confidential-task",priority:"normal",network_id:$net,from_session:"alice"}') + '{alias:"alice-secret-agent",task:"alice-confidential-task",priority:"normal",network_id:$net,from_session:"alice-secret-agent"}') TASK_ID=$(mcp_call "$ALICE_NTOK" "send_task" "$ARG" | jq -r '.message_id') -[[ -n "$TASK_ID" ]] || { echo "FAIL: no task id"; exit 1; } +[[ -n "$TASK_ID" && "$TASK_ID" != "null" ]] || { echo "FAIL: no task id"; exit 1; } ARG=$(jq -nc --arg t "$TASK_ID" \ '{alias:"alice",text:"alice-private-reply-text",in_reply_to:$t,status:"replied",from_session:"alice-secret-agent"}') mcp_call "$ALICE_NTOK" "send_reply" "$ARG" | jq -e '.ok == true' >/dev/null \ diff --git a/tests/qa-dash-10-incremental-poll/run.sh b/tests/qa-dash-10-incremental-poll/run.sh index 958aab89..4a0d5bcd 100644 --- a/tests/qa-dash-10-incremental-poll/run.sh +++ b/tests/qa-dash-10-incremental-poll/run.sh @@ -79,7 +79,7 @@ mcp_call "$NTOK" "report_status" "$ARG" | jq -e '.ok == true' >/dev/null \ do_send() { local text="$1" ARG=$(jq -nc --arg net "$NET_ID" --arg t "$text" \ - '{alias:"dash10-agent",task:$t,priority:"normal",network_id:$net,from_session:"admin"}') + '{alias:"dash10-agent",task:$t,priority:"normal",network_id:$net,from_session:"dash10-agent"}') mcp_call "$NTOK" "send_task" "$ARG" | jq -r '.message_id' } diff --git a/tests/qa-hub-06b-cross-user-isolation/run.sh b/tests/qa-hub-06b-cross-user-isolation/run.sh index 880a6514..f4181edb 100644 --- a/tests/qa-hub-06b-cross-user-isolation/run.sh +++ b/tests/qa-hub-06b-cross-user-isolation/run.sh @@ -94,7 +94,7 @@ mcp_call "$ALICE_NTOK" "report_status" "$ARG" | jq -e '.ok == true' >/dev/null \ echo "[3] alice sends a 'top-secret-alice' task to alice-agent" ARG=$(jq -nc --arg a "alice-agent" --arg t "top-secret-alice-payload" --arg net "$ALICE_NET" \ - '{alias:$a,task:$t,priority:"normal",network_id:$net,from_session:"alice"}') + '{alias:$a,task:$t,priority:"normal",network_id:$net,from_session:"alice-agent"}') mcp_call "$ALICE_NTOK" "send_task" "$ARG" | jq -e '.message_id' >/dev/null \ || { echo "FAIL: alice send_task"; exit 1; } diff --git a/tests/qa-hub-09-task-state-machine/run.sh b/tests/qa-hub-09-task-state-machine/run.sh index 040bcdf6..751839aa 100644 --- a/tests/qa-hub-09-task-state-machine/run.sh +++ b/tests/qa-hub-09-task-state-machine/run.sh @@ -128,7 +128,7 @@ echo "[5] BRANCH cancelled: send → cancel_task" T_CXL=$(send_task "$UTOK" "$NET_ID" "agent-09" "task-cancelled") [[ "$(task_field "$UTOK" "$NET_ID" "$T_CXL" status)" == "delivered" ]] || \ { echo "FAIL: cancel PRE != delivered"; exit 1; } -ARG=$(jq -nc --arg t "$T_CXL" '{task_id:$t,reason:"user changed mind",from_session:"admin"}') +ARG=$(jq -nc --arg t "$T_CXL" '{task_id:$t,reason:"user changed mind",from_session:"agent-09"}') # cancel_task needs a network-scoped writer (canWrite). Use NTOK (which is # bound to NET_ID) — agent-09 cancelling a task targeted at itself. CXL_RESP=$(mcp_call "$NTOK" "cancel_task" "$ARG") @@ -163,7 +163,7 @@ sleep 0.2 { echo "FAIL: terminal task.status changed on second send_reply"; exit 1; } echo "[8] PIN: cancel_task on already-cancelled task returns ok:false" -ARG=$(jq -nc --arg t "$T_CXL" '{task_id:$t,reason:"again",from_session:"admin"}') +ARG=$(jq -nc --arg t "$T_CXL" '{task_id:$t,reason:"again",from_session:"agent-09"}') CXL2=$(mcp_call "$NTOK" "cancel_task" "$ARG") # cancel_task's WHERE excludes terminal states → changes=0 → ok:false echo "$CXL2" | jq -e '.ok == false' >/dev/null \