Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 189 additions & 0 deletions security/agent-auth-contract.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
---
title: "Agent Authentication Contract"
description: "ASG Agent Cloud v5.2.x API Key authentication specification"
---

# Agent Authentication Contract

This document defines the authentication contract for programmatic (agent/bot) access to ASG Agent Cloud.

## Authentication Hierarchy

ASG Gateway supports two authentication methods, evaluated in order:

1. **SIWS Session Cookie** (`asg_session`) — For console UI users
2. **Bearer Token API Key** — For agents and programmatic access

```
Authorization: Bearer asc_sk_...
```
Comment on lines +18 to +19
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use the documented key prefixes in the Authorization example.

The example shows asc_sk_..., but the format section defines asc_sk_live_ / asc_sk_test_. Align the example to avoid confusion.

Proposed fix
-Authorization: Bearer asc_sk_...
+Authorization: Bearer asc_sk_live_...
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Authorization: Bearer asc_sk_...
```
Authorization: Bearer asc_sk_live_...
🤖 Prompt for AI Agents
In `@security/agent-auth-contract.mdx` around lines 18 - 19, Update the
Authorization example to use one of the documented key prefixes (asc_sk_live_ or
asc_sk_test_) instead of the truncated asc_sk_ so it matches the format section;
edit the Authorization header string in the example (the `Authorization: Bearer
...` line) to show either `Authorization: Bearer asc_sk_live_...` or
`Authorization: Bearer asc_sk_test_...` to avoid confusion.


## API Key Format

| Prefix | Environment | Example |
|--------|-------------|---------|
| `asc_sk_live_` | Production | `asc_sk_live_abc123...` |
| `asc_sk_test_` | Staging/Dev | `asc_sk_test_xyz789...` |

Keys are 64-character random strings prefixed with environment indicator.

## Security Model

### Key Storage

- **Plain-text key**: Shown ONCE at creation time — user must save it
- **Server stores**: BCrypt hash only (cost=10)
- **No recovery**: Lost keys cannot be retrieved; user must rotate

### Scopes

| Scope | Description |
|-------|-------------|
| `read` | Query balance, history, usage stats (default) |
| `fund` | Initiate deposits, manage billing (requires opt-in) |

### Rate Limits

| Tier | RPM Limit | Default |
|------|-----------|---------|
| Free | 60 | ✓ |
| Plus | 300 | |
| Pro | 1000 | |

Limits are per-key, not per-wallet. 429 responses include `Retry-After` header.

## Endpoints (Billing Plane)

### Create Key

```http
POST /keys
Content-Type: application/json
Cookie: asg_session=...

{
"name": "My Agent Bot",
"scopes": ["read"],
"rate_limit_rpm": 60
}
```

**Response (201):**

```json
{
"key_id": "key_abc123",
"api_key": "asc_sk_live_...", // ⚠️ SHOW ONCE
"name": "My Agent Bot",
"scopes": ["read"],
"rate_limit_rpm": 60,
"created_at": "2026-02-03T12:00:00Z"
}
```

### List Keys

```http
GET /keys
Cookie: asg_session=...
```

**Response:**

```json
{
"keys": [
{
"key_id": "key_abc123",
"name": "My Agent Bot",
"prefix": "asc_sk_live_abc...", // First 16 chars only
"scopes": ["read"],
"rate_limit_rpm": 60,
"last_used_at": "2026-02-03T11:30:00Z",
"created_at": "2026-02-03T10:00:00Z"
}
]
}
```

### Revoke Key

```http
DELETE /keys/:key_id
Cookie: asg_session=...
```

### Rotate Key

```http
POST /keys/:key_id/rotate
Cookie: asg_session=...
```

**Response:** New key object (same as Create)

### Validate Key (Internal)

```http
POST /keys/validate
Content-Type: application/json

{ "api_key": "asc_sk_live_..." }
```

**Response:**

```json
{
"valid": true,
"key_id": "key_abc123",
"owner_wallet": "ABC...xyz",
"scopes": ["read"],
"rate_limit_rpm": 60
}
```

## Gateway Auth Middleware

The gateway validates keys via billing-plane `/keys/validate` with 5-minute caching.

```typescript
// Request gets decorated with:
interface AuthenticatedRequest extends Request {
apiKeyId?: string; // e.g., "key_abc123"
ownerWallet?: string; // Wallet that created the key
scopes?: string[]; // ["read"] or ["read", "fund"]
rateLimitRpm?: number; // Per-key rate limit
}
```

## Error Responses

| Status | Code | Description |
|--------|------|-------------|
| 401 | `UNAUTHORIZED` | Missing or invalid API key |
| 403 | `FORBIDDEN` | Missing required scope |
| 429 | `RATE_LIMITED` | Rate limit exceeded |

## Usage Example (Agent)

```typescript
const response = await fetch('https://agent.asgcompute.com/v1/account/balance', {
headers: {
'Authorization': 'Bearer asc_sk_live_your_key_here',
'Content-Type': 'application/json'
}
});

if (response.status === 401) {
// Re-authenticate or refresh key
}

const balance = await response.json();
```

## Related Documents

- [Quickstart for Agents](/docs/guide/agent-quickstart)
- [Rate Limiting](/docs/security/rate-limits)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider hyphenating “Rate‑Limiting” if used as a compound adjective.

LanguageTool flags this as a potential compound adjective. If the link title is intended as an adjective, hyphenate it.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~188-~188: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...gents](/docs/guide/agent-quickstart) - Rate Limiting - [Error C...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🤖 Prompt for AI Agents
In `@security/agent-auth-contract.mdx` at line 188, The link text "[Rate
Limiting](/docs/security/rate-limits)" should be hyphenated when used as a
compound adjective; update that token to "Rate‑Limiting" in the document
(replace the link label only, leaving the URL /docs/security/rate-limits
unchanged) wherever the phrase functions adjectivally so the link reads
"[Rate‑Limiting](/docs/security/rate-limits)".

- [Error Codes](/docs/api/errors)