Intents & PermitsPermit Validation

Permit Validation

A Permit is a short-lived, RS256-signed JWT issued after a human approves an Intent. Before executing any sensitive action, your backend must validate the permit. Validation can happen online (via the API) or offline (using the project public key).

Online Validation (SDK)

// After receiving the permit token from webhook or polling
const result = await sa.validatePermit(permitToken);

if (!result.valid) {
  throw new Error('Permit invalid: ' + result.reason);
}

// Safe to execute — result contains verified metadata
console.log(result.action);       // "deploy_production"
console.log(result.approvedBy);   // "jane@acme.io"
console.log(result.approvedAt);   // ISO timestamp
console.log(result.expiresAt);    // ISO timestamp

await deployToProduction(result.params);

Offline Validation

For environments with no outbound network access, you can validate permits offline using your project's RSA public key. Download it once from the dashboard and cache it:

import * as jose from 'jose';

const publicKey = await jose.importSPKI(
  process.env.SA_PUBLIC_KEY,
  'RS256'
);

const { payload } = await jose.jwtVerify(permitToken, publicKey, {
  issuer:   'https://api.silentauth.io',
  audience: process.env.SA_PROJECT_ID,
});

// payload.act   = action name
// payload.prms  = action parameters
// payload.apv   = approver email
// payload.exp   = expiry unix timestamp

Permit Claims Reference

ClaimTypeDescription
issstringIssuer — always https://api.silentauth.io
audstringAudience — your project ID
substringIntent ID that was approved
actstringAction name (e.g. deploy_production)
prmsobjectParameters from the original intent
apvstringEmail of the human approver
iatnumberIssued at (Unix timestamp)
expnumberExpiry (Unix timestamp)

Validation Failure Reasons

expired

Permit has passed its expiry time.

tampered

JWT signature does not verify.

action_mismatch

Permit action does not match the intended action.

already_used

Single-use permit has already been consumed.