npm package: @mandatum/sdk
Description: Zero-trust authorization and spending limits for AI agents. Ed25519-signed JWTs, policy enforcement, and payment gating in one line.
Author: Mandatum
Latest version: 1.0.0

# @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.

[![npm](https://img.shields.io/npm/v/@mandatum/sdk)](https://www.npmjs.com/package/@mandatum/sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

## Install

```bash
npm install @mandatum/sdk
```

## Quick Start

```javascript
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: 'cfo@yourcompany.com',
});

// ─── 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.

```javascript
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 stats
```

### Quick Boolean Check

If you just need a true/false gate:

```javascript
if (await mandatum.isAllowed(token, 'email:send', { to: 'user@example.com' })) {
  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

```javascript
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 budget
```

### Tokens

```javascript
mandatum.tokens.issue({ agentId, scopes, constraints, expiresIn })
mandatum.tokens.verify(token, action, context)
mandatum.tokens.revoke(jti)
mandatum.tokens.list({ agentId, status })
```

### Policies

```javascript
mandatum.policies.create({ name, resource, actions, constraints })
mandatum.policies.list()
mandatum.policies.get(id)
mandatum.policies.assign(agentId, policyId)
```

### Audit

```javascript
mandatum.audit.list({ limit, agentId })
mandatum.audit.verifyChain()         // verify hash-chain integrity
mandatum.audit.getReceipt(eventId)   // get signed receipt for an event
```

## Payment Gateway Wrappers

Pre-built wrappers that call `mandatum.check()` before creating payments:

### Razorpay

```javascript
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 spending
```

### Stripe

```javascript
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:

```javascript
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 evaluation
```

## Error Handling

All errors throw `MandatumError` with a `code` property:

```javascript
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](https://mandatumio.vercel.app)