@vess-id/ai-identity 0.0.1

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/dist/index.js ADDED
@@ -0,0 +1,4573 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ ACTION_REGISTRY: () => ACTION_REGISTRY,
35
+ AIdentityClient: () => AIdentityClient,
36
+ APIVCManager: () => APIVCManager,
37
+ AgentDIDManager: () => AgentDIDManager,
38
+ AgentManager: () => AgentManager,
39
+ AllowAllAbac: () => AllowAllAbac,
40
+ ConstraintEvaluator: () => ConstraintEvaluator,
41
+ DisclosureConfigManager: () => DisclosureConfigManager,
42
+ DummyCreds: () => DummyCreds,
43
+ DummyVpVerifier: () => DummyVpVerifier,
44
+ FilesystemKeyStorage: () => FilesystemKeyStorage,
45
+ KeyManager: () => KeyManager,
46
+ KeyRotationManager: () => KeyRotationManager,
47
+ MemoryKeyStorage: () => MemoryKeyStorage,
48
+ MemoryManager: () => MemoryManager,
49
+ MetricsManager: () => MetricsManager,
50
+ RevocationManager: () => RevocationManager,
51
+ SDJwtClient: () => SDJwtClient,
52
+ SimpleRebac: () => SimpleRebac,
53
+ ToolManager: () => ToolManager,
54
+ UserIdentityManager: () => UserIdentityManager,
55
+ VCManager: () => VCManager,
56
+ VPManager: () => VPManager,
57
+ checkPermissionWithVP: () => checkPermissionWithVP,
58
+ configure: () => configure,
59
+ createAjv: () => createAjv,
60
+ defaultConstraintEvaluator: () => defaultConstraintEvaluator,
61
+ evaluateConstraints: () => evaluateConstraints,
62
+ generateKeyPair: () => generateKeyPair,
63
+ generateNonce: () => generateNonce,
64
+ getClient: () => getClient,
65
+ getRequiredRelations: () => getRequiredRelations,
66
+ getRequiredScopes: () => getRequiredScopes,
67
+ indexActions: () => indexActions,
68
+ indexCapabilities: () => indexCapabilities,
69
+ loadActionRegistryFromFile: () => loadActionRegistryFromFile,
70
+ loadActionRegistryFromObject: () => loadActionRegistryFromObject,
71
+ planDelegationForVC: () => planDelegationForVC,
72
+ resolveActionsFromSelection: () => resolveActionsFromSelection,
73
+ signJWT: () => signJWT,
74
+ validateRegistryObject: () => validateRegistryObject,
75
+ verifyJWT: () => verifyJWT,
76
+ version: () => version
77
+ });
78
+ module.exports = __toCommonJS(index_exports);
79
+
80
+ // src/client.ts
81
+ var client_exports = {};
82
+ __export(client_exports, {
83
+ AIdentityClient: () => AIdentityClient,
84
+ configure: () => configure,
85
+ getClient: () => getClient
86
+ });
87
+
88
+ // src/config/index.ts
89
+ var globalConfig = {};
90
+ function configure(config) {
91
+ globalConfig = { ...globalConfig, ...config };
92
+ }
93
+ function getConfig() {
94
+ return globalConfig;
95
+ }
96
+ function getDidApiUrl(path3) {
97
+ const baseUrl = globalConfig.didApi?.baseUrl || process.env.DID_API_BASE_URL;
98
+ if (!baseUrl) {
99
+ throw new Error("DID API base URL not configured");
100
+ }
101
+ return `${baseUrl}${path3}`;
102
+ }
103
+ function getIssuerApiUrl(path3) {
104
+ const baseUrl = globalConfig.issuerApi?.baseUrl || process.env.ISSUER_API_BASE_URL;
105
+ if (!baseUrl) {
106
+ throw new Error("Issuer API base URL not configured");
107
+ }
108
+ return `${baseUrl}${path3}`;
109
+ }
110
+ function getVerifierApiUrl(path3) {
111
+ const baseUrl = globalConfig.verifierApi?.baseUrl || process.env.VERIFIER_API_BASE_URL;
112
+ if (!baseUrl) {
113
+ throw new Error("Verifier API base URL not configured");
114
+ }
115
+ return `${baseUrl}${path3}`;
116
+ }
117
+ function getApiHeaders(apiType) {
118
+ const headers = {
119
+ "Content-Type": "application/json"
120
+ };
121
+ let apiKey;
122
+ let bearerToken;
123
+ switch (apiType) {
124
+ case "did":
125
+ apiKey = globalConfig.didApi?.apiKey || process.env.DID_API_KEY;
126
+ bearerToken = globalConfig.didApi?.bearerToken;
127
+ break;
128
+ case "issuer":
129
+ apiKey = globalConfig.issuerApi?.apiKey || process.env.ISSUER_API_KEY;
130
+ bearerToken = globalConfig.issuerApi?.bearerToken;
131
+ break;
132
+ case "verifier":
133
+ apiKey = globalConfig.verifierApi?.apiKey || process.env.VERIFIER_API_KEY;
134
+ bearerToken = globalConfig.verifierApi?.bearerToken;
135
+ break;
136
+ }
137
+ if (apiKey) {
138
+ headers["x-api-key"] = apiKey;
139
+ }
140
+ if (bearerToken) {
141
+ headers["Authorization"] = `Bearer ${bearerToken}`;
142
+ }
143
+ return headers;
144
+ }
145
+
146
+ // src/did/key-manager.ts
147
+ var crypto = __toESM(require("crypto"));
148
+
149
+ // src/storage/filesystem-key-storage.ts
150
+ var fs = __toESM(require("fs/promises"));
151
+ var path = __toESM(require("path"));
152
+ var os = __toESM(require("os"));
153
+ var FilesystemKeyStorage = class {
154
+ keyStorePath;
155
+ constructor(config) {
156
+ this.keyStorePath = config?.options?.path || path.join(os.homedir(), ".vess", "keys");
157
+ }
158
+ async store(id, encryptedKey) {
159
+ await this.ensureKeyStoreExists();
160
+ const keyPath = this.getKeyPath(id);
161
+ await fs.writeFile(keyPath, encryptedKey, "utf-8");
162
+ }
163
+ async retrieve(id) {
164
+ const keyPath = this.getKeyPath(id);
165
+ try {
166
+ return await fs.readFile(keyPath, "utf-8");
167
+ } catch (error) {
168
+ if (error.code === "ENOENT") {
169
+ return null;
170
+ }
171
+ throw error;
172
+ }
173
+ }
174
+ async delete(id) {
175
+ const keyPath = this.getKeyPath(id);
176
+ try {
177
+ await fs.unlink(keyPath);
178
+ } catch (error) {
179
+ if (error.code !== "ENOENT") {
180
+ throw error;
181
+ }
182
+ }
183
+ }
184
+ async list() {
185
+ await this.ensureKeyStoreExists();
186
+ const files = await fs.readdir(this.keyStorePath);
187
+ return files.filter((f) => f.endsWith(".key")).map((f) => f.replace(".key", ""));
188
+ }
189
+ async isAvailable() {
190
+ try {
191
+ await this.ensureKeyStoreExists();
192
+ return true;
193
+ } catch {
194
+ return false;
195
+ }
196
+ }
197
+ async ensureKeyStoreExists() {
198
+ try {
199
+ await fs.access(this.keyStorePath);
200
+ } catch {
201
+ await fs.mkdir(this.keyStorePath, { recursive: true });
202
+ }
203
+ }
204
+ getKeyPath(id) {
205
+ return path.join(this.keyStorePath, `${id}.key`);
206
+ }
207
+ };
208
+
209
+ // src/storage/memory-key-storage.ts
210
+ var MemoryKeyStorage = class {
211
+ keys = /* @__PURE__ */ new Map();
212
+ async store(id, encryptedKey) {
213
+ this.keys.set(id, encryptedKey);
214
+ }
215
+ async retrieve(id) {
216
+ return this.keys.get(id) || null;
217
+ }
218
+ async delete(id) {
219
+ this.keys.delete(id);
220
+ }
221
+ async list() {
222
+ return Array.from(this.keys.keys());
223
+ }
224
+ async isAvailable() {
225
+ return true;
226
+ }
227
+ /**
228
+ * Clear all stored keys (for testing)
229
+ */
230
+ clear() {
231
+ this.keys.clear();
232
+ }
233
+ };
234
+
235
+ // src/did/key-manager.ts
236
+ var KeyManager = class {
237
+ encryptionKey;
238
+ storageProvider;
239
+ constructor(password, storageProvider) {
240
+ if (password) {
241
+ this.encryptionKey = crypto.scryptSync(password, "aidentity-salt", 32);
242
+ }
243
+ this.storageProvider = storageProvider || this.createDefaultStorageProvider();
244
+ }
245
+ createDefaultStorageProvider() {
246
+ const config = getConfig();
247
+ return new FilesystemKeyStorage({
248
+ type: "filesystem",
249
+ options: {
250
+ path: config.storage?.keyStorePath
251
+ }
252
+ });
253
+ }
254
+ async storeKey(did, privateKey) {
255
+ const keyData = JSON.stringify(privateKey);
256
+ const encrypted = this.encrypt(keyData);
257
+ await this.storageProvider.store(did, encrypted);
258
+ }
259
+ async getKey(did) {
260
+ const encrypted = await this.storageProvider.retrieve(did);
261
+ if (!encrypted) {
262
+ return null;
263
+ }
264
+ const decrypted = this.decrypt(encrypted);
265
+ return JSON.parse(decrypted);
266
+ }
267
+ async deleteKey(did) {
268
+ await this.storageProvider.delete(did);
269
+ }
270
+ async listDids() {
271
+ const keyIds = await this.storageProvider.list();
272
+ return keyIds.map((keyId) => this.didFromKeyId(keyId));
273
+ }
274
+ /**
275
+ * Check if storage is available
276
+ */
277
+ async isAvailable() {
278
+ return this.storageProvider.isAvailable();
279
+ }
280
+ // private getKeyId(did: string): string {
281
+ // // Use SHA256 hash to create short, storage-safe identifier
282
+ // return crypto.createHash('sha256').update(did).digest('hex').substring(0, 16)
283
+ // }
284
+ didFromKeyId(keyId) {
285
+ return keyId;
286
+ }
287
+ encrypt(data) {
288
+ if (!this.encryptionKey) {
289
+ return Buffer.from(data).toString("base64");
290
+ }
291
+ const iv = crypto.randomBytes(16);
292
+ const cipher = crypto.createCipheriv("aes-256-gcm", this.encryptionKey, iv);
293
+ let encrypted = cipher.update(data, "utf8", "base64");
294
+ encrypted += cipher.final("base64");
295
+ const authTag = cipher.getAuthTag();
296
+ const combined = Buffer.concat([iv, authTag, Buffer.from(encrypted, "base64")]);
297
+ return combined.toString("base64");
298
+ }
299
+ decrypt(encrypted) {
300
+ if (!this.encryptionKey) {
301
+ return Buffer.from(encrypted, "base64").toString("utf-8");
302
+ }
303
+ const combined = Buffer.from(encrypted, "base64");
304
+ const iv = combined.subarray(0, 16);
305
+ const authTag = combined.subarray(16, 32);
306
+ const encryptedData = combined.subarray(32);
307
+ const decipher = crypto.createDecipheriv("aes-256-gcm", this.encryptionKey, iv);
308
+ decipher.setAuthTag(authTag);
309
+ let decrypted = decipher.update(encryptedData, void 0, "utf8");
310
+ decrypted += decipher.final("utf8");
311
+ return decrypted;
312
+ }
313
+ };
314
+
315
+ // src/utils/sdjwt-client.ts
316
+ var import_sd_jwt_vc = require("@sd-jwt/sd-jwt-vc");
317
+ var import_crypto_nodejs = require("@sd-jwt/crypto-nodejs");
318
+
319
+ // src/utils/crypto.ts
320
+ var jose = __toESM(require("jose"));
321
+ var import_uuid = require("uuid");
322
+ var import_node_crypto = require("crypto");
323
+ async function generateKeyPair() {
324
+ const keyPair = await import_node_crypto.subtle.generateKey(
325
+ {
326
+ name: "ECDSA",
327
+ namedCurve: "P-256"
328
+ },
329
+ true,
330
+ // extractable
331
+ ["sign", "verify"]
332
+ );
333
+ const publicJwk = await import_node_crypto.subtle.exportKey("jwk", keyPair.publicKey);
334
+ const privateJwk = await import_node_crypto.subtle.exportKey("jwk", keyPair.privateKey);
335
+ const kid = (0, import_uuid.v4)();
336
+ publicJwk.kid = kid;
337
+ privateJwk.kid = kid;
338
+ publicJwk.alg = "ES256";
339
+ privateJwk.alg = "ES256";
340
+ return {
341
+ publicKey: publicJwk,
342
+ privateKey: privateJwk
343
+ };
344
+ }
345
+ async function signJWT(payload, privateKey, options) {
346
+ const alg = privateKey.alg || "ES256";
347
+ const key = await jose.importJWK(privateKey, alg);
348
+ const jwt = new jose.SignJWT(payload).setProtectedHeader({ alg, kid: privateKey.kid }).setIssuedAt().setJti(options?.jti ?? (0, import_uuid.v4)());
349
+ if (options?.issuer) jwt.setIssuer(options.issuer);
350
+ if (options?.audience) jwt.setAudience(options.audience);
351
+ if (options?.expiresIn) jwt.setExpirationTime(options.expiresIn);
352
+ if (options?.notBefore) jwt.setNotBefore(options.notBefore);
353
+ if (options?.subject) jwt.setSubject(options.subject);
354
+ return await jwt.sign(key);
355
+ }
356
+ async function verifyJWT(jwt, publicKey, options) {
357
+ const alg = publicKey.alg || "ES256";
358
+ const key = await jose.importJWK(publicKey, alg);
359
+ const verifyOptions = {};
360
+ if (options?.issuer) verifyOptions.issuer = options.issuer;
361
+ if (options?.audience) verifyOptions.audience = options.audience;
362
+ const { payload } = await jose.jwtVerify(jwt, key, verifyOptions);
363
+ return payload;
364
+ }
365
+ function generateNonce() {
366
+ return (0, import_uuid.v4)();
367
+ }
368
+ async function getSigner(privateKey) {
369
+ try {
370
+ const key = await import_node_crypto.subtle.importKey(
371
+ "jwk",
372
+ privateKey,
373
+ {
374
+ name: "ECDSA",
375
+ namedCurve: "P-256"
376
+ },
377
+ true,
378
+ ["sign"]
379
+ );
380
+ return async (data) => {
381
+ const encoder = new TextEncoder();
382
+ const signature = await import_node_crypto.subtle.sign(
383
+ {
384
+ name: "ECDSA",
385
+ hash: { name: "SHA-256" }
386
+ },
387
+ key,
388
+ encoder.encode(data)
389
+ );
390
+ const result = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
391
+ return result;
392
+ };
393
+ } catch (error) {
394
+ console.error("Error in getSigner:", error instanceof Error ? error.message : "Unknown error");
395
+ console.error("Key algorithm:", privateKey?.alg || "unknown");
396
+ console.error("Key type:", privateKey?.kty || "unknown");
397
+ throw error;
398
+ }
399
+ }
400
+ async function getVerifier(publicKey) {
401
+ const key = await import_node_crypto.subtle.importKey(
402
+ "jwk",
403
+ publicKey,
404
+ {
405
+ name: "ECDSA",
406
+ namedCurve: "P-256"
407
+ },
408
+ true,
409
+ ["verify"]
410
+ );
411
+ return async (data, signatureBase64url) => {
412
+ const encoder = new TextEncoder();
413
+ const signature = Uint8Array.from(
414
+ atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
415
+ (c) => c.charCodeAt(0)
416
+ );
417
+ const isValid = await import_node_crypto.subtle.verify(
418
+ {
419
+ name: "ECDSA",
420
+ hash: { name: "SHA-256" }
421
+ },
422
+ key,
423
+ signature,
424
+ encoder.encode(data)
425
+ );
426
+ return isValid;
427
+ };
428
+ }
429
+
430
+ // src/utils/sdjwt-client.ts
431
+ var SDJwtClient = class {
432
+ static instances = /* @__PURE__ */ new Map();
433
+ static keyManager;
434
+ static signerCache = /* @__PURE__ */ new Map();
435
+ static verifierCache = /* @__PURE__ */ new Map();
436
+ constructor() {
437
+ }
438
+ /**
439
+ * Initialize with KeyManager for DID-based key management
440
+ */
441
+ static setKeyManager(keyManager) {
442
+ this.keyManager = keyManager;
443
+ }
444
+ /**
445
+ * Get SDJwtVcInstance for issuer role (VC issuance)
446
+ */
447
+ static async getIssuerInstance(issuerDid) {
448
+ const cacheKey = `${issuerDid}:issuer`;
449
+ if (!this.instances.has(cacheKey)) {
450
+ const instance = await this.createInstance(issuerDid, "issuer");
451
+ this.instances.set(cacheKey, instance);
452
+ }
453
+ return this.instances.get(cacheKey);
454
+ }
455
+ /**
456
+ * Get SDJwtVcInstance for holder role (VP presentation)
457
+ */
458
+ static async getHolderInstance(holderDid) {
459
+ const cacheKey = `${holderDid}:holder`;
460
+ if (!this.instances.has(cacheKey)) {
461
+ const instance = await this.createInstance(holderDid, "holder");
462
+ this.instances.set(cacheKey, instance);
463
+ }
464
+ return this.instances.get(cacheKey);
465
+ }
466
+ /**
467
+ * Get SDJwtVcInstance with specified role (backward compatibility)
468
+ */
469
+ static async getSDJwtInstance(did, options) {
470
+ const role = options?.role || "issuer";
471
+ return role === "holder" ? this.getHolderInstance(did) : this.getIssuerInstance(did);
472
+ }
473
+ /**
474
+ * Create a new SDJwtVcInstance with DID-based keys and role
475
+ */
476
+ static async createInstance(did, role) {
477
+ if (!this.keyManager) {
478
+ this.keyManager = new KeyManager();
479
+ }
480
+ const privateKey = await this.keyManager.getKey(did);
481
+ if (!privateKey) {
482
+ throw new Error(`Private key not found for ${role}: ${did}`);
483
+ }
484
+ try {
485
+ const signerCacheKey = `signer:${did}`;
486
+ const verifierCacheKey = `verifier:${did}`;
487
+ let signer = this.signerCache.get(signerCacheKey);
488
+ let verifier = this.verifierCache.get(verifierCacheKey);
489
+ if (!signer) {
490
+ signer = await getSigner(privateKey);
491
+ this.signerCache.set(signerCacheKey, signer);
492
+ }
493
+ if (!verifier) {
494
+ const { d, key_ops, ...publicKey } = privateKey;
495
+ const publicKeyForVerifier = {
496
+ ...publicKey,
497
+ key_ops: ["verify"]
498
+ // Set correct key operations for verifier
499
+ };
500
+ verifier = await getVerifier(publicKeyForVerifier);
501
+ this.verifierCache.set(verifierCacheKey, verifier);
502
+ }
503
+ const config = {
504
+ signer,
505
+ verifier,
506
+ signAlg: import_crypto_nodejs.ES256.alg,
507
+ hasher: import_crypto_nodejs.digest,
508
+ hashAlg: "sha-256",
509
+ saltGenerator: import_crypto_nodejs.generateSalt
510
+ };
511
+ if (role === "holder") {
512
+ config.kbSigner = signer;
513
+ config.kbSignAlg = import_crypto_nodejs.ES256.alg;
514
+ }
515
+ return new import_sd_jwt_vc.SDJwtVcInstance(config);
516
+ } catch (error) {
517
+ console.error("\u274C Error creating SDJwtVcInstance:", error);
518
+ throw error;
519
+ }
520
+ }
521
+ /**
522
+ * Create disclosure frame for selective disclosure
523
+ */
524
+ static createDisclosureFrame(claims, selectivelyDisclosable = []) {
525
+ const frame = {};
526
+ const existingDisclosableFields = selectivelyDisclosable.filter(
527
+ (field) => claims.hasOwnProperty(field)
528
+ );
529
+ if (existingDisclosableFields.length > 0) {
530
+ frame._sd = existingDisclosableFields;
531
+ frame._sd_decoy = Math.max(0, Math.floor(existingDisclosableFields.length * 0.1));
532
+ }
533
+ for (const [key, value] of Object.entries(claims)) {
534
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
535
+ const nestedKeys = Object.keys(value);
536
+ const nestedFrame = this.createDisclosureFrame(
537
+ value,
538
+ nestedKeys
539
+ // Make all nested fields disclosable
540
+ );
541
+ frame[key] = nestedFrame;
542
+ }
543
+ }
544
+ return frame;
545
+ }
546
+ /**
547
+ * Issue an SD-JWT with selective disclosure
548
+ */
549
+ static async issueSDJWT(payload, _privateKey, selectiveDisclosureFields = []) {
550
+ const issuerDid = payload.iss || "unknown";
551
+ const sdjwtInstance = await this.getIssuerInstance(issuerDid);
552
+ const vcPayload = {
553
+ vct: "IdentityCredential",
554
+ // Default VC type
555
+ ...payload
556
+ };
557
+ const disclosureFrame = this.createDisclosureFrame(vcPayload, selectiveDisclosureFields);
558
+ return await sdjwtInstance.issue(vcPayload, disclosureFrame);
559
+ }
560
+ /**
561
+ * Verify an SD-JWT
562
+ */
563
+ static async verifySDJWT(credential) {
564
+ try {
565
+ const parts = credential.split("~");
566
+ if (parts.length === 0) {
567
+ return { valid: false, error: "Invalid SD-JWT format" };
568
+ }
569
+ const jwt = parts[0];
570
+ const jwtParts = jwt.split(".");
571
+ if (jwtParts.length !== 3) {
572
+ return { valid: false, error: "Invalid JWT format in SD-JWT" };
573
+ }
574
+ const payload = JSON.parse(Buffer.from(jwtParts[1], "base64url").toString());
575
+ const issuerDid = payload.iss;
576
+ if (!issuerDid) {
577
+ return { valid: false, error: "Issuer DID not found in SD-JWT" };
578
+ }
579
+ const sdjwtInstance = await this.getIssuerInstance(issuerDid);
580
+ const verificationResult = await sdjwtInstance.verify(credential);
581
+ const claims = await sdjwtInstance.getClaims(credential);
582
+ return {
583
+ valid: true,
584
+ payload: {
585
+ ...verificationResult.payload,
586
+ claims
587
+ }
588
+ };
589
+ } catch (error) {
590
+ return {
591
+ valid: false,
592
+ error: error.message
593
+ };
594
+ }
595
+ }
596
+ /**
597
+ * Legacy methods for backward compatibility
598
+ */
599
+ static async createSignerVerifier() {
600
+ const { privateKey, publicKey } = await this.generateKeyPair();
601
+ return {
602
+ signer: await getSigner(privateKey),
603
+ verifier: await getVerifier(publicKey)
604
+ };
605
+ }
606
+ static async generateKeyPair() {
607
+ return await generateKeyPair();
608
+ }
609
+ /**
610
+ * Clear caches for optimization
611
+ */
612
+ static clearCaches() {
613
+ this.instances.clear();
614
+ this.signerCache.clear();
615
+ this.verifierCache.clear();
616
+ }
617
+ /**
618
+ * Clear cache for specific issuer
619
+ */
620
+ static clearIssuerCache(issuerDid) {
621
+ this.instances.delete(issuerDid);
622
+ this.signerCache.delete(`signer:${issuerDid}`);
623
+ this.verifierCache.delete(`verifier:${issuerDid}`);
624
+ }
625
+ /**
626
+ * Get cache statistics
627
+ */
628
+ static getCacheStats() {
629
+ return {
630
+ instanceCount: this.instances.size,
631
+ signerCount: this.signerCache.size,
632
+ verifierCount: this.verifierCache.size
633
+ };
634
+ }
635
+ };
636
+
637
+ // src/agent/agent-did-manager.ts
638
+ var AgentDIDManager = class {
639
+ keyManager;
640
+ agentDIDMap = /* @__PURE__ */ new Map();
641
+ // agentId -> DID mapping
642
+ constructor(keyManager) {
643
+ this.keyManager = keyManager || new KeyManager();
644
+ }
645
+ /**
646
+ * Generate a new DID for an AI Agent
647
+ */
648
+ async generateAgentDID(agentId) {
649
+ const keyPair = await SDJwtClient.generateKeyPair();
650
+ const did = this.createDidJwk(keyPair.publicKey);
651
+ await this.keyManager.storeKey(did, keyPair.privateKey);
652
+ this.agentDIDMap.set(agentId, did);
653
+ await this.saveAgentDIDMapping(agentId, did);
654
+ return did;
655
+ }
656
+ /**
657
+ * Get DID for a specific agent
658
+ */
659
+ async getAgentDID(agentId) {
660
+ if (this.agentDIDMap.has(agentId)) {
661
+ return this.agentDIDMap.get(agentId);
662
+ }
663
+ const did = await this.loadAgentDIDMapping(agentId);
664
+ if (did) {
665
+ this.agentDIDMap.set(agentId, did);
666
+ return did;
667
+ }
668
+ throw new Error(`No DID found for agent: ${agentId}`);
669
+ }
670
+ /**
671
+ * Check if agent has a DID
672
+ */
673
+ async hasAgentDID(agentId) {
674
+ try {
675
+ await this.getAgentDID(agentId);
676
+ return true;
677
+ } catch {
678
+ return false;
679
+ }
680
+ }
681
+ /**
682
+ * Get agent's key pair
683
+ */
684
+ async getAgentKeyPair(agentId) {
685
+ const did = await this.getAgentDID(agentId);
686
+ const privateKey = await this.keyManager.getKey(did);
687
+ if (!privateKey) {
688
+ throw new Error(`Private key not found for agent: ${agentId}`);
689
+ }
690
+ return {
691
+ privateKey,
692
+ publicKey: this.extractPublicKey(privateKey)
693
+ };
694
+ }
695
+ /**
696
+ * Delete agent DID and associated keys
697
+ */
698
+ async deleteAgentDID(agentId) {
699
+ try {
700
+ const did = await this.getAgentDID(agentId);
701
+ await this.keyManager.deleteKey(did);
702
+ this.agentDIDMap.delete(agentId);
703
+ await this.deleteAgentDIDMapping(agentId);
704
+ } catch (error) {
705
+ throw new Error(`Failed to delete agent DID: ${error}`);
706
+ }
707
+ }
708
+ /**
709
+ * List all agent DIDs
710
+ */
711
+ async listAgentDIDs() {
712
+ const fs3 = await import("fs/promises");
713
+ const path3 = await import("path");
714
+ const os2 = await import("os");
715
+ const mappingDir = path3.join(os2.homedir(), ".vess", "agent-dids");
716
+ try {
717
+ const files = await fs3.readdir(mappingDir);
718
+ const results = [];
719
+ for (const file of files) {
720
+ if (file.endsWith(".did")) {
721
+ const agentId = file.replace(".did", "");
722
+ try {
723
+ const did = await this.getAgentDID(agentId);
724
+ results.push({ agentId, did });
725
+ } catch {
726
+ }
727
+ }
728
+ }
729
+ return results;
730
+ } catch {
731
+ return [];
732
+ }
733
+ }
734
+ /**
735
+ * Create did:jwk from public key
736
+ */
737
+ createDidJwk(publicKey) {
738
+ const publicJwk = {
739
+ kty: publicKey.kty,
740
+ crv: publicKey.crv,
741
+ x: publicKey.x,
742
+ y: publicKey.y,
743
+ use: publicKey.use,
744
+ alg: publicKey.alg
745
+ };
746
+ const encoded = Buffer.from(JSON.stringify(publicJwk)).toString("base64url");
747
+ return `did:jwk:${encoded}`;
748
+ }
749
+ /**
750
+ * Extract public key from private key
751
+ */
752
+ extractPublicKey(privateKey) {
753
+ const { d, key_ops, ...publicKey } = privateKey;
754
+ return {
755
+ ...publicKey
756
+ // Remove key_ops for public key
757
+ };
758
+ }
759
+ /**
760
+ * Save agent ID -> DID mapping to persistent storage
761
+ */
762
+ async saveAgentDIDMapping(agentId, did) {
763
+ const fs3 = await import("fs/promises");
764
+ const path3 = await import("path");
765
+ const os2 = await import("os");
766
+ const mappingDir = path3.join(os2.homedir(), ".vess", "agent-dids");
767
+ await fs3.mkdir(mappingDir, { recursive: true });
768
+ const mappingFile = path3.join(mappingDir, `${agentId}.did`);
769
+ await fs3.writeFile(mappingFile, did, "utf-8");
770
+ }
771
+ /**
772
+ * Load agent ID -> DID mapping from persistent storage
773
+ */
774
+ async loadAgentDIDMapping(agentId) {
775
+ const fs3 = await import("fs/promises");
776
+ const path3 = await import("path");
777
+ const os2 = await import("os");
778
+ const mappingFile = path3.join(os2.homedir(), ".vess", "agent-dids", `${agentId}.did`);
779
+ try {
780
+ return await fs3.readFile(mappingFile, "utf-8");
781
+ } catch {
782
+ return null;
783
+ }
784
+ }
785
+ /**
786
+ * Delete agent ID -> DID mapping from persistent storage
787
+ */
788
+ async deleteAgentDIDMapping(agentId) {
789
+ const fs3 = await import("fs/promises");
790
+ const path3 = await import("path");
791
+ const os2 = await import("os");
792
+ const mappingFile = path3.join(os2.homedir(), ".vess", "agent-dids", `${agentId}.did`);
793
+ try {
794
+ await fs3.unlink(mappingFile);
795
+ } catch {
796
+ }
797
+ }
798
+ };
799
+
800
+ // src/did/agent.ts
801
+ var import_uuid2 = require("uuid");
802
+ var AgentManager = class {
803
+ keyManager;
804
+ agentDIDManager;
805
+ constructor(keyManager) {
806
+ this.keyManager = keyManager || new KeyManager();
807
+ this.agentDIDManager = new AgentDIDManager(this.keyManager);
808
+ }
809
+ /**
810
+ * Create a new AI agent with unique ID and DID
811
+ */
812
+ async create(metadata) {
813
+ const agentId = (0, import_uuid2.v4)();
814
+ const agentDid = await this.agentDIDManager.generateAgentDID(agentId);
815
+ const didDocument = this.resolveDidJwkLocally(agentDid);
816
+ const agent = {
817
+ id: agentId,
818
+ did: agentDid,
819
+ didDocument,
820
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
821
+ metadata
822
+ };
823
+ try {
824
+ await this.registerDid(agent);
825
+ } catch (error) {
826
+ console.warn("Failed to register DID with API:", error);
827
+ }
828
+ return agent;
829
+ }
830
+ /**
831
+ * Get agent DID by agent ID
832
+ */
833
+ async getAgentDID(agentId) {
834
+ return await this.agentDIDManager.getAgentDID(agentId);
835
+ }
836
+ /**
837
+ * Get agent by ID
838
+ */
839
+ async getAgent(agentId) {
840
+ const agentDid = await this.agentDIDManager.getAgentDID(agentId);
841
+ const didDocument = await this.resolve(agentDid);
842
+ return {
843
+ id: agentId,
844
+ did: agentDid,
845
+ didDocument,
846
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
847
+ // TODO: Store actual creation time
848
+ };
849
+ }
850
+ /**
851
+ * Delete an agent and its DID
852
+ */
853
+ async deleteAgent(agentId) {
854
+ await this.agentDIDManager.deleteAgentDID(agentId);
855
+ }
856
+ /**
857
+ * Resolve a DID to get DID Document
858
+ */
859
+ async resolve(did) {
860
+ if (did.startsWith("did:jwk:")) {
861
+ return this.resolveDidJwkLocally(did);
862
+ }
863
+ try {
864
+ const response = await fetch(getDidApiUrl(`/api/v1/did/${encodeURIComponent(did)}`), {
865
+ headers: getApiHeaders("did")
866
+ });
867
+ if (!response.ok) {
868
+ throw new Error(`Failed to resolve DID: ${response.statusText}`);
869
+ }
870
+ const data = await response.json();
871
+ return data.didDocument;
872
+ } catch (error) {
873
+ throw new Error(`Failed to resolve DID: ${error}`);
874
+ }
875
+ }
876
+ /**
877
+ * Export agent with private key (for backup)
878
+ */
879
+ async export(did) {
880
+ const didDocument = await this.resolve(did);
881
+ const privateKey = await this.keyManager.getKey(did);
882
+ if (!privateKey) {
883
+ throw new Error(`Private key not found for DID: ${did}`);
884
+ }
885
+ const agent = {
886
+ did,
887
+ didDocument,
888
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
889
+ };
890
+ return { agent, privateKey };
891
+ }
892
+ /**
893
+ * Import agent from backup
894
+ */
895
+ async import(agent, privateKey) {
896
+ await this.keyManager.storeKey(agent.did, privateKey);
897
+ }
898
+ /**
899
+ * List all locally stored agents
900
+ */
901
+ async list() {
902
+ const agentDIDs = await this.agentDIDManager.listAgentDIDs();
903
+ const agents = [];
904
+ for (const { agentId, did } of agentDIDs) {
905
+ try {
906
+ const didDocument = await this.resolve(did);
907
+ agents.push({
908
+ id: agentId,
909
+ did,
910
+ didDocument,
911
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
912
+ // TODO: Store actual creation time
913
+ });
914
+ } catch (error) {
915
+ console.warn(`Failed to resolve Agent DID ${did}:`, error);
916
+ }
917
+ }
918
+ return agents;
919
+ }
920
+ createDidDocument(did, publicKey) {
921
+ const verificationMethodId = `${did}#0`;
922
+ return {
923
+ "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1"],
924
+ id: did,
925
+ verificationMethod: [
926
+ {
927
+ id: verificationMethodId,
928
+ type: "JsonWebKey2020",
929
+ controller: did,
930
+ publicKeyJwk: publicKey
931
+ }
932
+ ],
933
+ authentication: [verificationMethodId],
934
+ assertionMethod: [verificationMethodId],
935
+ capabilityInvocation: [verificationMethodId],
936
+ capabilityDelegation: [verificationMethodId]
937
+ };
938
+ }
939
+ resolveDidJwkLocally(did) {
940
+ const encoded = did.replace("did:jwk:", "");
941
+ const publicJwk = JSON.parse(Buffer.from(encoded, "base64url").toString());
942
+ return this.createDidDocument(did, publicJwk);
943
+ }
944
+ async registerDid(_agent) {
945
+ }
946
+ };
947
+
948
+ // src/identity/user-identity-manager.ts
949
+ var UserIdentityManager = class {
950
+ keyManager;
951
+ currentUserDID = null;
952
+ constructor(keyManager) {
953
+ this.keyManager = keyManager || new KeyManager();
954
+ }
955
+ /**
956
+ * Get or create current user DID
957
+ * This represents the user who will be the issuer of VCs
958
+ */
959
+ async getCurrentUserDID() {
960
+ if (this.currentUserDID) {
961
+ return this.currentUserDID;
962
+ }
963
+ const existingDID = await this.loadUserDID();
964
+ if (existingDID) {
965
+ this.currentUserDID = existingDID;
966
+ return existingDID;
967
+ }
968
+ return await this.createUserDID();
969
+ }
970
+ /**
971
+ * Create a new user DID (for issuing VCs)
972
+ */
973
+ async createUserDID() {
974
+ const keyPair = await SDJwtClient.generateKeyPair();
975
+ const did = this.createDidJwk(keyPair.publicKey);
976
+ await this.keyManager.storeKey(did, keyPair.privateKey);
977
+ await this.saveUserDID(did);
978
+ this.currentUserDID = did;
979
+ return did;
980
+ }
981
+ /**
982
+ * Get user's key pair
983
+ */
984
+ async getUserKeyPair() {
985
+ const did = await this.getCurrentUserDID();
986
+ const privateKey = await this.keyManager.getKey(did);
987
+ if (!privateKey) {
988
+ throw new Error("User private key not found");
989
+ }
990
+ return {
991
+ privateKey,
992
+ publicKey: this.extractPublicKey(privateKey)
993
+ };
994
+ }
995
+ /**
996
+ * Resolve user DID to DID Document
997
+ */
998
+ async resolveUserDID(did) {
999
+ const userDid = did || await this.getCurrentUserDID();
1000
+ if (!userDid.startsWith("did:jwk:")) {
1001
+ throw new Error("Only did:jwk supported for user identity");
1002
+ }
1003
+ return this.resolveDidJwkLocally(userDid);
1004
+ }
1005
+ /**
1006
+ * Export user identity for backup
1007
+ */
1008
+ async exportUserIdentity() {
1009
+ const did = await this.getCurrentUserDID();
1010
+ const privateKey = await this.keyManager.getKey(did);
1011
+ const didDocument = await this.resolveUserDID(did);
1012
+ if (!privateKey) {
1013
+ throw new Error("User private key not found");
1014
+ }
1015
+ return { did, privateKey, didDocument };
1016
+ }
1017
+ /**
1018
+ * Import user identity from backup
1019
+ */
1020
+ async importUserIdentity(backup) {
1021
+ await this.keyManager.storeKey(backup.did, backup.privateKey);
1022
+ await this.saveUserDID(backup.did);
1023
+ this.currentUserDID = backup.did;
1024
+ }
1025
+ /**
1026
+ * Reset user identity (create new DID)
1027
+ */
1028
+ async resetUserIdentity() {
1029
+ this.currentUserDID = null;
1030
+ await this.clearUserDID();
1031
+ return await this.createUserDID();
1032
+ }
1033
+ /**
1034
+ * Create did:jwk from public key
1035
+ */
1036
+ createDidJwk(publicKey) {
1037
+ const publicJwk = {
1038
+ kty: publicKey.kty,
1039
+ crv: publicKey.crv,
1040
+ x: publicKey.x,
1041
+ y: publicKey.y,
1042
+ use: publicKey.use,
1043
+ alg: publicKey.alg
1044
+ };
1045
+ const encoded = Buffer.from(JSON.stringify(publicJwk)).toString("base64url");
1046
+ return `did:jwk:${encoded}`;
1047
+ }
1048
+ /**
1049
+ * Extract public key from private key
1050
+ */
1051
+ extractPublicKey(privateKey) {
1052
+ const { d, key_ops, ...publicKey } = privateKey;
1053
+ return publicKey;
1054
+ }
1055
+ /**
1056
+ * Resolve did:jwk locally
1057
+ */
1058
+ resolveDidJwkLocally(did) {
1059
+ const encoded = did.replace("did:jwk:", "");
1060
+ const publicJwk = JSON.parse(Buffer.from(encoded, "base64url").toString());
1061
+ return this.createDidDocument(did, publicJwk);
1062
+ }
1063
+ /**
1064
+ * Create DID Document
1065
+ */
1066
+ createDidDocument(did, publicKey) {
1067
+ const verificationMethodId = `${did}#0`;
1068
+ return {
1069
+ "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1"],
1070
+ id: did,
1071
+ verificationMethod: [
1072
+ {
1073
+ id: verificationMethodId,
1074
+ type: "JsonWebKey2020",
1075
+ controller: did,
1076
+ publicKeyJwk: publicKey
1077
+ }
1078
+ ],
1079
+ authentication: [verificationMethodId],
1080
+ assertionMethod: [verificationMethodId],
1081
+ capabilityInvocation: [verificationMethodId],
1082
+ capabilityDelegation: [verificationMethodId]
1083
+ };
1084
+ }
1085
+ /**
1086
+ * Save current user DID to persistent storage
1087
+ */
1088
+ async saveUserDID(did) {
1089
+ const fs3 = await import("fs/promises");
1090
+ const path3 = await import("path");
1091
+ const os2 = await import("os");
1092
+ const configDir = path3.join(os2.homedir(), ".vess");
1093
+ await fs3.mkdir(configDir, { recursive: true });
1094
+ const userDIDFile = path3.join(configDir, "user-did.txt");
1095
+ await fs3.writeFile(userDIDFile, did, "utf-8");
1096
+ }
1097
+ /**
1098
+ * Load current user DID from persistent storage
1099
+ */
1100
+ async loadUserDID() {
1101
+ const fs3 = await import("fs/promises");
1102
+ const path3 = await import("path");
1103
+ const os2 = await import("os");
1104
+ const userDIDFile = path3.join(os2.homedir(), ".vess", "user-did.txt");
1105
+ try {
1106
+ return await fs3.readFile(userDIDFile, "utf-8");
1107
+ } catch {
1108
+ return null;
1109
+ }
1110
+ }
1111
+ /**
1112
+ * Clear saved user DID
1113
+ */
1114
+ async clearUserDID() {
1115
+ const fs3 = await import("fs/promises");
1116
+ const path3 = await import("path");
1117
+ const os2 = await import("os");
1118
+ const userDIDFile = path3.join(os2.homedir(), ".vess", "user-did.txt");
1119
+ try {
1120
+ await fs3.unlink(userDIDFile);
1121
+ } catch {
1122
+ }
1123
+ }
1124
+ };
1125
+
1126
+ // src/vc/vc-manager.ts
1127
+ var VCManager = class {
1128
+ keyManager;
1129
+ templates = /* @__PURE__ */ new Map();
1130
+ agentManager;
1131
+ userIdentityManager;
1132
+ constructor(keyManager, agentManager, userIdentityManager) {
1133
+ this.keyManager = keyManager || new KeyManager();
1134
+ this.agentManager = agentManager || new AgentManager(this.keyManager);
1135
+ this.userIdentityManager = userIdentityManager || new UserIdentityManager(this.keyManager);
1136
+ this.registerDefaultTemplates();
1137
+ }
1138
+ /**
1139
+ * Get fields that should be selectively disclosable based on VC type
1140
+ */
1141
+ getSelectivelyDisclosableFields(template) {
1142
+ switch (template) {
1143
+ case "ToolPermissionVC":
1144
+ return ["tool", "action", "scope", "conditions"];
1145
+ case "DataAccessVC":
1146
+ return ["resource", "actions", "scope", "conditions"];
1147
+ case "OrganizationVC":
1148
+ return ["organizationId", "employeeId", "department", "role", "permissions"];
1149
+ default:
1150
+ return [];
1151
+ }
1152
+ }
1153
+ /**
1154
+ * Issue a Verifiable Credential as SD-JWT VC
1155
+ * Enhanced to support User/Agent DID separation
1156
+ */
1157
+ async issue(template, claims, options) {
1158
+ const vcTemplate = this.templates.get(template);
1159
+ if (!vcTemplate) {
1160
+ throw new Error(`Unknown VC template: ${template}`);
1161
+ }
1162
+ const issuerDid = options.issuerDid || await this.userIdentityManager.getCurrentUserDID();
1163
+ let subjectDid;
1164
+ if (options.agentId) {
1165
+ subjectDid = await this.agentManager.getAgentDID(options.agentId);
1166
+ } else if (options.subjectDid) {
1167
+ subjectDid = options.subjectDid;
1168
+ } else {
1169
+ subjectDid = issuerDid;
1170
+ }
1171
+ const now = /* @__PURE__ */ new Date();
1172
+ const iat = Math.floor(now.getTime() / 1e3);
1173
+ const credentialSubject = {
1174
+ id: subjectDid,
1175
+ ...claims
1176
+ };
1177
+ if (vcTemplate.defaults) {
1178
+ Object.assign(credentialSubject, vcTemplate.defaults);
1179
+ }
1180
+ const vcPayload = {
1181
+ // SD-JWT VC specific fields
1182
+ vct: vcTemplate.type,
1183
+ iss: issuerDid,
1184
+ iat,
1185
+ cnf: {
1186
+ // Confirmation method - binding to subject's key
1187
+ jwk: await this.getSubjectPublicKey(subjectDid)
1188
+ },
1189
+ // Standard VC fields
1190
+ credentialSubject
1191
+ };
1192
+ if (options.expiresIn) {
1193
+ const expDate = this.calculateExpirationDate(options.expiresIn);
1194
+ vcPayload.exp = Math.floor(expDate.getTime() / 1e3);
1195
+ }
1196
+ const vc = {
1197
+ ...vcPayload,
1198
+ "@context": ["https://www.w3.org/ns/credentials/v2"],
1199
+ issuer: issuerDid,
1200
+ validFrom: now.toISOString()
1201
+ };
1202
+ if (vcTemplate.validate && !vcTemplate.validate(vc)) {
1203
+ throw new Error("VC validation failed");
1204
+ }
1205
+ SDJwtClient.setKeyManager(this.keyManager);
1206
+ const sdjwtInstance = await SDJwtClient.getIssuerInstance(issuerDid);
1207
+ const selectivelyDisclosableFields = this.getSelectivelyDisclosableFields(template);
1208
+ const credentialSubjectFrame = SDJwtClient.createDisclosureFrame(
1209
+ credentialSubject,
1210
+ selectivelyDisclosableFields
1211
+ );
1212
+ const disclosureFrame = {
1213
+ credentialSubject: credentialSubjectFrame
1214
+ };
1215
+ const sdjwtVc = await sdjwtInstance.issue(
1216
+ vcPayload,
1217
+ disclosureFrame
1218
+ );
1219
+ return sdjwtVc;
1220
+ }
1221
+ /**
1222
+ * Get subject's public key for cnf claim
1223
+ */
1224
+ async getSubjectPublicKey(subjectDid) {
1225
+ if (!subjectDid.startsWith("did:jwk:")) {
1226
+ throw new Error(`Unsupported DID method. Expected did:jwk, got: ${subjectDid}`);
1227
+ }
1228
+ try {
1229
+ const jwkEncoded = subjectDid.replace("did:jwk:", "");
1230
+ const jwkJson = Buffer.from(jwkEncoded, "base64url").toString("utf-8");
1231
+ const jwk = JSON.parse(jwkJson);
1232
+ const { d, key_ops, ...publicJwk } = jwk;
1233
+ const publicKeyForCnf = {
1234
+ ...publicJwk
1235
+ // Remove key_ops entirely for cnf claim as it's not needed there
1236
+ };
1237
+ return publicKeyForCnf;
1238
+ } catch (error) {
1239
+ throw new Error(
1240
+ `Failed to extract JWK from did:jwk: ${error instanceof Error ? error.message : "Unknown error"}`
1241
+ );
1242
+ }
1243
+ }
1244
+ /**
1245
+ * Issue using existing Issuer API (OID4VCI)
1246
+ */
1247
+ async issueViaAPI(credentialType, claims, options) {
1248
+ const offerResponse = await fetch(getIssuerApiUrl("/api/v1/credential/offer"), {
1249
+ method: "POST",
1250
+ headers: getApiHeaders("issuer"),
1251
+ body: JSON.stringify({
1252
+ credentialType,
1253
+ claims,
1254
+ subjectDid: options.subjectDid
1255
+ })
1256
+ });
1257
+ if (!offerResponse.ok) {
1258
+ throw new Error(`Failed to get credential offer: ${offerResponse.statusText}`);
1259
+ }
1260
+ const offer = await offerResponse.json();
1261
+ const acquireResponse = await fetch(getIssuerApiUrl("/api/v1/credential/acquire"), {
1262
+ method: "POST",
1263
+ headers: getApiHeaders("issuer"),
1264
+ body: JSON.stringify({
1265
+ offerId: offer.id,
1266
+ holderDid: options.subjectDid
1267
+ })
1268
+ });
1269
+ if (!acquireResponse.ok) {
1270
+ throw new Error(`Failed to acquire credential: ${acquireResponse.statusText}`);
1271
+ }
1272
+ const credential = await acquireResponse.json();
1273
+ return credential.jwt;
1274
+ }
1275
+ /**
1276
+ * Verify a SD-JWT VC
1277
+ */
1278
+ async verify(sdjwtVc, options) {
1279
+ const parts = sdjwtVc.split("~");
1280
+ const jwt = parts[0];
1281
+ const jwtParts = jwt.split(".");
1282
+ const payload = JSON.parse(Buffer.from(jwtParts[1], "base64url").toString());
1283
+ const issuerDid = payload.iss;
1284
+ if (!issuerDid) {
1285
+ throw new Error("Issuer DID not found in SD-JWT VC");
1286
+ }
1287
+ if (options?.expectedIssuer && issuerDid !== options.expectedIssuer) {
1288
+ throw new Error(`Issuer mismatch: expected ${options.expectedIssuer}, got ${issuerDid}`);
1289
+ }
1290
+ SDJwtClient.setKeyManager(this.keyManager);
1291
+ const sdjwtInstance = await SDJwtClient.getIssuerInstance(issuerDid);
1292
+ const { payload: verifiedPayload } = await sdjwtInstance.verify(
1293
+ sdjwtVc,
1294
+ options?.requiredClaims ? { requiredClaimKeys: options?.requiredClaims } : void 0
1295
+ );
1296
+ const disclosures = await sdjwtInstance.getClaims(sdjwtVc);
1297
+ const subjectId = verifiedPayload?.credentialSubject?.id || verifiedPayload.sub;
1298
+ if (options?.expectedSubject) {
1299
+ if (subjectId !== options.expectedSubject) {
1300
+ throw new Error(`Subject mismatch: expected ${options.expectedSubject}, got ${subjectId}`);
1301
+ }
1302
+ }
1303
+ return {
1304
+ payload: verifiedPayload,
1305
+ disclosures,
1306
+ issuer: issuerDid,
1307
+ subject: subjectId,
1308
+ issuedAt: verifiedPayload?.iat && new Date(verifiedPayload.iat * 1e3),
1309
+ expiresAt: verifiedPayload.exp ? new Date(verifiedPayload.exp * 1e3) : null
1310
+ };
1311
+ }
1312
+ /**
1313
+ * Revoke a Verifiable Credential
1314
+ */
1315
+ async revoke(_vcId, _issuerDid) {
1316
+ throw new Error("VC revocation not yet implemented");
1317
+ }
1318
+ /**
1319
+ * Register a custom VC template
1320
+ */
1321
+ registerTemplate(template) {
1322
+ this.templates.set(template.name, template);
1323
+ }
1324
+ registerDefaultTemplates() {
1325
+ this.templates.set("ToolPermissionVC", {
1326
+ type: "ToolPermissionVC",
1327
+ name: "ToolPermissionVC",
1328
+ description: "Permission to use a specific tool",
1329
+ validate: (vc) => {
1330
+ const toolVc = vc;
1331
+ return !!(toolVc.credentialSubject.tool && toolVc.credentialSubject.aud);
1332
+ }
1333
+ });
1334
+ this.templates.set("DataAccessVC", {
1335
+ type: "DataAccessVC",
1336
+ name: "DataAccessVC",
1337
+ description: "Permission to access data resources",
1338
+ validate: (vc) => {
1339
+ const dataVc = vc;
1340
+ return !!(dataVc.credentialSubject.resource && dataVc.credentialSubject.actions && dataVc.credentialSubject.actions.length > 0);
1341
+ }
1342
+ });
1343
+ }
1344
+ calculateExpirationDate(expiresIn) {
1345
+ const now = /* @__PURE__ */ new Date();
1346
+ const match = expiresIn.match(/^(\d+)([hdm])$/);
1347
+ if (!match) {
1348
+ throw new Error(`Invalid expiresIn format: ${expiresIn}`);
1349
+ }
1350
+ const value = parseInt(match[1]);
1351
+ const unit = match[2];
1352
+ switch (unit) {
1353
+ case "h":
1354
+ now.setHours(now.getHours() + value);
1355
+ break;
1356
+ case "d":
1357
+ now.setDate(now.getDate() + value);
1358
+ break;
1359
+ case "m":
1360
+ now.setMinutes(now.getMinutes() + value);
1361
+ break;
1362
+ default:
1363
+ throw new Error(`Unknown time unit: ${unit}`);
1364
+ }
1365
+ return now;
1366
+ }
1367
+ };
1368
+
1369
+ // src/vp/vp-manager.ts
1370
+ var import_crypto_nodejs2 = require("@sd-jwt/crypto-nodejs");
1371
+ var VPManager = class {
1372
+ keyManager;
1373
+ constructor(keyManager) {
1374
+ this.keyManager = keyManager || new KeyManager();
1375
+ SDJwtClient.setKeyManager(this.keyManager);
1376
+ }
1377
+ /**
1378
+ * Create a SD-JWT presentation using the present() method
1379
+ * This properly binds the holder's key to the SD-JWT VC
1380
+ */
1381
+ async create(vcs, options) {
1382
+ if (vcs.length === 0) {
1383
+ throw new Error("At least one SD-JWT VC is required for presentation");
1384
+ }
1385
+ const sdJwtInstance = await SDJwtClient.getHolderInstance(options.holderDid);
1386
+ const sdJwtVC = vcs[0];
1387
+ try {
1388
+ const decodedVC = await sdJwtInstance.decode(sdJwtVC);
1389
+ const presentableKeys = await decodedVC.presentableKeys(import_crypto_nodejs2.digest);
1390
+ const presentationFrame = {};
1391
+ presentableKeys.forEach((key) => {
1392
+ presentationFrame[key] = true;
1393
+ });
1394
+ const kbJwtPayload = {
1395
+ aud: options.domain,
1396
+ nonce: options.challenge,
1397
+ iat: Math.floor(Date.now() / 1e3)
1398
+ };
1399
+ const presentation = await sdJwtInstance.present(sdJwtVC, presentationFrame, {
1400
+ kb: { payload: kbJwtPayload }
1401
+ });
1402
+ return presentation;
1403
+ } catch (error) {
1404
+ console.error("ERROR: Error creating SD-JWT presentation:", error);
1405
+ throw new Error(`Failed to create SD-JWT presentation: ${error.message}`);
1406
+ }
1407
+ }
1408
+ /**
1409
+ * Verify a Verifiable Presentation
1410
+ */
1411
+ async verify(vpJwt, options) {
1412
+ const response = await fetch(getVerifierApiUrl("/api/v1/vp/verify"), {
1413
+ method: "POST",
1414
+ headers: getApiHeaders("verifier"),
1415
+ body: JSON.stringify({
1416
+ vp: vpJwt,
1417
+ challenge: options.expectedChallenge,
1418
+ domain: options.expectedDomain
1419
+ })
1420
+ });
1421
+ if (!response.ok) {
1422
+ throw new Error(`VP verification failed: ${response.statusText}`);
1423
+ }
1424
+ const result = await response.json();
1425
+ if (!result?.valid) {
1426
+ throw new Error(`VP verification failed: ${result?.error}`);
1427
+ }
1428
+ const vp = result?.verifiablePresentation;
1429
+ if (options.expectedHolder && vp.holder !== options.expectedHolder) {
1430
+ throw new Error(`Holder mismatch. Expected: ${options.expectedHolder}, Got: ${vp.holder}`);
1431
+ }
1432
+ if (vp.proof?.challenge !== options.expectedChallenge) {
1433
+ throw new Error("Challenge mismatch");
1434
+ }
1435
+ if (vp.proof?.domain !== options.expectedDomain) {
1436
+ throw new Error("Domain mismatch");
1437
+ }
1438
+ return vp;
1439
+ }
1440
+ /**
1441
+ * Create a VP request
1442
+ */
1443
+ createRequest(domain, query) {
1444
+ return {
1445
+ challenge: generateNonce(),
1446
+ domain,
1447
+ query
1448
+ };
1449
+ }
1450
+ /**
1451
+ * Submit VP to a verifier
1452
+ */
1453
+ async submit(vpJwt, verifierEndpoint) {
1454
+ const response = await fetch(verifierEndpoint, {
1455
+ method: "POST",
1456
+ headers: {
1457
+ "Content-Type": "application/json"
1458
+ },
1459
+ body: JSON.stringify({ vp: vpJwt })
1460
+ });
1461
+ if (!response.ok) {
1462
+ throw new Error(`Failed to submit VP: ${response.statusText}`);
1463
+ }
1464
+ return response.json();
1465
+ }
1466
+ };
1467
+
1468
+ // src/tool/tool-manager.ts
1469
+ var ToolManager = class {
1470
+ vpManager;
1471
+ tools = /* @__PURE__ */ new Map();
1472
+ proxyApiUrl;
1473
+ constructor(vpManager) {
1474
+ this.vpManager = vpManager || new VPManager();
1475
+ const config = getConfig();
1476
+ this.proxyApiUrl = config.proxyApi?.baseUrl || "http://localhost:3000";
1477
+ this.registerDefaultTools();
1478
+ }
1479
+ /**
1480
+ * Invoke a tool action with VC authorization
1481
+ */
1482
+ async invoke(tool, action, params, options) {
1483
+ const toolDef = this.tools.get(tool);
1484
+ if (!toolDef) {
1485
+ throw new Error(`Unknown tool: ${tool}`);
1486
+ }
1487
+ const actionDef = toolDef.actions.find((a) => a.name === action);
1488
+ if (!actionDef) {
1489
+ throw new Error(`Unknown action ${action} for tool ${tool}`);
1490
+ }
1491
+ const domain = new URL(this.proxyApiUrl).hostname;
1492
+ const challenge = this.generateChallenge();
1493
+ const vpJwt = await this.vpManager.create(options.vcs, {
1494
+ holderDid: options.holderDid,
1495
+ challenge,
1496
+ domain,
1497
+ purpose: "invocation"
1498
+ });
1499
+ if (this.proxyApiUrl === "mock://demo") {
1500
+ const mockResponse = {
1501
+ success: true,
1502
+ data: {
1503
+ message: "Mock Slack response - message posted successfully!",
1504
+ channel: params.channel || "#general",
1505
+ text: params.text || "Hello from AIdentity!",
1506
+ ts: Date.now().toString(),
1507
+ ok: true
1508
+ },
1509
+ metadata: {
1510
+ tool,
1511
+ action,
1512
+ holder: options.holderDid,
1513
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1514
+ mock: true
1515
+ }
1516
+ };
1517
+ await new Promise((resolve) => setTimeout(resolve, 500));
1518
+ return mockResponse;
1519
+ }
1520
+ const headers = {
1521
+ "Content-Type": "application/json",
1522
+ Authorization: `Bearer ${vpJwt}`,
1523
+ "X-Holder-DID": options.holderDid,
1524
+ "X-Auth-Challenge": challenge
1525
+ };
1526
+ if (!vpJwt.includes("~")) {
1527
+ headers["X-VCs"] = JSON.stringify(options.vcs);
1528
+ }
1529
+ const response = await fetch(`${this.proxyApiUrl}/api/v1/tool/invoke`, {
1530
+ method: "POST",
1531
+ headers,
1532
+ body: JSON.stringify({
1533
+ tool,
1534
+ action,
1535
+ params,
1536
+ challenge
1537
+ })
1538
+ });
1539
+ if (!response.ok) {
1540
+ const contentType = response.headers.get("content-type");
1541
+ if (contentType && contentType.includes("application/json")) {
1542
+ try {
1543
+ const errorResponse = await response.json();
1544
+ if (errorResponse.success === false) {
1545
+ return errorResponse;
1546
+ }
1547
+ return {
1548
+ success: false,
1549
+ error: errorResponse.message || errorResponse.error || "Tool invocation failed",
1550
+ metadata: errorResponse.metadata
1551
+ };
1552
+ } catch (parseError) {
1553
+ const error = await response.text();
1554
+ return {
1555
+ success: false,
1556
+ error: `Tool invocation failed: ${error}`
1557
+ };
1558
+ }
1559
+ } else {
1560
+ const error = await response.text();
1561
+ return {
1562
+ success: false,
1563
+ error: `Tool invocation failed: ${error}`
1564
+ };
1565
+ }
1566
+ }
1567
+ const result = await response.json();
1568
+ return result;
1569
+ }
1570
+ /**
1571
+ * List available tools
1572
+ */
1573
+ list() {
1574
+ return Array.from(this.tools.values());
1575
+ }
1576
+ /**
1577
+ * Get a specific tool definition
1578
+ */
1579
+ getTool(name) {
1580
+ return this.tools.get(name);
1581
+ }
1582
+ /**
1583
+ * Register a custom tool
1584
+ */
1585
+ registerTool(tool) {
1586
+ this.tools.set(tool.name, tool);
1587
+ }
1588
+ /**
1589
+ * Check if VCs authorize a tool action
1590
+ */
1591
+ async checkAuthorization(vcs, tool, action, resourceScope) {
1592
+ for (const vcJwt of vcs) {
1593
+ try {
1594
+ const parts = vcJwt.split(".");
1595
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
1596
+ if (payload.credentialSubject?.tool === `${tool}.${action}`) {
1597
+ if (resourceScope) {
1598
+ const vcScope = payload.credentialSubject.resourceScope;
1599
+ if (!this.matchScope(vcScope, resourceScope)) {
1600
+ continue;
1601
+ }
1602
+ }
1603
+ return true;
1604
+ }
1605
+ } catch {
1606
+ continue;
1607
+ }
1608
+ }
1609
+ return false;
1610
+ }
1611
+ matchScope(vcScope, requiredScope) {
1612
+ for (const [key, value] of Object.entries(requiredScope)) {
1613
+ if (vcScope[key] !== value && vcScope[key] !== "*") {
1614
+ return false;
1615
+ }
1616
+ }
1617
+ return true;
1618
+ }
1619
+ generateChallenge() {
1620
+ return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
1621
+ }
1622
+ registerDefaultTools() {
1623
+ this.tools.set("slack", {
1624
+ name: "slack",
1625
+ description: "Slack workspace operations",
1626
+ actions: [
1627
+ {
1628
+ name: "postMessage",
1629
+ description: "Post a message to a channel",
1630
+ parameters: {
1631
+ channel: "string",
1632
+ text: "string",
1633
+ thread_ts: "string?"
1634
+ }
1635
+ },
1636
+ {
1637
+ name: "getChannels",
1638
+ description: "List channels",
1639
+ parameters: {}
1640
+ },
1641
+ {
1642
+ name: "getUserInfo",
1643
+ description: "Get user information",
1644
+ parameters: {
1645
+ userId: "string"
1646
+ }
1647
+ },
1648
+ {
1649
+ name: "getChannelHistory",
1650
+ description: "Get channel history",
1651
+ parameters: {
1652
+ channel: "string",
1653
+ latest: "string?",
1654
+ oldest: "string?",
1655
+ limit: "number?",
1656
+ inclusive: "boolean?"
1657
+ }
1658
+ }
1659
+ ]
1660
+ });
1661
+ this.tools.set("github", {
1662
+ name: "github",
1663
+ description: "GitHub repository operations",
1664
+ actions: [
1665
+ {
1666
+ name: "createIssue",
1667
+ description: "Create a new issue",
1668
+ parameters: {
1669
+ owner: "string",
1670
+ repo: "string",
1671
+ title: "string",
1672
+ body: "string",
1673
+ labels: "string[]?"
1674
+ }
1675
+ },
1676
+ {
1677
+ name: "listIssues",
1678
+ description: "List repository issues",
1679
+ parameters: {
1680
+ owner: "string",
1681
+ repo: "string",
1682
+ state: "string?"
1683
+ }
1684
+ },
1685
+ {
1686
+ name: "getRepo",
1687
+ description: "Get repository information",
1688
+ parameters: {
1689
+ owner: "string",
1690
+ repo: "string"
1691
+ }
1692
+ }
1693
+ ]
1694
+ });
1695
+ this.tools.set("gmail", {
1696
+ name: "gmail",
1697
+ description: "Gmail operations",
1698
+ actions: [
1699
+ {
1700
+ name: "sendMessage",
1701
+ description: "Send an email message",
1702
+ parameters: {
1703
+ to: "string",
1704
+ subject: "string",
1705
+ body: "string",
1706
+ cc: "string[]?",
1707
+ bcc: "string[]?",
1708
+ format: "string?"
1709
+ }
1710
+ },
1711
+ {
1712
+ name: "getMessages",
1713
+ description: "Get email messages",
1714
+ parameters: {
1715
+ query: "string?",
1716
+ maxResults: "number?",
1717
+ pageToken: "string?",
1718
+ labelIds: "string[]?"
1719
+ }
1720
+ },
1721
+ {
1722
+ name: "getMessage",
1723
+ description: "Get a specific email message",
1724
+ parameters: {
1725
+ messageId: "string",
1726
+ format: "string?"
1727
+ }
1728
+ },
1729
+ {
1730
+ name: "getLabels",
1731
+ description: "Get available labels",
1732
+ parameters: {}
1733
+ },
1734
+ {
1735
+ name: "searchMessages",
1736
+ description: "Search email messages",
1737
+ parameters: {
1738
+ query: "string",
1739
+ maxResults: "number?",
1740
+ pageToken: "string?"
1741
+ }
1742
+ },
1743
+ {
1744
+ name: "modifyMessage",
1745
+ description: "Modify message labels",
1746
+ parameters: {
1747
+ messageId: "string",
1748
+ addLabelIds: "string[]?",
1749
+ removeLabelIds: "string[]?"
1750
+ }
1751
+ },
1752
+ {
1753
+ name: "createDraft",
1754
+ description: "Create a draft email",
1755
+ parameters: {
1756
+ to: "string",
1757
+ subject: "string",
1758
+ body: "string",
1759
+ cc: "string[]?",
1760
+ bcc: "string[]?",
1761
+ format: "string?"
1762
+ }
1763
+ }
1764
+ ]
1765
+ });
1766
+ this.tools.set("drive", {
1767
+ name: "drive",
1768
+ description: "Google Drive operations",
1769
+ actions: [
1770
+ {
1771
+ name: "listFiles",
1772
+ description: "List files in folder",
1773
+ parameters: {
1774
+ folderId: "string?",
1775
+ query: "string?",
1776
+ maxResults: "number?",
1777
+ pageToken: "string?",
1778
+ orderBy: "string?"
1779
+ }
1780
+ },
1781
+ {
1782
+ name: "getFile",
1783
+ description: "Get file information",
1784
+ parameters: {
1785
+ fileId: "string",
1786
+ fields: "string?"
1787
+ }
1788
+ },
1789
+ {
1790
+ name: "createFile",
1791
+ description: "Create a new file",
1792
+ parameters: {
1793
+ name: "string",
1794
+ content: "string",
1795
+ mimeType: "string?",
1796
+ parents: "string[]?",
1797
+ description: "string?"
1798
+ }
1799
+ },
1800
+ {
1801
+ name: "updateFile",
1802
+ description: "Update an existing file",
1803
+ parameters: {
1804
+ fileId: "string",
1805
+ name: "string?",
1806
+ content: "string?",
1807
+ description: "string?"
1808
+ }
1809
+ },
1810
+ {
1811
+ name: "deleteFile",
1812
+ description: "Delete a file",
1813
+ parameters: {
1814
+ fileId: "string"
1815
+ }
1816
+ },
1817
+ {
1818
+ name: "getFolders",
1819
+ description: "List folders",
1820
+ parameters: {
1821
+ parentId: "string?"
1822
+ }
1823
+ },
1824
+ {
1825
+ name: "createFolder",
1826
+ description: "Create a new folder",
1827
+ parameters: {
1828
+ name: "string",
1829
+ parentId: "string?",
1830
+ description: "string?"
1831
+ }
1832
+ },
1833
+ {
1834
+ name: "downloadFile",
1835
+ description: "Download file content",
1836
+ parameters: {
1837
+ fileId: "string",
1838
+ mimeType: "string?"
1839
+ }
1840
+ },
1841
+ {
1842
+ name: "shareFile",
1843
+ description: "Share file with permissions",
1844
+ parameters: {
1845
+ fileId: "string",
1846
+ type: "string",
1847
+ role: "string",
1848
+ emailAddress: "string?",
1849
+ domain: "string?"
1850
+ }
1851
+ }
1852
+ ]
1853
+ });
1854
+ this.tools.set("jira", {
1855
+ name: "jira",
1856
+ description: "Jira project and issue management",
1857
+ actions: [
1858
+ {
1859
+ name: "getProjects",
1860
+ description: "List all Jira projects",
1861
+ parameters: {
1862
+ recent: "number?"
1863
+ }
1864
+ },
1865
+ {
1866
+ name: "getBoard",
1867
+ description: "Get Jira board details",
1868
+ parameters: {
1869
+ boardId: "number"
1870
+ }
1871
+ },
1872
+ {
1873
+ name: "getBoards",
1874
+ description: "List all Jira boards",
1875
+ parameters: {
1876
+ projectKeyOrId: "string?",
1877
+ type: "string?"
1878
+ }
1879
+ },
1880
+ {
1881
+ name: "getSprints",
1882
+ description: "Get sprints for a Jira board",
1883
+ parameters: {
1884
+ boardId: "number",
1885
+ state: "string?"
1886
+ }
1887
+ },
1888
+ {
1889
+ name: "getSprintIssues",
1890
+ description: "Get issues in a specific sprint",
1891
+ parameters: {
1892
+ sprintId: "number",
1893
+ maxResults: "number?"
1894
+ }
1895
+ },
1896
+ {
1897
+ name: "searchIssues",
1898
+ description: "Search for Jira issues using JQL",
1899
+ parameters: {
1900
+ jql: "string",
1901
+ maxResults: "number?",
1902
+ startAt: "number?"
1903
+ }
1904
+ },
1905
+ {
1906
+ name: "getIssue",
1907
+ description: "Get a specific Jira issue",
1908
+ parameters: {
1909
+ issueIdOrKey: "string"
1910
+ }
1911
+ },
1912
+ {
1913
+ name: "getIssueWorklogs",
1914
+ description: "Get worklogs for a specific issue",
1915
+ parameters: {
1916
+ issueKey: "string"
1917
+ }
1918
+ },
1919
+ {
1920
+ name: "createIssue",
1921
+ description: "Create a new Jira issue",
1922
+ parameters: {
1923
+ projectKey: "string",
1924
+ summary: "string",
1925
+ description: "string?",
1926
+ issueType: "string",
1927
+ priority: "string?",
1928
+ assignee: "string?"
1929
+ }
1930
+ }
1931
+ ]
1932
+ });
1933
+ }
1934
+ };
1935
+
1936
+ // src/memory/memory-manager.ts
1937
+ var MemoryManager = class {
1938
+ vpManager;
1939
+ proxyApiUrl;
1940
+ constructor(vpManager) {
1941
+ this.vpManager = vpManager || new VPManager();
1942
+ const config = getConfig();
1943
+ this.proxyApiUrl = config.proxyApi?.baseUrl || "http://localhost:3000";
1944
+ }
1945
+ /**
1946
+ * Write a document to memory
1947
+ */
1948
+ async write(content, options) {
1949
+ const domain = new URL(this.proxyApiUrl).hostname;
1950
+ const challenge = this.generateChallenge();
1951
+ const vpJwt = await this.vpManager.create(options.vcs, {
1952
+ holderDid: options.holderDid,
1953
+ challenge,
1954
+ domain,
1955
+ purpose: "write"
1956
+ });
1957
+ const response = await fetch(`${this.proxyApiUrl}/api/v1/memory/${options.namespace}/doc`, {
1958
+ method: "POST",
1959
+ headers: {
1960
+ "Content-Type": "application/json",
1961
+ Authorization: `Bearer ${vpJwt}`
1962
+ },
1963
+ body: JSON.stringify({
1964
+ content,
1965
+ metadata: options.metadata,
1966
+ challenge
1967
+ })
1968
+ });
1969
+ if (!response.ok) {
1970
+ const error = await response.text();
1971
+ throw new Error(`Failed to write to memory: ${error}`);
1972
+ }
1973
+ return response.json();
1974
+ }
1975
+ /**
1976
+ * Query memory with vector search
1977
+ */
1978
+ async query(query, options) {
1979
+ const domain = new URL(this.proxyApiUrl).hostname;
1980
+ const challenge = this.generateChallenge();
1981
+ const vpJwt = await this.vpManager.create(options.vcs, {
1982
+ holderDid: options.holderDid,
1983
+ challenge,
1984
+ domain,
1985
+ purpose: "read"
1986
+ });
1987
+ const queryParams = {
1988
+ query,
1989
+ namespace: options.namespace,
1990
+ limit: options.limit || 10,
1991
+ filter: options.filter
1992
+ };
1993
+ const namespace = options.namespace || "default";
1994
+ const response = await fetch(`${this.proxyApiUrl}/api/v1/memory/${namespace}/query`, {
1995
+ method: "POST",
1996
+ headers: {
1997
+ "Content-Type": "application/json",
1998
+ Authorization: `Bearer ${vpJwt}`
1999
+ },
2000
+ body: JSON.stringify({
2001
+ ...queryParams,
2002
+ challenge
2003
+ })
2004
+ });
2005
+ if (!response.ok) {
2006
+ const error = await response.text();
2007
+ throw new Error(`Failed to query memory: ${error}`);
2008
+ }
2009
+ return response.json();
2010
+ }
2011
+ /**
2012
+ * Delete a document from memory
2013
+ */
2014
+ async delete(documentId, options) {
2015
+ const domain = new URL(this.proxyApiUrl).hostname;
2016
+ const challenge = this.generateChallenge();
2017
+ const vpJwt = await this.vpManager.create(options.vcs, {
2018
+ holderDid: options.holderDid,
2019
+ challenge,
2020
+ domain,
2021
+ purpose: "delete"
2022
+ });
2023
+ const response = await fetch(
2024
+ `${this.proxyApiUrl}/api/v1/memory/${options.namespace}/${documentId}`,
2025
+ {
2026
+ method: "DELETE",
2027
+ headers: {
2028
+ Authorization: `Bearer ${vpJwt}`,
2029
+ "X-Challenge": challenge
2030
+ }
2031
+ }
2032
+ );
2033
+ if (!response.ok) {
2034
+ const error = await response.text();
2035
+ throw new Error(`Failed to delete from memory: ${error}`);
2036
+ }
2037
+ }
2038
+ /**
2039
+ * List documents in a namespace
2040
+ */
2041
+ async list(options) {
2042
+ const domain = new URL(this.proxyApiUrl).hostname;
2043
+ const challenge = this.generateChallenge();
2044
+ const vpJwt = await this.vpManager.create(options.vcs, {
2045
+ holderDid: options.holderDid,
2046
+ challenge,
2047
+ domain,
2048
+ purpose: "read"
2049
+ });
2050
+ const params = new URLSearchParams({
2051
+ limit: (options.limit || 100).toString(),
2052
+ offset: (options.offset || 0).toString()
2053
+ });
2054
+ const response = await fetch(
2055
+ `${this.proxyApiUrl}/api/v1/memory/${options.namespace}/list?${params}`,
2056
+ {
2057
+ headers: {
2058
+ Authorization: `Bearer ${vpJwt}`,
2059
+ "X-Challenge": challenge
2060
+ }
2061
+ }
2062
+ );
2063
+ if (!response.ok) {
2064
+ const error = await response.text();
2065
+ throw new Error(`Failed to list memory documents: ${error}`);
2066
+ }
2067
+ return response.json();
2068
+ }
2069
+ /**
2070
+ * Check if VCs authorize memory access
2071
+ */
2072
+ async checkAuthorization(vcs, action, resource) {
2073
+ for (const vcJwt of vcs) {
2074
+ try {
2075
+ const parts = vcJwt.split(".");
2076
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
2077
+ const vcResource = payload.credentialSubject?.resource;
2078
+ const vcActions = payload.credentialSubject?.actions || [];
2079
+ if (this.matchResource(vcResource, resource)) {
2080
+ if (vcActions.includes(action)) {
2081
+ return true;
2082
+ }
2083
+ }
2084
+ } catch {
2085
+ continue;
2086
+ }
2087
+ }
2088
+ return false;
2089
+ }
2090
+ matchResource(vcResource, requiredResource) {
2091
+ if (vcResource.endsWith("/*")) {
2092
+ const prefix = vcResource.slice(0, -2);
2093
+ return requiredResource.startsWith(prefix);
2094
+ }
2095
+ return vcResource === requiredResource;
2096
+ }
2097
+ generateChallenge() {
2098
+ return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
2099
+ }
2100
+ };
2101
+
2102
+ // src/organization/organization-manager.ts
2103
+ var OrganizationManager = class {
2104
+ vpManager;
2105
+ vcManager;
2106
+ apiBaseUrl;
2107
+ constructor(vpManager, vcManager) {
2108
+ this.vpManager = vpManager || new VPManager();
2109
+ this.vcManager = vcManager || new VCManager();
2110
+ const config = getConfig();
2111
+ this.apiBaseUrl = config.proxyApi?.baseUrl || "http://localhost:3000";
2112
+ }
2113
+ /**
2114
+ * Request tool permissions using employee VC
2115
+ */
2116
+ async requestToolPermissions(employeeVCJWT, requestedTools, holderDid) {
2117
+ const challenge = this.generateChallenge();
2118
+ const vpRequest = {
2119
+ employeeVC: employeeVCJWT,
2120
+ requestedTools,
2121
+ challenge,
2122
+ domain: new URL(this.apiBaseUrl).hostname
2123
+ };
2124
+ const response = await fetch(`${this.apiBaseUrl}/api/organization/employee/permissions`, {
2125
+ method: "POST",
2126
+ headers: { "Content-Type": "application/json" },
2127
+ body: JSON.stringify(vpRequest)
2128
+ });
2129
+ if (!response.ok) {
2130
+ throw new Error(`Permission request failed: ${response.statusText}`);
2131
+ }
2132
+ const result = await response.json();
2133
+ if (!result.success) {
2134
+ throw new Error(`Permission denied: ${result.error}`);
2135
+ }
2136
+ return {
2137
+ permittedPermissions: result.permittedPermissions,
2138
+ employee: result.employee
2139
+ };
2140
+ }
2141
+ /**
2142
+ * Issue tool permissions to AI Agent based on organization approval
2143
+ */
2144
+ async issueOrganizationDelegatedPermissions(agentDid, employeeVCJWT, requestedTools, issuerDid) {
2145
+ const { permittedPermissions } = await this.requestToolPermissions(
2146
+ employeeVCJWT,
2147
+ requestedTools,
2148
+ issuerDid
2149
+ );
2150
+ const issuedVCs = [];
2151
+ for (const permission of permittedPermissions) {
2152
+ for (const action of permission.actions) {
2153
+ const vc = await this.vcManager.issue(
2154
+ "ToolPermissionVC",
2155
+ {
2156
+ tool: `${permission.tool}.${action}`,
2157
+ aud: permission.tool,
2158
+ organizationDelegated: true,
2159
+ sourceEmployeeVC: employeeVCJWT
2160
+ // Include reference to source employee VC
2161
+ },
2162
+ {
2163
+ issuerDid,
2164
+ subjectDid: agentDid,
2165
+ expiresIn: permission.duration || "8h"
2166
+ }
2167
+ );
2168
+ issuedVCs.push(vc);
2169
+ }
2170
+ }
2171
+ return issuedVCs;
2172
+ }
2173
+ /**
2174
+ * Create simplified workflow for employee to AI Agent delegation
2175
+ */
2176
+ async delegateToAIAgent(employeeVCJWT, agentDid, tools, issuerDid, options) {
2177
+ const requestedTools = tools.map((tool) => ({
2178
+ tool,
2179
+ actions: ["read", "write"],
2180
+ // Request common actions
2181
+ duration: options?.duration,
2182
+ justification: options?.justification
2183
+ }));
2184
+ const issuedVCs = await this.issueOrganizationDelegatedPermissions(
2185
+ agentDid,
2186
+ employeeVCJWT,
2187
+ requestedTools,
2188
+ issuerDid
2189
+ );
2190
+ const permissionSummary = {};
2191
+ for (const tool of tools) {
2192
+ const relatedVCs = issuedVCs.filter((vc) => vc.includes(tool));
2193
+ permissionSummary[tool] = relatedVCs.map((vc) => this.extractActionFromVC(vc));
2194
+ }
2195
+ return {
2196
+ issuedVCs,
2197
+ permissionSummary
2198
+ };
2199
+ }
2200
+ /**
2201
+ * Register organization with AIdentity
2202
+ */
2203
+ async registerOrganization(config) {
2204
+ const response = await fetch(`${this.apiBaseUrl}/api/organization/register`, {
2205
+ method: "POST",
2206
+ headers: { "Content-Type": "application/json" },
2207
+ body: JSON.stringify(config)
2208
+ });
2209
+ if (!response.ok) {
2210
+ throw new Error(`Organization registration failed: ${response.statusText}`);
2211
+ }
2212
+ }
2213
+ generateChallenge() {
2214
+ return `challenge_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
2215
+ }
2216
+ extractActionFromVC(vcJWT) {
2217
+ try {
2218
+ const [, payload] = vcJWT.split(".");
2219
+ const vc = JSON.parse(Buffer.from(payload, "base64url").toString());
2220
+ return vc.credentialSubject.tool.split(".").pop() || "unknown";
2221
+ } catch {
2222
+ return "unknown";
2223
+ }
2224
+ }
2225
+ };
2226
+
2227
+ // src/grant/grant-manager.ts
2228
+ var GrantManager = class {
2229
+ constructor(_vpManager) {
2230
+ }
2231
+ /**
2232
+ * Grant提案を取得
2233
+ * @param options - 提案オプション
2234
+ * @param options.oauthTokenId - OAuthトークンID
2235
+ * @param options.targetUserId - 対象ユーザーID
2236
+ * @param options.projectId - プロジェクトID
2237
+ * @param authOptions - 認証オプション(VP or issuerDid)
2238
+ */
2239
+ async suggest(options, authOptions) {
2240
+ const headers = {
2241
+ "Content-Type": "application/json"
2242
+ };
2243
+ if (authOptions.vpJwt) {
2244
+ headers["Authorization"] = `Bearer ${authOptions.vpJwt}`;
2245
+ } else if (authOptions.issuerDid) {
2246
+ headers["x-issuer-did"] = authOptions.issuerDid;
2247
+ } else {
2248
+ throw new Error("Either vpJwt or issuerDid is required for authentication");
2249
+ }
2250
+ const response = await fetch(getDidApiUrl("/api/v1/grants/suggest"), {
2251
+ method: "POST",
2252
+ headers,
2253
+ body: JSON.stringify(options)
2254
+ });
2255
+ if (!response.ok) {
2256
+ const error = await response.json();
2257
+ throw new Error(error.error || `Failed to get grant suggestion: ${response.statusText}`);
2258
+ }
2259
+ const result = await response.json();
2260
+ return result.data;
2261
+ }
2262
+ /**
2263
+ * Grant提案を確認して作成
2264
+ * @param request - 確認リクエスト
2265
+ * @param authOptions - 認証オプション
2266
+ */
2267
+ async confirm(request, authOptions) {
2268
+ const headers = {
2269
+ "Content-Type": "application/json"
2270
+ };
2271
+ if (authOptions.vpJwt) {
2272
+ headers["Authorization"] = `Bearer ${authOptions.vpJwt}`;
2273
+ } else if (authOptions.issuerDid) {
2274
+ headers["x-issuer-did"] = authOptions.issuerDid;
2275
+ } else {
2276
+ throw new Error("Either vpJwt or issuerDid is required for authentication");
2277
+ }
2278
+ const response = await fetch(getDidApiUrl("/api/v1/grants/confirm"), {
2279
+ method: "POST",
2280
+ headers,
2281
+ body: JSON.stringify(request)
2282
+ });
2283
+ if (!response.ok) {
2284
+ const error = await response.json();
2285
+ throw new Error(error.error || `Failed to confirm grant: ${response.statusText}`);
2286
+ }
2287
+ const result = await response.json();
2288
+ return result.data;
2289
+ }
2290
+ /**
2291
+ * Grantを直接作成
2292
+ * @param request - Grant作成リクエスト
2293
+ * @param authOptions - 認証オプション
2294
+ */
2295
+ async create(request, authOptions) {
2296
+ const headers = {
2297
+ "Content-Type": "application/json"
2298
+ };
2299
+ if (authOptions.vpJwt) {
2300
+ headers["Authorization"] = `Bearer ${authOptions.vpJwt}`;
2301
+ } else if (authOptions.issuerDid) {
2302
+ headers["x-issuer-did"] = authOptions.issuerDid;
2303
+ } else {
2304
+ throw new Error("Either vpJwt or issuerDid is required for authentication");
2305
+ }
2306
+ const response = await fetch(getDidApiUrl("/api/v1/grants"), {
2307
+ method: "POST",
2308
+ headers,
2309
+ body: JSON.stringify(request)
2310
+ });
2311
+ if (!response.ok) {
2312
+ const error = await response.json();
2313
+ throw new Error(error.error || `Failed to create grant: ${response.statusText}`);
2314
+ }
2315
+ const result = await response.json();
2316
+ return result.data;
2317
+ }
2318
+ /**
2319
+ * ユーザー用のGrant一覧を取得
2320
+ * @param userId - ユーザーID
2321
+ * @param status - フィルタするステータス(オプション)
2322
+ */
2323
+ async listForUser(userId, status) {
2324
+ const headers = {
2325
+ "Content-Type": "application/json"
2326
+ };
2327
+ const encodedUserId = encodeURIComponent(userId);
2328
+ const url = status ? getDidApiUrl(`/api/v1/grants/user/${encodedUserId}?status=${status}`) : getDidApiUrl(`/api/v1/grants/user/${encodedUserId}`);
2329
+ const response = await fetch(url, {
2330
+ method: "GET",
2331
+ headers
2332
+ });
2333
+ if (!response.ok) {
2334
+ const error = await response.json();
2335
+ throw new Error(error.error || `Failed to list grants for user: ${response.statusText}`);
2336
+ }
2337
+ const result = await response.json();
2338
+ return result.data;
2339
+ }
2340
+ /**
2341
+ * Issuer用のGrant一覧を取得
2342
+ * @param issuerDid - IssuerのDID
2343
+ * @param status - フィルタするステータス(オプション)
2344
+ */
2345
+ async listForIssuer(issuerDid, status) {
2346
+ const headers = {
2347
+ "Content-Type": "application/json"
2348
+ };
2349
+ const encodedDid = encodeURIComponent(issuerDid);
2350
+ const url = status ? getDidApiUrl(`/api/v1/grants/issuer/${encodedDid}?status=${status}`) : getDidApiUrl(`/api/v1/grants/issuer/${encodedDid}`);
2351
+ const response = await fetch(url, {
2352
+ method: "GET",
2353
+ headers
2354
+ });
2355
+ if (!response.ok) {
2356
+ const error = await response.json();
2357
+ throw new Error(error.error || `Failed to list grants for issuer: ${response.statusText}`);
2358
+ }
2359
+ const result = await response.json();
2360
+ return result.data;
2361
+ }
2362
+ /**
2363
+ * Grantを取得
2364
+ * @param grantId - GrantのID
2365
+ */
2366
+ async get(grantId) {
2367
+ const headers = {
2368
+ "Content-Type": "application/json"
2369
+ };
2370
+ const response = await fetch(getDidApiUrl(`/api/v1/grants/${grantId}`), {
2371
+ method: "GET",
2372
+ headers
2373
+ });
2374
+ if (!response.ok) {
2375
+ const error = await response.json();
2376
+ throw new Error(error.error || `Failed to get grant: ${response.statusText}`);
2377
+ }
2378
+ const result = await response.json();
2379
+ return result.data;
2380
+ }
2381
+ /**
2382
+ * Grantを取り消し
2383
+ * @param grantId - GrantのID
2384
+ * @param reason - 取り消し理由
2385
+ * @param authOptions - 認証オプション
2386
+ */
2387
+ async revoke(grantId, reason, authOptions) {
2388
+ const headers = {
2389
+ "Content-Type": "application/json"
2390
+ };
2391
+ if (authOptions.vpJwt) {
2392
+ headers["Authorization"] = `Bearer ${authOptions.vpJwt}`;
2393
+ } else if (authOptions.issuerDid) {
2394
+ headers["x-issuer-did"] = authOptions.issuerDid;
2395
+ } else {
2396
+ throw new Error("Either vpJwt or issuerDid is required for authentication");
2397
+ }
2398
+ const response = await fetch(getDidApiUrl(`/api/v1/grants/${grantId}`), {
2399
+ method: "DELETE",
2400
+ headers,
2401
+ body: JSON.stringify({ reason })
2402
+ });
2403
+ if (!response.ok) {
2404
+ const error = await response.json();
2405
+ throw new Error(error.error || `Failed to revoke grant: ${response.statusText}`);
2406
+ }
2407
+ const result = await response.json();
2408
+ return result.data;
2409
+ }
2410
+ /**
2411
+ * Grant権限をチェック
2412
+ * @param request - 権限チェックリクエスト
2413
+ */
2414
+ async checkPermission(request) {
2415
+ const headers = {
2416
+ "Content-Type": "application/json"
2417
+ };
2418
+ const response = await fetch(getDidApiUrl("/api/v1/grants/check"), {
2419
+ method: "POST",
2420
+ headers,
2421
+ body: JSON.stringify(request)
2422
+ });
2423
+ if (!response.ok) {
2424
+ const error = await response.json();
2425
+ throw new Error(error.error || `Failed to check grant permission: ${response.statusText}`);
2426
+ }
2427
+ const result = await response.json();
2428
+ return result.data;
2429
+ }
2430
+ /**
2431
+ * Grant更新
2432
+ * @param grantId - GrantのID
2433
+ * @param request - 更新リクエスト
2434
+ * @param authOptions - 認証オプション
2435
+ */
2436
+ async update(grantId, request, authOptions) {
2437
+ const headers = {
2438
+ "Content-Type": "application/json"
2439
+ };
2440
+ if (authOptions.vpJwt) {
2441
+ headers["Authorization"] = `Bearer ${authOptions.vpJwt}`;
2442
+ } else if (authOptions.issuerDid) {
2443
+ headers["x-issuer-did"] = authOptions.issuerDid;
2444
+ } else {
2445
+ throw new Error("Either vpJwt or issuerDid is required for authentication");
2446
+ }
2447
+ const response = await fetch(getDidApiUrl(`/api/v1/grants/${grantId}`), {
2448
+ method: "PUT",
2449
+ headers,
2450
+ body: JSON.stringify(request)
2451
+ });
2452
+ if (!response.ok) {
2453
+ const error = await response.json();
2454
+ throw new Error(error.error || `Failed to update grant: ${response.statusText}`);
2455
+ }
2456
+ const result = await response.json();
2457
+ return result.data;
2458
+ }
2459
+ };
2460
+
2461
+ // src/client.ts
2462
+ __reExport(client_exports, require("@vess-id/ai-identity-types"));
2463
+ var AIdentityClient = class {
2464
+ agent;
2465
+ user;
2466
+ vc;
2467
+ vp;
2468
+ tool;
2469
+ memory;
2470
+ organization;
2471
+ grant;
2472
+ keyManager;
2473
+ currentAgent;
2474
+ constructor(config, password) {
2475
+ if (config) {
2476
+ configure(config);
2477
+ }
2478
+ this.keyManager = new KeyManager(password);
2479
+ this.agent = new AgentManager(this.keyManager);
2480
+ this.user = new UserIdentityManager(this.keyManager);
2481
+ this.vc = new VCManager(this.keyManager, this.agent, this.user);
2482
+ this.vp = new VPManager(this.keyManager);
2483
+ this.tool = new ToolManager(this.vp);
2484
+ this.memory = new MemoryManager(this.vp);
2485
+ this.organization = new OrganizationManager(this.vp, this.vc);
2486
+ this.grant = new GrantManager(this.vp);
2487
+ }
2488
+ /**
2489
+ * Quick setup: Create or load an agent
2490
+ */
2491
+ async setup(did) {
2492
+ if (did) {
2493
+ this.currentAgent = await this.agent.export(did).then(({ agent }) => agent);
2494
+ } else {
2495
+ this.currentAgent = await this.agent.create();
2496
+ }
2497
+ return this.currentAgent;
2498
+ }
2499
+ /**
2500
+ * Get current agent
2501
+ */
2502
+ getCurrentAgent() {
2503
+ return this.currentAgent;
2504
+ }
2505
+ /**
2506
+ * Get current user DID
2507
+ */
2508
+ async getCurrentUserDID() {
2509
+ return this.user.getCurrentUserDID();
2510
+ }
2511
+ /**
2512
+ * Create or reset user identity
2513
+ */
2514
+ async resetUserIdentity() {
2515
+ return this.user.resetUserIdentity();
2516
+ }
2517
+ /**
2518
+ * Issue a VC for tool permission
2519
+ * Enhanced to support User → Agent delegation pattern
2520
+ */
2521
+ async issueToolPermission(tool, action, options) {
2522
+ return this.vc.issue(
2523
+ "ToolPermissionVC",
2524
+ {
2525
+ tool: `${tool}.${action}`,
2526
+ resourceScope: options.resourceScope,
2527
+ aud: tool
2528
+ },
2529
+ {
2530
+ issuerDid: options.issuerDid,
2531
+ subjectDid: options.subjectDid,
2532
+ agentId: options.agentId,
2533
+ expiresIn: options.expiresIn || "1h"
2534
+ }
2535
+ );
2536
+ }
2537
+ /**
2538
+ * Issue a VC for data access
2539
+ * Enhanced to support User → Agent delegation pattern
2540
+ */
2541
+ async issueDataAccess(resource, actions, options) {
2542
+ return this.vc.issue(
2543
+ "DataAccessVC",
2544
+ {
2545
+ resource,
2546
+ actions
2547
+ },
2548
+ {
2549
+ issuerDid: options.issuerDid,
2550
+ subjectDid: options.subjectDid,
2551
+ agentId: options.agentId,
2552
+ expiresIn: options.expiresIn || "24h"
2553
+ }
2554
+ );
2555
+ }
2556
+ /**
2557
+ * Invoke a tool with automatic VP creation
2558
+ */
2559
+ async invokeTool(tool, action, params, vcs) {
2560
+ const holderDid = this.currentAgent?.did;
2561
+ if (!holderDid) {
2562
+ throw new Error("No current agent available");
2563
+ }
2564
+ return this.tool.invoke(tool, action, params, {
2565
+ vcs,
2566
+ holderDid
2567
+ });
2568
+ }
2569
+ /**
2570
+ * Write to memory with automatic VP creation
2571
+ */
2572
+ async writeMemory(content, namespace, vcs, metadata) {
2573
+ const holderDid = this.currentAgent?.did;
2574
+ if (!holderDid) {
2575
+ throw new Error("No current agent available");
2576
+ }
2577
+ return this.memory.write(content, {
2578
+ namespace,
2579
+ metadata,
2580
+ vcs,
2581
+ holderDid
2582
+ });
2583
+ }
2584
+ /**
2585
+ * Query memory with automatic VP creation
2586
+ */
2587
+ async queryMemory(query, vcs, options) {
2588
+ const holderDid = this.currentAgent?.did;
2589
+ if (!holderDid) {
2590
+ throw new Error("No current agent available");
2591
+ }
2592
+ return this.memory.query(query, {
2593
+ ...options,
2594
+ vcs,
2595
+ holderDid
2596
+ });
2597
+ }
2598
+ };
2599
+ var defaultClient;
2600
+ function getClient(config, password) {
2601
+ if (!defaultClient) {
2602
+ defaultClient = new AIdentityClient(config, password);
2603
+ }
2604
+ return defaultClient;
2605
+ }
2606
+
2607
+ // src/vc/api-vc-manager.ts
2608
+ var import_ai_identity_types2 = require("@vess-id/ai-identity-types");
2609
+
2610
+ // src/organization/disclosure-config-manager.ts
2611
+ var import_ai_identity_types = require("@vess-id/ai-identity-types");
2612
+ var DisclosureConfigManager = class {
2613
+ configs = /* @__PURE__ */ new Map();
2614
+ /**
2615
+ * Set disclosure configuration for an organization
2616
+ */
2617
+ async setOrganizationConfig(organizationDid, config) {
2618
+ const existingConfig = this.configs.get(organizationDid);
2619
+ const now = /* @__PURE__ */ new Date();
2620
+ const newConfig = {
2621
+ organizationDid,
2622
+ defaultFields: config.defaultFields || [],
2623
+ credentialTypeConfigs: config.credentialTypeConfigs || /* @__PURE__ */ new Map(),
2624
+ createdAt: existingConfig?.createdAt || now,
2625
+ updatedAt: now
2626
+ };
2627
+ this.configs.set(organizationDid, newConfig);
2628
+ }
2629
+ /**
2630
+ * Get disclosure configuration for an organization
2631
+ */
2632
+ async getOrganizationConfig(organizationDid) {
2633
+ return this.configs.get(organizationDid) || null;
2634
+ }
2635
+ /**
2636
+ * Set credential type specific disclosure configuration
2637
+ */
2638
+ async setCredentialTypeConfig(organizationDid, credentialType, config) {
2639
+ let orgConfig = this.configs.get(organizationDid);
2640
+ if (!orgConfig) {
2641
+ const now = /* @__PURE__ */ new Date();
2642
+ orgConfig = {
2643
+ organizationDid,
2644
+ defaultFields: [],
2645
+ credentialTypeConfigs: /* @__PURE__ */ new Map(),
2646
+ createdAt: now,
2647
+ updatedAt: now
2648
+ };
2649
+ }
2650
+ orgConfig.credentialTypeConfigs.set(credentialType, config);
2651
+ orgConfig.updatedAt = /* @__PURE__ */ new Date();
2652
+ this.configs.set(organizationDid, orgConfig);
2653
+ }
2654
+ /**
2655
+ * Get selective disclosure fields for a specific credential type and organization
2656
+ */
2657
+ async getSelectiveDisclosureFields(organizationDid, credentialType, requestedFields) {
2658
+ const orgConfig = this.configs.get(organizationDid);
2659
+ if (!orgConfig) {
2660
+ return this.getDefaultConfiguration(credentialType, requestedFields);
2661
+ }
2662
+ const typeConfig = orgConfig.credentialTypeConfigs.get(credentialType);
2663
+ if (!typeConfig) {
2664
+ return {
2665
+ selectiveFields: requestedFields || orgConfig.defaultFields,
2666
+ mandatoryFields: [],
2667
+ neverDisclose: [],
2668
+ decoyCount: 0
2669
+ };
2670
+ }
2671
+ let selectiveFields = requestedFields || typeConfig.selectiveFields;
2672
+ selectiveFields = selectiveFields.filter(
2673
+ (field) => !typeConfig.neverDisclose.includes(field)
2674
+ );
2675
+ return {
2676
+ selectiveFields,
2677
+ mandatoryFields: typeConfig.mandatoryFields,
2678
+ neverDisclose: typeConfig.neverDisclose,
2679
+ decoyCount: typeConfig.decoyFields || 0
2680
+ };
2681
+ }
2682
+ /**
2683
+ * Get default configuration for credential types
2684
+ */
2685
+ getDefaultConfiguration(credentialType, requestedFields) {
2686
+ const defaultConfigs = {
2687
+ [import_ai_identity_types.CredentialType.PROJECT_ACCESS]: {
2688
+ selectiveFields: ["permissions", "projectId"],
2689
+ mandatoryFields: ["role"],
2690
+ neverDisclose: ["privateKey", "secret"]
2691
+ },
2692
+ [import_ai_identity_types.CredentialType.TOOL_ACCESS]: {
2693
+ selectiveFields: ["actions", "tool", "resourceScope"],
2694
+ mandatoryFields: [],
2695
+ neverDisclose: ["privateKey", "secret"]
2696
+ },
2697
+ [import_ai_identity_types.CredentialType.ADMIN]: {
2698
+ selectiveFields: ["adminLevel", "scope"],
2699
+ mandatoryFields: ["authorizedBy"],
2700
+ neverDisclose: ["privateKey", "secret", "internalId"]
2701
+ },
2702
+ [import_ai_identity_types.CredentialType.DEVELOPER]: {
2703
+ selectiveFields: ["skills", "experience", "projects"],
2704
+ mandatoryFields: ["name"],
2705
+ neverDisclose: ["salary", "privateInfo"]
2706
+ },
2707
+ [import_ai_identity_types.CredentialType.TEMPORARY]: {
2708
+ selectiveFields: requestedFields || [],
2709
+ mandatoryFields: [],
2710
+ neverDisclose: ["privateKey", "secret"]
2711
+ },
2712
+ [import_ai_identity_types.CredentialType.RECEIPT]: {
2713
+ selectiveFields: ["action", "resource", "outcome", "amount", "description", "date", "transactionId"],
2714
+ mandatoryFields: ["grantId", "auditEventId", "receiptType"],
2715
+ neverDisclose: ["signature", "privateKey", "secret", "internalReference"]
2716
+ }
2717
+ };
2718
+ const config = defaultConfigs[credentialType] || defaultConfigs[import_ai_identity_types.CredentialType.TEMPORARY];
2719
+ return {
2720
+ selectiveFields: requestedFields || config.selectiveFields || [],
2721
+ mandatoryFields: config.mandatoryFields || [],
2722
+ neverDisclose: config.neverDisclose || [],
2723
+ decoyCount: 0
2724
+ };
2725
+ }
2726
+ /**
2727
+ * Validate disclosure request against organization policy
2728
+ */
2729
+ async validateDisclosureRequest(organizationDid, credentialType, requestedFields) {
2730
+ const config = await this.getSelectiveDisclosureFields(organizationDid, credentialType, requestedFields);
2731
+ const errors = [];
2732
+ const rejectedFields = [];
2733
+ const forbiddenFields = requestedFields.filter(
2734
+ (field) => config.neverDisclose.includes(field)
2735
+ );
2736
+ if (forbiddenFields.length > 0) {
2737
+ rejectedFields.push(...forbiddenFields);
2738
+ errors.push(`Fields not allowed for disclosure: ${forbiddenFields.join(", ")}`);
2739
+ }
2740
+ const allowedFields = requestedFields.filter(
2741
+ (field) => !config.neverDisclose.includes(field)
2742
+ );
2743
+ return {
2744
+ valid: errors.length === 0,
2745
+ allowedFields,
2746
+ rejectedFields,
2747
+ errors
2748
+ };
2749
+ }
2750
+ /**
2751
+ * Get all organization configurations (for admin purposes)
2752
+ */
2753
+ async getAllConfigurations() {
2754
+ return Array.from(this.configs.values());
2755
+ }
2756
+ /**
2757
+ * Delete organization configuration
2758
+ */
2759
+ async deleteOrganizationConfig(organizationDid) {
2760
+ return this.configs.delete(organizationDid);
2761
+ }
2762
+ };
2763
+
2764
+ // src/vc/api-vc-manager.ts
2765
+ var APIVCManager = class {
2766
+ keyManager;
2767
+ disclosureManager;
2768
+ constructor(keyManager, disclosureManager) {
2769
+ this.keyManager = keyManager || new KeyManager();
2770
+ this.disclosureManager = disclosureManager || new DisclosureConfigManager();
2771
+ SDJwtClient.setKeyManager(this.keyManager);
2772
+ }
2773
+ /**
2774
+ * Issue an SD-JWT VC with selective disclosure
2775
+ */
2776
+ async issueSDJWTVC(request) {
2777
+ if (!request.issuer || !request.subject) {
2778
+ throw new Error("Issuer and subject DIDs are required");
2779
+ }
2780
+ const privateKey = await this.keyManager.getKey(request.issuer);
2781
+ if (!privateKey) {
2782
+ throw new Error(`Private key not found for issuer: ${request.issuer}`);
2783
+ }
2784
+ const now = /* @__PURE__ */ new Date();
2785
+ const iat = Math.floor(now.getTime() / 1e3);
2786
+ const expirationDate = request.expirationDate || new Date(now.getTime() + 24 * 60 * 60 * 1e3);
2787
+ const exp = Math.floor(expirationDate.getTime() / 1e3);
2788
+ const vcPayload = {
2789
+ iss: request.issuer,
2790
+ sub: request.subject,
2791
+ iat,
2792
+ exp,
2793
+ vct: request.type || import_ai_identity_types2.CredentialType.TEMPORARY,
2794
+ // IETF SD-JWT VC credential type
2795
+ // Direct claims (can be selectively disclosed)
2796
+ ...request.claims
2797
+ };
2798
+ const disclosureConfig = await this.disclosureManager.getSelectiveDisclosureFields(
2799
+ request.issuer,
2800
+ request.type || import_ai_identity_types2.CredentialType.TEMPORARY,
2801
+ request.selectiveDisclosureFields
2802
+ );
2803
+ const credential = await SDJwtClient.issueSDJWT(
2804
+ vcPayload,
2805
+ privateKey,
2806
+ disclosureConfig.selectiveFields
2807
+ );
2808
+ return {
2809
+ credential,
2810
+ issuer: request.issuer,
2811
+ subject: request.subject,
2812
+ type: request.type || import_ai_identity_types2.CredentialType.TEMPORARY,
2813
+ expiresAt: expirationDate
2814
+ };
2815
+ }
2816
+ /**
2817
+ * Verify an SD-JWT VC
2818
+ */
2819
+ async verifySDJWTVC(credential) {
2820
+ try {
2821
+ if (!credential || typeof credential !== "string") {
2822
+ return {
2823
+ valid: false,
2824
+ error: "Invalid credential format"
2825
+ };
2826
+ }
2827
+ const result = await SDJwtClient.verifySDJWT(credential);
2828
+ if (!result.valid || !result.payload) {
2829
+ return {
2830
+ valid: false,
2831
+ error: result.error || "Verification failed"
2832
+ };
2833
+ }
2834
+ return {
2835
+ valid: true,
2836
+ payload: {
2837
+ iss: result.payload.iss,
2838
+ sub: result.payload.sub,
2839
+ vct: result.payload.vct,
2840
+ exp: result.payload.exp,
2841
+ iat: result.payload.iat,
2842
+ // Include any other claims from the payload
2843
+ ...Object.fromEntries(
2844
+ Object.entries(result.payload).filter(
2845
+ ([key]) => !["iss", "sub", "vct", "exp", "iat"].includes(key)
2846
+ )
2847
+ )
2848
+ }
2849
+ };
2850
+ } catch (error) {
2851
+ return {
2852
+ valid: false,
2853
+ error: `Verification error: ${error instanceof Error ? error.message : "Unknown error"}`
2854
+ };
2855
+ }
2856
+ }
2857
+ /**
2858
+ * Issue a project access credential
2859
+ */
2860
+ async issueProjectAccessCredential(agentDid, projectId, permissions, issuerDid, expirationHours = 24) {
2861
+ const expirationDate = new Date(Date.now() + expirationHours * 60 * 60 * 1e3);
2862
+ return this.issueSDJWTVC({
2863
+ issuer: issuerDid,
2864
+ subject: agentDid,
2865
+ type: import_ai_identity_types2.CredentialType.PROJECT_ACCESS,
2866
+ claims: {
2867
+ projectId,
2868
+ permissions,
2869
+ role: "developer"
2870
+ },
2871
+ expirationDate,
2872
+ projectId,
2873
+ selectiveDisclosureFields: ["permissions"]
2874
+ });
2875
+ }
2876
+ /**
2877
+ * Issue a tool access credential
2878
+ */
2879
+ async issueToolAccessCredential(agentDid, toolName, actions, projectId, issuerDid, expirationHours = 24) {
2880
+ const expirationDate = new Date(Date.now() + expirationHours * 60 * 60 * 1e3);
2881
+ return this.issueSDJWTVC({
2882
+ issuer: issuerDid,
2883
+ subject: agentDid,
2884
+ type: import_ai_identity_types2.CredentialType.TOOL_ACCESS,
2885
+ claims: {
2886
+ tool: toolName,
2887
+ actions,
2888
+ projectId
2889
+ },
2890
+ expirationDate,
2891
+ projectId,
2892
+ selectiveDisclosureFields: ["actions", "tool"]
2893
+ });
2894
+ }
2895
+ /**
2896
+ * Issue a multi-tool access credential
2897
+ */
2898
+ async issueMultiToolCredential(agentDid, toolPermissions, projectId, issuerDid, expirationHours = 24) {
2899
+ const expirationDate = new Date(Date.now() + expirationHours * 60 * 60 * 1e3);
2900
+ return this.issueSDJWTVC({
2901
+ issuer: issuerDid,
2902
+ subject: agentDid,
2903
+ type: import_ai_identity_types2.CredentialType.TOOL_ACCESS,
2904
+ claims: {
2905
+ toolPermissions,
2906
+ projectId
2907
+ },
2908
+ expirationDate,
2909
+ projectId,
2910
+ selectiveDisclosureFields: ["toolPermissions"]
2911
+ });
2912
+ }
2913
+ /**
2914
+ * Issue an admin credential
2915
+ */
2916
+ async issueAdminCredential(agentDid, scope, projectId, issuerDid, expirationHours = 8) {
2917
+ const expirationDate = new Date(Date.now() + expirationHours * 60 * 60 * 1e3);
2918
+ return this.issueSDJWTVC({
2919
+ issuer: issuerDid,
2920
+ subject: agentDid,
2921
+ type: import_ai_identity_types2.CredentialType.ADMIN,
2922
+ claims: {
2923
+ scope,
2924
+ projectId,
2925
+ adminLevel: scope === "global" ? "super" : "project"
2926
+ },
2927
+ expirationDate,
2928
+ projectId,
2929
+ selectiveDisclosureFields: ["adminLevel", "scope"]
2930
+ });
2931
+ }
2932
+ };
2933
+
2934
+ // src/organization/key-rotation-manager.ts
2935
+ var KeyRotationManager = class {
2936
+ keyManager;
2937
+ config;
2938
+ constructor(keyManager, config) {
2939
+ this.keyManager = keyManager;
2940
+ this.config = {
2941
+ rotationInterval: 24 * 30,
2942
+ // 30 days default
2943
+ keepOldKeys: 5,
2944
+ // Keep 5 old keys
2945
+ warningThreshold: 24,
2946
+ // Warn 1 day before
2947
+ ...config
2948
+ };
2949
+ }
2950
+ /**
2951
+ * Check if organization keys need rotation
2952
+ */
2953
+ async checkRotationStatus(organizationDid) {
2954
+ const now = /* @__PURE__ */ new Date();
2955
+ const nextRotationDate = new Date(now.getTime() + this.config.rotationInterval * 60 * 60 * 1e3);
2956
+ return {
2957
+ currentKeyId: organizationDid,
2958
+ nextRotationDate,
2959
+ oldKeys: [],
2960
+ needsRotation: false,
2961
+ warningActive: false
2962
+ };
2963
+ }
2964
+ /**
2965
+ * Rotate organization keys
2966
+ * NOTE: Currently not implemented for did:jwk
2967
+ */
2968
+ async rotateOrganizationKeys(organizationDid) {
2969
+ throw new Error("Key rotation is not supported for did:jwk. Consider using did:web for production environments that require key rotation.");
2970
+ }
2971
+ /**
2972
+ * Get old keys for verification (useful for grace periods)
2973
+ */
2974
+ async getOldKeysForVerification(organizationDid) {
2975
+ return [];
2976
+ }
2977
+ /**
2978
+ * Plan future key rotation (for did:web or other mutable DID methods)
2979
+ */
2980
+ async planKeyRotation(organizationDid) {
2981
+ const now = /* @__PURE__ */ new Date();
2982
+ const plannedRotationDate = new Date(now.getTime() + this.config.rotationInterval * 60 * 60 * 1e3);
2983
+ const currentKeyAge = 0;
2984
+ return {
2985
+ plannedRotationDate,
2986
+ currentKeyAge,
2987
+ recommendedAction: "none"
2988
+ // No rotation needed for did:jwk
2989
+ };
2990
+ }
2991
+ /**
2992
+ * Update rotation configuration
2993
+ */
2994
+ updateConfig(newConfig) {
2995
+ this.config = {
2996
+ ...this.config,
2997
+ ...newConfig
2998
+ };
2999
+ }
3000
+ /**
3001
+ * Get current configuration
3002
+ */
3003
+ getConfig() {
3004
+ return { ...this.config };
3005
+ }
3006
+ };
3007
+
3008
+ // src/monitoring/metrics-manager.ts
3009
+ var MetricsManager = class {
3010
+ metrics = /* @__PURE__ */ new Map();
3011
+ operations = [];
3012
+ maxOperationHistory = 1e3;
3013
+ /**
3014
+ * Start tracking an operation
3015
+ */
3016
+ startOperation(operation, metadata) {
3017
+ const operationId = `${operation}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
3018
+ const startTime = performance.now();
3019
+ this.operations.push({
3020
+ operation,
3021
+ startTime,
3022
+ endTime: 0,
3023
+ success: false,
3024
+ ...metadata
3025
+ });
3026
+ return operationId;
3027
+ }
3028
+ /**
3029
+ * End tracking an operation
3030
+ */
3031
+ endOperation(operationId, success, error) {
3032
+ const endTime = performance.now();
3033
+ const operation = this.operations[this.operations.length - 1];
3034
+ if (operation) {
3035
+ operation.endTime = endTime;
3036
+ operation.success = success;
3037
+ operation.error = error;
3038
+ this.updateMetrics(operation);
3039
+ }
3040
+ if (this.operations.length > this.maxOperationHistory) {
3041
+ this.operations = this.operations.slice(-this.maxOperationHistory);
3042
+ }
3043
+ }
3044
+ /**
3045
+ * Update aggregated metrics
3046
+ */
3047
+ updateMetrics(operation) {
3048
+ const key = operation.issuerDid || "global";
3049
+ let metrics = this.metrics.get(key);
3050
+ if (!metrics) {
3051
+ metrics = {
3052
+ issuanceCount: 0,
3053
+ verificationCount: 0,
3054
+ failedIssuances: 0,
3055
+ failedVerifications: 0,
3056
+ averageIssuanceTime: 0,
3057
+ averageVerificationTime: 0,
3058
+ cacheHitRate: 0,
3059
+ lastActivity: /* @__PURE__ */ new Date()
3060
+ };
3061
+ }
3062
+ const duration = operation.endTime - operation.startTime;
3063
+ if (operation.operation === "issue") {
3064
+ metrics.issuanceCount++;
3065
+ if (!operation.success) {
3066
+ metrics.failedIssuances++;
3067
+ }
3068
+ metrics.averageIssuanceTime = (metrics.averageIssuanceTime * (metrics.issuanceCount - 1) + duration) / metrics.issuanceCount;
3069
+ } else {
3070
+ metrics.verificationCount++;
3071
+ if (!operation.success) {
3072
+ metrics.failedVerifications++;
3073
+ }
3074
+ metrics.averageVerificationTime = (metrics.averageVerificationTime * (metrics.verificationCount - 1) + duration) / metrics.verificationCount;
3075
+ }
3076
+ metrics.lastActivity = /* @__PURE__ */ new Date();
3077
+ this.metrics.set(key, metrics);
3078
+ }
3079
+ /**
3080
+ * Get metrics for a specific issuer or global
3081
+ */
3082
+ getMetrics(issuerDid) {
3083
+ const key = issuerDid || "global";
3084
+ return this.metrics.get(key) || null;
3085
+ }
3086
+ /**
3087
+ * Get all metrics
3088
+ */
3089
+ getAllMetrics() {
3090
+ return new Map(this.metrics);
3091
+ }
3092
+ /**
3093
+ * Get recent operations
3094
+ */
3095
+ getRecentOperations(limit = 100) {
3096
+ return this.operations.slice(-limit);
3097
+ }
3098
+ /**
3099
+ * Get operation statistics
3100
+ */
3101
+ getOperationStats() {
3102
+ const now = Date.now();
3103
+ const oneMinuteAgo = now - 6e4;
3104
+ const recentOps = this.operations.filter((op) => op.startTime > oneMinuteAgo);
3105
+ const successfulOps = this.operations.filter((op) => op.success);
3106
+ const totalDuration = this.operations.reduce((sum, op) => sum + (op.endTime - op.startTime), 0);
3107
+ return {
3108
+ totalOperations: this.operations.length,
3109
+ successRate: this.operations.length > 0 ? successfulOps.length / this.operations.length : 0,
3110
+ averageResponseTime: this.operations.length > 0 ? totalDuration / this.operations.length : 0,
3111
+ operationsPerMinute: recentOps.length
3112
+ };
3113
+ }
3114
+ /**
3115
+ * Update cache hit rate
3116
+ */
3117
+ updateCacheHitRate(issuerDid, hit) {
3118
+ const key = issuerDid || "global";
3119
+ let metrics = this.metrics.get(key);
3120
+ if (!metrics) {
3121
+ metrics = {
3122
+ issuanceCount: 0,
3123
+ verificationCount: 0,
3124
+ failedIssuances: 0,
3125
+ failedVerifications: 0,
3126
+ averageIssuanceTime: 0,
3127
+ averageVerificationTime: 0,
3128
+ cacheHitRate: 0,
3129
+ lastActivity: /* @__PURE__ */ new Date()
3130
+ };
3131
+ }
3132
+ const currentRate = metrics.cacheHitRate;
3133
+ const newRate = hit ? Math.min(1, currentRate + 0.1) : Math.max(0, currentRate - 0.1);
3134
+ metrics.cacheHitRate = newRate;
3135
+ metrics.lastActivity = /* @__PURE__ */ new Date();
3136
+ this.metrics.set(key, metrics);
3137
+ }
3138
+ /**
3139
+ * Reset metrics
3140
+ */
3141
+ resetMetrics(issuerDid) {
3142
+ if (issuerDid) {
3143
+ this.metrics.delete(issuerDid);
3144
+ } else {
3145
+ this.metrics.clear();
3146
+ this.operations = [];
3147
+ }
3148
+ }
3149
+ /**
3150
+ * Export metrics as JSON
3151
+ */
3152
+ exportMetrics() {
3153
+ return {
3154
+ aggregatedMetrics: Object.fromEntries(this.metrics),
3155
+ recentOperations: this.getRecentOperations(50),
3156
+ summary: this.getOperationStats()
3157
+ };
3158
+ }
3159
+ };
3160
+
3161
+ // src/revocation/revocation-manager.ts
3162
+ var RevocationManager = class {
3163
+ revocationLists = /* @__PURE__ */ new Map();
3164
+ credentialStatuses = /* @__PURE__ */ new Map();
3165
+ /**
3166
+ * Create a new revocation list
3167
+ */
3168
+ async createRevocationList(issuer, type = "StatusList2021", purpose = "revocation") {
3169
+ const id = `${issuer}#revocation-list-${Date.now()}`;
3170
+ const now = /* @__PURE__ */ new Date();
3171
+ const revocationList = {
3172
+ id,
3173
+ issuer,
3174
+ type,
3175
+ statusPurpose: purpose,
3176
+ encodedList: this.createEmptyBitString(1e5),
3177
+ // Start with 100k slots
3178
+ entries: [],
3179
+ createdAt: now,
3180
+ updatedAt: now
3181
+ };
3182
+ this.revocationLists.set(id, revocationList);
3183
+ return revocationList;
3184
+ }
3185
+ /**
3186
+ * Add credential to revocation list
3187
+ */
3188
+ async addCredentialToRevocationList(credentialId, listId, statusIndex) {
3189
+ const revocationList = this.revocationLists.get(listId);
3190
+ if (!revocationList) {
3191
+ throw new Error(`Revocation list not found: ${listId}`);
3192
+ }
3193
+ const index = statusIndex ?? this.findNextAvailableIndex(listId);
3194
+ const statusInfo = {
3195
+ id: `${credentialId}#status`,
3196
+ type: "StatusList2021Entry",
3197
+ statusListIndex: index,
3198
+ statusListCredential: listId
3199
+ };
3200
+ this.credentialStatuses.set(credentialId, statusInfo);
3201
+ return statusInfo;
3202
+ }
3203
+ /**
3204
+ * Revoke a credential
3205
+ */
3206
+ async revokeCredential(credentialId, reason, revokedBy) {
3207
+ const statusInfo = this.credentialStatuses.get(credentialId);
3208
+ if (!statusInfo) {
3209
+ throw new Error(`Credential not found in revocation tracking: ${credentialId}`);
3210
+ }
3211
+ const revocationList = this.revocationLists.get(statusInfo.statusListCredential);
3212
+ if (!revocationList) {
3213
+ throw new Error(`Revocation list not found: ${statusInfo.statusListCredential}`);
3214
+ }
3215
+ const updatedBitString = this.setBitInString(
3216
+ revocationList.encodedList,
3217
+ statusInfo.statusListIndex,
3218
+ true
3219
+ );
3220
+ const revocationEntry = {
3221
+ credentialId,
3222
+ revocationDate: /* @__PURE__ */ new Date(),
3223
+ reason,
3224
+ revokedBy: revokedBy || "system"
3225
+ };
3226
+ revocationList.encodedList = updatedBitString;
3227
+ revocationList.entries.push(revocationEntry);
3228
+ revocationList.updatedAt = /* @__PURE__ */ new Date();
3229
+ statusInfo.revocationReason = reason;
3230
+ statusInfo.revocationDate = /* @__PURE__ */ new Date();
3231
+ this.revocationLists.set(revocationList.id, revocationList);
3232
+ this.credentialStatuses.set(credentialId, statusInfo);
3233
+ return true;
3234
+ }
3235
+ /**
3236
+ * Check if credential is revoked
3237
+ */
3238
+ async isCredentialRevoked(credentialId) {
3239
+ const statusInfo = this.credentialStatuses.get(credentialId);
3240
+ if (!statusInfo) {
3241
+ return { revoked: false };
3242
+ }
3243
+ const revocationList = this.revocationLists.get(statusInfo.statusListCredential);
3244
+ if (!revocationList) {
3245
+ return { revoked: false };
3246
+ }
3247
+ const isRevoked = this.getBitFromString(
3248
+ revocationList.encodedList,
3249
+ statusInfo.statusListIndex
3250
+ );
3251
+ if (!isRevoked) {
3252
+ return { revoked: false };
3253
+ }
3254
+ const entry = revocationList.entries.find((e) => e.credentialId === credentialId);
3255
+ return {
3256
+ revoked: true,
3257
+ reason: entry?.reason,
3258
+ revokedDate: entry?.revocationDate,
3259
+ revokedBy: entry?.revokedBy
3260
+ };
3261
+ }
3262
+ /**
3263
+ * Get credential status info
3264
+ */
3265
+ async getCredentialStatus(credentialId) {
3266
+ return this.credentialStatuses.get(credentialId) || null;
3267
+ }
3268
+ /**
3269
+ * Get revocation list
3270
+ */
3271
+ async getRevocationList(listId) {
3272
+ return this.revocationLists.get(listId) || null;
3273
+ }
3274
+ /**
3275
+ * Get all revocation lists for an issuer
3276
+ */
3277
+ async getIssuerRevocationLists(issuer) {
3278
+ return Array.from(this.revocationLists.values()).filter((list) => list.issuer === issuer);
3279
+ }
3280
+ /**
3281
+ * Restore/unreovke a credential
3282
+ */
3283
+ async restoreCredential(credentialId) {
3284
+ const statusInfo = this.credentialStatuses.get(credentialId);
3285
+ if (!statusInfo) {
3286
+ throw new Error(`Credential not found in revocation tracking: ${credentialId}`);
3287
+ }
3288
+ const revocationList = this.revocationLists.get(statusInfo.statusListCredential);
3289
+ if (!revocationList) {
3290
+ throw new Error(`Revocation list not found: ${statusInfo.statusListCredential}`);
3291
+ }
3292
+ const updatedBitString = this.setBitInString(
3293
+ revocationList.encodedList,
3294
+ statusInfo.statusListIndex,
3295
+ false
3296
+ );
3297
+ revocationList.encodedList = updatedBitString;
3298
+ revocationList.updatedAt = /* @__PURE__ */ new Date();
3299
+ delete statusInfo.revocationReason;
3300
+ delete statusInfo.revocationDate;
3301
+ this.revocationLists.set(revocationList.id, revocationList);
3302
+ this.credentialStatuses.set(credentialId, statusInfo);
3303
+ return true;
3304
+ }
3305
+ /**
3306
+ * Create empty bit string
3307
+ */
3308
+ createEmptyBitString(size) {
3309
+ const bytes = Math.ceil(size / 8);
3310
+ const buffer = Buffer.alloc(bytes, 0);
3311
+ return buffer.toString("base64");
3312
+ }
3313
+ /**
3314
+ * Set bit in encoded string
3315
+ */
3316
+ setBitInString(encodedString, index, value) {
3317
+ const buffer = Buffer.from(encodedString, "base64");
3318
+ const byteIndex = Math.floor(index / 8);
3319
+ const bitIndex = index % 8;
3320
+ if (byteIndex >= buffer.length) {
3321
+ throw new Error(`Bit index ${index} is out of bounds for buffer of size ${buffer.length * 8}`);
3322
+ }
3323
+ if (value) {
3324
+ buffer[byteIndex] |= 1 << 7 - bitIndex;
3325
+ } else {
3326
+ buffer[byteIndex] &= ~(1 << 7 - bitIndex);
3327
+ }
3328
+ return buffer.toString("base64");
3329
+ }
3330
+ /**
3331
+ * Get bit from encoded string
3332
+ */
3333
+ getBitFromString(encodedString, index) {
3334
+ const buffer = Buffer.from(encodedString, "base64");
3335
+ const byteIndex = Math.floor(index / 8);
3336
+ const bitIndex = index % 8;
3337
+ if (byteIndex >= buffer.length) {
3338
+ return false;
3339
+ }
3340
+ return (buffer[byteIndex] & 1 << 7 - bitIndex) !== 0;
3341
+ }
3342
+ /**
3343
+ * Find next available index in revocation list
3344
+ */
3345
+ findNextAvailableIndex(listId) {
3346
+ const usedIndices = Array.from(this.credentialStatuses.values()).filter((status) => status.statusListCredential === listId).map((status) => status.statusListIndex);
3347
+ let index = 0;
3348
+ while (usedIndices.includes(index)) {
3349
+ index++;
3350
+ }
3351
+ return index;
3352
+ }
3353
+ /**
3354
+ * Export revocation list in standard format
3355
+ */
3356
+ async exportRevocationList(listId) {
3357
+ const list = this.revocationLists.get(listId);
3358
+ if (!list) {
3359
+ return null;
3360
+ }
3361
+ return {
3362
+ "@context": [
3363
+ "https://www.w3.org/2018/credentials/v1",
3364
+ "https://w3id.org/vc/status-list/2021/v1"
3365
+ ],
3366
+ id: list.id,
3367
+ type: ["VerifiableCredential", "StatusList2021Credential"],
3368
+ issuer: list.issuer,
3369
+ validFrom: list.createdAt.toISOString(),
3370
+ credentialSubject: {
3371
+ id: `${list.id}#list`,
3372
+ type: list.type,
3373
+ statusPurpose: list.statusPurpose,
3374
+ encodedList: list.encodedList
3375
+ }
3376
+ };
3377
+ }
3378
+ };
3379
+
3380
+ // src/constraint/constraint-evaluator.ts
3381
+ var DEFAULT_OPTIONS = {
3382
+ invocationWarningThreshold: 5,
3383
+ riskWarningRatio: 0.8,
3384
+ defaultTimezone: "UTC"
3385
+ };
3386
+ var ConstraintEvaluator = class {
3387
+ options;
3388
+ constructor(options) {
3389
+ this.options = { ...DEFAULT_OPTIONS, ...options };
3390
+ }
3391
+ /**
3392
+ * 制約を総合評価
3393
+ */
3394
+ evaluate(constraints, context, currentInvocations, expiresAt) {
3395
+ const violations = [];
3396
+ const warnings = [];
3397
+ const expirationResult = this.checkExpiration(expiresAt, constraints.expiresAt);
3398
+ if (expirationResult.violation) {
3399
+ violations.push(expirationResult.violation);
3400
+ }
3401
+ const invocationResult = this.checkInvocationLimit(
3402
+ constraints.maxInvocations,
3403
+ currentInvocations
3404
+ );
3405
+ if (invocationResult.violation) {
3406
+ violations.push(invocationResult.violation);
3407
+ }
3408
+ if (invocationResult.warning) {
3409
+ warnings.push(invocationResult.warning);
3410
+ }
3411
+ if (constraints.timeWindow) {
3412
+ const timeResult = this.checkTimeWindow(
3413
+ constraints.timeWindow,
3414
+ new Date(context.timestamp)
3415
+ );
3416
+ if (timeResult.violation) {
3417
+ violations.push(timeResult.violation);
3418
+ }
3419
+ if (timeResult.warning) {
3420
+ warnings.push(timeResult.warning);
3421
+ }
3422
+ }
3423
+ if (constraints.ipAllowlist && constraints.ipAllowlist.length > 0 && context.ipAddress) {
3424
+ const ipResult = this.checkIpAllowlist(constraints.ipAllowlist, context.ipAddress);
3425
+ if (ipResult.violation) {
3426
+ violations.push(ipResult.violation);
3427
+ }
3428
+ }
3429
+ if (constraints.riskThreshold !== void 0 && context.riskScore !== void 0) {
3430
+ const riskResult = this.checkRiskThreshold(constraints.riskThreshold, context.riskScore);
3431
+ if (riskResult.violation) {
3432
+ violations.push(riskResult.violation);
3433
+ }
3434
+ if (riskResult.warning) {
3435
+ warnings.push(riskResult.warning);
3436
+ }
3437
+ }
3438
+ return {
3439
+ allowed: violations.length === 0,
3440
+ violations,
3441
+ warnings,
3442
+ evaluatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3443
+ context
3444
+ };
3445
+ }
3446
+ /**
3447
+ * 期限チェック
3448
+ */
3449
+ checkExpiration(grantExpiresAt, constraintExpiresAt) {
3450
+ const now = /* @__PURE__ */ new Date();
3451
+ if (grantExpiresAt && new Date(grantExpiresAt) < now) {
3452
+ return {
3453
+ violation: {
3454
+ type: "expired",
3455
+ message: `Grant expired at ${grantExpiresAt.toISOString()}`,
3456
+ details: { expiresAt: grantExpiresAt.toISOString(), now: now.toISOString() }
3457
+ }
3458
+ };
3459
+ }
3460
+ if (constraintExpiresAt && new Date(constraintExpiresAt) < now) {
3461
+ return {
3462
+ violation: {
3463
+ type: "expired",
3464
+ message: `Constraint expired at ${constraintExpiresAt}`,
3465
+ details: { expiresAt: constraintExpiresAt, now: now.toISOString() }
3466
+ }
3467
+ };
3468
+ }
3469
+ return {};
3470
+ }
3471
+ /**
3472
+ * 実行回数チェック
3473
+ */
3474
+ checkInvocationLimit(maxInvocations, currentInvocations) {
3475
+ if (maxInvocations === void 0 || currentInvocations === void 0) {
3476
+ return {};
3477
+ }
3478
+ const remaining = maxInvocations - currentInvocations;
3479
+ if (remaining <= 0) {
3480
+ return {
3481
+ violation: {
3482
+ type: "max_invocations",
3483
+ message: `Invocation limit reached (${maxInvocations} max, ${currentInvocations} used)`,
3484
+ details: { maxInvocations, currentInvocations, remaining: 0 }
3485
+ }
3486
+ };
3487
+ }
3488
+ if (remaining <= this.options.invocationWarningThreshold) {
3489
+ return {
3490
+ warning: {
3491
+ type: "approaching_limit",
3492
+ message: `Only ${remaining} invocations remaining out of ${maxInvocations}`,
3493
+ details: { maxInvocations, currentInvocations, remaining }
3494
+ }
3495
+ };
3496
+ }
3497
+ return {};
3498
+ }
3499
+ /**
3500
+ * 時間帯チェック
3501
+ */
3502
+ checkTimeWindow(timeWindow, currentTime) {
3503
+ const timezone = timeWindow.timezone || this.options.defaultTimezone;
3504
+ if (timeWindow.daysOfWeek && timeWindow.daysOfWeek.length > 0) {
3505
+ const currentDay = this.getDayOfWeekInTimezone(currentTime, timezone);
3506
+ if (!timeWindow.daysOfWeek.includes(currentDay)) {
3507
+ return {
3508
+ violation: {
3509
+ type: "time_window",
3510
+ message: `Current day (${this.getDayName(currentDay)}) is not in allowed days`,
3511
+ details: {
3512
+ currentDay,
3513
+ allowedDays: timeWindow.daysOfWeek,
3514
+ allowedDayNames: timeWindow.daysOfWeek.map((d) => this.getDayName(d))
3515
+ }
3516
+ }
3517
+ };
3518
+ }
3519
+ }
3520
+ if (timeWindow.start && timeWindow.end) {
3521
+ const currentTimeStr = this.getTimeInTimezone(currentTime, timezone);
3522
+ if (timeWindow.start <= timeWindow.end) {
3523
+ if (currentTimeStr < timeWindow.start || currentTimeStr > timeWindow.end) {
3524
+ return {
3525
+ violation: {
3526
+ type: "time_window",
3527
+ message: `Current time (${currentTimeStr}) is outside allowed window (${timeWindow.start}-${timeWindow.end})`,
3528
+ details: { currentTime: currentTimeStr, start: timeWindow.start, end: timeWindow.end, timezone }
3529
+ }
3530
+ };
3531
+ }
3532
+ } else {
3533
+ if (currentTimeStr < timeWindow.start && currentTimeStr > timeWindow.end) {
3534
+ return {
3535
+ violation: {
3536
+ type: "time_window",
3537
+ message: `Current time (${currentTimeStr}) is outside allowed window (${timeWindow.start}-${timeWindow.end})`,
3538
+ details: { currentTime: currentTimeStr, start: timeWindow.start, end: timeWindow.end, timezone }
3539
+ }
3540
+ };
3541
+ }
3542
+ }
3543
+ const endMinutes = this.timeToMinutes(timeWindow.end);
3544
+ const currentMinutes = this.timeToMinutes(currentTimeStr);
3545
+ const minutesUntilEnd = endMinutes - currentMinutes;
3546
+ if (minutesUntilEnd > 0 && minutesUntilEnd <= 60) {
3547
+ return {
3548
+ warning: {
3549
+ type: "unusual_time",
3550
+ message: `Only ${minutesUntilEnd} minutes remaining in allowed time window`,
3551
+ details: { minutesUntilEnd, windowEnd: timeWindow.end }
3552
+ }
3553
+ };
3554
+ }
3555
+ }
3556
+ return {};
3557
+ }
3558
+ /**
3559
+ * IPアドレスチェック
3560
+ */
3561
+ checkIpAllowlist(allowlist, ipAddress) {
3562
+ if (allowlist.includes("*")) {
3563
+ return {};
3564
+ }
3565
+ if (allowlist.includes(ipAddress)) {
3566
+ return {};
3567
+ }
3568
+ for (const entry of allowlist) {
3569
+ if (entry.includes("/")) {
3570
+ if (this.isIpInCidr(ipAddress, entry)) {
3571
+ return {};
3572
+ }
3573
+ }
3574
+ }
3575
+ return {
3576
+ violation: {
3577
+ type: "ip_allowlist",
3578
+ message: `IP address ${ipAddress} is not in the allowlist`,
3579
+ details: { ipAddress, allowlist }
3580
+ }
3581
+ };
3582
+ }
3583
+ /**
3584
+ * リスクスコアチェック
3585
+ */
3586
+ checkRiskThreshold(threshold, currentScore) {
3587
+ if (currentScore > threshold) {
3588
+ return {
3589
+ violation: {
3590
+ type: "risk_threshold",
3591
+ message: `Risk score ${currentScore} exceeds threshold ${threshold}`,
3592
+ details: { currentScore, threshold }
3593
+ }
3594
+ };
3595
+ }
3596
+ const warningThreshold = threshold * this.options.riskWarningRatio;
3597
+ if (currentScore > warningThreshold) {
3598
+ return {
3599
+ warning: {
3600
+ type: "high_risk",
3601
+ message: `Risk score ${currentScore} is approaching threshold ${threshold}`,
3602
+ details: { currentScore, threshold, warningThreshold }
3603
+ }
3604
+ };
3605
+ }
3606
+ return {};
3607
+ }
3608
+ // ============================================================================
3609
+ // Helper Methods
3610
+ // ============================================================================
3611
+ getDayOfWeekInTimezone(date, timezone) {
3612
+ try {
3613
+ const options = { weekday: "short", timeZone: timezone };
3614
+ const dayStr = date.toLocaleDateString("en-US", options);
3615
+ const dayMap = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 };
3616
+ return dayMap[dayStr] ?? date.getDay();
3617
+ } catch {
3618
+ return date.getDay();
3619
+ }
3620
+ }
3621
+ getTimeInTimezone(date, timezone) {
3622
+ try {
3623
+ const options = {
3624
+ hour: "2-digit",
3625
+ minute: "2-digit",
3626
+ hour12: false,
3627
+ timeZone: timezone
3628
+ };
3629
+ return date.toLocaleTimeString("en-US", options);
3630
+ } catch {
3631
+ return date.toISOString().slice(11, 16);
3632
+ }
3633
+ }
3634
+ getDayName(day) {
3635
+ const names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
3636
+ return names[day] || "Unknown";
3637
+ }
3638
+ timeToMinutes(time) {
3639
+ const [hours, minutes] = time.split(":").map(Number);
3640
+ return hours * 60 + minutes;
3641
+ }
3642
+ isIpInCidr(ip, cidr) {
3643
+ try {
3644
+ const [range, bits] = cidr.split("/");
3645
+ const mask = parseInt(bits, 10);
3646
+ const ipNum = this.ipToNumber(ip);
3647
+ const rangeNum = this.ipToNumber(range);
3648
+ const maskNum = ~(2 ** (32 - mask) - 1);
3649
+ return (ipNum & maskNum) === (rangeNum & maskNum);
3650
+ } catch {
3651
+ return false;
3652
+ }
3653
+ }
3654
+ ipToNumber(ip) {
3655
+ const parts = ip.split(".").map(Number);
3656
+ return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3];
3657
+ }
3658
+ };
3659
+ var defaultConstraintEvaluator = new ConstraintEvaluator();
3660
+ function evaluateConstraints(constraints, context, currentInvocations, expiresAt) {
3661
+ return defaultConstraintEvaluator.evaluate(constraints, context, currentInvocations, expiresAt);
3662
+ }
3663
+
3664
+ // src/registry/action-registry.ts
3665
+ var import_ajv = __toESM(require("ajv"));
3666
+ var import_ajv_formats = __toESM(require("ajv-formats"));
3667
+ var import_promises = __toESM(require("fs/promises"));
3668
+ var import_node_path = __toESM(require("path"));
3669
+ var actionMetaSchema = {
3670
+ $id: "https://vess.ai/schemas/action-meta.json",
3671
+ type: "object",
3672
+ additionalProperties: false,
3673
+ required: ["action", "resource_type", "required_relations", "required_scopes", "version"],
3674
+ properties: {
3675
+ action: { type: "string", minLength: 1 },
3676
+ resource_type: {
3677
+ type: "string",
3678
+ enum: ["SlackChannel", "GitHubRepo", "DriveFile"]
3679
+ },
3680
+ required_relations: {
3681
+ type: "array",
3682
+ minItems: 1,
3683
+ items: {
3684
+ type: "string",
3685
+ enum: ["viewer", "editor", "admin", "owner", "act_as"]
3686
+ }
3687
+ },
3688
+ required_scopes: {
3689
+ type: "array",
3690
+ minItems: 1,
3691
+ items: { type: "string", minLength: 1 }
3692
+ },
3693
+ capability: { type: "string" },
3694
+ input_schema: { type: "object" },
3695
+ // ← ここは後段で「JSON Schemaとして」別検証
3696
+ constraints: { type: "object", additionalProperties: true },
3697
+ effects: {
3698
+ type: "array",
3699
+ items: { type: "string", minLength: 1 }
3700
+ },
3701
+ risk: { type: "string", enum: ["low", "medium", "high"] },
3702
+ version: { type: "string", minLength: 1 }
3703
+ }
3704
+ };
3705
+ var capabilityMetaSchema = {
3706
+ $id: "https://vess.ai/schemas/capability-meta.json",
3707
+ type: "object",
3708
+ additionalProperties: false,
3709
+ required: ["capability", "includes", "version"],
3710
+ properties: {
3711
+ capability: { type: "string", minLength: 1 },
3712
+ description: { type: "string" },
3713
+ includes: {
3714
+ type: "array",
3715
+ minItems: 1,
3716
+ items: { type: "string", minLength: 1 }
3717
+ },
3718
+ version: { type: "string", minLength: 1 }
3719
+ }
3720
+ };
3721
+ var registrySchema = {
3722
+ $id: "https://vess.ai/schemas/action-registry.json",
3723
+ type: "object",
3724
+ additionalProperties: false,
3725
+ required: ["registry_version", "actions"],
3726
+ properties: {
3727
+ registry_version: { type: "string", minLength: 1 },
3728
+ actions: {
3729
+ type: "array",
3730
+ minItems: 1,
3731
+ items: { $ref: "https://vess.ai/schemas/action-meta.json" }
3732
+ },
3733
+ capabilities: {
3734
+ type: "array",
3735
+ items: { $ref: "https://vess.ai/schemas/capability-meta.json" }
3736
+ }
3737
+ }
3738
+ };
3739
+ function createAjv() {
3740
+ const ajv = new import_ajv.default({
3741
+ allErrors: true,
3742
+ strict: true,
3743
+ allowUnionTypes: true
3744
+ // draft-2020-12 デフォルト。input_schema のメタ検証に使う。
3745
+ });
3746
+ (0, import_ajv_formats.default)(ajv);
3747
+ ajv.addSchema(actionMetaSchema);
3748
+ ajv.addSchema(capabilityMetaSchema);
3749
+ ajv.addSchema(registrySchema);
3750
+ return ajv;
3751
+ }
3752
+ function validateRegistryObject(registry) {
3753
+ const ajv = createAjv();
3754
+ const validate = ajv.getSchema("https://vess.ai/schemas/action-registry.json");
3755
+ if (!validate) {
3756
+ return { ok: false, errors: ["Ajv schema not loaded"] };
3757
+ }
3758
+ const valid = validate(registry);
3759
+ if (!valid) {
3760
+ return {
3761
+ ok: false,
3762
+ errors: validate.errors ? formatAjvErrors(validate.errors) : []
3763
+ };
3764
+ }
3765
+ const typed = registry;
3766
+ const schemaErrors = [];
3767
+ for (const a of typed.actions) {
3768
+ if (a.input_schema) {
3769
+ try {
3770
+ const local = new import_ajv.default({ strict: true, allErrors: true });
3771
+ (0, import_ajv_formats.default)(local);
3772
+ const compiled = local.compile(a.input_schema);
3773
+ if (compiled.errors?.length) {
3774
+ schemaErrors.push(
3775
+ `[${a.action}] input_schema errors: ${formatAjvErrors(
3776
+ compiled.errors
3777
+ ).join("; ")}`
3778
+ );
3779
+ }
3780
+ } catch (e) {
3781
+ schemaErrors.push(`[${a.action}] input_schema invalid: ${e?.message ?? String(e)}`);
3782
+ }
3783
+ }
3784
+ }
3785
+ if (schemaErrors.length) {
3786
+ return { ok: false, errors: schemaErrors };
3787
+ }
3788
+ if (typed.capabilities?.length) {
3789
+ const actionsSet = new Set(typed.actions.map((x) => x.action));
3790
+ for (const c of typed.capabilities) {
3791
+ for (const act of c.includes) {
3792
+ if (!actionsSet.has(act)) {
3793
+ schemaErrors.push(`[capability:${c.capability}] includes unknown action: ${act}`);
3794
+ }
3795
+ }
3796
+ }
3797
+ }
3798
+ if (schemaErrors.length) {
3799
+ return { ok: false, errors: schemaErrors };
3800
+ }
3801
+ return { ok: true };
3802
+ }
3803
+ function formatAjvErrors(errors) {
3804
+ if (!errors?.length) return [];
3805
+ return errors.map((e) => {
3806
+ const instancePath = e.instancePath || "/";
3807
+ const msg = e.message || "invalid";
3808
+ const params = e.params && Object.keys(e.params).length ? ` (${JSON.stringify(e.params)})` : "";
3809
+ return `${instancePath}: ${msg}${params}`;
3810
+ });
3811
+ }
3812
+ async function loadActionRegistryFromFile(filePath) {
3813
+ const abs = import_node_path.default.resolve(filePath);
3814
+ const raw = await import_promises.default.readFile(abs, "utf8");
3815
+ const json = JSON.parse(raw);
3816
+ const result = validateRegistryObject(json);
3817
+ if (!result.ok) {
3818
+ const errs = result.errors?.join("\n - ") || "";
3819
+ throw new Error(`ActionRegistry validation failed:
3820
+ - ${errs}`);
3821
+ }
3822
+ return json;
3823
+ }
3824
+ function loadActionRegistryFromObject(obj) {
3825
+ const result = validateRegistryObject(obj);
3826
+ if (!result.ok) {
3827
+ const errs = result.errors?.join("\n - ") || "";
3828
+ throw new Error(`ActionRegistry validation failed:
3829
+ - ${errs}`);
3830
+ }
3831
+ return obj;
3832
+ }
3833
+ function indexActions(reg) {
3834
+ const map = /* @__PURE__ */ new Map();
3835
+ for (const a of reg.actions) map.set(a.action, a);
3836
+ return map;
3837
+ }
3838
+ function indexCapabilities(reg) {
3839
+ const map = /* @__PURE__ */ new Map();
3840
+ for (const c of reg.capabilities ?? []) map.set(c.capability, c);
3841
+ return map;
3842
+ }
3843
+ function getRequiredScopes(regIndex, action) {
3844
+ return regIndex.get(action)?.required_scopes ?? [];
3845
+ }
3846
+ function getRequiredRelations(regIndex, action) {
3847
+ return regIndex.get(action)?.required_relations ?? [];
3848
+ }
3849
+
3850
+ // src/registry/access-orchestrator.ts
3851
+ function resolveActionsFromSelection(registry, selection) {
3852
+ const aIndex = indexActions(registry);
3853
+ const cIndex = indexCapabilities(registry);
3854
+ const out = /* @__PURE__ */ new Set();
3855
+ for (const item of selection) {
3856
+ if (aIndex.has(item)) {
3857
+ out.add(item);
3858
+ continue;
3859
+ }
3860
+ const cap = cIndex.get(item);
3861
+ if (cap) {
3862
+ for (const act of cap.includes) out.add(act);
3863
+ continue;
3864
+ }
3865
+ }
3866
+ return [...out];
3867
+ }
3868
+ async function planDelegationForVC(input) {
3869
+ const {
3870
+ registry,
3871
+ issuerUserDid,
3872
+ requested,
3873
+ resourceScope,
3874
+ rebac,
3875
+ abac,
3876
+ creds,
3877
+ providerByIa = {},
3878
+ context
3879
+ } = input;
3880
+ const requestedActions = resolveActionsFromSelection(registry, requested);
3881
+ const aIndex = indexActions(registry);
3882
+ const granted = [];
3883
+ const rejected = [];
3884
+ const traceByAction = {};
3885
+ const resourceScopes = resourceScope.filter((s) => s.kind === "Resource");
3886
+ for (const action of requestedActions) {
3887
+ const meta = aIndex.get(action);
3888
+ const t = {};
3889
+ traceByAction[action] = t;
3890
+ if (!meta) {
3891
+ rejected.push(action);
3892
+ continue;
3893
+ }
3894
+ if (resourceScopes.length) {
3895
+ let rebacOk = false;
3896
+ for (const rs of resourceScopes) {
3897
+ const rels = getRequiredRelations(aIndex, action);
3898
+ const ok = await rebac.check(
3899
+ issuerUserDid,
3900
+ rels.length ? rels : ["owner", "admin", "editor", "viewer"],
3901
+ {
3902
+ id: rs.id,
3903
+ type: rs.type,
3904
+ iaId: ""
3905
+ // 発行時点では空でもOK。持っているなら入れる。
3906
+ }
3907
+ );
3908
+ if (ok) {
3909
+ rebacOk = true;
3910
+ break;
3911
+ }
3912
+ }
3913
+ t.rebac = { ok: rebacOk, relations: getRequiredRelations(aIndex, action) };
3914
+ if (!rebacOk) {
3915
+ rejected.push(action);
3916
+ continue;
3917
+ }
3918
+ }
3919
+ const abacDec = await abac.evaluate({
3920
+ principal: { id: issuerUserDid, roles: ["user"] },
3921
+ resource: {
3922
+ kind: resourceScopes[0]?.type ?? meta.resource_type,
3923
+ id: resourceScopes[0]?.id ?? "SCOPE_ONLY",
3924
+ attr: {}
3925
+ },
3926
+ action,
3927
+ context
3928
+ });
3929
+ t.abac = { ok: abacDec.allow, ruleId: abacDec.ruleId, reason: abacDec.reason };
3930
+ if (!abacDec.allow) {
3931
+ rejected.push(action);
3932
+ continue;
3933
+ }
3934
+ let scopeOk = true;
3935
+ const required = getRequiredScopes(aIndex, action);
3936
+ if (resourceScopes.length && required.length) {
3937
+ scopeOk = false;
3938
+ for (const rs of resourceScopes) {
3939
+ const provider = inferProviderByResourceType(rs.type);
3940
+ const cred = await creds.pickMinimal(provider, "", required, issuerUserDid);
3941
+ if (cred) {
3942
+ scopeOk = true;
3943
+ break;
3944
+ }
3945
+ }
3946
+ }
3947
+ t.scope = { ok: scopeOk, required };
3948
+ if (!scopeOk) {
3949
+ rejected.push(action);
3950
+ continue;
3951
+ }
3952
+ granted.push(action);
3953
+ }
3954
+ return { granted_actions: granted, rejected_actions: rejected, traceByAction };
3955
+ }
3956
+ function inferProviderByResourceType(rt) {
3957
+ switch (rt) {
3958
+ case "SlackChannel":
3959
+ return "slack";
3960
+ case "GitHubRepo":
3961
+ return "github";
3962
+ case "DriveFile":
3963
+ return "google";
3964
+ }
3965
+ }
3966
+ async function checkPermissionWithVP(input) {
3967
+ const { registry, actorDid, action, resource, vpToken, context, rebac, abac, creds, vpVerifier } = input;
3968
+ const aIndex = indexActions(registry);
3969
+ const meta = aIndex.get(action);
3970
+ if (!meta) {
3971
+ return { allow: false, reason: "unknown_action", trace: {} };
3972
+ }
3973
+ const trace = {};
3974
+ const rels = getRequiredRelations(aIndex, action);
3975
+ const rebacOk = await rebac.check(actorDid, rels.length ? rels : ["viewer"], resource);
3976
+ trace.rebac = { ok: rebacOk, relations: rels };
3977
+ if (!rebacOk) {
3978
+ return { allow: false, reason: "rebac_denied", trace };
3979
+ }
3980
+ const vc = await vpVerifier.verifyAndExtractClaims(vpToken);
3981
+ let matchedAction = vc.allowed_actions?.includes(action) ?? false;
3982
+ let inScope = isResourceInScopes(resource, vc.resource_scope || []);
3983
+ const notExpired = !vc.expires_at || new Date(vc.expires_at).getTime() > Date.now();
3984
+ trace.delegation = {
3985
+ ok: matchedAction && inScope && notExpired,
3986
+ matched_action: matchedAction,
3987
+ in_scope: inScope,
3988
+ notExpired
3989
+ };
3990
+ if (!trace.delegation.ok) {
3991
+ return { allow: false, reason: "delegation_denied", trace };
3992
+ }
3993
+ const abacDec = await abac.evaluate({
3994
+ principal: {
3995
+ id: actorDid,
3996
+ roles: ["agent"],
3997
+ claims: {
3998
+ assurance_level: vc.assurance_level,
3999
+ actor: vc.actor
4000
+ }
4001
+ },
4002
+ resource: {
4003
+ kind: resource.type,
4004
+ id: resource.id,
4005
+ attr: resource.attr || {}
4006
+ },
4007
+ action,
4008
+ context
4009
+ });
4010
+ trace.abac = { ok: abacDec.allow, ruleId: abacDec.ruleId, reason: abacDec.reason };
4011
+ if (!abacDec.allow) {
4012
+ return { allow: false, reason: "abac_denied", trace };
4013
+ }
4014
+ const provider = inferProviderByResourceType(resource.type);
4015
+ const requiredScopes = getRequiredScopes(aIndex, action);
4016
+ const cred = await creds.pickMinimal(provider, resource.iaId, requiredScopes, actorDid);
4017
+ trace.scope = {
4018
+ ok: !!cred,
4019
+ required: requiredScopes,
4020
+ chosenCredentialId: cred?.id
4021
+ };
4022
+ if (!cred) {
4023
+ return { allow: false, reason: "insufficient_scopes", trace, credential: null };
4024
+ }
4025
+ return { allow: true, trace, credential: cred };
4026
+ }
4027
+ function isResourceInScopes(resource, scopes) {
4028
+ for (const s of scopes) {
4029
+ if (s.kind === "Resource") {
4030
+ if (s.type === resource.type && s.id === resource.id) return true;
4031
+ } else if (s.kind === "IntegrationAccount") {
4032
+ if (s.id === resource.iaId) return true;
4033
+ } else if (s.kind === "Workspace") {
4034
+ return true;
4035
+ }
4036
+ }
4037
+ return false;
4038
+ }
4039
+ var AllowAllAbac = class {
4040
+ async evaluate() {
4041
+ return { allow: true, ruleId: "allow_all" };
4042
+ }
4043
+ };
4044
+ var SimpleRebac = class {
4045
+ constructor(allowRelations = ["viewer", "editor", "admin", "owner", "act_as"]) {
4046
+ this.allowRelations = allowRelations;
4047
+ }
4048
+ async check(_sub, relations) {
4049
+ return relations.some((r) => this.allowRelations.includes(r));
4050
+ }
4051
+ };
4052
+ var DummyCreds = class {
4053
+ async pickMinimal(provider, _iaId, requiredScopes) {
4054
+ if (!requiredScopes.length) return { id: `${provider}-none`, provider, scopes: [] };
4055
+ return { id: `${provider}-demo`, provider, scopes: requiredScopes };
4056
+ }
4057
+ };
4058
+ var DummyVpVerifier = class {
4059
+ constructor(vc) {
4060
+ this.vc = vc;
4061
+ }
4062
+ async verifyAndExtractClaims() {
4063
+ return this.vc;
4064
+ }
4065
+ };
4066
+
4067
+ // src/registry/action-registry-json.ts
4068
+ var ACTION_REGISTRY = {
4069
+ registry_version: "2025-09-28",
4070
+ actions: [
4071
+ {
4072
+ action: "slack:channel.post_message",
4073
+ resource_type: "SlackChannel",
4074
+ required_relations: ["editor", "act_as"],
4075
+ required_scopes: ["chat:write"],
4076
+ capability: "slack.messaging.basic",
4077
+ input_schema: {
4078
+ type: "object",
4079
+ properties: {
4080
+ text: { type: "string", minLength: 1, maxLength: 4e4 },
4081
+ thread_ts: { type: "string" },
4082
+ attachments: { type: "array" }
4083
+ },
4084
+ required: ["text"],
4085
+ additionalProperties: false
4086
+ },
4087
+ constraints: { rate_bucket: "slack.post" },
4088
+ effects: ["Create:Message"],
4089
+ risk: "low",
4090
+ version: "1.0.0"
4091
+ },
4092
+ {
4093
+ action: "slack:channel.read",
4094
+ resource_type: "SlackChannel",
4095
+ required_relations: ["viewer", "editor", "admin", "owner"],
4096
+ required_scopes: ["channels:history", "groups:history", "im:history", "mpim:history"],
4097
+ capability: "slack.read.basic",
4098
+ input_schema: {
4099
+ type: "object",
4100
+ properties: {
4101
+ latest: { type: "string" },
4102
+ oldest: { type: "string" },
4103
+ limit: { type: "integer", minimum: 1, maximum: 1e3 }
4104
+ },
4105
+ additionalProperties: false
4106
+ },
4107
+ constraints: { rate_bucket: "slack.read" },
4108
+ effects: ["Read:Message"],
4109
+ risk: "low",
4110
+ version: "1.0.0"
4111
+ },
4112
+ {
4113
+ action: "slack:channel.add_reaction",
4114
+ resource_type: "SlackChannel",
4115
+ required_relations: ["editor", "act_as"],
4116
+ required_scopes: ["reactions:write", "chat:write"],
4117
+ capability: "slack.messaging.enhanced",
4118
+ input_schema: {
4119
+ type: "object",
4120
+ properties: {
4121
+ name: { type: "string", minLength: 1 },
4122
+ timestamp: { type: "string" }
4123
+ },
4124
+ required: ["name", "timestamp"],
4125
+ additionalProperties: false
4126
+ },
4127
+ constraints: { rate_bucket: "slack.post" },
4128
+ effects: ["Update:MessageReaction"],
4129
+ risk: "low",
4130
+ version: "1.0.0"
4131
+ },
4132
+ {
4133
+ action: "gh:repo.read",
4134
+ resource_type: "GitHubRepo",
4135
+ required_relations: ["viewer", "editor", "admin", "owner"],
4136
+ required_scopes: ["repo", "public_repo"],
4137
+ capability: "gh.read.basic",
4138
+ input_schema: {
4139
+ type: "object",
4140
+ properties: {
4141
+ path: { type: "string" },
4142
+ ref: { type: "string" }
4143
+ },
4144
+ additionalProperties: false
4145
+ },
4146
+ constraints: { rate_bucket: "github.read" },
4147
+ effects: ["Read:Repo"],
4148
+ risk: "low",
4149
+ version: "1.0.0"
4150
+ },
4151
+ {
4152
+ action: "gh:repo.create_issue",
4153
+ resource_type: "GitHubRepo",
4154
+ required_relations: ["editor", "act_as"],
4155
+ required_scopes: ["repo"],
4156
+ capability: "gh.issues.triage",
4157
+ input_schema: {
4158
+ type: "object",
4159
+ properties: {
4160
+ title: { type: "string", minLength: 1 },
4161
+ body: { type: "string" },
4162
+ labels: { type: "array", items: { type: "string" } },
4163
+ assignees: { type: "array", items: { type: "string" } }
4164
+ },
4165
+ required: ["title"],
4166
+ additionalProperties: false
4167
+ },
4168
+ constraints: { rate_bucket: "github.write" },
4169
+ effects: ["Create:Issue"],
4170
+ risk: "medium",
4171
+ version: "1.0.0"
4172
+ },
4173
+ {
4174
+ action: "gh:repo.comment",
4175
+ resource_type: "GitHubRepo",
4176
+ required_relations: ["editor", "act_as"],
4177
+ required_scopes: ["repo"],
4178
+ capability: "gh.issues.triage",
4179
+ input_schema: {
4180
+ type: "object",
4181
+ properties: {
4182
+ issue_number: { type: "integer", minimum: 1 },
4183
+ body: { type: "string", minLength: 1 }
4184
+ },
4185
+ required: ["issue_number", "body"],
4186
+ additionalProperties: false
4187
+ },
4188
+ constraints: { rate_bucket: "github.write" },
4189
+ effects: ["Create:IssueComment"],
4190
+ risk: "low",
4191
+ version: "1.0.0"
4192
+ },
4193
+ {
4194
+ action: "gh:repo.create_pr",
4195
+ resource_type: "GitHubRepo",
4196
+ required_relations: ["editor", "act_as"],
4197
+ required_scopes: ["repo"],
4198
+ capability: "gh.code.collab",
4199
+ input_schema: {
4200
+ type: "object",
4201
+ properties: {
4202
+ title: { type: "string", minLength: 1 },
4203
+ head: { type: "string", minLength: 1 },
4204
+ base: { type: "string", minLength: 1 },
4205
+ body: { type: "string" },
4206
+ draft: { type: "boolean" }
4207
+ },
4208
+ required: ["title", "head", "base"],
4209
+ additionalProperties: false
4210
+ },
4211
+ constraints: { rate_bucket: "github.write" },
4212
+ effects: ["Create:PullRequest"],
4213
+ risk: "medium",
4214
+ version: "1.0.0"
4215
+ },
4216
+ {
4217
+ action: "gh:repo.merge_pr",
4218
+ resource_type: "GitHubRepo",
4219
+ required_relations: ["admin", "owner"],
4220
+ required_scopes: ["repo"],
4221
+ capability: "gh.code.maintain",
4222
+ input_schema: {
4223
+ type: "object",
4224
+ properties: {
4225
+ pr_number: { type: "integer", minimum: 1 },
4226
+ merge_method: { type: "string", enum: ["merge", "squash", "rebase"] }
4227
+ },
4228
+ required: ["pr_number"],
4229
+ additionalProperties: false
4230
+ },
4231
+ constraints: { rate_bucket: "github.write", requires_reviews_passed: true },
4232
+ effects: ["Update:PullRequestMerge"],
4233
+ risk: "high",
4234
+ version: "1.0.0"
4235
+ },
4236
+ {
4237
+ action: "google:drive.file.read",
4238
+ resource_type: "DriveFile",
4239
+ required_relations: ["viewer", "editor", "admin", "owner"],
4240
+ required_scopes: ["https://www.googleapis.com/auth/drive.readonly"],
4241
+ capability: "gdrive.read.basic",
4242
+ input_schema: {
4243
+ type: "object",
4244
+ properties: {
4245
+ fields: { type: "string" }
4246
+ },
4247
+ additionalProperties: false
4248
+ },
4249
+ constraints: { rate_bucket: "gdrive.read" },
4250
+ effects: ["Read:FileContent"],
4251
+ risk: "low",
4252
+ version: "1.0.0"
4253
+ },
4254
+ {
4255
+ action: "google:drive.file.write",
4256
+ resource_type: "DriveFile",
4257
+ required_relations: ["editor", "act_as"],
4258
+ required_scopes: ["https://www.googleapis.com/auth/drive.file"],
4259
+ capability: "gdrive.write.basic",
4260
+ input_schema: {
4261
+ type: "object",
4262
+ properties: {
4263
+ mimeType: { type: "string" },
4264
+ content_base64: { type: "string" }
4265
+ },
4266
+ required: ["content_base64"],
4267
+ additionalProperties: false
4268
+ },
4269
+ constraints: { rate_bucket: "gdrive.write", max_size_mb: 50 },
4270
+ effects: ["Update:FileContent"],
4271
+ risk: "medium",
4272
+ version: "1.0.0"
4273
+ },
4274
+ {
4275
+ action: "google:drive.file.create",
4276
+ resource_type: "DriveFile",
4277
+ required_relations: ["editor", "act_as"],
4278
+ required_scopes: ["https://www.googleapis.com/auth/drive.file"],
4279
+ capability: "gdrive.write.basic",
4280
+ input_schema: {
4281
+ type: "object",
4282
+ properties: {
4283
+ name: { type: "string", minLength: 1 },
4284
+ mimeType: { type: "string" },
4285
+ parent_folder_id: { type: "string" },
4286
+ content_base64: { type: "string" }
4287
+ },
4288
+ required: ["name"],
4289
+ additionalProperties: false
4290
+ },
4291
+ constraints: { rate_bucket: "gdrive.write", max_size_mb: 50 },
4292
+ effects: ["Create:File"],
4293
+ risk: "medium",
4294
+ version: "1.0.0"
4295
+ },
4296
+ {
4297
+ action: "google:drive.file.list_in_folder",
4298
+ resource_type: "DriveFile",
4299
+ required_relations: ["viewer", "editor", "admin", "owner"],
4300
+ required_scopes: ["https://www.googleapis.com/auth/drive.readonly"],
4301
+ capability: "gdrive.read.basic",
4302
+ input_schema: {
4303
+ type: "object",
4304
+ properties: {
4305
+ folder_id: { type: "string" },
4306
+ q: { type: "string" },
4307
+ page_size: { type: "integer", minimum: 1, maximum: 1e3 }
4308
+ },
4309
+ required: ["folder_id"],
4310
+ additionalProperties: false
4311
+ },
4312
+ constraints: { rate_bucket: "gdrive.read" },
4313
+ effects: ["Read:FileList"],
4314
+ risk: "low",
4315
+ version: "1.0.0"
4316
+ },
4317
+ {
4318
+ action: "jira:issue.search",
4319
+ resource_type: "JiraIssue",
4320
+ required_relations: ["viewer", "editor", "admin", "owner"],
4321
+ required_scopes: ["read:jira-work", "read:jira-user"],
4322
+ capability: "jira.read.basic",
4323
+ input_schema: {
4324
+ type: "object",
4325
+ properties: {
4326
+ jql: { type: "string", minLength: 1 },
4327
+ maxResults: { type: "integer", minimum: 1, maximum: 100 },
4328
+ startAt: { type: "integer", minimum: 0 }
4329
+ },
4330
+ required: ["jql"],
4331
+ additionalProperties: false
4332
+ },
4333
+ constraints: { rate_bucket: "jira.read" },
4334
+ effects: ["Read:IssueList"],
4335
+ risk: "low",
4336
+ version: "1.0.0"
4337
+ },
4338
+ {
4339
+ action: "jira:issue.get",
4340
+ resource_type: "JiraIssue",
4341
+ required_relations: ["viewer", "editor", "admin", "owner"],
4342
+ required_scopes: ["read:jira-work"],
4343
+ capability: "jira.read.basic",
4344
+ input_schema: {
4345
+ type: "object",
4346
+ properties: {
4347
+ issueIdOrKey: { type: "string", minLength: 1 }
4348
+ },
4349
+ required: ["issueIdOrKey"],
4350
+ additionalProperties: false
4351
+ },
4352
+ constraints: { rate_bucket: "jira.read" },
4353
+ effects: ["Read:Issue"],
4354
+ risk: "low",
4355
+ version: "1.0.0"
4356
+ },
4357
+ {
4358
+ action: "jira:project.list",
4359
+ resource_type: "JiraProject",
4360
+ required_relations: ["viewer", "editor", "admin", "owner"],
4361
+ required_scopes: ["read:jira-work"],
4362
+ capability: "jira.read.basic",
4363
+ input_schema: {
4364
+ type: "object",
4365
+ properties: {
4366
+ recent: { type: "number" }
4367
+ },
4368
+ additionalProperties: false
4369
+ },
4370
+ constraints: { rate_bucket: "jira.read" },
4371
+ effects: ["Read:ProjectList"],
4372
+ risk: "low",
4373
+ version: "1.0.0"
4374
+ },
4375
+ {
4376
+ action: "jira:board.list",
4377
+ resource_type: "JiraBoard",
4378
+ required_relations: ["viewer", "editor", "admin", "owner"],
4379
+ required_scopes: ["read:jira-work"],
4380
+ capability: "jira.read.basic",
4381
+ input_schema: {
4382
+ type: "object",
4383
+ properties: {
4384
+ projectKeyOrId: { type: "string" },
4385
+ type: { type: "string" }
4386
+ },
4387
+ additionalProperties: false
4388
+ },
4389
+ constraints: { rate_bucket: "jira.read" },
4390
+ effects: ["Read:BoardList"],
4391
+ risk: "low",
4392
+ version: "1.0.0"
4393
+ },
4394
+ {
4395
+ action: "jira:sprint.list",
4396
+ resource_type: "JiraSprint",
4397
+ required_relations: ["viewer", "editor", "admin", "owner"],
4398
+ required_scopes: ["read:jira-work"],
4399
+ capability: "jira.read.basic",
4400
+ input_schema: {
4401
+ type: "object",
4402
+ properties: {
4403
+ boardId: { type: "number", minimum: 1 },
4404
+ state: { type: "string" }
4405
+ },
4406
+ required: ["boardId"],
4407
+ additionalProperties: false
4408
+ },
4409
+ constraints: { rate_bucket: "jira.read" },
4410
+ effects: ["Read:SprintList"],
4411
+ risk: "low",
4412
+ version: "1.0.0"
4413
+ },
4414
+ {
4415
+ action: "jira:sprint.get_issues",
4416
+ resource_type: "JiraSprint",
4417
+ required_relations: ["viewer", "editor", "admin", "owner"],
4418
+ required_scopes: ["read:jira-work"],
4419
+ capability: "jira.read.basic",
4420
+ input_schema: {
4421
+ type: "object",
4422
+ properties: {
4423
+ sprintId: { type: "number", minimum: 1 },
4424
+ maxResults: { type: "number", minimum: 1, maximum: 100 }
4425
+ },
4426
+ required: ["sprintId"],
4427
+ additionalProperties: false
4428
+ },
4429
+ constraints: { rate_bucket: "jira.read" },
4430
+ effects: ["Read:IssueList"],
4431
+ risk: "low",
4432
+ version: "1.0.0"
4433
+ },
4434
+ {
4435
+ action: "jira:issue.create",
4436
+ resource_type: "JiraIssue",
4437
+ required_relations: ["editor", "act_as"],
4438
+ required_scopes: ["write:jira-work"],
4439
+ capability: "jira.write.basic",
4440
+ input_schema: {
4441
+ type: "object",
4442
+ properties: {
4443
+ projectKey: { type: "string", minLength: 1 },
4444
+ summary: { type: "string", minLength: 1 },
4445
+ description: { type: "string" },
4446
+ issueType: { type: "string", minLength: 1 },
4447
+ priority: { type: "string" },
4448
+ assignee: { type: "string" }
4449
+ },
4450
+ required: ["projectKey", "summary", "issueType"],
4451
+ additionalProperties: false
4452
+ },
4453
+ constraints: { rate_bucket: "jira.write" },
4454
+ effects: ["Create:Issue"],
4455
+ risk: "medium",
4456
+ version: "1.0.0"
4457
+ }
4458
+ ],
4459
+ capabilities: [
4460
+ {
4461
+ capability: "slack.messaging.basic",
4462
+ description: "Post and read messages in channels",
4463
+ includes: ["slack:channel.post_message", "slack:channel.read"],
4464
+ version: "1.0.0"
4465
+ },
4466
+ {
4467
+ capability: "slack.messaging.enhanced",
4468
+ description: "Reactions and advanced messaging",
4469
+ includes: ["slack:channel.add_reaction"],
4470
+ version: "1.0.0"
4471
+ },
4472
+ {
4473
+ capability: "gh.read.basic",
4474
+ description: "Read repository content and metadata",
4475
+ includes: ["gh:repo.read"],
4476
+ version: "1.0.0"
4477
+ },
4478
+ {
4479
+ capability: "gh.issues.triage",
4480
+ description: "Create and comment on issues",
4481
+ includes: ["gh:repo.create_issue", "gh:repo.comment"],
4482
+ version: "1.0.0"
4483
+ },
4484
+ {
4485
+ capability: "gh.code.collab",
4486
+ description: "Open pull requests for collaboration",
4487
+ includes: ["gh:repo.create_pr"],
4488
+ version: "1.0.0"
4489
+ },
4490
+ {
4491
+ capability: "gh.code.maintain",
4492
+ description: "Merge pull requests (high risk)",
4493
+ includes: ["gh:repo.merge_pr"],
4494
+ version: "1.0.0"
4495
+ },
4496
+ {
4497
+ capability: "gdrive.read.basic",
4498
+ description: "Read Drive files and listings",
4499
+ includes: ["google:drive.file.read", "google:drive.file.list_in_folder"],
4500
+ version: "1.0.0"
4501
+ },
4502
+ {
4503
+ capability: "gdrive.write.basic",
4504
+ description: "Create and update Drive files",
4505
+ includes: ["google:drive.file.write", "google:drive.file.create"],
4506
+ version: "1.0.0"
4507
+ },
4508
+ {
4509
+ capability: "jira.read.basic",
4510
+ description: "Read Jira issues, projects, boards, and sprints",
4511
+ includes: ["jira:issue.search", "jira:issue.get", "jira:project.list", "jira:board.list", "jira:sprint.list", "jira:sprint.get_issues"],
4512
+ version: "1.0.0"
4513
+ },
4514
+ {
4515
+ capability: "jira.write.basic",
4516
+ description: "Create Jira issues",
4517
+ includes: ["jira:issue.create"],
4518
+ version: "1.0.0"
4519
+ }
4520
+ ]
4521
+ };
4522
+
4523
+ // src/index.ts
4524
+ __reExport(index_exports, require("@vess-id/ai-identity-types"), module.exports);
4525
+ var version = "0.0.1";
4526
+ // Annotate the CommonJS export names for ESM import in node:
4527
+ 0 && (module.exports = {
4528
+ ACTION_REGISTRY,
4529
+ AIdentityClient,
4530
+ APIVCManager,
4531
+ AgentDIDManager,
4532
+ AgentManager,
4533
+ AllowAllAbac,
4534
+ ConstraintEvaluator,
4535
+ DisclosureConfigManager,
4536
+ DummyCreds,
4537
+ DummyVpVerifier,
4538
+ FilesystemKeyStorage,
4539
+ KeyManager,
4540
+ KeyRotationManager,
4541
+ MemoryKeyStorage,
4542
+ MemoryManager,
4543
+ MetricsManager,
4544
+ RevocationManager,
4545
+ SDJwtClient,
4546
+ SimpleRebac,
4547
+ ToolManager,
4548
+ UserIdentityManager,
4549
+ VCManager,
4550
+ VPManager,
4551
+ checkPermissionWithVP,
4552
+ configure,
4553
+ createAjv,
4554
+ defaultConstraintEvaluator,
4555
+ evaluateConstraints,
4556
+ generateKeyPair,
4557
+ generateNonce,
4558
+ getClient,
4559
+ getRequiredRelations,
4560
+ getRequiredScopes,
4561
+ indexActions,
4562
+ indexCapabilities,
4563
+ loadActionRegistryFromFile,
4564
+ loadActionRegistryFromObject,
4565
+ planDelegationForVC,
4566
+ resolveActionsFromSelection,
4567
+ signJWT,
4568
+ validateRegistryObject,
4569
+ verifyJWT,
4570
+ version,
4571
+ ...require("@vess-id/ai-identity-types")
4572
+ });
4573
+ //# sourceMappingURL=index.js.map