# @agntor/trust-proxy

Express middleware for x402 transaction validation with Agntor audit tickets. Includes prompt injection guard, JWT proof validation, and PII redaction.

## Installation

```bash
npm install @agntor/trust-proxy @agntor/sdk express
```

## Quick Start

```typescript
import express from 'express';
import { createTrustProxy } from '@agntor/trust-proxy';
import { TicketIssuer } from '@agntor/sdk';

const app = express();
app.use(express.json());

// Initialize issuer
const issuer = new TicketIssuer({
  signingKey: process.env.AGNTOR_SECRET_KEY!,
  issuer: 'agntor.com',
});

// Apply trust proxy to protected routes
app.use('/api/agent', createTrustProxy({ issuer }));

// Protected endpoint
app.post('/api/agent/execute', (req, res) => {
  // Access validated agent info
  const { agentId, auditLevel } = req.agntor!;
  
  res.json({
    message: 'Transaction approved',
    agent: agentId,
    level: auditLevel,
  });
});

app.listen(3000);
```

## API Reference

### `createTrustProxy(config: TrustProxyConfig)`

Creates the trust validation middleware.

**Config Options:**

```typescript
{
  issuer: TicketIssuer;                    // Required
  headerName?: string;                     // Default: 'x-agntor-proof'
  requireProof?: boolean;                  // Default: true
  validateTransactionValue?: boolean;      // Default: true
  transactionValuePath?: string;           // Default: 'amount'
  mcpServerPath?: string;                  // Default: 'mcp_server'
  paymentProtocolPath?: string;            // Default: 'payment_protocol'
  x402PaymentProofPath?: string;           // Default: 'x402_proof'
  onError?: (error, req, res) => void;     // Custom error handler
  onSuccess?: (result, req) => void;       // Success callback
}
```

### Pre-configured Variants

**`strictTrustProxy(config)`** - Always requires and validates proof
**`optionalTrustProxy(config)`** - Logs but doesn't block invalid tickets

## Request Flow

When a ticket includes `requires_x402_payment: true`, requests must include:
`payment_protocol: "x402"` and an `x402_proof` object with a `txHash`.

### 1. Missing X-AGNTOR-Proof Header

```
POST /api/agent/execute
```

**Response: 402 Payment Required**
```json
{
  "error": "Payment Required",
  "code": 402,
  "message": "X-AGNTOR-Proof header required for agent transaction",
  "payment_context": {
    "required_proof": "X-AGNTOR-Proof",
    "issuer_endpoint": "https://agntor.com/issue-ticket",
    "documentation": "https://agntor.com/x402-handshake"
  }
}
```

### 2. Valid Proof Provided

```
POST /api/agent/execute
X-AGNTOR-Proof: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
  "amount": 25.0,
  "mcp_server": "finance-node"
}
```

**Middleware Action:**
- Validates JWT signature
- Checks expiry
- Enforces `max_op_value` constraint
- Verifies `allowed_mcp_servers` whitelist
- Attaches `req.agntor` with agent info

**Request continues to handler with:**
```typescript
req.agntor = {
  ticket: { /* full payload */ },
  agentId: "agent-12345",
  auditLevel: "Gold"
}
```

### 3. Invalid/Expired Proof

**Response: 403 Forbidden**
```json
{
  "error": "Forbidden",
  "code": 403,
  "message": "Agent certification validation failed",
  "reason": "Ticket has expired",
  "error_code": "EXPIRED"
}
```

## Advanced Usage

### Custom Error Handling

```typescript
app.use('/api', createTrustProxy({
  issuer,
  onError: (error, req, res) => {
    // Log to monitoring system
    console.error('Trust violation:', error);
    
    // Custom response
    res.status(error.statusCode).json({
      error: error.message,
      agent_id: req.headers['x-agent-id'],
      timestamp: new Date().toISOString(),
    });
  },
}));
```

### Metrics Collection

```typescript
app.use('/api', createTrustProxy({
  issuer,
  onSuccess: (result, req) => {
    metrics.increment('agntor.validations.success', {
      audit_level: result.payload!.audit_level,
      agent_id: result.payload!.sub,
    });
  },
}));
```

### Nested Transaction Data

```typescript
// Request body structure
{
  "transaction": {
    "payment": {
      "amount": 100.0
    }
  },
  "target": {
    "mcp_server": "banking-node"
  }
}

// Configure proxy
createTrustProxy({
  issuer,
  transactionValuePath: 'transaction.payment.amount',
  mcpServerPath: 'target.mcp_server',
})
```

### Rate Limiting Integration

```typescript
import rateLimit from 'express-rate-limit';

// Apply rate limiter after trust proxy
app.use('/api', createTrustProxy({ issuer }));

app.use('/api', rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: (req) => {
    const maxOps = req.agntor?.ticket?.constraints.max_ops_per_hour;
    return maxOps || 100;
  },
  keyGenerator: (req) => req.agntor?.agentId || req.ip,
}));
```

## Error Codes

| Code | Meaning | Status |
|------|---------|--------|
| `EXPIRED` | Ticket past expiry | 403 |
| `INVALID_SIGNATURE` | Cryptographic failure | 403 |
| `INVALID_FORMAT` | Malformed token | 403 |
| `KILL_SWITCH` | Agent emergency disabled | 403 |
| `CONSTRAINT_VIOLATION` | Transaction exceeds limits | 403 |
| `VALIDATION_FAILED` | Generic validation error | 403 |
| `INTERNAL_ERROR` | System error | 500 |

## TypeScript Support

```typescript
import { AgntorRequest } from '@agntor/trust-proxy';

app.post('/api/agent/execute', (req: AgntorRequest, res) => {
  // Full type safety
  const agentId = req.agntor!.agentId;
  const constraints = req.agntor!.ticket.constraints;
  
  if (constraints.kill_switch_active) {
    // TypeScript knows this field exists
  }
});
```

## Security Best Practices

1. **Always use HTTPS in production**
2. **Validate on every financial transaction**
3. **Set short ticket lifetimes** (5 minutes recommended)
4. **Monitor failed validations** - may indicate attack
5. **Implement kill switch webhooks** for real-time revocation
6. **Use separate keys for dev/staging/prod**

## Performance

- **Validation time**: <5ms per request
- **Memory overhead**: ~50 bytes per request
- **Supports**: 10,000+ req/sec on standard hardware

Designed for high-throughput agent marketplaces.
