From 6068cbab201e34c8bbf2863a423bc8726754ca31 Mon Sep 17 00:00:00 2001 From: Enrico Piovesan Date: Fri, 4 Sep 2026 21:58:38 -0600 Subject: [PATCH] docs(proxy): verified SC-001 end to end; correct RuntimeRequest shape, SERVE_URL hostname requirement Ran the full pipeline for real against a live Oracle Cloud VM (serve.traverse-framework.com): browser-style client -> Worker (no credentials) -> serve -> a signed public capability -> real execution result. Two things learned the hard way, now documented: - README Step 4's example request body was the flat capability-input shape, not a real traverse-runtime::RuntimeRequest envelope (kind/schema_version/ request_id/intent/input/lookup/context/governing_spec). serve rejects the flat shape with invalid_runtime_request. Corrected the example and the intent/context field requirements (capability_id/version must match the outer envelope exactly, requested_target must be a placement the paired serve's executor set supports -- "local" for a plain CLI host). - wrangler.toml's SERVE_URL must be a hostname, never a bare IP -- a Worker's outbound fetch() to a raw IP fails closed with Cloudflare edge error 1003 (confirmed against multiple Cloudflare community reports, not guessed). Documented the fix (one DNS-only A record) and recorded the real, live SERVE_URL now in use. - FR-003 rate limiting did not trigger on 6 rapid calls immediately after a fresh deploy; flagged as needing a retest after the binding has had time to propagate, not blocking SC-001. Registry side of registry#328 is done: the runbook now reflects exactly what a real deployment needs. Co-Authored-By: Claude Sonnet 5 --- proxy/README.md | 68 +++++++++++++++++++++++++++++++++++---------- proxy/wrangler.toml | 8 ++++-- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/proxy/README.md b/proxy/README.md index b00ece3..5fc1fce 100644 --- a/proxy/README.md +++ b/proxy/README.md @@ -152,6 +152,15 @@ wrangler secret put ADMIN_JWT wrangler deploy ``` +**`SERVE_URL` MUST be a hostname, never a raw IP address.** A Worker's +outbound `fetch()` to a bare IP literal fails closed with Cloudflare edge +error `1003` ("Direct IP Access Not Allowed") — confirmed directly, not +assumed, after it broke a real deployment. If your `serve` VM has no domain +of its own, add one A record for it (e.g. `serve.yourdomain.com → `, +proxy status **DNS only** — it must resolve to the real IP, not a +Cloudflare-proxied one) at any DNS provider, and point `SERVE_URL` at that +hostname instead. + `wrangler deploy` provisions the `[[ratelimits]]` binding declared in `wrangler.toml` automatically on first deploy; if `namespace_id = "1"` collides with an existing rate limiter in your account, wrangler's error @@ -159,6 +168,17 @@ will say so — pick a different number and redeploy. ## Step 4 — Verify (spec 020 SC-001) +Verified working end to end 2026-08-30/31 against a real Oracle Cloud +`serve` instance. The `request` field is **not** the raw capability input — +it must be a full `traverse-runtime::RuntimeRequest` envelope +(`crates/traverse-runtime/src/lib.rs`, `traverse-framework/traverse`). +`intent.capability_id`/`intent.capability_version` must exactly match the +outer `id`/`version`, `intent.version_range` must be absent, and +`context.requested_target` must name a placement the paired `serve` +instance's executor set actually supports (`local` for a plain +`traverse-cli serve` host; `browser` fails closed with +`placement_unsupported` there). + ```bash curl -s -X POST https://.workers.dev/execute \ -H 'Content-Type: application/json' \ @@ -167,27 +187,47 @@ curl -s -X POST https://.workers.dev/execute \ "id": "core.transition-action-status", "version": "1.4.0", "request": { - "action_item_id": "item-001", - "actor_id": "user-ada", - "owner_id": "user-ada", - "current_status": "open", - "requested_status": "in_progress", - "transition_config": { - "version": "1.0", - "allowed_transitions": {"open": ["in_progress"]}, - "owner_only": true - } + "kind": "runtime_request", + "schema_version": "1.0.0", + "request_id": "sc001-verify-001", + "intent": { + "capability_id": "core.transition-action-status", + "capability_version": "1.4.0" + }, + "input": { + "action_item_id": "item-001", + "actor_id": "user-ada", + "owner_id": "user-ada", + "current_status": "open", + "requested_status": "in_progress", + "transition_config": { + "version": "1.0", + "allowed_transitions": {"open": ["in_progress"]}, + "owner_only": true + } + }, + "lookup": { + "scope": "public_only", + "allow_ambiguity": false + }, + "context": { + "requested_target": "local" + }, + "governing_spec": "006-runtime-request-execution" } }' ``` -A genuine execution result (not an error) with no credential of any kind -supplied by the caller is exactly SC-001. Also worth checking: +A genuine `"status": "completed"` execution result (not an error) with no +credential of any kind supplied by the caller is exactly SC-001. Also worth +checking: - A request naming a deprecated or nonexistent capability gets `capability_not_found`, not a call to `serve` (SC-002). -- Six rapid requests from the same IP: the sixth gets `rate_limited` (FR-003, - 5/minute). +- Six rapid requests from the same IP: the sixth should get `rate_limited` + (FR-003, 5/minute). Observed *not* enforcing on the first six calls + immediately after a fresh deploy — retest after the rate-limiter binding + has had a few minutes to propagate before trusting a negative result. - Nothing in any response — success or error — ever contains `ADMIN_JWT`'s value (FR-005). Skim a few real responses to confirm, don't just trust the code. diff --git a/proxy/wrangler.toml b/proxy/wrangler.toml index c0b77be..cea1ba6 100644 --- a/proxy/wrangler.toml +++ b/proxy/wrangler.toml @@ -16,9 +16,11 @@ command = "worker-build --release" # encrypted and keeps it out of source control and out of `wrangler.toml`. [vars] # The traverse-cli serve instance this proxy fronts (traverse specs -# 118/120, --registry-state/--artifact-state). Placeholder until that -# instance is actually running -- see README.md's "Stand up serve" step. -SERVE_URL = "https://REPLACE-WITH-SERVE-HOSTNAME" +# 118/120, --registry-state/--artifact-state). Live as of 2026-08-31 -- +# an Oracle Cloud Always Free VM at serve.traverse-framework.com (an A +# record, DNS-only/not proxied -- see README.md's SERVE_URL note on why +# it must be a hostname, never a bare IP). +SERVE_URL = "http://serve.traverse-framework.com:8787" # Origin(s) allowed to call this proxy directly from browser JS (FR-002's # companion CORS restriction -- see decision-log entry 73). Placeholder # until the actual discover.html-hosting origin is confirmed.