@kici-dev/orchestrator 0.10.0 → 0.11.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/dist/cli/api-client.d.ts +20 -1
- package/dist/cli/commands/attestations.d.ts +10 -0
- package/dist/cli/commands/cold-store-impl.d.ts +3 -3
- package/dist/cli/commands/cold-store.d.ts +6 -3
- package/dist/cli/commands/context.d.ts +3 -1
- package/dist/cli/commands/dashboard-encryption-key.d.ts +18 -0
- package/dist/cli/commands/event-dlq.d.ts +2 -2
- package/dist/cli/commands/registration.d.ts +8 -4
- package/dist/cli/commands/secret.d.ts +1 -0
- package/dist/cli/commands/shared/confirm.d.ts +19 -0
- package/dist/cli.js +251 -158
- package/dist/contexts/variable-store.d.ts +2 -0
- package/dist/index.js +26 -0
- package/dist/routes/admin-contexts.d.ts +6 -0
- package/dist/routes/admin-registrations.d.ts +2 -2
- package/dist/secrets/audit-logger.d.ts +1 -1
- package/dist/server.js +174 -25
- package/dist/standalone.js +174 -25
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +53 -53
package/dist/cli.js
CHANGED
|
@@ -254,6 +254,32 @@ var AdminApiClient = class {
|
|
|
254
254
|
return this.request("DELETE", `/api/v1/admin/secrets/${encodeURIComponent(orgId)}/${encodeURIComponent(scope)}/${encodeURIComponent(key)}`);
|
|
255
255
|
}
|
|
256
256
|
/**
|
|
257
|
+
* Create an empty secret scope. A `<backend>:` qualifier selects the
|
|
258
|
+
* backend; an unqualified scope targets the PG backend. Creating a scope
|
|
259
|
+
* that already exists succeeds and changes nothing.
|
|
260
|
+
*/
|
|
261
|
+
async createScope(orgId, scope) {
|
|
262
|
+
return this.request("POST", "/api/v1/admin/secrets/scopes", {
|
|
263
|
+
orgId,
|
|
264
|
+
scope
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Rename a secret scope inside its backend. The route refuses a move between
|
|
269
|
+
* backends and a rename onto a scope that already exists.
|
|
270
|
+
*/
|
|
271
|
+
async renameScope(orgId, oldScope, newScope) {
|
|
272
|
+
return this.request("PUT", "/api/v1/admin/secrets/scopes/rename", {
|
|
273
|
+
orgId,
|
|
274
|
+
oldScope,
|
|
275
|
+
newScope
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
/** Delete a secret scope and every secret in it. */
|
|
279
|
+
async deleteScope(orgId, scope) {
|
|
280
|
+
return this.request("DELETE", `/api/v1/admin/secrets/scopes/${encodeURIComponent(orgId)}/${encodeURIComponent(scope)}`);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
257
283
|
* Create (or upsert) a deployment context. `allowLocalExecution` lets
|
|
258
284
|
* CLI-initiated / local runs resolve secrets through this context.
|
|
259
285
|
*/
|
|
@@ -1284,7 +1310,7 @@ var AuditLogger = class {
|
|
|
1284
1310
|
* engine's `shouldRecordSecretResolve` helper) since they're written
|
|
1285
1311
|
* once per JOB-step secret resolution and dwarf every other action's
|
|
1286
1312
|
* volume. Denied resolves and every other action (`setSecret`,
|
|
1287
|
-
* `deleteSecret`, `rotateKey`, `secret-outputs.reveal`) bypass the
|
|
1313
|
+
* `deleteSecret`, the scope writes, `rotateKey`, `secret-outputs.reveal`) bypass the
|
|
1288
1314
|
* sampler — they are transactional with the mutation and must always
|
|
1289
1315
|
* land.
|
|
1290
1316
|
*
|
|
@@ -1494,6 +1520,48 @@ async function warnIfContextUnbound(args) {
|
|
|
1494
1520
|
if (found && type?.success && found.bindings.length === 0) (args.warn ?? console.error)(unboundContextWarning(args.orgId, args.name, type.data));
|
|
1495
1521
|
}
|
|
1496
1522
|
//#endregion
|
|
1523
|
+
//#region src/cli/commands/shared/confirm.ts
|
|
1524
|
+
/**
|
|
1525
|
+
* Yes/no confirmation prompt for the `kici-admin` verbs that change or destroy
|
|
1526
|
+
* state unless the operator passes `--yes`.
|
|
1527
|
+
*/
|
|
1528
|
+
/** Message of the error raised when stdin ends before the operator answers. */
|
|
1529
|
+
const NO_CONFIRMATION_ANSWER = "no answer to the confirmation prompt: stdin closed before a line arrived. Pass --yes to run without the prompt.";
|
|
1530
|
+
/**
|
|
1531
|
+
* Write `prompt` and read one line of answer.
|
|
1532
|
+
*
|
|
1533
|
+
* Resolves true when the line is `y` or `yes` (any case, surrounding spaces
|
|
1534
|
+
* ignored) and false for any other line. Rejects with
|
|
1535
|
+
* {@link NO_CONFIRMATION_ANSWER} when stdin ends before a line arrives, as it
|
|
1536
|
+
* does for a script, a cron job or a `< /dev/null` redirect. Resolving false
|
|
1537
|
+
* there would let a verb run without `--yes` exit 0 having done nothing, and
|
|
1538
|
+
* the script that ran it would read that as success.
|
|
1539
|
+
*/
|
|
1540
|
+
function confirmPrompt(prompt, io = {
|
|
1541
|
+
input: process.stdin,
|
|
1542
|
+
output: process.stderr
|
|
1543
|
+
}) {
|
|
1544
|
+
const rl = createInterface({
|
|
1545
|
+
input: io.input,
|
|
1546
|
+
output: io.output
|
|
1547
|
+
});
|
|
1548
|
+
return new Promise((resolve, reject) => {
|
|
1549
|
+
let answered = false;
|
|
1550
|
+
const settle = (answer) => {
|
|
1551
|
+
if (answered) return;
|
|
1552
|
+
answered = true;
|
|
1553
|
+
rl.close();
|
|
1554
|
+
const normalized = answer.trim().toLowerCase();
|
|
1555
|
+
resolve(normalized === "y" || normalized === "yes");
|
|
1556
|
+
};
|
|
1557
|
+
rl.once("close", () => {
|
|
1558
|
+
if (!answered) reject(/* @__PURE__ */ new Error(NO_CONFIRMATION_ANSWER));
|
|
1559
|
+
});
|
|
1560
|
+
rl.once("line", settle);
|
|
1561
|
+
rl.question(prompt, settle);
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
//#endregion
|
|
1497
1565
|
//#region src/cli/commands/secret.ts
|
|
1498
1566
|
function resolveDirectDbUrl$10(explicit) {
|
|
1499
1567
|
return explicit ?? process.env.KICI_DATABASE_URL ?? null;
|
|
@@ -1658,7 +1726,7 @@ function registerSecretCommands(program, getClient) {
|
|
|
1658
1726
|
sec.command("delete <orgId> <scope> <key>").description("Delete a secret").option("--yes", "Skip confirmation prompt").action(async (orgId, scope, key, opts) => {
|
|
1659
1727
|
try {
|
|
1660
1728
|
if (!opts.yes) {
|
|
1661
|
-
if (!await
|
|
1729
|
+
if (!await confirmPrompt(`Are you sure you want to delete secret '${key}' from scope '${scope}'? [y/N] `)) {
|
|
1662
1730
|
console.log("Aborted.");
|
|
1663
1731
|
return;
|
|
1664
1732
|
}
|
|
@@ -1670,6 +1738,7 @@ function registerSecretCommands(program, getClient) {
|
|
|
1670
1738
|
process.exit(1);
|
|
1671
1739
|
}
|
|
1672
1740
|
});
|
|
1741
|
+
registerSecretScopeCommands(sec, getClient);
|
|
1673
1742
|
sec.command("fix-prefixed-scopes <orgId>").description("Repair PG-backend secret scopes stored with a stale pg: qualifier (direct-DB). Each affected scope is renamed to its bare path, re-encrypting every secret under the corrected AAD. Exits 2 when any scope needs manual repair.").option("--dry-run", "Print the plan and exit without writing").option("--database-url <url>", "Orchestrator DB URL (or KICI_DATABASE_URL)").action(async (orgId, opts) => {
|
|
1674
1743
|
const dbUrl = resolveDirectDbUrl$10(opts.databaseUrl);
|
|
1675
1744
|
if (!dbUrl) {
|
|
@@ -1720,17 +1789,48 @@ function registerSecretCommands(program, getClient) {
|
|
|
1720
1789
|
if (skipped > 0) process.exit(2);
|
|
1721
1790
|
});
|
|
1722
1791
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1792
|
+
/**
|
|
1793
|
+
* `secret scope create|rename|delete` — the operator path for the dashboard's
|
|
1794
|
+
* scope writes (`secrets.scope.*` in the dashboard-write policy). HTTP only,
|
|
1795
|
+
* like `secret scopes`: each verb calls the orchestrator admin API.
|
|
1796
|
+
*/
|
|
1797
|
+
function registerSecretScopeCommands(sec, getClient) {
|
|
1798
|
+
const scope = sec.command("scope").description("Create, rename or delete a secret scope");
|
|
1799
|
+
scope.command("create <orgId> <scope>").description("Create an empty secret scope. A <backend>: qualifier selects the backend; an unqualified scope targets the PG backend. An existing scope stays unchanged.").option("--json", "Emit JSON output").action(async (orgId, scopeName, opts) => {
|
|
1800
|
+
try {
|
|
1801
|
+
const result = await getClient().createScope(orgId, scopeName);
|
|
1802
|
+
if (opts.json) console.log(JSON.stringify(result));
|
|
1803
|
+
else console.log(`Secret scope '${scopeName}' created for org ${orgId}.`);
|
|
1804
|
+
} catch (err) {
|
|
1805
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
1806
|
+
process.exit(1);
|
|
1807
|
+
}
|
|
1728
1808
|
});
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1809
|
+
scope.command("rename <orgId> <oldScope> <newScope>").description("Rename a secret scope inside its backend. Refuses a move between backends and a rename onto a scope that already exists.").option("--json", "Emit JSON output").action(async (orgId, oldScope, newScope, opts) => {
|
|
1810
|
+
try {
|
|
1811
|
+
const result = await getClient().renameScope(orgId, oldScope, newScope);
|
|
1812
|
+
if (opts.json) console.log(JSON.stringify(result));
|
|
1813
|
+
else console.log(`Secret scope '${oldScope}' renamed to '${newScope}' for org ${orgId}.`);
|
|
1814
|
+
} catch (err) {
|
|
1815
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
1816
|
+
process.exit(1);
|
|
1817
|
+
}
|
|
1818
|
+
});
|
|
1819
|
+
scope.command("delete <orgId> <scope>").description("Delete a secret scope and every secret in it").option("--yes", "Skip confirmation prompt").option("--json", "Emit JSON output").action(async (orgId, scopeName, opts) => {
|
|
1820
|
+
try {
|
|
1821
|
+
if (!opts.yes) {
|
|
1822
|
+
if (!await confirmPrompt(`Are you sure you want to delete scope '${scopeName}' and every secret in it? [y/N] `)) {
|
|
1823
|
+
console.log("Aborted.");
|
|
1824
|
+
return;
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
const result = await getClient().deleteScope(orgId, scopeName);
|
|
1828
|
+
if (opts.json) console.log(JSON.stringify(result));
|
|
1829
|
+
else console.log(`Secret scope '${scopeName}' deleted for org ${orgId}.`);
|
|
1830
|
+
} catch (err) {
|
|
1831
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
1832
|
+
process.exit(1);
|
|
1833
|
+
}
|
|
1734
1834
|
});
|
|
1735
1835
|
}
|
|
1736
1836
|
//#endregion
|
|
@@ -1808,7 +1908,7 @@ function formatAuditTable(entries) {
|
|
|
1808
1908
|
].join("\n");
|
|
1809
1909
|
}
|
|
1810
1910
|
function registerAuditCommands(program, getClient) {
|
|
1811
|
-
program.command("audit").description("Query the secrets audit log").option("--context <name>", "Filter by context name").option("--routing-key <rk>", "Filter by routing key (required for cold-store scan)").option("--action <action>", "Filter by action type").option("--from <date>", "From date (ISO 8601)").option("--to <date>", "To date (ISO 8601)").option("--limit <n>", "Max entries to return", "100").option("--offset <n>", "Offset for pagination").option("--include-archived", "Include rows from cold storage
|
|
1911
|
+
program.command("audit").description("Query the secrets audit log").option("--context <name>", "Filter by context name").option("--routing-key <rk>", "Filter by routing key (required for cold-store scan)").option("--action <action>", "Filter by action type").option("--from <date>", "From date (ISO 8601)").option("--to <date>", "To date (ISO 8601)").option("--limit <n>", "Max entries to return", "100").option("--offset <n>", "Offset for pagination").option("--include-archived", "Include rows from cold storage", false).action(async (opts) => {
|
|
1812
1912
|
try {
|
|
1813
1913
|
const entries = await getClient().queryAudit({
|
|
1814
1914
|
contextName: opts.context,
|
|
@@ -13768,7 +13868,7 @@ function resolveDatabaseUrl$7(explicit) {
|
|
|
13768
13868
|
if (!url) throw new Error("Database URL required. Pass --database-url or set KICI_DATABASE_URL.");
|
|
13769
13869
|
return url;
|
|
13770
13870
|
}
|
|
13771
|
-
async function confirmInteractive$
|
|
13871
|
+
async function confirmInteractive$1(prompt, expected) {
|
|
13772
13872
|
if (!process.stdin.isTTY) return false;
|
|
13773
13873
|
process.stderr.write(prompt);
|
|
13774
13874
|
const rl = createInterface({
|
|
@@ -13896,7 +13996,7 @@ function registerDbCommands(program, getClient) {
|
|
|
13896
13996
|
const url = resolveDatabaseUrl$7(opts.databaseUrl);
|
|
13897
13997
|
const { dbName } = parseDatabaseUrl(url);
|
|
13898
13998
|
if (!opts.yes) {
|
|
13899
|
-
if (!await confirmInteractive$
|
|
13999
|
+
if (!await confirmInteractive$1(`About to DROP + RECREATE database "${dbName}". Type "${dbName}" to confirm: `, dbName)) {
|
|
13900
14000
|
console.error("Aborted.");
|
|
13901
14001
|
process.exit(1);
|
|
13902
14002
|
}
|
|
@@ -13948,7 +14048,7 @@ function registerDbCommands(program, getClient) {
|
|
|
13948
14048
|
const url = resolveDatabaseUrl$7(opts.databaseUrl);
|
|
13949
14049
|
const { dbName } = parseDatabaseUrl(url);
|
|
13950
14050
|
if (!opts.yes) {
|
|
13951
|
-
if (!await confirmInteractive$
|
|
14051
|
+
if (!await confirmInteractive$1(`About to RESTORE (--clean) into database "${dbName}", overwriting its contents. Type "${dbName}" to confirm: `, dbName)) {
|
|
13952
14052
|
console.error("Aborted.");
|
|
13953
14053
|
process.exit(1);
|
|
13954
14054
|
}
|
|
@@ -16007,19 +16107,9 @@ function registerSourceCommands(program, getClient) {
|
|
|
16007
16107
|
});
|
|
16008
16108
|
src.command("remove <routingKey>").description("Remove a source (GitHub, or generic/local with --generic / --local)").option("--yes", "Skip confirmation").option("--generic", "Remove a generic source (routingKey is treated as source ID)").option("--local", "Remove a local (file://) source (routingKey is treated as source ID)").option("--hard", "Permanently delete a generic/local source (requires --generic or --local)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").action(async (routingKey, opts) => {
|
|
16009
16109
|
try {
|
|
16010
|
-
if (!opts.yes) {
|
|
16011
|
-
|
|
16012
|
-
|
|
16013
|
-
output: process.stdout
|
|
16014
|
-
});
|
|
16015
|
-
const answer = await new Promise((resolve) => {
|
|
16016
|
-
rl.question(`Remove source "${routingKey}"? (y/N) `, resolve);
|
|
16017
|
-
});
|
|
16018
|
-
rl.close();
|
|
16019
|
-
if (answer.toLowerCase() !== "y") {
|
|
16020
|
-
console.log("Cancelled.");
|
|
16021
|
-
return;
|
|
16022
|
-
}
|
|
16110
|
+
if (!opts.yes && !await confirmPrompt(`Remove source "${routingKey}"? (y/N) `)) {
|
|
16111
|
+
console.log("Cancelled.");
|
|
16112
|
+
return;
|
|
16023
16113
|
}
|
|
16024
16114
|
const dbUrl = resolveDirectDbUrl$9(opts.databaseUrl);
|
|
16025
16115
|
if (dbUrl) {
|
|
@@ -18292,16 +18382,6 @@ function readAttestations(db) {
|
|
|
18292
18382
|
}
|
|
18293
18383
|
//#endregion
|
|
18294
18384
|
//#region src/cli/commands/attestations.ts
|
|
18295
|
-
/**
|
|
18296
|
-
* `kici-admin attestations` — orchestrator-DB-direct provenance maintenance.
|
|
18297
|
-
*
|
|
18298
|
-
* attestations reverify [--all] Recompute stored verdicts (verify-at-ingest
|
|
18299
|
-
* backfill). Default scope: pending /
|
|
18300
|
-
* unverifiable rows; `--all` re-evaluates
|
|
18301
|
-
* every row. Direct DB + object storage.
|
|
18302
|
-
*
|
|
18303
|
-
* Classified `kici-admin` (orchestrator DB plane) per .claude/rules/platform-admin.md.
|
|
18304
|
-
*/
|
|
18305
18385
|
init_client();
|
|
18306
18386
|
const logger$15 = createLogger({ prefix: "kici-admin-attestations" });
|
|
18307
18387
|
function resolveDatabaseUrl$5(explicit) {
|
|
@@ -18330,18 +18410,6 @@ function buildStorage(config) {
|
|
|
18330
18410
|
signingSecret: "kici-admin-reverify"
|
|
18331
18411
|
});
|
|
18332
18412
|
}
|
|
18333
|
-
async function confirmInteractive$3(prompt) {
|
|
18334
|
-
const rl = createInterface({
|
|
18335
|
-
input: process.stdin,
|
|
18336
|
-
output: process.stderr
|
|
18337
|
-
});
|
|
18338
|
-
try {
|
|
18339
|
-
const answer = await new Promise((resolve) => rl.question(prompt, resolve));
|
|
18340
|
-
return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
|
|
18341
|
-
} finally {
|
|
18342
|
-
rl.close();
|
|
18343
|
-
}
|
|
18344
|
-
}
|
|
18345
18413
|
/** Render attestation rows as a compact human table (stderr note when empty). */
|
|
18346
18414
|
function printAttestationTable(rows) {
|
|
18347
18415
|
if (rows.length === 0) {
|
|
@@ -18371,7 +18439,7 @@ function registerAttestationsCommands(program, getClient) {
|
|
|
18371
18439
|
const config = loadConfig();
|
|
18372
18440
|
const url = resolveDatabaseUrl$5(opts.databaseUrl ?? (config.databaseUrl || void 0));
|
|
18373
18441
|
if (opts.all && !opts.yes) {
|
|
18374
|
-
if (!await
|
|
18442
|
+
if (!await confirmPrompt("Re-evaluate the verdict of EVERY attestation (including already-verified)? [y/N] ")) {
|
|
18375
18443
|
console.error("Aborted.");
|
|
18376
18444
|
process.exit(1);
|
|
18377
18445
|
}
|
|
@@ -18725,7 +18793,7 @@ var DbSigner = class DbSigner {
|
|
|
18725
18793
|
* halves ONLY — never private material.
|
|
18726
18794
|
*
|
|
18727
18795
|
* The PRIVATE key is non-exportable by design: there is no export of private
|
|
18728
|
-
* material and no import. Loss recovery is a routine rotation
|
|
18796
|
+
* material and no import. Loss recovery is a routine rotation.
|
|
18729
18797
|
*/
|
|
18730
18798
|
init_client();
|
|
18731
18799
|
const logger$14 = createLogger({ prefix: "kici-admin-signing-key" });
|
|
@@ -18766,18 +18834,6 @@ function resolveSecretKey$1() {
|
|
|
18766
18834
|
if (!config.secretKey) throw new Error("KICI_SECRET_KEY is required to generate a db-custody signing key (it wraps the private JWK).");
|
|
18767
18835
|
return config.secretKey;
|
|
18768
18836
|
}
|
|
18769
|
-
async function confirmInteractive$2(prompt) {
|
|
18770
|
-
const rl = createInterface({
|
|
18771
|
-
input: process.stdin,
|
|
18772
|
-
output: process.stderr
|
|
18773
|
-
});
|
|
18774
|
-
try {
|
|
18775
|
-
const a = (await new Promise((resolve) => rl.question(prompt, resolve))).trim().toLowerCase();
|
|
18776
|
-
return a === "y" || a === "yes";
|
|
18777
|
-
} finally {
|
|
18778
|
-
rl.close();
|
|
18779
|
-
}
|
|
18780
|
-
}
|
|
18781
18837
|
async function withRepo$1(databaseUrl, fn) {
|
|
18782
18838
|
const pool = createPool(resolveDatabaseUrl$4(databaseUrl));
|
|
18783
18839
|
const db = createDb$1(pool);
|
|
@@ -18869,7 +18925,7 @@ function registerSigningKeyCommands(program, tryGetClient) {
|
|
|
18869
18925
|
process.stderr.write(`Generated active signing key ${outcome.kid}.\n`);
|
|
18870
18926
|
}
|
|
18871
18927
|
}, {
|
|
18872
|
-
confirm:
|
|
18928
|
+
confirm: confirmPrompt,
|
|
18873
18929
|
yes: opts.yes,
|
|
18874
18930
|
dryRun: opts.dryRun
|
|
18875
18931
|
});
|
|
@@ -18893,7 +18949,7 @@ function registerSigningKeyCommands(program, tryGetClient) {
|
|
|
18893
18949
|
process.stderr.write(`Rotated: new active signing key ${kid}.\n`);
|
|
18894
18950
|
}
|
|
18895
18951
|
}, {
|
|
18896
|
-
confirm:
|
|
18952
|
+
confirm: confirmPrompt,
|
|
18897
18953
|
yes: opts.yes,
|
|
18898
18954
|
dryRun: opts.dryRun
|
|
18899
18955
|
});
|
|
@@ -18915,7 +18971,7 @@ function registerSigningKeyCommands(program, tryGetClient) {
|
|
|
18915
18971
|
signingKey.command("revoke <kid>").description("Distrust a compromised key (REMOVED from the JWKS; everything it signed is distrusted)").requiredOption("--reason <reason>", "Why the key is being revoked (audit)").option("--database-url <url>", "Orchestrator DB URL (else KICI_DATABASE_URL)").option("--yes", "Skip the confirmation prompt").action(async (kid, opts) => {
|
|
18916
18972
|
try {
|
|
18917
18973
|
if (!opts.yes) {
|
|
18918
|
-
if (!await
|
|
18974
|
+
if (!await confirmPrompt(`Revoke signing key ${kid}? Everything it ever signed becomes UNVERIFIABLE. [y/N] `)) {
|
|
18919
18975
|
console.error("Aborted.");
|
|
18920
18976
|
process.exit(1);
|
|
18921
18977
|
}
|
|
@@ -19287,24 +19343,6 @@ async function generateDashboardEncryptionKey(secretKey) {
|
|
|
19287
19343
|
}
|
|
19288
19344
|
//#endregion
|
|
19289
19345
|
//#region src/cli/commands/dashboard-encryption-key.ts
|
|
19290
|
-
/**
|
|
19291
|
-
* `kici-admin dashboard-encryption-key` — the orchestrator's X25519
|
|
19292
|
-
* dashboard-encryption key: the trust root a browser seals a secret / variable
|
|
19293
|
-
* value to under the `encrypted` dashboard-write posture, so the hosted control
|
|
19294
|
-
* plane relays only opaque ciphertext.
|
|
19295
|
-
*
|
|
19296
|
-
* dashboard-encryption-key show Print the active kid, its public JWK, where
|
|
19297
|
-
* the JWKS is published, and the Verified-tier
|
|
19298
|
-
* URL (when that tier is opted into).
|
|
19299
|
-
* dashboard-encryption-key list List every key on record (kid / status / created_at).
|
|
19300
|
-
* dashboard-encryption-key rotate Mint a new active key; the prior active key
|
|
19301
|
-
* is retired from the published JWKS, but its
|
|
19302
|
-
* private half stays on record so envelopes
|
|
19303
|
-
* already sealed to it still decrypt.
|
|
19304
|
-
*
|
|
19305
|
-
* The PRIVATE half is master-key wrapped (`KICI_SECRET_KEY`) in the orchestrator
|
|
19306
|
-
* DB and is never exportable — recovery from a lost key is a routine rotation.
|
|
19307
|
-
*/
|
|
19308
19346
|
init_client();
|
|
19309
19347
|
const logger$9 = createLogger({ prefix: "kici-admin-dashboard-encryption-key" });
|
|
19310
19348
|
function resolveDatabaseUrl$3(explicit) {
|
|
@@ -19317,18 +19355,6 @@ function resolveSecretKey() {
|
|
|
19317
19355
|
if (!config.secretKey) throw new Error("KICI_SECRET_KEY is required for the dashboard encryption key (it wraps the private key).");
|
|
19318
19356
|
return config.secretKey;
|
|
19319
19357
|
}
|
|
19320
|
-
async function confirmInteractive$1(prompt) {
|
|
19321
|
-
const rl = createInterface({
|
|
19322
|
-
input: process.stdin,
|
|
19323
|
-
output: process.stderr
|
|
19324
|
-
});
|
|
19325
|
-
try {
|
|
19326
|
-
const a = (await new Promise((resolve) => rl.question(prompt, resolve))).trim().toLowerCase();
|
|
19327
|
-
return a === "y" || a === "yes";
|
|
19328
|
-
} finally {
|
|
19329
|
-
rl.close();
|
|
19330
|
-
}
|
|
19331
|
-
}
|
|
19332
19358
|
async function withRepo(databaseUrl, fn) {
|
|
19333
19359
|
const pool = createPool(resolveDatabaseUrl$3(databaseUrl));
|
|
19334
19360
|
const db = createDb$1(pool);
|
|
@@ -19435,7 +19461,7 @@ function registerDashboardEncryptionKeyCommands(program) {
|
|
|
19435
19461
|
process.stderr.write(`Rotated: new active dashboard-encryption key ${kid}.\n`);
|
|
19436
19462
|
}
|
|
19437
19463
|
}, {
|
|
19438
|
-
confirm:
|
|
19464
|
+
confirm: confirmPrompt,
|
|
19439
19465
|
yes: opts.yes,
|
|
19440
19466
|
dryRun: opts.dryRun
|
|
19441
19467
|
});
|
|
@@ -19705,7 +19731,7 @@ function registerBackendCommands(program, getClient) {
|
|
|
19705
19731
|
try {
|
|
19706
19732
|
scopeInfo = ` has ${(await getClient().getBackend(name)).scopeCount ?? 0} discovered scopes -- they will become unavailable.`;
|
|
19707
19733
|
} catch {}
|
|
19708
|
-
if (!await
|
|
19734
|
+
if (!await confirmPrompt(`Backend "${name}"${scopeInfo} Continue? [y/N] `)) {
|
|
19709
19735
|
console.log("Aborted.");
|
|
19710
19736
|
return;
|
|
19711
19737
|
}
|
|
@@ -19892,21 +19918,6 @@ function printBackendSummary(b) {
|
|
|
19892
19918
|
console.log(` Sync interval: ${Math.round(Number(b.syncIntervalMs) / 6e4)}m`);
|
|
19893
19919
|
console.log(` Enabled: ${b.enabled}`);
|
|
19894
19920
|
}
|
|
19895
|
-
/**
|
|
19896
|
-
* Simple confirmation prompt.
|
|
19897
|
-
*/
|
|
19898
|
-
async function confirm$3(message) {
|
|
19899
|
-
const rl = createInterface({
|
|
19900
|
-
input: process.stdin,
|
|
19901
|
-
output: process.stderr
|
|
19902
|
-
});
|
|
19903
|
-
return new Promise((resolve) => {
|
|
19904
|
-
rl.question(message, (answer) => {
|
|
19905
|
-
rl.close();
|
|
19906
|
-
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
19907
|
-
});
|
|
19908
|
-
});
|
|
19909
|
-
}
|
|
19910
19921
|
//#endregion
|
|
19911
19922
|
//#region src/cli/commands/diagnose.ts
|
|
19912
19923
|
/** ANSI color codes for terminal output. */
|
|
@@ -20491,18 +20502,12 @@ async function resolveUpgradeTarget(args) {
|
|
|
20491
20502
|
platform
|
|
20492
20503
|
};
|
|
20493
20504
|
}
|
|
20494
|
-
/** Prompt the user for confirmation
|
|
20495
|
-
|
|
20496
|
-
|
|
20505
|
+
/** Prompt the user for confirmation on stdout, beside the upgrade plan it follows. */
|
|
20506
|
+
function confirm$1(message) {
|
|
20507
|
+
return confirmPrompt(`${message} [y/N] `, {
|
|
20497
20508
|
input: process.stdin,
|
|
20498
20509
|
output: process.stdout
|
|
20499
20510
|
});
|
|
20500
|
-
return new Promise((resolve) => {
|
|
20501
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
20502
|
-
rl.close();
|
|
20503
|
-
resolve(answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes");
|
|
20504
|
-
});
|
|
20505
|
-
});
|
|
20506
20511
|
}
|
|
20507
20512
|
/** Download a file from a URL to a local path. */
|
|
20508
20513
|
async function downloadArchive(url, destPath) {
|
|
@@ -20924,7 +20929,7 @@ async function performVersionedUpgrade(component, opts, hooks = {}) {
|
|
|
20924
20929
|
console.log(` Install path: ${versionedDirPath}`);
|
|
20925
20930
|
console.log(" The service will be stopped during upgrade.");
|
|
20926
20931
|
console.log("");
|
|
20927
|
-
if (!await confirm$
|
|
20932
|
+
if (!await confirm$1("Proceed with upgrade?")) {
|
|
20928
20933
|
console.log("Upgrade cancelled.");
|
|
20929
20934
|
return;
|
|
20930
20935
|
}
|
|
@@ -21037,7 +21042,7 @@ async function restartOnlyUpgrade(component, config, resolvedInstance, manager,
|
|
|
21037
21042
|
console.log(`This will restart "${config.name}" onto the npm-installed version ${verdict.version}.`);
|
|
21038
21043
|
console.log(" The service will be stopped briefly during the restart.");
|
|
21039
21044
|
console.log("");
|
|
21040
|
-
if (!await confirm$
|
|
21045
|
+
if (!await confirm$1("Proceed with upgrade?")) {
|
|
21041
21046
|
console.log("Upgrade cancelled.");
|
|
21042
21047
|
return;
|
|
21043
21048
|
}
|
|
@@ -21063,7 +21068,7 @@ async function performSelfDrivingInstall(component, config, resolvedInstance, ma
|
|
|
21063
21068
|
console.log(`This will install ${target.owningPackage}@${version} using ${target.npmPath}`);
|
|
21064
21069
|
console.log(` (node runtime: ${target.nodeExecPath}), then restart "${config.name}".`);
|
|
21065
21070
|
console.log("");
|
|
21066
|
-
if (!await confirm$
|
|
21071
|
+
if (!await confirm$1("Proceed with upgrade?")) {
|
|
21067
21072
|
console.log("Upgrade cancelled.");
|
|
21068
21073
|
return;
|
|
21069
21074
|
}
|
|
@@ -21120,7 +21125,7 @@ async function handlePick(component, platform, installBase, config, manager, res
|
|
|
21120
21125
|
console.log(` Install path: ${path.join(installBase, `${component}-${target}`)}`);
|
|
21121
21126
|
console.log(" The service will be stopped during the switch.");
|
|
21122
21127
|
console.log("");
|
|
21123
|
-
if (!await confirm$
|
|
21128
|
+
if (!await confirm$1("Proceed with switch?")) {
|
|
21124
21129
|
console.log("Pick cancelled.");
|
|
21125
21130
|
return;
|
|
21126
21131
|
}
|
|
@@ -21168,7 +21173,7 @@ async function assertSchemaAllowsSwitch(args) {
|
|
|
21168
21173
|
console.log("");
|
|
21169
21174
|
console.log(" !! The running service could not be reached, so the schema was not checked.");
|
|
21170
21175
|
console.log("");
|
|
21171
|
-
return yes ? true : confirm$
|
|
21176
|
+
return yes ? true : confirm$1("Proceed with the switch anyway?");
|
|
21172
21177
|
}
|
|
21173
21178
|
const recordedHead = resolvedInstance.manifest.migrationHeads?.[targetVersion];
|
|
21174
21179
|
const verdict = schemaGuardVerdict({
|
|
@@ -21181,7 +21186,7 @@ async function assertSchemaAllowsSwitch(args) {
|
|
|
21181
21186
|
console.log("");
|
|
21182
21187
|
console.log(verdict.message);
|
|
21183
21188
|
console.log("");
|
|
21184
|
-
return yes ? true : confirm$
|
|
21189
|
+
return yes ? true : confirm$1("Proceed with the switch anyway?");
|
|
21185
21190
|
}
|
|
21186
21191
|
if (!migrateDown) {
|
|
21187
21192
|
console.error("");
|
|
@@ -21276,7 +21281,7 @@ async function handleRollback(component, platform, installBase, config, manager,
|
|
|
21276
21281
|
console.log(` Current version: ${currentVersion}`);
|
|
21277
21282
|
console.log(` Rollback to: ${previousVersion}`);
|
|
21278
21283
|
console.log("");
|
|
21279
|
-
if (!await confirm$
|
|
21284
|
+
if (!await confirm$1("Proceed with rollback?")) {
|
|
21280
21285
|
console.log("Rollback cancelled.");
|
|
21281
21286
|
return;
|
|
21282
21287
|
}
|
|
@@ -22802,7 +22807,7 @@ init_manifest();
|
|
|
22802
22807
|
const ALL_PLATFORMS = AgentPlatform.options;
|
|
22803
22808
|
/** The orchestrator's own version (single-version invariant) = the packaged agent version. */
|
|
22804
22809
|
function resolveKiciVersion() {
|
|
22805
|
-
return "0.
|
|
22810
|
+
return "0.11.0";
|
|
22806
22811
|
}
|
|
22807
22812
|
/** Parse the --platform value: default set | single | CSV | `all`. */
|
|
22808
22813
|
function parsePlatforms(raw) {
|
|
@@ -26832,6 +26837,72 @@ function registerContextCommands(program, getClient) {
|
|
|
26832
26837
|
process.exit(1);
|
|
26833
26838
|
}
|
|
26834
26839
|
});
|
|
26840
|
+
registerSourceOverrideCommands(env, getClient);
|
|
26841
|
+
}
|
|
26842
|
+
function printSourceOverrides(rows) {
|
|
26843
|
+
if (rows.length === 0) {
|
|
26844
|
+
console.log("No source overrides found.");
|
|
26845
|
+
return;
|
|
26846
|
+
}
|
|
26847
|
+
const header = [
|
|
26848
|
+
"ROUTING KEY",
|
|
26849
|
+
"KEY",
|
|
26850
|
+
"VALUE"
|
|
26851
|
+
];
|
|
26852
|
+
const data = rows.map((r) => [
|
|
26853
|
+
r.routing_key,
|
|
26854
|
+
r.key,
|
|
26855
|
+
r.value
|
|
26856
|
+
]);
|
|
26857
|
+
const widths = header.map((h, i) => Math.max(h.length, ...data.map((row) => row[i].length)));
|
|
26858
|
+
const pad = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
|
|
26859
|
+
console.log(header.map((h, i) => pad(h, widths[i])).join(" "));
|
|
26860
|
+
for (const row of data) console.log(row.map((c, i) => pad(c, widths[i])).join(" "));
|
|
26861
|
+
}
|
|
26862
|
+
/** Admin API path of one source override, every segment URI-encoded. */
|
|
26863
|
+
function sourceOverridePath(opts) {
|
|
26864
|
+
const params = new URLSearchParams({ orgId: opts.org });
|
|
26865
|
+
return `/api/v1/admin/contexts/${encodeURIComponent(opts.env)}/source-overrides/${encodeURIComponent(opts.routingKey)}/${encodeURIComponent(opts.key)}?${params}`;
|
|
26866
|
+
}
|
|
26867
|
+
/**
|
|
26868
|
+
* `context source-override list|set|delete` — the operator path for the
|
|
26869
|
+
* dashboard's per-source override writes (`contexts.source_overrides.*` in the
|
|
26870
|
+
* dashboard-write policy). HTTP only: each verb calls the orchestrator admin API.
|
|
26871
|
+
*/
|
|
26872
|
+
function registerSourceOverrideCommands(context, getClient) {
|
|
26873
|
+
const so = context.command("source-override").description("Per-source variable overrides in a context (HTTP only)");
|
|
26874
|
+
so.command("list").description("List the source overrides in a context, for every source unless --routing-key").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Context name").option("--routing-key <key>", "Only list the overrides for this source routing key").option("--json", "Emit JSON output").action(async (opts) => {
|
|
26875
|
+
try {
|
|
26876
|
+
const params = new URLSearchParams({ orgId: opts.org });
|
|
26877
|
+
if (opts.routingKey) params.set("routingKey", opts.routingKey);
|
|
26878
|
+
const result = await getClient().get(`/api/v1/admin/contexts/${encodeURIComponent(opts.env)}/source-overrides?${params}`);
|
|
26879
|
+
if (opts.json) console.log(JSON.stringify(result));
|
|
26880
|
+
else printSourceOverrides(result.overrides);
|
|
26881
|
+
} catch (err) {
|
|
26882
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
26883
|
+
process.exit(1);
|
|
26884
|
+
}
|
|
26885
|
+
});
|
|
26886
|
+
so.command("set").description("Set the value one source sees for a context variable key. A locked context variable keeps its own value.").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Context name").requiredOption("--routing-key <key>", "Routing key of the source the override applies to").requiredOption("--key <key>", "Variable key").requiredOption("--value <value>", "Override value").option("--json", "Emit JSON output").action(async (opts) => {
|
|
26887
|
+
try {
|
|
26888
|
+
const result = await getClient().put(sourceOverridePath(opts), { value: opts.value });
|
|
26889
|
+
if (opts.json) console.log(JSON.stringify(result));
|
|
26890
|
+
else console.log(`context source-override set: key=${opts.key} routing-key=${opts.routingKey} (env=${opts.env})`);
|
|
26891
|
+
} catch (err) {
|
|
26892
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
26893
|
+
process.exit(1);
|
|
26894
|
+
}
|
|
26895
|
+
});
|
|
26896
|
+
so.command("delete").description("Delete one source override, so the source resolves the key from the context variables").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Context name").requiredOption("--routing-key <key>", "Routing key of the source the override applies to").requiredOption("--key <key>", "Variable key").option("--json", "Emit JSON output").action(async (opts) => {
|
|
26897
|
+
try {
|
|
26898
|
+
const result = await getClient().delete(sourceOverridePath(opts));
|
|
26899
|
+
if (opts.json) console.log(JSON.stringify(result));
|
|
26900
|
+
else console.log(`context source-override delete: key=${opts.key} routing-key=${opts.routingKey} (env=${opts.env})`);
|
|
26901
|
+
} catch (err) {
|
|
26902
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
26903
|
+
process.exit(1);
|
|
26904
|
+
}
|
|
26905
|
+
});
|
|
26835
26906
|
}
|
|
26836
26907
|
//#endregion
|
|
26837
26908
|
//#region src/cli/commands/variable.ts
|
|
@@ -26886,7 +26957,7 @@ function registerVariableCommands(program, getClient) {
|
|
|
26886
26957
|
vr.command("delete <orgId> <context> <key>").description("Delete a context variable").option("--yes", "Skip confirmation prompt").action(async (orgId, context, key, opts) => {
|
|
26887
26958
|
try {
|
|
26888
26959
|
if (!opts.yes) {
|
|
26889
|
-
if (!await
|
|
26960
|
+
if (!await confirmPrompt(`Are you sure you want to delete variable '${key}' from context '${context}'? [y/N] `)) {
|
|
26890
26961
|
console.log("Aborted.");
|
|
26891
26962
|
return;
|
|
26892
26963
|
}
|
|
@@ -26899,19 +26970,6 @@ function registerVariableCommands(program, getClient) {
|
|
|
26899
26970
|
}
|
|
26900
26971
|
});
|
|
26901
26972
|
}
|
|
26902
|
-
async function confirm$1(message) {
|
|
26903
|
-
const { createInterface } = await import("node:readline");
|
|
26904
|
-
const rl = createInterface({
|
|
26905
|
-
input: process.stdin,
|
|
26906
|
-
output: process.stderr
|
|
26907
|
-
});
|
|
26908
|
-
return new Promise((resolve) => {
|
|
26909
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
26910
|
-
rl.close();
|
|
26911
|
-
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
26912
|
-
});
|
|
26913
|
-
});
|
|
26914
|
-
}
|
|
26915
26973
|
//#endregion
|
|
26916
26974
|
//#region src/cli/commands/queue.ts
|
|
26917
26975
|
function resolveDirectDbUrl$3(explicit) {
|
|
@@ -27214,7 +27272,7 @@ function printRegistrationShow(res) {
|
|
|
27214
27272
|
console.log(`updated_at: ${r.updated_at}`);
|
|
27215
27273
|
}
|
|
27216
27274
|
function registerRegistrationCommands(program, getClient) {
|
|
27217
|
-
const reg = program.command("registration").description("Registered workflow
|
|
27275
|
+
const reg = program.command("registration").description("Registered workflow instances (workflow_registrations table)");
|
|
27218
27276
|
reg.command("list").description("List workflow_registrations rows (also returns registry_version)").option("--org <id>", "Filter by customer_id").option("--routing-key <k>", "Filter by routing_key").option("--repo <ident>", "Filter by repo_identifier").option("--trigger-type <type>", "Filter by trigger type (in trigger_types[])").option("--limit <n>", "Max rows (default 100, max 1000)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
27219
27277
|
try {
|
|
27220
27278
|
const limit = parseIntOption(opts.limit, "--limit");
|
|
@@ -27257,6 +27315,42 @@ function registerRegistrationCommands(program, getClient) {
|
|
|
27257
27315
|
process.exit(1);
|
|
27258
27316
|
}
|
|
27259
27317
|
});
|
|
27318
|
+
registerRegistrationWriteCommands(reg, getClient);
|
|
27319
|
+
}
|
|
27320
|
+
/**
|
|
27321
|
+
* `registration disable|enable|delete` — the operator path for the dashboard's
|
|
27322
|
+
* `registration.disable` / `registration.delete` writes. `enable` is the same
|
|
27323
|
+
* admin route as `disable`, with the flag cleared.
|
|
27324
|
+
*/
|
|
27325
|
+
function registerRegistrationWriteCommands(reg, getClient) {
|
|
27326
|
+
const setDisabled = async (id, disabled, json) => {
|
|
27327
|
+
try {
|
|
27328
|
+
const result = await getClient().patch(`/api/v1/admin/registrations/${encodeURIComponent(id)}/disable`, { disabled });
|
|
27329
|
+
if (json) console.log(JSON.stringify(result));
|
|
27330
|
+
else console.log(`registration ${disabled ? "disable" : "enable"}: id=${id} disabled=${result.disabled} registry_version=${result.registryVersion}`);
|
|
27331
|
+
} catch (err) {
|
|
27332
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
27333
|
+
process.exit(1);
|
|
27334
|
+
}
|
|
27335
|
+
};
|
|
27336
|
+
reg.command("disable <id>").description("Disable a workflow registration: it stays registered, but its triggers stop dispatching").option("--json", "Emit JSON output").action(async (id, opts) => setDisabled(id, true, opts.json));
|
|
27337
|
+
reg.command("enable <id>").description("Re-enable a disabled workflow registration").option("--json", "Emit JSON output").action(async (id, opts) => setDisabled(id, false, opts.json));
|
|
27338
|
+
reg.command("delete <id>").description("Delete a workflow registration by id").option("--yes", "Skip confirmation prompt").option("--json", "Emit JSON output").action(async (id, opts) => {
|
|
27339
|
+
try {
|
|
27340
|
+
if (!opts.yes) {
|
|
27341
|
+
if (!await confirmPrompt(`Are you sure you want to delete registration '${id}'? [y/N] `)) {
|
|
27342
|
+
console.log("Aborted.");
|
|
27343
|
+
return;
|
|
27344
|
+
}
|
|
27345
|
+
}
|
|
27346
|
+
const result = await getClient().delete(`/api/v1/admin/registrations/${encodeURIComponent(id)}`);
|
|
27347
|
+
if (opts.json) console.log(JSON.stringify(result));
|
|
27348
|
+
else console.log(`registration delete: id=${id} deleted=${result.deleted} registry_version=${result.registryVersion}`);
|
|
27349
|
+
} catch (err) {
|
|
27350
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
27351
|
+
process.exit(1);
|
|
27352
|
+
}
|
|
27353
|
+
});
|
|
27260
27354
|
}
|
|
27261
27355
|
//#endregion
|
|
27262
27356
|
//#region src/cli/commands/event.ts
|
|
@@ -28770,7 +28864,7 @@ var init_orchestrator_cold_store = __esmMin((() => {
|
|
|
28770
28864
|
//#endregion
|
|
28771
28865
|
//#region src/cli/commands/cold-store-impl.ts
|
|
28772
28866
|
/**
|
|
28773
|
-
*
|
|
28867
|
+
* Implementations for `kici-admin cold-store` subcommands.
|
|
28774
28868
|
*
|
|
28775
28869
|
* Mirrors the Platform-side implementation in
|
|
28776
28870
|
* `packages/platform/src/admin/cold-store-commands.ts` — same shape,
|
|
@@ -28785,9 +28879,8 @@ var init_orchestrator_cold_store = __esmMin((() => {
|
|
|
28785
28879
|
* - prints results to stdout (JSON Lines for list-chunks, JSONL for
|
|
28786
28880
|
* peek-chunk, free-form for the others)
|
|
28787
28881
|
*
|
|
28788
|
-
*
|
|
28789
|
-
*
|
|
28790
|
-
* same shape the Platform admin CLI uses for `audit_log`.
|
|
28882
|
+
* No per-invocation breadcrumb row is written: the Platform admin CLI's
|
|
28883
|
+
* `audit_log` breadcrumb has no `access_log` counterpart here.
|
|
28791
28884
|
*/
|
|
28792
28885
|
var cold_store_impl_exports = /* @__PURE__ */ __exportAll({
|
|
28793
28886
|
archiveNow: () => archiveNow,
|
|
@@ -29050,7 +29143,7 @@ async function replayChunk(opts) {
|
|
|
29050
29143
|
}
|
|
29051
29144
|
}
|
|
29052
29145
|
/**
|
|
29053
|
-
*
|
|
29146
|
+
* Promote a chunk's rows back into the orchestrator PG.
|
|
29054
29147
|
* Mirrors the Platform-side `replayIntoPg`. Adapter must implement
|
|
29055
29148
|
* `replayInsert` — currently only `execution_runs`.
|
|
29056
29149
|
*/
|
|
@@ -29182,7 +29275,7 @@ async function reconcile(opts) {
|
|
|
29182
29275
|
}
|
|
29183
29276
|
}
|
|
29184
29277
|
/**
|
|
29185
|
-
*
|
|
29278
|
+
* List chunks past their cold-retention horizon. Read-only;
|
|
29186
29279
|
* no S3 or PG mutation. Emits one JSON line per row so the output is
|
|
29187
29280
|
* easy to pipe through `jq` / `column -t` / etc.
|
|
29188
29281
|
*/
|
|
@@ -29206,7 +29299,7 @@ async function listPurgeable(opts) {
|
|
|
29206
29299
|
}
|
|
29207
29300
|
}
|
|
29208
29301
|
/**
|
|
29209
|
-
*
|
|
29302
|
+
* Delete S3 objects + clean up PG bookkeeping for chunks
|
|
29210
29303
|
* past their cold-retention horizon. Defaults to dry-run; pass
|
|
29211
29304
|
* `--apply` to actually delete.
|
|
29212
29305
|
*/
|
|
@@ -29358,7 +29451,7 @@ function registerColdStoreCommands(program, _getClient) {
|
|
|
29358
29451
|
process.exit(2);
|
|
29359
29452
|
}
|
|
29360
29453
|
});
|
|
29361
|
-
coldStore.command("replay-into-pg <chunkId>").description("
|
|
29454
|
+
coldStore.command("replay-into-pg <chunkId>").description("Promote every row in a chunk back into orchestrator PG (clear archived_at, write a replay audit row)").option("--database-url <url>", "Orchestrator Postgres URL (else KICI_DATABASE_URL)").requiredOption("--table <table>", "Adapter table name (currently: execution_runs)").requiredOption("--tenant <rk>", "Routing key for the chunk").requiredOption("--partition-date <YYYY-MM-DD>", "Partition date for the chunk").action(async (chunkId, opts) => {
|
|
29362
29455
|
try {
|
|
29363
29456
|
const databaseUrl = resolveDatabaseUrl(opts);
|
|
29364
29457
|
const { replayIntoPg } = await Promise.resolve().then(() => (init_cold_store_impl(), cold_store_impl_exports));
|
|
@@ -29389,7 +29482,7 @@ function registerColdStoreCommands(program, _getClient) {
|
|
|
29389
29482
|
process.exit(2);
|
|
29390
29483
|
}
|
|
29391
29484
|
});
|
|
29392
|
-
coldStore.command("list-purgeable").description("
|
|
29485
|
+
coldStore.command("list-purgeable").description("List chunks past their cold-retention horizon (read-only)").option("--database-url <url>", "Orchestrator Postgres URL (else KICI_DATABASE_URL)").option("--table <table>", "Filter to a single adapter table (else all)").option("--bucket <bucket>", "Filter to a single cold-bucket (30d / 180d / 1y / 2y)").option("--limit <n>", "Max candidates to inspect", "1000").action(async (opts) => {
|
|
29393
29486
|
try {
|
|
29394
29487
|
const databaseUrl = resolveDatabaseUrl(opts);
|
|
29395
29488
|
const { listPurgeable } = await Promise.resolve().then(() => (init_cold_store_impl(), cold_store_impl_exports));
|
|
@@ -29404,7 +29497,7 @@ function registerColdStoreCommands(program, _getClient) {
|
|
|
29404
29497
|
process.exit(2);
|
|
29405
29498
|
}
|
|
29406
29499
|
});
|
|
29407
|
-
coldStore.command("purge-now").description("
|
|
29500
|
+
coldStore.command("purge-now").description("Purge expired chunks from S3 + PG bookkeeping. DRY-RUN by default — pass --apply to actually delete.").option("--database-url <url>", "Orchestrator Postgres URL (else KICI_DATABASE_URL)").option("--table <table>", "Filter to a single adapter table (else all)").option("--bucket <bucket>", "Filter to a single cold-bucket (30d / 180d / 1y / 2y)").option("--limit <n>", "Max candidates to process", "1000").option("--apply", "Actually delete (default is dry-run)").action(async (opts) => {
|
|
29408
29501
|
try {
|
|
29409
29502
|
const databaseUrl = resolveDatabaseUrl(opts);
|
|
29410
29503
|
const { purgeNow } = await Promise.resolve().then(() => (init_cold_store_impl(), cold_store_impl_exports));
|
|
@@ -33902,7 +33995,7 @@ Token vocabulary:
|
|
|
33902
33995
|
* where no bundler substituted the constant — the same shape `server.ts` and
|
|
33903
33996
|
* `standalone.ts` use for `ORCHESTRATOR_VERSION`.
|
|
33904
33997
|
*/
|
|
33905
|
-
const CLI_VERSION = "0.
|
|
33998
|
+
const CLI_VERSION = "0.11.0";
|
|
33906
33999
|
/**
|
|
33907
34000
|
* Build the kici-admin Commander program with every command group registered.
|
|
33908
34001
|
* Exported so the surface registry can walk the real command tree without
|