Skip to content

feat(gateway): forwarded headers and triggers by route (FD-4683) - #443

Merged
earakely-scale merged 5 commits into
mainfrom
wloo/website-gateway-auth
Nov 5, 2026
Merged

earakely-scale merged 5 commits into
mainfrom
wloo/website-gateway-auth

Conversation

@williamloo-scale

@williamloo-scale williamloo-scale commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

The gateway side of website/v1: the address a site is reached at, and triggers matched by route. Keyed roles were part of this change and are held back (see below).

  • Forwarded headers. /svc and /website set X-Forwarded-Host, -Proto and -Prefix and drop the client's copies; a front's own X-Forwarded-Host and -Proto win, else the request's Host and scheme. The SDK takes the prefix as the root path, so base_url, request.url and redirects name the gateway's address. Behind the prefix, a site still judges its reserved paths and the clock rule by its own path: a catch-all @api route can't answer /agentenv/..., and with the clock unreadable the card, the data plane and sync_time still answer at /svc/<name>/.
  • Triggers by route. A website trigger's when may name op, a route of the site's card, and then matches only requests that reach it. Registration refuses an op the card doesn't name, and an op on a site whose card can't be read. triggers/v1 declares website_op, so an older gateway is refused. The card's website/v1 routes[].path is now the path the route is served at, converters included (/api/files/{rest:path}), so the gateway matches nested and typed paths.

Held back: keyed roles

One key per deploy let any holder, a deployed agent included, claim any role, and neither the hub nor agentenvhub-sdk sends the key yet. How roles are proven is left for its own design. Here, as on main, the gateway believes the role header alone, and an SDK site, holding no key, treats every caller as default. The earlier commits of this branch keep the version that was here.

Test

  • CI on this head. The protocol suite passed locally (1,207) and lint is clean.
  • End to end on a VM, a local Docker gateway in front of an MCP server and two SDK sites. The run came before keyed roles were held back; the code below is unchanged since.
    • Forwarded headers: the site saw the gateway's host and prefix on /website and /svc. A client's X-Forwarded-Prefix and an invalid -Proto were ignored, and a trailing-slash redirect named the gateway's address. Conformance passed 8 of 8 through /svc.
    • Triggers by route: registration refuses an unknown op, listing the routes, and a non-website app. Op triggers matched GET, POST, HEAD and a nested {rest:path} route. An op trigger on a site whose card was down at registration was refused, then accepted once the site was back.
    • Lost clock: with the clock unreachable, pages behind /svc answered 503 while the card, data/get, ready and sync_time answered, and an unknown reserved path answered 404, not the catch-all.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The reviewed changes appear safe to merge.

Summary

This PR forwards the gateway address to websites and adds triggers that match named website routes.

  • Proxied sites now see the gateway address and path.
  • Website triggers can fire for a named route.

Diagram

sequenceDiagram
    participant Client
    participant Gateway
    participant Website
    participant Triggers
    Client->>Gateway: Request under /website or /svc
    Gateway->>Website: Forward request with gateway address headers
    Website-->>Gateway: Response
    Gateway->>Gateway: Match forwarded path to named route
    Gateway->>Triggers: Evaluate request with route name
    Triggers-->>Gateway: Wait for matching barrier, if any
    Gateway-->>Client: Return response
Loading

Reviews (18) · Last reviewed commit: "refactor(gateway)!: hold keyed roles bac..." · Reviewed by Greptile

@williamloo-scale williamloo-scale changed the title website: gateway role key, forwarded headers, triggers by route (FD-4683) feat(gateway): a keyed deploy's role key, forwarded headers, and triggers by route (FD-4683) Nov 3, 2026
@williamloo-scale
williamloo-scale marked this pull request as ready for review November 3, 2026 00:24
@williamloo-scale
williamloo-scale requested a review from a team as a code owner November 3, 2026 00:24
Comment thread src/agent_env/env/gateway/rest_proxy.py Resolved
Comment thread src/agent_env/env/gateway/gateway.py Resolved
Comment thread src/agent_env/env/gateway/gateway.py Resolved
Comment thread src/agent_env/env/gateway/rest_proxy.py Resolved
@earakely-scale

Copy link
Copy Markdown
Collaborator

A heads-up from #478 (M8.54). The driver's /svc/<app>/ now follows this PR's forwarded-header convention: it drops the caller's X-Forwarded-Host, -Proto and -Prefix and sets its own, and drops hop-by-hop headers and those a Connection header names. That lives in agentenv_protocol.computer.svc (passed_on, to_app), while this PR has its own in env/gateway/rest_proxy.py (HOP_BY_HOP, FORWARDED_*).

Once both merge, could the gateway use the same helpers, so there's one convention to keep in step (which headers drop, how X-Forwarded-Proto is set, a chained proxy's values)? No change needed in this PR; I'm happy to do it as a follow-up.

williamloo-scale and others added 2 commits November 4, 2026 22:17
…gers by route (FD-4683)

This PR's change, rebased as one commit onto #429.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ock are judged by the site's own path

With X-Forwarded-Prefix the prefix leads scope["path"], so the clock's exception for the card and data plane and
the guard that keeps a broad @api route off reserved paths both missed them: through the gateway's /svc/<name>/ a
lost clock answered 503 to agentenv's own data/get, ready and sync_time, and a catch-all route served a page at
/agentenv/x. Both, and the static fallback, now read the path without the root path, as routing does, which also
drops the private starlette._utils import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale force-pushed the wloo/website-gateway-auth branch from 8389f76 to c7f214b Compare November 5, 2026 06:42
@earakely-scale
earakely-scale changed the base branch from wloo/website-notes-example to main November 5, 2026 06:42
@greptile-apps

greptile-apps Bot commented Nov 5, 2026

Copy link
Copy Markdown

Comments Outside Diff

These findings could not be posted inline.

  • P1 Failed checks leave data erased packages/agentenv-protocol/src/agentenv_protocol/website/conformance.py:191 ▶

    _data_plane calls data/reset before entering the try and sets added_back = True before data/add succeeds. If reset clears data but returns an error, or the first add fails before restoring anything, cleanup never retries the saved export. The check reports failure but leaves the site's data missing.

    Put reset inside the protected block and mark the export restored only after add succeeds. Add tests for both failure paths; the existing test covers only a failed read after reset.

earakely-scale and others added 2 commits November 4, 2026 23:12
The rebase onto main was pushed while the pull request still targeted the old stack base, which it conflicted with, so the pull_request workflows never ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…K serves no health path

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Role keys come out of this change: one key per deploy lets any holder, a deployed agent included, claim any role, and neither the hub nor agentenvhub-sdk sends the key yet. Forwarded headers and triggers by route stay. The gateway again believes the role header alone, and an SDK site, holding no key, treats every caller as default, as on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale earakely-scale changed the title feat(gateway): a keyed deploy's role key, forwarded headers, and triggers by route (FD-4683) feat(gateway): forwarded headers and triggers by route (FD-4683) Nov 5, 2026
@earakely-scale
earakely-scale merged commit a730e67 into main Nov 5, 2026
63 of 65 checks passed
@earakely-scale
earakely-scale deleted the wloo/website-gateway-auth branch November 5, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants