miteclaw-cross-repo-e2e
Cross-repo end-to-end harness for the W17.1 Marketplace Web POST Bridge.
This repo owns no production code. Its only job is to verify the contract between three independent repos:
| Repo | Role | Contract surface |
|---|---|---|
miteclaw | Gateway + Arena (this org's monorepo) | internal/auth.IssueArenaDelegateToken, internal/gateway.NewJWTVerifier |
miteclaw-marketplace | Web BFF (Cloudflare deploy) | requestDelegateToken, createAgentListing |
miteclaw-cross-repo-e2e (this repo) | In-process E2E test harness | n/a |
The test harness does not stand up the full production stack. It boots two in-process HTTP servers (an Arena mint stub + a minimal Gateway verify stub) and a small Go test that exercises the end-to-end flow over real HTTP. The Marketplace BFF side is verified by its own vitest suite in miteclaw-marketplace; this repo verifies that the contracts hold on the wire.
Running
The harness is a Go module that consumes the miteclaw repo via a replace directive. Place it as a sibling of the miteclaw checkout (or point MITECLAW_REPO at the on-disk path):
git clone https://github.com/vpnv6786/miteclaw.git
git clone https://github.com/vpnv6786/miteclaw-cross-repo-e2e.git
cd miteclaw-cross-repo-e2e
MITECLAW_REPO=../miteclaw go test ./tests/... -race -vOr use the convenience script:
./scripts/run.shWhat's verified
The 11 E2E cases live in tests/marketplace_post_bridge_e2e_test.go. They cover:
- Happy-path mint → verify → POST listing → 201 receipt
- JWT signature validity (Arena signs, Gateway verifies)
iss == arenaclaimaud == marketplace-webclaim (positive + negative)scope == avatar:listingclaim (positive + negative)sub == local-api:<hex64>shapeexp > now(positive + expired)jtireplay protection- Idempotency replay semantics (
idempotency_replay: trueon second call) - Schema anchor (listing_id, agent_version_id, owner_subject, manifest_digest patterns)
- Missing service token → Arena mint refuses (401, no envelope)
Staging smoke (W17.1.1)
tests/staging_smoke_test.go is the staging smoke suite for the W17.1.1 mutations rollout (CC-1 … CC-8, one case per row of the miteclaw test matrix docs/harness/test-matrix/marketplace-mutations-flip.md, MFL-001…008). It runs against live staging HTTP endpoints — the real Arena mint wire, the real Gateway listing handler, and the real Marketplace BFF tRPC surface — so it needs no miteclaw checkout, but it must never run blind.
OFF BY DEFAULT. Every case t.Skips unless its SMOKE_* environment variables are exported. No secret is ever committed; values come from your shell or a CI secrets store.
| Case | Verifies | Requires |
|---|---|---|
| CC-1 | Real Arena mint returns RS256 JWT with anchored claims (iss=arena, aud=marketplace-web, sub=local-api:<hex64>, scope=[avatar:listing], TTL≤15m, jti) | SMOKE_ARENA_DELEGATE_URL, SMOKE_SERVICE_TOKEN |
| CC-2 | ACK unset → readiness auth_bridge_pending, mutation refused 412, no mint | + SMOKE_MARKETPLACE_BASE_URL, SMOKE_SESSION_JWT, listing inputs |
| CC-3 | Rate-limit burst → 429 (production capacity 30/60s; SMOKE_RATE_LIMIT_CAPACITY overrides) | mode mutations_ready |
| CC-4 | Kill switch → policy_gate_blocked, 2 mutations refused 412, reads stay up | mode policy_gate_blocked |
| CC-5 | Expired / garbage delegated JWT → Gateway 401 owner_unresolved, no fallback write | + SMOKE_RELAY_BASE_URL, listing inputs |
| CC-6 | Deny path leaves no write (blank evidence ref → 400 invalid_request / 403 commerce_gate_denied), never 201 | same as CC-5 |
| CC-7 | Post-ACK flip → mutations_ready + live happy path (ok:true, or idempotent 412 re-run) | mode mutations_ready |
| CC-8 | SLO drill: SMOKE_SLO_SAMPLES mint+mutation samples, P95 mint ≤2s / mutation ≤3s, 0% errors, markdown report (evidence §3/§5) | same as CC-5 |
Environment contract
Required (a case skips with a precise message when its inputs are unset):
| Variable | Shape |
|---|---|
SMOKE_MARKETPLACE_BASE_URL | https://<staging-marketplace> (BFF tRPC root) |
SMOKE_RELAY_BASE_URL | https://<staging-relay> (Gateway root) |
SMOKE_ARENA_DELEGATE_URL | https://<staging-arena>/api/v1/arena/auth/delegate-token |
SMOKE_SERVICE_TOKEN | Arena service token (secret) |
SMOKE_SESSION_JWT | Marketplace web session JWT (secret) |
SMOKE_AGENT_VERSION_ID | av_[a-f0-9]{32} |
SMOKE_EXPECTED_DIGEST | sha256:[a-f0-9]{64} |
Optional: SMOKE_OWNER_SUBJECT (default local-api:000…0), SMOKE_SLO_SAMPLES (30), SMOKE_RATE_LIMIT_CAPACITY (30), SMOKE_EXPECT_MODE (pin a mode — mismatch is a hard failure, not a skip), SMOKE_HTTP_TIMEOUT_SECONDS (15), SMOKE_REPORT_FILE (write the CC-8 report, mode 0600 — keep the path outside this repo).
Running
export SMOKE_MARKETPLACE_BASE_URL=… SMOKE_RELAY_BASE_URL=… \
SMOKE_ARENA_DELEGATE_URL=… SMOKE_SERVICE_TOKEN=… \
SMOKE_SESSION_JWT=… SMOKE_AGENT_VERSION_ID=… SMOKE_EXPECTED_DIGEST=…
./scripts/run-staging-smoke.sh # warns on unset vars, then runs CC-1…CC-8CC-2/CC-4/CC-7 are ops drills tied to a staged state: without SMOKE_EXPECT_MODE they skip unless readiness already reports the expected mode. The harness never setsMARKETPLACE_STAGING_EVIDENCE_ACK or MARKETPLACE_POLICY_GATE — the ACK flip is a human-only decision (decision record M3); the suite only observes and asserts mode-consistent behavior.
Staging round-trip smoke (W18 M7 / W19)
tests/roundtrip_smoke_test.go is the round-trip smoke suite for the Arena↔Marketplace purchase flow (CC-9 … CC-12, one case per row of the miteclaw test matrix docs/harness/test-matrix/arena-marketplace-roundtrip.md, MFL-015…018). It exercises the reverse direction of the contract: Marketplace emits purchase.completed (miteclaw.marketplace.purchase-completed.v1) into its durable outbox (design.md §1.2), Arena polls the outbox read endpoint (§1.3), verifies the purchase:admit service token (iss=marketplace-bff, aud=arena-admission, scope=purchase:admit, jti=event_id, exp 30d — M3), and runs W20 AdmitFromPurchase's three guard layers (§2.1: processed_events PK, state-machine guard, drift re-poll). The Arena-side store lives in miteclaw/internal, so harness/roundtrip.go re-implements the guard logic as a pure function over observed staging state — a production drift surfaces as a contract failure.
OFF BY DEFAULT. Every case t.Skips unless the round-trip SMOKE_* environment variables are exported. No secret is ever committed.
| Case | Verifies | Requires |
|---|---|---|
| CC-9 | Outbox emit → Arena poll → verify claims (iss/aud/scope/jti=event_id/sub) → admit; Arena-side audit set emitted (dual-entry with Marketplace audit.purchase.completed, host-side) | SMOKE_PURCHASE_EVENT_URL, SMOKE_PURCHASE_FIXTURE |
| CC-10 | Replay event (processed_events PK hit) → cached 200, no re-commit, no double audit | SMOKE_PURCHASE_EVENT_URL (+ fixture to pin target) |
| CC-11 | Drift: listing state ≠ purchased → effect_outcome_unknown, no admit, audit.purchase.drift.detected, human reconcile (no auto-rollback) | SMOKE_PURCHASE_EVENT_URL (+ SMOKE_LISTING_STATE_URL or fixture listing_state) |
| CC-12 | SLO drill: round-trip P95 ≤ 5.0s (after SMOKE_POLL_INTERVAL_SECONDS, default 30), 0% errors, markdown report; outbox-write ≤500ms + audit dual-entry ≤1.0s are host-side rows | both + fixture |
Environment contract (round-trip)
Required (a case skips with a precise message when its inputs are unset):
| Variable | Shape |
|---|---|
SMOKE_PURCHASE_EVENT_URL | https://<staging-marketplace>/api/marketplace/outbox/purchase-events (read endpoint, §1.3) |
SMOKE_PURCHASE_FIXTURE | JSON file: `{"agent_version_id":"av_<hex32>", "owner_subject":"local-api:<hex64>"?, "status":"purchased"?, "listing_state":"purchased |
Optional: SMOKE_OUTBOX_READ_TOKEN (Arena's long-lived read token, aud=marketplace-outbox-read, scope=outbox:read — sent as Bearer when set), SMOKE_LISTING_STATE_URL (Marketplace listing-state base for the live CC-11 drift re-poll), SMOKE_POLL_INTERVAL_SECONDS (30; mirrors production ARENA_POLL_INTERVAL_SECONDS), SMOKE_SLO_SAMPLES (30, inherited from CC-8), SMOKE_HTTP_TIMEOUT_SECONDS (15), SMOKE_REPORT_FILE (write the CC-12 report, mode 0600 — keep the path outside this repo).
Running (round-trip)
export SMOKE_PURCHASE_EVENT_URL=… SMOKE_PURCHASE_FIXTURE=/path/to/fixture.json
./scripts/run-roundtrip-smoke.sh # warns on unset vars, then runs CC-9…CC-12CC-9/CC-12 require a staged purchased fixture; CC-11 additionally needs a non-purchased listing state (live or fixture-pinned) — without it the case skips as not staged. The harness never setsMARKETPLACE_STAGING_EVIDENCE_ACK or MARKETPLACE_POLICY_GATE (same human-only invariant as the CC-1…CC-8 suite).
Maintenance
This repo is intentionally small. Changes here should be limited to contract tests. If a new repo joins the cross-repo contract (e.g. a dedicated owner-bridge), add a harness/<repo>.go stub and extend the test file with a contract case.
Status
- W17.1 (Marketplace Web POST Bridge): under test (11 contract cases).
- W17.1.1 (mutations rollout): staging smoke suite delivered (CC-1…CC-8, off-by-default); live drills run during ops Phases 3–5.
- W19/W20 (Arena↔Marketplace round-trip): design packet delivered in
miteclaw(PR #1318, merged); round-trip smoke skeleton (CC-9…CC-12, off-by-default) delivered here — live drills run post-M8 (W17.1.1 ops Phases 3–7 complete,mutationsEnabled: trueproduction ≥ 1 monitor cycle).