latestOpenAPI 3.0.32026-08-227451,2751.8 MB

d0fc0114da66

LinkMablnet

Authorize a mablnet Host to join a Link Label's tunnel

Validates a HostCredentials blob presented by a mablnet client (Link Agent, execution Host, or future desktop-app Host) and returns the tenantId / hostIdentity / validUntil triple the mablnet protocol needs to admit the client. Internally called by Link Router on every carrier-join — see mablnet-client-authorization.md in link/mablnet/docs for the full design. Three caller types are accepted, all auth'd against the standard mabl-api chain: link_agent API keys (workspace-scoped Link Agent keys), execution API keys (workspace-scoped, TTL'd, minted per test run), or user OAuth tokens (workspace members with write permission, mabl support admins included). The request body's workspace_id is cross-checked against the auth principal. Failure semantics: 401 for bad credential / malformed body / stale issued_at / replayed nonce / (link_agent callers only) host_id not matching any active Link Agent; 402 for billing-suspended or LINK feature disabled; 403 for auth principal not authorised on workspace_id; 5xx for transient backend failures including Redis-unavailable (fail-closed on the nonce cache).

post/link/mablnet/authorize/host

Request body

peer_credentialstring

Base64 of the verbatim Ed25519-signed peer JOIN credential blob ({role: "peer", sub, workspace_id, label, host_id, issued_at, expires_at, nonce, signature} as minted). Present only on the peer path; its presence selects that path.

owner_type'workspace' | 'company' | 'user'

The kind of entity a mablnet tunnel is scoped to — its "owner". workspace is the classic scope: one tunnel per workspace. company scopes a single tunnel to an entire company, so every workspace under that company shares one mablnet tenant (and one Link Agent fleet) instead of needing a tunnel each. user is a personal tunnel scoped to a single user, private to that user — its egress is the user's own machine, used to route a cloud test run through it. All three are mablnet-only: legacy Link Tunnel is always workspace-scoped.

owner_idstring

The id of the owning entity — a workspace id when owner_type is workspace, a company id when company. Cross-checked against the auth principal: an api-key caller must be scoped to this workspace (or to a company that owns it, or — for a company owner — to a workspace within that company); a user-OAuth caller must be able to modify it. Required on the api-key path.

labelstring

The Link Label name within the owner (the customer-facing "tunnel name"). (owner_type, owner_id, label) uniquely identifies a tunnel; multiple Hosts can be in the same tunnel concurrently. Required on the api-key path.

host_idstring

Per-Host-instance identifier the caller advertises. For link_agent keys this is composite — <link-agent-id>:<host-bundle-version> — and the LinkAgent.id prefix (the segment before the first :, or the whole value when there is none) MUST match an active LinkAgent.id in (workspace_id, label); the version suffix is accepted and echoed so each host-bundle generation is a distinct Host. For execution keys and user OAuth callers this is validated for shape only (UUID-like or la--prefixed mabl uid, ≤128 chars). Echoed back as host_identity in the response.

issued_atstring date-time

RFC 3339 timestamp when the caller constructed this blob. Rejected if more than ±5 minutes from server time (sliding-window replay bound).

noncestring

16 random bytes from SecureRandom, hex-encoded (32 chars). One-shot uniqueness guard; the server-side cache rejects repeats within a 10 minute window per auth principal.

router_infrastructure_keystring

The link infrastructure key of the Router forwarding this JOIN (its LINK_ROUTER_INFRA_KEY — mabl for the shared cluster, the customer key for a dedicated cluster). When present, the api enforces cluster exclusivity for BOTH credential paths: the caller-tenant's resolved key must equal this value or the JOIN is denied (a dedicated company's tunnels cannot ride the shared cluster, and nobody outside the company can join its dedicated cluster). Absent on Routers that predate key-reporting — the check is skipped, which is correct only while such Routers exist; see dedicated-link-infra.md in link/mablnet/docs.

Response

Authorization granted

tenant_idinteger required

Unsigned 32-bit mablnet tenant identifier for this tunnel ([0x00000001, 0xFEFFFFFF]; system-tenant range 0xFFxxxxxx reserved). Derived from the LinkLabel; see mablnet-tenant-id-derivation.md in link/mablnet/docs.

host_identitystring required

The host_id the caller supplied, echoed back after caller-type-branched validation. Used by the mablnet library for reconnect-grace bookkeeping.

valid_untilstring date-time required

RFC 3339 timestamp marking when this authorization expires. Fixed 1h window (now + 1h) regardless of caller type. The caller refreshes before this point via another POST /link/mablnet/authorize/host.

access'full' | 'control_plane'

How much of the tenant this peer may reach once admitted. full — every service, subject to the usual tenant and visibility rules. control_plane — only services the Host registered as control-plane (the operator RPC surface); a stream to anything the Host advertises on its owner's behalf, such as SOCKS or probes, is refused by the Host at accept. Read off the peer credential's signed access claim, so the decision is the one made at mint time. Always present on this response — unlike the credential claim itself, which is omitted when full to keep ordinary credentials byte-identical. An absent value still means full: it is what an api predating this field returns, and what every api-key join carries. Restriction is opted into, never inferred from absence. The Router records this with the Host's registration and serves it to other Hosts asking PeerAccessQuery; see support-admin-tunnel-access.md in link/mablnet/docs.