Deployment
Serve plugin Fetch handlers with authentication, mount paths, and archive compression.
createFetchHandler(plugin, options) returns (request: Request) => Promise<Response>. Use it directly in Cloudflare Workers, Bun, Deno, and any framework route that accepts Fetch Request and Response objects. A framework with different request types needs only an adapter at its boundary; the package itself has no framework dependency.
The handler serves the archive for every GET request and runs a command for a matching POST request. It routes a command from the longest matching suffix of the request path, so the same handler works at the origin root, under /crtr, and behind a proxy that preserves that path.
Mount paths
Install the public URL where the handler is mounted. For https://acme.example.com/crtr, run crtr pkg plugin install --endpoint https://acme.example.com/crtr --name acme. The archive generated for that request declares /crtr/acme/... as every rest.path.
This prefix is required because crtr stores only https://acme.example.com as the command transport endpoint after installation. An archive declaring /acme/... for a handler mounted at /crtr sends commands to the origin root. Do not use baseUrl as a repair; absolute paths replace a base URL path.
Set baseUrl only when request.url is not the public URL, such as a proxy that rewrites the path or terminates TLS on a different host. Pass the complete public URL, including its mount path, to createFetchHandler. The generated rest.path must be the public path an agent could request directly.
Authentication
Pass token to require Authorization: Bearer <token> on archive and command requests. --auth-env NAME tells crtr which environment variable of the calling process holds that value. It does not configure the server. For a command an agent runs, the calling process is its broker, which reads the profile env store (crtr profile env set <profile> --name NAME) rather than your shell's exports. Omitting token serves without authentication and logs a warning when the handler is created.
A capability provider registered in the directory passes auth: {issuer, audience} instead of token; passing both throws. issuer is the directory's issuer URL and audience is the provider's endpoint URL exactly as registered. Every command request's bearer must be an outbound token the directory minted. The handler verifies it with @crouter/identity: it fetches the JWKS from <issuer>/.well-known/jwks.json, caches it, and refetches once when a token names an unknown kid. It checks the signature, iss, aud (exact match, so a trailing slash differs) and exp. A failed check answers 401 unauthorized. Next the called leaf's <plugin>:<group> must be in the token's scope. If it is not, the handler answers 403 scope_missing with that string in both field and received. A command request under auth must also carry Crtr-Request-Id. Every leaf then gets ctx.caller: {sub, grantee, clientId, scope, initiatingApp, act, jti, requestId, runId?}. act and initiatingApp are for your audit; the kit authorizes nothing on them. The archive and GET /versions stay public under auth. For local development, point issuer at a test issuer that serves /.well-known/jwks.json.
Major versions
A definition with version: N, or a list of definitions with one per supported major, is served per major. Each major N is mounted under <mount>/v<N>/, and its archive at GET <mount>/v<N>/ declares /v<N> routes. GET <mount>/versions answers {latest, supported}. An unversioned single definition keeps the unversioned paths above. With baseUrl, pass the endpoint without any /v<N> segment.
Archive response
The install response is an uncompressed tar with Content-Type: application/x-tar. Do not configure a proxy, CDN, or framework middleware to gzip or otherwise compress it. Crtr rejects compressed archive bytes. The handler sends an ETag and supports conditional If-None-Match requests automatically.
A non-streaming successful command response is a bare JSON result object. Error responses are JSON error envelopes on non-2xx statuses. See Errors and streaming for the exact error shape.