feat(engine)!: replace plan entitlements with host admission hooks
The engine has no plans, usage quotas or billing. Admission and metering are host concerns, exposed through AdmissionHooks; self-host passes none and every workspace is admitted.
Admission hooks
EngineDeps.admission (also createNodeRuntime({ admission }) and startServer({ admission })):
interface AdmissionHooks {
admit?(ctx: { workspace; action: 'request' | 'message' }): Promise<AdmissionDenial | null | undefined>;
committed?(ctx): Promise<void>; // 2xx, never an idempotent replay
rateLimitPerMinute?(workspace): Promise<number>; // per-workspace ceiling override
}
interface AdmissionDenial { status; code; message; details?; retryAt? }
requestis checked inrateLimitafter the per-minute bucket, so throttled requests never reach the host.messageis checked on channel posts, DMs, group DMs and thread replies.- A denial renders as
{ ok: false, error: { code, message, ...details } }with its status.Retry-After/X-RateLimit-Resetare set only whenretryAtis given. - A denied message send that has an
Idempotency-Keystill replays its stored receipt. Only a fresh send is refused, and that refusal leaves no idempotency lock behind. committedruns throughrunInBackground(waitUntilon Workers).- A hook that throws admits the request. A failing
rateLimitPerMinutefalls back toEngineConfig.rateLimitPerMinute(default 30,000).
Plans out of the engine
EntitlementsProvider,StaticEntitlementsProvider,PLAN_LIMITS, the plan-limit and message-allowance middleware,usageTracker, and theusage:*KV counter helpers no longer exist.- Migration
0077_drop_workspace_plan.sqldropsworkspaces.plan.Workspace.planis no longer in the API, OpenAPI,@relaycast/types, or the Rust and Swift SDK models. WorkspaceDeliveryPolicyConfig.resolvereceives{ id }.- Self-hosted workspaces are never quota-limited, so #432 (self-host workspaces hitting
freequotas through the schema default) cannot occur.
Release and downstream
Major bump for engine/types/Swift (a public field, an error code and exports are removed); the Rust SDK change goes into its pending 10.0.0. relaycast-cloud must move its tier table (PLAN_LIMITS, the workspace-plan: override, trial allowance, api-call metering, upgrade guidance) behind AdmissionHooks. It must also copy workspaces.plan into its own storage before applying engine migration 0077; its fleet/routes.ts writes that column directly today.
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Agent Relay sessions
claudesession661e56aa· opened viagh pr create· last active 2026-10-27