@dupecom/botcha-cloudflare 0.16.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/auth.d.ts +48 -3
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +89 -21
- package/dist/dashboard/docs.d.ts +15 -0
- package/dist/dashboard/docs.d.ts.map +1 -0
- package/dist/dashboard/docs.js +556 -0
- package/dist/dashboard/layout.d.ts +12 -0
- package/dist/dashboard/layout.d.ts.map +1 -1
- package/dist/dashboard/layout.js +12 -5
- package/dist/dashboard/showcase.d.ts.map +1 -1
- package/dist/dashboard/showcase.js +2 -1
- package/dist/dashboard/whitepaper.d.ts.map +1 -1
- package/dist/dashboard/whitepaper.js +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +125 -13
- package/dist/static.d.ts +592 -2
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +422 -9
- package/dist/tap-attestation-routes.d.ts +204 -0
- package/dist/tap-attestation-routes.d.ts.map +1 -0
- package/dist/tap-attestation-routes.js +396 -0
- package/dist/tap-attestation.d.ts +178 -0
- package/dist/tap-attestation.d.ts.map +1 -0
- package/dist/tap-attestation.js +416 -0
- package/dist/tap-delegation-routes.d.ts +236 -0
- package/dist/tap-delegation-routes.d.ts.map +1 -0
- package/dist/tap-delegation-routes.js +378 -0
- package/dist/tap-delegation.d.ts +127 -0
- package/dist/tap-delegation.d.ts.map +1 -0
- package/dist/tap-delegation.js +490 -0
- package/dist/tap-jwks.d.ts +2 -1
- package/dist/tap-jwks.d.ts.map +1 -1
- package/dist/tap-jwks.js +31 -7
- package/dist/tap-reputation-routes.d.ts +154 -0
- package/dist/tap-reputation-routes.d.ts.map +1 -0
- package/dist/tap-reputation-routes.js +341 -0
- package/dist/tap-reputation.d.ts +136 -0
- package/dist/tap-reputation.d.ts.map +1 -0
- package/dist/tap-reputation.js +346 -0
- package/package.json +1 -1
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TAP Delegation Chain API Routes
|
|
3
|
+
*
|
|
4
|
+
* Endpoints for creating, querying, revoking, and verifying
|
|
5
|
+
* delegation chains between TAP agents.
|
|
6
|
+
*
|
|
7
|
+
* Routes:
|
|
8
|
+
* POST /v1/delegations — Create delegation
|
|
9
|
+
* GET /v1/delegations/:id — Get delegation details
|
|
10
|
+
* GET /v1/delegations — List delegations (by agent)
|
|
11
|
+
* POST /v1/delegations/:id/revoke — Revoke delegation (cascades)
|
|
12
|
+
* POST /v1/verify/delegation — Verify delegation chain
|
|
13
|
+
*/
|
|
14
|
+
import type { Context } from 'hono';
|
|
15
|
+
/**
|
|
16
|
+
* POST /v1/delegations
|
|
17
|
+
* Create a delegation from one agent to another
|
|
18
|
+
*/
|
|
19
|
+
export declare function createDelegationRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
20
|
+
success: false;
|
|
21
|
+
error: string | undefined;
|
|
22
|
+
message: string;
|
|
23
|
+
}, 401, "json">) | (Response & import("hono").TypedResponse<{
|
|
24
|
+
success: false;
|
|
25
|
+
error: string;
|
|
26
|
+
message: string | undefined;
|
|
27
|
+
}, any, "json">) | (Response & import("hono").TypedResponse<{
|
|
28
|
+
success: true;
|
|
29
|
+
delegation_id: string;
|
|
30
|
+
grantor_id: string;
|
|
31
|
+
grantee_id: string;
|
|
32
|
+
app_id: string;
|
|
33
|
+
capabilities: {
|
|
34
|
+
action: import("./tap-agents.js").TAPAction;
|
|
35
|
+
scope?: string[] | undefined;
|
|
36
|
+
restrictions?: {
|
|
37
|
+
[x: string]: any;
|
|
38
|
+
max_amount?: number | undefined;
|
|
39
|
+
rate_limit?: number | undefined;
|
|
40
|
+
} | undefined;
|
|
41
|
+
}[];
|
|
42
|
+
chain: string[];
|
|
43
|
+
depth: number;
|
|
44
|
+
max_depth: number;
|
|
45
|
+
parent_delegation_id: string | null;
|
|
46
|
+
created_at: string;
|
|
47
|
+
expires_at: string;
|
|
48
|
+
metadata: {
|
|
49
|
+
[x: string]: string;
|
|
50
|
+
} | null;
|
|
51
|
+
}, 201, "json">)>;
|
|
52
|
+
/**
|
|
53
|
+
* GET /v1/delegations/:id
|
|
54
|
+
* Get delegation details
|
|
55
|
+
*/
|
|
56
|
+
export declare function getDelegationRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
57
|
+
success: false;
|
|
58
|
+
error: string;
|
|
59
|
+
message: string;
|
|
60
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
61
|
+
success: false;
|
|
62
|
+
error: string;
|
|
63
|
+
message: string;
|
|
64
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
65
|
+
success: true;
|
|
66
|
+
delegation_id: string;
|
|
67
|
+
grantor_id: string;
|
|
68
|
+
grantee_id: string;
|
|
69
|
+
app_id: string;
|
|
70
|
+
capabilities: {
|
|
71
|
+
action: import("./tap-agents.js").TAPAction;
|
|
72
|
+
scope?: string[] | undefined;
|
|
73
|
+
restrictions?: {
|
|
74
|
+
[x: string]: any;
|
|
75
|
+
max_amount?: number | undefined;
|
|
76
|
+
rate_limit?: number | undefined;
|
|
77
|
+
} | undefined;
|
|
78
|
+
}[];
|
|
79
|
+
chain: string[];
|
|
80
|
+
depth: number;
|
|
81
|
+
max_depth: number;
|
|
82
|
+
parent_delegation_id: string | null;
|
|
83
|
+
created_at: string;
|
|
84
|
+
expires_at: string;
|
|
85
|
+
revoked: boolean;
|
|
86
|
+
revoked_at: string | null;
|
|
87
|
+
revocation_reason: string | null;
|
|
88
|
+
metadata: {
|
|
89
|
+
[x: string]: string;
|
|
90
|
+
} | null;
|
|
91
|
+
time_remaining: number;
|
|
92
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
93
|
+
success: false;
|
|
94
|
+
error: string;
|
|
95
|
+
message: string;
|
|
96
|
+
}, 500, "json">)>;
|
|
97
|
+
/**
|
|
98
|
+
* GET /v1/delegations
|
|
99
|
+
* List delegations for an agent
|
|
100
|
+
*
|
|
101
|
+
* Query params:
|
|
102
|
+
* agent_id — required, the agent to list delegations for
|
|
103
|
+
* direction — 'in', 'out', or 'both' (default: 'both')
|
|
104
|
+
* include_revoked — 'true' to include revoked delegations
|
|
105
|
+
* include_expired — 'true' to include expired delegations
|
|
106
|
+
*/
|
|
107
|
+
export declare function listDelegationsRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
108
|
+
success: false;
|
|
109
|
+
error: string | undefined;
|
|
110
|
+
message: string;
|
|
111
|
+
}, 401, "json">) | (Response & import("hono").TypedResponse<{
|
|
112
|
+
success: false;
|
|
113
|
+
error: string;
|
|
114
|
+
message: string;
|
|
115
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
116
|
+
success: false;
|
|
117
|
+
error: string;
|
|
118
|
+
message: string;
|
|
119
|
+
}, 500, "json">) | (Response & import("hono").TypedResponse<{
|
|
120
|
+
success: true;
|
|
121
|
+
delegations: {
|
|
122
|
+
delegation_id: string;
|
|
123
|
+
grantor_id: string;
|
|
124
|
+
grantee_id: string;
|
|
125
|
+
capabilities: {
|
|
126
|
+
action: import("./tap-agents.js").TAPAction;
|
|
127
|
+
scope?: string[] | undefined;
|
|
128
|
+
restrictions?: {
|
|
129
|
+
[x: string]: any;
|
|
130
|
+
max_amount?: number | undefined;
|
|
131
|
+
rate_limit?: number | undefined;
|
|
132
|
+
} | undefined;
|
|
133
|
+
}[];
|
|
134
|
+
chain: string[];
|
|
135
|
+
depth: number;
|
|
136
|
+
created_at: string;
|
|
137
|
+
expires_at: string;
|
|
138
|
+
revoked: boolean;
|
|
139
|
+
parent_delegation_id: string | null;
|
|
140
|
+
}[];
|
|
141
|
+
count: number;
|
|
142
|
+
agent_id: string;
|
|
143
|
+
direction: "out" | "in" | "both";
|
|
144
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">)>;
|
|
145
|
+
/**
|
|
146
|
+
* POST /v1/delegations/:id/revoke
|
|
147
|
+
* Revoke a delegation (cascades to sub-delegations)
|
|
148
|
+
*/
|
|
149
|
+
export declare function revokeDelegationRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
150
|
+
success: false;
|
|
151
|
+
error: string;
|
|
152
|
+
message: string;
|
|
153
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
154
|
+
success: false;
|
|
155
|
+
error: string | undefined;
|
|
156
|
+
message: string;
|
|
157
|
+
}, 401, "json">) | (Response & import("hono").TypedResponse<{
|
|
158
|
+
success: false;
|
|
159
|
+
error: string;
|
|
160
|
+
message: string;
|
|
161
|
+
}, 404, "json">) | (Response & import("hono").TypedResponse<{
|
|
162
|
+
success: false;
|
|
163
|
+
error: string;
|
|
164
|
+
message: string;
|
|
165
|
+
}, 403, "json">) | (Response & import("hono").TypedResponse<{
|
|
166
|
+
success: false;
|
|
167
|
+
error: string;
|
|
168
|
+
message: string | undefined;
|
|
169
|
+
}, 500, "json">) | (Response & import("hono").TypedResponse<{
|
|
170
|
+
success: true;
|
|
171
|
+
delegation_id: string;
|
|
172
|
+
revoked: true;
|
|
173
|
+
revoked_at: string | null;
|
|
174
|
+
revocation_reason: string | null;
|
|
175
|
+
message: string;
|
|
176
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">)>;
|
|
177
|
+
/**
|
|
178
|
+
* POST /v1/verify/delegation
|
|
179
|
+
* Verify an entire delegation chain is valid
|
|
180
|
+
*
|
|
181
|
+
* Body: { delegation_id: string }
|
|
182
|
+
*
|
|
183
|
+
* Returns the full chain and effective capabilities if valid.
|
|
184
|
+
*/
|
|
185
|
+
export declare function verifyDelegationRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
|
|
186
|
+
success: false;
|
|
187
|
+
error: string;
|
|
188
|
+
message: string;
|
|
189
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
190
|
+
success: false;
|
|
191
|
+
valid: false;
|
|
192
|
+
error: string | undefined;
|
|
193
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
194
|
+
success: true;
|
|
195
|
+
valid: true;
|
|
196
|
+
chain_length: number;
|
|
197
|
+
chain: {
|
|
198
|
+
delegation_id: string;
|
|
199
|
+
grantor_id: string;
|
|
200
|
+
grantee_id: string;
|
|
201
|
+
capabilities: {
|
|
202
|
+
action: import("./tap-agents.js").TAPAction;
|
|
203
|
+
scope?: string[] | undefined;
|
|
204
|
+
restrictions?: {
|
|
205
|
+
[x: string]: any;
|
|
206
|
+
max_amount?: number | undefined;
|
|
207
|
+
rate_limit?: number | undefined;
|
|
208
|
+
} | undefined;
|
|
209
|
+
}[];
|
|
210
|
+
depth: number;
|
|
211
|
+
created_at: string;
|
|
212
|
+
expires_at: string;
|
|
213
|
+
}[];
|
|
214
|
+
effective_capabilities: {
|
|
215
|
+
action: import("./tap-agents.js").TAPAction;
|
|
216
|
+
scope?: string[] | undefined;
|
|
217
|
+
restrictions?: {
|
|
218
|
+
[x: string]: any;
|
|
219
|
+
max_amount?: number | undefined;
|
|
220
|
+
rate_limit?: number | undefined;
|
|
221
|
+
} | undefined;
|
|
222
|
+
}[] | undefined;
|
|
223
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
|
|
224
|
+
success: false;
|
|
225
|
+
error: string;
|
|
226
|
+
message: string;
|
|
227
|
+
}, 500, "json">)>;
|
|
228
|
+
declare const _default: {
|
|
229
|
+
createDelegationRoute: typeof createDelegationRoute;
|
|
230
|
+
getDelegationRoute: typeof getDelegationRoute;
|
|
231
|
+
listDelegationsRoute: typeof listDelegationsRoute;
|
|
232
|
+
revokeDelegationRoute: typeof revokeDelegationRoute;
|
|
233
|
+
verifyDelegationRoute: typeof verifyDelegationRoute;
|
|
234
|
+
};
|
|
235
|
+
export default _default;
|
|
236
|
+
//# sourceMappingURL=tap-delegation-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap-delegation-routes.d.ts","sourceRoot":"","sources":["../src/tap-delegation-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AA4CpC;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsGrD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAmDlD;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oEAqEpD;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;oEAsErD;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAkDrD;;;;;;;;AAED,wBAME"}
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TAP Delegation Chain API Routes
|
|
3
|
+
*
|
|
4
|
+
* Endpoints for creating, querying, revoking, and verifying
|
|
5
|
+
* delegation chains between TAP agents.
|
|
6
|
+
*
|
|
7
|
+
* Routes:
|
|
8
|
+
* POST /v1/delegations — Create delegation
|
|
9
|
+
* GET /v1/delegations/:id — Get delegation details
|
|
10
|
+
* GET /v1/delegations — List delegations (by agent)
|
|
11
|
+
* POST /v1/delegations/:id/revoke — Revoke delegation (cascades)
|
|
12
|
+
* POST /v1/verify/delegation — Verify delegation chain
|
|
13
|
+
*/
|
|
14
|
+
import { extractBearerToken, verifyToken } from './auth.js';
|
|
15
|
+
import { TAP_VALID_ACTIONS } from './tap-agents.js';
|
|
16
|
+
import { createDelegation, getDelegation, listDelegations, revokeDelegation, verifyDelegationChain, } from './tap-delegation.js';
|
|
17
|
+
// ============ VALIDATION HELPERS ============
|
|
18
|
+
async function validateAppAccess(c, requireAuth = true) {
|
|
19
|
+
const queryAppId = c.req.query('app_id');
|
|
20
|
+
let jwtAppId;
|
|
21
|
+
const authHeader = c.req.header('authorization');
|
|
22
|
+
const token = extractBearerToken(authHeader);
|
|
23
|
+
if (token) {
|
|
24
|
+
const result = await verifyToken(token, c.env.JWT_SECRET, c.env);
|
|
25
|
+
if (result.valid && result.payload) {
|
|
26
|
+
jwtAppId = result.payload.app_id;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const appId = queryAppId || jwtAppId;
|
|
30
|
+
if (requireAuth && !appId) {
|
|
31
|
+
return { valid: false, error: 'MISSING_APP_ID', status: 401 };
|
|
32
|
+
}
|
|
33
|
+
return { valid: true, appId };
|
|
34
|
+
}
|
|
35
|
+
// ============ ROUTE HANDLERS ============
|
|
36
|
+
/**
|
|
37
|
+
* POST /v1/delegations
|
|
38
|
+
* Create a delegation from one agent to another
|
|
39
|
+
*/
|
|
40
|
+
export async function createDelegationRoute(c) {
|
|
41
|
+
try {
|
|
42
|
+
const appAccess = await validateAppAccess(c, true);
|
|
43
|
+
if (!appAccess.valid) {
|
|
44
|
+
return c.json({
|
|
45
|
+
success: false,
|
|
46
|
+
error: appAccess.error,
|
|
47
|
+
message: 'Authentication required'
|
|
48
|
+
}, (appAccess.status || 401));
|
|
49
|
+
}
|
|
50
|
+
const body = await c.req.json().catch(() => ({}));
|
|
51
|
+
// Validate required fields
|
|
52
|
+
if (!body.grantor_id || !body.grantee_id) {
|
|
53
|
+
return c.json({
|
|
54
|
+
success: false,
|
|
55
|
+
error: 'MISSING_REQUIRED_FIELDS',
|
|
56
|
+
message: 'grantor_id and grantee_id are required'
|
|
57
|
+
}, 400);
|
|
58
|
+
}
|
|
59
|
+
if (!body.capabilities || !Array.isArray(body.capabilities) || body.capabilities.length === 0) {
|
|
60
|
+
return c.json({
|
|
61
|
+
success: false,
|
|
62
|
+
error: 'MISSING_CAPABILITIES',
|
|
63
|
+
message: 'At least one capability is required'
|
|
64
|
+
}, 400);
|
|
65
|
+
}
|
|
66
|
+
// Validate capability actions
|
|
67
|
+
for (const cap of body.capabilities) {
|
|
68
|
+
if (!cap.action || !TAP_VALID_ACTIONS.includes(cap.action)) {
|
|
69
|
+
return c.json({
|
|
70
|
+
success: false,
|
|
71
|
+
error: 'INVALID_CAPABILITY',
|
|
72
|
+
message: `Invalid capability action. Valid: ${TAP_VALID_ACTIONS.join(', ')}`
|
|
73
|
+
}, 400);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const options = {
|
|
77
|
+
grantor_id: body.grantor_id,
|
|
78
|
+
grantee_id: body.grantee_id,
|
|
79
|
+
capabilities: body.capabilities,
|
|
80
|
+
duration_seconds: body.duration_seconds,
|
|
81
|
+
max_depth: body.max_depth,
|
|
82
|
+
parent_delegation_id: body.parent_delegation_id,
|
|
83
|
+
metadata: body.metadata,
|
|
84
|
+
};
|
|
85
|
+
const result = await createDelegation(c.env.AGENTS, c.env.SESSIONS, appAccess.appId, options);
|
|
86
|
+
if (!result.success) {
|
|
87
|
+
// Determine appropriate status code
|
|
88
|
+
const status = result.error?.includes('not found') ? 404
|
|
89
|
+
: result.error?.includes('does not belong') ? 403
|
|
90
|
+
: result.error?.includes('Cannot delegate') ? 403
|
|
91
|
+
: result.error?.includes('depth limit') ? 403
|
|
92
|
+
: result.error?.includes('cycle') ? 409
|
|
93
|
+
: result.error?.includes('revoked') ? 410
|
|
94
|
+
: result.error?.includes('expired') ? 410
|
|
95
|
+
: 400;
|
|
96
|
+
return c.json({
|
|
97
|
+
success: false,
|
|
98
|
+
error: 'DELEGATION_CREATION_FAILED',
|
|
99
|
+
message: result.error
|
|
100
|
+
}, status);
|
|
101
|
+
}
|
|
102
|
+
const del = result.delegation;
|
|
103
|
+
return c.json({
|
|
104
|
+
success: true,
|
|
105
|
+
delegation_id: del.delegation_id,
|
|
106
|
+
grantor_id: del.grantor_id,
|
|
107
|
+
grantee_id: del.grantee_id,
|
|
108
|
+
app_id: del.app_id,
|
|
109
|
+
capabilities: del.capabilities,
|
|
110
|
+
chain: del.chain,
|
|
111
|
+
depth: del.depth,
|
|
112
|
+
max_depth: del.max_depth,
|
|
113
|
+
parent_delegation_id: del.parent_delegation_id || null,
|
|
114
|
+
created_at: new Date(del.created_at).toISOString(),
|
|
115
|
+
expires_at: new Date(del.expires_at).toISOString(),
|
|
116
|
+
metadata: del.metadata || null,
|
|
117
|
+
}, 201);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
console.error('Delegation creation error:', error);
|
|
121
|
+
return c.json({
|
|
122
|
+
success: false,
|
|
123
|
+
error: 'INTERNAL_ERROR',
|
|
124
|
+
message: 'Internal server error'
|
|
125
|
+
}, 500);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* GET /v1/delegations/:id
|
|
130
|
+
* Get delegation details
|
|
131
|
+
*/
|
|
132
|
+
export async function getDelegationRoute(c) {
|
|
133
|
+
try {
|
|
134
|
+
const delegationId = c.req.param('id');
|
|
135
|
+
if (!delegationId) {
|
|
136
|
+
return c.json({
|
|
137
|
+
success: false,
|
|
138
|
+
error: 'MISSING_DELEGATION_ID',
|
|
139
|
+
message: 'Delegation ID is required'
|
|
140
|
+
}, 400);
|
|
141
|
+
}
|
|
142
|
+
const result = await getDelegation(c.env.SESSIONS, delegationId);
|
|
143
|
+
if (!result.success || !result.delegation) {
|
|
144
|
+
return c.json({
|
|
145
|
+
success: false,
|
|
146
|
+
error: 'DELEGATION_NOT_FOUND',
|
|
147
|
+
message: result.error || 'Delegation not found or expired'
|
|
148
|
+
}, 404);
|
|
149
|
+
}
|
|
150
|
+
const del = result.delegation;
|
|
151
|
+
return c.json({
|
|
152
|
+
success: true,
|
|
153
|
+
delegation_id: del.delegation_id,
|
|
154
|
+
grantor_id: del.grantor_id,
|
|
155
|
+
grantee_id: del.grantee_id,
|
|
156
|
+
app_id: del.app_id,
|
|
157
|
+
capabilities: del.capabilities,
|
|
158
|
+
chain: del.chain,
|
|
159
|
+
depth: del.depth,
|
|
160
|
+
max_depth: del.max_depth,
|
|
161
|
+
parent_delegation_id: del.parent_delegation_id || null,
|
|
162
|
+
created_at: new Date(del.created_at).toISOString(),
|
|
163
|
+
expires_at: new Date(del.expires_at).toISOString(),
|
|
164
|
+
revoked: del.revoked,
|
|
165
|
+
revoked_at: del.revoked_at ? new Date(del.revoked_at).toISOString() : null,
|
|
166
|
+
revocation_reason: del.revocation_reason || null,
|
|
167
|
+
metadata: del.metadata || null,
|
|
168
|
+
time_remaining: Math.max(0, del.expires_at - Date.now()),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error('Delegation retrieval error:', error);
|
|
173
|
+
return c.json({
|
|
174
|
+
success: false,
|
|
175
|
+
error: 'INTERNAL_ERROR',
|
|
176
|
+
message: 'Internal server error'
|
|
177
|
+
}, 500);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* GET /v1/delegations
|
|
182
|
+
* List delegations for an agent
|
|
183
|
+
*
|
|
184
|
+
* Query params:
|
|
185
|
+
* agent_id — required, the agent to list delegations for
|
|
186
|
+
* direction — 'in', 'out', or 'both' (default: 'both')
|
|
187
|
+
* include_revoked — 'true' to include revoked delegations
|
|
188
|
+
* include_expired — 'true' to include expired delegations
|
|
189
|
+
*/
|
|
190
|
+
export async function listDelegationsRoute(c) {
|
|
191
|
+
try {
|
|
192
|
+
const appAccess = await validateAppAccess(c, true);
|
|
193
|
+
if (!appAccess.valid) {
|
|
194
|
+
return c.json({
|
|
195
|
+
success: false,
|
|
196
|
+
error: appAccess.error,
|
|
197
|
+
message: 'Authentication required'
|
|
198
|
+
}, (appAccess.status || 401));
|
|
199
|
+
}
|
|
200
|
+
const agentId = c.req.query('agent_id');
|
|
201
|
+
if (!agentId) {
|
|
202
|
+
return c.json({
|
|
203
|
+
success: false,
|
|
204
|
+
error: 'MISSING_AGENT_ID',
|
|
205
|
+
message: 'agent_id query parameter is required'
|
|
206
|
+
}, 400);
|
|
207
|
+
}
|
|
208
|
+
const direction = (c.req.query('direction') || 'both');
|
|
209
|
+
const includeRevoked = c.req.query('include_revoked') === 'true';
|
|
210
|
+
const includeExpired = c.req.query('include_expired') === 'true';
|
|
211
|
+
const result = await listDelegations(c.env.SESSIONS, {
|
|
212
|
+
agent_id: agentId,
|
|
213
|
+
app_id: appAccess.appId,
|
|
214
|
+
direction,
|
|
215
|
+
include_revoked: includeRevoked,
|
|
216
|
+
include_expired: includeExpired,
|
|
217
|
+
});
|
|
218
|
+
if (!result.success) {
|
|
219
|
+
return c.json({
|
|
220
|
+
success: false,
|
|
221
|
+
error: 'LIST_FAILED',
|
|
222
|
+
message: result.error || 'Failed to list delegations'
|
|
223
|
+
}, 500);
|
|
224
|
+
}
|
|
225
|
+
const delegations = result.delegations.map(del => ({
|
|
226
|
+
delegation_id: del.delegation_id,
|
|
227
|
+
grantor_id: del.grantor_id,
|
|
228
|
+
grantee_id: del.grantee_id,
|
|
229
|
+
capabilities: del.capabilities,
|
|
230
|
+
chain: del.chain,
|
|
231
|
+
depth: del.depth,
|
|
232
|
+
created_at: new Date(del.created_at).toISOString(),
|
|
233
|
+
expires_at: new Date(del.expires_at).toISOString(),
|
|
234
|
+
revoked: del.revoked,
|
|
235
|
+
parent_delegation_id: del.parent_delegation_id || null,
|
|
236
|
+
}));
|
|
237
|
+
return c.json({
|
|
238
|
+
success: true,
|
|
239
|
+
delegations,
|
|
240
|
+
count: delegations.length,
|
|
241
|
+
agent_id: agentId,
|
|
242
|
+
direction,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
console.error('Delegation listing error:', error);
|
|
247
|
+
return c.json({
|
|
248
|
+
success: false,
|
|
249
|
+
error: 'INTERNAL_ERROR',
|
|
250
|
+
message: 'Internal server error'
|
|
251
|
+
}, 500);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* POST /v1/delegations/:id/revoke
|
|
256
|
+
* Revoke a delegation (cascades to sub-delegations)
|
|
257
|
+
*/
|
|
258
|
+
export async function revokeDelegationRoute(c) {
|
|
259
|
+
try {
|
|
260
|
+
const delegationId = c.req.param('id');
|
|
261
|
+
if (!delegationId) {
|
|
262
|
+
return c.json({
|
|
263
|
+
success: false,
|
|
264
|
+
error: 'MISSING_DELEGATION_ID',
|
|
265
|
+
message: 'Delegation ID is required'
|
|
266
|
+
}, 400);
|
|
267
|
+
}
|
|
268
|
+
const appAccess = await validateAppAccess(c, true);
|
|
269
|
+
if (!appAccess.valid) {
|
|
270
|
+
return c.json({
|
|
271
|
+
success: false,
|
|
272
|
+
error: appAccess.error,
|
|
273
|
+
message: 'Authentication required'
|
|
274
|
+
}, (appAccess.status || 401));
|
|
275
|
+
}
|
|
276
|
+
// Verify delegation exists and belongs to this app
|
|
277
|
+
const existing = await getDelegation(c.env.SESSIONS, delegationId);
|
|
278
|
+
if (!existing.success || !existing.delegation) {
|
|
279
|
+
return c.json({
|
|
280
|
+
success: false,
|
|
281
|
+
error: 'DELEGATION_NOT_FOUND',
|
|
282
|
+
message: 'Delegation not found or expired'
|
|
283
|
+
}, 404);
|
|
284
|
+
}
|
|
285
|
+
if (existing.delegation.app_id !== appAccess.appId) {
|
|
286
|
+
return c.json({
|
|
287
|
+
success: false,
|
|
288
|
+
error: 'UNAUTHORIZED',
|
|
289
|
+
message: 'Delegation does not belong to this app'
|
|
290
|
+
}, 403);
|
|
291
|
+
}
|
|
292
|
+
const body = await c.req.json().catch(() => ({}));
|
|
293
|
+
const reason = body.reason || undefined;
|
|
294
|
+
const result = await revokeDelegation(c.env.SESSIONS, delegationId, reason);
|
|
295
|
+
if (!result.success) {
|
|
296
|
+
return c.json({
|
|
297
|
+
success: false,
|
|
298
|
+
error: 'REVOCATION_FAILED',
|
|
299
|
+
message: result.error
|
|
300
|
+
}, 500);
|
|
301
|
+
}
|
|
302
|
+
const del = result.delegation;
|
|
303
|
+
return c.json({
|
|
304
|
+
success: true,
|
|
305
|
+
delegation_id: del.delegation_id,
|
|
306
|
+
revoked: true,
|
|
307
|
+
revoked_at: del.revoked_at ? new Date(del.revoked_at).toISOString() : null,
|
|
308
|
+
revocation_reason: del.revocation_reason || null,
|
|
309
|
+
message: 'Delegation revoked. Sub-delegations have been cascaded.',
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
console.error('Delegation revocation error:', error);
|
|
314
|
+
return c.json({
|
|
315
|
+
success: false,
|
|
316
|
+
error: 'INTERNAL_ERROR',
|
|
317
|
+
message: 'Internal server error'
|
|
318
|
+
}, 500);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* POST /v1/verify/delegation
|
|
323
|
+
* Verify an entire delegation chain is valid
|
|
324
|
+
*
|
|
325
|
+
* Body: { delegation_id: string }
|
|
326
|
+
*
|
|
327
|
+
* Returns the full chain and effective capabilities if valid.
|
|
328
|
+
*/
|
|
329
|
+
export async function verifyDelegationRoute(c) {
|
|
330
|
+
try {
|
|
331
|
+
const body = await c.req.json().catch(() => ({}));
|
|
332
|
+
if (!body.delegation_id) {
|
|
333
|
+
return c.json({
|
|
334
|
+
success: false,
|
|
335
|
+
error: 'MISSING_DELEGATION_ID',
|
|
336
|
+
message: 'delegation_id is required'
|
|
337
|
+
}, 400);
|
|
338
|
+
}
|
|
339
|
+
const result = await verifyDelegationChain(c.env.AGENTS, c.env.SESSIONS, body.delegation_id);
|
|
340
|
+
if (!result.valid) {
|
|
341
|
+
return c.json({
|
|
342
|
+
success: false,
|
|
343
|
+
valid: false,
|
|
344
|
+
error: result.error,
|
|
345
|
+
}, 400);
|
|
346
|
+
}
|
|
347
|
+
return c.json({
|
|
348
|
+
success: true,
|
|
349
|
+
valid: true,
|
|
350
|
+
chain_length: result.chain.length,
|
|
351
|
+
chain: result.chain.map(del => ({
|
|
352
|
+
delegation_id: del.delegation_id,
|
|
353
|
+
grantor_id: del.grantor_id,
|
|
354
|
+
grantee_id: del.grantee_id,
|
|
355
|
+
capabilities: del.capabilities,
|
|
356
|
+
depth: del.depth,
|
|
357
|
+
created_at: new Date(del.created_at).toISOString(),
|
|
358
|
+
expires_at: new Date(del.expires_at).toISOString(),
|
|
359
|
+
})),
|
|
360
|
+
effective_capabilities: result.effective_capabilities,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
console.error('Delegation verification error:', error);
|
|
365
|
+
return c.json({
|
|
366
|
+
success: false,
|
|
367
|
+
error: 'INTERNAL_ERROR',
|
|
368
|
+
message: 'Internal server error'
|
|
369
|
+
}, 500);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
export default {
|
|
373
|
+
createDelegationRoute,
|
|
374
|
+
getDelegationRoute,
|
|
375
|
+
listDelegationsRoute,
|
|
376
|
+
revokeDelegationRoute,
|
|
377
|
+
verifyDelegationRoute,
|
|
378
|
+
};
|