@i4ctime/q-ring 0.17.5 → 0.18.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/README.md +52 -10
- package/dist/{chunk-VMDD5QTJ.js → chunk-NTCTVLSK.js} +126 -38
- package/dist/chunk-NTCTVLSK.js.map +1 -0
- package/dist/{chunk-5ZCQSBVS.js → chunk-ZBPMEJRO.js} +142 -38
- package/dist/chunk-ZBPMEJRO.js.map +1 -0
- package/dist/dashboard-LICF6OZ5.js +699 -0
- package/dist/dashboard-LICF6OZ5.js.map +1 -0
- package/dist/dashboard-OEHI6OOD.js +699 -0
- package/dist/dashboard-OEHI6OOD.js.map +1 -0
- package/dist/index.js +833 -82
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +681 -172
- package/dist/mcp.js.map +1 -1
- package/package.json +10 -10
- package/dist/chunk-5ZCQSBVS.js.map +0 -1
- package/dist/chunk-VMDD5QTJ.js.map +0 -1
- package/dist/dashboard-K7LYTWSL.js +0 -685
- package/dist/dashboard-K7LYTWSL.js.map +0 -1
- package/dist/dashboard-ZN3FPR73.js +0 -685
- package/dist/dashboard-ZN3FPR73.js.map +0 -1
|
@@ -36,6 +36,10 @@ var SecretMetadataSchema = z.object({
|
|
|
36
36
|
ephemeral: z.boolean().optional(),
|
|
37
37
|
rotationFormat: z.string().optional(),
|
|
38
38
|
rotationPrefix: z.string().optional(),
|
|
39
|
+
rotatedAt: z.string().optional(),
|
|
40
|
+
// `.catch(undefined)`: a bad interval strips the reminder rather than
|
|
41
|
+
// rejecting the whole envelope (which would surface the JSON as the value).
|
|
42
|
+
rotateEveryDays: z.number().int().positive().max(3650).optional().catch(void 0),
|
|
39
43
|
provider: z.string().optional(),
|
|
40
44
|
validationUrl: z.string().optional(),
|
|
41
45
|
requiresApproval: z.boolean().optional(),
|
|
@@ -73,6 +77,8 @@ function createEnvelope(value, opts) {
|
|
|
73
77
|
accessCount: 0,
|
|
74
78
|
rotationFormat: opts?.rotationFormat,
|
|
75
79
|
rotationPrefix: opts?.rotationPrefix,
|
|
80
|
+
rotatedAt: opts?.rotatedAt ?? now,
|
|
81
|
+
rotateEveryDays: opts?.rotateEveryDays,
|
|
76
82
|
provider: opts?.provider,
|
|
77
83
|
requiresApproval: opts?.requiresApproval,
|
|
78
84
|
jitProvider: opts?.jitProvider,
|
|
@@ -302,14 +308,13 @@ import {
|
|
|
302
308
|
closeSync,
|
|
303
309
|
statSync as statSync3
|
|
304
310
|
} from "fs";
|
|
305
|
-
import { join as
|
|
306
|
-
import { homedir as homedir3 } from "os";
|
|
311
|
+
import { join as join6 } from "path";
|
|
307
312
|
import { createHash, createHmac, randomBytes as randomBytes2 } from "crypto";
|
|
308
313
|
|
|
309
314
|
// src/core/backend.ts
|
|
310
315
|
import { Entry as NapiEntry, findCredentials as napiFindCredentials } from "@napi-rs/keyring";
|
|
311
316
|
import { existsSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, chmodSync } from "fs";
|
|
312
|
-
import { dirname as dirname2, join as
|
|
317
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
313
318
|
import { homedir as homedir2 } from "os";
|
|
314
319
|
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from "crypto";
|
|
315
320
|
|
|
@@ -321,8 +326,19 @@ import {
|
|
|
321
326
|
readFileSync as readFileSync3,
|
|
322
327
|
statSync as statSync2
|
|
323
328
|
} from "fs";
|
|
324
|
-
import { join as
|
|
329
|
+
import { join as join4 } from "path";
|
|
330
|
+
|
|
331
|
+
// src/utils/config-dir.ts
|
|
325
332
|
import { homedir } from "os";
|
|
333
|
+
import { join as join3 } from "path";
|
|
334
|
+
var CONFIG_DIR_ENV = "QRING_CONFIG_DIR";
|
|
335
|
+
function configDir() {
|
|
336
|
+
const override = process.env[CONFIG_DIR_ENV];
|
|
337
|
+
if (override && override.trim()) return override;
|
|
338
|
+
return join3(homedir(), ".config", "q-ring");
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// src/utils/file-lock.ts
|
|
326
342
|
function sleepSync(ms) {
|
|
327
343
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
328
344
|
}
|
|
@@ -335,11 +351,11 @@ function isProcessAlive(pid) {
|
|
|
335
351
|
}
|
|
336
352
|
}
|
|
337
353
|
function withFileLock(name, fn, opts = {}) {
|
|
338
|
-
const baseDir = process.env.QRING_LOCK_DIR ?? (process.env.QRING_AUDIT_DIR ?
|
|
339
|
-
const lockDir =
|
|
354
|
+
const baseDir = process.env.QRING_LOCK_DIR ?? (process.env.QRING_AUDIT_DIR ? join4(process.env.QRING_AUDIT_DIR, ".locks") : configDir());
|
|
355
|
+
const lockDir = join4(baseDir, opts.dir ?? "locks");
|
|
340
356
|
mkdirSync(lockDir, { recursive: true, mode: 448 });
|
|
341
357
|
const safe = Buffer.from(name, "utf8").toString("base64url");
|
|
342
|
-
const lockPath =
|
|
358
|
+
const lockPath = join4(lockDir, `${safe}.lock`);
|
|
343
359
|
const deadline = Date.now() + (opts.timeoutMs ?? 8e3);
|
|
344
360
|
const staleMs = opts.staleMs ?? 3e4;
|
|
345
361
|
while (Date.now() < deadline) {
|
|
@@ -382,6 +398,12 @@ var PATH_ENV = "QRING_FILE_BACKEND_PATH";
|
|
|
382
398
|
var PBKDF2_ITERATIONS = 21e4;
|
|
383
399
|
var KEY_LENGTH = 32;
|
|
384
400
|
var FILE_PREFIX = "qfile1";
|
|
401
|
+
function keyringFailure(op, err) {
|
|
402
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
403
|
+
return new BackendUnavailableError(
|
|
404
|
+
`OS keyring ${op} failed \u2014 the credential store is locked or unreachable (${detail}). Unlock your keyring (or set ${BACKEND_ENV}=file with ${PASSPHRASE_ENV} for a headless store) and retry.`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
385
407
|
var BackendUnavailableError = class extends Error {
|
|
386
408
|
constructor(message) {
|
|
387
409
|
super(message);
|
|
@@ -399,7 +421,7 @@ function activeBackend() {
|
|
|
399
421
|
return "keyring";
|
|
400
422
|
}
|
|
401
423
|
function storePath() {
|
|
402
|
-
return process.env[PATH_ENV] ??
|
|
424
|
+
return process.env[PATH_ENV] ?? join5(homedir2(), ".config", "q-ring", "file-backend.enc");
|
|
403
425
|
}
|
|
404
426
|
function passphrase() {
|
|
405
427
|
const p = process.env[PASSPHRASE_ENV];
|
|
@@ -492,7 +514,11 @@ var Entry = class {
|
|
|
492
514
|
if (activeBackend() === "file") {
|
|
493
515
|
return loadStore().map[this.storeKey()] ?? null;
|
|
494
516
|
}
|
|
495
|
-
|
|
517
|
+
try {
|
|
518
|
+
return this.delegate().getPassword();
|
|
519
|
+
} catch (err) {
|
|
520
|
+
throw keyringFailure("read", err);
|
|
521
|
+
}
|
|
496
522
|
}
|
|
497
523
|
setPassword(password) {
|
|
498
524
|
if (activeBackend() === "file") {
|
|
@@ -511,7 +537,11 @@ var Entry = class {
|
|
|
511
537
|
return existed;
|
|
512
538
|
});
|
|
513
539
|
}
|
|
514
|
-
|
|
540
|
+
try {
|
|
541
|
+
return this.delegate().deleteCredential();
|
|
542
|
+
} catch (err) {
|
|
543
|
+
throw keyringFailure("delete", err);
|
|
544
|
+
}
|
|
515
545
|
}
|
|
516
546
|
// @napi-rs/keyring's other delete alias, used by `qring doctor`.
|
|
517
547
|
deletePassword() {
|
|
@@ -592,14 +622,14 @@ function getAuditDir() {
|
|
|
592
622
|
}
|
|
593
623
|
return process.env.QRING_AUDIT_DIR;
|
|
594
624
|
}
|
|
595
|
-
const dir =
|
|
625
|
+
const dir = configDir();
|
|
596
626
|
if (!existsSync2(dir)) {
|
|
597
627
|
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
598
628
|
}
|
|
599
629
|
return dir;
|
|
600
630
|
}
|
|
601
631
|
function getAuditPath() {
|
|
602
|
-
return
|
|
632
|
+
return join6(getAuditDir(), "audit.jsonl");
|
|
603
633
|
}
|
|
604
634
|
function getLastLineHash() {
|
|
605
635
|
const path = getAuditPath();
|
|
@@ -849,8 +879,7 @@ function detectAnomalies(key) {
|
|
|
849
879
|
|
|
850
880
|
// src/core/entanglement.ts
|
|
851
881
|
import { existsSync as existsSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "fs";
|
|
852
|
-
import { join as
|
|
853
|
-
import { homedir as homedir4 } from "os";
|
|
882
|
+
import { join as join7 } from "path";
|
|
854
883
|
|
|
855
884
|
// src/utils/registry.ts
|
|
856
885
|
import { existsSync as existsSync3, readFileSync as readFileSync6, renameSync } from "fs";
|
|
@@ -880,11 +909,11 @@ function loadJsonRegistry(path, empty) {
|
|
|
880
909
|
// src/core/entanglement.ts
|
|
881
910
|
var REGISTRY_VERSION = 1;
|
|
882
911
|
function getRegistryPath() {
|
|
883
|
-
const dir =
|
|
912
|
+
const dir = configDir();
|
|
884
913
|
if (!existsSync4(dir)) {
|
|
885
914
|
mkdirSync4(dir, { recursive: true, mode: 448 });
|
|
886
915
|
}
|
|
887
|
-
return
|
|
916
|
+
return join7(dir, "entanglement.json");
|
|
888
917
|
}
|
|
889
918
|
function loadRegistry() {
|
|
890
919
|
return loadJsonRegistry(getRegistryPath(), { pairs: [] });
|
|
@@ -926,8 +955,7 @@ function listEntanglements() {
|
|
|
926
955
|
|
|
927
956
|
// src/core/hooks.ts
|
|
928
957
|
import { existsSync as existsSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "fs";
|
|
929
|
-
import { join as
|
|
930
|
-
import { homedir as homedir5 } from "os";
|
|
958
|
+
import { join as join8 } from "path";
|
|
931
959
|
import { execFile, spawn } from "child_process";
|
|
932
960
|
import { randomUUID } from "crypto";
|
|
933
961
|
|
|
@@ -1151,11 +1179,11 @@ function httpRequest(opts) {
|
|
|
1151
1179
|
|
|
1152
1180
|
// src/core/hooks.ts
|
|
1153
1181
|
function getRegistryPath2() {
|
|
1154
|
-
const dir =
|
|
1182
|
+
const dir = configDir();
|
|
1155
1183
|
if (!existsSync5(dir)) {
|
|
1156
1184
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
1157
1185
|
}
|
|
1158
|
-
return
|
|
1186
|
+
return join8(dir, "hooks.json");
|
|
1159
1187
|
}
|
|
1160
1188
|
function loadRegistry2() {
|
|
1161
1189
|
return loadJsonRegistry(getRegistryPath2(), { hooks: [] });
|
|
@@ -1425,12 +1453,11 @@ async function fireHooks(payload, tags) {
|
|
|
1425
1453
|
|
|
1426
1454
|
// src/core/approval.ts
|
|
1427
1455
|
import { existsSync as existsSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6 } from "fs";
|
|
1428
|
-
import { join as
|
|
1429
|
-
import { homedir as homedir6 } from "os";
|
|
1456
|
+
import { join as join9 } from "path";
|
|
1430
1457
|
import { createHmac as createHmac2, randomBytes as randomBytes3, timingSafeEqual } from "crypto";
|
|
1431
1458
|
function getHmacSecret() {
|
|
1432
|
-
const dir =
|
|
1433
|
-
const secretPath =
|
|
1459
|
+
const dir = configDir();
|
|
1460
|
+
const secretPath = join9(dir, ".approval-key");
|
|
1434
1461
|
if (!existsSync6(dir)) mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
1435
1462
|
if (existsSync6(secretPath)) {
|
|
1436
1463
|
return readFileSync7(secretPath, "utf8").trim();
|
|
@@ -1466,11 +1493,11 @@ function verifyHmac(entry) {
|
|
|
1466
1493
|
}
|
|
1467
1494
|
}
|
|
1468
1495
|
function getRegistryPath3() {
|
|
1469
|
-
const dir =
|
|
1496
|
+
const dir = configDir();
|
|
1470
1497
|
if (!existsSync6(dir)) {
|
|
1471
1498
|
mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
1472
1499
|
}
|
|
1473
|
-
return
|
|
1500
|
+
return join9(dir, "approvals.json");
|
|
1474
1501
|
}
|
|
1475
1502
|
function loadRegistry3() {
|
|
1476
1503
|
return loadJsonRegistry(getRegistryPath3(), { approvals: [] });
|
|
@@ -1548,7 +1575,7 @@ function listApprovals() {
|
|
|
1548
1575
|
|
|
1549
1576
|
// src/core/policy.ts
|
|
1550
1577
|
import { statSync as statSync4 } from "fs";
|
|
1551
|
-
import { join as
|
|
1578
|
+
import { join as join10 } from "path";
|
|
1552
1579
|
import { z as z2 } from "zod";
|
|
1553
1580
|
var stringArray = z2.array(z2.string());
|
|
1554
1581
|
var mcpPolicySchema = z2.object({
|
|
@@ -1607,7 +1634,7 @@ function resolvePolicyPath(projectPath) {
|
|
|
1607
1634
|
}
|
|
1608
1635
|
function configMtime(pp) {
|
|
1609
1636
|
try {
|
|
1610
|
-
return statSync4(
|
|
1637
|
+
return statSync4(join10(pp, ".q-ring.json")).mtimeMs;
|
|
1611
1638
|
} catch {
|
|
1612
1639
|
return 0;
|
|
1613
1640
|
}
|
|
@@ -1630,7 +1657,7 @@ function loadPolicy(projectPath) {
|
|
|
1630
1657
|
if (!parsed.success) {
|
|
1631
1658
|
const issues = parsed.error.issues.map((i) => `policy${i.path.length ? "." + i.path.join(".") : ""}: ${i.message}`).join("; ");
|
|
1632
1659
|
const error = new PolicyConfigError(
|
|
1633
|
-
`Invalid policy in ${
|
|
1660
|
+
`Invalid policy in ${join10(pp, ".q-ring.json")} \u2014 refusing to run under an unparseable security policy (fail closed). Fix these and retry: ${issues}`
|
|
1634
1661
|
);
|
|
1635
1662
|
console.error(`q-ring: ${error.message}`);
|
|
1636
1663
|
cachedPolicy = { path: pp, mtimeMs, error };
|
|
@@ -1894,16 +1921,15 @@ function notifyApprovalRequested(key, source) {
|
|
|
1894
1921
|
|
|
1895
1922
|
// src/core/canary-webhooks.ts
|
|
1896
1923
|
import { existsSync as existsSync7, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7 } from "fs";
|
|
1897
|
-
import { join as
|
|
1898
|
-
import { homedir as homedir7 } from "os";
|
|
1924
|
+
import { join as join11 } from "path";
|
|
1899
1925
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1900
1926
|
var CANARY_ALERT_TYPES = ["discord", "slack", "ntfy", "generic"];
|
|
1901
1927
|
function getRegistryPath4() {
|
|
1902
1928
|
const override = process.env.QRING_CANARY_ALERTS_PATH;
|
|
1903
1929
|
if (override) return override;
|
|
1904
|
-
const dir =
|
|
1930
|
+
const dir = configDir();
|
|
1905
1931
|
if (!existsSync7(dir)) mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
1906
|
-
return
|
|
1932
|
+
return join11(dir, "canary-alerts.json");
|
|
1907
1933
|
}
|
|
1908
1934
|
function loadRegistry4() {
|
|
1909
1935
|
return loadJsonRegistry(getRegistryPath4(), { channels: [] });
|
|
@@ -2253,6 +2279,10 @@ registry.register(httpProvider);
|
|
|
2253
2279
|
function withJitEnvelopeLock(service, key, fn) {
|
|
2254
2280
|
return withFileLock(`${service}\0${key}`, fn, { dir: "jit-locks" });
|
|
2255
2281
|
}
|
|
2282
|
+
var MAX_ROTATE_EVERY_DAYS = 3650;
|
|
2283
|
+
function isValidRotateEveryDays(days) {
|
|
2284
|
+
return Number.isInteger(days) && days >= 1 && days <= MAX_ROTATE_EVERY_DAYS;
|
|
2285
|
+
}
|
|
2256
2286
|
function readEnvelope(service, key) {
|
|
2257
2287
|
const entry = new Entry(service, key);
|
|
2258
2288
|
const raw = entry.getPassword();
|
|
@@ -2415,6 +2445,14 @@ function setSecret(key, value, opts = {}) {
|
|
|
2415
2445
|
let envelope;
|
|
2416
2446
|
const rotFmt = opts.rotationFormat ?? existing?.meta.rotationFormat;
|
|
2417
2447
|
const rotPfx = opts.rotationPrefix ?? existing?.meta.rotationPrefix;
|
|
2448
|
+
const rotEvery = opts.rotateEveryDays ?? existing?.meta.rotateEveryDays;
|
|
2449
|
+
if (rotEvery !== void 0 && !isValidRotateEveryDays(rotEvery)) {
|
|
2450
|
+
throw new Error(
|
|
2451
|
+
`rotateEveryDays must be a whole number of days between 1 and ${MAX_ROTATE_EVERY_DAYS}`
|
|
2452
|
+
);
|
|
2453
|
+
}
|
|
2454
|
+
const valueChanged = !existing || (opts.states ? JSON.stringify(existing.states ?? null) !== JSON.stringify(opts.states) : existing.states !== void 0 || existing.value !== value);
|
|
2455
|
+
const rotatedAt = valueChanged ? (/* @__PURE__ */ new Date()).toISOString() : existing?.meta.rotatedAt ?? existing?.meta.updatedAt ?? existing?.meta.createdAt;
|
|
2418
2456
|
const prov = opts.provider ?? existing?.meta.provider;
|
|
2419
2457
|
const reqApp = opts.requiresApproval ?? existing?.meta.requiresApproval;
|
|
2420
2458
|
const jitProv = opts.jitProvider ?? existing?.meta.jitProvider;
|
|
@@ -2445,6 +2483,8 @@ function setSecret(key, value, opts = {}) {
|
|
|
2445
2483
|
entangled: existing?.meta.entangled,
|
|
2446
2484
|
rotationFormat: rotFmt,
|
|
2447
2485
|
rotationPrefix: rotPfx,
|
|
2486
|
+
rotatedAt,
|
|
2487
|
+
rotateEveryDays: rotEvery,
|
|
2448
2488
|
provider: prov,
|
|
2449
2489
|
requiresApproval: reqApp,
|
|
2450
2490
|
jitProvider: jitProv,
|
|
@@ -2460,6 +2500,8 @@ function setSecret(key, value, opts = {}) {
|
|
|
2460
2500
|
entangled: existing?.meta.entangled,
|
|
2461
2501
|
rotationFormat: rotFmt,
|
|
2462
2502
|
rotationPrefix: rotPfx,
|
|
2503
|
+
rotatedAt,
|
|
2504
|
+
rotateEveryDays: rotEvery,
|
|
2463
2505
|
provider: prov,
|
|
2464
2506
|
requiresApproval: reqApp,
|
|
2465
2507
|
jitProvider: jitProv,
|
|
@@ -2742,6 +2784,61 @@ function disentangleSecrets(sourceKey, sourceOpts, targetKey, targetOpts) {
|
|
|
2742
2784
|
});
|
|
2743
2785
|
}
|
|
2744
2786
|
|
|
2787
|
+
// src/core/rotation.ts
|
|
2788
|
+
var DAY_MS = 864e5;
|
|
2789
|
+
var DUE_SOON_FRACTION = 0.2;
|
|
2790
|
+
var DUE_SOON_MAX_DAYS = 7;
|
|
2791
|
+
function dueSoonWindowDays(rotateEveryDays) {
|
|
2792
|
+
return Math.min(rotateEveryDays * DUE_SOON_FRACTION, DUE_SOON_MAX_DAYS);
|
|
2793
|
+
}
|
|
2794
|
+
function parseMs(iso) {
|
|
2795
|
+
if (!iso) return null;
|
|
2796
|
+
const ms = new Date(iso).getTime();
|
|
2797
|
+
return Number.isFinite(ms) ? ms : null;
|
|
2798
|
+
}
|
|
2799
|
+
function rotationStatus(meta, now = Date.now()) {
|
|
2800
|
+
const nowMs = typeof now === "number" ? now : now.getTime();
|
|
2801
|
+
const lastRotatedAt = meta.rotatedAt ?? meta.updatedAt ?? meta.createdAt;
|
|
2802
|
+
const lastMs = parseMs(lastRotatedAt) ?? nowMs;
|
|
2803
|
+
const ageDays = Math.max(0, Math.floor((nowMs - lastMs) / DAY_MS));
|
|
2804
|
+
const every = meta.rotateEveryDays;
|
|
2805
|
+
if (!every || !Number.isFinite(every) || every <= 0) {
|
|
2806
|
+
return {
|
|
2807
|
+
lastRotatedAt,
|
|
2808
|
+
ageDays,
|
|
2809
|
+
rotateEveryDays: null,
|
|
2810
|
+
dueAt: null,
|
|
2811
|
+
daysUntilDue: null,
|
|
2812
|
+
state: "unscheduled"
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
const dueMs = lastMs + every * DAY_MS;
|
|
2816
|
+
const untilMs = dueMs - nowMs;
|
|
2817
|
+
const daysUntilDue = Math.ceil(untilMs / DAY_MS);
|
|
2818
|
+
let state = "ok";
|
|
2819
|
+
if (untilMs <= 0) state = "overdue";
|
|
2820
|
+
else if (untilMs <= dueSoonWindowDays(every) * DAY_MS) state = "due-soon";
|
|
2821
|
+
return {
|
|
2822
|
+
lastRotatedAt,
|
|
2823
|
+
ageDays,
|
|
2824
|
+
rotateEveryDays: every,
|
|
2825
|
+
dueAt: new Date(dueMs).toISOString(),
|
|
2826
|
+
daysUntilDue,
|
|
2827
|
+
state
|
|
2828
|
+
};
|
|
2829
|
+
}
|
|
2830
|
+
function describeRotation(status) {
|
|
2831
|
+
if (status.state === "unscheduled" || status.daysUntilDue === null) return "unscheduled";
|
|
2832
|
+
if (status.daysUntilDue > 0) return `due in ${status.daysUntilDue}d`;
|
|
2833
|
+
if (status.daysUntilDue === 0) return "due now";
|
|
2834
|
+
return `overdue ${-status.daysUntilDue}d`;
|
|
2835
|
+
}
|
|
2836
|
+
function compareRotationUrgency(a, b) {
|
|
2837
|
+
const ad = a.daysUntilDue ?? Number.POSITIVE_INFINITY;
|
|
2838
|
+
const bd = b.daysUntilDue ?? Number.POSITIVE_INFINITY;
|
|
2839
|
+
return ad - bd;
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2745
2842
|
// src/core/tunnel.ts
|
|
2746
2843
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
2747
2844
|
var tunnelStore = /* @__PURE__ */ new Map();
|
|
@@ -2816,8 +2913,8 @@ function tunnelList() {
|
|
|
2816
2913
|
|
|
2817
2914
|
// src/core/memory.ts
|
|
2818
2915
|
import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, chmodSync as chmodSync3 } from "fs";
|
|
2819
|
-
import { join as
|
|
2820
|
-
import {
|
|
2916
|
+
import { join as join12 } from "path";
|
|
2917
|
+
import { hostname, userInfo } from "os";
|
|
2821
2918
|
import {
|
|
2822
2919
|
createCipheriv as createCipheriv2,
|
|
2823
2920
|
createDecipheriv as createDecipheriv2,
|
|
@@ -2829,7 +2926,7 @@ var MEMORY_FILE = "agent-memory.enc";
|
|
|
2829
2926
|
var KEYRING_SERVICE = "qring-memory-key";
|
|
2830
2927
|
var KEYRING_ACCOUNT = "encryption-key";
|
|
2831
2928
|
function getMemoryDir() {
|
|
2832
|
-
const dir =
|
|
2929
|
+
const dir = configDir();
|
|
2833
2930
|
if (!existsSync8(dir)) {
|
|
2834
2931
|
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
2835
2932
|
}
|
|
@@ -2843,7 +2940,7 @@ function writeMemoryFile(path, data) {
|
|
|
2843
2940
|
}
|
|
2844
2941
|
}
|
|
2845
2942
|
function getMemoryPath() {
|
|
2846
|
-
return
|
|
2943
|
+
return join12(getMemoryDir(), MEMORY_FILE);
|
|
2847
2944
|
}
|
|
2848
2945
|
var PBKDF2_ITERATIONS2 = 21e4;
|
|
2849
2946
|
var KEY_LENGTH2 = 32;
|
|
@@ -3061,6 +3158,8 @@ function listAgentSessions(query = {}) {
|
|
|
3061
3158
|
|
|
3062
3159
|
export {
|
|
3063
3160
|
PACKAGE_VERSION,
|
|
3161
|
+
configDir,
|
|
3162
|
+
Entry,
|
|
3064
3163
|
hashProjectPath,
|
|
3065
3164
|
serviceForScope,
|
|
3066
3165
|
checkDecay,
|
|
@@ -3101,6 +3200,8 @@ export {
|
|
|
3101
3200
|
wrapToolRequiresApproval,
|
|
3102
3201
|
getWrapRateLimit,
|
|
3103
3202
|
wrapRedactsResults,
|
|
3203
|
+
MAX_ROTATE_EVERY_DAYS,
|
|
3204
|
+
isValidRotateEveryDays,
|
|
3104
3205
|
getSecret,
|
|
3105
3206
|
getEnvelope,
|
|
3106
3207
|
setSecret,
|
|
@@ -3111,6 +3212,9 @@ export {
|
|
|
3111
3212
|
exportSecrets,
|
|
3112
3213
|
entangleSecrets,
|
|
3113
3214
|
disentangleSecrets,
|
|
3215
|
+
rotationStatus,
|
|
3216
|
+
describeRotation,
|
|
3217
|
+
compareRotationUrgency,
|
|
3114
3218
|
tunnelCreate,
|
|
3115
3219
|
tunnelRead,
|
|
3116
3220
|
tunnelDestroy,
|
|
@@ -3123,4 +3227,4 @@ export {
|
|
|
3123
3227
|
buildSessions,
|
|
3124
3228
|
listAgentSessions
|
|
3125
3229
|
};
|
|
3126
|
-
//# sourceMappingURL=chunk-
|
|
3230
|
+
//# sourceMappingURL=chunk-ZBPMEJRO.js.map
|