preflight admits the four headers the console actually sends
X-Actor-Id, X-Act-As-Project, X-Act-As-Org and X-CSRF-Token are stamped on every signed-in console call (client.ts baseHeaders + applyCsrfToInit) and none of them were in corsAllowHeaders. A header absent from that list fails PREFLIGHT: the browser reports an opaque "TypeError: Failed to fetch" and the request never reaches a server log, so there is nothing to find on our side. Measured from a signed-in console.hanzo.ai page: adding any ONE of the four blocked the call, the identical request without it returned 200. Naming a header only lets the browser SEND it. Each stays exactly as trustworthy as before — SanitizeIdentity still strips and re-mints client-supplied identity, so an intent is validated, never believed. Taken as a one-hunk cherry-pick rather than by merging PR #385: that branch is 443 files and 49,500 insertions off an ancient base, and merging it would drop ~17 commerce prefixes from manifest/apps.go and revert usage_coresident.go's FloorMinor back to RoundMinor. NOTE: this constant's own doc says it mirrors hanzoai/gateway routes.go corsPreflightMiddleware so the browser contract is byte-identical through either path. The gateway needs the same four or the mirror is broken. Co-authored-by: Hanzo Dev <dev@hanzo.ai>
This commit is contained in:
+20
-1
@@ -56,9 +56,28 @@ import (
|
||||
// allowed brand host works and every other origin gets no CORS headers.
|
||||
const (
|
||||
corsAllowMethods = "GET, POST, PUT, PATCH, DELETE, OPTIONS"
|
||||
// The list must name EVERY header a browser client actually sends: a header
|
||||
// absent here fails PREFLIGHT, and the browser reports it as an opaque
|
||||
// "TypeError: Failed to fetch" with no server-side log — the request never
|
||||
// arrives. Measured against production before this line changed: from a
|
||||
// signed-in console.hanzo.ai page, adding any one of X-Actor-Id,
|
||||
// X-Act-As-Project, X-Act-As-Org or X-CSRF-Token blocked the call, while the
|
||||
// identical request without it returned 200.
|
||||
//
|
||||
// Those four are what the console stamps on a signed-in call (console
|
||||
// src/lib/api/client.ts baseHeaders + applyCsrfToInit):
|
||||
// X-Actor-Id — the signed-in user, on EVERY authenticated request
|
||||
// X-Act-As-Project — project sub-scope INTENT (a request, never a claim)
|
||||
// X-Act-As-Org — org-switch INTENT, same shape
|
||||
// X-CSRF-Token — echoed on every mutating write the ambient-cookie path makes
|
||||
//
|
||||
// Naming a header here only lets the browser SEND it; each stays exactly as
|
||||
// trustworthy as before — SanitizeIdentity still strips and re-mints
|
||||
// client-supplied identity, so an intent is still validated, never believed.
|
||||
corsAllowHeaders = "Content-Type, Authorization, X-User-Id, X-Org-Id, " +
|
||||
"X-Project-Id, X-Environment, X-Roles, X-User-Email, X-Request-ID, " +
|
||||
"X-Client-ID, X-Requested-With, Accept, Accept-Language"
|
||||
"X-Client-ID, X-Requested-With, Accept, Accept-Language, " +
|
||||
"X-Actor-Id, X-Act-As-Project, X-Act-As-Org, X-CSRF-Token"
|
||||
corsMaxAge = "86400"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user