@provian/mcp 0.0.0-stage → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +264 -2
- package/bin/provian-mcp.mjs +18 -0
- package/dist/agent-wallet-registration.d.ts +34 -0
- package/dist/agent-wallet-registration.d.ts.map +1 -0
- package/dist/agent-wallet-registration.js +440 -0
- package/dist/agent-wallet-registration.js.map +1 -0
- package/dist/core/challenge.d.ts +187 -0
- package/dist/core/challenge.d.ts.map +1 -0
- package/dist/core/challenge.js +536 -0
- package/dist/core/challenge.js.map +1 -0
- package/dist/core/crypto.d.ts +44 -0
- package/dist/core/crypto.d.ts.map +1 -0
- package/dist/core/crypto.js +124 -0
- package/dist/core/crypto.js.map +1 -0
- package/dist/core/disclosure-request.d.ts +169 -0
- package/dist/core/disclosure-request.d.ts.map +1 -0
- package/dist/core/disclosure-request.js +400 -0
- package/dist/core/disclosure-request.js.map +1 -0
- package/dist/core/genesis-offer.d.ts +25 -0
- package/dist/core/genesis-offer.d.ts.map +1 -0
- package/dist/core/genesis-offer.js +34 -0
- package/dist/core/genesis-offer.js.map +1 -0
- package/dist/core/harness-tool-vocabulary.d.ts +55 -0
- package/dist/core/harness-tool-vocabulary.d.ts.map +1 -0
- package/dist/core/harness-tool-vocabulary.js +116 -0
- package/dist/core/harness-tool-vocabulary.js.map +1 -0
- package/dist/core/keccak256.d.ts +15 -0
- package/dist/core/keccak256.d.ts.map +1 -0
- package/dist/core/keccak256.js +111 -0
- package/dist/core/keccak256.js.map +1 -0
- package/dist/core/key-custody.d.ts +33 -0
- package/dist/core/key-custody.d.ts.map +1 -0
- package/dist/core/key-custody.js +59 -0
- package/dist/core/key-custody.js.map +1 -0
- package/dist/core/meter-hash.d.ts +2 -0
- package/dist/core/meter-hash.d.ts.map +1 -0
- package/dist/core/meter-hash.js +8 -0
- package/dist/core/meter-hash.js.map +1 -0
- package/dist/core/meter-wire.d.ts +193 -0
- package/dist/core/meter-wire.d.ts.map +1 -0
- package/dist/core/meter-wire.js +418 -0
- package/dist/core/meter-wire.js.map +1 -0
- package/dist/core/output-signature.d.ts +162 -0
- package/dist/core/output-signature.d.ts.map +1 -0
- package/dist/core/output-signature.js +367 -0
- package/dist/core/output-signature.js.map +1 -0
- package/dist/core/presentation.d.ts +141 -0
- package/dist/core/presentation.d.ts.map +1 -0
- package/dist/core/presentation.js +160 -0
- package/dist/core/presentation.js.map +1 -0
- package/dist/core/recovery-seal.d.ts +36 -0
- package/dist/core/recovery-seal.d.ts.map +1 -0
- package/dist/core/recovery-seal.js +122 -0
- package/dist/core/recovery-seal.js.map +1 -0
- package/dist/core/server.d.ts +38 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +106 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/thread-reader.d.ts +8 -0
- package/dist/core/thread-reader.d.ts.map +1 -0
- package/dist/core/thread-reader.js +47 -0
- package/dist/core/thread-reader.js.map +1 -0
- package/dist/core/tool-set.d.ts +28 -0
- package/dist/core/tool-set.d.ts.map +1 -0
- package/dist/core/tool-set.js +71 -0
- package/dist/core/tool-set.js.map +1 -0
- package/dist/core/tools.d.ts +151 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +3621 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/types.d.ts +189 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +17 -0
- package/dist/core/types.js.map +1 -0
- package/dist/credentials.d.ts +46 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +213 -0
- package/dist/credentials.js.map +1 -0
- package/dist/device-credentials.d.ts +57 -0
- package/dist/device-credentials.d.ts.map +1 -0
- package/dist/device-credentials.js +403 -0
- package/dist/device-credentials.js.map +1 -0
- package/dist/eip191.d.ts +18 -0
- package/dist/eip191.d.ts.map +1 -0
- package/dist/eip191.js +41 -0
- package/dist/eip191.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime-env.d.ts +131 -0
- package/dist/runtime-env.d.ts.map +1 -0
- package/dist/runtime-env.js +328 -0
- package/dist/runtime-env.js.map +1 -0
- package/dist/stdio.d.ts +6 -0
- package/dist/stdio.d.ts.map +1 -0
- package/dist/stdio.js +136 -0
- package/dist/stdio.js.map +1 -0
- package/package.json +60 -4
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MCP_AGENT_WALLET_IDENTITY_PATH = exports.MCP_PENDING_AGENT_WALLET_PATH = void 0;
|
|
37
|
+
exports.loadOrCreatePendingAgentWalletRegistration = loadOrCreatePendingAgentWalletRegistration;
|
|
38
|
+
exports.reloadPendingAgentWalletRegistration = reloadPendingAgentWalletRegistration;
|
|
39
|
+
exports.completePendingAgentWalletRegistration = completePendingAgentWalletRegistration;
|
|
40
|
+
exports.loadCompletedAgentWalletIdentity = loadCompletedAgentWalletIdentity;
|
|
41
|
+
exports.clearCompletedAgentWalletPending = clearCompletedAgentWalletPending;
|
|
42
|
+
const crypto_1 = require("crypto");
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const os_1 = require("os");
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const util_1 = require("util");
|
|
47
|
+
const crypto_2 = require("./core/crypto");
|
|
48
|
+
exports.MCP_PENDING_AGENT_WALLET_PATH = path.join((0, os_1.homedir)(), '.provian', 'pending-mcp-agent-wallet.json');
|
|
49
|
+
exports.MCP_AGENT_WALLET_IDENTITY_PATH = path.join((0, os_1.homedir)(), '.provian', 'agent-wallet-identity.json');
|
|
50
|
+
const PENDING_KEYS = [
|
|
51
|
+
'address',
|
|
52
|
+
'agent_id',
|
|
53
|
+
'agent_name',
|
|
54
|
+
'constitution_accepted_at',
|
|
55
|
+
'context_sha256',
|
|
56
|
+
'created_at_ms',
|
|
57
|
+
'encrypted_private_key',
|
|
58
|
+
'platform',
|
|
59
|
+
'public_key',
|
|
60
|
+
'registration_id',
|
|
61
|
+
'schema_version',
|
|
62
|
+
];
|
|
63
|
+
const ENCRYPTED_KEY_KEYS = [
|
|
64
|
+
'N',
|
|
65
|
+
'cipher',
|
|
66
|
+
'ciphertext',
|
|
67
|
+
'iv',
|
|
68
|
+
'kdf',
|
|
69
|
+
'p',
|
|
70
|
+
'r',
|
|
71
|
+
'salt',
|
|
72
|
+
'tag',
|
|
73
|
+
];
|
|
74
|
+
const FINAL_KEYS = ['pending_identity', 'schema_version', 'wallet_id'];
|
|
75
|
+
function isRecord(value) {
|
|
76
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
77
|
+
}
|
|
78
|
+
function hasExactKeys(value, expected) {
|
|
79
|
+
const actual = Object.keys(value).sort();
|
|
80
|
+
return actual.length === expected.length
|
|
81
|
+
&& actual.every((key, index) => key === expected[index]);
|
|
82
|
+
}
|
|
83
|
+
function hasPathEntry(filePath) {
|
|
84
|
+
try {
|
|
85
|
+
fs.lstatSync(filePath);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (error.code === 'ENOENT')
|
|
90
|
+
return false;
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function readPrivateJson(filePath, label) {
|
|
95
|
+
const noFollow = process.platform === 'win32' ? 0 : fs.constants.O_NOFOLLOW;
|
|
96
|
+
let fd;
|
|
97
|
+
try {
|
|
98
|
+
const pathStat = fs.lstatSync(filePath);
|
|
99
|
+
if (!pathStat.isFile() || pathStat.isSymbolicLink()) {
|
|
100
|
+
throw new Error(`${label} must be a private regular file`);
|
|
101
|
+
}
|
|
102
|
+
fd = fs.openSync(filePath, fs.constants.O_RDONLY | noFollow);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (error instanceof Error && error.message.startsWith(label))
|
|
106
|
+
throw error;
|
|
107
|
+
throw new Error(`${label} is missing, unreadable, or unsafe`);
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const stat = fs.fstatSync(fd);
|
|
111
|
+
if (!stat.isFile()
|
|
112
|
+
|| (process.platform !== 'win32' && (stat.mode & 0o077) !== 0)) {
|
|
113
|
+
throw new Error(`${label} must be a private 0600 regular file`);
|
|
114
|
+
}
|
|
115
|
+
return JSON.parse(fs.readFileSync(fd, 'utf8'));
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (error instanceof Error && error.message.startsWith(label))
|
|
119
|
+
throw error;
|
|
120
|
+
throw new Error(`${label} is malformed`);
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
fs.closeSync(fd);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function contextHash(context) {
|
|
127
|
+
return (0, crypto_1.createHash)('sha256').update(JSON.stringify({
|
|
128
|
+
relay_url: context.relay_url,
|
|
129
|
+
agent_name: context.agent_name,
|
|
130
|
+
requested_agent_id: context.requested_agent_id,
|
|
131
|
+
platform: context.platform,
|
|
132
|
+
}), 'utf8').digest('hex');
|
|
133
|
+
}
|
|
134
|
+
function validateContext(context) {
|
|
135
|
+
if (typeof context.relay_url !== 'string' || context.relay_url.trim().length === 0
|
|
136
|
+
|| typeof context.agent_name !== 'string' || context.agent_name.trim().length === 0
|
|
137
|
+
|| context.agent_name.length > 200
|
|
138
|
+
|| typeof context.platform !== 'string' || context.platform.trim().length === 0
|
|
139
|
+
|| context.platform.length > 64
|
|
140
|
+
|| (context.requested_agent_id !== null
|
|
141
|
+
&& !/^[A-Za-z0-9._-]{1,128}$/.test(context.requested_agent_id))) {
|
|
142
|
+
throw new Error('MCP wallet registration context is malformed');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function aad(file) {
|
|
146
|
+
return Buffer.from(JSON.stringify(file), 'utf8');
|
|
147
|
+
}
|
|
148
|
+
function deriveKey(passphrase, salt, N) {
|
|
149
|
+
return (0, crypto_1.scryptSync)(passphrase, salt, 32, { N, r: 8, p: 1, maxmem: 256 * N * 8 });
|
|
150
|
+
}
|
|
151
|
+
function parsePendingFile(value, expectedContext) {
|
|
152
|
+
if (!isRecord(value) || !hasExactKeys(value, PENDING_KEYS)) {
|
|
153
|
+
throw new Error('Pending MCP wallet identity has an unknown or incomplete schema');
|
|
154
|
+
}
|
|
155
|
+
const encrypted = value.encrypted_private_key;
|
|
156
|
+
if (!isRecord(encrypted) || !hasExactKeys(encrypted, ENCRYPTED_KEY_KEYS)) {
|
|
157
|
+
throw new Error('Pending MCP wallet encryption metadata has an unknown or incomplete schema');
|
|
158
|
+
}
|
|
159
|
+
if (value.schema_version !== 'provian-mcp-agent-wallet-pending/v1'
|
|
160
|
+
|| typeof value.context_sha256 !== 'string'
|
|
161
|
+
|| !/^[0-9a-f]{64}$/.test(value.context_sha256)
|
|
162
|
+
|| typeof value.registration_id !== 'string'
|
|
163
|
+
|| !/^[A-Za-z0-9][A-Za-z0-9_.:@-]{15,127}$/.test(value.registration_id)
|
|
164
|
+
|| typeof value.agent_id !== 'string'
|
|
165
|
+
|| !/^[A-Za-z0-9._-]{1,128}$/.test(value.agent_id)
|
|
166
|
+
|| typeof value.agent_name !== 'string'
|
|
167
|
+
|| value.agent_name.trim().length === 0
|
|
168
|
+
|| value.agent_name.length > 200
|
|
169
|
+
|| typeof value.platform !== 'string'
|
|
170
|
+
|| value.platform.trim().length === 0
|
|
171
|
+
|| value.platform.length > 64
|
|
172
|
+
|| typeof value.constitution_accepted_at !== 'string'
|
|
173
|
+
|| typeof value.created_at_ms !== 'number'
|
|
174
|
+
|| !Number.isSafeInteger(value.created_at_ms)
|
|
175
|
+
|| value.created_at_ms < 0
|
|
176
|
+
|| value.created_at_ms > 8640000000000000
|
|
177
|
+
|| new Date(value.created_at_ms).toISOString() !== value.constitution_accepted_at
|
|
178
|
+
|| typeof value.public_key !== 'string'
|
|
179
|
+
|| !/^[0-9a-f]{128}$/.test(value.public_key)
|
|
180
|
+
|| typeof value.address !== 'string'
|
|
181
|
+
|| !/^0x[0-9a-fA-F]{40}$/.test(value.address)
|
|
182
|
+
|| encrypted.cipher !== 'aes-256-gcm'
|
|
183
|
+
|| encrypted.kdf !== 'scrypt'
|
|
184
|
+
|| typeof encrypted.N !== 'number'
|
|
185
|
+
|| !Number.isSafeInteger(encrypted.N)
|
|
186
|
+
|| encrypted.N < 1 << 10
|
|
187
|
+
|| encrypted.N > 1 << 20
|
|
188
|
+
|| (encrypted.N & (encrypted.N - 1)) !== 0
|
|
189
|
+
|| encrypted.r !== 8
|
|
190
|
+
|| encrypted.p !== 1
|
|
191
|
+
|| typeof encrypted.salt !== 'string'
|
|
192
|
+
|| !/^[0-9a-f]{64}$/.test(encrypted.salt)
|
|
193
|
+
|| typeof encrypted.iv !== 'string'
|
|
194
|
+
|| !/^[0-9a-f]{24}$/.test(encrypted.iv)
|
|
195
|
+
|| typeof encrypted.tag !== 'string'
|
|
196
|
+
|| !/^[0-9a-f]{32}$/.test(encrypted.tag)
|
|
197
|
+
|| typeof encrypted.ciphertext !== 'string'
|
|
198
|
+
|| !/^[0-9a-f]{64}$/.test(encrypted.ciphertext)) {
|
|
199
|
+
throw new Error('Pending MCP wallet identity is malformed');
|
|
200
|
+
}
|
|
201
|
+
if (expectedContext
|
|
202
|
+
&& (value.context_sha256 !== contextHash(expectedContext)
|
|
203
|
+
|| value.agent_name !== expectedContext.agent_name
|
|
204
|
+
|| value.platform !== expectedContext.platform
|
|
205
|
+
|| (expectedContext.requested_agent_id !== null
|
|
206
|
+
&& value.agent_id !== expectedContext.requested_agent_id))) {
|
|
207
|
+
throw new Error('Pending MCP wallet identity does not match this relay/request context; refusing replacement');
|
|
208
|
+
}
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
function parseFinalFile(value) {
|
|
212
|
+
if (!isRecord(value) || !hasExactKeys(value, FINAL_KEYS)
|
|
213
|
+
|| value.schema_version !== 'provian-mcp-agent-wallet/v1'
|
|
214
|
+
|| typeof value.wallet_id !== 'string'
|
|
215
|
+
|| !/^wallet_aw_[A-Za-z0-9_-]+$/.test(value.wallet_id)) {
|
|
216
|
+
throw new Error('Completed MCP wallet identity is malformed');
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
schema_version: value.schema_version,
|
|
220
|
+
wallet_id: value.wallet_id,
|
|
221
|
+
pending_identity: parsePendingFile(value.pending_identity),
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function encryptPrivateKey(privateKey, header, passphrase, N) {
|
|
225
|
+
if (passphrase.length < 8)
|
|
226
|
+
throw new Error('PROVIAN_KEYSTORE_PASSPHRASE must be at least 8 characters');
|
|
227
|
+
const salt = (0, crypto_1.randomBytes)(32);
|
|
228
|
+
const iv = (0, crypto_1.randomBytes)(12);
|
|
229
|
+
const cipher = (0, crypto_1.createCipheriv)('aes-256-gcm', deriveKey(passphrase, salt, N), iv);
|
|
230
|
+
cipher.setAAD(aad(header));
|
|
231
|
+
const ciphertext = Buffer.concat([
|
|
232
|
+
cipher.update(Buffer.from(privateKey, 'hex')),
|
|
233
|
+
cipher.final(),
|
|
234
|
+
]);
|
|
235
|
+
return {
|
|
236
|
+
cipher: 'aes-256-gcm',
|
|
237
|
+
kdf: 'scrypt',
|
|
238
|
+
N,
|
|
239
|
+
r: 8,
|
|
240
|
+
p: 1,
|
|
241
|
+
salt: salt.toString('hex'),
|
|
242
|
+
iv: iv.toString('hex'),
|
|
243
|
+
tag: cipher.getAuthTag().toString('hex'),
|
|
244
|
+
ciphertext: ciphertext.toString('hex'),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function decryptPrivateKey(file, passphrase) {
|
|
248
|
+
const encrypted = file.encrypted_private_key;
|
|
249
|
+
const { encrypted_private_key: _encrypted, ...header } = file;
|
|
250
|
+
const decipher = (0, crypto_1.createDecipheriv)('aes-256-gcm', deriveKey(passphrase, Buffer.from(encrypted.salt, 'hex'), encrypted.N), Buffer.from(encrypted.iv, 'hex'));
|
|
251
|
+
decipher.setAAD(aad(header));
|
|
252
|
+
decipher.setAuthTag(Buffer.from(encrypted.tag, 'hex'));
|
|
253
|
+
try {
|
|
254
|
+
const privateKey = Buffer.concat([
|
|
255
|
+
decipher.update(Buffer.from(encrypted.ciphertext, 'hex')),
|
|
256
|
+
decipher.final(),
|
|
257
|
+
]).toString('hex');
|
|
258
|
+
if (!/^[0-9a-f]{64}$/.test(privateKey)
|
|
259
|
+
|| (0, crypto_2.deriveAddressFromPrivateKey)(privateKey).toLowerCase() !== file.address.toLowerCase()
|
|
260
|
+
|| (0, crypto_2.derivePublicKeyFromPrivateKey)(privateKey) !== file.public_key) {
|
|
261
|
+
throw new Error('Pending MCP wallet key does not match its declared identity');
|
|
262
|
+
}
|
|
263
|
+
return privateKey;
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
throw new Error('Unable to decrypt pending MCP wallet identity');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function atomicCreate(filePath, value) {
|
|
270
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
271
|
+
const temp = `${filePath}.${process.pid}.${(0, crypto_1.randomBytes)(8).toString('hex')}.tmp`;
|
|
272
|
+
const fd = fs.openSync(temp, 'wx', 0o600);
|
|
273
|
+
try {
|
|
274
|
+
fs.writeFileSync(fd, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
275
|
+
fs.fsyncSync(fd);
|
|
276
|
+
}
|
|
277
|
+
finally {
|
|
278
|
+
fs.closeSync(fd);
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
fs.linkSync(temp, filePath);
|
|
282
|
+
const dirFd = fs.openSync(path.dirname(filePath), 'r');
|
|
283
|
+
try {
|
|
284
|
+
fs.fsyncSync(dirFd);
|
|
285
|
+
}
|
|
286
|
+
finally {
|
|
287
|
+
fs.closeSync(dirFd);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
finally {
|
|
291
|
+
try {
|
|
292
|
+
fs.unlinkSync(temp);
|
|
293
|
+
}
|
|
294
|
+
catch { /* linked */ }
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function fsyncParentDirectory(filePath) {
|
|
298
|
+
const directoryFd = fs.openSync(path.dirname(filePath), 'r');
|
|
299
|
+
try {
|
|
300
|
+
fs.fsyncSync(directoryFd);
|
|
301
|
+
}
|
|
302
|
+
finally {
|
|
303
|
+
fs.closeSync(directoryFd);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function unlinkDurably(filePath) {
|
|
307
|
+
fs.unlinkSync(filePath);
|
|
308
|
+
fsyncParentDirectory(filePath);
|
|
309
|
+
}
|
|
310
|
+
function decodedPending(raw, context, passphrase) {
|
|
311
|
+
const file = parsePendingFile(raw, context);
|
|
312
|
+
return {
|
|
313
|
+
file,
|
|
314
|
+
registration: {
|
|
315
|
+
registrationId: file.registration_id,
|
|
316
|
+
agentId: file.agent_id,
|
|
317
|
+
agentName: file.agent_name,
|
|
318
|
+
platform: file.platform,
|
|
319
|
+
constitutionAcceptedAt: file.constitution_accepted_at,
|
|
320
|
+
privateKey: decryptPrivateKey(file, passphrase),
|
|
321
|
+
publicKey: file.public_key,
|
|
322
|
+
address: file.address,
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function readPending(context, passphrase, pendingPath) {
|
|
327
|
+
return decodedPending(readPrivateJson(pendingPath, 'Pending MCP wallet identity'), context, passphrase).registration;
|
|
328
|
+
}
|
|
329
|
+
function loadOrCreatePendingAgentWalletRegistration(context, passphrase, pendingPath = exports.MCP_PENDING_AGENT_WALLET_PATH, scryptN = 1 << 17) {
|
|
330
|
+
validateContext(context);
|
|
331
|
+
if (hasPathEntry(pendingPath))
|
|
332
|
+
return readPending(context, passphrase, pendingPath);
|
|
333
|
+
const slug = context.agent_name.toLowerCase()
|
|
334
|
+
.replace(/[^a-z0-9._-]+/g, '-')
|
|
335
|
+
.replace(/^[-.]+|[-.]+$/g, '') || 'mcp-agent';
|
|
336
|
+
const agentId = context.requested_agent_id ?? `${slug}-${(0, crypto_1.randomBytes)(3).toString('hex')}`;
|
|
337
|
+
if (!/^[A-Za-z0-9._-]{1,128}$/.test(agentId))
|
|
338
|
+
throw new Error('agent_id format is invalid');
|
|
339
|
+
const keyPair = (0, crypto_2.generateAgentKeyPair)();
|
|
340
|
+
const createdAtMs = Date.now();
|
|
341
|
+
const header = {
|
|
342
|
+
schema_version: 'provian-mcp-agent-wallet-pending/v1',
|
|
343
|
+
context_sha256: contextHash(context),
|
|
344
|
+
registration_id: `mcp-agent-registration-${(0, crypto_1.randomUUID)()}`,
|
|
345
|
+
agent_id: agentId,
|
|
346
|
+
agent_name: context.agent_name,
|
|
347
|
+
platform: context.platform,
|
|
348
|
+
constitution_accepted_at: new Date(createdAtMs).toISOString(),
|
|
349
|
+
public_key: keyPair.publicKey,
|
|
350
|
+
address: keyPair.address,
|
|
351
|
+
created_at_ms: createdAtMs,
|
|
352
|
+
};
|
|
353
|
+
const file = {
|
|
354
|
+
...header,
|
|
355
|
+
encrypted_private_key: encryptPrivateKey(keyPair.privateKey, header, passphrase, scryptN),
|
|
356
|
+
};
|
|
357
|
+
try {
|
|
358
|
+
atomicCreate(pendingPath, file);
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
if (error.code !== 'EEXIST')
|
|
362
|
+
throw error;
|
|
363
|
+
return readPending(context, passphrase, pendingPath);
|
|
364
|
+
}
|
|
365
|
+
return { ...readPending(context, passphrase, pendingPath) };
|
|
366
|
+
}
|
|
367
|
+
/** Re-read the encrypted pending bytes after the relay challenge and require
|
|
368
|
+
* them to match the exact identity used for that challenge. The create POST
|
|
369
|
+
* must be built only from this second authenticated snapshot. */
|
|
370
|
+
function reloadPendingAgentWalletRegistration(context, passphrase, expected, pendingPath = exports.MCP_PENDING_AGENT_WALLET_PATH) {
|
|
371
|
+
validateContext(context);
|
|
372
|
+
const reloaded = readPending(context, passphrase, pendingPath);
|
|
373
|
+
if (!(0, util_1.isDeepStrictEqual)(reloaded, expected)) {
|
|
374
|
+
throw new Error('Pending MCP wallet identity changed after the relay challenge');
|
|
375
|
+
}
|
|
376
|
+
return { ...reloaded };
|
|
377
|
+
}
|
|
378
|
+
function completePendingAgentWalletRegistration(registrationId, wallet, options) {
|
|
379
|
+
validateContext(options.context);
|
|
380
|
+
const pendingPath = options.pendingPath ?? exports.MCP_PENDING_AGENT_WALLET_PATH;
|
|
381
|
+
const finalPath = options.finalPath ?? exports.MCP_AGENT_WALLET_IDENTITY_PATH;
|
|
382
|
+
if (!/^wallet_aw_[A-Za-z0-9_-]+$/.test(wallet.wallet_id)
|
|
383
|
+
|| !/^0x[0-9a-fA-F]{40}$/.test(wallet.address)) {
|
|
384
|
+
throw new Error('Completed MCP wallet response has a malformed wallet identity');
|
|
385
|
+
}
|
|
386
|
+
const decoded = decodedPending(readPrivateJson(pendingPath, 'Pending MCP wallet identity'), options.context, options.passphrase);
|
|
387
|
+
const pending = decoded.file;
|
|
388
|
+
if (pending.registration_id !== registrationId
|
|
389
|
+
|| pending.address.toLowerCase() !== wallet.address.toLowerCase()) {
|
|
390
|
+
throw new Error('Pending MCP wallet identity changed before completion');
|
|
391
|
+
}
|
|
392
|
+
const final = {
|
|
393
|
+
schema_version: 'provian-mcp-agent-wallet/v1',
|
|
394
|
+
wallet_id: wallet.wallet_id,
|
|
395
|
+
pending_identity: pending,
|
|
396
|
+
};
|
|
397
|
+
if (hasPathEntry(finalPath)) {
|
|
398
|
+
const existing = parseFinalFile(readPrivateJson(finalPath, 'Completed MCP wallet identity'));
|
|
399
|
+
decodedPending(existing.pending_identity, options.context, options.passphrase);
|
|
400
|
+
if (!(0, util_1.isDeepStrictEqual)(existing, final)) {
|
|
401
|
+
throw new Error('A different final MCP wallet identity already exists');
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
atomicCreate(finalPath, final);
|
|
406
|
+
}
|
|
407
|
+
options.afterDurableStage?.('final_identity_durable');
|
|
408
|
+
unlinkDurably(pendingPath);
|
|
409
|
+
options.afterDurableStage?.('pending_identity_removed');
|
|
410
|
+
return finalPath;
|
|
411
|
+
}
|
|
412
|
+
function loadCompletedAgentWalletIdentity(passphrase, finalPath = exports.MCP_AGENT_WALLET_IDENTITY_PATH, expectedContext) {
|
|
413
|
+
if (expectedContext)
|
|
414
|
+
validateContext(expectedContext);
|
|
415
|
+
if (!hasPathEntry(finalPath))
|
|
416
|
+
return null;
|
|
417
|
+
const final = parseFinalFile(readPrivateJson(finalPath, 'Completed MCP wallet identity'));
|
|
418
|
+
const decoded = decodedPending(final.pending_identity, expectedContext, passphrase);
|
|
419
|
+
const pending = decoded.file;
|
|
420
|
+
return {
|
|
421
|
+
walletId: final.wallet_id,
|
|
422
|
+
...decoded.registration,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
/** Remove a retained pending file only after the final encrypted identity and
|
|
426
|
+
* separate exact same-wallet credentials have both been verified by the
|
|
427
|
+
* caller. This is the restart path for a crash after final-identity fsync. */
|
|
428
|
+
function clearCompletedAgentWalletPending(passphrase, expectedContext, pendingPath = exports.MCP_PENDING_AGENT_WALLET_PATH, finalPath = exports.MCP_AGENT_WALLET_IDENTITY_PATH) {
|
|
429
|
+
validateContext(expectedContext);
|
|
430
|
+
if (!hasPathEntry(pendingPath))
|
|
431
|
+
return;
|
|
432
|
+
const pending = decodedPending(readPrivateJson(pendingPath, 'Pending MCP wallet identity'), expectedContext, passphrase).file;
|
|
433
|
+
const final = parseFinalFile(readPrivateJson(finalPath, 'Completed MCP wallet identity'));
|
|
434
|
+
decodedPending(final.pending_identity, expectedContext, passphrase);
|
|
435
|
+
if (!(0, util_1.isDeepStrictEqual)(final.pending_identity, pending)) {
|
|
436
|
+
throw new Error('Pending MCP wallet identity conflicts with the completed identity');
|
|
437
|
+
}
|
|
438
|
+
unlinkDurably(pendingPath);
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=agent-wallet-registration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-wallet-registration.js","sourceRoot":"","sources":["../src/agent-wallet-registration.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6XA,gGAsCC;AAKD,oFAYC;AAED,wFA0CC;AAED,4EAgBC;AAKD,4EAqBC;AA5gBD,mCAOgB;AAChB,uCAAyB;AACzB,2BAA6B;AAC7B,2CAA6B;AAC7B,+BAAyC;AAEzC,0CAIuB;AAUV,QAAA,6BAA6B,GAAG,IAAI,CAAC,IAAI,CACpD,IAAA,YAAO,GAAE,EAAE,UAAU,EAAE,+BAA+B,CACvD,CAAC;AACW,QAAA,8BAA8B,GAAG,IAAI,CAAC,IAAI,CACrD,IAAA,YAAO,GAAE,EAAE,UAAU,EAAE,4BAA4B,CACpD,CAAC;AA8CF,MAAM,YAAY,GAAG;IACnB,SAAS;IACT,UAAU;IACV,YAAY;IACZ,0BAA0B;IAC1B,gBAAgB;IAChB,eAAe;IACf,uBAAuB;IACvB,UAAU;IACV,YAAY;IACZ,iBAAiB;IACjB,gBAAgB;CACR,CAAC;AACX,MAAM,kBAAkB,GAAG;IACzB,GAAG;IACH,QAAQ;IACR,YAAY;IACZ,IAAI;IACJ,KAAK;IACL,GAAG;IACH,GAAG;IACH,MAAM;IACN,KAAK;CACG,CAAC;AACX,MAAM,UAAU,GAAG,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,CAAU,CAAC;AAEhF,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,YAAY,CAAC,KAA8B,EAAE,QAA2B;IAC/E,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACzC,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;WACnC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB,EAAE,KAAa;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC;IAC5E,IAAI,EAAU,CAAC;IACf,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,iCAAiC,CAAC,CAAC;QAC7D,CAAC;QACD,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,oCAAoC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;eACb,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,sCAAsC,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAY,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC;IAC3C,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,OAAuC;IAC1D,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QAChD,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,eAAe,CAAC,OAAuC;IAC9D,IAAI,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WAC7E,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WAChF,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG;WAC/B,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WAC5E,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE;WAC5B,CAAC,OAAO,CAAC,kBAAkB,KAAK,IAAI;eAClC,CAAC,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,GAAG,CAAC,IAA2D;IACtE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,SAAS,CAAC,UAAkB,EAAE,IAAY,EAAE,CAAS;IAC5D,OAAO,IAAA,mBAAU,EAAC,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAc,EACd,eAAgD;IAEhD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC9C,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,kBAAkB,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,KAAK,qCAAqC;WAC7D,OAAO,KAAK,CAAC,cAAc,KAAK,QAAQ;WACxC,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;WAC5C,OAAO,KAAK,CAAC,eAAe,KAAK,QAAQ;WACzC,CAAC,uCAAuC,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC;WACpE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;WAClC,CAAC,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;WAC/C,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;WACpC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WACpC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG;WAC7B,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;WAClC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;WAClC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE;WAC1B,OAAO,KAAK,CAAC,wBAAwB,KAAK,QAAQ;WAClD,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ;WACvC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC;WAC1C,KAAK,CAAC,aAAa,GAAG,CAAC;WACvB,KAAK,CAAC,aAAa,GAAG,gBAAqB;WAC3C,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,wBAAwB;WAC9E,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;WACpC,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;WACzC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;WACjC,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;WAC1C,SAAS,CAAC,MAAM,KAAK,aAAa;WAClC,SAAS,CAAC,GAAG,KAAK,QAAQ;WAC1B,OAAO,SAAS,CAAC,CAAC,KAAK,QAAQ;WAC/B,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;WAClC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE;WACrB,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE;WACrB,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;WACvC,SAAS,CAAC,CAAC,KAAK,CAAC;WACjB,SAAS,CAAC,CAAC,KAAK,CAAC;WACjB,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ;WAClC,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;WACtC,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ;WAChC,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;WACpC,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ;WACjC,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;WACrC,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ;WACxC,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,eAAe;WACd,CAAC,KAAK,CAAC,cAAc,KAAK,WAAW,CAAC,eAAe,CAAC;eACpD,KAAK,CAAC,UAAU,KAAK,eAAe,CAAC,UAAU;eAC/C,KAAK,CAAC,QAAQ,KAAK,eAAe,CAAC,QAAQ;eAC3C,CAAC,eAAe,CAAC,kBAAkB,KAAK,IAAI;mBAC1C,KAAK,CAAC,QAAQ,KAAK,eAAe,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;IACJ,CAAC;IACD,OAAO,KAA0C,CAAC;AACpD,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC;WACnD,KAAK,CAAC,cAAc,KAAK,6BAA6B;WACtD,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;WACnC,CAAC,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO;QACL,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,gBAAgB,EAAE,gBAAgB,CAAC,KAAK,CAAC,gBAAgB,CAAC;KAC3D,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CACxB,UAAkB,EAClB,MAA6D,EAC7D,UAAkB,EAClB,CAAS;IAET,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IACxG,MAAM,IAAI,GAAG,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,EAAE,GAAG,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,aAAa,EAAE,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjF,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,EAAE;KACf,CAAC,CAAC;IACH,OAAO;QACL,MAAM,EAAE,aAAa;QACrB,GAAG,EAAE,QAAQ;QACb,CAAC;QACD,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC1B,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;QACtB,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;QACxC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAA4B,EAAE,UAAkB;IACzE,MAAM,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAC7C,MAAM,EAAE,qBAAqB,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9D,MAAM,QAAQ,GAAG,IAAA,yBAAgB,EAC/B,aAAa,EACb,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,EACtE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CACjC,CAAC;IACF,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;YAC/B,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACzD,QAAQ,CAAC,KAAK,EAAE;SACjB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC;eACjC,IAAA,oCAA2B,EAAC,UAAU,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;eACpF,IAAA,sCAA6B,EAAC,UAAU,CAAC,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB,EAAE,KAAc;IACpD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,IAAI,IAAA,oBAAW,EAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IAChF,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC;YAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB;IAC5C,MAAM,WAAW,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC5B,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACxB,oBAAoB,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,cAAc,CACrB,GAAY,EACZ,OAAmD,EACnD,UAAkB;IAElB,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO;QACL,IAAI;QACJ,YAAY,EAAE;YACZ,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,SAAS,EAAE,IAAI,CAAC,UAAU;YAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,sBAAsB,EAAE,IAAI,CAAC,wBAAwB;YACrD,UAAU,EAAE,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC;YAC/C,SAAS,EAAE,IAAI,CAAC,UAAU;YAC1B,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,OAAuC,EACvC,UAAkB,EAClB,WAAmB;IAEnB,OAAO,cAAc,CACnB,eAAe,CAAC,WAAW,EAAE,6BAA6B,CAAC,EAC3D,OAAO,EACP,UAAU,CACX,CAAC,YAAY,CAAC;AACjB,CAAC;AAED,SAAgB,0CAA0C,CACxD,OAAuC,EACvC,UAAkB,EAClB,cAAsB,qCAA6B,EACnD,OAAO,GAAG,CAAC,IAAI,EAAE;IAEjB,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,YAAY,CAAC,WAAW,CAAC;QAAE,OAAO,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE;SAC1C,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,kBAAkB,IAAI,GAAG,IAAI,IAAI,IAAA,oBAAW,EAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;IAC1F,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC5F,MAAM,OAAO,GAAG,IAAA,6BAAoB,GAAE,CAAC;IACvC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,MAAM,MAAM,GAA0D;QACpE,cAAc,EAAE,qCAAqC;QACrD,cAAc,EAAE,WAAW,CAAC,OAAO,CAAC;QACpC,eAAe,EAAE,0BAA0B,IAAA,mBAAU,GAAE,EAAE;QACzD,QAAQ,EAAE,OAAO;QACjB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,wBAAwB,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE;QAC7D,UAAU,EAAE,OAAO,CAAC,SAAS;QAC7B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,aAAa,EAAE,WAAW;KAC3B,CAAC;IACF,MAAM,IAAI,GAA2B;QACnC,GAAG,MAAM;QACT,qBAAqB,EAAE,iBAAiB,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC;KAC1F,CAAC;IACF,IAAI,CAAC;QACH,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,KAAK,CAAC;QACpE,OAAO,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED;;iEAEiE;AACjE,SAAgB,oCAAoC,CAClD,OAAuC,EACvC,UAAkB,EAClB,QAAwC,EACxC,cAAsB,qCAA6B;IAEnD,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAC/D,IAAI,CAAC,IAAA,wBAAiB,EAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;AACzB,CAAC;AAED,SAAgB,sCAAsC,CACpD,cAAsB,EACtB,MAA8C,EAC9C,OAA+C;IAE/C,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,qCAA6B,CAAC;IACzE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,sCAA8B,CAAC;IACtE,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;WACnD,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,OAAO,GAAG,cAAc,CAC5B,eAAe,CAAC,WAAW,EAAE,6BAA6B,CAAC,EAC3D,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,UAAU,CACnB,CAAC;IACF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAC7B,IAAI,OAAO,CAAC,eAAe,KAAK,cAAc;WACzC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,KAAK,GAAyB;QAClC,cAAc,EAAE,6BAA6B;QAC7C,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,gBAAgB,EAAE,OAAO;KAC1B,CAAC;IACF,IAAI,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,cAAc,CAC7B,eAAe,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAC5D,CAAC;QACF,cAAc,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QAC/E,IAAI,CAAC,IAAA,wBAAiB,EAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,CAAC,iBAAiB,EAAE,CAAC,wBAAwB,CAAC,CAAC;IACtD,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3B,OAAO,CAAC,iBAAiB,EAAE,CAAC,0BAA0B,CAAC,CAAC;IACxD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,gCAAgC,CAC9C,UAAkB,EAClB,YAAoB,sCAA8B,EAClD,eAAgD;IAEhD,IAAI,eAAe;QAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IACtD,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,KAAK,GAAG,cAAc,CAC1B,eAAe,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAC5D,CAAC;IACF,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,gBAAgB,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;IACpF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAC7B,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,SAAS;QACzB,GAAG,OAAO,CAAC,YAAY;KACxB,CAAC;AACJ,CAAC;AAED;;8EAE8E;AAC9E,SAAgB,gCAAgC,CAC9C,UAAkB,EAClB,eAA+C,EAC/C,cAAsB,qCAA6B,EACnD,YAAoB,sCAA8B;IAElD,eAAe,CAAC,eAAe,CAAC,CAAC;IACjC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC;QAAE,OAAO;IACvC,MAAM,OAAO,GAAG,cAAc,CAC5B,eAAe,CAAC,WAAW,EAAE,6BAA6B,CAAC,EAC3D,eAAe,EACf,UAAU,CACX,CAAC,IAAI,CAAC;IACP,MAAM,KAAK,GAAG,cAAc,CAC1B,eAAe,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAC5D,CAAC;IACF,cAAc,CAAC,KAAK,CAAC,gBAAgB,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;IACpE,IAAI,CAAC,IAAA,wBAAiB,EAAC,KAAK,CAAC,gBAAgB,EAAE,OAAO,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACvF,CAAC;IACD,aAAa,CAAC,WAAW,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SIGNED CHALLENGES (`provian-challenge-v1`,) — the requester's half of burn-to-present, for
|
|
3
|
+
* the MCP tool core.
|
|
4
|
+
*
|
|
5
|
+
* SHARED CORE — canonical in `provian-mcp/src/core/`, mirrored byte-identically into
|
|
6
|
+
* `provian-backend/src/mcp/core/`. Edit only the canonical copy and run `scripts/sync-mcp-core.sh`.
|
|
7
|
+
*
|
|
8
|
+
* A byte-for-byte port of the relay's `core/presentation/challenge.ts` (signing string, predicate
|
|
9
|
+
* digest, parse, structural rules, Ed25519 verdict). The MCP core cannot import the relay or the
|
|
10
|
+
* SDK, so it carries its own audited copy, pinned by the fixed vectors in
|
|
11
|
+
* `challenge.test.ts` the same vectors every other package pins.
|
|
12
|
+
*
|
|
13
|
+
* A requester hands a presenter `{ v, audience, challenge, predicates?, issuedAt, expiresAt,
|
|
14
|
+
* presenter?, requester, sig }`. With `requester`/`sig` it is SIGNED (Ed25519): a domain requester
|
|
15
|
+
* with its own key published at `https://<domain>/.well-known/provian-requester.json`, a wallet
|
|
16
|
+
* requester by the RELAY with the Provian presentation key (`/v1/present/jwks`) after it
|
|
17
|
+
* authenticated that wallet. `audience === requester.id`, so the presentation's `aud` IS the
|
|
18
|
+
* verified requester. An unsigned legacy `{ audience, challenge, predicates? }` stays valid and is
|
|
19
|
+
* shown UNVERIFIED; a signed challenge failing any check is INVALID and refused (Unknown = Block).
|
|
20
|
+
*
|
|
21
|
+
* The one outbound fetch here (a domain requester's key document) is SSRF-guarded to the same bar
|
|
22
|
+
* as the relay (Security Invariant #6): hostname regex (no IP literals, no localhost), resolve and
|
|
23
|
+
* refuse ANY private address, pin the socket to the validated address (no DNS-rebinding TOCTOU),
|
|
24
|
+
* https only, no redirects, ≤ 64 KiB, ≤ 5 s. Node built-ins only, so the relay mirror compiles with
|
|
25
|
+
* nothing new.
|
|
26
|
+
*/
|
|
27
|
+
import { requesterString, type PredicateRequest } from './presentation';
|
|
28
|
+
import { type CanonicalDisclosureRequest } from './disclosure-request';
|
|
29
|
+
export declare const CHALLENGE_SIGNING_TAG = "provian-challenge-v1";
|
|
30
|
+
export declare const CHALLENGE_ENVELOPE_VERSION: 1;
|
|
31
|
+
/** The requester key document path under the requester's domain. */
|
|
32
|
+
export declare const REQUESTER_WELL_KNOWN_PATH = "/.well-known/provian-requester.json";
|
|
33
|
+
/** Signed-challenge lifetime bounds (seconds): 60 s .. 7 days. */
|
|
34
|
+
export declare const CHALLENGE_MIN_TTL_SECONDS = 60;
|
|
35
|
+
export declare const CHALLENGE_MAX_TTL_SECONDS: number;
|
|
36
|
+
/** Local gates default to 15 minutes. */
|
|
37
|
+
export declare const CHALLENGE_DEFAULT_TTL_SECONDS = 900;
|
|
38
|
+
export declare const REQUESTER_KEYS_MAX_BYTES: number;
|
|
39
|
+
export declare const REQUESTER_KEYS_TIMEOUT_MS = 5000;
|
|
40
|
+
export declare const REQUESTER_KEYS_CACHE_MS: number;
|
|
41
|
+
export type RequesterType = 'domain' | 'wallet';
|
|
42
|
+
export interface RequesterIdentity {
|
|
43
|
+
readonly type: RequesterType;
|
|
44
|
+
readonly id: string;
|
|
45
|
+
/** wallet only. */
|
|
46
|
+
readonly address?: string;
|
|
47
|
+
}
|
|
48
|
+
export { requesterString };
|
|
49
|
+
export interface EnvelopeRequester {
|
|
50
|
+
readonly type: RequesterType;
|
|
51
|
+
/** domain: the hostname. wallet: the Provian wallet id. */
|
|
52
|
+
readonly id: string;
|
|
53
|
+
/** wallet only: the wallet's lowercase EVM address (Provian-attested). */
|
|
54
|
+
readonly address?: string;
|
|
55
|
+
/** The Ed25519 key id — the domain's well-known kid, or the Provian JWKS kid for a wallet. */
|
|
56
|
+
readonly kid: string;
|
|
57
|
+
}
|
|
58
|
+
export interface ChallengeEnvelope {
|
|
59
|
+
readonly v?: number;
|
|
60
|
+
readonly audience: string;
|
|
61
|
+
readonly challenge: string;
|
|
62
|
+
readonly predicates?: readonly PredicateRequest[];
|
|
63
|
+
/** Requester-named disclosure requests (2026-10-10). */
|
|
64
|
+
readonly disclosures?: readonly CanonicalDisclosureRequest[];
|
|
65
|
+
readonly issuedAt?: number;
|
|
66
|
+
readonly expiresAt?: number;
|
|
67
|
+
readonly presenter?: string;
|
|
68
|
+
readonly requester?: EnvelopeRequester;
|
|
69
|
+
readonly sig?: string;
|
|
70
|
+
}
|
|
71
|
+
/** One Ed25519 public key from a requester's well-known document (or the Provian JWKS). */
|
|
72
|
+
export interface RequesterJwk {
|
|
73
|
+
readonly kty: string;
|
|
74
|
+
readonly crv?: string;
|
|
75
|
+
readonly x?: string;
|
|
76
|
+
readonly kid: string;
|
|
77
|
+
}
|
|
78
|
+
/** Fetch a domain requester's published keys. Throws when unreachable / malformed. */
|
|
79
|
+
export type FetchRequesterKeys = (domain: string) => Promise<readonly RequesterJwk[]>;
|
|
80
|
+
/** The Provian presentation public keys, or a lazy loader for them (fetched only for a wallet requester). */
|
|
81
|
+
export type ProvianChallengeKeys = readonly RequesterJwk[] | (() => Promise<readonly RequesterJwk[]>);
|
|
82
|
+
export type ChallengeInvalidReason = 'malformed' | 'unsupported_version' | 'bad_requester' | 'audience_not_requester' | 'bad_window' | 'bad_presenter' | 'bad_signature' | 'key_not_found' | 'requester_key_unreachable';
|
|
83
|
+
export type ChallengeVerdict = {
|
|
84
|
+
readonly status: 'verified';
|
|
85
|
+
readonly requester: RequesterIdentity;
|
|
86
|
+
readonly envelope: ChallengeEnvelope;
|
|
87
|
+
} | {
|
|
88
|
+
readonly status: 'unverified';
|
|
89
|
+
readonly envelope: ChallengeEnvelope;
|
|
90
|
+
} | {
|
|
91
|
+
readonly status: 'invalid';
|
|
92
|
+
readonly reason: ChallengeInvalidReason;
|
|
93
|
+
readonly envelope?: ChallengeEnvelope;
|
|
94
|
+
} | {
|
|
95
|
+
readonly status: 'expired';
|
|
96
|
+
readonly requester: RequesterIdentity;
|
|
97
|
+
readonly envelope: ChallengeEnvelope;
|
|
98
|
+
} | {
|
|
99
|
+
readonly status: 'not_addressed';
|
|
100
|
+
readonly requester: RequesterIdentity;
|
|
101
|
+
readonly envelope: ChallengeEnvelope;
|
|
102
|
+
};
|
|
103
|
+
/** True when the envelope carries a requester signature (identity claim). */
|
|
104
|
+
export declare function isSignedChallenge(env: ChallengeEnvelope): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Parse an untrusted challenge envelope (object or JSON string). Structural only — no signature
|
|
107
|
+
* check. Returns null when it is not a well-formed challenge (legacy or signed).
|
|
108
|
+
*/
|
|
109
|
+
export declare function parseChallengeEnvelope(raw: unknown): ChallengeEnvelope | null;
|
|
110
|
+
/** sha256 hex of the canonical (sorted, normalized) predicate list — the signing-string commitment. */
|
|
111
|
+
export declare function challengePredicatesDigest(predicates: readonly PredicateRequest[] | undefined): string;
|
|
112
|
+
/** The exact bytes a requester signs. Fixed line order, `\n`-joined, no trailing newline. */
|
|
113
|
+
export declare function challengeSigningString(env: {
|
|
114
|
+
audience: string;
|
|
115
|
+
challenge: string;
|
|
116
|
+
issuedAt: number;
|
|
117
|
+
expiresAt: number;
|
|
118
|
+
requester: {
|
|
119
|
+
type: RequesterType;
|
|
120
|
+
id: string;
|
|
121
|
+
address?: string;
|
|
122
|
+
kid: string;
|
|
123
|
+
};
|
|
124
|
+
presenter?: string;
|
|
125
|
+
predicates?: readonly PredicateRequest[];
|
|
126
|
+
disclosures?: readonly CanonicalDisclosureRequest[];
|
|
127
|
+
}): string;
|
|
128
|
+
/** Structural rules for a SIGNED envelope (A.2), excluding the signature itself. */
|
|
129
|
+
export declare function checkSignedStructure(env: ChallengeEnvelope): ChallengeInvalidReason | null;
|
|
130
|
+
/**
|
|
131
|
+
* Verify a challenge envelope the way a presenter surface must BEFORE burning (A.3). Unsigned →
|
|
132
|
+
* `unverified`; signed and every check passes → `verified` (or `expired` / `not_addressed` when
|
|
133
|
+
* the signature holds but the deadline passed / the challenge names another presenter); any
|
|
134
|
+
* failure → `invalid`. A domain requester needs `fetchRequesterKeys`; a wallet requester needs
|
|
135
|
+
* `provianKeys` (the Provian presentation JWKS, or a lazy loader for it).
|
|
136
|
+
*/
|
|
137
|
+
export declare function verifyChallengeEnvelope(env: ChallengeEnvelope, opts?: {
|
|
138
|
+
fetchRequesterKeys?: FetchRequesterKeys;
|
|
139
|
+
provianKeys?: ProvianChallengeKeys;
|
|
140
|
+
nowSeconds?: number;
|
|
141
|
+
presenterAddress?: string;
|
|
142
|
+
}): Promise<ChallengeVerdict>;
|
|
143
|
+
/** Parse a well-known requester key document body (or a JWKS). Throws on a malformed document. */
|
|
144
|
+
export declare function parseRequesterKeyDocument(body: unknown): RequesterJwk[];
|
|
145
|
+
export interface RequesterVerdictView {
|
|
146
|
+
readonly status: ChallengeVerdict['status'];
|
|
147
|
+
/** The verified (or signature-verified but refused) identity; null for unsigned / invalid. */
|
|
148
|
+
readonly identity: RequesterIdentity | null;
|
|
149
|
+
/** invalid only: why. */
|
|
150
|
+
readonly reason?: ChallengeInvalidReason;
|
|
151
|
+
/** One line a presenter surface shows. */
|
|
152
|
+
readonly display: string;
|
|
153
|
+
}
|
|
154
|
+
export declare function describeVerdict(v: ChallengeVerdict): RequesterVerdictView;
|
|
155
|
+
/** A fresh unsigned (legacy) challenge in the wire shape. Presenters see it as UNVERIFIED. */
|
|
156
|
+
export declare function issueUnsignedChallenge(input: {
|
|
157
|
+
audience: string;
|
|
158
|
+
predicates?: readonly PredicateRequest[];
|
|
159
|
+
disclosures?: readonly CanonicalDisclosureRequest[];
|
|
160
|
+
ttlSeconds?: number;
|
|
161
|
+
presenter?: string;
|
|
162
|
+
nowSeconds?: number;
|
|
163
|
+
}): ChallengeEnvelope;
|
|
164
|
+
/**
|
|
165
|
+
* Private / internal / non-routable address predicate. Anything it cannot parse as a public IPv4 /
|
|
166
|
+
* IPv6 address is treated as private (fail-closed). A superset of the relay's `isPrivateIp`
|
|
167
|
+
* (adds CGNAT, multicast/reserved, IPv6 multicast, NAT64 / 6to4 which can embed a private v4).
|
|
168
|
+
*/
|
|
169
|
+
export declare function isPrivateIp(ip: string): boolean;
|
|
170
|
+
/** A requester domain the guard will fetch from: the spec's hostname regex, never localhost. */
|
|
171
|
+
export declare function isAllowedRequesterDomain(domain: string): boolean;
|
|
172
|
+
export interface RequesterKeyFetchDeps {
|
|
173
|
+
/** Resolve a hostname to A + AAAA addresses (test seam). */
|
|
174
|
+
readonly resolveHostname?: (hostname: string) => Promise<string[]>;
|
|
175
|
+
/** Perform the pinned GET (test seam). Resolves the body, or null on any non-2xx / failure. */
|
|
176
|
+
readonly get?: (url: string, pinnedIp: string) => Promise<Buffer | null>;
|
|
177
|
+
readonly nowMs?: () => number;
|
|
178
|
+
}
|
|
179
|
+
/** Clear the per-domain key cache (tests / key rotation). */
|
|
180
|
+
export declare function clearRequesterKeyCache(): void;
|
|
181
|
+
/**
|
|
182
|
+
* Fetch a domain requester's Ed25519 keys, SSRF-guarded. Throws on any failure (the caller maps a
|
|
183
|
+
* throw to `requester_key_unreachable`, never to a verified identity). Cached 5 minutes per domain
|
|
184
|
+
* so one requester cannot turn a presenter surface into a request amplifier.
|
|
185
|
+
*/
|
|
186
|
+
export declare function fetchRequesterKeysGuarded(domain: string, deps?: RequesterKeyFetchDeps): Promise<RequesterJwk[]>;
|
|
187
|
+
//# sourceMappingURL=challenge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge.d.ts","sourceRoot":"","sources":["../../src/core/challenge.ts"],"names":[],"mappings":"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"}
|