@blink-authority-com/claude-code-plugin 1.0.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/LICENSE +21 -0
- package/README.md +146 -0
- package/dist/bsec-client.d.ts +35 -0
- package/dist/bsec-client.d.ts.map +1 -0
- package/dist/bsec-client.js +122 -0
- package/dist/bsec-client.js.map +1 -0
- package/dist/docs/cache.d.ts +19 -0
- package/dist/docs/cache.d.ts.map +1 -0
- package/dist/docs/cache.js +92 -0
- package/dist/docs/cache.js.map +1 -0
- package/dist/docs/fetcher.d.ts +19 -0
- package/dist/docs/fetcher.d.ts.map +1 -0
- package/dist/docs/fetcher.js +81 -0
- package/dist/docs/fetcher.js.map +1 -0
- package/dist/docs/parser.d.ts +33 -0
- package/dist/docs/parser.d.ts.map +1 -0
- package/dist/docs/parser.js +145 -0
- package/dist/docs/parser.js.map +1 -0
- package/dist/docs/search.d.ts +38 -0
- package/dist/docs/search.d.ts.map +1 -0
- package/dist/docs/search.js +180 -0
- package/dist/docs/search.js.map +1 -0
- package/dist/docs/tools/api.d.ts +12 -0
- package/dist/docs/tools/api.d.ts.map +1 -0
- package/dist/docs/tools/api.js +58 -0
- package/dist/docs/tools/api.js.map +1 -0
- package/dist/docs/tools/cli.d.ts +12 -0
- package/dist/docs/tools/cli.d.ts.map +1 -0
- package/dist/docs/tools/cli.js +56 -0
- package/dist/docs/tools/cli.js.map +1 -0
- package/dist/docs/tools/concepts.d.ts +18 -0
- package/dist/docs/tools/concepts.d.ts.map +1 -0
- package/dist/docs/tools/concepts.js +136 -0
- package/dist/docs/tools/concepts.js.map +1 -0
- package/dist/docs/tools/sdk.d.ts +12 -0
- package/dist/docs/tools/sdk.d.ts.map +1 -0
- package/dist/docs/tools/sdk.js +72 -0
- package/dist/docs/tools/sdk.js.map +1 -0
- package/dist/docs/tools/search.d.ts +11 -0
- package/dist/docs/tools/search.d.ts.map +1 -0
- package/dist/docs/tools/search.js +36 -0
- package/dist/docs/tools/search.js.map +1 -0
- package/dist/docs/types.d.ts +70 -0
- package/dist/docs/types.d.ts.map +1 -0
- package/dist/docs/types.js +8 -0
- package/dist/docs/types.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +622 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/debug.d.ts +16 -0
- package/dist/prompts/debug.d.ts.map +1 -0
- package/dist/prompts/debug.js +34 -0
- package/dist/prompts/debug.js.map +1 -0
- package/dist/prompts/integrate.d.ts +16 -0
- package/dist/prompts/integrate.d.ts.map +1 -0
- package/dist/prompts/integrate.js +30 -0
- package/dist/prompts/integrate.js.map +1 -0
- package/dist/prompts/review.d.ts +16 -0
- package/dist/prompts/review.d.ts.map +1 -0
- package/dist/prompts/review.js +28 -0
- package/dist/prompts/review.js.map +1 -0
- package/dist/resources/changelog.d.ts +22 -0
- package/dist/resources/changelog.d.ts.map +1 -0
- package/dist/resources/changelog.js +55 -0
- package/dist/resources/changelog.js.map +1 -0
- package/dist/resources/errors.d.ts +16 -0
- package/dist/resources/errors.d.ts.map +1 -0
- package/dist/resources/errors.js +103 -0
- package/dist/resources/errors.js.map +1 -0
- package/dist/resources/patterns.d.ts +16 -0
- package/dist/resources/patterns.d.ts.map +1 -0
- package/dist/resources/patterns.js +151 -0
- package/dist/resources/patterns.js.map +1 -0
- package/dist/templates/approval-workflow.d.ts +6 -0
- package/dist/templates/approval-workflow.d.ts.map +1 -0
- package/dist/templates/approval-workflow.js +467 -0
- package/dist/templates/approval-workflow.js.map +1 -0
- package/dist/templates/audit-trail.d.ts +6 -0
- package/dist/templates/audit-trail.d.ts.map +1 -0
- package/dist/templates/audit-trail.js +396 -0
- package/dist/templates/audit-trail.js.map +1 -0
- package/dist/templates/cli-tool.d.ts +6 -0
- package/dist/templates/cli-tool.d.ts.map +1 -0
- package/dist/templates/cli-tool.js +346 -0
- package/dist/templates/cli-tool.js.map +1 -0
- package/dist/templates/express-api.d.ts +6 -0
- package/dist/templates/express-api.d.ts.map +1 -0
- package/dist/templates/express-api.js +314 -0
- package/dist/templates/express-api.js.map +1 -0
- package/dist/templates/notary.d.ts +6 -0
- package/dist/templates/notary.d.ts.map +1 -0
- package/dist/templates/notary.js +360 -0
- package/dist/templates/notary.js.map +1 -0
- package/dist/test.d.ts +8 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +140 -0
- package/dist/test.js.map +1 -0
- package/dist/tools/add-signing.d.ts +19 -0
- package/dist/tools/add-signing.d.ts.map +1 -0
- package/dist/tools/add-signing.js +317 -0
- package/dist/tools/add-signing.js.map +1 -0
- package/dist/tools/decode.d.ts +13 -0
- package/dist/tools/decode.d.ts.map +1 -0
- package/dist/tools/decode.js +262 -0
- package/dist/tools/decode.js.map +1 -0
- package/dist/tools/hierarchy.d.ts +13 -0
- package/dist/tools/hierarchy.d.ts.map +1 -0
- package/dist/tools/hierarchy.js +319 -0
- package/dist/tools/hierarchy.js.map +1 -0
- package/dist/tools/lint.d.ts +13 -0
- package/dist/tools/lint.d.ts.map +1 -0
- package/dist/tools/lint.js +323 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/scaffold.d.ts +11 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +84 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/sign-test.d.ts +17 -0
- package/dist/tools/sign-test.d.ts.map +1 -0
- package/dist/tools/sign-test.js +126 -0
- package/dist/tools/sign-test.js.map +1 -0
- package/dist/tools/test-vectors.d.ts +13 -0
- package/dist/tools/test-vectors.d.ts.map +1 -0
- package/dist/tools/test-vectors.js +169 -0
- package/dist/tools/test-vectors.js.map +1 -0
- package/dist/tools/verify-local.d.ts +17 -0
- package/dist/tools/verify-local.d.ts.map +1 -0
- package/dist/tools/verify-local.js +233 -0
- package/dist/tools/verify-local.js.map +1 -0
- package/dist/tools/verify-test.d.ts +17 -0
- package/dist/tools/verify-test.d.ts.map +1 -0
- package/dist/tools/verify-test.js +107 -0
- package/dist/tools/verify-test.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* blink_add_signing tool handler.
|
|
3
|
+
*
|
|
4
|
+
* Takes existing code and a signing pattern, returns enhanced code
|
|
5
|
+
* with BLINK signing added. Uses string manipulation (not AST) for v1.
|
|
6
|
+
*
|
|
7
|
+
* Patterns:
|
|
8
|
+
* sign-response — Add BLINK signing middleware to Express responses
|
|
9
|
+
* sign-document — Add document hashing + BLINK signing
|
|
10
|
+
* sign-audit-entry — Add hash-chained audit entry signing
|
|
11
|
+
* verify-incoming — Add incoming signature verification
|
|
12
|
+
*/
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Imports to inject per pattern
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const BLINK_IMPORTS = {
|
|
17
|
+
'sign-response': `import { BlinkSigner, AlgoSuiteId } from '@blink-technology/sdk';`,
|
|
18
|
+
'sign-document': `import { BlinkSigner, AlgoSuiteId } from '@blink-technology/sdk';
|
|
19
|
+
import { createHash } from 'node:crypto';`,
|
|
20
|
+
'sign-audit-entry': `import { BlinkSigner, AlgoSuiteId } from '@blink-technology/sdk';
|
|
21
|
+
import { createHash } from 'node:crypto';`,
|
|
22
|
+
'verify-incoming': `import { BlinkVerifier } from '@blink-technology/sdk';`,
|
|
23
|
+
};
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// BLINK initialization snippet (added if not already present)
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
const BLINK_INIT = `
|
|
28
|
+
// --- BLINK Authority: Signer lifecycle ---
|
|
29
|
+
let blinkSigner: BlinkSigner;
|
|
30
|
+
let blinkPublicKey: Uint8Array;
|
|
31
|
+
|
|
32
|
+
async function initBlink(): Promise<void> {
|
|
33
|
+
const bsecUrl = process.env['BSEC_URL'] ?? 'http://localhost:9100';
|
|
34
|
+
const slotName = process.env['SLOT_NAME'] ?? 'default';
|
|
35
|
+
blinkSigner = await BlinkSigner.connect(bsecUrl, slotName, AlgoSuiteId.Ed25519);
|
|
36
|
+
blinkPublicKey = await blinkSigner.vrfPublicKey();
|
|
37
|
+
console.log('[blink] Connected to BSEC');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function shutdownBlink(): Promise<void> {
|
|
41
|
+
if (blinkSigner) {
|
|
42
|
+
await blinkSigner.close();
|
|
43
|
+
console.log('[blink] Disconnected');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// --- End BLINK init ---
|
|
47
|
+
`;
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Pattern-specific code snippets
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
const SIGN_RESPONSE_MIDDLEWARE = `
|
|
52
|
+
// --- BLINK Authority: Signing middleware ---
|
|
53
|
+
// This middleware intercepts res.json() calls and adds a BLINK signature.
|
|
54
|
+
// The signature envelope is attached as HTTP headers.
|
|
55
|
+
function blinkSigningMiddleware() {
|
|
56
|
+
return (req: any, res: any, next: any) => {
|
|
57
|
+
const originalJson = res.json.bind(res);
|
|
58
|
+
res.json = (body: unknown) => {
|
|
59
|
+
const bodyStr = JSON.stringify(body);
|
|
60
|
+
const payload = new TextEncoder().encode(bodyStr);
|
|
61
|
+
blinkSigner.sign(payload)
|
|
62
|
+
.then((envelopeBytes: Uint8Array) => {
|
|
63
|
+
res.setHeader('X-BLINK-Signature', Buffer.from(envelopeBytes).toString('base64'));
|
|
64
|
+
res.setHeader('X-BLINK-PublicKey', Buffer.from(blinkPublicKey).toString('hex'));
|
|
65
|
+
res.setHeader('X-BLINK-Signed', 'true');
|
|
66
|
+
originalJson(body);
|
|
67
|
+
})
|
|
68
|
+
.catch((err: Error) => {
|
|
69
|
+
console.error('[blink] Signing failed:', err);
|
|
70
|
+
res.setHeader('X-BLINK-Signed', 'false');
|
|
71
|
+
originalJson(body);
|
|
72
|
+
});
|
|
73
|
+
return res;
|
|
74
|
+
};
|
|
75
|
+
next();
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// --- End BLINK signing middleware ---
|
|
79
|
+
`;
|
|
80
|
+
const SIGN_DOCUMENT_CODE = `
|
|
81
|
+
// --- BLINK Authority: Document signing ---
|
|
82
|
+
// Hash the document with SHA-256, then sign the hash with BLINK.
|
|
83
|
+
// Returns a notarization certificate with the signature envelope.
|
|
84
|
+
async function signDocument(fileBuffer: Buffer, filename: string) {
|
|
85
|
+
const hash = createHash('sha256').update(new Uint8Array(fileBuffer)).digest();
|
|
86
|
+
const hashBytes = new Uint8Array(hash.buffer, hash.byteOffset, hash.byteLength);
|
|
87
|
+
|
|
88
|
+
// Sign the hash — BLINK produces a single-use credential for this operation
|
|
89
|
+
const envelopeBytes = await blinkSigner.signDetached(hashBytes);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
document: { filename, size: fileBuffer.length, hash: hash.toString('hex') },
|
|
93
|
+
envelope: Buffer.from(envelopeBytes).toString('base64'),
|
|
94
|
+
signerPublicKey: Buffer.from(blinkPublicKey).toString('hex'),
|
|
95
|
+
signedAt: new Date().toISOString(),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// --- End BLINK document signing ---
|
|
99
|
+
`;
|
|
100
|
+
const SIGN_AUDIT_ENTRY_CODE = `
|
|
101
|
+
// --- BLINK Authority: Hash-chained audit entry signing ---
|
|
102
|
+
// Each entry links to the previous via SHA-256(previous envelope).
|
|
103
|
+
// The first entry uses GENESIS_HASH as its previous hash.
|
|
104
|
+
const GENESIS_HASH = '0'.repeat(64);
|
|
105
|
+
let lastEnvelopeHash = GENESIS_HASH;
|
|
106
|
+
let auditSequence = 0;
|
|
107
|
+
|
|
108
|
+
async function signAuditEntry(entry: {
|
|
109
|
+
actor: string;
|
|
110
|
+
action: string;
|
|
111
|
+
resource: string;
|
|
112
|
+
detail?: string;
|
|
113
|
+
}) {
|
|
114
|
+
auditSequence++;
|
|
115
|
+
const canonical = {
|
|
116
|
+
id: \`AUD-\${auditSequence.toString().padStart(8, '0')}\`,
|
|
117
|
+
sequenceNumber: auditSequence,
|
|
118
|
+
timestamp: new Date().toISOString(),
|
|
119
|
+
actor: entry.actor,
|
|
120
|
+
action: entry.action,
|
|
121
|
+
resource: entry.resource,
|
|
122
|
+
...(entry.detail ? { detail: entry.detail } : {}),
|
|
123
|
+
previousEntryHash: lastEnvelopeHash,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const payload = new TextEncoder().encode(JSON.stringify(canonical));
|
|
127
|
+
const envelopeBytes = await blinkSigner.sign(payload);
|
|
128
|
+
const envelope = Buffer.from(envelopeBytes).toString('base64');
|
|
129
|
+
|
|
130
|
+
// Update the chain — next entry will reference this envelope's hash
|
|
131
|
+
lastEnvelopeHash = createHash('sha256')
|
|
132
|
+
.update(Buffer.from(envelope, 'base64'))
|
|
133
|
+
.digest('hex');
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
...canonical,
|
|
137
|
+
envelope,
|
|
138
|
+
signerPublicKey: Buffer.from(blinkPublicKey).toString('hex'),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// --- End BLINK audit entry signing ---
|
|
142
|
+
`;
|
|
143
|
+
const VERIFY_INCOMING_CODE = `
|
|
144
|
+
// --- BLINK Authority: Incoming signature verification ---
|
|
145
|
+
// Verify a BLINK signature from incoming request headers.
|
|
146
|
+
// Expects: X-BLINK-Signature (base64 envelope), X-BLINK-PublicKey (hex key)
|
|
147
|
+
function blinkVerifyMiddleware() {
|
|
148
|
+
return async (req: any, res: any, next: any) => {
|
|
149
|
+
const signatureB64 = req.headers['x-blink-signature'];
|
|
150
|
+
const publicKeyHex = req.headers['x-blink-publickey'];
|
|
151
|
+
|
|
152
|
+
if (!signatureB64 || !publicKeyHex) {
|
|
153
|
+
res.status(401).json({ error: 'Missing BLINK signature headers' });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const publicKey = new Uint8Array(Buffer.from(publicKeyHex, 'hex'));
|
|
159
|
+
const verifier = new BlinkVerifier(publicKey, {
|
|
160
|
+
freshnessWindowMs: 5 * 60 * 1000, // 5 minute freshness window
|
|
161
|
+
clockSkewToleranceMs: 30_000,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const envelopeBytes = new Uint8Array(Buffer.from(signatureB64, 'base64'));
|
|
165
|
+
const result = verifier.verify(envelopeBytes);
|
|
166
|
+
|
|
167
|
+
if (!result.valid) {
|
|
168
|
+
res.status(401).json({ error: 'Invalid BLINK signature', reason: result.reason });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Attach verification result to request for downstream use
|
|
173
|
+
req.blinkVerification = result;
|
|
174
|
+
next();
|
|
175
|
+
} catch (err) {
|
|
176
|
+
res.status(401).json({ error: 'BLINK verification failed', detail: String(err) });
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// --- End BLINK verification middleware ---
|
|
181
|
+
`;
|
|
182
|
+
function hasBlinkImport(code) {
|
|
183
|
+
return code.includes('@blink-technology/sdk') || code.includes('BlinkSigner') || code.includes('BlinkVerifier');
|
|
184
|
+
}
|
|
185
|
+
function hasBlinkInit(code) {
|
|
186
|
+
return code.includes('BlinkSigner.connect') || code.includes('initBlink');
|
|
187
|
+
}
|
|
188
|
+
function applyPattern(code, pattern) {
|
|
189
|
+
const lines = code.split('\n');
|
|
190
|
+
const changes = [];
|
|
191
|
+
let result = code;
|
|
192
|
+
let insertionOffset = 0;
|
|
193
|
+
// Step 1: Add imports at the top (if not already present)
|
|
194
|
+
if (!hasBlinkImport(code)) {
|
|
195
|
+
const importLine = BLINK_IMPORTS[pattern];
|
|
196
|
+
// Find the last import line or insert at line 0
|
|
197
|
+
let lastImportIdx = -1;
|
|
198
|
+
for (let i = 0; i < lines.length; i++) {
|
|
199
|
+
if (lines[i].startsWith('import ') || lines[i].startsWith('import{')) {
|
|
200
|
+
lastImportIdx = i;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const insertAt = lastImportIdx + 1;
|
|
204
|
+
const resultLines = result.split('\n');
|
|
205
|
+
resultLines.splice(insertAt, 0, importLine);
|
|
206
|
+
result = resultLines.join('\n');
|
|
207
|
+
changes.push({
|
|
208
|
+
description: `Added BLINK SDK import(s)`,
|
|
209
|
+
line_range: `${insertAt + 1}`,
|
|
210
|
+
});
|
|
211
|
+
insertionOffset += importLine.split('\n').length;
|
|
212
|
+
}
|
|
213
|
+
// Step 2: Add BLINK initialization (if not present)
|
|
214
|
+
if (!hasBlinkInit(code) && pattern !== 'verify-incoming') {
|
|
215
|
+
const resultLines = result.split('\n');
|
|
216
|
+
// Find a good insertion point — after imports, before main code
|
|
217
|
+
let insertAt = 0;
|
|
218
|
+
for (let i = 0; i < resultLines.length; i++) {
|
|
219
|
+
if (resultLines[i].startsWith('import ') || resultLines[i].startsWith('import{')) {
|
|
220
|
+
insertAt = i + 1;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Skip blank lines after imports
|
|
224
|
+
while (insertAt < resultLines.length && resultLines[insertAt].trim() === '') {
|
|
225
|
+
insertAt++;
|
|
226
|
+
}
|
|
227
|
+
const initLines = BLINK_INIT.split('\n');
|
|
228
|
+
resultLines.splice(insertAt, 0, ...initLines);
|
|
229
|
+
result = resultLines.join('\n');
|
|
230
|
+
changes.push({
|
|
231
|
+
description: 'Added BLINK signer initialization and shutdown functions',
|
|
232
|
+
line_range: `${insertAt + 1}-${insertAt + initLines.length}`,
|
|
233
|
+
});
|
|
234
|
+
insertionOffset += initLines.length;
|
|
235
|
+
}
|
|
236
|
+
// Step 3: Add the pattern-specific code
|
|
237
|
+
let patternCode;
|
|
238
|
+
let patternDescription;
|
|
239
|
+
switch (pattern) {
|
|
240
|
+
case 'sign-response':
|
|
241
|
+
patternCode = SIGN_RESPONSE_MIDDLEWARE;
|
|
242
|
+
patternDescription = 'Added BLINK signing middleware for Express responses';
|
|
243
|
+
break;
|
|
244
|
+
case 'sign-document':
|
|
245
|
+
patternCode = SIGN_DOCUMENT_CODE;
|
|
246
|
+
patternDescription = 'Added document hashing + BLINK signing function';
|
|
247
|
+
break;
|
|
248
|
+
case 'sign-audit-entry':
|
|
249
|
+
patternCode = SIGN_AUDIT_ENTRY_CODE;
|
|
250
|
+
patternDescription = 'Added hash-chained audit entry signing function';
|
|
251
|
+
break;
|
|
252
|
+
case 'verify-incoming':
|
|
253
|
+
patternCode = VERIFY_INCOMING_CODE;
|
|
254
|
+
patternDescription = 'Added incoming BLINK signature verification middleware';
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
// Append the pattern code at the end of the file
|
|
258
|
+
const resultLines = result.split('\n');
|
|
259
|
+
const insertAt = resultLines.length;
|
|
260
|
+
result = result + '\n' + patternCode;
|
|
261
|
+
changes.push({
|
|
262
|
+
description: patternDescription,
|
|
263
|
+
line_range: `${insertAt + 1}-${insertAt + patternCode.split('\n').length}`,
|
|
264
|
+
});
|
|
265
|
+
// Step 4: Add usage comments
|
|
266
|
+
if (pattern === 'sign-response') {
|
|
267
|
+
// Try to find app.use or express() to suggest where to add the middleware
|
|
268
|
+
const appUseIdx = resultLines.findIndex(l => l.includes('app.use(') && !l.includes('blinkSigning'));
|
|
269
|
+
if (appUseIdx >= 0) {
|
|
270
|
+
changes.push({
|
|
271
|
+
description: 'Add `app.use(blinkSigningMiddleware());` before your routes (see existing app.use calls)',
|
|
272
|
+
line_range: `${appUseIdx + 1}`,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (pattern === 'verify-incoming') {
|
|
277
|
+
changes.push({
|
|
278
|
+
description: 'Add `app.use(blinkVerifyMiddleware());` to protect routes that require verified signatures',
|
|
279
|
+
line_range: 'N/A',
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
return { enhanced_code: result, changes };
|
|
283
|
+
}
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
// Tool handler
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
export function handleAddSigning(args) {
|
|
288
|
+
const code = String(args.code ?? '');
|
|
289
|
+
const pattern = String(args.pattern ?? '');
|
|
290
|
+
if (!code) {
|
|
291
|
+
return {
|
|
292
|
+
content: [{
|
|
293
|
+
type: 'text',
|
|
294
|
+
text: JSON.stringify({ error: 'Missing required parameter: code' }),
|
|
295
|
+
}],
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
const validPatterns = ['sign-response', 'sign-document', 'sign-audit-entry', 'verify-incoming'];
|
|
299
|
+
if (!validPatterns.includes(pattern)) {
|
|
300
|
+
return {
|
|
301
|
+
content: [{
|
|
302
|
+
type: 'text',
|
|
303
|
+
text: JSON.stringify({
|
|
304
|
+
error: `Unknown pattern: "${pattern}". Valid patterns: ${validPatterns.join(', ')}`,
|
|
305
|
+
}),
|
|
306
|
+
}],
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
const result = applyPattern(code, pattern);
|
|
310
|
+
return {
|
|
311
|
+
content: [{
|
|
312
|
+
type: 'text',
|
|
313
|
+
text: JSON.stringify(result, null, 2),
|
|
314
|
+
}],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=add-signing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-signing.js","sourceRoot":"","sources":["../../src/tools/add-signing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* blink_decode_envelope tool handler.
|
|
3
|
+
*
|
|
4
|
+
* Parses a base64-encoded BLINK envelope and explains each field.
|
|
5
|
+
* Useful for debugging signing/verification issues.
|
|
6
|
+
*/
|
|
7
|
+
export declare function handleDecodeEnvelope(args: Record<string, unknown>): {
|
|
8
|
+
content: Array<{
|
|
9
|
+
type: string;
|
|
10
|
+
text: string;
|
|
11
|
+
}>;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=decode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../src/tools/decode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuFH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAkMpD"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* blink_decode_envelope tool handler.
|
|
3
|
+
*
|
|
4
|
+
* Parses a base64-encoded BLINK envelope and explains each field.
|
|
5
|
+
* Useful for debugging signing/verification issues.
|
|
6
|
+
*/
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Field explanations
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
const FIELD_EXPLANATIONS = {
|
|
11
|
+
signature: 'The digital signature over the payload hash, produced by the ephemeral signing key. ' +
|
|
12
|
+
'Length depends on algorithm: Ed25519 = 64 bytes, ML-DSA-44 = 2420 bytes.',
|
|
13
|
+
ephemeral_public_key: 'The ephemeral public key derived from the VRF output. This key is unique per signing ' +
|
|
14
|
+
'operation and is used to verify the signature. Ed25519 = 32 bytes, ML-DSA-44 = 1312 bytes.',
|
|
15
|
+
vrf_proof: 'The ECVRF proof (pi) that proves the ephemeral key was correctly derived from the ' +
|
|
16
|
+
'master key and domain input. Allows offline verification of key provenance. Typically 80 bytes.',
|
|
17
|
+
p_derive: 'The derived public key (P_derive) from the VRF evaluation. This is the public component ' +
|
|
18
|
+
'of the master identity that was used to generate the ephemeral key.',
|
|
19
|
+
domain_input: 'The domain separation string used as VRF input. Typically formatted as ' +
|
|
20
|
+
'"purpose:identity:timestamp" to bind the key derivation to a specific context.',
|
|
21
|
+
timestamp: 'ISO 8601 timestamp recording when the envelope was created. Used for freshness ' +
|
|
22
|
+
'checks — envelopes older than the freshness window may be rejected.',
|
|
23
|
+
algorithm: 'The cryptographic algorithm suite used for signing. Ed25519 is the default; ' +
|
|
24
|
+
'ML-DSA-44 provides post-quantum resistance.',
|
|
25
|
+
payload_hash: 'The SHA-256 hash of the original payload that was signed. The signature is over ' +
|
|
26
|
+
'this hash, not the raw payload, enabling hash-then-sign verification.',
|
|
27
|
+
};
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Expected field sizes (bytes) per algorithm
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
const EXPECTED_SIZES = {
|
|
32
|
+
ed25519: {
|
|
33
|
+
signature: 64,
|
|
34
|
+
ephemeral_public_key: 32,
|
|
35
|
+
vrf_proof: 80,
|
|
36
|
+
p_derive: 32,
|
|
37
|
+
},
|
|
38
|
+
'ml-dsa-44': {
|
|
39
|
+
signature: 2420,
|
|
40
|
+
ephemeral_public_key: 1312,
|
|
41
|
+
vrf_proof: 80,
|
|
42
|
+
p_derive: 32,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const REQUIRED_FIELDS = [
|
|
46
|
+
'signature',
|
|
47
|
+
'ephemeral_public_key',
|
|
48
|
+
'vrf_proof',
|
|
49
|
+
'p_derive',
|
|
50
|
+
'domain_input',
|
|
51
|
+
'timestamp',
|
|
52
|
+
'algorithm',
|
|
53
|
+
'payload_hash',
|
|
54
|
+
];
|
|
55
|
+
// Freshness window: 5 minutes
|
|
56
|
+
const FRESHNESS_WINDOW_MS = 5 * 60 * 1000;
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Helper: safe base64 decode length
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
function base64ByteLength(b64) {
|
|
61
|
+
try {
|
|
62
|
+
return Buffer.from(b64, 'base64').length;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return -1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function isValidBase64(s) {
|
|
69
|
+
try {
|
|
70
|
+
const buf = Buffer.from(s, 'base64');
|
|
71
|
+
return buf.length > 0 && Buffer.from(buf).toString('base64') === s.replace(/\s/g, '');
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Handler
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
export function handleDecodeEnvelope(args) {
|
|
81
|
+
const envelopeB64 = args.envelope;
|
|
82
|
+
if (!envelopeB64 || typeof envelopeB64 !== 'string' || envelopeB64.trim() === '') {
|
|
83
|
+
return {
|
|
84
|
+
content: [{
|
|
85
|
+
type: 'text',
|
|
86
|
+
text: JSON.stringify({
|
|
87
|
+
valid_format: false,
|
|
88
|
+
error: 'Missing or empty "envelope" parameter. Provide a base64-encoded BLINK envelope.',
|
|
89
|
+
}),
|
|
90
|
+
}],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// Step 1: Base64 decode
|
|
94
|
+
let decoded;
|
|
95
|
+
try {
|
|
96
|
+
decoded = Buffer.from(envelopeB64, 'base64').toString('utf-8');
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return {
|
|
100
|
+
content: [{
|
|
101
|
+
type: 'text',
|
|
102
|
+
text: JSON.stringify({
|
|
103
|
+
valid_format: false,
|
|
104
|
+
error: 'Failed to base64-decode the envelope. Ensure it is valid base64.',
|
|
105
|
+
}),
|
|
106
|
+
}],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// Step 2: JSON parse
|
|
110
|
+
let envelope;
|
|
111
|
+
try {
|
|
112
|
+
envelope = JSON.parse(decoded);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return {
|
|
116
|
+
content: [{
|
|
117
|
+
type: 'text',
|
|
118
|
+
text: JSON.stringify({
|
|
119
|
+
valid_format: false,
|
|
120
|
+
error: 'Decoded data is not valid JSON. A BLINK envelope must be a JSON object.',
|
|
121
|
+
raw_preview: decoded.substring(0, 200),
|
|
122
|
+
}),
|
|
123
|
+
}],
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// Step 3: Extract and explain fields
|
|
127
|
+
const warnings = [];
|
|
128
|
+
const missingFields = [];
|
|
129
|
+
const fields = {};
|
|
130
|
+
for (const field of REQUIRED_FIELDS) {
|
|
131
|
+
if (envelope[field] === undefined || envelope[field] === null) {
|
|
132
|
+
missingFields.push(field);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
fields[field] = envelope[field];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (missingFields.length > 0) {
|
|
139
|
+
warnings.push(`Missing required fields: ${missingFields.join(', ')}`);
|
|
140
|
+
}
|
|
141
|
+
// Step 4: Calculate sizes for binary fields
|
|
142
|
+
const sizes = {};
|
|
143
|
+
const binaryFields = ['signature', 'ephemeral_public_key', 'vrf_proof', 'p_derive'];
|
|
144
|
+
const algo = (envelope.algorithm || 'ed25519').toLowerCase().replace(/_/g, '-');
|
|
145
|
+
const expectedForAlgo = EXPECTED_SIZES[algo] || EXPECTED_SIZES['ed25519'];
|
|
146
|
+
for (const field of binaryFields) {
|
|
147
|
+
const val = envelope[field];
|
|
148
|
+
if (val && typeof val === 'string') {
|
|
149
|
+
const bytes = base64ByteLength(val);
|
|
150
|
+
const expected = expectedForAlgo[field];
|
|
151
|
+
sizes[field] = {
|
|
152
|
+
bytes,
|
|
153
|
+
expected,
|
|
154
|
+
match: expected ? bytes === expected : undefined,
|
|
155
|
+
};
|
|
156
|
+
if (expected && bytes !== expected) {
|
|
157
|
+
warnings.push(`${field}: expected ${expected} bytes for ${algo}, got ${bytes} bytes`);
|
|
158
|
+
}
|
|
159
|
+
if (!isValidBase64(val)) {
|
|
160
|
+
warnings.push(`${field}: value is not valid base64 encoding`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Step 5: Parse domain_input
|
|
165
|
+
let domainParsed = null;
|
|
166
|
+
const domainInput = envelope.domain_input;
|
|
167
|
+
if (domainInput && typeof domainInput === 'string') {
|
|
168
|
+
const parts = domainInput.split(':');
|
|
169
|
+
if (parts.length >= 3) {
|
|
170
|
+
domainParsed = {
|
|
171
|
+
purpose: parts[0],
|
|
172
|
+
identity: parts[1],
|
|
173
|
+
timestamp: parts.slice(2).join(':'),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
else if (parts.length === 2) {
|
|
177
|
+
domainParsed = {
|
|
178
|
+
purpose: parts[0],
|
|
179
|
+
identity: parts[1],
|
|
180
|
+
};
|
|
181
|
+
warnings.push('domain_input has only 2 parts (expected purpose:identity:timestamp)');
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
warnings.push('domain_input does not follow expected format (purpose:identity:timestamp)');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Step 6: Check timestamp freshness
|
|
188
|
+
let timestampAnalysis = null;
|
|
189
|
+
const timestamp = envelope.timestamp;
|
|
190
|
+
if (timestamp && typeof timestamp === 'string') {
|
|
191
|
+
const parsed = new Date(timestamp);
|
|
192
|
+
if (isNaN(parsed.getTime())) {
|
|
193
|
+
warnings.push('timestamp is not a valid ISO 8601 date');
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
const now = Date.now();
|
|
197
|
+
const age = now - parsed.getTime();
|
|
198
|
+
const fresh = Math.abs(age) <= FRESHNESS_WINDOW_MS;
|
|
199
|
+
timestampAnalysis = {
|
|
200
|
+
parsed: parsed.toISOString(),
|
|
201
|
+
age_seconds: Math.round(age / 1000),
|
|
202
|
+
fresh,
|
|
203
|
+
freshness_window_seconds: FRESHNESS_WINDOW_MS / 1000,
|
|
204
|
+
};
|
|
205
|
+
if (!fresh) {
|
|
206
|
+
if (age > 0) {
|
|
207
|
+
warnings.push(`Envelope timestamp is ${Math.round(age / 1000)}s old (freshness window: ${FRESHNESS_WINDOW_MS / 1000}s)`);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
warnings.push('Envelope timestamp is in the future');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Step 7: Check algorithm
|
|
216
|
+
const algorithmValue = envelope.algorithm;
|
|
217
|
+
let algorithmValid = false;
|
|
218
|
+
if (algorithmValue) {
|
|
219
|
+
const normalised = algorithmValue.toLowerCase().replace(/[_-]/g, '');
|
|
220
|
+
algorithmValid = normalised === 'ed25519' || normalised === 'mldsa44';
|
|
221
|
+
if (!algorithmValid) {
|
|
222
|
+
warnings.push(`Unknown algorithm: "${algorithmValue}". Supported: Ed25519, ML-DSA-44`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Step 8: Check payload_hash format
|
|
226
|
+
const payloadHash = envelope.payload_hash;
|
|
227
|
+
if (payloadHash && typeof payloadHash === 'string') {
|
|
228
|
+
if (!/^[0-9a-fA-F]{64}$/.test(payloadHash)) {
|
|
229
|
+
warnings.push('payload_hash does not appear to be a 64-character hex SHA-256 hash');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Extra fields
|
|
233
|
+
const knownFields = new Set(REQUIRED_FIELDS);
|
|
234
|
+
const extraFields = Object.keys(envelope).filter((k) => !knownFields.has(k));
|
|
235
|
+
if (extraFields.length > 0) {
|
|
236
|
+
warnings.push(`Extra fields present: ${extraFields.join(', ')}`);
|
|
237
|
+
}
|
|
238
|
+
// Build explanation
|
|
239
|
+
const explanationParts = [];
|
|
240
|
+
for (const field of REQUIRED_FIELDS) {
|
|
241
|
+
if (envelope[field] !== undefined) {
|
|
242
|
+
explanationParts.push(`- ${field}: ${FIELD_EXPLANATIONS[field] || 'Unknown field'}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const result = {
|
|
246
|
+
valid_format: missingFields.length === 0,
|
|
247
|
+
fields,
|
|
248
|
+
sizes,
|
|
249
|
+
domain_parsed: domainParsed,
|
|
250
|
+
timestamp_analysis: timestampAnalysis,
|
|
251
|
+
algorithm_valid: algorithmValid,
|
|
252
|
+
field_explanations: explanationParts,
|
|
253
|
+
warnings,
|
|
254
|
+
};
|
|
255
|
+
return {
|
|
256
|
+
content: [{
|
|
257
|
+
type: 'text',
|
|
258
|
+
text: JSON.stringify(result, null, 2),
|
|
259
|
+
}],
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=decode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode.js","sourceRoot":"","sources":["../../src/tools/decode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* blink_hierarchy_design tool handler.
|
|
3
|
+
*
|
|
4
|
+
* Given an organisational description, suggests a BLINK key hierarchy
|
|
5
|
+
* with INS naming, algorithm recommendations, and delegation model.
|
|
6
|
+
*/
|
|
7
|
+
export declare function handleHierarchyDesign(args: Record<string, unknown>): {
|
|
8
|
+
content: Array<{
|
|
9
|
+
type: string;
|
|
10
|
+
text: string;
|
|
11
|
+
}>;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=hierarchy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hierarchy.d.ts","sourceRoot":"","sources":["../../src/tools/hierarchy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgHH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CA4PpD"}
|