@positronic/cli 0.0.59 → 0.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/lib/jwt-auth.js +245 -30
- package/dist/src/lib/ssh-agent-signer.js +296 -0
- package/dist/src/lib/ssh-key-utils.js +9 -0
- package/dist/src/types/sshpk-agent.d.js +0 -0
- package/dist/types/lib/jwt-auth.d.ts +36 -1
- package/dist/types/lib/jwt-auth.d.ts.map +1 -1
- package/dist/types/lib/ssh-agent-signer.d.ts +31 -0
- package/dist/types/lib/ssh-agent-signer.d.ts.map +1 -0
- package/dist/types/lib/ssh-key-utils.d.ts +6 -0
- package/dist/types/lib/ssh-key-utils.d.ts.map +1 -1
- package/package.json +5 -4
package/dist/src/lib/jwt-auth.js
CHANGED
|
@@ -157,13 +157,24 @@ function _ts_generator(thisArg, body) {
|
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
import { SignJWT, importPKCS8 } from 'jose';
|
|
160
|
+
import { SignJWT, importPKCS8, base64url } from 'jose';
|
|
161
161
|
import { existsSync } from 'fs';
|
|
162
|
-
import {
|
|
162
|
+
import { createPrivateKey } from 'crypto';
|
|
163
|
+
import { loadPrivateKey, getPrivateKeyFingerprint, getPublicKeyFingerprint, resolvePrivateKeyPath } from './ssh-key-utils.js';
|
|
163
164
|
import { ProjectConfigManager } from '../commands/project-config-manager.js';
|
|
165
|
+
import { AgentSigner } from './ssh-agent-signer.js';
|
|
166
|
+
/**
|
|
167
|
+
* Check if an error indicates an encrypted key
|
|
168
|
+
*/ function isEncryptedKeyError(error) {
|
|
169
|
+
if (_instanceof(error, Error) && error.name === 'KeyEncryptedError') {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
164
174
|
/**
|
|
165
175
|
* JWT Auth Provider for authenticating API requests
|
|
166
176
|
* Uses SSH private keys to sign short-lived JWTs
|
|
177
|
+
* Falls back to ssh-agent for encrypted keys
|
|
167
178
|
*/ export var JwtAuthProvider = /*#__PURE__*/ function() {
|
|
168
179
|
"use strict";
|
|
169
180
|
function JwtAuthProvider() {
|
|
@@ -172,6 +183,11 @@ import { ProjectConfigManager } from '../commands/project-config-manager.js';
|
|
|
172
183
|
_define_property(this, "fingerprint", null);
|
|
173
184
|
_define_property(this, "initialized", false);
|
|
174
185
|
_define_property(this, "initError", null);
|
|
186
|
+
// Agent fallback support
|
|
187
|
+
_define_property(this, "encryptedKeyPath", null);
|
|
188
|
+
_define_property(this, "agentSigner", null);
|
|
189
|
+
_define_property(this, "agentKey", null);
|
|
190
|
+
_define_property(this, "useAgent", false);
|
|
175
191
|
this.initialize();
|
|
176
192
|
}
|
|
177
193
|
_create_class(JwtAuthProvider, [
|
|
@@ -191,16 +207,42 @@ import { ProjectConfigManager } from '../commands/project-config-manager.js';
|
|
|
191
207
|
this.fingerprint = getPrivateKeyFingerprint(this.privateKey);
|
|
192
208
|
this.initialized = true;
|
|
193
209
|
} catch (error) {
|
|
194
|
-
|
|
210
|
+
if (isEncryptedKeyError(error)) {
|
|
211
|
+
// Store the path for agent fallback - we'll try the agent in createToken()
|
|
212
|
+
var configManager1 = new ProjectConfigManager();
|
|
213
|
+
var configuredPath1 = configManager1.getPrivateKeyPath();
|
|
214
|
+
this.encryptedKeyPath = resolvePrivateKeyPath(configuredPath1);
|
|
215
|
+
this.initError = _instanceof(error, Error) ? error : new Error('Key is encrypted');
|
|
216
|
+
} else {
|
|
217
|
+
this.initError = _instanceof(error, Error) ? error : new Error('Failed to initialize JWT auth provider');
|
|
218
|
+
}
|
|
195
219
|
}
|
|
196
220
|
}
|
|
197
221
|
},
|
|
198
222
|
{
|
|
199
223
|
/**
|
|
200
224
|
* Check if the provider is ready to create JWTs
|
|
225
|
+
* Returns true if we have a direct key OR if we have an encrypted key
|
|
226
|
+
* that might work with agent fallback
|
|
201
227
|
*/ key: "isReady",
|
|
202
228
|
value: function isReady() {
|
|
203
|
-
|
|
229
|
+
// Direct key is loaded and ready
|
|
230
|
+
if (this.initialized && this.privateKey !== null) {
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
// Encrypted key might work with agent fallback
|
|
234
|
+
if (this.encryptedKeyPath !== null) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
/**
|
|
242
|
+
* Check if we have an encrypted key that requires agent fallback
|
|
243
|
+
*/ key: "hasEncryptedKey",
|
|
244
|
+
value: function hasEncryptedKey() {
|
|
245
|
+
return this.encryptedKeyPath !== null;
|
|
204
246
|
}
|
|
205
247
|
},
|
|
206
248
|
{
|
|
@@ -227,12 +269,18 @@ import { ProjectConfigManager } from '../commands/project-config-manager.js';
|
|
|
227
269
|
if (!this.privateKey) {
|
|
228
270
|
throw new Error('Private key not loaded');
|
|
229
271
|
}
|
|
230
|
-
|
|
272
|
+
return this.getAlgorithmForKeyType(this.privateKey.type, this.privateKey.curve);
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
key: "getAlgorithmForKeyType",
|
|
277
|
+
value: /**
|
|
278
|
+
* Map SSH key type string to JWT algorithm
|
|
279
|
+
*/ function getAlgorithmForKeyType(keyType, curve) {
|
|
231
280
|
if (keyType === 'rsa') {
|
|
232
281
|
return 'RS256';
|
|
233
282
|
} else if (keyType === 'ecdsa') {
|
|
234
283
|
// ECDSA curve determines algorithm
|
|
235
|
-
var curve = this.privateKey.curve;
|
|
236
284
|
if (curve === 'nistp256') {
|
|
237
285
|
return 'ES256';
|
|
238
286
|
} else if (curve === 'nistp384') {
|
|
@@ -248,22 +296,102 @@ import { ProjectConfigManager } from '../commands/project-config-manager.js';
|
|
|
248
296
|
throw new Error("Unsupported key type: ".concat(keyType));
|
|
249
297
|
}
|
|
250
298
|
},
|
|
299
|
+
{
|
|
300
|
+
key: "getPkcs8Pem",
|
|
301
|
+
value: /**
|
|
302
|
+
* Convert the SSH private key to PKCS8 PEM format
|
|
303
|
+
* Ed25519 keys need special handling because sshpk's PKCS8 output
|
|
304
|
+
* is not compatible with Node.js/OpenSSL
|
|
305
|
+
*/ function getPkcs8Pem() {
|
|
306
|
+
if (!this.privateKey) {
|
|
307
|
+
throw new Error('Private key not loaded');
|
|
308
|
+
}
|
|
309
|
+
if (this.privateKey.type === 'ed25519') {
|
|
310
|
+
// For Ed25519, sshpk's PKCS8 output includes the public key in a format
|
|
311
|
+
// that Node.js/OpenSSL doesn't understand. Instead, we construct a JWK
|
|
312
|
+
// from the raw key parts and let Node's crypto handle the conversion.
|
|
313
|
+
// sshpk stores Ed25519 key data in 'k' (seed) and 'A' (public) parts
|
|
314
|
+
var parts = this.privateKey.part;
|
|
315
|
+
var seed = parts.k.data;
|
|
316
|
+
var publicKey = parts.A.data;
|
|
317
|
+
// Construct JWK and let Node's crypto convert to PKCS8
|
|
318
|
+
var jwk = {
|
|
319
|
+
kty: 'OKP',
|
|
320
|
+
crv: 'Ed25519',
|
|
321
|
+
d: seed.toString('base64url'),
|
|
322
|
+
x: publicKey.toString('base64url')
|
|
323
|
+
};
|
|
324
|
+
var keyObj = createPrivateKey({
|
|
325
|
+
key: jwk,
|
|
326
|
+
format: 'jwk'
|
|
327
|
+
});
|
|
328
|
+
return keyObj.export({
|
|
329
|
+
type: 'pkcs8',
|
|
330
|
+
format: 'pem'
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
// For RSA and ECDSA, sshpk's PKCS8 output works fine
|
|
334
|
+
return this.privateKey.toString('pkcs8');
|
|
335
|
+
}
|
|
336
|
+
},
|
|
251
337
|
{
|
|
252
338
|
key: "createToken",
|
|
253
339
|
value: /**
|
|
254
340
|
* Create a short-lived JWT for authentication
|
|
255
341
|
*/ function createToken() {
|
|
342
|
+
return _async_to_generator(function() {
|
|
343
|
+
return _ts_generator(this, function(_state) {
|
|
344
|
+
switch(_state.label){
|
|
345
|
+
case 0:
|
|
346
|
+
// If we have a direct private key, use the standard jose signing path
|
|
347
|
+
if (this.privateKey && this.fingerprint) {
|
|
348
|
+
return [
|
|
349
|
+
2,
|
|
350
|
+
this.createTokenDirect()
|
|
351
|
+
];
|
|
352
|
+
}
|
|
353
|
+
if (!this.encryptedKeyPath) return [
|
|
354
|
+
3,
|
|
355
|
+
2
|
|
356
|
+
];
|
|
357
|
+
return [
|
|
358
|
+
4,
|
|
359
|
+
this.tryAgentFallback()
|
|
360
|
+
];
|
|
361
|
+
case 1:
|
|
362
|
+
_state.sent();
|
|
363
|
+
_state.label = 2;
|
|
364
|
+
case 2:
|
|
365
|
+
// If agent fallback succeeded, use agent signing
|
|
366
|
+
if (this.useAgent && this.agentSigner && this.agentKey && this.fingerprint) {
|
|
367
|
+
return [
|
|
368
|
+
2,
|
|
369
|
+
this.createTokenWithAgent()
|
|
370
|
+
];
|
|
371
|
+
}
|
|
372
|
+
// No authentication method available
|
|
373
|
+
throw this.initError || new Error('JWT auth provider not initialized');
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}).call(this);
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
key: "createTokenDirect",
|
|
381
|
+
value: /**
|
|
382
|
+
* Create JWT using direct private key (jose library)
|
|
383
|
+
*/ function createTokenDirect() {
|
|
256
384
|
return _async_to_generator(function() {
|
|
257
385
|
var algorithm, pkcs8Pem, joseKey, jwt;
|
|
258
386
|
return _ts_generator(this, function(_state) {
|
|
259
387
|
switch(_state.label){
|
|
260
388
|
case 0:
|
|
261
389
|
if (!this.privateKey || !this.fingerprint) {
|
|
262
|
-
throw new Error('
|
|
390
|
+
throw new Error('Private key not loaded');
|
|
263
391
|
}
|
|
264
392
|
algorithm = this.getAlgorithm();
|
|
265
393
|
// Convert SSH private key to PKCS8 PEM format
|
|
266
|
-
pkcs8Pem = this.
|
|
394
|
+
pkcs8Pem = this.getPkcs8Pem();
|
|
267
395
|
return [
|
|
268
396
|
4,
|
|
269
397
|
importPKCS8(pkcs8Pem, algorithm)
|
|
@@ -286,6 +414,106 @@ import { ProjectConfigManager } from '../commands/project-config-manager.js';
|
|
|
286
414
|
});
|
|
287
415
|
}).call(this);
|
|
288
416
|
}
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
key: "tryAgentFallback",
|
|
420
|
+
value: /**
|
|
421
|
+
* Try to use ssh-agent for signing when private key is encrypted
|
|
422
|
+
*/ function tryAgentFallback() {
|
|
423
|
+
return _async_to_generator(function() {
|
|
424
|
+
var pubKeyPath, fingerprint, agent, agentKey;
|
|
425
|
+
return _ts_generator(this, function(_state) {
|
|
426
|
+
switch(_state.label){
|
|
427
|
+
case 0:
|
|
428
|
+
if (!this.encryptedKeyPath) {
|
|
429
|
+
return [
|
|
430
|
+
2
|
|
431
|
+
];
|
|
432
|
+
}
|
|
433
|
+
// Get fingerprint from public key file
|
|
434
|
+
pubKeyPath = this.encryptedKeyPath + '.pub';
|
|
435
|
+
if (!existsSync(pubKeyPath)) {
|
|
436
|
+
throw new Error("Key is encrypted and public key file not found at ".concat(pubKeyPath, ".\n") + "Cannot determine key fingerprint for ssh-agent lookup.");
|
|
437
|
+
}
|
|
438
|
+
fingerprint = getPublicKeyFingerprint(pubKeyPath);
|
|
439
|
+
agent = new AgentSigner();
|
|
440
|
+
if (!agent.isAvailable()) {
|
|
441
|
+
throw new Error("Key is encrypted and ssh-agent is not running.\n" + "Start ssh-agent or use an unencrypted key.");
|
|
442
|
+
}
|
|
443
|
+
return [
|
|
444
|
+
4,
|
|
445
|
+
agent.hasKey(fingerprint)
|
|
446
|
+
];
|
|
447
|
+
case 1:
|
|
448
|
+
agentKey = _state.sent();
|
|
449
|
+
if (!agentKey) {
|
|
450
|
+
throw new Error("Key is encrypted and not loaded in ssh-agent.\n" + "Run: ssh-add ".concat(this.encryptedKeyPath));
|
|
451
|
+
}
|
|
452
|
+
this.agentSigner = agent;
|
|
453
|
+
this.agentKey = agentKey;
|
|
454
|
+
this.fingerprint = fingerprint;
|
|
455
|
+
this.useAgent = true;
|
|
456
|
+
this.initError = null;
|
|
457
|
+
this.initialized = true;
|
|
458
|
+
return [
|
|
459
|
+
2
|
|
460
|
+
];
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}).call(this);
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
key: "createTokenWithAgent",
|
|
468
|
+
value: /**
|
|
469
|
+
* Create JWT using ssh-agent for signing
|
|
470
|
+
* Manually constructs the JWT since jose expects to do signing itself
|
|
471
|
+
*/ function createTokenWithAgent() {
|
|
472
|
+
return _async_to_generator(function() {
|
|
473
|
+
var keyType, curve, algorithm, header, encodedHeader, now, payload, encodedPayload, signingInput, signature, signatureBytes, encodedSignature;
|
|
474
|
+
return _ts_generator(this, function(_state) {
|
|
475
|
+
switch(_state.label){
|
|
476
|
+
case 0:
|
|
477
|
+
if (!this.agentSigner || !this.agentKey || !this.fingerprint) {
|
|
478
|
+
throw new Error('Agent signing not configured');
|
|
479
|
+
}
|
|
480
|
+
// Get algorithm from agent key type
|
|
481
|
+
keyType = this.agentKey.type;
|
|
482
|
+
curve = this.agentKey.curve;
|
|
483
|
+
algorithm = this.getAlgorithmForKeyType(keyType, curve);
|
|
484
|
+
// Build JWT header
|
|
485
|
+
header = {
|
|
486
|
+
alg: algorithm
|
|
487
|
+
};
|
|
488
|
+
encodedHeader = base64url.encode(JSON.stringify(header));
|
|
489
|
+
// Build JWT payload
|
|
490
|
+
now = Math.floor(Date.now() / 1000);
|
|
491
|
+
payload = {
|
|
492
|
+
sub: this.fingerprint,
|
|
493
|
+
iat: now,
|
|
494
|
+
exp: now + 30
|
|
495
|
+
};
|
|
496
|
+
encodedPayload = base64url.encode(JSON.stringify(payload));
|
|
497
|
+
// Create signing input
|
|
498
|
+
signingInput = "".concat(encodedHeader, ".").concat(encodedPayload);
|
|
499
|
+
return [
|
|
500
|
+
4,
|
|
501
|
+
this.agentSigner.sign(this.agentKey, Buffer.from(signingInput))
|
|
502
|
+
];
|
|
503
|
+
case 1:
|
|
504
|
+
signature = _state.sent();
|
|
505
|
+
// Convert sshpk.Signature to raw bytes for JWT
|
|
506
|
+
// sshpk's toBuffer() gives us the raw signature bytes
|
|
507
|
+
signatureBytes = signature.toBuffer('raw');
|
|
508
|
+
encodedSignature = base64url.encode(signatureBytes);
|
|
509
|
+
return [
|
|
510
|
+
2,
|
|
511
|
+
"".concat(signingInput, ".").concat(encodedSignature)
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
}).call(this);
|
|
516
|
+
}
|
|
289
517
|
}
|
|
290
518
|
]);
|
|
291
519
|
return JwtAuthProvider;
|
|
@@ -313,33 +541,31 @@ var providerInstance = null;
|
|
|
313
541
|
}
|
|
314
542
|
/**
|
|
315
543
|
* Get the Authorization header if auth is available
|
|
316
|
-
*
|
|
544
|
+
* Throws if there's an auth configuration error
|
|
545
|
+
* Returns empty object with warning if no key is configured
|
|
317
546
|
*/ export function getAuthHeader() {
|
|
318
547
|
return _async_to_generator(function() {
|
|
319
|
-
var provider,
|
|
548
|
+
var provider, error, token;
|
|
320
549
|
return _ts_generator(this, function(_state) {
|
|
321
550
|
switch(_state.label){
|
|
322
551
|
case 0:
|
|
323
552
|
provider = getJwtAuthProvider();
|
|
324
553
|
if (!provider.isReady()) {
|
|
554
|
+
error = provider.getError();
|
|
555
|
+
if (error) {
|
|
556
|
+
throw error;
|
|
557
|
+
}
|
|
558
|
+
console.warn('Warning: No SSH key configured for authentication. Run "px auth login" to configure.');
|
|
325
559
|
return [
|
|
326
560
|
2,
|
|
327
561
|
{}
|
|
328
562
|
];
|
|
329
563
|
}
|
|
330
|
-
_state.label = 1;
|
|
331
|
-
case 1:
|
|
332
|
-
_state.trys.push([
|
|
333
|
-
1,
|
|
334
|
-
3,
|
|
335
|
-
,
|
|
336
|
-
4
|
|
337
|
-
]);
|
|
338
564
|
return [
|
|
339
565
|
4,
|
|
340
566
|
provider.createToken()
|
|
341
567
|
];
|
|
342
|
-
case
|
|
568
|
+
case 1:
|
|
343
569
|
token = _state.sent();
|
|
344
570
|
return [
|
|
345
571
|
2,
|
|
@@ -347,17 +573,6 @@ var providerInstance = null;
|
|
|
347
573
|
Authorization: "Bearer ".concat(token)
|
|
348
574
|
}
|
|
349
575
|
];
|
|
350
|
-
case 3:
|
|
351
|
-
error = _state.sent();
|
|
352
|
-
console.error('Warning: Failed to create auth token:', error);
|
|
353
|
-
return [
|
|
354
|
-
2,
|
|
355
|
-
{}
|
|
356
|
-
];
|
|
357
|
-
case 4:
|
|
358
|
-
return [
|
|
359
|
-
2
|
|
360
|
-
];
|
|
361
576
|
}
|
|
362
577
|
});
|
|
363
578
|
})();
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _class_call_check(instance, Constructor) {
|
|
31
|
+
if (!(instance instanceof Constructor)) {
|
|
32
|
+
throw new TypeError("Cannot call a class as a function");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _defineProperties(target, props) {
|
|
36
|
+
for(var i = 0; i < props.length; i++){
|
|
37
|
+
var descriptor = props[i];
|
|
38
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
39
|
+
descriptor.configurable = true;
|
|
40
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
41
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
45
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
46
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
47
|
+
return Constructor;
|
|
48
|
+
}
|
|
49
|
+
function _define_property(obj, key, value) {
|
|
50
|
+
if (key in obj) {
|
|
51
|
+
Object.defineProperty(obj, key, {
|
|
52
|
+
value: value,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
obj[key] = value;
|
|
59
|
+
}
|
|
60
|
+
return obj;
|
|
61
|
+
}
|
|
62
|
+
function _ts_generator(thisArg, body) {
|
|
63
|
+
var f, y, t, _ = {
|
|
64
|
+
label: 0,
|
|
65
|
+
sent: function() {
|
|
66
|
+
if (t[0] & 1) throw t[1];
|
|
67
|
+
return t[1];
|
|
68
|
+
},
|
|
69
|
+
trys: [],
|
|
70
|
+
ops: []
|
|
71
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
72
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
73
|
+
return this;
|
|
74
|
+
}), g;
|
|
75
|
+
function verb(n) {
|
|
76
|
+
return function(v) {
|
|
77
|
+
return step([
|
|
78
|
+
n,
|
|
79
|
+
v
|
|
80
|
+
]);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function step(op) {
|
|
84
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
85
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
86
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
87
|
+
if (y = 0, t) op = [
|
|
88
|
+
op[0] & 2,
|
|
89
|
+
t.value
|
|
90
|
+
];
|
|
91
|
+
switch(op[0]){
|
|
92
|
+
case 0:
|
|
93
|
+
case 1:
|
|
94
|
+
t = op;
|
|
95
|
+
break;
|
|
96
|
+
case 4:
|
|
97
|
+
_.label++;
|
|
98
|
+
return {
|
|
99
|
+
value: op[1],
|
|
100
|
+
done: false
|
|
101
|
+
};
|
|
102
|
+
case 5:
|
|
103
|
+
_.label++;
|
|
104
|
+
y = op[1];
|
|
105
|
+
op = [
|
|
106
|
+
0
|
|
107
|
+
];
|
|
108
|
+
continue;
|
|
109
|
+
case 7:
|
|
110
|
+
op = _.ops.pop();
|
|
111
|
+
_.trys.pop();
|
|
112
|
+
continue;
|
|
113
|
+
default:
|
|
114
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
115
|
+
_ = 0;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
119
|
+
_.label = op[1];
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
123
|
+
_.label = t[1];
|
|
124
|
+
t = op;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
if (t && _.label < t[2]) {
|
|
128
|
+
_.label = t[2];
|
|
129
|
+
_.ops.push(op);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
if (t[2]) _.ops.pop();
|
|
133
|
+
_.trys.pop();
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
op = body.call(thisArg, _);
|
|
137
|
+
} catch (e) {
|
|
138
|
+
op = [
|
|
139
|
+
6,
|
|
140
|
+
e
|
|
141
|
+
];
|
|
142
|
+
y = 0;
|
|
143
|
+
} finally{
|
|
144
|
+
f = t = 0;
|
|
145
|
+
}
|
|
146
|
+
if (op[0] & 5) throw op[1];
|
|
147
|
+
return {
|
|
148
|
+
value: op[0] ? op[1] : void 0,
|
|
149
|
+
done: true
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
import { Client as AgentClient } from 'sshpk-agent';
|
|
154
|
+
/**
|
|
155
|
+
* Wrapper for ssh-agent operations using sshpk-agent
|
|
156
|
+
*/ export var AgentSigner = /*#__PURE__*/ function() {
|
|
157
|
+
"use strict";
|
|
158
|
+
function AgentSigner() {
|
|
159
|
+
_class_call_check(this, AgentSigner);
|
|
160
|
+
_define_property(this, "client", null);
|
|
161
|
+
_define_property(this, "keys", null);
|
|
162
|
+
}
|
|
163
|
+
_create_class(AgentSigner, [
|
|
164
|
+
{
|
|
165
|
+
/**
|
|
166
|
+
* Check if ssh-agent is available (SSH_AUTH_SOCK environment variable exists)
|
|
167
|
+
*/ key: "isAvailable",
|
|
168
|
+
value: function isAvailable() {
|
|
169
|
+
return !!process.env.SSH_AUTH_SOCK;
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
key: "getClient",
|
|
174
|
+
value: /**
|
|
175
|
+
* Get the agent client, creating it lazily
|
|
176
|
+
*/ function getClient() {
|
|
177
|
+
if (!this.client) {
|
|
178
|
+
this.client = new AgentClient();
|
|
179
|
+
}
|
|
180
|
+
return this.client;
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
key: "getKeys",
|
|
185
|
+
value: /**
|
|
186
|
+
* List all keys available in the ssh-agent
|
|
187
|
+
*/ function getKeys() {
|
|
188
|
+
return _async_to_generator(function() {
|
|
189
|
+
var _this, client;
|
|
190
|
+
return _ts_generator(this, function(_state) {
|
|
191
|
+
_this = this;
|
|
192
|
+
if (this.keys) {
|
|
193
|
+
return [
|
|
194
|
+
2,
|
|
195
|
+
this.keys
|
|
196
|
+
];
|
|
197
|
+
}
|
|
198
|
+
client = this.getClient();
|
|
199
|
+
return [
|
|
200
|
+
2,
|
|
201
|
+
new Promise(function(resolve, reject) {
|
|
202
|
+
client.listKeys(function(err, keys) {
|
|
203
|
+
if (err) {
|
|
204
|
+
reject(err);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
_this.keys = keys;
|
|
208
|
+
resolve(keys);
|
|
209
|
+
});
|
|
210
|
+
})
|
|
211
|
+
];
|
|
212
|
+
});
|
|
213
|
+
}).call(this);
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
key: "hasKey",
|
|
218
|
+
value: /**
|
|
219
|
+
* Check if the agent has a key with the given fingerprint
|
|
220
|
+
* Returns the key if found, null otherwise
|
|
221
|
+
*/ function hasKey(fingerprint) {
|
|
222
|
+
return _async_to_generator(function() {
|
|
223
|
+
var keys, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, key, keyFingerprint;
|
|
224
|
+
return _ts_generator(this, function(_state) {
|
|
225
|
+
switch(_state.label){
|
|
226
|
+
case 0:
|
|
227
|
+
return [
|
|
228
|
+
4,
|
|
229
|
+
this.getKeys()
|
|
230
|
+
];
|
|
231
|
+
case 1:
|
|
232
|
+
keys = _state.sent();
|
|
233
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
234
|
+
try {
|
|
235
|
+
for(_iterator = keys[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
236
|
+
key = _step.value;
|
|
237
|
+
keyFingerprint = key.fingerprint('sha256').toString();
|
|
238
|
+
if (keyFingerprint === fingerprint) {
|
|
239
|
+
return [
|
|
240
|
+
2,
|
|
241
|
+
key
|
|
242
|
+
];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
} catch (err) {
|
|
246
|
+
_didIteratorError = true;
|
|
247
|
+
_iteratorError = err;
|
|
248
|
+
} finally{
|
|
249
|
+
try {
|
|
250
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
251
|
+
_iterator.return();
|
|
252
|
+
}
|
|
253
|
+
} finally{
|
|
254
|
+
if (_didIteratorError) {
|
|
255
|
+
throw _iteratorError;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return [
|
|
260
|
+
2,
|
|
261
|
+
null
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}).call(this);
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
key: "sign",
|
|
270
|
+
value: /**
|
|
271
|
+
* Sign data with a key from the agent
|
|
272
|
+
* Returns the sshpk.Signature object
|
|
273
|
+
*/ function sign(key, data) {
|
|
274
|
+
return _async_to_generator(function() {
|
|
275
|
+
var client;
|
|
276
|
+
return _ts_generator(this, function(_state) {
|
|
277
|
+
client = this.getClient();
|
|
278
|
+
return [
|
|
279
|
+
2,
|
|
280
|
+
new Promise(function(resolve, reject) {
|
|
281
|
+
client.sign(key, data, function(err, signature) {
|
|
282
|
+
if (err) {
|
|
283
|
+
reject(err);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
resolve(signature);
|
|
287
|
+
});
|
|
288
|
+
})
|
|
289
|
+
];
|
|
290
|
+
});
|
|
291
|
+
}).call(this);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
]);
|
|
295
|
+
return AgentSigner;
|
|
296
|
+
}();
|
|
@@ -171,6 +171,15 @@ import { createPublicKey } from 'crypto';
|
|
|
171
171
|
var publicKey = privateKey.toPublic();
|
|
172
172
|
return publicKey.fingerprint('sha256').toString();
|
|
173
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Get the fingerprint from a public key file (.pub file)
|
|
176
|
+
* This is useful when the private key is encrypted but we need the fingerprint
|
|
177
|
+
* to look up the key in ssh-agent
|
|
178
|
+
*/ export function getPublicKeyFingerprint(pubKeyPath) {
|
|
179
|
+
var content = readFileSync(pubKeyPath, 'utf-8').trim();
|
|
180
|
+
var sshKey = sshpk.parseKey(content, 'auto');
|
|
181
|
+
return sshKey.fingerprint('sha256').toString();
|
|
182
|
+
}
|
|
174
183
|
/**
|
|
175
184
|
* Resolve the private key path from environment, config, or default
|
|
176
185
|
* @param configuredPath - Optional configured path from ProjectConfigManager
|
|
File without changes
|
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JWT Auth Provider for authenticating API requests
|
|
3
3
|
* Uses SSH private keys to sign short-lived JWTs
|
|
4
|
+
* Falls back to ssh-agent for encrypted keys
|
|
4
5
|
*/
|
|
5
6
|
export declare class JwtAuthProvider {
|
|
6
7
|
private privateKey;
|
|
7
8
|
private fingerprint;
|
|
8
9
|
private initialized;
|
|
9
10
|
private initError;
|
|
11
|
+
private encryptedKeyPath;
|
|
12
|
+
private agentSigner;
|
|
13
|
+
private agentKey;
|
|
14
|
+
private useAgent;
|
|
10
15
|
constructor();
|
|
11
16
|
private initialize;
|
|
12
17
|
/**
|
|
13
18
|
* Check if the provider is ready to create JWTs
|
|
19
|
+
* Returns true if we have a direct key OR if we have an encrypted key
|
|
20
|
+
* that might work with agent fallback
|
|
14
21
|
*/
|
|
15
22
|
isReady(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Check if we have an encrypted key that requires agent fallback
|
|
25
|
+
*/
|
|
26
|
+
hasEncryptedKey(): boolean;
|
|
16
27
|
/**
|
|
17
28
|
* Get the error that occurred during initialization, if any
|
|
18
29
|
*/
|
|
@@ -25,10 +36,33 @@ export declare class JwtAuthProvider {
|
|
|
25
36
|
* Map SSH key type to JWT algorithm
|
|
26
37
|
*/
|
|
27
38
|
private getAlgorithm;
|
|
39
|
+
/**
|
|
40
|
+
* Map SSH key type string to JWT algorithm
|
|
41
|
+
*/
|
|
42
|
+
private getAlgorithmForKeyType;
|
|
43
|
+
/**
|
|
44
|
+
* Convert the SSH private key to PKCS8 PEM format
|
|
45
|
+
* Ed25519 keys need special handling because sshpk's PKCS8 output
|
|
46
|
+
* is not compatible with Node.js/OpenSSL
|
|
47
|
+
*/
|
|
48
|
+
private getPkcs8Pem;
|
|
28
49
|
/**
|
|
29
50
|
* Create a short-lived JWT for authentication
|
|
30
51
|
*/
|
|
31
52
|
createToken(): Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Create JWT using direct private key (jose library)
|
|
55
|
+
*/
|
|
56
|
+
private createTokenDirect;
|
|
57
|
+
/**
|
|
58
|
+
* Try to use ssh-agent for signing when private key is encrypted
|
|
59
|
+
*/
|
|
60
|
+
private tryAgentFallback;
|
|
61
|
+
/**
|
|
62
|
+
* Create JWT using ssh-agent for signing
|
|
63
|
+
* Manually constructs the JWT since jose expects to do signing itself
|
|
64
|
+
*/
|
|
65
|
+
private createTokenWithAgent;
|
|
32
66
|
}
|
|
33
67
|
/**
|
|
34
68
|
* Get the singleton JWT auth provider instance
|
|
@@ -45,7 +79,8 @@ export declare function resetJwtAuthProvider(): void;
|
|
|
45
79
|
export declare function isAuthAvailable(): boolean;
|
|
46
80
|
/**
|
|
47
81
|
* Get the Authorization header if auth is available
|
|
48
|
-
*
|
|
82
|
+
* Throws if there's an auth configuration error
|
|
83
|
+
* Returns empty object with warning if no key is configured
|
|
49
84
|
*/
|
|
50
85
|
export declare function getAuthHeader(): Promise<Record<string, string>>;
|
|
51
86
|
//# sourceMappingURL=jwt-auth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-auth.d.ts","sourceRoot":"","sources":["../../../src/lib/jwt-auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"jwt-auth.d.ts","sourceRoot":"","sources":["../../../src/lib/jwt-auth.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAsB;IAGvC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,QAAQ,CAAS;;IAMzB,OAAO,CAAC,UAAU;IAqClB;;;;OAIG;IACH,OAAO,IAAI,OAAO;IAYlB;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,QAAQ,IAAI,KAAK,GAAG,IAAI;IAIxB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAqB9B;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAiCnB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAoBpC;;OAEG;YACW,iBAAiB;IAwB/B;;OAEG;YACW,gBAAgB;IAwC9B;;;OAGG;YACW,oBAAoB;CAuCnC;AAKD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAgBrE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import sshpk from 'sshpk';
|
|
2
|
+
/**
|
|
3
|
+
* Wrapper for ssh-agent operations using sshpk-agent
|
|
4
|
+
*/
|
|
5
|
+
export declare class AgentSigner {
|
|
6
|
+
private client;
|
|
7
|
+
private keys;
|
|
8
|
+
/**
|
|
9
|
+
* Check if ssh-agent is available (SSH_AUTH_SOCK environment variable exists)
|
|
10
|
+
*/
|
|
11
|
+
isAvailable(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Get the agent client, creating it lazily
|
|
14
|
+
*/
|
|
15
|
+
private getClient;
|
|
16
|
+
/**
|
|
17
|
+
* List all keys available in the ssh-agent
|
|
18
|
+
*/
|
|
19
|
+
getKeys(): Promise<sshpk.Key[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Check if the agent has a key with the given fingerprint
|
|
22
|
+
* Returns the key if found, null otherwise
|
|
23
|
+
*/
|
|
24
|
+
hasKey(fingerprint: string): Promise<sshpk.Key | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Sign data with a key from the agent
|
|
27
|
+
* Returns the sshpk.Signature object
|
|
28
|
+
*/
|
|
29
|
+
sign(key: sshpk.Key, data: Buffer): Promise<sshpk.Signature>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ssh-agent-signer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssh-agent-signer.d.ts","sourceRoot":"","sources":["../../../src/lib/ssh-agent-signer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA4B;IAExC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,OAAO,CAAC,SAAS;IAOjB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAmBrC;;;OAGG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;IAa5D;;;OAGG;IACG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;CAanE"}
|
|
@@ -29,6 +29,12 @@ export declare function loadPrivateKey(pathOrEnv?: string): sshpk.PrivateKey;
|
|
|
29
29
|
* Get the fingerprint of a private key (from its public component)
|
|
30
30
|
*/
|
|
31
31
|
export declare function getPrivateKeyFingerprint(privateKey: sshpk.PrivateKey): string;
|
|
32
|
+
/**
|
|
33
|
+
* Get the fingerprint from a public key file (.pub file)
|
|
34
|
+
* This is useful when the private key is encrypted but we need the fingerprint
|
|
35
|
+
* to look up the key in ssh-agent
|
|
36
|
+
*/
|
|
37
|
+
export declare function getPublicKeyFingerprint(pubKeyPath: string): string;
|
|
32
38
|
/**
|
|
33
39
|
* Resolve the private key path from environment, config, or default
|
|
34
40
|
* @param configuredPath - Optional configured path from ProjectConfigManager
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssh-key-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/ssh-key-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAmB,UAAU,EAAE,MAAM,QAAQ,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,UAAU,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,aAAa,EAAE,CAkDjD;AA0CD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAiBpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,CAyBnE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAG7E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAoB5E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKlD"}
|
|
1
|
+
{"version":3,"file":"ssh-key-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/ssh-key-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAmB,UAAU,EAAE,MAAM,QAAQ,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,UAAU,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,aAAa,EAAE,CAkDjD;AA0CD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAiBpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,CAyBnE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAoB5E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKlD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@positronic/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.60",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"clean": "rm -rf tsconfig.tsbuildinfo dist node_modules"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@positronic/core": "^0.0.
|
|
27
|
-
"@positronic/spec": "^0.0.
|
|
28
|
-
"@positronic/template-new-project": "^0.0.
|
|
26
|
+
"@positronic/core": "^0.0.60",
|
|
27
|
+
"@positronic/spec": "^0.0.60",
|
|
28
|
+
"@positronic/template-new-project": "^0.0.60",
|
|
29
29
|
"caz": "^2.0.0",
|
|
30
30
|
"chokidar": "^3.6.0",
|
|
31
31
|
"dotenv": "^16.4.7",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"react": "^18.3.1",
|
|
39
39
|
"react-robot": "^1.2.1",
|
|
40
40
|
"sshpk": "^1.18.0",
|
|
41
|
+
"sshpk-agent": "^1.8.1",
|
|
41
42
|
"yargs": "^17.7.2"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|