Let a federated worker read the intent endpoint
Found live on the first burn-in task. Every federated launch failed with `effective intent: federation: 401 Unauthorized: unauthorized surface`, and the task nacked back to queued. GET /v1/tasks/<id>/intent was added so a worker renders its own launch instruction from the reduced intent, but authz.HTTPWithSessions never got the matching worker-path exemption. An unlabelled request defaults to the Web surface, which is session-gated, so the one caller the endpoint exists for could never reach it. Twenty test packages passed throughout, because the authz tests covered the surface capability table and not the worker path list. Only the live owner path established this. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -225,7 +225,14 @@ func HTTPWithSessions(tokens map[Surface]string, sessions *Sessions, next http.H
|
||||
workerPath := strings.HasPrefix(r.URL.Path, "/v1/federation/") ||
|
||||
(r.Method == http.MethodGet && r.URL.Path == "/v1/tasks") ||
|
||||
(r.Method == http.MethodPost && r.URL.Path == "/v1/artifacts") ||
|
||||
(r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/v1/artifacts/"))
|
||||
(r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/v1/artifacts/")) ||
|
||||
// A federated worker renders its own launch instruction from the
|
||||
// reduced intent, so this read is as necessary to it as the task
|
||||
// list. Found live on the first burn-in task: the endpoint was
|
||||
// added for workers, the exemption was not, and every federated
|
||||
// launch failed with "effective intent: federation: 401
|
||||
// Unauthorized: unauthorized surface".
|
||||
(r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/v1/tasks/") && strings.HasSuffix(r.URL.Path, "/intent"))
|
||||
if federationRegistration || r.URL.Path == HarnessTurnPath || (worker && workerPath) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
|
||||
@@ -140,6 +140,8 @@ func TestFederationRequestsUseTheirOwnCredentials(t *testing.T) {
|
||||
{name: "worker task reconciliation reaches worker handler", method: http.MethodGet, path: "/v1/tasks", worker: "workpc-opencode", want: http.StatusNoContent},
|
||||
{name: "worker artifact read reaches worker handler", method: http.MethodGet, path: "/v1/artifacts/ref", worker: "workpc-opencode", want: http.StatusNoContent},
|
||||
{name: "worker artifact upload reaches worker handler", method: http.MethodPost, path: "/v1/artifacts", worker: "workpc-opencode", want: http.StatusNoContent},
|
||||
{name: "worker intent read reaches worker handler", method: http.MethodGet, path: "/v1/tasks/06G3YR34117MAYT6KEAC9RJHD0/intent", worker: "workpc-opencode", want: http.StatusNoContent},
|
||||
{name: "unnamed intent read remains web gated", method: http.MethodGet, path: "/v1/tasks/06G3YR34117MAYT6KEAC9RJHD0/intent", want: http.StatusUnauthorized},
|
||||
{name: "unnamed worker request remains web gated", method: http.MethodGet, path: "/v1/federation/events", want: http.StatusUnauthorized},
|
||||
{name: "worker list remains web gated", method: http.MethodGet, path: "/v1/federation/workers", want: http.StatusUnauthorized},
|
||||
} {
|
||||
|
||||
Reference in New Issue
Block a user