@mandatum/sdk
v1.0.0
Published
Zero-trust authorization and spending limits for AI agents. Ed25519-signed JWTs, policy enforcement, and payment gating in one line.
Downloads
7
Maintainers
Readme
@mandatum/sdk
Zero-trust authorization and spending limits for AI agents. One line of code to verify permissions, enforce budgets, and generate tamper-proof audit receipts.
Install
npm install @mandatum/sdkQuick Start
import { Mandatum } from '@mandatum/sdk';
const mandatum = new Mandatum({
apiKey: 'mdt_live_xxxxxxxxxxxxxxxx',
baseUrl: 'https://mandatum-fbg9.onrender.com', // or your self-hosted URL
});
// ─── 1. Register an Agent ───────────────────────────────
const agent = await mandatum.agents.create({
name: 'PaymentBot',
type: 'payment',
delegator: '[email protected]',
});
// ─── 2. Create a Spending Policy ────────────────────────
const policy = await mandatum.policies.create({
name: 'cloud-budget',
resource: 'payments',
actions: ['payments:execute'],
constraints: {
max_amount: 5000,
daily_limit: 10000,
currency: 'INR',
},
});
await mandatum.policies.assign(agent.id, policy.id);
// ─── 3. Issue a Scoped Token ────────────────────────────
const { token } = await mandatum.tokens.issue({
agentId: agent.id,
scopes: ['payments:execute'],
constraints: { max_amount: 5000, currency: 'INR' },
expiresIn: '1h',
});
// ─── 4. The 1-Line Permission Gate ─────────────────────
const result = await mandatum.check(token, 'payments:execute', {
amount: 350,
currency: 'INR',
vendor: 'DigitalOcean',
});
if (result.allowed) {
console.log('✅ Approved — receipt:', result.receipt.receiptId);
// Proceed with payment
} else {
console.log('❌ Blocked:', result.reason);
}Core Concepts
The Permission Gate
Every agent action goes through mandatum.check(). It verifies the JWT signature (Ed25519), checks scopes, evaluates spending constraints, enforces rate limits, and returns a cryptographically signed receipt — all in one call.
const result = await mandatum.check(token, action, context);
// result.allowed → boolean
// result.reason → why it was blocked (if denied)
// result.receipt → { receiptId, signature, timestamp }
// result.checks → detailed constraint evaluations
// result.rateLimit → current usage statsQuick Boolean Check
If you just need a true/false gate:
if (await mandatum.isAllowed(token, 'email:send', { to: '[email protected]' })) {
sendEmail();
}API Reference
new Mandatum(config)
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | required | Your API key (mdt_live_...) |
| baseUrl | string | http://localhost:3001 | Mandatum API URL |
| timeout | number | 10000 | Request timeout in ms |
Agents
mandatum.agents.create({ name, type, delegator, description })
mandatum.agents.list({ status, search, environment })
mandatum.agents.get(id)
mandatum.agents.suspend(id)
mandatum.agents.revoke(id) // cascading — revokes all child agents + tokens
mandatum.agents.spend(id, { amount, currency, vendor, category })
mandatum.agents.spending(id) // returns today/total spent + remaining budgetTokens
mandatum.tokens.issue({ agentId, scopes, constraints, expiresIn })
mandatum.tokens.verify(token, action, context)
mandatum.tokens.revoke(jti)
mandatum.tokens.list({ agentId, status })Policies
mandatum.policies.create({ name, resource, actions, constraints })
mandatum.policies.list()
mandatum.policies.get(id)
mandatum.policies.assign(agentId, policyId)Audit
mandatum.audit.list({ limit, agentId })
mandatum.audit.verifyChain() // verify hash-chain integrity
mandatum.audit.getReceipt(eventId) // get signed receipt for an eventPayment Gateway Wrappers
Pre-built wrappers that call mandatum.check() before creating payments:
Razorpay
import { MandatumRazorpay } from '@mandatum/sdk/payments/razorpay';
const pay = new MandatumRazorpay(razorpayClient, mandatum, agent.id);
const result = await pay.createPayment({
amount: 50000, // paise
currency: 'INR',
description: 'Cloud hosting',
});
// Automatically checks limits → creates Razorpay order → records spendingStripe
import { MandatumStripe } from '@mandatum/sdk/payments/stripe';
const pay = new MandatumStripe(stripeClient, mandatum, agent.id);
const result = await pay.createPaymentIntent({
amount: 5000, // cents
currency: 'usd',
});Local Verification (Sub-1ms)
For latency-critical paths, verify token signatures locally without a network round-trip:
const mandatum = new Mandatum({
apiKey: 'mdt_live_...',
localVerification: true, // fetches public key on init
});
// check() now verifies the signature locally first,
// then calls the server only for constraint evaluationError Handling
All errors throw MandatumError with a code property:
import { MandatumError } from '@mandatum/sdk';
try {
await mandatum.check(token, 'payments:execute', { amount: 999999 });
} catch (err) {
if (err instanceof MandatumError) {
console.log(err.code); // 'RATE_LIMIT_MINUTE', 'TIMEOUT', 'API_ERROR'
console.log(err.status); // HTTP status code (if applicable)
}
}Security
- All tokens are Ed25519-signed JWTs — tamper-proof and verifiable with the public key
- API keys are SHA-256 hashed before storage — Mandatum never stores raw keys
- Audit events are hash-chained — any tampering breaks the chain
- Receipts are cryptographically signed — non-repudiable proof of authorization
License
MIT © Mandatum
