From 99087a41c4a5b2920f7250f8fdce1d5bdb5c9eab Mon Sep 17 00:00:00 2001 From: core-devops Date: Fri, 5 Jun 2026 11:54:13 -0700 Subject: [PATCH] fix(e2e): surface/fix saas step-9 HMA memory POST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 9/11 'Writing + reading HMA memory on parent' failed in staging-saas run 223471 with a bare '❌ memory POST failed' — the curl exited 22 (HTTP 500 under --fail-with-body) but the call piped its body to /dev/null, so the workspace-server error body was discarded. This is the same #2310-class opacity: we saw the status only via curl's stderr line ('curl: (22) The requested URL returned error: 500') and nothing about WHICH 500 path fired. The POST /workspaces/:id/memories handler returns 500 from exactly two branches — 'failed to resolve writable namespaces' and 'failed to store memory' (plugin write) — and 503 for 'memory plugin is not configured'. Distinguishing them requires the response body, which the test threw away. The payload ({content, scope:LOCAL}) matches the handler contract, so this is NOT a stale-endpoint/payload bug (that would be 400). Fix (test-only): capture http_code (-w) + body (-o) for both the memory write and the read-back, mirroring the already-hardened step-9b/A2A pattern, and fail with the sanitized status+body. Next staging-saas run will print the exact 500 body so the underlying mechanism (namespace resolve vs plugin write) can be named. Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/e2e/test_staging_full_saas.sh | 40 ++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/tests/e2e/test_staging_full_saas.sh b/tests/e2e/test_staging_full_saas.sh index 01ddfb9db..f347ca17f 100755 --- a/tests/e2e/test_staging_full_saas.sh +++ b/tests/e2e/test_staging_full_saas.sh @@ -1434,12 +1434,44 @@ print(json.dumps({ 'scope': 'LOCAL' })) ") - tenant_call POST "/workspaces/$PARENT_ID/memories" \ + # SURFACE THE BODY (mirrors the step-9b / A2A pattern): the previous + # `>/dev/null || fail "memory POST failed"` discarded the response body + # that --fail-with-body deliberately preserves on a non-2xx, so a 500 from + # the workspace-server HMA path (e.g. "failed to store memory" / + # "failed to resolve writable namespaces", or a 503 "memory plugin is not + # configured") was reported as a bare "memory POST failed" — opaque, the + # same #2310-class blind spot. Route http_code into -w and body into -o, + # then fail with the sanitized status+body so the mechanism is visible. + MEM_POST_TMP=$(e2e_tmp /tmp/e2e_mem_post.XXXXXX) + set +e + MEM_POST_CODE=$(tenant_call POST "/workspaces/$PARENT_ID/memories" \ -H "Content-Type: application/json" \ - -d "$MEM_PAYLOAD" >/dev/null || fail "memory POST failed" - MEM_LIST=$(tenant_call GET "/workspaces/$PARENT_ID/memories?scope=LOCAL") + -d "$MEM_PAYLOAD" \ + -o "$MEM_POST_TMP" -w "%{http_code}" 2>/dev/null) + MEM_POST_RC=$? + set -e + MEM_POST_CODE=${MEM_POST_CODE:-000} + if [ "$MEM_POST_RC" != "0" ] || [ "$MEM_POST_CODE" -lt 200 ] || [ "$MEM_POST_CODE" -ge 300 ]; then + MEM_POST_BODY=$(head -c 400 "$MEM_POST_TMP" 2>/dev/null | sanitize_http_body) + fail "memory POST /workspaces/$PARENT_ID/memories failed (curl_rc=$MEM_POST_RC, http=$MEM_POST_CODE): ${MEM_POST_BODY:-}" + fi + + # Same fail-closed surfacing for the read-back: a 5xx / network error here + # previously slipped through the bare `$(tenant_call ...)` capture and only + # showed up as "not readable" with an empty list. + MEM_LIST_TMP=$(e2e_tmp /tmp/e2e_mem_list.XXXXXX) + set +e + MEM_LIST_CODE=$(tenant_call GET "/workspaces/$PARENT_ID/memories?scope=LOCAL" \ + -o "$MEM_LIST_TMP" -w "%{http_code}" 2>/dev/null) + MEM_LIST_RC=$? + set -e + MEM_LIST_CODE=${MEM_LIST_CODE:-000} + MEM_LIST=$(cat "$MEM_LIST_TMP" 2>/dev/null || echo "") + if [ "$MEM_LIST_RC" != "0" ] || [ "$MEM_LIST_CODE" -lt 200 ] || [ "$MEM_LIST_CODE" -ge 300 ]; then + fail "memory GET /workspaces/$PARENT_ID/memories failed (curl_rc=$MEM_LIST_RC, http=$MEM_LIST_CODE): $(printf '%s' "$MEM_LIST" | sanitize_http_body | head -c 400)" + fi if ! echo "$MEM_LIST" | grep -q "run $SLUG"; then - fail "HMA memory not readable after write. List: ${MEM_LIST:0:200}" + fail "HMA memory not readable after write (http=$MEM_LIST_CODE). List: $(printf '%s' "$MEM_LIST" | sanitize_http_body | head -c 200)" fi ok "HMA memory write+read roundtripped" -- 2.52.0