molecule-core/workspace-server/internal/middleware
Hongming Wang 8516a8f9c6 fix(tenant-guard): allowlist /buildinfo so redeploy verifier can reach it
The /buildinfo route added in #2398 to verify each tenant runs the
published SHA was 404'd by TenantGuard on every production tenant —
the allowlist had /health, /metrics, /registry/register,
/registry/heartbeat, but not /buildinfo. The redeploy workflows
curl /buildinfo from a CI runner with no X-Molecule-Org-Id header,
TenantGuard 404'd them, gin's NoRoute proxied to canvas, canvas
returned its HTML 404 page, jq read empty git_sha, and the verifier
silently soft-warned every tenant as "unreachable" — which the
workflow doesn't fail on.

Confirmed externally:
  curl https://hongmingwang.moleculesai.app/buildinfo
  → HTTP 404 + Content-Type: text/html (Next.js "404: This page
    could not be found.") even though /health on the same host
    returns {"status":"ok"} from gin.

The buildinfo package's own doc already declares /buildinfo public
by design ("Public is intentional: it's a build identifier, not
operational state. The same string is already published as
org.opencontainers.image.revision on the container image, so no new
info is exposed.") — the allowlist just missed it.

Pin the alignment in tenant_guard_test.go:
TestTenantGuard_AllowlistBypassesCheck now asserts /buildinfo
returns 200 without an org header alongside /health and /metrics,
so a future allowlist edit can't silently regress the verifier
again.

Closes the silent-success failure mode: stale tenants will now
show up as STALE (hard-fail) rather than UNREACHABLE (soft-warn).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 12:54:51 -07:00
..
devmode_test.go refactor(middleware): extract dev-mode fail-open predicate 2026-04-23 14:55:34 -07:00
devmode.go fix: six UX bugs (peers auth, scroll, chat tabs, config persist, + visibility) 2026-04-23 20:18:30 -07:00
mcp_ratelimit_test.go chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
mcp_ratelimit.go chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
ratelimit_test.go chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
ratelimit.go fix: dev-mode bypass for IP rate limiter + 429 retry on GET 2026-04-23 20:44:09 -07:00
securityheaders_test.go chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
securityheaders.go chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
session_auth_test.go fix(canvas/a11y): restore aria-hidden on backdrop div after cherry-pick conflict 2026-04-24 03:10:18 +00:00
session_auth.go fix(canvas/a11y): aria-hidden SVGs, MissingKeysModal dialog, session cookie auth 2026-04-24 04:30:26 +00:00
tenant_guard_test.go fix(tenant-guard): allowlist /buildinfo so redeploy verifier can reach it 2026-04-30 12:54:51 -07:00
tenant_guard.go fix(tenant-guard): allowlist /buildinfo so redeploy verifier can reach it 2026-04-30 12:54:51 -07:00
wsauth_middleware_canvasorbearer_test.go refactor(wsauth): extract lookupTokenByHash to dedup auth predicate across 3 callers 2026-04-30 03:11:38 -07:00
wsauth_middleware_org_id_test.go test(middleware): add last_used_at ExpectExec for WorkspaceAuth org-token tests 2026-04-24 13:01:42 +00:00
wsauth_middleware_test.go refactor(wsauth): extract lookupTokenByHash to dedup auth predicate across 3 callers 2026-04-30 03:11:38 -07:00
wsauth_middleware.go feat(platform,canvas): classify "datastore unavailable" as 503 + dedicated UI 2026-04-26 00:01:56 -07:00