identity is the composer's: one constructor, and no subsystem asserts it
CI/CD / image (push) Failing after 33m28s
CI/CD / gate (push) Successful in 13s
CI/CD / containment (push) Successful in 1m38s
CI/CD / rollout (push) Skipped
CI/CD / reach (push) Skipped
CI/CD / fanout (push) Skipped
CI/CD / receipt (push) Skipped
Hanzo CI/CD / cicd (push) Successful in 12s

cloud.App(name, cfg, deps, tools) now builds every program — the host and all
125 plugin programs — and installs the canonical chain through identity in one
place. Identify states the order invariant once: the boundary that mints the
validated org runs before the enrichment that parks it, and neither exists
without the other. Middleware order at the host is proven byte-identical
before and after (18 entries), so a refused request is still audited.

Every subsystem self-install of the enrichment is deleted — 74 sites across 67
packages. A subsystem asserting identity for itself repeats a claim it cannot
check; two of those copies sat on nodes owning no routes, which zip refuses to
compose, and that is the outage that took /v1/o11y and /v1/integrations down.
The childless spelling is gone everywhere: a gate passed TO Group is installed
at the root bounded by its prefix, and the two-step form that slipped past
that (a bare Group then Use on it) is collapsed at its last holdouts —
referrals' three gates and the audit fixtures.

Tests stop rebuilding the composer by hand: each package that mounts on a
bare app owns one compose helper, so anonymous cases still refuse and
principal-carrying cases reach the handler exactly as production does.

Also fixed, found by the constructor's own test: the markdown negotiation
replaced the Vary header CORS had written, so every CORS response on every
program advertised Vary: Accept — a shared cache could hand one origin's body
to a different origin. The later writer is additive now.

Census: zero non-test enrichment installs under apps/, zero childless chains.
Build and vet clean over the whole tree in the shipping mode.
This commit is contained in:
antje
2026-08-04 14:33:13 -07:00
parent d5c5b44fcb
commit 9396df7021
222 changed files with 1605 additions and 1032 deletions
+187
View File
@@ -0,0 +1,187 @@
package cloud
import (
"github.com/hanzoai/cloud/apps/sites"
"github.com/zap-proto/zip"
"github.com/zap-proto/zip/middleware"
)
// App returns an app carrying everything a Hanzo program must carry, in the one
// order those parts are correct in. It is the only way to obtain one: a program
// mounts its subsystem on what it gets back and never builds a zip.App itself.
//
// The point is what a caller no longer has the opportunity to forget. Identity is
// not an option a program passes, it is a property of the value it receives, so a
// program is either holding an app that identifies its callers or it is holding
// nothing. Every other member here was equally forgettable and was equally
// forgotten: the o11y binary assembled its own app and reached production with no
// panic recovery, no request id, no response-header posture, no tracing, no
// request log and no typed-op enrichment — a shape nobody chose and nobody could
// see, because there was nothing to compare it against.
//
// WHERE THE EDGE IS. Production runs ingress → gateway → the front door
// (cmd/cloud) → this program. The gateway is the public edge and owns rate
// limiting for the internet. The front door installs no middleware of its own —
// it routes, serves the console, threads operator flags and scopes credentials —
// so a program built here is its OWN edge and defends itself. That is why the
// browser and flood defenses are here rather than borrowed from a parent. A
// program reached over the plane socket instead trusts what its host asserted:
// the kernel answers which process is calling, and the boundary's findings travel
// with the request.
//
// name is what the program calls itself in a diagnostic. tools is the MCP surface,
// which only a program holding a subsystem list can project — everyone else passes
// nil and serves none.
func App(name string, cfg *Config, deps Deps, tools zip.Source) *zip.App {
app := zip.New(zip.Config{
AppName: name,
Logger: deps.Logger,
ReadBufferSize: cfg.ReadBufferSize,
BodyLimit: cfg.BodyLimit,
MCP: zip.MCPConfig{Source: tools},
// Cloud's refusal renderer, in place of zip's default — which reads only a
// *zip.HTTPError and answers 500 for everything else, so a propagated 402
// or 403 reached the console as a dead card. See errmap.go.
ErrorHandler: ErrorHandler,
// Static Server fallback for responses the ProductionHeaders middleware
// cannot reach — the transport's own pre-routing errors (431/400) and any
// fiber path that bypasses the chain. Set to this deployment's brand so
// those bytes read Server: <brand>, never the framework default "zip" or
// "fasthttp" (zip>=v1.8.1 propagates this onto the fasthttp transport).
// Handled responses are still branded per-Host by ProductionHeaders.
ServerHeader: cfg.Brand,
})
// Canonical middleware pipeline. Order matters:
// 1. Recover — panic → JSON 500
// 2. RequestID — generate / propagate X-Request-Id
// 3. Tracing — one OTel SERVER span per /v1/* request, over ZAP
// 4. Logger — request-line log
// 5. SanitizeIdentity — establish a VALIDATED principal (see Identify)
app.Use(middleware.Recover())
app.Use(middleware.RequestID())
// Production response-header posture — the Stripe/Cloudflare/GitHub-grade
// signals plus a security floor, from ONE home in the framework so every
// service inherits the same wire posture. Registered right after RequestID
// (before the site edge and the business chain) so its headers ride out on
// every response: success, error, 404, AND the public-site static bytes.
// - Server: the white-label brand of the request Host (BrandForHostOK) — a
// lux/zoo caller is never served "hanzo" and no response leaks the
// framework name; an unmatched Host falls back to this deployment's own
// brand (cfg.Brand), never a framework/single-brand default.
// - X-Api-Version: the build version (brand-neutral key) for support correlation.
// - HSTS + nosniff: the always-safe security floor (no X-Frame-Options/CSP
// here — the console SPA owns its own framing rules).
// X-Request-Id stays owned by RequestID above; the two compose.
app.Use(middleware.ProductionHeaders(middleware.ProductionHeadersConfig{
Brand: func(host string) string { b, _ := BrandForHostOK(host); return b },
Neutral: cfg.Brand,
Version: cfg.Version,
HSTS: true,
}))
// Markdown content negotiation. Registered here — outermost of the business
// chain, just inside Recover/RequestID — so its post-Continue transform sees
// the FINAL response body and re-serializes it via zap-proto/md when the
// caller asked for markdown (Accept: text/markdown or ?format=md). JSON stays
// the default for machines; cfg.MarkdownDefaultPrefixes lets designated
// agent endpoints (/v1/code/, /v1/agents/…) default to markdown. Touches NO
// handler and fails safe (a render error leaves the JSON intact). See
// middleware_markdown.go.
app.Use(MarkdownNegotiation(cfg.MarkdownDefaultPrefixes))
// Request tracing. Sits right after RequestID (so the span carries the
// request_id) and BEFORE identity/audit/billing/handlers, so the whole
// authenticated pipeline nests under one span and the span CONTEXT it writes
// via SetContext parents every downstream span (agent.run → agent.step →
// chat) into a single trace. Spans ship over the SAME global provider installed
// by InstallTelemetry, landing in hanzoai/datastore.
// Health/readiness/metrics + non-/v1 paths are skipped (see traceable). See
// middleware_tracing.go.
app.Use(TracingMiddleware())
app.Use(middleware.Logger(deps.Logger))
// Public site edge (clients/sites). Installed FIRST — after Recover/RequestID/
// Logger, BEFORE SanitizeIdentity + BillingGate — so a request whose Host is a
// published-site host (`<slug>.hanzo.app`) is served the site's static bytes
// from OUR S3 and returns HERE, never entering the authenticated/billed API
// pipeline. A published site is a PUBLIC artifact: no IAM JWT, no balance gate.
// For every other Host this middleware calls Continue() and the pipeline below
// runs unchanged. The slug→{org,bucket,prefix} resolver is the projects store,
// injected at its Mount via sites.SetResolver; until then a site host 404s
// honestly. Org isolation (org+prefix come only from the store keyed by the
// validated slug; object keys are rooted-clean) lives in clients/sites.
// The edge asks the app that owns the store when it is not in this process,
// which in production is always: the pod boots ~25 single-app processes, so
// the registry projects.Mount writes is nil here. Co-resident still wins with
// no hop — currentResolver prefers the in-process one.
sites.SetFallbackResolver(planeSites{})
app.Use(sites.New(sites.ConfigFromEnv(cfg.Domain), deps.Logger).Middleware())
// Edge policy — the role this program absorbs because nothing in front of it
// installs middleware. Runs BEFORE identity by design:
// - EdgeCORS answers the browser OPTIONS preflight (which carries no
// credentials) and short-circuits it, so a preflight never reaches auth.
// No-op unless CLOUD_CORS_ORIGINS is set (the shared ingress owns CORS on
// the recommended rollout — enabling both would double the ACAO header).
// - EdgeRateLimit caps an ANONYMOUS per-IP flood before the JWKS/validate/
// downstream work it would trigger — the one gap ScopeRateLimit (which keys
// on the validated org, below) structurally can't see. Keyed on the
// public client IP; in-cluster direct callers (no X-Forwarded-For) are
// exempt, matching the standalone gateway's public-only scope. See
// middleware_edge.go.
app.Use(EdgeCORS(deps.GatewayPolicy))
app.Use(EdgeRateLimit(deps.GatewayPolicy))
Identify(app, cfg)
return app
}
// Identify gives an app a trustworthy answer to who is calling, and makes that
// answer reachable from every route beneath it. App does this for every program,
// which is the only reason it can no longer be skipped.
//
// The two halves are one function because each is wrong without the other, and
// wrong in a way nothing reports. IdentityMiddleware deletes the authority
// headers a client sent and re-mints them from a verified IAM token, so it runs
// first: what it produces is the only principal in the process anyone may trust.
// The enrichment then parks that principal on the request context, which is the
// only path by which a typed op reaches it — a zip.Get[In, Out] handler receives a
// context and its decoded In and nothing else. Reversed, it parks whatever the
// caller claimed for itself. Installed alone, the boundary validates a caller and
// then every typed op reads an empty org and refuses that same caller, which
// reaches the wire as a 403 from a service behaving exactly as built.
//
// That last failure is the reason this is a function rather than two lines of
// advice. It is what the o11y binary did while assembling its own app, and its
// subsystem then compensated from inside its own Mount, on a group node that
// owned no routes — a program zip refuses to compose, which is the outage.
func Identify(app *zip.App, cfg *Config) {
// The identity trust boundary. HIP-0519 says identity is verified once, at the
// edge, and that is the shape to reach. It rests on ONE assumption: the gateway
// is the only ingress. That assumption does not hold here yet, and the estate's
// own red-team probe says so — with this middleware removed, a request carrying
// a forged X-Org-Id, X-User-Id and X-User-IsAdmin reads another org's secret
// VALUE from the in-cluster KMS listener:
//
// PROBE (b) forged org + forged X-User-Id + IsAdmin → 200 {"value":"…"}
//
// So this stays until service listeners are unreachable except through the
// gateway. Removing it is a network-policy change first and a code change
// second, and doing the code half alone is a cross-tenant secret read.
// red_orgscope_isolation_test.go and TestAudit_AnonRequestNotAttributedToForgedOrg
// fail the moment it is dropped; they are the gate on that work, not obstacles
// to it.
app.Use(IdentityMiddleware(cfg))
// Besides the validated org, this carries the request a proxying subsystem
// forwards identity from and the slot a creator writes 201 or 202 into. It must
// precede every typed route, because fiber runs middleware in registration
// order and one installed after its leaves never runs. A subsystem whose routes
// are spread across several top-level nouns owns no single prefix to hang it
// on, which is the other reason it belongs to whoever composes the app. See
// typed.go.
app.Use(Bridge())
}
+3 -13
View File
@@ -150,19 +150,9 @@ func MountAccount(app cloud.Router, deps cloud.Deps) error {
// routesAccount wires the specific self-service routes (order 48).
func routesAccount(s *cloud.Service[state], app cloud.Router) error {
// Bridge FIRST: a typed op receives only a context, so the request facts its
// signature drops — here the VALIDATED principal every route resolves its caller
// from — reach it by being parked there. fiber runs middleware in registration
// order, so this must precede the leaves below. Serve installs one app-wide too
// and nesting is harmless (the inner one is what the handler sees); this one is
// what makes the subsystem self-sufficient when it is mounted on a bare app,
// which is exactly what its own tests do.
//
// It goes through Use, not Group(prefix, mw): account's routes are spread across
// six top-level nouns, so it owns no single prefix to hang a group on — and
// Router.Use is the door that fans middleware out over the prefixes the
// composition root declared for this subsystem, which is precisely that set.
app.Use(cloud.Bridge())
// The composer owns cloud.Bridge: the fused host installs it once at its root
// and the plugin constructor does the same for a plugin program, so no
// subsystem installs it.
// The typed registrars take the App behind the Router: a typed op is a route
// PLUS a registry entry, and the registry lives on the App (scope.go). A
+9
View File
@@ -255,12 +255,20 @@ func mountApp(t *testing.T, base, clientID, clientSecret string) *zip.App {
return mount(t, "hanzo")
}
// compose installs what a host installs. A subsystem never installs cloud.Bridge:
// the program's composer owns it — serve.go at the root of the fused host, the
// plugin constructor for a plugin program. In a test the test is the composer, so
// it owes the same install; skipping it drives a program where every org-scoped op
// answers 403 for a reason production callers never see.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mount mounts the account subsystem on a bare app — exactly what production
// registers (account@48). The caller sets the IAM env (IAM_URL / IAM_MINT_CLIENT_*)
// before calling.
func mount(t *testing.T, brand string) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
deps := cloud.Deps{Logger: luxlog.New("test"), Brand: brand}
if err := MountAccount(app, deps); err != nil {
t.Fatalf("MountAccount: %v", err)
@@ -742,6 +750,7 @@ func TestAccountClaimsNothingUnderIAM(t *testing.T) {
t.Setenv("IAM_MINT_CLIENT_SECRET", "s3cr3t")
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := MountAccount(app, cloud.Deps{Logger: luxlog.New("test"), Brand: "hanzo"}); err != nil {
t.Fatalf("MountAccount: %v", err)
}
+1
View File
@@ -120,6 +120,7 @@ func mountAvatar(t *testing.T) (*zip.App, *memVFS, *fakeIAM) {
// sources could not enqueue: a framework cap below the app's, surfacing as an
// opaque error nobody could act on.
app := zip.New(zip.Config{Logger: luxlog.New("test"), BodyLimit: edgeBodyLimit})
compose(app)
deps := cloud.Deps{Logger: luxlog.New("test"), Brand: "hanzo", Domain: "api.hanzo.ai", VFS: vfs}
if err := MountAccount(app, deps); err != nil {
t.Fatalf("MountAccount: %v", err)
+4 -2
View File
@@ -49,8 +49,10 @@ var alice = map[string]string{"X-User-Id": "alice", "X-Org-Id": "acme"}
func pinApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
// MountAccount installs the identity middleware PinBillingSubject relies on; mounting
// it keeps the probe on the same trust plane as the real co-resident registration.
// compose installs the identity middleware PinBillingSubject relies on; mounting
// the real subsystem keeps the probe on the same trust plane as the co-resident
// registration.
compose(app)
if err := MountAccount(app, cloud.Deps{Logger: luxlog.New("test"), Brand: "hanzo"}); err != nil {
t.Fatalf("MountAccount: %v", err)
}
+6 -5
View File
@@ -115,11 +115,12 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
func routes(app cloud.Router, s *cloud.Service[core.State]) {
o := ops{s: s}
z := cloud.ZipApp(app)
// The bridge FIRST: fiber runs middleware in registration order, so one installed
// after these leaves would never run — and every op below takes the request off the
// context it parks. Bounded to admin's own subtree. Serve installs one app-wide too;
// nesting is harmless, and this is what makes the surface testable on a bare app.
app.Use(cloud.Bridge())
// Every op below takes the request off the context, and whoever composes the app
// parks it there — at the root, ahead of these leaves, since fiber runs
// middleware in registration order. This surface installs none of its own: one
// it installed for itself could only hang on a /v1/admin node, and every op
// below registers through the root, so that node would carry middleware over an
// empty subtree and zip refuses to compose it.
// Org-scoped panels — AdmitScoped. Cross-tenant reads are impossible for a
// non-super caller.
+3
View File
@@ -39,6 +39,7 @@ func mount(t *testing.T, iamURL, commerceURL, healthURL string) func(method, pat
func mountService(t *testing.T, iamURL, commerceURL, healthURL string) (func(method, path string, hdr map[string]string) (*http.Response, []byte), *cloud.Service[core.State], *fiber.App) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
s := &cloud.Service[core.State]{State: core.State{
IAM: iam.New(iamURL),
Commerce: commerce.New(commerceURL, "test-token"),
@@ -731,6 +732,7 @@ func TestMount_NilGuards(t *testing.T) {
t.Error("Mount(nil app) must error")
}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{}); err == nil {
t.Error("Mount(nil logger) must error")
}
@@ -747,6 +749,7 @@ func servePlatformEmpty(t *testing.T) {
t.Helper()
t.Setenv("ZIP_RUNTIME_DIR", t.TempDir())
app := zip.New(zip.Config{AppName: "platform"})
compose(app)
zip.Post[struct{}, plane.Fleet](app, "/platform/fleet",
func(context.Context, *struct{}) (*plane.Fleet, error) {
return &plane.Fleet{}, nil
+5 -3
View File
@@ -34,9 +34,11 @@ func mountWithStore(t *testing.T) (*auditstore.Recorder, func(method, path strin
app := zip.New(zip.Config{Logger: luxlog.New("test")})
s := &cloud.Service[core.State]{State: core.State{AdminOrg: "admin", AuditStore: rec}}
// Mirror the real mount: the request bridge, then the typed ops. A typed op sees
// the caller only through the bridge, so registering routes without it would test
// a wiring that cannot exist.
// Stand in for the composer: the principal enrichment at the root, then the
// typed ops — the order cloud.App gives every production program. A typed op
// sees the caller only through what the enrichment parks, and a group at
// /v1/admin would be a node of its own with no routes beneath it, which zip
// refuses to compose.
app.Use(cloud.Bridge())
Routes(app, s)
fa := app.Fiber()
+15
View File
@@ -0,0 +1,15 @@
package admin
import (
"github.com/hanzoai/cloud"
"github.com/zap-proto/zip"
)
// compose stands in for the composer. Production programs are built by
// cloud.App, which installs the principal enrichment once at the root before
// any route; a test that mounts this subsystem on a bare app owns that duty
// itself, exactly once, here. A test that sends no identity is unaffected —
// with nothing validated there is nothing to park — so anonymous cases still
// refuse, and principal-carrying cases reach the handler as they do in
// production.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
+1
View File
@@ -29,6 +29,7 @@ func spec(t *testing.T) (map[string]any, []string) {
Logger: luxlog.New("test"),
OpenAPI: zip.OpenAPIConfig{Title: "cloud", Version: "v1.0.0"},
})
compose(app)
routes(app, &cloud.Service[core.State]{State: core.State{AdminOrg: "admin"}})
var live []string
+1
View File
@@ -19,6 +19,7 @@ import (
func ctxWith(t *testing.T, headers map[string]string, fn func(c *zip.Ctx)) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
app.Get("/probe", func(c *zip.Ctx) error {
fn(c)
return c.NoContent(204)
+15
View File
@@ -0,0 +1,15 @@
package admission
import (
"github.com/hanzoai/cloud"
"github.com/zap-proto/zip"
)
// compose stands in for the composer. Production programs are built by
// cloud.App, which installs the principal enrichment once at the root before
// any route; a test that mounts this subsystem on a bare app owns that duty
// itself, exactly once, here. A test that sends no identity is unaffected —
// with nothing validated there is nothing to park — so anonymous cases still
// refuse, and principal-carrying cases reach the handler as they do in
// production.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
+2
View File
@@ -38,6 +38,7 @@ func gateApp(t *testing.T, approvalStatus string) *zip.App {
}, time.Minute)
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
app.Use(Enforce(EnforceConfig{WaitlistURL: "https://waitlist.hanzo.ai", Approvals: approvals, Gate: testGate}))
app.Get("/*", func(c *zip.Ctx) error { return c.String(200, "ok") })
return app
@@ -214,6 +215,7 @@ func TestRule_ForwardHeaderApproved_ThroughWithoutLookup(t *testing.T) {
// host, so Enforce never gates pre-boot.
func TestEnforce_DefaultGate_FailsOpenPreBoot(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
app.Use(Enforce(EnforceConfig{WaitlistURL: "https://waitlist.hanzo.ai",
Approvals: newApprovalsWithLookup(func(context.Context, string, string) (string, bool) { return "pending", true }, time.Minute)}))
app.Get("/*", func(c *zip.Ctx) error { return c.String(200, "ok") })
+5 -3
View File
@@ -348,9 +348,11 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// gated user can still resolve mode.
//
// A typed op receives only a context, so the request the ?host= default falls
// back to has to be parked there. Installed BEFORE the leaf — fiber runs
// middleware in registration order, so one installed after it never runs.
app.Use(cloud.Bridge())
// back to reaches it from that context. Whoever composes the app parks it there,
// at the root, ahead of every leaf; this surface installs no middleware of its
// own. One that it installed for itself could only hang on a /v1/flags/waitlist
// node, and the leaf below registers through the root, so that node would carry
// middleware over an empty subtree and zip refuses to compose it.
zip.Get(cloud.ZipApp(app), "/v1/flags/waitlist", waitlistOps{}.mode)
log.Info("admission gate ready", "services", n)
return nil
+1
View File
@@ -24,6 +24,7 @@ import (
func mountGate(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir(), Brand: "hanzo"}); err != nil {
t.Fatalf("Mount: %v", err)
}
+5 -8
View File
@@ -119,14 +119,11 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// method are projected from. The exception is named at its registration below.
func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/ads")
// The Bridge FIRST, on the subtree ads owns: a typed op receives only a
// context, so the validated org has to be parked there, and fiber runs
// middleware in registration order — one installed after these leaves would
// never run. cloud.Listen installs one app-wide too; nesting is harmless (the
// inner one is what the handler sees), and having it here is what makes this
// package's own tests — which mount on a bare app — exercise the same
// tenancy the binary does.
g.Use(cloud.Bridge())
// A typed op receives only a context, so the validated org it reads is parked
// there by cloud.Bridge. This subsystem does not install it: the program's
// composer does, once at the root, after the identity check that mints the org
// and before any subsystem registers a route — an order only the composer can
// hold.
// Ops are declared ON THE GROUP: every zip.Router is an OpTarget, and the op's
// path is the group's prefix composed with the leaf — the identity every
+10 -3
View File
@@ -35,13 +35,20 @@ var untypedByDesign = map[string]string{
"zip can declare a body-tolerant op.",
}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer does, once at the root. In a test
// the test IS the composer, so it owes the same install — skipping it does not
// test a stricter program, it tests one where every org-scoped op answers 403
// for a reason production could never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountApp mounts the ads surface on a fresh in-memory app with a temp store,
// exactly as the unified binary does — and, deliberately, with NO app-wide
// cloud.Bridge, so the bridge these ops read their tenant through has to be the
// one routes() installs itself.
// composed exactly as the unified binary is: cloud.Bridge at the root, the
// subsystem's routes beneath it.
func mountApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+4 -7
View File
@@ -350,14 +350,11 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// request that carried one. Serve installs one app-wide, which is why serving
// was unaffected and only the tests — which Mount onto a bare app — could see
// it; a gate whose absence just one door down is invisible in production is the
// kind that stays broken. Under Serve a scope bounds this to the prefixes the
// manifest declares, and under a bare Mount it is app-wide, which is what the
// subsystem's own door honestly is.
//
// fiber runs middleware in registration order, so it goes above every route
// below, group included.
app.Use(cloud.Bridge())
g := app.Group("/v1/agents")
// cloud.Bridge parks the validated org on the context a typed op receives; it
// is the composer's install — once at the root of every program — so this
// package does not install its own.
//
// The root of the surface. Declared on the App with its WHOLE path, not on the
// group with an empty leaf: joining "/v1/agents" with "" yields "/v1/agents/",
// a different path from the one these two have always served.
+1
View File
@@ -88,6 +88,7 @@ func mountBilled(t *testing.T, commerceURL string, ai types.AIClient) *zip.App {
t.Fatalf("metering.New: %v", err)
}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
// AIFallbackModel="best" arms the agent runner's failover so the retry/failover
// tests exercise the real escalation path; it never fires for a run whose model
// answers (or fails non-transiently), so the other billed tests are unaffected.
+7
View File
@@ -15,6 +15,12 @@ import (
"github.com/zap-proto/zip"
)
// compose installs what the program's composer installs — cloud.Bridge, once at
// the app root. A subsystem never installs its own, so a test app owes the same
// root install; without it every org-scoped op answers a 403 no production
// program would produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountApp mounts the agents surface with a deterministic fake AI so run() is
// exercised end-to-end over HTTP without a real gateway. Pass a nil interface
// to exercise the no-inference fail-closed path.
@@ -40,6 +46,7 @@ func mountAppDir(t *testing.T, dir string) *zip.App {
func mountAppIn(t *testing.T, dir string, ai types.AIClient, defaultModel string) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: dir, AI: ai, AIDefaultModel: defaultModel}); err != nil {
t.Fatalf("Mount: %v", err)
}
+1 -2
View File
@@ -203,8 +203,7 @@ func toEventView(e Event) eventView {
//
// The typed ops are declared on the GROUP, so each op's path is the group's
// prefix composed with its leaf — the same composition the router does, and the
// identity every projection keys on. cloud.Bridge is installed once, at the top
// of Mount, ahead of this call.
// identity every projection keys on.
func mountSessions(s *cloud.Service[state], app cloud.Router) {
o := sessionOps{s: s}
g := app.Group("/v1/agents")
-6
View File
@@ -624,12 +624,6 @@ type patchTargetIn struct {
// captured as a ref. The static /v1/agents/targets precedes /v1/agents/targets/:id.
func mountTargets(s *cloud.Service[state], app cloud.Router) {
g := app.Group("/v1/agents")
// cloud.Bridge is installed ONCE, at the top of Mount, ahead of every leaf on
// this prefix. It used to be installed here, which was too late for the leaves
// registered before this call: fiber runs middleware in registration order, so
// the sessions and agent-CRUD routes above would have had no org on the context
// the moment they became typed ops.
//
// TYPED ops, declared on the group itself: zip.Get and friends take any
// Router since v1.18.0, so the prefix is part of each op's path and every
// projection — the document, the MCP tool, the CLI command, the call plane —
+4 -12
View File
@@ -199,18 +199,10 @@ func routes(app cloud.Router, s *cloud.Service[state]) {
// A typed op receives ONLY a context, so the validated org has to be PARKED
// there — never carried as an In field, which is caller-supplied and would make
// a cross-tenant read something the caller asserts for itself. cloud.Bridge
// parks it, and it is installed FIRST because fiber runs middleware in
// registration order: one installed below a leaf never runs for that leaf.
//
// On a scoped mount Use installs it once per prefix the subsystem DECLARES
// (scope.go), which is why plugin/analytics/main.go now declares all six of
// this app's prefixes: with only the /v1/<name> default, the typed reads at
// /v1/errors and /v1/insights/* would sit outside every prefix this subsystem
// could gate. Serve installs one app-wide too; nesting is harmless, and the
// tests mount this subsystem on a bare app with no Serve, so the subsystem's
// own install is what makes them pass.
app.Use(cloud.Bridge())
// parks it, and the COMPOSER installs it, not this subsystem: the fused host
// once at its root (serve.go), and a plugin program's constructor likewise. An
// install here would hang middleware on prefixes with no routes beneath them,
// a program zip refuses to compose.
o := readOps{s: s}
// The read lenses, declared on the GROUP: each op's path is the prefix composed
// with its leaf — the same composition the router does, and the identity every
+1
View File
@@ -44,6 +44,7 @@ import (
func liveApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("live")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("live")}); err != nil {
t.Fatalf("Mount: %v", err)
}
+1 -1
View File
@@ -403,7 +403,7 @@ func TestRoutedPostSetIsExactlyTheDoors(t *testing.T) {
var posts []string
// GetRoutes(true) drops the `use` entries — middleware, which fiber keeps in the
// same stack as routes and reports under every method at the prefix it gates.
// cloud.Bridge is one of those (routes installs it so a typed op can read the
// cloud.Bridge is one of those (compose installs it so a typed op can read the
// validated org), and so is every middleware Serve installs app-wide, so an
// unfiltered read has never been "the POST surface" in the real binary either. A
// middleware is a passthrough, not a door: it dispatches nothing.
+7
View File
@@ -19,9 +19,16 @@ import (
"github.com/zap-proto/zip"
)
// compose installs what a host installs. A subsystem never installs cloud.Bridge
// (routes says why): the program's composer owns it — serve.go in production — so
// a test app owes the same install, else every org-scoped op answers 403 for a
// reason no composed program has.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mountApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test")}); err != nil {
t.Fatalf("Mount: %v", err)
}
+11 -8
View File
@@ -83,13 +83,16 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// routes registers the org-scoped audit surface.
//
// Bridge FIRST and noStore beside it, both installed BEFORE the leaf: fiber runs
// middleware in registration order, so one installed after its route never runs.
// Bridge parks the validated org, which is the only way a typed op — which
// receives a context and nothing else — can resolve the tenant. Serve installs
// one app-wide too; nesting is harmless (the inner one is what the handler sees)
// and this package's own tests mount on a bare app with no Serve, so this
// install is what makes them pass.
// cloud.Bridge is absent on purpose: the composer owns that install — the fused
// host at its root, a plugin program in its constructor — and it is what parks
// the validated org, the only way a typed op (a context and nothing else) can
// resolve the tenant.
//
// noStore takes the ROOT form, before the leaf because fiber runs middleware in
// registration order. A group at /v1/audit cannot carry it: the op below is
// declared on the App, so that group would hold middleware with no routes
// beneath it, a program zip refuses to compose. Through the scoped Router the
// root form is confined to /v1/audit, the one prefix this subsystem declares.
//
// USE, NOT A MIDDLEWARE-CARRYING GROUP. This used to say
// `app.Group("/v1/audit", Bridge(), noStore())`, and that is the one shape this
@@ -110,7 +113,7 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// joining "/v1/audit" with "" yields "/v1/audit/", a different path from the one
// this API has always served, and one that would ship in OpenAPI and the SDK.
func routes(app cloud.Router, zapp *zip.App, s *cloud.Service[state]) {
app.Use(zip.H(cloud.Bridge()), zip.H(noStore()))
app.Use(noStore())
o := ops{s: s}
zip.Get(zapp, "/v1/audit", o.list)
}
+7
View File
@@ -37,9 +37,16 @@ func newStore(t *testing.T) *audit.Recorder {
return rec
}
// compose gives the test app what every real composer gives its program: the
// fused host installs cloud.Bridge at its root and a plugin program's
// constructor does the same, so a bare test app that skipped it would answer
// 401 for a reason production can never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mountApp(t *testing.T, store *audit.Recorder) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), Audit: store}); err != nil {
t.Fatalf("Mount: %v", err)
}
+5 -7
View File
@@ -186,16 +186,15 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// SDK method.
//
// The two subtrees are declared on their OWN groups, because they are two surfaces:
// /v1/authors is the tenant's, /v1/admin/authors is the platform's. Both get
// cloud.Bridge, which is what parks the validated org a typed op reads — never an In
// field, which is caller-supplied and would be a cross-tenant read the caller
// asserted for itself. fiber runs middleware in registration order, so each Use
// precedes its own leaves; nesting under Serve's own Bridge is harmless.
// /v1/authors is the tenant's, /v1/admin/authors is the platform's. A typed op reads
// the validated org parked on the context by cloud.Bridge — never an In field, which
// is caller-supplied and would be a cross-tenant read the caller asserted for itself.
// The composer owns that install, once at its root; both groups here are bare path
// prefixes.
func routes(app cloud.Router, zapp *zip.App, s *cloud.Service[state]) {
o := ops{s: s}
g := app.Group("/v1/authors")
g.Use(cloud.Bridge())
// The root of the tenant surface, declared on the App with its whole path rather
// than on the group with an empty leaf: joining "/v1/authors" with "" yields
// "/v1/authors/", a DIFFERENT path from the one it has always served.
@@ -206,7 +205,6 @@ func routes(app cloud.Router, zapp *zip.App, s *cloud.Service[state]) {
zip.Post(g, "/deploys/record", o.recordDeploy)
ga := app.Group("/v1/admin/authors")
ga.Use(cloud.Bridge())
zip.Get(zapp, "/v1/admin/authors", o.adminList)
zip.Post(ga, "/sweep", o.adminSweep)
zip.Post(ga, "/:id/approve", o.adminApprove)
+9
View File
@@ -137,6 +137,13 @@ func (g *fakeGitHub) fetchFile(_ context.Context, _, owner, repo, branch, path s
return g.files[owner+"/"+repo+"@"+branch+"/"+path], nil
}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root. In a
// test the test IS the composer, so it owes the same thing — a test that skips it
// tests a program where every org-scoped op answers 403 for a reason that would
// never exist in production. Same helper apps/integrations uses.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mount builds an authors app backed by a fresh store + injected fakes, returning the
// app, the service, and the fakes for assertions.
func mount(t *testing.T) (*zip.App, *cloud.Service[state], *fakeCommerce, *fakeGitHub) {
@@ -159,6 +166,7 @@ func mount(t *testing.T) (*zip.App, *cloud.Service[state], *fakeCommerce, *fakeG
},
}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, app, s)
return app, s, fc, fg
}
@@ -917,6 +925,7 @@ func sweptAccrued(t *testing.T, body []byte) int {
// a temp DataDir, proving the package boots as the binary loads it.
func TestMount(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir(), Brand: "hanzo"}); err != nil {
t.Fatalf("Mount: %v", err)
}
+4 -5
View File
@@ -118,11 +118,10 @@ func routes(app cloud.Router, s *cloud.Service[struct{}]) {
g := app.Group("/v1/auto")
o := ops{s: s}
// Bridge FIRST: a typed op receives only a context, so the validated
// principal reaches it by being parked there — never as an In field,
// which is caller-supplied and would be a cross-tenant read the caller
// asserted for itself.
g.Use(cloud.Bridge())
// cloud.Bridge is not installed here: the composer installs it once at the
// root, after the identity check that mints the validated org and before any
// subsystem registers a route — an order only the whole program can assert.
// The ops below read what it parks off the context.
zip.Get(g, "/status", o.status)
zip.Get(g, "/pieces", o.pieces)
+1
View File
@@ -37,6 +37,7 @@ func liveApp(t *testing.T) *zip.App {
}
t.Setenv("AUTO_UPSTREAM", up)
app := zip.New(zip.Config{Logger: luxlog.New("autolive"), DisableStartupMessage: true})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("autolive"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+10
View File
@@ -241,6 +241,13 @@ func (f *fakeAuto) handler() http.Handler {
})
}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root, after
// the identity check that mints the validated org and before any subsystem
// registers a route. In production that composer is serve.go. In a test the test
// IS the composer, so it owes the same thing.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// harness mounts the app against a fake upstream and returns both.
func harness(t *testing.T) (*zip.App, *fakeAuto) {
t.Helper()
@@ -250,6 +257,7 @@ func harness(t *testing.T) (*zip.App, *fakeAuto) {
t.Setenv("AUTO_UPSTREAM", srv.URL)
app := zip.New(zip.Config{Logger: luxlog.New("autotest"), DisableStartupMessage: true})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("autotest"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
@@ -502,6 +510,7 @@ func TestEngineDown503Relays(t *testing.T) {
defer srv.Close()
t.Setenv("AUTO_UPSTREAM", srv.URL)
app := zip.New(zip.Config{Logger: luxlog.New("autotest"), DisableStartupMessage: true})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("autotest"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
@@ -522,6 +531,7 @@ func TestStatusIsAnHonestLens(t *testing.T) {
}
down := zip.New(zip.Config{Logger: luxlog.New("autotest"), DisableStartupMessage: true})
compose(down)
t.Setenv("AUTO_UPSTREAM", "http://127.0.0.1:1") // nothing listens
if err := Mount(down, cloud.Deps{Logger: luxlog.New("autotest"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
+3 -9
View File
@@ -204,15 +204,9 @@ type ops struct{ s *cloud.Service[state] }
// message and an address that lives only in the URL never arrives.
func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/automations")
// Bridge FIRST: a typed op receives only a context, so the validated org reaches
// it by being parked there — never as an In field, which is caller-supplied and
// would be a cross-tenant read the caller asserted for itself. fiber runs
// middleware in registration order, so this must precede the leaves below.
// Serve installs one for the whole binary; this one is what makes the SUBSYSTEM
// self-contained, so a harness that mounts it without Serve (this package's own
// tests) resolves the same org the server does. Nesting is harmless — the inner
// one is what the handler sees.
g.Use(cloud.Bridge())
// cloud.Bridge is installed by whoever composes the app — the fused host at
// its root — never here: the validated org still reaches every typed op below
// because the root install parks it on the context.
o := ops{s: s}
zip.Get(g, "/connectors", o.connectors)
+7 -8
View File
@@ -113,14 +113,13 @@ func Shutdown() error {
func routes(app cloud.Router, s *cloud.Service[*state]) {
g := app.Group("/v1/books")
// Bridge FIRST, then noStore: fiber runs middleware in registration order, so
// one installed after its leaves never runs. Bridge parks the VALIDATED org on
// the context, which is the only way a typed op — which receives a context and
// its decoded In and nothing else — can resolve its tenant; noStore carries the
// Cache-Control every books answer has always sent. Both are prefix-scoped, and
// nesting under Serve's own app-wide Bridge is harmless (the inner one is what
// the handler sees). See typed.go.
g.Use(cloud.Bridge(), noStore())
// noStore carries the Cache-Control header every books answer has always sent.
// It precedes the leaves because fiber runs middleware in registration order.
// cloud.Bridge is not installed here: the composer owns it — the fused host
// installs it once at its root, and the plugin constructor does the same for a
// plugin program — and typed ops read the validated org it parks on the
// context. See typed.go.
g.Use(noStore())
// TYPED ops, declared on the group: the prefix is part of each op's path and
// therefore of every projection — the document, the MCP tool, the CLI command,
+8
View File
@@ -37,11 +37,19 @@ import (
var wireCfg = zip.TestConfig{Timeout: 60 * time.Second, FailOnTimeout: true}
// compose installs what a host installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root, and
// in a test the test is the composer, so it owes the same install. A test that
// skips it does not test a stricter program — it tests one where every op that
// reads the org answers a refusal production can never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountBooks brings up the real /v1/books surface over a temp DataDir: the real
// router, the real middleware, the real stores.
func mountBooks(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
deps := cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}
if err := Mount(app, deps); err != nil {
t.Fatalf("mount: %v", err)
+4 -7
View File
@@ -195,13 +195,10 @@ type ops struct{ s *cloud.Service[state] }
// registration below. A typed op answers ONE marshalled value at ONE declared
// success status, and these three do not.
func routes(app cloud.Router, s *cloud.Service[state], deps cloud.Deps) {
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there. fiber runs middleware in registration
// order, so one installed after its leaves never runs. Installed through the
// scope's Use, once per declared prefix, so it lands on exactly the subtrees
// this subsystem declares (/v1/bot/connect, /v1/bot/nodes, /v1/bot/peer/invoke)
// rather than on a /v1/bot the scope does not own — which would fail the mount.
app.Use(cloud.Bridge())
// cloud.Bridge is not installed here. Whoever composes the program installs it
// once at the root — after the identity check that mints the validated org and
// before any subsystem registers a route (serve.go) — because that order is a
// property of the whole program and no subsystem can assert it for itself.
// One transport for the process, not one per dial: it carries the uptime a
// node reads out of the handshake, which is the process's, not the socket's.
+10
View File
@@ -20,6 +20,15 @@ import (
// an i/o timeout, which teaches nothing. The generous bound still fails a hang.
var botTestCfg = zip.TestConfig{Timeout: 30 * time.Second, FailOnTimeout: true}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root, after
// the identity check that mints the validated org and before any subsystem
// registers a route. In production that composer is serve.go. In a test the test
// IS the composer, so it owes the same thing — and a test that skips it does not
// test a stricter program, it tests a program where every org-scoped op answers
// 403 for a reason that would never exist in production.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountBot builds the surface over a registry the test controls, through the same
// routes() the binary calls — so what a test drives is the code that ships.
func mountBot(t *testing.T, reg *Registry) *zip.App {
@@ -30,6 +39,7 @@ func mountBot(t *testing.T, reg *Registry) *zip.App {
State: state{reg: reg},
}
app := zip.New(zip.Config{Logger: luxlog.New("test"), DisableStartupMessage: true})
compose(app)
routes(app, s, deps)
return app
}
+3 -6
View File
@@ -178,12 +178,9 @@ type ops struct{ s *cloud.Service[state] }
// route, the OpenAPI operation, the MCP tool, the CLI command and every generated
// SDK method follow. POST /v1/bots/run stays a raw handler; see run for why.
func routes(app cloud.Router, s *cloud.Service[state]) {
// Bridge FIRST: a typed op receives only a context, so the validated org reaches
// it by being parked there — never as an input field, which is caller-supplied.
// fiber runs middleware in registration order, so one installed after its leaves
// never runs. Installed through the SUBSYSTEM's own router, which scopes it to
// the prefix this app declares (/v1/bots) rather than the whole binary.
app.Use(cloud.Bridge())
// The composer owns cloud.Bridge: the fused host installs it once at its root
// and the plugin constructor does the same for a plugin program, so no
// subsystem installs it.
// UNIFIED PAYWALL (server-side enforcement). To gate this group behind the
// caller's plan, prepend the middleware to the group:
+8
View File
@@ -94,6 +94,13 @@ func (f *fakeRuntime) has(org, id string) bool {
return ok
}
// compose installs what a host installs. A subsystem never installs cloud.Bridge:
// the program's composer owns it — serve.go at the root of the fused host, the
// plugin constructor for a plugin program. In a test the test is the composer, so
// it owes the same install; skipping it drives a program where every org-scoped op
// answers 403 for a reason production callers never see.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountWith builds the surface over an injected runtime, exactly as Mount does over
// the real one — routes() is the shared registration path, so what a test drives is
// the code that ships.
@@ -105,6 +112,7 @@ func mountWith(t *testing.T, rt Runtime) *zip.App {
State: state{gateway: gatewayBase(), runtime: rt},
}
app := zip.New(zip.Config{Logger: luxlog.New("test"), DisableStartupMessage: true})
compose(app)
routes(app, s)
return app
}
+1
View File
@@ -80,6 +80,7 @@ func mountFleet(t *testing.T, rt *stubRuntime) *zip.App {
t.Setenv(gatewayURLEnv, "https://bot.example.test")
rt.start(t)
app := zip.New(zip.Config{Logger: luxlog.New("test"), DisableStartupMessage: true})
compose(app)
deps := cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}
if err := visor.Mount(app, deps); err != nil { // Wire order: visor first — the shadowing mount
t.Fatalf("visor.Mount: %v", err)
+6 -6
View File
@@ -139,13 +139,13 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
func routes(app cloud.Router, zapp *zip.App, s *cloud.Service[state]) {
o := ops{s: s}
g := app.Group("/v1/campaign")
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there — never as an In field, which is
// A typed op receives only a context, so the validated org it reads is parked
// there by cloud.Bridge — never carried as an In field, which is
// caller-supplied and would be a cross-tenant read the caller asserted for
// itself. fiber runs middleware in registration order, so this must precede
// every leaf below; nesting under Serve's own Bridge is harmless (the inner
// one is what the handler sees).
g.Use(cloud.Bridge())
// itself. This subsystem does not install the bridge: the program's composer
// does, once at the root, after the identity check that mints the org and
// before any subsystem registers a route — an order only the composer can
// hold.
zip.Get(g, "/summary", o.summary)
+8
View File
@@ -29,9 +29,17 @@ import (
const wireTimeout = 10 * time.Second
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer does, once at the root. In a test
// the test IS the composer, so it owes the same install — skipping it does not
// test a stricter program, it tests one where every org-scoped op answers 403
// for a reason production could never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mountWire(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
-7
View File
@@ -125,13 +125,6 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// which of its fields does that.
func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/captable")
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there — never as an In field, which is
// caller-supplied and would be a cross-tenant read the caller asserted for
// itself. fiber runs middleware in registration order, so this must precede
// the leaves below; it is prefix-scoped, and nesting under Serve's own Bridge
// is harmless (the inner one is what the handler sees).
g.Use(cloud.Bridge())
// Then the bundle's own envelope: a typed op that must answer the bundle's
// 400/404/409/500 returns a goja.BundleErr, and this writes those bytes back
// verbatim. Also before the leaves, for the same registration-order reason.
+1
View File
@@ -15,6 +15,7 @@ import (
func mountForFacade(t *testing.T) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+7
View File
@@ -15,6 +15,12 @@ import (
"github.com/zap-proto/zip"
)
// compose installs what the program's composer installs — cloud.Bridge, once at
// the app root. A subsystem never installs its own, so a test app owes the same
// root install; without it every org-scoped op answers a 403 no production
// program would produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountApp builds a bare zip.App (no SanitizeIdentity middleware, so X-Org-Id +
// X-User-Id are trusted verbatim — the standard cloud leaf test harness) and
// mounts the captable leaf on it. This exercises the REAL HTTP path: routing →
@@ -23,6 +29,7 @@ import (
func mountApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+3 -4
View File
@@ -433,13 +433,12 @@ func TestScalarCarriesEveryJSONToken(t *testing.T) {
// newAppMCP mounts captable the way the SERVER does: one cloud.Bridge at the app
// ROOT. zip's own projections of the typed-op registry — the MCP endpoint at /mcp
// and the call plane at /.well-known/zip/op/ — are ordinary routes on the app
// itself, so they sit OUTSIDE the /v1/captable group and the group's own Bridge
// never runs for them. cloud.Listen installs the root one, which is what gives them
// a validated org in production.
// itself, outside the /v1/captable group, so only the root install reaches them.
// cloud.Listen makes that root install in production.
func newAppMCP(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
app.Use(cloud.Bridge())
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+10 -19
View File
@@ -219,27 +219,18 @@ func build(b cloud.Base) (state, error) {
// routes registers the lens.
//
// Bridge FIRST and BEFORE the leaf: fiber runs middleware in registration order,
// so one installed after its route never runs. A typed op receives only a
// context, so the validated org reaches it by being parked there — never as an
// In field, which is caller-supplied and would be a cross-tenant read the caller
// asserted for itself. Serve installs one app-wide too; nesting is harmless, and
// this package's own tests mount on a bare app with no Serve, so this install is
// what makes them pass.
// A typed op receives only a context, so the validated org reaches it by being
// parked there — never as an In field, which is caller-supplied and would be a
// cross-tenant read the caller asserted for itself. cloud.Bridge parks it, and
// the COMPOSER installs it, not this subsystem: the fused host once at its root
// (serve.go), and a plugin program's constructor likewise. The install this
// subsystem used to make sat on a group with no routes beneath it, a program zip
// refuses to compose.
//
// USE, NOT A MIDDLEWARE-CARRYING GROUP — the same correction as auditlog, for
// the same reason. This used to say `app.Group("/v1/catalog", Bridge())`, but
// the op below is declared on the App with its WHOLE path, so no route sits
// beneath that group; middleware over an empty subtree can never run, and zip
// refuses to compose it. Use is the ONE composition verb, and it means the right
// thing through both routers: cloud's scope gates it to this subsystem's
// declared subtrees, and a bare *zip.App treats root middleware as always-live.
//
// The op keeps its WHOLE path rather than moving to a group with an empty leaf:
// joining "/v1/catalog" with "" yields "/v1/catalog/", a different path from the
// one this API has always served, and one that would ship in OpenAPI and the SDK.
// The op is declared on the App with its WHOLE path, not on a group with an
// empty leaf: joining "/v1/catalog" with "" yields "/v1/catalog/", a different
// path from the one this API has always served.
func routes(app cloud.Router, s *cloud.Service[state]) {
app.Use(zip.H(cloud.Bridge()))
o := ops{s: s}
zip.Get(cloud.ZipApp(app), "/v1/catalog", o.browse)
}
+7
View File
@@ -15,11 +15,18 @@ import (
"github.com/zap-proto/zip"
)
// compose installs what a host installs. A subsystem never installs cloud.Bridge
// (routes says why): the program's composer owns it — serve.go in production — so
// a test app owes the same install, else every org-scoped op answers 403 for a
// reason no composed program has.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mount brings up the index (the store) and the catalog (the lens) on one app,
// exactly as apps.go orders them.
func mount(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{DisableStartupMessage: true})
compose(app)
deps := cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}
if err := index.Mount(app, deps); err != nil {
t.Fatalf("index.Mount: %v", err)
+7
View File
@@ -54,6 +54,12 @@ type testEnv struct {
dataDir string
}
// compose gives the test app what every real composer gives its program: the
// fused host installs cloud.Bridge at its root and a plugin program's
// constructor does the same, so a bare test app that skipped it would answer
// 403 for a reason production can never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// newApp mounts channels exactly as apps.go does. Integrations stays
// unmounted on purpose: LinkedSubject fails soft (empty UserID),
// OrgForExternalID / ConnectionFor answer not-found — the fail-closed side
@@ -62,6 +68,7 @@ func newApp(t *testing.T) *testEnv {
t.Helper()
logs := &syncBuf{}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
dataDir := t.TempDir()
deps := cloud.Deps{Logger: luxlog.NewWriter(logs), DataDir: dataDir, Domain: "api.hanzo.ai"}
if err := Mount(app, deps); err != nil {
+3 -7
View File
@@ -52,14 +52,10 @@ func routes(app cloud.Router, s *cloud.Service[state]) error {
if zapp == nil {
return fmt.Errorf("channels.Mount: router exposes no zip.App, so no typed op could be registered")
}
// A typed op receives only a context, so the validated org has to be parked
// there. cloud.Bridge parks it, and the composer owns that install: the
// fused host at its root, a plugin program in its constructor.
g := app.Group("/v1/channels")
// The Bridge FIRST, bounded to the subtree channels owns: a typed op receives
// only a context, so the validated org has to be parked there, and fiber runs
// middleware in registration order — one installed after these leaves would
// never run. cloud.Listen installs one app-wide too; nesting is harmless, and
// having it here is what makes this package's own tests — which mount on a
// bare app — exercise the same tenancy the binary does.
g.Use(cloud.Bridge())
o := ops{s: s}
// cloud.Terminal is func(func(*zip.Ctx) error) func(*zip.Ctx) error; zip.Middleware
+1
View File
@@ -331,6 +331,7 @@ func meteredHarness(t *testing.T, tokens map[string]string, rec *capture, result
t.Cleanup(func() { tokenFor = prev })
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir(), Metering: m}); err != nil {
t.Fatalf("Mount: %v", err)
}
+5 -7
View File
@@ -171,13 +171,11 @@ func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/cloudflare")
o := ops{s: s}
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there — never as an In field, which is
// caller-supplied and would be a cross-tenant read the caller asserted for
// itself. fiber runs middleware in registration order, so this must precede
// the leaves below; it is prefix-scoped, and nesting under Serve's own Bridge
// is harmless (the inner one is what the handler sees).
g.Use(cloud.Bridge())
// A typed op receives only a context, so the validated org reaches it by
// being parked there — never as an In field, which is caller-supplied and
// would be a cross-tenant read the caller asserted for itself. cloud.Bridge
// does the parking, and the composer owns that install, once at its root;
// this group is a bare path prefix.
// Zones + Analytics (read) — enumerate the org's zones and read a zone's traffic
// analytics; the zone ids feed Workers routes and analytics. Zone/record
+8
View File
@@ -87,6 +87,13 @@ func fakeCF(rec *capture, resultFor func(path string) (int, string)) http.Handle
}
}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root. In a
// test the test IS the composer, so it owes the same thing — a test that skips it
// tests a program where every org-scoped op answers 403 for a reason that would
// never exist in production. Same helper apps/integrations uses.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// harness mounts the subsystem against a fake CF and per-org token seam.
func harness(t *testing.T, tokens map[string]string, rec *capture, resultFor func(string) (int, string)) *zip.App {
t.Helper()
@@ -108,6 +115,7 @@ func harness(t *testing.T, tokens map[string]string, rec *capture, resultFor fun
t.Cleanup(func() { tokenFor = prev })
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+6 -10
View File
@@ -105,18 +105,14 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
}
// routes registers the /v1/code surface. It is a FUNCTION rather than inline in
// Mount so this package's own tests drive the REAL registration — the Bridge
// included — instead of a reconstruction of it that can drift from what the
// binary serves.
// Mount so this package's own tests drive the REAL registration instead of a
// reconstruction of it that can drift from what the binary serves.
func routes(app cloud.Router, s *service) error {
g := app.Group("/v1/code")
// The Bridge FIRST, bounded to the subtree code owns: a typed op receives only
// a context, so the validated org has to be parked there, and fiber runs
// middleware in registration order — one installed after these leaves would
// never run. cloud.Listen installs one app-wide too; nesting is harmless, and
// having it here is what makes this package's own tests — which mount on a
// bare app — exercise the same tenancy the binary does.
g.Use(cloud.Bridge())
// cloud.Bridge is not installed here: the composer installs it once at the
// root, after the identity check that mints the validated org and before any
// subsystem registers a route — an order only the whole program can assert.
// The ops below read what it parks off the context.
// Every route is a TYPED op: one registry entry, which is what the OpenAPI
// operation, the MCP tool, the CLI command and every generated SDK method are
+10 -3
View File
@@ -69,14 +69,21 @@ func newTestService(t *testing.T) *service {
return s
}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root, after
// the identity check that mints the validated org and before any subsystem
// registers a route. In production that composer is serve.go. In a test the test
// IS the composer, so it owes the same thing.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func newTestApp(t *testing.T) (*zip.App, *service) {
t.Helper()
s := newTestService(t)
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
// The REAL registration, not a reconstruction of it: routes() is what Mount
// calls, so the Bridge that carries the validated org to every typed op is
// exercised here exactly as the binary installs it. A hand-listed copy drifts
// silently the first time a route moves.
// calls, so every typed op is exercised here exactly as the binary serves it.
// A hand-listed copy drifts silently the first time a route moves.
if err := routes(app, s); err != nil {
t.Fatalf("routes: %v", err)
}
+3 -2
View File
@@ -219,8 +219,9 @@ func TestSearchDegradedKeyIsConditional(t *testing.T) {
// TestFailsClosedWithoutAValidatedPrincipal is the tenancy claim: no request
// field can name the tenant, so an anonymous caller reads and writes nothing —
// and the Bridge routes() installs is what carries the validated org to every op,
// so this also proves that middleware precedes the leaves.
// and compose has installed cloud.Bridge at the root exactly as the program's
// composer does, so each 403 is an op refusing a missing org, never an artifact
// of a missing install.
func TestFailsClosedWithoutAValidatedPrincipal(t *testing.T) {
app, _ := newTestApp(t)
for _, r := range []struct {
+3 -8
View File
@@ -185,14 +185,9 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
func routes(app cloud.Router, zapp *zip.App, s *cloud.Service[state]) {
o := ops{s: s}
g := app.Group("/v1/company")
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there — never as an In field, which is
// caller-supplied and would be a cross-tenant read the caller asserted for
// itself. fiber runs middleware in registration order, so this must precede
// every leaf below; it is prefix-scoped, and nesting under Serve's own Bridge
// is harmless (the inner one is what the handler sees). It also carries the
// 201 an op cannot state in its own signature — see begin.
g.Use(cloud.Bridge())
// cloud.Bridge is installed by whoever composes the app — the fused host at
// its root — never here. The root install is also what carries begin's 201
// back out (cloud.Created writes into the slot that install parked).
// UNTYPED, and registered HERE so the body cap below never applies to it: the
// deck is document BYTES, not JSON, and its size ceiling has always been the
+5 -6
View File
@@ -146,12 +146,11 @@ func init() {
// split its two 200 shapes (reconciled check vs benign unknown-reference no-op).
func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group(routePrefix)
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there — never as an In field, which is
// caller-supplied and would be a cross-tenant read the caller asserted for
// itself. fiber runs middleware in registration order, so this precedes the
// leaves below.
g.Use(cloud.Bridge())
// cloud.Bridge is not installed here: the composer owns it — the fused host
// installs it once at its root, and the plugin constructor does the same for a
// plugin program — and typed ops read the validated org it parks on the
// context. bodyCap precedes the leaves because fiber runs middleware in
// registration order.
g.Use(bodyCap())
o := ops{s: s}
+9
View File
@@ -45,6 +45,13 @@ func (f fakeProvider) Check(context.Context, string, string) (idv.Result, error)
return idv.Result{Ref: "ref_" + f.name, Status: f.checkStatus}, nil
}
// compose installs what a host installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root, and
// in a test the test is the composer, so it owes the same install. A test that
// skips it does not test a stricter program — it tests one where every op that
// reads the org answers a refusal production can never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mount brings compliance up on a bare app with a real audit recorder, and
// returns the app + the recorder for assertions. The provider defaults to Manual.
func mount(t *testing.T) (*zip.App, *audit.Recorder) {
@@ -55,6 +62,7 @@ func mount(t *testing.T) (*zip.App, *audit.Recorder) {
t.Fatalf("audit.Open: %v", err)
}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir(), Audit: rec}); err != nil {
t.Fatalf("Mount: %v", err)
}
@@ -173,6 +181,7 @@ func mountWithWebhook(t *testing.T, secret string) *zip.App {
t.Fatalf("audit.Open: %v", err)
}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
deps := cloud.Deps{
Logger: luxlog.New("test"), DataDir: t.TempDir(), Audit: rec,
KMS: fakeKMS{ref: "kms://idv-webhook", secret: []byte(secret)},
+1 -1
View File
@@ -27,7 +27,7 @@ func doRaw(t *testing.T, app *zip.App, rq *http.Request) *http.Response {
}
// TestHealthNeedsNoPrincipal pins the ONE route on this surface that does not
// read a tenant. It is the route the group's cloud.Bridge could most easily have
// read a tenant. It is the route the composer's cloud.Bridge could most easily have
// broken: Bridge is what parks the validated org for every other op, and if it
// REFUSED a request that carries no org, installing it in front of the leaves
// would have turned liveness into a 403 — the failure mode where a subsystem
+6 -7
View File
@@ -36,13 +36,12 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
}
log := deps.Logger
g := app.Group("/v1/automations/connectors")
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there — never as an In field, which is
// caller-supplied. When this package is mounted through automations.Mount the
// automations group's Bridge already covers the path; this one is what makes
// the SUBSYSTEM self-contained when mounted alone. Nesting is harmless — the
// inner one is what the handler sees.
g.Use(cloud.Bridge())
// cloud.Bridge is not installed here. Whoever composes the program installs it
// once at the root — after the identity check that mints the validated org and
// before any subsystem registers a route (serve.go) — because that order is a
// property of the whole program and no subsystem can assert it for itself. The
// validated org still reaches the typed op only off the context, never as an
// In field, which is caller-supplied.
zip.Post(g, "/:id/run", run)
if log != nil {
log.New("subsystem", "connectorruntime").Info(
+11 -2
View File
@@ -14,12 +14,21 @@ import (
"github.com/zap-proto/zip"
)
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (Mount says why): the program's composer installs it once at the root, after
// the identity check that mints the validated org and before any subsystem
// registers a route. In production that composer is serve.go. In a test the test
// IS the composer, so it owes the same thing — and a test that skips it does not
// test a stricter program, it tests a program where every org-scoped op answers
// 403 for a reason that would never exist in production.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// newApp mounts connectorruntime ALONE — no automations group around it — which is
// what proves the subsystem self-contained: its own Bridge is the only thing that
// parks the org the typed op resolves.
// what proves the subsystem composes on its own.
func newApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test")}); err != nil {
t.Fatalf("Mount: %v", err)
}
+3 -9
View File
@@ -100,17 +100,11 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
// channels/generate/publish) never collide with the parameterised transition route
// (which is three segments deep), so registration order is not load-bearing here.
//
// cloud.Bridge is installed on the group FIRST, ahead of every leaf: a typed op
// receives a context.Context and its decoded In and nothing else, so the validated
// org crosses on the context and there is no request for it to read. Serve installs
// the same middleware for the whole binary, and nesting is harmless (the inner one
// is the one the handler sees) — it is declared here so the subsystem is
// self-sufficient: mounted on a bare app, by a test or by any composition root that
// is not Serve, its typed ops still resolve their tenant instead of refusing every
// caller.
// The composer owns cloud.Bridge: the fused host installs it once at its root
// and the plugin constructor does the same for a plugin program, so no
// subsystem installs it.
func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/content")
g.Use(cloud.Bridge())
o := contentOps{s: s}
zip.Get(g, "/lifecycle", o.getLifecycle)
zip.Get(g, "/board", o.getBoard)
+8
View File
@@ -111,9 +111,17 @@ func TestEnforceLifecycleHook(t *testing.T) {
// ---- integration: the loop end-to-end over the REAL framework store ----
// compose installs what a host installs. A subsystem never installs cloud.Bridge:
// the program's composer owns it — serve.go at the root of the fused host, the
// plugin constructor for a plugin program. In a test the test is the composer, so
// it owes the same install; skipping it drives a program where every org-scoped op
// answers 403 for a reason production callers never see.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mountContent(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := framework.Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("framework.Mount: %v", err)
}
+1
View File
@@ -108,6 +108,7 @@ func mountWith(t *testing.T, deps cloud.Deps) *zip.App {
deps.Domain = "api.test"
}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := framework.Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("framework.Mount: %v", err)
}
+5 -7
View File
@@ -165,13 +165,11 @@ type ops struct{ s *cloud.Service[state] }
// roll-up, and the Startup Program application intake.
func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/crm")
// Bridge FIRST: a typed op receives only a context, so the validated org
// reaches it by being parked there. fiber runs middleware in registration
// order, so one installed after its leaves never runs. Serve installs the same
// bridge for the whole binary; nesting is harmless (the inner one is what the
// handler sees) and this keeps the subsystem's ops org-scoped wherever it is
// mounted — including a test app that never calls Serve.
g.Use(cloud.Bridge())
// A typed op receives only a context, so the validated org it reads is parked
// there by cloud.Bridge. This subsystem does not install it: the program's
// composer does, once at the root, after the identity check that mints the org
// and before any subsystem registers a route — an order only the composer can
// hold.
// Declared on the GROUP: the op's path is the prefix composed with the leaf,
// which is the identity every projection keys on, and cmd/zipdoc (zip v1.18.3+)
+8
View File
@@ -13,9 +13,17 @@ import (
"github.com/zap-proto/zip"
)
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer does, once at the root. In a test
// the test IS the composer, so it owes the same install — skipping it does not
// test a stricter program, it tests one where every org-scoped op answers 403
// for a reason production could never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mountApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+1
View File
@@ -48,6 +48,7 @@ const product = "risk"
func published(t *testing.T) *openapi.Document {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("datasettest"), DisableStartupMessage: true})
compose(app)
if err := mount(newPlane(&fake{}), app); err != nil {
t.Fatalf("mount: %v", err)
}
+11 -17
View File
@@ -147,16 +147,16 @@ type scan struct {
since time.Time
}
// Mount wires the dataset leaves of /v1/risk onto app.
// Mount registers the dataset leaves of /v1/risk onto app.
//
// EVERY INHERITED CAPABILITY IS WIRED HERE, EXPLICITLY. Being embedded in cloud
// EVERY INHERITED CAPABILITY IS NAMED HERE, EXPLICITLY. Being embedded in cloud
// makes each one AVAILABLE; none is automatic:
//
// IAM auth SanitizeIdentity mints X-Org-Id from the verified bearer, in
// serve.go. This app never validates a token and never can.
// tenant gate cloud.Bridge() on the group, FIRST, before any leaf — a typed op
// receives only a context, and Bridge is what parks the validated
// org in it. fiber orders middleware by registration.
// tenant gate cloud.Bridge parks the validated org on the context a typed op
// receives; it is the composer's install — once at the root of
// every program — so this package does not install it.
// meter+gate cloud.NewResourceMeter(deps, "dataset"); Gate before the one
// priced op and Meter after it.
// logs cloud.NewBase(deps, "dataset") gives the scoped logger.
@@ -226,28 +226,22 @@ func (p *plane) ready(ctx context.Context) error {
// plane came from — the same split apps/ml makes, for the same reason: a test
// pins the plane and exercises the wire.
func mount(p *plane, app cloud.Router) error {
// TWO SEAMS, EACH FOR WHAT IT IS FOR.
//
// app.Use installs the tenant bridge ONCE PER DECLARED PREFIX — the scope
// reads manifest.Apps for that — so the middleware lands exactly on
// /v1/risk/datasets and nowhere else. Grouping at /v1/risk to get a shorter leaf
// would install it across a subtree this app does not own — that stem is the
// decision plane's — which is the escape the scope exists to refuse.
//
// cloud.ZipApp recovers the typed-op registry, which the Router interface does
// not carry, and the ops register at ABSOLUTE paths on it. That is what keeps
// the published address exactly `/v1/risk/datasets` — a group root composes to
// `/v1/risk/datasets/`, and a trailing slash in the document is a trailing slash
// in every generated SDK.
//
// Bridge FIRST, before any leaf: a typed op receives only a context, and this
// is what parks the validated org that tenant.Of reads. fiber runs middleware
// in registration order, so an install after its leaves never runs.
// cloud.Bridge is the composer's install — once at the root of every program —
// so this package installs only its own envelope. app.Use lands that ONCE PER
// DECLARED PREFIX — the scope reads manifest.Apps for that — so it covers
// /v1/risk/datasets and nowhere else; grouping at /v1/risk for a shorter leaf
// would spread it across a subtree this app does not own — that stem is the
// decision plane's — which is the escape the scope exists to refuse.
z := cloud.ZipApp(app)
if z == nil {
return fmt.Errorf("dataset.Mount: the router carries no typed-op registry")
}
app.Use(cloud.Bridge())
// DenyEnvelope renders a gate refusal as the money wire's own bytes, the same
// ones every other Hanzo surface emits — one error contract for "no funds"
// across the fleet instead of this plane's private spelling of it. It touches
+7
View File
@@ -83,9 +83,16 @@ func (l *ledger) charged() []int64 {
return append([]int64(nil), l.debit...)
}
// compose installs what the program's composer installs — cloud.Bridge, once at
// the app root. A subsystem never installs its own, so a test app owes the same
// root install; without it every org-scoped op answers a 403 no production
// program would produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mountHTTP(t *testing.T, p *plane) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
if err := mount(p, app); err != nil {
t.Fatalf("mount: %v", err)
}
+1
View File
@@ -29,6 +29,7 @@ import (
func projections(t *testing.T) (served map[string]bool, typed map[string]*openapi.Operation) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("datasettest"), DisableStartupMessage: true})
compose(app)
if err := mount(newPlane(&fake{}), app); err != nil {
t.Fatalf("mount: %v", err)
}
+1
View File
@@ -25,6 +25,7 @@ import (
func listApplicationsAs(t *testing.T, s *cloud.Service[state], headers map[string]string) (int, map[string]any) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, s)
req := httptest.NewRequest("GET", "/v1/deploy/applications", nil)
for k, v := range headers {
+15
View File
@@ -0,0 +1,15 @@
package deploy
import (
"github.com/hanzoai/cloud"
"github.com/zap-proto/zip"
)
// compose stands in for the composer. Production programs are built by
// cloud.App, which installs the principal enrichment once at the root before
// any route; a test that mounts this subsystem on a bare app owns that duty
// itself, exactly once, here. A test that sends no identity is unaffected —
// with nothing validated there is nothing to park — so anonymous cases still
// refuse, and principal-carrying cases reach the handler as they do in
// production.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
+6 -2
View File
@@ -48,7 +48,7 @@ const dashPrefix = "/v1/deploy"
// registerDashboardRoutes wires the ArgoCD-UI-compatible API surface (no FE —
// the SPA is a separate hanzoai/spa App). Called from routes() (deploy.go), which
// owns the group and installs the bridge and the sign-in bounce on it.
// installs the sign-in bounce so it covers this prefix.
//
// Every READ here is a TYPED op declared on that group, so the op's path is the
// prefix composed with the leaf — the identity every projection keys on — and the
@@ -62,7 +62,11 @@ func registerDashboardRoutes(app cloud.Router, s *cloud.Service[state]) {
// `g := <router>.Group("/prefix")` in the SAME file, and a prefix it cannot
// resolve is prose filed under the wrong path and silently dropped from both the
// document and the MCP tool — so it refuses, naming the file, the line and this
// fix. routes() (deploy.go) hangs the group's middleware off the same prefix.
// fix. The group is a bare path prefix carrying NO middleware, which is what
// keeps it composable: the leaves below register through THIS node, and
// middleware belongs on the root gated by path (routes(), deploy.go), because a
// second Group at the same prefix would be a fresh node — middleware there
// stands beside these routes, not above them, and zip judges the node.
g := app.Group(dashPrefix)
o := ops{s: s}
+4
View File
@@ -28,6 +28,7 @@ import (
func getJSON(t *testing.T, s *cloud.Service[state], path string) map[string]any {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, s)
req := httptest.NewRequest("GET", path, nil)
req.Header.Set("X-User-IsAdmin", "true")
@@ -136,6 +137,7 @@ func TestDashProjectsEndpoint_PrefersRealCRs(t *testing.T) {
// the SuperAdmin claim (fail-closed, no fleet/cluster data to an anonymous caller).
func TestNewRoutesRequireAdmin(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, fakeService())
for _, path := range []string{"/v1/deploy/clusters", "/v1/deploy/projects", "/v1/deploy/stream/applications"} {
// EventSource sends Accept: text/event-stream + Sec-Fetch-Dest: empty, so a
@@ -162,6 +164,7 @@ func TestNewRoutesRequireAdmin(t *testing.T) {
// the writer eagerly on SendStreamWriter — see setStreamHeaders).
func TestStreamSetsSSEHeaders(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
c := app.TestCtx("GET", "/v1/deploy/stream/applications")
setStreamHeaders(c)
resp := c.Fiber().Response()
@@ -184,6 +187,7 @@ func TestStreamSetsSSEHeaders(t *testing.T) {
func TestStreamFailsClosedWithoutCluster(t *testing.T) {
noK8s := &cloud.Service[state]{Base: cloud.Base{Log: luxlog.New("test")}, State: state{initErr: "no kubeconfig"}}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
c := app.TestCtx("GET", "/v1/deploy/stream/applications")
err := dashStreamApps(noK8s, c)
if err == nil {
+2
View File
@@ -17,6 +17,7 @@ import (
// /v1/deploy/ui route without wrapping it in guard() breaks this test.
func TestDeployRoutesRequireAdmin(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, fakeService()) // the COMPLETE surface: native + engine + dashboard
guarded := []struct{ method, path string }{
@@ -109,6 +110,7 @@ func TestDeployRoutesRequireAdmin(t *testing.T) {
// anonymous answer carries the sign-in URL and NOTHING that identifies anyone.
func TestUserInfoIsPublicBootstrap(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, fakeService())
resp, err := app.Test(httptest.NewRequest("GET", "/v1/deploy/session/userinfo", nil))
+20 -25
View File
@@ -296,35 +296,30 @@ func init() {
// routes registers the /v1/deploy/* surface. Every observing/mutating route is
// SuperAdmin-gated; the health probe is public (real k8s reachability).
//
// The first statement is the plane's MIDDLEWARE, hung on the /v1/deploy prefix so
// it reaches every route below — the typed ops in dashboard.go included, which
// register their own leaves on the same prefix. It carries the two facts every
// route beneath it needs:
//
// - cloud.Bridge, which parks the request on the context so a TYPED op — which
// receives only a context — can still reach the validated principal its
// scope is derived from (typed.go). Serve installs the same bridge for the
// whole binary; nesting is harmless (the inner one is what the handler sees)
// and this keeps the ops scoped wherever they are mounted, including a test
// app that never calls Serve.
// - bounce, which turns a REFUSED browser navigation into the sign-in redirect
// (scope.go). It is one rule for the typed ops and the raw handlers alike.
// The first statement is bounce, which turns a REFUSED browser navigation into the
// sign-in redirect (scope.go) — one rule for the typed ops in dashboard.go and the
// raw handlers here alike. It is deploy's own presentation rule and nothing else:
// the request every typed op reads its principal off is parked on the context by
// whoever composes the app, so this surface installs no bridge of its own.
//
// It is installed FIRST: fiber runs middleware in registration order, so one
// installed after its leaves never runs.
//
// It goes on the ROOT rather than on a Group(dashPrefix) node, and cloud.Router
// confines it by PATH — scope.Use gates every request on the prefixes deploy
// declares (scope.go, manifest/apps.go). The group form put the middleware on a
// node of its own: each Group call makes a fresh node, so it stood beside — not
// above — the node dashboard.go creates for its leaves, and zip judges the node,
// not the path, so it refuses to compose middleware no route beneath it can reach.
// Deploy declares its subtree as an explicit list of /v1/deploy/<resource> paths
// rather than /v1/deploy itself, and that list covers every route registered here:
// health, login, callback, logout, reconcile, and the dashboard's settings,
// session/userinfo, version, account/can-i, applications, stream/applications,
// clusters, projects and gitops. What the change drops is /v1/deploy paths with no
// route, which answer 404 — and bounce reshapes a 403 and nothing else, so their
// answer is what it was.
func routes(app cloud.Router, s *cloud.Service[state]) {
// ON THE ROUTER, not on a Group(dashPrefix) of its own. This read
// `app.Group(dashPrefix).Use(...)`, and the routes it meant to wrap are
// composed under a DIFFERENT app.Group(dashPrefix) — the one dashboard.go
// builds. Group returns a NEW definition on every call, so those are two nodes
// at the same path: the middleware sat on the empty one, and NEITHER
// cloud.Bridge NOR bounce ever ran for a single route of this surface. Every
// prefix this subsystem declares is under dashPrefix (manifest/apps.go), so a
// scope bounds this to exactly what the group named, and the plugin binary
// serves nothing else — the bound is unchanged, it is now a predicate over the
// request rather than a place in the tree that the routes turned out not to be
// in.
app.Use(cloud.Bridge(), zip.H(bounce))
app.Use(zip.H(bounce))
// Liveness — public (probe-able without a JWT). It stays a RAW handler because
// it answers 503 carrying the SAME domain body as its 200 (status + the k8s and
+1
View File
@@ -110,6 +110,7 @@ func TestGitOpsHistoryCap(t *testing.T) {
func TestGitOpsGuarded(t *testing.T) {
s := fakeService()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, s)
resp, err := app.Test(httptest.NewRequest("GET", "/v1/deploy/gitops", nil))
if err != nil {
+3
View File
@@ -99,6 +99,7 @@ func TestWantsDocument(t *testing.T) {
// navigation gets bounced to sign-in. Neither is ever served the data.
func TestGuardRefusesNonAdmin(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, fakeService())
// API call (no Accept, the shape every API client and the existing e2e sends).
@@ -364,6 +365,7 @@ func TestSignInFailsClosedWithoutPublicOrigin(t *testing.T) {
verify: func(string) (cloud.VerifiedIdentity, error) { return cloud.VerifiedIdentity{}, nil },
} // publicURL deliberately empty
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, svc)
// A forged Host must NOT be adopted as the origin.
@@ -613,6 +615,7 @@ func signinApp(t *testing.T, issuer string) (*zip.App, *fakeIAM) {
},
}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, svc)
return app, iam
}
+3 -2
View File
@@ -121,8 +121,9 @@ func navigating(c *zip.Ctx) bool {
}
// bounce turns a REFUSED browser navigation into the sign-in redirect, and leaves
// every other answer alone. Installed once, on the /v1/deploy group (routes,
// deploy.go), so it covers the typed ops and the raw handlers with one rule.
// every other answer alone. Installed once, on the root and confined by path to
// the /v1/deploy prefixes this subsystem declares (routes, deploy.go), so it
// covers the typed ops and the raw handlers with one rule.
//
// It reads the ANSWER, not the caller: a 403 is the only thing it reshapes, and
// only for a request that positively identifies as a document GET — so the API
+2
View File
@@ -48,6 +48,7 @@ func orgAppCR(ns, name, org, project string) *unstructured.Unstructured {
func getAs(t *testing.T, s *cloud.Service[state], path string, headers map[string]string) *http.Response {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, s)
req := httptest.NewRequest("GET", path, nil)
for k, v := range headers {
@@ -97,6 +98,7 @@ func appNames(body map[string]any) map[string]bool {
func probeScope(t *testing.T, headers map[string]string) (scope, bool) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
var got scope
var ok bool
app.Get("/probe", func(c *zip.Ctx) error {
+1
View File
@@ -25,6 +25,7 @@ func fakeGit(t *testing.T, rev string, files []plane.File, fault error) {
t.Setenv("ZIP_RUNTIME_DIR", t.TempDir())
app := zip.New(zip.Config{AppName: "git", Logger: luxlog.New("gittest")})
compose(app)
zip.Post[plane.FilesIn, plane.Files](app, "/git/files",
func(ctx context.Context, _ *plane.FilesIn) (*plane.Files, error) {
if fault != nil {
+3
View File
@@ -37,6 +37,7 @@ import (
func probe(t *testing.T, s *cloud.Service[state], req *http.Request) (int, string) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, s)
resp, err := app.Test(req)
if err != nil {
@@ -132,6 +133,7 @@ func TestRefusalIsA403AndANavigationIsBounced(t *testing.T) {
nav := httptest.NewRequest(http.MethodGet, path, nil)
nav.Header.Set("Sec-Fetch-Dest", "document")
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, s)
resp, err := app.Test(nav)
if err != nil {
@@ -246,6 +248,7 @@ func TestPostsStayRawBecauseZipDecodesTheBodyFirst(t *testing.T) {
// carries prose. Nothing on this plane publishes an operationId and nothing else.
func TestEveryTypedOpIsInTheDocumentWithProse(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
routes(app, fakeService())
doc, err := openapi.Spec(app, openapi.Info{Title: "deploy", Version: "v1"})
if err != nil {
+5 -8
View File
@@ -150,15 +150,12 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
//
// Registration order is match order, and it is the order it has always been.
func routes(app cloud.Router, zapp *zip.App, s *cloud.Service[state]) {
// The bridge FIRST, bounded to destinations' own subtree: a typed op receives
// only a context, so the validated org has to be parked there, and fiber runs
// middleware in registration order — one installed after these leaves would
// never run. cloud.Listen installs one app-wide too; nesting is harmless (the
// inner one is what the handler sees), and having it here is what makes this
// package's own tests — which mount on a bare zip.App — exercise the same
// tenancy the binary does.
// A typed op receives only a context, so the validated org has to be parked
// there. cloud.Bridge parks it, and the COMPOSER installs it, not this
// subsystem: the fused host once at its root (serve.go), and a plugin
// program's constructor likewise. An install here would only repeat the one
// the program already carries.
g := app.Group("/v1/destinations")
g.Use(cloud.Bridge())
o := ops{s: s}
zip.Get(zapp, "/v1/destinations", o.list)
+8 -3
View File
@@ -36,13 +36,18 @@ var untypedByDesign = map[string]string{
"and a CLI command — not a document claiming it takes no body.",
}
// compose installs what a host installs. A subsystem never installs cloud.Bridge
// (routes says why): the program's composer owns it — serve.go in production — so
// a test app owes the same install, else every org-scoped op answers 403 for a
// reason no composed program has.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountApp mounts the destinations surface on a fresh in-memory app with a temp
// store, exactly as the unified binary does — and, deliberately, with NO app-wide
// cloud.Bridge, so the bridge these ops read their tenant through has to be the
// one Mount installs itself.
// store, exactly as the unified binary does: composed at the root, then mounted.
func mountApp(t *testing.T) *zip.App {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
t.Setenv(publicFanoutEnv, "0") // a document is not a reason to install a live sink
if err := Mount(app, cloud.Deps{Logger: luxlog.New("test"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
+5 -10
View File
@@ -150,16 +150,11 @@ type ops struct{ s *cloud.Service[state] }
// groups, because joining a "/v1/vpcs" prefix with an empty leaf yields
// "/v1/vpcs/" — a different path from the one this surface has always served.
func routes(app cloud.Router, s *cloud.Service[state]) {
// cloud.Bridge carries into a typed op the request its signature drops — this
// subsystem resolves its tenant through tenant(), which reads the validated
// principal AND the SuperAdmin bit, so it needs the request itself and not
// only the org. On the scoped Router this installs once per DECLARED prefix
// (/v1/vpcs, /v1/balancers) and nowhere else. It must precede the leaves
// below: fiber runs middleware in registration order, so one installed after
// them never runs for them. Serve installs one app-wide too — nesting is
// harmless (the inner one is what the handler sees) and the tests mount this
// subsystem on a bare app with no Serve, so this install is what makes them pass.
app.Use(cloud.Bridge())
// cloud.Bridge belongs to the composer — the fused host installs it at its
// root, and a plugin program's constructor does the same — so it is already
// in place when these ops run. This package only reads what it parks:
// tenant() resolves the validated principal and the SuperAdmin bit from the
// context.
zapp := cloud.ZipApp(app)
if zapp == nil {
s.Log.Error("do: router exposes no op registry; the DigitalOcean surface would serve routes no projection knows")
+9
View File
@@ -95,9 +95,16 @@ func (f *fakeLBs) Delete(_ context.Context, id string) (*godo.Response, error) {
// ── harness ──────────────────────────────────────────────────────────────────
// compose gives the test app what every real composer gives its program: the
// fused host installs cloud.Bridge at its root and a plugin program's
// constructor does the same, so a bare test app that skipped it would answer
// 403 for a reason production can never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mountFake(t *testing.T) (*zip.App, *fakeVPCs, *fakeLBs) {
t.Helper()
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
vpcs := &fakeVPCs{byID: map[string]*godo.VPC{}}
lbs := &fakeLBs{byID: map[string]*godo.LoadBalancer{}}
s := &cloud.Service[state]{Base: cloud.NewBase(cloud.Deps{Logger: luxlog.New("test")}, "do"), State: state{vpcs: vpcs, lbs: lbs}}
@@ -260,6 +267,7 @@ func TestForgePathRefused(t *testing.T) {
// X-Org-Id present but NO X-User-Id (the forgeable path) → still 403.
app2 := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app2)
s := &cloud.Service[state]{Base: cloud.NewBase(cloud.Deps{Logger: luxlog.New("test")}, "do"), State: state{vpcs: &fakeVPCs{byID: map[string]*godo.VPC{}}, lbs: &fakeLBs{byID: map[string]*godo.LoadBalancer{}}}}
routes(app2, s)
rq := httptest.NewRequest(http.MethodGet, "/v1/vpcs", nil)
@@ -278,6 +286,7 @@ func TestForgePathRefused(t *testing.T) {
// honest 503 — never a fabricated resource.
func TestFailClosedWhenUnconfigured(t *testing.T) {
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
s := &cloud.Service[state]{Base: cloud.NewBase(cloud.Deps{Logger: luxlog.New("test")}, "do"), State: state{}} // nil seams → unconfigured
routes(app, s)
+3 -4
View File
@@ -160,10 +160,9 @@ func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/engine")
o := ops{s: s}
// Bridge FIRST: a typed op receives only a context, so the validated
// principal reaches it by being parked there — never as an In field.
g.Use(cloud.Bridge())
// A typed op receives only a context, so the validated principal reaches it
// parked there by cloud.Bridge — never as an In field. The composer owns
// that install, once at its root; this group is a bare path prefix.
zip.Get(g, "/status", o.status,
zip.WithOperationID("engineStatus"),
zip.WithSummary("Whether the serving runtime is reachable, and which build it runs"))
+1
View File
@@ -34,6 +34,7 @@ func liveApp(t *testing.T) *zip.App {
t.Setenv("ENGINE_UPSTREAM", up)
t.Setenv("ENGINE_API_KEY", os.Getenv("ENGINE_E2E_KEY"))
app := zip.New(zip.Config{Logger: luxlog.New("enginelive"), DisableStartupMessage: true})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("enginelive"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+9
View File
@@ -150,6 +150,13 @@ func (f *fakeEngine) handler() http.Handler {
})
}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root. In a
// test the test IS the composer, so it owes the same thing — a test that skips it
// tests a program where every op answers 403 for a reason that would never exist
// in production. Same helper apps/integrations uses.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// harness mounts the app against a fake upstream and returns both.
func harness(t *testing.T) (*zip.App, *fakeEngine) {
t.Helper()
@@ -160,6 +167,7 @@ func harness(t *testing.T) (*zip.App, *fakeEngine) {
t.Setenv("ENGINE_API_KEY", "svc-key-test")
app := zip.New(zip.Config{Logger: luxlog.New("enginetest"), DisableStartupMessage: true})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("enginetest"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
@@ -435,6 +443,7 @@ func TestStatusIsAnHonestLens(t *testing.T) {
}
down := zip.New(zip.Config{Logger: luxlog.New("enginetest"), DisableStartupMessage: true})
compose(down)
t.Setenv("ENGINE_UPSTREAM", "http://127.0.0.1:1") // nothing listens
if err := Mount(down, cloud.Deps{Logger: luxlog.New("enginetest"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
+5 -9
View File
@@ -116,15 +116,11 @@ type ops struct{ s *service }
// calls it, and so do the package's tests, so a test can never exercise a router
// this binary does not serve.
func routes(app cloud.Router, s *service) {
// Bridge FIRST: a typed op receives only a context, so the validated org and the
// request its admin gates read reach it by being parked there. fiber runs
// middleware in registration order, so one installed after its leaves never runs.
// Installed through the SUBSYSTEM's own router, which scopes it to the prefixes
// this app declares — BOTH of them: this surface owns two top-level nouns
// (/v1/entitlements and /v1/orgs/:org/entitlements), and the /v1/<name> default
// MountPrefixes falls back to covers only the first, so plugin/entitlements/main.go
// passes manifest.PrefixesFor("entitlements") rather than relying on it.
app.Use(cloud.Bridge())
// cloud.Bridge is not installed here: the composer installs it once at the
// root, after the identity check that mints the validated org and before any
// subsystem registers a route — an order only the whole program can assert.
// The ops below read what it parks (the validated org, and the request their
// admin gates inspect) off the context.
// Declared on GROUPS: the op's path is the prefix composed with the leaf, which
// is the identity every projection keys on, and cmd/zipdoc resolves the prefix
+9 -2
View File
@@ -70,13 +70,20 @@ func (f *fakeCommerce) CheckEntitlement(_ context.Context, orgID, productID stri
// ── harness ──────────────────────────────────────────────────────────────────
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root, after
// the identity check that mints the validated org and before any subsystem
// registers a route. In production that composer is serve.go. In a test the test
// IS the composer, so it owes the same thing.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
func mount(t *testing.T, commerce cloud.CommerceClient) (*zip.App, *service) {
t.Helper()
s := &service{store: openTestStore(t), commerce: commerce, log: luxlog.New("test")}
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
// The REAL registration, not a reconstruction of it: a test that rebuilt the
// router by hand could exercise a surface this binary does not serve — and
// would silently drop the cloud.Bridge every typed op resolves its org through.
// router by hand could exercise a surface this binary does not serve.
routes(app, s)
return app, s
}
+4 -5
View File
@@ -101,9 +101,8 @@ func TestEveryTypedOpIsDescribed(t *testing.T) {
// pass fixed. This subsystem owns TWO top-level nouns, and the /v1/<name> default
// MountPrefixes falls back to covers only ONE of them — so before the fix the
// standalone binary attributed half its surface to no subsystem, and any middleware
// the subsystem installed through its own router (including the typed-op Bridge
// every op resolves its org through) landed on /v1/entitlements alone and never ran
// for /v1/orgs/…. The apps/plan defect, in its partial form.
// the subsystem installed through its own router landed on /v1/entitlements alone
// and never ran for /v1/orgs/…. The apps/plan defect, in its partial form.
//
// It reads the MANIFEST — the same list plugin/entitlements/main.go passes — against
// the routes the REAL mount serves, so adding a route outside both prefixes goes red
@@ -143,8 +142,8 @@ func TestDeclaredPrefixesCoverEveryServedRoute(t *testing.T) {
}
if !found {
t.Errorf("%s is served but lies outside every declared prefix %v — cloud.Declare cannot "+
"attribute it, and the subsystem's own middleware (the typed-op Bridge included) will "+
"not run for it. Add the prefix to manifest/apps.go.", key, prefixes)
"attribute it, and the subsystem's own middleware will not run for it. "+
"Add the prefix to manifest/apps.go.", key, prefixes)
}
}
// And the default the framework would fall back to must NOT be enough, so the
+4 -9
View File
@@ -34,15 +34,10 @@ import (
type ops struct{ s *cloud.Service[state] }
func routes(app cloud.Router, s *cloud.Service[state]) {
// cloud.Bridge carries into a typed op the request its signature drops. This
// surface needs more than the org key: the PROJECT scope that narrows within
// it, and the actor an audited write is recorded under. On the scoped Router
// this installs once per DECLARED prefix (/v1/flags) and nowhere else, and it
// must precede the leaves below — fiber runs middleware in registration order.
// Serve installs one app-wide too; nesting is harmless (the inner one is what
// the handler sees) and the tests mount this subsystem on a bare app with no
// Serve, so this install is what makes them pass.
app.Use(cloud.Bridge())
// cloud.Bridge is installed by whoever composes the app — the fused host at
// its root — never here: the org, project scope and actor every op below
// reads still arrive because the root install parks the request on the
// context.
zapp := cloud.ZipApp(app)
if zapp == nil {
s.Log.Error("flags: router exposes no op registry; the flag surface would serve routes no projection knows")
+9
View File
@@ -27,11 +27,20 @@ import (
var httpCfg = zip.TestConfig{Timeout: 10 * time.Second, FailOnTimeout: true}
// compose installs what a HOST installs. A subsystem never installs cloud.Bridge
// (routes says why): the program's composer installs it once at the root, after
// the identity check and before any route registers. In a test the test IS the
// composer, so it owes the same install — a test that skips it does not test a
// stricter program, it tests one where every org-scoped op answers 403 for a
// reason that would never exist in production.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// mountHTTP puts the flag surface on a bare app over a temp-dir store tree.
func mountHTTP(t *testing.T) *zip.App {
t.Helper()
c := newTestClient(t)
app := zip.New(zip.Config{Logger: luxlog.New("test")})
compose(app)
svc := &cloud.Service[state]{
Base: cloud.NewBase(cloud.Deps{Logger: luxlog.New("test")}, "flags"),
State: state{client: c},
+4 -5
View File
@@ -141,11 +141,10 @@ func routes(app cloud.Router, s *cloud.Service[state]) {
g := app.Group("/v1/flow")
o := ops{s: s}
// Bridge FIRST: a typed op receives only a context, so the validated
// principal reaches it by being parked there — never as an In field, which
// is caller-supplied and would be a cross-tenant read the caller asserted
// for itself.
g.Use(cloud.Bridge())
// cloud.Bridge is not installed here: the composer owns it — the fused
// host installs it once at its root, and the plugin constructor does the
// same for a plugin program — and typed ops read the validated principal
// it parks on the context.
zip.Get(g, "/status", o.status)
+1
View File
@@ -36,6 +36,7 @@ func liveApp(t *testing.T) *zip.App {
t.Setenv("FLOW_UPSTREAM", up)
t.Setenv("FLOW_API_KEY", os.Getenv("FLOW_E2E_KEY"))
app := zip.New(zip.Config{Logger: luxlog.New("flowlive"), DisableStartupMessage: true})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("flowlive"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
+9
View File
@@ -183,6 +183,13 @@ func (f *fakeFlow) handler() http.Handler {
})
}
// compose installs what a host installs. A subsystem never installs cloud.Bridge
// (routes() says why): the program's composer installs it once at the root, and
// in a test the test is the composer, so it owes the same install. A test that
// skips it does not test a stricter program — it tests one where every op that
// reads the principal answers a refusal production can never produce.
func compose(app *zip.App) { app.Use(cloud.Bridge()) }
// harness mounts the app against a fake upstream and returns both.
func harness(t *testing.T) (*zip.App, *fakeFlow) {
t.Helper()
@@ -193,6 +200,7 @@ func harness(t *testing.T) (*zip.App, *fakeFlow) {
t.Setenv("FLOW_API_KEY", "svc-key-test")
app := zip.New(zip.Config{Logger: luxlog.New("flowtest"), DisableStartupMessage: true})
compose(app)
if err := Mount(app, cloud.Deps{Logger: luxlog.New("flowtest"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
}
@@ -448,6 +456,7 @@ func TestStatusIsAnHonestLens(t *testing.T) {
}
down := zip.New(zip.Config{Logger: luxlog.New("flowtest"), DisableStartupMessage: true})
compose(down)
t.Setenv("FLOW_UPSTREAM", "http://127.0.0.1:1") // nothing listens
if err := Mount(down, cloud.Deps{Logger: luxlog.New("flowtest"), DataDir: t.TempDir()}); err != nil {
t.Fatalf("Mount: %v", err)
+11 -6
View File
@@ -93,12 +93,17 @@ func Mount(app cloud.Router, deps cloud.Deps) error {
g := app.Group("/v1/framework")
// The bridges, FIRST: a typed op receives only a context, so every request
// fact its signature drops has to be parked there — the validated org by
// cloud.Bridge, the two header-only identity facts by bridgeFacts. fiber runs
// middleware in registration order, so one installed after its leaves never
// runs; and the group bounds them to the subtree this subsystem serves.
g.Use(cloud.Bridge(), zip.H(bridgeFacts))
// bridgeFacts FIRST: a typed op receives only a context, so the two
// header-only identity facts its signature drops have to be parked there.
// fiber runs middleware in registration order, so one installed after its
// leaves never runs; and the group bounds it to the subtree this subsystem
// serves.
//
// cloud.Bridge is not installed here. Whoever composes the program installs it
// once at the root — after the identity check that mints the validated org and
// before any subsystem registers a route (serve.go) — because that order is a
// property of the whole program and no subsystem can assert it for itself.
g.Use(zip.H(bridgeFacts))
o := ops{s: s}

Some files were not shown because too many files have changed in this diff Show More