@vallum/registry 0.0.0-prerelease

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.
@@ -0,0 +1,329 @@
1
+ export function createInMemoryIotaIdentityVerificationCache() {
2
+ const entries = new Map();
3
+ return {
4
+ get(key) {
5
+ return entries.get(key);
6
+ },
7
+ set(key, entry) {
8
+ entries.set(key, entry);
9
+ },
10
+ delete(key) {
11
+ entries.delete(key);
12
+ },
13
+ };
14
+ }
15
+ export function createIotaIdentityVerifiedResolver(baseResolver, options) {
16
+ return {
17
+ async resolve(name) {
18
+ const resolved = await baseResolver.resolve(name);
19
+ if (!resolved.ok)
20
+ return resolved;
21
+ const identity = await verifyAgentProfileIdentity(resolved.profile, options);
22
+ if (identity.ok)
23
+ return resolved;
24
+ return {
25
+ ok: false,
26
+ error: {
27
+ code: identityErrorToResolveCode(identity.error.code),
28
+ message: identity.error.message,
29
+ name: resolved.profile.name,
30
+ },
31
+ };
32
+ },
33
+ };
34
+ }
35
+ export async function verifyAgentProfileIdentity(profile, options) {
36
+ const now = options.now?.() ?? new Date();
37
+ const cacheKey = identityVerificationCacheKey(profile, options.trustPolicy);
38
+ if (options.forceRefresh)
39
+ options.verificationCache?.delete?.(cacheKey);
40
+ const cached = readFreshIdentityCache(options, cacheKey, now);
41
+ if (cached)
42
+ return withoutCacheMetadata(cached);
43
+ const agentDidDocument = await resolveDidDocument(profile.agentDid, options.didResolver);
44
+ if (!agentDidDocument.ok)
45
+ return agentDidDocument;
46
+ if (extractDidDocumentId(agentDidDocument.document) !== profile.agentDid) {
47
+ return failIdentity("PROFILE_UNVERIFIABLE", "Resolved agent DID document does not match the profile.");
48
+ }
49
+ const ownerDidDocument = await resolveDidDocument(profile.ownerDid, options.didResolver);
50
+ if (!ownerDidDocument.ok)
51
+ return ownerDidDocument;
52
+ if (extractDidDocumentId(ownerDidDocument.document) !== profile.ownerDid) {
53
+ return failIdentity("PROFILE_UNVERIFIABLE", "Resolved owner DID document does not match the profile.");
54
+ }
55
+ const credentialRefs = profileCredentialRefs(profile);
56
+ if (options.trustPolicy && !options.credentialValidator && credentialRefs.length > 0) {
57
+ return failIdentity("PROFILE_UNVERIFIABLE", "IOTA Identity credential validator is required by trust policy.");
58
+ }
59
+ if (options.credentialValidator) {
60
+ for (const credentialRef of credentialRefs) {
61
+ let credential;
62
+ try {
63
+ credential = await options.credentialValidator.validateCredentialRef(credentialRef, {
64
+ profile,
65
+ agentDidDocument: agentDidDocument.document,
66
+ ownerDidDocument: ownerDidDocument.document,
67
+ });
68
+ }
69
+ catch {
70
+ return failIdentity("PROFILE_UNVERIFIABLE", "IOTA Identity credential validation failed.");
71
+ }
72
+ if (!credential.ok) {
73
+ return failIdentity(credentialErrorToIdentityCode(credential.code), credential.message);
74
+ }
75
+ const trusted = evaluateIotaIdentityCredentialTrustPolicy(credential.evidence, options.trustPolicy, now);
76
+ if (!trusted.ok) {
77
+ return failIdentity(credentialErrorToIdentityCode(trusted.code), trusted.message);
78
+ }
79
+ }
80
+ }
81
+ const verified = {
82
+ ok: true,
83
+ agentDidDocument: agentDidDocument.document,
84
+ ownerDidDocument: ownerDidDocument.document,
85
+ credentialRefsChecked: credentialRefs,
86
+ };
87
+ writeIdentityCache(options, cacheKey, verified, now);
88
+ return verified;
89
+ }
90
+ export function evaluateIotaIdentityCredentialTrustPolicy(evidence, policy, now = new Date()) {
91
+ if (!policy)
92
+ return { ok: true };
93
+ const policyShape = validateTrustPolicyShape(policy);
94
+ if (!policyShape.ok)
95
+ return policyShape;
96
+ if (!evidence) {
97
+ return unverifiable("Credential evidence is missing trust-policy evidence.");
98
+ }
99
+ if (!policy.trustedIssuerDids.includes(evidence.issuerDid)) {
100
+ return unverifiable("Credential evidence was not issued by a trusted DID.");
101
+ }
102
+ if (!isVerificationMethodAllowed(evidence.issuerDid, evidence.verificationMethod, policy.allowedVerificationMethods)) {
103
+ return unverifiable("Credential evidence was not signed with an allowed verification method.");
104
+ }
105
+ for (const requiredType of policy.requiredCredentialTypes ?? []) {
106
+ if (!evidence.credentialTypes?.includes(requiredType)) {
107
+ return unverifiable("Credential evidence is missing a required credential type.");
108
+ }
109
+ }
110
+ if (policy.requireCredentialStatus && !evidence.credentialStatus) {
111
+ return unverifiable("Credential evidence is missing required revocation status evidence.");
112
+ }
113
+ if (evidence.credentialStatus) {
114
+ if (evidence.credentialStatus.revoked) {
115
+ return {
116
+ ok: false,
117
+ code: "CREDENTIAL_REVOKED",
118
+ message: "Credential evidence is revoked by trust-policy evidence.",
119
+ };
120
+ }
121
+ if (policy.acceptedCredentialStatusTypes
122
+ && !policy.acceptedCredentialStatusTypes.includes(evidence.credentialStatus.type)) {
123
+ return unverifiable("Credential evidence uses an unsupported credential status type.");
124
+ }
125
+ }
126
+ const expiresAt = parseOptionalTimestamp(evidence.expiresAt);
127
+ if (expiresAt === "invalid")
128
+ return unverifiable("Credential evidence has an invalid expiry timestamp.");
129
+ if (expiresAt && expiresAt.getTime() <= now.getTime()) {
130
+ return {
131
+ ok: false,
132
+ code: "CREDENTIAL_EXPIRED",
133
+ message: "Credential evidence is expired.",
134
+ };
135
+ }
136
+ if (policy.maxCredentialAgeMs !== undefined) {
137
+ const issuedAt = parseOptionalTimestamp(evidence.issuedAt);
138
+ if (issuedAt === "invalid" || !issuedAt) {
139
+ return unverifiable("Credential evidence is missing valid issuance evidence required by trust policy.");
140
+ }
141
+ if (issuedAt.getTime() > now.getTime()) {
142
+ return unverifiable("Credential evidence has a future issuance timestamp.");
143
+ }
144
+ if (now.getTime() - issuedAt.getTime() > policy.maxCredentialAgeMs) {
145
+ return {
146
+ ok: false,
147
+ code: "CREDENTIAL_EXPIRED",
148
+ message: "Credential evidence exceeds trust-policy max credential age.",
149
+ };
150
+ }
151
+ }
152
+ return { ok: true };
153
+ }
154
+ function readFreshIdentityCache(options, key, now) {
155
+ if (!isCacheEnabled(options))
156
+ return undefined;
157
+ const entry = options.verificationCache?.get(key);
158
+ if (!entry)
159
+ return undefined;
160
+ if (Date.parse(entry.expiresAt) > now.getTime())
161
+ return entry;
162
+ options.verificationCache?.delete?.(key);
163
+ return undefined;
164
+ }
165
+ function writeIdentityCache(options, key, result, now) {
166
+ if (!isCacheEnabled(options))
167
+ return;
168
+ const ttlMs = options.cacheTtlMs ?? 0;
169
+ options.verificationCache?.set(key, {
170
+ ...result,
171
+ cachedAt: now.toISOString(),
172
+ expiresAt: new Date(now.getTime() + ttlMs).toISOString(),
173
+ });
174
+ }
175
+ function withoutCacheMetadata(entry) {
176
+ return {
177
+ ok: true,
178
+ agentDidDocument: entry.agentDidDocument,
179
+ ownerDidDocument: entry.ownerDidDocument,
180
+ credentialRefsChecked: entry.credentialRefsChecked,
181
+ };
182
+ }
183
+ function isCacheEnabled(options) {
184
+ return Boolean(options.verificationCache
185
+ && options.cacheTtlMs
186
+ && Number.isFinite(options.cacheTtlMs)
187
+ && options.cacheTtlMs > 0);
188
+ }
189
+ function identityVerificationCacheKey(profile, trustPolicy) {
190
+ return JSON.stringify({
191
+ version: profile.version,
192
+ name: profile.name,
193
+ agentDid: profile.agentDid,
194
+ ownerDid: profile.ownerDid,
195
+ walletStatus: profile.wallet.status,
196
+ expiresAt: profile.expiresAt,
197
+ status: profile.status,
198
+ revocation: {
199
+ revoked: profile.revocation.revoked,
200
+ revokedAt: profile.revocation.revokedAt ?? "",
201
+ },
202
+ credentialRefs: profileCredentialRefs(profile),
203
+ trustPolicy: trustPolicyCacheKey(trustPolicy),
204
+ });
205
+ }
206
+ async function resolveDidDocument(did, resolver) {
207
+ try {
208
+ if (resolver.resolveDid) {
209
+ return { ok: true, document: await resolver.resolveDid(did) };
210
+ }
211
+ if (resolver.resolve) {
212
+ return { ok: true, document: await resolver.resolve(did) };
213
+ }
214
+ }
215
+ catch {
216
+ return {
217
+ ok: false,
218
+ error: {
219
+ code: "PROFILE_UNVERIFIABLE",
220
+ message: "IOTA Identity DID resolution failed.",
221
+ },
222
+ };
223
+ }
224
+ return {
225
+ ok: false,
226
+ error: {
227
+ code: "PROFILE_UNVERIFIABLE",
228
+ message: "IOTA Identity DID resolver is not configured.",
229
+ },
230
+ };
231
+ }
232
+ function extractDidDocumentId(document) {
233
+ if (!isRecord(document))
234
+ return undefined;
235
+ const id = document.id;
236
+ if (typeof id === "string")
237
+ return id;
238
+ if (typeof id === "function")
239
+ return String(id.call(document));
240
+ if (id && typeof id === "object" && "toString" in id && typeof id.toString === "function") {
241
+ return id.toString();
242
+ }
243
+ return undefined;
244
+ }
245
+ function profileCredentialRefs(profile) {
246
+ const refs = new Set();
247
+ profile.credentialRefs?.forEach((ref) => refs.add(ref));
248
+ for (const capability of profile.capabilities) {
249
+ capability.credentialRefs?.forEach((ref) => refs.add(ref));
250
+ }
251
+ return [...refs];
252
+ }
253
+ function credentialErrorToIdentityCode(code) {
254
+ if (code === "CREDENTIAL_REVOKED")
255
+ return "PROFILE_REVOKED";
256
+ if (code === "CREDENTIAL_EXPIRED")
257
+ return "PROFILE_EXPIRED";
258
+ return "PROFILE_UNVERIFIABLE";
259
+ }
260
+ function validateTrustPolicyShape(policy) {
261
+ if (policy.trustedIssuerDids.length === 0
262
+ || !policy.trustedIssuerDids.every((issuerDid) => issuerDid.startsWith("did:iota:"))) {
263
+ return unverifiable("IOTA Identity trust policy has no trusted issuers.");
264
+ }
265
+ if (policy.allowedVerificationMethods.length === 0
266
+ || !policy.allowedVerificationMethods.every((method) => method.startsWith("did:iota:") || method.startsWith("#"))) {
267
+ return unverifiable("IOTA Identity trust policy has no allowed verification methods.");
268
+ }
269
+ if (policy.requiredCredentialTypes?.some((credentialType) => credentialType.trim() === "")) {
270
+ return unverifiable("IOTA Identity trust policy has an invalid credential type requirement.");
271
+ }
272
+ if (policy.acceptedCredentialStatusTypes?.some((statusType) => statusType.trim() === "")) {
273
+ return unverifiable("IOTA Identity trust policy has an invalid credential status type.");
274
+ }
275
+ if (policy.maxCredentialAgeMs !== undefined
276
+ && (!Number.isFinite(policy.maxCredentialAgeMs) || policy.maxCredentialAgeMs <= 0)) {
277
+ return unverifiable("IOTA Identity trust policy has an invalid max credential age.");
278
+ }
279
+ return { ok: true };
280
+ }
281
+ function isVerificationMethodAllowed(issuerDid, verificationMethod, allowedVerificationMethods) {
282
+ if (!verificationMethod.startsWith(`${issuerDid}#`))
283
+ return false;
284
+ return allowedVerificationMethods.some((allowed) => {
285
+ if (allowed === verificationMethod)
286
+ return true;
287
+ return allowed.startsWith("#") && `${issuerDid}${allowed}` === verificationMethod;
288
+ });
289
+ }
290
+ function parseOptionalTimestamp(value) {
291
+ if (value === undefined)
292
+ return undefined;
293
+ const timestamp = Date.parse(value);
294
+ if (Number.isNaN(timestamp))
295
+ return "invalid";
296
+ return new Date(timestamp);
297
+ }
298
+ function trustPolicyCacheKey(policy) {
299
+ if (!policy)
300
+ return null;
301
+ return {
302
+ trustedIssuerDids: [...policy.trustedIssuerDids].sort(),
303
+ allowedVerificationMethods: [...policy.allowedVerificationMethods].sort(),
304
+ requiredCredentialTypes: [...(policy.requiredCredentialTypes ?? [])].sort(),
305
+ acceptedCredentialStatusTypes: [...(policy.acceptedCredentialStatusTypes ?? [])].sort(),
306
+ requireCredentialStatus: Boolean(policy.requireCredentialStatus),
307
+ maxCredentialAgeMs: policy.maxCredentialAgeMs ?? null,
308
+ };
309
+ }
310
+ function unverifiable(message) {
311
+ return {
312
+ ok: false,
313
+ code: "CREDENTIAL_UNVERIFIABLE",
314
+ message,
315
+ };
316
+ }
317
+ function identityErrorToResolveCode(code) {
318
+ return code;
319
+ }
320
+ function failIdentity(code, message) {
321
+ return {
322
+ ok: false,
323
+ error: { code, message },
324
+ };
325
+ }
326
+ function isRecord(value) {
327
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
328
+ }
329
+ //# sourceMappingURL=iotaIdentityAdapter.js.map
@@ -0,0 +1,49 @@
1
+ import { type AgentResolver } from "./resolveAgent.js";
2
+ import { type IotaIdentityVerificationOptions } from "./iotaIdentityAdapter.js";
3
+ export declare const IOTA_NAMES_RESOLVE_ADDRESS_QUERY = "\nquery ResolveIotaNamesAddress($name: String!) {\n resolveIotaNamesAddress(name: $name) {\n address\n }\n}\n";
4
+ export interface IotaNamesGraphQLRequest {
5
+ readonly query: string;
6
+ readonly variables: Readonly<Record<string, unknown>>;
7
+ }
8
+ export interface IotaNamesGraphQLError {
9
+ readonly message?: string;
10
+ }
11
+ export interface IotaNamesGraphQLResponse<TData> {
12
+ readonly data?: TData;
13
+ readonly errors?: readonly IotaNamesGraphQLError[];
14
+ }
15
+ export interface IotaNamesGraphQLClient {
16
+ readonly query: <TData>(request: IotaNamesGraphQLRequest) => Promise<IotaNamesGraphQLResponse<TData>>;
17
+ }
18
+ export type IotaNamesAddressResolution = {
19
+ readonly ok: true;
20
+ readonly name: string;
21
+ readonly address: string;
22
+ readonly source: "iota-names-graphql";
23
+ } | {
24
+ readonly ok: false;
25
+ readonly error: {
26
+ readonly code: "IOTA_NAME_NOT_FOUND" | "IOTA_NAMES_GRAPHQL_ERROR" | "IOTA_NAMES_MALFORMED_RESPONSE";
27
+ readonly message: string;
28
+ };
29
+ readonly name: string;
30
+ };
31
+ export interface FetchIotaNamesGraphQLClientOptions {
32
+ readonly endpoint: string;
33
+ readonly fetch?: typeof fetch;
34
+ }
35
+ export interface IotaNamesProfileSource {
36
+ readonly getProfileByAddress: (address: string, context: {
37
+ readonly name: string;
38
+ }) => Promise<unknown | undefined>;
39
+ }
40
+ export interface IotaNamesAgentResolverOptions {
41
+ readonly graphQL: IotaNamesGraphQLClient;
42
+ readonly profileSource: IotaNamesProfileSource;
43
+ readonly identity?: IotaIdentityVerificationOptions;
44
+ readonly now?: () => Date;
45
+ }
46
+ export declare function createFetchIotaNamesGraphQLClient(options: FetchIotaNamesGraphQLClientOptions): IotaNamesGraphQLClient;
47
+ export declare function resolveIotaNamesAddress(name: string, graphQL: IotaNamesGraphQLClient): Promise<IotaNamesAddressResolution>;
48
+ export declare function createIotaNamesAgentResolver(options: IotaNamesAgentResolverOptions): AgentResolver;
49
+ //# sourceMappingURL=iotaNamesAdapter.d.ts.map
@@ -0,0 +1,188 @@
1
+ import { validateAgentProfile, } from "./profileSchema.js";
2
+ import { resolveAgentValidationErrorCode, } from "./resolveAgent.js";
3
+ import { verifyAgentProfileIdentity } from "./iotaIdentityAdapter.js";
4
+ export const IOTA_NAMES_RESOLVE_ADDRESS_QUERY = `
5
+ query ResolveIotaNamesAddress($name: String!) {
6
+ resolveIotaNamesAddress(name: $name) {
7
+ address
8
+ }
9
+ }
10
+ `;
11
+ export function createFetchIotaNamesGraphQLClient(options) {
12
+ const fetchImpl = options.fetch ?? fetch;
13
+ return {
14
+ async query(request) {
15
+ const response = await fetchImpl(options.endpoint, {
16
+ method: "POST",
17
+ headers: {
18
+ "content-type": "application/json",
19
+ },
20
+ body: JSON.stringify(request),
21
+ });
22
+ if (!response.ok) {
23
+ return {
24
+ errors: [{ message: `IOTA Names GraphQL request failed with HTTP ${response.status}.` }],
25
+ };
26
+ }
27
+ return await response.json();
28
+ },
29
+ };
30
+ }
31
+ export async function resolveIotaNamesAddress(name, graphQL) {
32
+ const normalizedName = normalizeName(name);
33
+ let response;
34
+ try {
35
+ response = await graphQL.query({
36
+ query: IOTA_NAMES_RESOLVE_ADDRESS_QUERY,
37
+ variables: { name: normalizedName },
38
+ });
39
+ }
40
+ catch {
41
+ return {
42
+ ok: false,
43
+ name: normalizedName,
44
+ error: {
45
+ code: "IOTA_NAMES_GRAPHQL_ERROR",
46
+ message: "IOTA Names GraphQL request failed.",
47
+ },
48
+ };
49
+ }
50
+ if (response.errors?.length) {
51
+ return {
52
+ ok: false,
53
+ name: normalizedName,
54
+ error: {
55
+ code: "IOTA_NAMES_GRAPHQL_ERROR",
56
+ message: "IOTA Names GraphQL returned errors.",
57
+ },
58
+ };
59
+ }
60
+ const resolved = response.data?.resolveIotaNamesAddress;
61
+ if (resolved === null) {
62
+ return {
63
+ ok: false,
64
+ name: normalizedName,
65
+ error: {
66
+ code: "IOTA_NAME_NOT_FOUND",
67
+ message: "IOTA name did not resolve to an address.",
68
+ },
69
+ };
70
+ }
71
+ if (!isRecord(resolved) || typeof resolved.address !== "string" || resolved.address.trim() === "") {
72
+ return {
73
+ ok: false,
74
+ name: normalizedName,
75
+ error: {
76
+ code: "IOTA_NAMES_MALFORMED_RESPONSE",
77
+ message: "IOTA Names GraphQL returned a malformed address response.",
78
+ },
79
+ };
80
+ }
81
+ return {
82
+ ok: true,
83
+ name: normalizedName,
84
+ address: resolved.address,
85
+ source: "iota-names-graphql",
86
+ };
87
+ }
88
+ export function createIotaNamesAgentResolver(options) {
89
+ return {
90
+ async resolve(name) {
91
+ const normalizedName = normalizeName(name);
92
+ const addressResolution = await resolveIotaNamesAddress(normalizedName, options.graphQL);
93
+ if (!addressResolution.ok) {
94
+ return resolveNamesError(normalizedName, addressResolution.error.message, addressResolution.error.code);
95
+ }
96
+ let profile;
97
+ try {
98
+ profile = await options.profileSource.getProfileByAddress(addressResolution.address, {
99
+ name: normalizedName,
100
+ });
101
+ }
102
+ catch {
103
+ return unresolvedProfile(normalizedName, "Agent Profile metadata source failed.");
104
+ }
105
+ if (!profile) {
106
+ return {
107
+ ok: false,
108
+ error: {
109
+ code: "PROFILE_NOT_FOUND",
110
+ message: "No Agent Profile metadata was found for the resolved IOTA name address.",
111
+ name: normalizedName,
112
+ },
113
+ };
114
+ }
115
+ return validateNamesProfile(normalizedName, addressResolution.address, profile, options);
116
+ },
117
+ };
118
+ }
119
+ async function validateNamesProfile(name, address, profile, options) {
120
+ const validation = validateAgentProfile(profile, { now: options.now?.() });
121
+ if (!validation.ok) {
122
+ return {
123
+ ok: false,
124
+ error: {
125
+ code: resolveAgentValidationErrorCode(validation.errors),
126
+ message: "Agent profile failed validation.",
127
+ name,
128
+ validationErrors: validation.errors,
129
+ },
130
+ };
131
+ }
132
+ if (validation.profile.name !== name) {
133
+ return unresolvedProfile(name, "Resolved profile name does not match the IOTA name.");
134
+ }
135
+ if (normalizeAddress(validation.profile.wallet.address) !== normalizeAddress(address)) {
136
+ return unresolvedProfile(name, "Resolved profile wallet address does not match the IOTA name target.");
137
+ }
138
+ if (options.identity) {
139
+ const identity = await verifyAgentProfileIdentity(validation.profile, options.identity);
140
+ if (!identity.ok) {
141
+ return {
142
+ ok: false,
143
+ error: {
144
+ code: identity.error.code,
145
+ message: identity.error.message,
146
+ name,
147
+ },
148
+ };
149
+ }
150
+ }
151
+ return {
152
+ ok: true,
153
+ profile: validation.profile,
154
+ };
155
+ }
156
+ function resolveNamesError(name, message, code) {
157
+ if (code === "IOTA_NAME_NOT_FOUND") {
158
+ return {
159
+ ok: false,
160
+ error: {
161
+ code: "PROFILE_NOT_FOUND",
162
+ message,
163
+ name,
164
+ },
165
+ };
166
+ }
167
+ return unresolvedProfile(name, message);
168
+ }
169
+ function unresolvedProfile(name, message) {
170
+ return {
171
+ ok: false,
172
+ error: {
173
+ code: "PROFILE_UNVERIFIABLE",
174
+ message,
175
+ name,
176
+ },
177
+ };
178
+ }
179
+ function normalizeName(name) {
180
+ return name.trim();
181
+ }
182
+ function normalizeAddress(address) {
183
+ return address.trim().toLowerCase();
184
+ }
185
+ function isRecord(value) {
186
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
187
+ }
188
+ //# sourceMappingURL=iotaNamesAdapter.js.map
@@ -0,0 +1,76 @@
1
+ export declare const AGENT_PROFILE_VERSION: "agent-profile/v1";
2
+ export type AgentProfileStatus = "active" | "revoked" | "expired";
3
+ export type AgentWalletStatus = "active" | "disabled" | "revoked" | "rotated";
4
+ export interface AgentProfileWallet {
5
+ readonly walletId: string;
6
+ readonly address: string;
7
+ readonly signerRef: string;
8
+ readonly creationSource: "agent_created" | "operator_provisioned" | "imported_reference";
9
+ readonly status: AgentWalletStatus;
10
+ readonly rotatedToWalletId?: string;
11
+ }
12
+ export interface AgentProfileEndpoint {
13
+ readonly type: "mcp" | "a2a" | "agent_card" | "https";
14
+ readonly url: string;
15
+ }
16
+ export interface AgentProfileCapability {
17
+ readonly id: string;
18
+ readonly displayName?: string;
19
+ readonly contracts?: readonly string[];
20
+ readonly scopes?: readonly string[];
21
+ readonly credentialRefs?: readonly string[];
22
+ }
23
+ export interface AgentProfileContractTemplate {
24
+ readonly id: string;
25
+ readonly packageId?: string;
26
+ readonly module?: string;
27
+ readonly functionName?: string;
28
+ }
29
+ export interface AgentProfilePaymentMethod {
30
+ readonly type: "iota" | "x402" | "external";
31
+ readonly asset: string;
32
+ readonly address?: string;
33
+ }
34
+ export interface AgentProfileRevocation {
35
+ readonly revoked: boolean;
36
+ readonly reason?: string;
37
+ readonly revokedAt?: string;
38
+ }
39
+ export interface AgentProfile {
40
+ readonly version: typeof AGENT_PROFILE_VERSION;
41
+ readonly name: string;
42
+ readonly agentDid: string;
43
+ readonly ownerDid: string;
44
+ readonly wallet: AgentProfileWallet;
45
+ readonly capabilities: readonly AgentProfileCapability[];
46
+ readonly endpoints: readonly AgentProfileEndpoint[];
47
+ readonly credentialRefs?: readonly string[];
48
+ readonly supportedContracts?: readonly AgentProfileContractTemplate[];
49
+ readonly paymentMethods?: readonly AgentProfilePaymentMethod[];
50
+ readonly spendPolicyRef?: string;
51
+ readonly reputationRef?: string;
52
+ readonly expiresAt: string;
53
+ readonly status: AgentProfileStatus;
54
+ readonly revocation: AgentProfileRevocation;
55
+ readonly metadata?: Record<string, string>;
56
+ }
57
+ export type AgentProfileValidationErrorCode = "PROFILE_NOT_OBJECT" | "UNSUPPORTED_VERSION" | "REQUIRED_FIELD_MISSING" | "FIELD_INVALID" | "PROFILE_REVOKED" | "PROFILE_EXPIRED" | "SECRET_FIELD_NOT_ALLOWED";
58
+ export interface AgentProfileValidationError {
59
+ readonly code: AgentProfileValidationErrorCode;
60
+ readonly path: string;
61
+ readonly message: string;
62
+ }
63
+ export type AgentProfileValidationResult = {
64
+ readonly ok: true;
65
+ readonly profile: AgentProfile;
66
+ } | {
67
+ readonly ok: false;
68
+ readonly errors: readonly AgentProfileValidationError[];
69
+ readonly status?: AgentProfileStatus;
70
+ };
71
+ export interface AgentProfileValidationOptions {
72
+ readonly now?: Date;
73
+ }
74
+ export declare function validAgentProfileFixture(): AgentProfile;
75
+ export declare function validateAgentProfile(value: unknown, options?: AgentProfileValidationOptions): AgentProfileValidationResult;
76
+ //# sourceMappingURL=profileSchema.d.ts.map