Repository navigation
feat(tools)!: tool packages call stock routes with the run bearer; delete workflow-* hub mounts (CL-8159) - #764
Merged
Merged
Conversation
The hub's signed deploy frame already carries the run's tenantId and principalId (HarnessConfig). The sidecar now threads both through the child's substrate config as WORKFLOW_TENANT_ID / WORKFLOW_PRINCIPAL_ID and exposes them on the step env, so an agent tool package can address stock /api/tenants/:tenantId/* routes instead of a Workbench-specific mirror. The on-disk deployment record carries the pair too (version 2), so a boot-time restore reseeds it rather than standing up a child whose tools cannot name their tenant. The hub widens @intx/hub-api's existing run-bearer middleware from the single deploy endpoint to the whole tenant subtree, as an outer wrap of the built app. A request with no bearer credential is untouched. Claude-Session: https://claude.ai/code/session_01RweuMUskU2nvcFhdckc7EG
…un bearer list_principals, list_grants, grant_access and revoke_access now speak the stock Interchange tenant routes with the workflow run's own bearer credential, instead of a Workbench-specific /api/workflow-access mirror. That mirror, its hub mount and its tests are deleted. The delegation ceiling the mirror enforced moves into the tool: before it grants or revokes, it reads the caller's own grants in the caller's own tenant and evaluates each requested resource/action pair with @intx/authz's own engine, refusing anything outside the caller's authority. Grants are not inherited across the tenant ancestor tree, so a parent tenant's grant is never read as authority in a child. Two fidelity gaps against a server-side ceiling remain, tracked as upstream asks on CL-7575: role-derived grants are invisible to the stock principal-filtered listing, and the read-then-write is not atomic. Claude-Session: https://claude.ai/code/session_01RweuMUskU2nvcFhdckc7EG
list_connections now answers from the stock Interchange provider and credential routes, read with the workflow run's own bearer credential: a connector is connected when the tenant holds an active credential against a provider named for it, the same keying an agent launch resolves a credential by. The tool pairs that answer with the deploying build's own connector registry for display names and links, which the hub does not know. The /api/workflow-connections/connections route is deleted along with its tests. The mount survives only as the MCP-server registry @corbits/mcp-tools resolves an mcp:<slug> server through; MCP servers are not a stock Interchange concept, so CL-8164 retires it with the rest of MCP server configuration. Until then list_connections no longer reports MCP-connected servers: a curated preset is still offered as a card, and counts as connected when a credential exists under its own id. Known gap, recorded upstream: the stock provider listing includes ancestor tenants but the stock credential listing does not, so a credential held only by a parent tenant reads as not connected. Claude-Session: https://claude.ai/code/session_01RweuMUskU2nvcFhdckc7EG
This was referenced Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Agent tool packages now address stock Interchange tenant routes with the workflow run's own bearer credential, instead of Workbench-specific
/api/workflow-*mirrors. CL-8159.How the run bearer reaches a stock route
Two pieces, both Workbench-owned — no vendored file changed.
Addressing. The hub's signed deploy frame is a
HarnessConfigcarryingtenantIdandprincipalId. The sidecar now threads both into the workflow child's substrate config asWORKFLOW_TENANT_ID/WORKFLOW_PRINCIPAL_ID(arktype-validated, required, no fallback) and exposes them on the step env beside the existingdefinitionId, so a tool package can fill the:tenantIdsegment every stock tenant route carries. The on-disk deployment record carries the pair too, at schema version 2, so a boot-time restore reseeds it; a version-1 record fails the parse and is redeployed rather than restored into a child whose tools cannot name their tenant.Authorization.
@intx/hub-apialready resolves a sidecar bearer plus run address intoprincipal+tenant(workflow-run-deploy-auth), but mounts it only on/api/tenants/:tenantId/workflows/deployments.apps/hubnow wraps the built app and mounts that same middleware on/api/tenants/:tenantId/*, ahead of the stockresolveTenant— an outer wrap becausecreateApp()has already registered its own middleware by the time it returns. A request with no bearer credential is untouched; the:tenantIdsegment is never trusted, since the middleware sets the tenant from the authenticated run alone.Mapping
list_principalsGET /api/workflow-access/principalsGET /api/tenants/:t/principals, all pageslist_grantsGET /api/workflow-access/grantsGET /api/tenants/:t/grants, all pagesgrant_accessPOST /api/workflow-access/grants(multi-action)POST /api/tenants/:t/grantsper actionrevoke_accessDELETE /api/workflow-access/grants/:idGETthe grant, ceiling check,DELETE /api/tenants/:t/grants/:idlist_connectionsGET /api/workflow-connections/connectionsGET /api/tenants/:t/providers+/credentials, paired with the build's own connector registryrequest_connectionThe delegation ceiling stock
POST /grantsdoes not have moves into the tool: it reads the caller's own grants in the caller's own tenant and evaluates each requested resource/action pair with@intx/authz's ownevaluateGrants, refusing anything outside the caller's reach before any write. Grants are not inherited across the tenant ancestor tree, so a parent tenant's grant is never read as authority in a child. Credentials and providers are read through the stock routes as-is, with no own-tenant filter added.Dropped
mcp_list_serversis not dropped, butlist_connectionsno longer reports MCP-connected servers. MCP servers are not a stock Interchange concept, so/api/workflow-connectionssurvives only as themcp:<slug>registry@corbits/mcp-toolsresolves a server URL through —GET /connectionsis deleted. Deleting the whole mount would have broken every@corbits/mcp-toolsoperation, not just the listing. CL-8164 retires it with the rest of MCP server configuration. A curated preset is still offered as a card and counts as connected when a credential exists under its own id.@corbits/access-toolsno longer exports./routes;packages/access-tools/src/routes.tsand its two test suites are deleted, as is theConnectionSummaryexport from@corbits/connections.Not in this PR
Two of the four mounts need work that does not fit a route swap, each filed as its own issue under CL-8155:
createWorkflowCatalogRoutesresolves a model chain per request fromResolvedOfferingrows,modelPricingrows, and the bench model policy. Stock/offeringsreturns a different shape, there is no stock pricing route, and the bench model policy (theoverCeilingflag) has no stock route at all. That last one needs a ruling: a route, or an accepted loss.deploymaps cleanly onto stockPOST /workflows/deploymentsand is ready to do, butreadSource/author/republishread and write git trees whose only stock equivalent is git smart-HTTP on the asset repo, which the sandbox would have to speak. Deleting the mount before that works would delete three operations outright, so both halves land together.Upstream asks
GET /providersincludes ancestor tenants; stockGET /credentialsdoes not, so a credential held only by a parent tenant reads as not connected.https://claude.ai/code/session_01RweuMUskU2nvcFhdckc7EG