Configuration
The environment variable differs from the Python SDK, and one of them is
going to trip you up. TypeScript reads ROTASCALE_API_URL. Python reads
ROTASCALE_URL. Set both if you run both in the same deployment.
TypeScript also falls back to https://api.rotascale.com when neither is set,
and there is no such deployment. RotaGrant runs single-tenant inside your
environment, so a default hosted URL cannot be right for anybody. Set baseUrl
or ROTASCALE_API_URL explicitly; the Python SDK raises instead, which is the
better behaviour of the two.
Authorising an action
Options object rather than positional arguments, which is the one deliberate
divergence from the Python shape.
throwOnRefusal is on by default, so the unsafe path is one you write
deliberately rather than get by forgetting to check a return value.
Handling refusals
Exhausted and Gated extend Blocked, so check them before Blocked.
An instanceof Blocked branch placed first swallows all three and you lose the
only field that tells you what to do next.
RequestRefused is TypeScript-only and covers a malformed request rather than a
governance decision. It has no Python counterpart because the Python client
raises the underlying HTTP error.
Trajectories and middleware
currentTrajectory() reaches the active trajectory without threading it
through every function.
As in Python, middleware records and does not authorise. Only your code
knows which action is consequential. See Framework middleware.
What it deliberately does not do
No governance fact is derived client-side. enforcing and suppressed read
fields the server sends; there is no second opinion about what a refusal means,
because two SDKs disagreeing about that is worse than either being wrong alone.