Identity Package
The identity packages verify Caracal mandate JWTs. Use them when you are building an adapter or custom resource-server boundary that accepts mandates directly.
Do not use identity verification alone as a production authorization boundary when revocation must take effect before token expiry; compose it through Verify Package with a shared revocation store.
Install
Section titled “Install”| Ecosystem | Package |
|---|---|
| TypeScript | npm install @caracalai/identity |
| Python | pip install caracalai-identity |
| Go | go get github.com/garudex-labs/caracal/packages/identity/go |
Node packages target Node >=22; Python packages require Python >=3.12.
Verification inputs
Section titled “Verification inputs”| Option | Meaning |
|---|---|
issuer / Issuer | Expected STS issuer. |
audience / Audience | Expected audience for the mandate. |
zoneId / expected_zone_id / ZoneID | Required zone trust anchor. It fixes which zone’s signing keyset verifies the token and must equal the zone_id claim, so key selection is never influenced by the unverified token. Verification fails closed when it is missing. |
requiredScopes / required_scopes / RequiredScopes | Scopes every accepted mandate must contain. |
requiredTargets / required_targets / RequiredTargets | Target resources every accepted mandate must include. |
requiredUse / required_use / RequiredUse | Token use, usually resource. |
requireSession / require_session / RequireSession | Require a governed Session identity. |
requireDelegation / require_delegation / RequireDelegation | Require a Delegation claim (delegation_edge_id on the wire). |
requireChainContains / require_chain_contains / RequireChainContains | Require an application in the delegation chain. |
maxHopCount / max_hop_count / MaxHopCount | Cap delegation chain depth. |
TypeScript example
Section titled “TypeScript example”import { verify } from '@caracalai/identity'
const claims = await verify(token, { issuer: 'https://sts.pipernet.example', audience: 'https://api.pipernet.example', zoneId: '0195f2a9-1b22-7c3d-9e4f-5a6b7c8d9e0f', requiredScopes: ['pipernet:read'], requiredTargets: ['resource://pipernet'],})Parsed claim names
Section titled “Parsed claim names”The identity packages map raw JWT claims to canonical language-level fields:
| Meaning | TypeScript | Python | Go | Raw JWT claim |
|---|---|---|---|---|
| Authority record ID | authorityRecordId | authority_record_id | AuthorityRecordID | sid |
| Root authority record ID | rootAuthorityRecordId | root_authority_record_id | RootAuthorityRecordID | root_sid |
| Session ID | sessionId | session_id | SessionID | agent_session_id |
| Delegation ID | delegationId | delegation_id | DelegationID | delegation_edge_id |
JWKS caching
Section titled “JWKS caching”STS signing keysets are zone-scoped: every fetch hits {issuer}/.well-known/jwks.json?zone_id={zone} and is cached per issuer and zone. TypeScript verifiers use an in-memory JWKS cache by default. Build a cache explicitly when a resource server wants shorter local-development TTLs, a custom fetch implementation, or warmup during service boot.
import { createJwksCache, verify } from '@caracalai/identity'
const jwksCache = createJwksCache({ ttlMs: 300_000, fetchTimeoutMs: 5_000 })await jwksCache.warm('https://sts.pipernet.example', '0195f2a9-1b22-7c3d-9e4f-5a6b7c8d9e0f')
const claims = await verify(token, { issuer: 'https://sts.pipernet.example', audience: 'https://api.pipernet.example', zoneId: '0195f2a9-1b22-7c3d-9e4f-5a6b7c8d9e0f', jwksCache,})Go and Python identity packages also cache issuer JWKS metadata in memory and cap documents at 256 KiB. Python JwksCache(http_client=...) accepts an injected async client for private CAs, proxies, or mTLS. Go callers use NewJWKSCache(httpClient, ttl) and pass it through Config.JWKSCache; GetJWKSContext retains the bounded default. Python exposes warm_jwks(issuer, zone_id) for service boot.
Failure classes
Section titled “Failure classes”| Error | Meaning |
|---|---|
TokenInvalidError | Signature, issuer, audience, expiry, use, or claim validation failed. |
ZoneInvalidError | The token zone did not match the expected zone. |
ScopeInsufficientError | A required scope is missing. |
SessionRequiredError | The verifier requires a governed Session identity. |
DelegationRequiredError | The verifier requires delegated authority. |
ChainMismatchError | The delegation chain is missing a required application. |
HopCountExceededError | The mandate exceeds the configured hop limit. |
Verification is local except for JWKS retrieval. It does not call STS to refresh or exchange a token, and it does not retry application work. Zone ID, issuer, audience, required use, scopes, targets, Session, Delegation, chain, and hop requirements are security inputs and must come from trusted service configuration.
When to Use Verify Package
Section titled “When to Use Verify Package”Use Verify Package when you also need revocation checks, reusable verifier defaults, bearer-header parsing, and safe debugging hints. Use the identity package directly when you are composing your own verifier or adapter boundary.

