CI/CD / gate (push) Canceled after 0s
CI/CD / containment (push) Canceled after 0s
CI/CD / image (push) Canceled after 0s
CI/CD / rollout (push) Canceled after 0s
CI/CD / reach (push) Canceled after 0s
CI/CD / fanout (push) Canceled after 0s
CI/CD / receipt (push) Canceled after 0s
/v1/dataroom/* has served fourteen routes and reached no agent. An untyped route appends no op to zip's registry, and the MCP door renders tools FROM that registry — so the fleet answered tools/list with 570 tools and not one of them opened a data room. The hole was never the mount (dataroom mounts, and /v1/dataroom/health has been answering in production); it was that every route was an untyped relay. Ten of them are typed ops now — every JSON route on the admin surface, which is the whole demo surface: open a room, put documents in it, grant a party access, and list what exists. Each still relays the bundle's own (status, body); what changed is that it now carries an In and an Out, so the same declaration yields the tool, the OpenAPI operation, the SDK method and the CLI command. The package doc claimed NONE of these could be typed, on two premises the shared kit answers: that a relayed answer is opaque (it is not — the bundle's shapers are total and schema.go types them, which is what the models are), and that a typed error path would overwrite the bundle's envelope (it does not — BundleErr carries the bundle's status and BYTES). captable had already disproved both; this makes that the second use rather than the second copy, so Scalar, SizedIn, BundleErr and Envelope move to apps/goja, beside the bundle seam they serve. ScalarList is the one piece captable did not need. A bundle substitutes an EMPTY list for anything that is not an array, so an agent told allowList is a `string` sends one, the room discards it, and the call SUCCEEDS having ignored the access control — a link meant for one investor admitting everyone, reported as success. Declaring the array is what puts that failure out of reach. Four routes stay relays for reasons in the wire, each named at its registration: the upload takes the file itself as the body, the two /file routes answer with a byte stream, and the three public viewer routes have no principal to read. Proven: the demo flow end to end over the typed routes; the reads byte-identical to the bundle they replace; the cross-tenant link index still written, so a granted link still opens for an anonymous visitor; org scoping; the room's own refusal envelope intact; and the ten tools present with descriptions and schemas. The regenerated captable subset is operationId-only (40 lines, 0 schema changes) — pre-existing drift between the committed spelling and what zip v1.24.1 derives, corrected by regenerating from source rather than by hand. The same drift had left one captable test asserting a tool name nothing produces; it now asserts the derived one. Co-authored-by: Hanzo Dev <dev@hanzo.ai>