@kici-dev/orchestrator 0.1.13 → 0.1.15
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 +13 -1
- package/dist/__test-helpers__/mock-db.d.ts +2 -0
- package/dist/agent/dispatcher.d.ts +110 -6
- package/dist/agent/registry.d.ts +14 -0
- package/dist/app.d.ts +11 -0
- package/dist/cache/agent-job-failed-error.d.ts +13 -0
- package/dist/cache/dispatch-cache-ref-tracker.d.ts +45 -0
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/user-cache.d.ts +116 -0
- package/dist/cancel/cancel-run.d.ts +56 -0
- package/dist/cli/commands/environment.d.ts +1 -0
- package/dist/cli/service/index.d.ts +1 -1
- package/dist/cli/service/instance/manifest.d.ts +9 -0
- package/dist/cli.js +601 -113
- package/dist/cluster/peer-registry.d.ts +6 -0
- package/dist/config/schema.d.ts +4 -0
- package/dist/config.d.ts +13 -0
- package/dist/dashboard/handler.d.ts +92 -1
- package/dist/db/migrations/025_init_failure.d.ts +16 -0
- package/dist/db/migrations/026_event_log_lockfile_corrupt.d.ts +11 -0
- package/dist/db/migrations/027_workflow_timeout.d.ts +20 -0
- package/dist/db/migrations/028_org_settings_user_cache.d.ts +4 -0
- package/dist/db/migrations/029_dispatch_queue_attempts.d.ts +16 -0
- package/dist/db/migrations/030_held_runs_env_set_null.d.ts +13 -0
- package/dist/db/migrations/031_dispatch_queue_ack_deadline.d.ts +19 -0
- package/dist/db/migrations/032_org_settings_dispatch_ack_timeout.d.ts +14 -0
- package/dist/db/types.d.ts +52 -2
- package/dist/diagnostics/checks/index.d.ts +2 -1
- package/dist/diagnostics/checks/scaler.d.ts +13 -0
- package/dist/diagnostics/types.d.ts +5 -2
- package/dist/environments/environment-store.d.ts +14 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +362 -40
- package/dist/lockfile-cache.d.ts +1 -1
- package/dist/metrics/prometheus.d.ts +8 -0
- package/dist/orchestrator-core.d.ts +4 -1
- package/dist/pipeline/dispatch-matched-workflow.d.ts +9 -0
- package/dist/pipeline/inline-eval.d.ts +17 -2
- package/dist/pipeline/process-webhook.d.ts +19 -0
- package/dist/pipeline/processor.d.ts +6 -1
- package/dist/pipeline/test-pipeline.d.ts +10 -0
- package/dist/providers/github/lock-file.d.ts +1 -1
- package/dist/providers/internal/lock-file-fetcher.d.ts +3 -2
- package/dist/queue/job-queue.d.ts +53 -1
- package/dist/reporting/execution-tracker.d.ts +80 -7
- package/dist/routes/admin-environments.d.ts +1 -0
- package/dist/scaler/bare-metal-backend.d.ts +1 -0
- package/dist/scaler/container-backend.d.ts +3 -2
- package/dist/scaler/failure-tracker.d.ts +46 -0
- package/dist/scaler/firecracker-backend.d.ts +17 -0
- package/dist/scaler/manager.d.ts +10 -0
- package/dist/scaler/nftables.d.ts +25 -3
- package/dist/scaler/types.d.ts +26 -1
- package/dist/server.js +4421 -1459
- package/dist/stale-detector/workflow-deadline-detector.d.ts +49 -0
- package/dist/standalone.js +17003 -14561
- package/dist/storage/filesystem.d.ts +12 -3
- package/dist/storage/s3.d.ts +17 -4
- package/dist/storage/types.d.ts +25 -5
- package/dist/worker/in-memory-job-queue.d.ts +40 -7
- package/dist/ws/agent-handler.d.ts +13 -0
- package/dist/ws/dashboard-env-handler.d.ts +1 -0
- package/dist/ws/platform-client.d.ts +10 -1
- package/package.json +13 -10
- package/sbom.spdx.json +91 -36
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { fileURLToPath as __cjs_fileURLToPath } from "node:url";
|
|
3
|
-
import { dirname as __cjs_dirname } from "node:path";
|
|
4
|
-
__cjs_dirname(__cjs_fileURLToPath(import.meta.url));
|
|
5
2
|
import { createRequire } from "node:module";
|
|
6
3
|
import { Command } from "commander";
|
|
7
|
-
import { BaseColdStore, ChunkLru, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createDb, createDbRole, createEnvironmentTemplateDirect, createLogger, createPool, createReadOnlyDbUser, decodeChunk, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, listEnvironmentsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, sha256, showEnvironmentDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
|
|
4
|
+
import { BaseColdStore, ChunkLru, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createDb, createDbRole, createEnvironmentTemplateDirect, createLogger, createPool, createReadOnlyDbUser, decodeChunk, deleteEnvironmentDirect, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, listEnvironmentsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, sha256, showEnvironmentDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
|
|
8
5
|
import * as fs$1 from "node:fs";
|
|
9
6
|
import fs, { createWriteStream, promises, readFileSync } from "node:fs";
|
|
10
7
|
import crypto, { createDecipheriv, createHash, hkdfSync, randomBytes, randomUUID } from "node:crypto";
|
|
@@ -989,6 +986,8 @@ var init_schema = __esmMin((() => {
|
|
|
989
986
|
cacheTtlDays: z.coerce.number().optional(),
|
|
990
987
|
cacheBuildTimeoutMs: z.coerce.number().optional(),
|
|
991
988
|
cacheMaxTarballBytes: z.coerce.number().optional(),
|
|
989
|
+
userCacheQuotaBytes: z.coerce.number().optional(),
|
|
990
|
+
userCacheTtlMs: z.coerce.number().optional(),
|
|
992
991
|
eventRouter: z.object({
|
|
993
992
|
maxChainDepth: z.coerce.number().optional(),
|
|
994
993
|
rateLimitPerWorkflowPerMinute: z.coerce.number().optional(),
|
|
@@ -1063,6 +1062,8 @@ var init_schema = __esmMin((() => {
|
|
|
1063
1062
|
cacheTtlDays: z.coerce.number().default(30),
|
|
1064
1063
|
cacheBuildTimeoutMs: z.coerce.number().default(6e5),
|
|
1065
1064
|
cacheMaxTarballBytes: z.coerce.number().default(524288e3),
|
|
1065
|
+
userCacheQuotaBytes: z.coerce.number().default(5 * 1024 * 1024 * 1024),
|
|
1066
|
+
userCacheTtlMs: z.coerce.number().default(10080 * 60 * 1e3),
|
|
1066
1067
|
eventRouterMaxChainDepth: z.coerce.number().default(10),
|
|
1067
1068
|
eventRouterRateLimitPerWorkflowPerMinute: z.coerce.number().default(100),
|
|
1068
1069
|
eventRouterEventTtlSeconds: z.coerce.number().default(604800),
|
|
@@ -1517,8 +1518,8 @@ var init_client = __esmMin((() => {
|
|
|
1517
1518
|
//#region src/db/migrations/001_initial.ts
|
|
1518
1519
|
init_client();
|
|
1519
1520
|
var _001_initial_exports = /* @__PURE__ */ __exportAll({
|
|
1520
|
-
down: () => down$
|
|
1521
|
-
up: () => up$
|
|
1521
|
+
down: () => down$31,
|
|
1522
|
+
up: () => up$31
|
|
1522
1523
|
});
|
|
1523
1524
|
/**
|
|
1524
1525
|
* Squashed initial migration -- creates the complete Orchestrator database schema.
|
|
@@ -2210,7 +2211,7 @@ const DDL_STATEMENTS = [
|
|
|
2210
2211
|
`ALTER TABLE ONLY public.held_runs
|
|
2211
2212
|
ADD CONSTRAINT held_runs_environment_id_fkey FOREIGN KEY (environment_id) REFERENCES public.environments(id);`
|
|
2212
2213
|
];
|
|
2213
|
-
async function up$
|
|
2214
|
+
async function up$31(db) {
|
|
2214
2215
|
for (const stmt of DDL_STATEMENTS) await sql.raw(stmt).execute(db);
|
|
2215
2216
|
await sql`
|
|
2216
2217
|
INSERT INTO cluster_meta (key, value)
|
|
@@ -2232,7 +2233,7 @@ async function up$23(db) {
|
|
|
2232
2233
|
* Rollback drops everything created above. Uses CASCADE on table drops to cut
|
|
2233
2234
|
* through the FK graph without relying on exact topological order.
|
|
2234
2235
|
*/
|
|
2235
|
-
async function down$
|
|
2236
|
+
async function down$31(db) {
|
|
2236
2237
|
for (const [trig, tbl] of [["source_secrets_change_trigger", "scoped_secrets"], ["sources_change_trigger", "sources"]]) await sql.raw(`DROP TRIGGER IF EXISTS ${trig} ON public.${tbl}`).execute(db);
|
|
2237
2238
|
for (const table of [
|
|
2238
2239
|
"workflow_registrations",
|
|
@@ -2279,8 +2280,8 @@ async function down$23(db) {
|
|
|
2279
2280
|
//#endregion
|
|
2280
2281
|
//#region src/db/migrations/002_config_versions_key_version.ts
|
|
2281
2282
|
var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
|
|
2282
|
-
down: () => down$
|
|
2283
|
-
up: () => up$
|
|
2283
|
+
down: () => down$30,
|
|
2284
|
+
up: () => up$30
|
|
2284
2285
|
});
|
|
2285
2286
|
/**
|
|
2286
2287
|
* Add key_version column to config_versions so that sensitive-field encryption
|
|
@@ -2294,13 +2295,13 @@ var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
|
|
|
2294
2295
|
* No index is needed: rotation does a full-table scan; reads are by
|
|
2295
2296
|
* `version` primary key and never filter on `key_version`.
|
|
2296
2297
|
*/
|
|
2297
|
-
async function up$
|
|
2298
|
+
async function up$30(db) {
|
|
2298
2299
|
await sql`
|
|
2299
2300
|
ALTER TABLE public.config_versions
|
|
2300
2301
|
ADD COLUMN key_version integer NOT NULL DEFAULT 1
|
|
2301
2302
|
`.execute(db);
|
|
2302
2303
|
}
|
|
2303
|
-
async function down$
|
|
2304
|
+
async function down$30(db) {
|
|
2304
2305
|
await sql`
|
|
2305
2306
|
ALTER TABLE public.config_versions
|
|
2306
2307
|
DROP COLUMN key_version
|
|
@@ -2309,8 +2310,8 @@ async function down$22(db) {
|
|
|
2309
2310
|
//#endregion
|
|
2310
2311
|
//#region src/db/migrations/003_access_log.ts
|
|
2311
2312
|
var _003_access_log_exports = /* @__PURE__ */ __exportAll({
|
|
2312
|
-
down: () => down$
|
|
2313
|
-
up: () => up$
|
|
2313
|
+
down: () => down$29,
|
|
2314
|
+
up: () => up$29
|
|
2314
2315
|
});
|
|
2315
2316
|
/**
|
|
2316
2317
|
* Access log: one row per read or orchestrator-admin mutation attributable
|
|
@@ -2334,7 +2335,7 @@ var _003_access_log_exports = /* @__PURE__ */ __exportAll({
|
|
|
2334
2335
|
* Retention is TTL-based via expires_at; packages/orchestrator/src/queue/
|
|
2335
2336
|
* cleanup.ts picks up the prune pass.
|
|
2336
2337
|
*/
|
|
2337
|
-
async function up$
|
|
2338
|
+
async function up$29(db) {
|
|
2338
2339
|
await sql`
|
|
2339
2340
|
CREATE TABLE public.access_log (
|
|
2340
2341
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
@@ -2372,28 +2373,28 @@ async function up$21(db) {
|
|
|
2372
2373
|
ON public.access_log (actor_type, actor_id, created_at DESC)
|
|
2373
2374
|
`.execute(db);
|
|
2374
2375
|
}
|
|
2375
|
-
async function down$
|
|
2376
|
+
async function down$29(db) {
|
|
2376
2377
|
await sql`DROP TABLE IF EXISTS public.access_log`.execute(db);
|
|
2377
2378
|
}
|
|
2378
2379
|
//#endregion
|
|
2379
2380
|
//#region src/db/migrations/004_rename_bundle_to_source.ts
|
|
2380
2381
|
var _004_rename_bundle_to_source_exports = /* @__PURE__ */ __exportAll({
|
|
2381
|
-
down: () => down$
|
|
2382
|
-
up: () => up$
|
|
2382
|
+
down: () => down$28,
|
|
2383
|
+
up: () => up$28
|
|
2383
2384
|
});
|
|
2384
|
-
async function up$
|
|
2385
|
+
async function up$28(db) {
|
|
2385
2386
|
await db.schema.alterTable("dispatch_queue").renameColumn("bundle_url", "source_tar_url").execute();
|
|
2386
2387
|
await db.schema.alterTable("dispatch_queue").renameColumn("bundle_hash", "source_tar_hash").execute();
|
|
2387
2388
|
}
|
|
2388
|
-
async function down$
|
|
2389
|
+
async function down$28(db) {
|
|
2389
2390
|
await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_url", "bundle_url").execute();
|
|
2390
2391
|
await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_hash", "bundle_hash").execute();
|
|
2391
2392
|
}
|
|
2392
2393
|
//#endregion
|
|
2393
2394
|
//#region src/db/migrations/005_cold_store_chunk_counter.ts
|
|
2394
2395
|
var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
|
|
2395
|
-
down: () => down$
|
|
2396
|
-
up: () => up$
|
|
2396
|
+
down: () => down$27,
|
|
2397
|
+
up: () => up$27
|
|
2397
2398
|
});
|
|
2398
2399
|
/**
|
|
2399
2400
|
* Cold-store chunk counter table.
|
|
@@ -2410,7 +2411,7 @@ var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
|
|
|
2410
2411
|
*
|
|
2411
2412
|
* sections 5 and 8.
|
|
2412
2413
|
*/
|
|
2413
|
-
async function up$
|
|
2414
|
+
async function up$27(db) {
|
|
2414
2415
|
await sql`
|
|
2415
2416
|
CREATE TABLE public.cold_store_chunk_counts (
|
|
2416
2417
|
db TEXT NOT NULL,
|
|
@@ -2428,14 +2429,14 @@ async function up$19(db) {
|
|
|
2428
2429
|
ON public.cold_store_chunk_counts (db, table_name)
|
|
2429
2430
|
`.execute(db);
|
|
2430
2431
|
}
|
|
2431
|
-
async function down$
|
|
2432
|
+
async function down$27(db) {
|
|
2432
2433
|
await sql`DROP TABLE IF EXISTS public.cold_store_chunk_counts`.execute(db);
|
|
2433
2434
|
}
|
|
2434
2435
|
//#endregion
|
|
2435
2436
|
//#region src/db/migrations/006_runs_jobs_steps_archived_at.ts
|
|
2436
2437
|
var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
2437
|
-
down: () => down$
|
|
2438
|
-
up: () => up$
|
|
2438
|
+
down: () => down$26,
|
|
2439
|
+
up: () => up$26
|
|
2439
2440
|
});
|
|
2440
2441
|
/**
|
|
2441
2442
|
* `execution_runs` / `execution_jobs` / `execution_steps` cold-store
|
|
@@ -2471,7 +2472,7 @@ var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
|
2471
2472
|
* - `idx_execution_jobs_routing_key_created (routing_key, created_at)`
|
|
2472
2473
|
* - `idx_execution_steps_routing_key_created (routing_key, created_at)`
|
|
2473
2474
|
*/
|
|
2474
|
-
async function up$
|
|
2475
|
+
async function up$26(db) {
|
|
2475
2476
|
await sql`
|
|
2476
2477
|
ALTER TABLE public.execution_runs
|
|
2477
2478
|
ADD COLUMN archived_at TIMESTAMPTZ NULL,
|
|
@@ -2516,7 +2517,7 @@ async function up$18(db) {
|
|
|
2516
2517
|
ON public.execution_steps (routing_key, created_at)
|
|
2517
2518
|
`.execute(db);
|
|
2518
2519
|
}
|
|
2519
|
-
async function down$
|
|
2520
|
+
async function down$26(db) {
|
|
2520
2521
|
await sql`DROP INDEX IF EXISTS public.idx_execution_steps_routing_key_created`.execute(db);
|
|
2521
2522
|
await sql`
|
|
2522
2523
|
ALTER TABLE public.execution_steps
|
|
@@ -2541,8 +2542,8 @@ async function down$18(db) {
|
|
|
2541
2542
|
//#endregion
|
|
2542
2543
|
//#region src/db/migrations/007_audit_logs_archived_at.ts
|
|
2543
2544
|
var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
2544
|
-
down: () => down$
|
|
2545
|
-
up: () => up$
|
|
2545
|
+
down: () => down$25,
|
|
2546
|
+
up: () => up$25
|
|
2546
2547
|
});
|
|
2547
2548
|
/**
|
|
2548
2549
|
* `secret_audit_log` and `access_log` cold-store schema additions, plus
|
|
@@ -2582,7 +2583,7 @@ var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
|
2582
2583
|
* `down()` would not have meaningful retention bounds. Acceptable for
|
|
2583
2584
|
* staging.
|
|
2584
2585
|
*/
|
|
2585
|
-
async function up$
|
|
2586
|
+
async function up$25(db) {
|
|
2586
2587
|
await sql`
|
|
2587
2588
|
ALTER TABLE public.secret_audit_log
|
|
2588
2589
|
ADD COLUMN archived_at TIMESTAMPTZ NULL,
|
|
@@ -2603,7 +2604,7 @@ async function up$17(db) {
|
|
|
2603
2604
|
DROP COLUMN IF EXISTS expires_at
|
|
2604
2605
|
`.execute(db);
|
|
2605
2606
|
}
|
|
2606
|
-
async function down$
|
|
2607
|
+
async function down$25(db) {
|
|
2607
2608
|
await sql`
|
|
2608
2609
|
ALTER TABLE public.access_log
|
|
2609
2610
|
ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '90 days')
|
|
@@ -2631,8 +2632,8 @@ async function down$17(db) {
|
|
|
2631
2632
|
//#endregion
|
|
2632
2633
|
//#region src/db/migrations/008_event_log_archived_at.ts
|
|
2633
2634
|
var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
2634
|
-
down: () => down$
|
|
2635
|
-
up: () => up$
|
|
2635
|
+
down: () => down$24,
|
|
2636
|
+
up: () => up$24
|
|
2636
2637
|
});
|
|
2637
2638
|
/**
|
|
2638
2639
|
* `event_log` cold-store schema additions plus removal of the
|
|
@@ -2670,7 +2671,7 @@ var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
|
|
|
2670
2671
|
* — best effort; rows inserted between `up()` and a hypothetical
|
|
2671
2672
|
* `down()` would not have meaningful retention bounds.
|
|
2672
2673
|
*/
|
|
2673
|
-
async function up$
|
|
2674
|
+
async function up$24(db) {
|
|
2674
2675
|
await sql`
|
|
2675
2676
|
ALTER TABLE public.event_log
|
|
2676
2677
|
ADD COLUMN archived_at TIMESTAMPTZ NULL,
|
|
@@ -2686,7 +2687,7 @@ async function up$16(db) {
|
|
|
2686
2687
|
DROP COLUMN IF EXISTS expires_at
|
|
2687
2688
|
`.execute(db);
|
|
2688
2689
|
}
|
|
2689
|
-
async function down$
|
|
2690
|
+
async function down$24(db) {
|
|
2690
2691
|
await sql`
|
|
2691
2692
|
ALTER TABLE public.event_log
|
|
2692
2693
|
ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '30 days')
|
|
@@ -2705,8 +2706,8 @@ async function down$16(db) {
|
|
|
2705
2706
|
//#endregion
|
|
2706
2707
|
//#region src/db/migrations/009_access_log_trigram.ts
|
|
2707
2708
|
var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
|
|
2708
|
-
down: () => down$
|
|
2709
|
-
up: () => up$
|
|
2709
|
+
down: () => down$23,
|
|
2710
|
+
up: () => up$23
|
|
2710
2711
|
});
|
|
2711
2712
|
/**
|
|
2712
2713
|
* Trigram (pg_trgm) index on access_log.error_message for the federated
|
|
@@ -2719,7 +2720,7 @@ var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
|
|
|
2719
2720
|
* EXISTS` are both safe to re-run. No CONCURRENTLY because Kysely runs
|
|
2720
2721
|
* migrations inside a transaction; the lock is brief on a sampled table.
|
|
2721
2722
|
*/
|
|
2722
|
-
async function up$
|
|
2723
|
+
async function up$23(db) {
|
|
2723
2724
|
await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
|
|
2724
2725
|
await sql`
|
|
2725
2726
|
CREATE INDEX IF NOT EXISTS access_log_error_message_trgm_idx
|
|
@@ -2728,14 +2729,14 @@ async function up$15(db) {
|
|
|
2728
2729
|
WHERE error_message IS NOT NULL
|
|
2729
2730
|
`.execute(db);
|
|
2730
2731
|
}
|
|
2731
|
-
async function down$
|
|
2732
|
+
async function down$23(db) {
|
|
2732
2733
|
await sql`DROP INDEX IF EXISTS public.access_log_error_message_trgm_idx`.execute(db);
|
|
2733
2734
|
}
|
|
2734
2735
|
//#endregion
|
|
2735
2736
|
//#region src/db/migrations/010_cold_store_chunks.ts
|
|
2736
2737
|
var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
|
|
2737
|
-
down: () => down$
|
|
2738
|
-
up: () => up$
|
|
2738
|
+
down: () => down$22,
|
|
2739
|
+
up: () => up$22
|
|
2739
2740
|
});
|
|
2740
2741
|
/**
|
|
2741
2742
|
* Cold-store chunk index — Phase 2 (cold-store purge).
|
|
@@ -2767,7 +2768,7 @@ var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
|
|
|
2767
2768
|
* forever. Adapters that don't opt into per-bucket archival via
|
|
2768
2769
|
* `coldTtlDays` don't insert here either.
|
|
2769
2770
|
*/
|
|
2770
|
-
async function up$
|
|
2771
|
+
async function up$22(db) {
|
|
2771
2772
|
await sql`
|
|
2772
2773
|
CREATE TABLE public.cold_store_chunks (
|
|
2773
2774
|
db TEXT NOT NULL,
|
|
@@ -2794,14 +2795,14 @@ async function up$14(db) {
|
|
|
2794
2795
|
ON public.cold_store_chunks (db, table_name, tenant_id, archived_at DESC)
|
|
2795
2796
|
`.execute(db);
|
|
2796
2797
|
}
|
|
2797
|
-
async function down$
|
|
2798
|
+
async function down$22(db) {
|
|
2798
2799
|
await sql`DROP TABLE IF EXISTS public.cold_store_chunks`.execute(db);
|
|
2799
2800
|
}
|
|
2800
2801
|
//#endregion
|
|
2801
2802
|
//#region src/db/migrations/011_drop_source_secrets_notify.ts
|
|
2802
2803
|
var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
|
|
2803
|
-
down: () => down$
|
|
2804
|
-
up: () => up$
|
|
2804
|
+
down: () => down$21,
|
|
2805
|
+
up: () => up$21
|
|
2805
2806
|
});
|
|
2806
2807
|
/**
|
|
2807
2808
|
* Drop the `source_secrets_change_trigger` and the
|
|
@@ -2820,11 +2821,11 @@ var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
|
|
|
2820
2821
|
* in `001_initial.ts`. They wake up no consumer until the `WebhookSecretManager`
|
|
2821
2822
|
* is restored, so this migration is safe to roll back.
|
|
2822
2823
|
*/
|
|
2823
|
-
async function up$
|
|
2824
|
+
async function up$21(db) {
|
|
2824
2825
|
await sql`DROP TRIGGER IF EXISTS source_secrets_change_trigger ON public.scoped_secrets`.execute(db);
|
|
2825
2826
|
await sql`DROP FUNCTION IF EXISTS public.notify_source_secrets_change() CASCADE`.execute(db);
|
|
2826
2827
|
}
|
|
2827
|
-
async function down$
|
|
2828
|
+
async function down$21(db) {
|
|
2828
2829
|
await sql`
|
|
2829
2830
|
CREATE OR REPLACE FUNCTION public.notify_source_secrets_change() RETURNS trigger
|
|
2830
2831
|
LANGUAGE plpgsql
|
|
@@ -2863,8 +2864,8 @@ async function down$13(db) {
|
|
|
2863
2864
|
//#endregion
|
|
2864
2865
|
//#region src/db/migrations/012_peer_credentials_active_uniq.ts
|
|
2865
2866
|
var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
|
|
2866
|
-
down: () => down$
|
|
2867
|
-
up: () => up$
|
|
2867
|
+
down: () => down$20,
|
|
2868
|
+
up: () => up$20
|
|
2868
2869
|
});
|
|
2869
2870
|
/**
|
|
2870
2871
|
* Add a partial unique index on `peer_credentials (instance_id) WHERE
|
|
@@ -2890,7 +2891,7 @@ var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
|
|
|
2890
2891
|
* `down()` only drops the index; it does NOT undo the dedupe (there's no
|
|
2891
2892
|
* safe way to recreate revoked rows, and the dedupe is monotonic).
|
|
2892
2893
|
*/
|
|
2893
|
-
async function up$
|
|
2894
|
+
async function up$20(db) {
|
|
2894
2895
|
await sql`
|
|
2895
2896
|
UPDATE public.peer_credentials
|
|
2896
2897
|
SET revoked_at = NOW()
|
|
@@ -2908,14 +2909,14 @@ async function up$12(db) {
|
|
|
2908
2909
|
WHERE revoked_at IS NULL
|
|
2909
2910
|
`.execute(db);
|
|
2910
2911
|
}
|
|
2911
|
-
async function down$
|
|
2912
|
+
async function down$20(db) {
|
|
2912
2913
|
await sql`DROP INDEX IF EXISTS public.peer_credentials_active_uniq`.execute(db);
|
|
2913
2914
|
}
|
|
2914
2915
|
//#endregion
|
|
2915
2916
|
//#region src/db/migrations/013_execution_log_bytes.ts
|
|
2916
2917
|
var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
|
|
2917
|
-
down: () => down$
|
|
2918
|
-
up: () => up$
|
|
2918
|
+
down: () => down$19,
|
|
2919
|
+
up: () => up$19
|
|
2919
2920
|
});
|
|
2920
2921
|
/**
|
|
2921
2922
|
* Add `log_bytes BIGINT NOT NULL DEFAULT 0` columns to `execution_runs` and
|
|
@@ -2934,7 +2935,7 @@ var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
|
|
|
2934
2935
|
*
|
|
2935
2936
|
* Idempotent (`ADD COLUMN IF NOT EXISTS`).
|
|
2936
2937
|
*/
|
|
2937
|
-
async function up$
|
|
2938
|
+
async function up$19(db) {
|
|
2938
2939
|
await sql`
|
|
2939
2940
|
ALTER TABLE public.execution_runs
|
|
2940
2941
|
ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
|
|
@@ -2944,15 +2945,15 @@ async function up$11(db) {
|
|
|
2944
2945
|
ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
|
|
2945
2946
|
`.execute(db);
|
|
2946
2947
|
}
|
|
2947
|
-
async function down$
|
|
2948
|
+
async function down$19(db) {
|
|
2948
2949
|
await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS log_bytes`.execute(db);
|
|
2949
2950
|
await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS log_bytes`.execute(db);
|
|
2950
2951
|
}
|
|
2951
2952
|
//#endregion
|
|
2952
2953
|
//#region src/db/migrations/014_kici_events_lease_retry.ts
|
|
2953
2954
|
var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
|
|
2954
|
-
down: () => down$
|
|
2955
|
-
up: () => up$
|
|
2955
|
+
down: () => down$18,
|
|
2956
|
+
up: () => up$18
|
|
2956
2957
|
});
|
|
2957
2958
|
/**
|
|
2958
2959
|
* Add lease + retry + DLQ columns to `kici_events` so the EventRouter can
|
|
@@ -2986,7 +2987,7 @@ var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
|
|
|
2986
2987
|
*
|
|
2987
2988
|
* Idempotent (`ADD COLUMN IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`).
|
|
2988
2989
|
*/
|
|
2989
|
-
async function up$
|
|
2990
|
+
async function up$18(db) {
|
|
2990
2991
|
await sql`
|
|
2991
2992
|
ALTER TABLE public.kici_events
|
|
2992
2993
|
ADD COLUMN IF NOT EXISTS claimed_at TIMESTAMPTZ,
|
|
@@ -3017,7 +3018,7 @@ async function up$10(db) {
|
|
|
3017
3018
|
WHERE dlq_at IS NOT NULL
|
|
3018
3019
|
`.execute(db);
|
|
3019
3020
|
}
|
|
3020
|
-
async function down$
|
|
3021
|
+
async function down$18(db) {
|
|
3021
3022
|
await sql`DROP INDEX IF EXISTS public.idx_kici_events_dlq`.execute(db);
|
|
3022
3023
|
await sql`DROP INDEX IF EXISTS public.idx_kici_events_lease_expired`.execute(db);
|
|
3023
3024
|
await sql`DROP INDEX IF EXISTS public.idx_kici_events_retry_due`.execute(db);
|
|
@@ -3035,8 +3036,8 @@ async function down$10(db) {
|
|
|
3035
3036
|
//#endregion
|
|
3036
3037
|
//#region src/db/migrations/015_org_settings_customer_scoped.ts
|
|
3037
3038
|
var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
|
|
3038
|
-
down: () => down$
|
|
3039
|
-
up: () => up$
|
|
3039
|
+
down: () => down$17,
|
|
3040
|
+
up: () => up$17
|
|
3040
3041
|
});
|
|
3041
3042
|
/**
|
|
3042
3043
|
* Org-scope `org_settings` and qualify each glob entry by source.
|
|
@@ -3064,7 +3065,7 @@ var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
|
|
|
3064
3065
|
* Idempotent: a re-run on an already-migrated DB sees `customer_id` exists
|
|
3065
3066
|
* and the list columns are already jsonb, so it is a no-op.
|
|
3066
3067
|
*/
|
|
3067
|
-
async function up$
|
|
3068
|
+
async function up$17(db) {
|
|
3068
3069
|
if ((await sql`
|
|
3069
3070
|
SELECT EXISTS (
|
|
3070
3071
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3189,7 +3190,7 @@ async function up$9(db) {
|
|
|
3189
3190
|
await sql`DROP TABLE _org_settings_merged`.execute(db);
|
|
3190
3191
|
await sql`DROP TABLE _org_settings_stage`.execute(db);
|
|
3191
3192
|
}
|
|
3192
|
-
async function down$
|
|
3193
|
+
async function down$17(db) {
|
|
3193
3194
|
if (!(await sql`
|
|
3194
3195
|
SELECT EXISTS (
|
|
3195
3196
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3214,8 +3215,8 @@ async function down$9(db) {
|
|
|
3214
3215
|
//#endregion
|
|
3215
3216
|
//#region src/db/migrations/016_org_settings_allow_http_npm.ts
|
|
3216
3217
|
var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
|
|
3217
|
-
down: () => down$
|
|
3218
|
-
up: () => up$
|
|
3218
|
+
down: () => down$16,
|
|
3219
|
+
up: () => up$16
|
|
3219
3220
|
});
|
|
3220
3221
|
/**
|
|
3221
3222
|
* Add `org_settings.allow_http_npm_registries boolean NOT NULL DEFAULT false`.
|
|
@@ -3228,7 +3229,7 @@ var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
|
|
|
3228
3229
|
*
|
|
3229
3230
|
* Idempotent: a re-run on a DB that already has the column is a no-op.
|
|
3230
3231
|
*/
|
|
3231
|
-
async function up$
|
|
3232
|
+
async function up$16(db) {
|
|
3232
3233
|
if ((await sql`
|
|
3233
3234
|
SELECT EXISTS (
|
|
3234
3235
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3242,7 +3243,7 @@ async function up$8(db) {
|
|
|
3242
3243
|
ADD COLUMN allow_http_npm_registries boolean NOT NULL DEFAULT false
|
|
3243
3244
|
`.execute(db);
|
|
3244
3245
|
}
|
|
3245
|
-
async function down$
|
|
3246
|
+
async function down$16(db) {
|
|
3246
3247
|
await sql`
|
|
3247
3248
|
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS allow_http_npm_registries
|
|
3248
3249
|
`.execute(db);
|
|
@@ -3250,8 +3251,8 @@ async function down$8(db) {
|
|
|
3250
3251
|
//#endregion
|
|
3251
3252
|
//#region src/db/migrations/017_org_id_widen.ts
|
|
3252
3253
|
var _017_org_id_widen_exports = /* @__PURE__ */ __exportAll({
|
|
3253
|
-
down: () => down$
|
|
3254
|
-
up: () => up$
|
|
3254
|
+
down: () => down$15,
|
|
3255
|
+
up: () => up$15
|
|
3255
3256
|
});
|
|
3256
3257
|
/**
|
|
3257
3258
|
* Widen every orchestrator-side `org_id varchar(12)` column to
|
|
@@ -3291,17 +3292,17 @@ const ORG_ID_TABLES$1 = [
|
|
|
3291
3292
|
"held_runs",
|
|
3292
3293
|
"scoped_secrets"
|
|
3293
3294
|
];
|
|
3294
|
-
async function up$
|
|
3295
|
+
async function up$15(db) {
|
|
3295
3296
|
for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(16)`).execute(db);
|
|
3296
3297
|
}
|
|
3297
|
-
async function down$
|
|
3298
|
+
async function down$15(db) {
|
|
3298
3299
|
for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(12)`).execute(db);
|
|
3299
3300
|
}
|
|
3300
3301
|
//#endregion
|
|
3301
3302
|
//#region src/db/migrations/018_org_id_prefix_backfill.ts
|
|
3302
3303
|
var _018_org_id_prefix_backfill_exports = /* @__PURE__ */ __exportAll({
|
|
3303
|
-
down: () => down$
|
|
3304
|
-
up: () => up$
|
|
3304
|
+
down: () => down$14,
|
|
3305
|
+
up: () => up$14
|
|
3305
3306
|
});
|
|
3306
3307
|
/**
|
|
3307
3308
|
* Prefix every orchestrator-side tenant string with `org_` to align
|
|
@@ -3346,19 +3347,19 @@ const CUSTOMER_ID_TABLES = [
|
|
|
3346
3347
|
"workflow_registrations",
|
|
3347
3348
|
"org_settings"
|
|
3348
3349
|
];
|
|
3349
|
-
async function up$
|
|
3350
|
+
async function up$14(db) {
|
|
3350
3351
|
for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = 'org_' || org_id WHERE org_id <> 'kici-admin' AND org_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3351
3352
|
for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = 'org_' || customer_id WHERE customer_id <> 'kici-admin' AND customer_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3352
3353
|
}
|
|
3353
|
-
async function down$
|
|
3354
|
+
async function down$14(db) {
|
|
3354
3355
|
for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = substring(customer_id from 5) WHERE customer_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3355
3356
|
for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = substring(org_id from 5) WHERE org_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
|
|
3356
3357
|
}
|
|
3357
3358
|
//#endregion
|
|
3358
3359
|
//#region src/db/migrations/019_generic_sources_change_notify.ts
|
|
3359
3360
|
var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
|
|
3360
|
-
down: () => down$
|
|
3361
|
-
up: () => up$
|
|
3361
|
+
down: () => down$13,
|
|
3362
|
+
up: () => up$13
|
|
3362
3363
|
});
|
|
3363
3364
|
/**
|
|
3364
3365
|
* Add a Postgres trigger on `generic_webhook_sources` that emits
|
|
@@ -3381,7 +3382,7 @@ var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
|
|
|
3381
3382
|
* (`notify_sources_change()` + `sources_change_trigger`, defined in
|
|
3382
3383
|
* `001_initial.ts`).
|
|
3383
3384
|
*/
|
|
3384
|
-
async function up$
|
|
3385
|
+
async function up$13(db) {
|
|
3385
3386
|
await sql`
|
|
3386
3387
|
CREATE FUNCTION public.notify_generic_sources_change() RETURNS trigger
|
|
3387
3388
|
LANGUAGE plpgsql
|
|
@@ -3402,15 +3403,15 @@ async function up$5(db) {
|
|
|
3402
3403
|
FOR EACH ROW EXECUTE FUNCTION public.notify_generic_sources_change()
|
|
3403
3404
|
`.execute(db);
|
|
3404
3405
|
}
|
|
3405
|
-
async function down$
|
|
3406
|
+
async function down$13(db) {
|
|
3406
3407
|
await sql`DROP TRIGGER IF EXISTS generic_sources_change_trigger ON public.generic_webhook_sources`.execute(db);
|
|
3407
3408
|
await sql`DROP FUNCTION IF EXISTS public.notify_generic_sources_change()`.execute(db);
|
|
3408
3409
|
}
|
|
3409
3410
|
//#endregion
|
|
3410
3411
|
//#region src/db/migrations/020_org_settings_dashboard_write_policy.ts
|
|
3411
3412
|
var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportAll({
|
|
3412
|
-
down: () => down$
|
|
3413
|
-
up: () => up$
|
|
3413
|
+
down: () => down$12,
|
|
3414
|
+
up: () => up$12
|
|
3414
3415
|
});
|
|
3415
3416
|
/**
|
|
3416
3417
|
* Add `org_settings.dashboard_write_policy jsonb NOT NULL DEFAULT '{}'`.
|
|
@@ -3425,7 +3426,7 @@ var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportA
|
|
|
3425
3426
|
*
|
|
3426
3427
|
* Idempotent: a re-run on a DB that already has the column is a no-op.
|
|
3427
3428
|
*/
|
|
3428
|
-
async function up$
|
|
3429
|
+
async function up$12(db) {
|
|
3429
3430
|
if ((await sql`
|
|
3430
3431
|
SELECT EXISTS (
|
|
3431
3432
|
SELECT 1 FROM information_schema.columns
|
|
@@ -3439,7 +3440,7 @@ async function up$4(db) {
|
|
|
3439
3440
|
ADD COLUMN dashboard_write_policy jsonb NOT NULL DEFAULT '{}'::jsonb
|
|
3440
3441
|
`.execute(db);
|
|
3441
3442
|
}
|
|
3442
|
-
async function down$
|
|
3443
|
+
async function down$12(db) {
|
|
3443
3444
|
await sql`
|
|
3444
3445
|
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dashboard_write_policy
|
|
3445
3446
|
`.execute(db);
|
|
@@ -3447,8 +3448,8 @@ async function down$4(db) {
|
|
|
3447
3448
|
//#endregion
|
|
3448
3449
|
//#region src/db/migrations/021_check_run_tracking.ts
|
|
3449
3450
|
var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
|
|
3450
|
-
down: () => down$
|
|
3451
|
-
up: () => up$
|
|
3451
|
+
down: () => down$11,
|
|
3452
|
+
up: () => up$11
|
|
3452
3453
|
});
|
|
3453
3454
|
/**
|
|
3454
3455
|
* Add `check_run_tracking` table for HA-safe check-run state persistence.
|
|
@@ -3472,7 +3473,7 @@ var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
|
|
|
3472
3473
|
*
|
|
3473
3474
|
* Idempotent: a re-run on a DB that already has the table is a no-op.
|
|
3474
3475
|
*/
|
|
3475
|
-
async function up$
|
|
3476
|
+
async function up$11(db) {
|
|
3476
3477
|
if ((await sql`
|
|
3477
3478
|
SELECT EXISTS (
|
|
3478
3479
|
SELECT 1 FROM information_schema.tables
|
|
@@ -3503,14 +3504,14 @@ async function up$3(db) {
|
|
|
3503
3504
|
WHERE run_id IS NOT NULL
|
|
3504
3505
|
`.execute(db);
|
|
3505
3506
|
}
|
|
3506
|
-
async function down$
|
|
3507
|
+
async function down$11(db) {
|
|
3507
3508
|
await sql`DROP TABLE IF EXISTS public.check_run_tracking`.execute(db);
|
|
3508
3509
|
}
|
|
3509
3510
|
//#endregion
|
|
3510
3511
|
//#region src/db/migrations/022_scaler_manager_state.ts
|
|
3511
3512
|
var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
|
|
3512
|
-
down: () => down$
|
|
3513
|
-
up: () => up$
|
|
3513
|
+
down: () => down$10,
|
|
3514
|
+
up: () => up$10
|
|
3514
3515
|
});
|
|
3515
3516
|
/**
|
|
3516
3517
|
* Add three tables persisting `ScalerManager` per-coord state:
|
|
@@ -3537,7 +3538,7 @@ var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
|
|
|
3537
3538
|
* Idempotent: a re-run on a DB that already has any of these tables
|
|
3538
3539
|
* leaves the existing one alone.
|
|
3539
3540
|
*/
|
|
3540
|
-
async function up$
|
|
3541
|
+
async function up$10(db) {
|
|
3541
3542
|
const tableExists = async (name) => {
|
|
3542
3543
|
return (await sql`
|
|
3543
3544
|
SELECT EXISTS (
|
|
@@ -3587,7 +3588,7 @@ async function up$2(db) {
|
|
|
3587
3588
|
`.execute(db);
|
|
3588
3589
|
}
|
|
3589
3590
|
}
|
|
3590
|
-
async function down$
|
|
3591
|
+
async function down$10(db) {
|
|
3591
3592
|
await sql`DROP TABLE IF EXISTS public.scaler_reservations`.execute(db);
|
|
3592
3593
|
await sql`DROP TABLE IF EXISTS public.scaler_agent_jobs`.execute(db);
|
|
3593
3594
|
await sql`DROP TABLE IF EXISTS public.scaler_spawning_agents`.execute(db);
|
|
@@ -3595,8 +3596,8 @@ async function down$2(db) {
|
|
|
3595
3596
|
//#endregion
|
|
3596
3597
|
//#region src/db/migrations/023_dispatch_queue_recovery_deadline.ts
|
|
3597
3598
|
var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll({
|
|
3598
|
-
down: () => down$
|
|
3599
|
-
up: () => up$
|
|
3599
|
+
down: () => down$9,
|
|
3600
|
+
up: () => up$9
|
|
3600
3601
|
});
|
|
3601
3602
|
/**
|
|
3602
3603
|
* Add `dispatch_queue.recovery_deadline TIMESTAMPTZ` and
|
|
@@ -3620,7 +3621,7 @@ var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll(
|
|
|
3620
3621
|
* Idempotent: re-running on a DB that already has either column is a
|
|
3621
3622
|
* no-op.
|
|
3622
3623
|
*/
|
|
3623
|
-
async function up$
|
|
3624
|
+
async function up$9(db) {
|
|
3624
3625
|
const colExists = async (name) => {
|
|
3625
3626
|
return (await sql`
|
|
3626
3627
|
SELECT EXISTS (
|
|
@@ -3645,7 +3646,7 @@ async function up$1(db) {
|
|
|
3645
3646
|
WHERE recovery_deadline IS NOT NULL
|
|
3646
3647
|
`.execute(db);
|
|
3647
3648
|
}
|
|
3648
|
-
async function down$
|
|
3649
|
+
async function down$9(db) {
|
|
3649
3650
|
await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_recovery_deadline`.execute(db);
|
|
3650
3651
|
await sql`
|
|
3651
3652
|
ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS recovery_agent_id
|
|
@@ -3657,8 +3658,8 @@ async function down$1(db) {
|
|
|
3657
3658
|
//#endregion
|
|
3658
3659
|
//#region src/db/migrations/024_dispatch_queue_provisioning_error.ts
|
|
3659
3660
|
var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll({
|
|
3660
|
-
down: () => down,
|
|
3661
|
-
up: () => up
|
|
3661
|
+
down: () => down$8,
|
|
3662
|
+
up: () => up$8
|
|
3662
3663
|
});
|
|
3663
3664
|
/**
|
|
3664
3665
|
* Add `dispatch_queue.last_provisioning_error TEXT` recording the most
|
|
@@ -3674,7 +3675,7 @@ var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll
|
|
|
3674
3675
|
*
|
|
3675
3676
|
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
3676
3677
|
*/
|
|
3677
|
-
async function up(db) {
|
|
3678
|
+
async function up$8(db) {
|
|
3678
3679
|
const colExists = async (name) => {
|
|
3679
3680
|
return (await sql`
|
|
3680
3681
|
SELECT EXISTS (
|
|
@@ -3690,12 +3691,326 @@ async function up(db) {
|
|
|
3690
3691
|
ADD COLUMN last_provisioning_error TEXT
|
|
3691
3692
|
`.execute(db);
|
|
3692
3693
|
}
|
|
3693
|
-
async function down(db) {
|
|
3694
|
+
async function down$8(db) {
|
|
3694
3695
|
await sql`
|
|
3695
3696
|
ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS last_provisioning_error
|
|
3696
3697
|
`.execute(db);
|
|
3697
3698
|
}
|
|
3698
3699
|
//#endregion
|
|
3700
|
+
//#region src/db/migrations/025_init_failure.ts
|
|
3701
|
+
var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
|
|
3702
|
+
down: () => down$7,
|
|
3703
|
+
up: () => up$7
|
|
3704
|
+
});
|
|
3705
|
+
/**
|
|
3706
|
+
* Add `init_failure jsonb` columns to `execution_runs` and `execution_jobs`.
|
|
3707
|
+
*
|
|
3708
|
+
* Presence of this column on a row means the run/job never executed a step
|
|
3709
|
+
* because of an init-phase failure; absence (NULL) means a normal run.
|
|
3710
|
+
* Shape on the wire is `InitFailure` from `@kici-dev/engine`. The dashboard
|
|
3711
|
+
* reads this column directly so it can render the right banner without
|
|
3712
|
+
* round-tripping to the orchestrator (which may be offline).
|
|
3713
|
+
*
|
|
3714
|
+
* Idempotent: re-running on a DB that already has either column is a no-op
|
|
3715
|
+
* for that column.
|
|
3716
|
+
*/
|
|
3717
|
+
async function up$7(db) {
|
|
3718
|
+
const colExists = async (table, name) => {
|
|
3719
|
+
return (await sql`
|
|
3720
|
+
SELECT EXISTS (
|
|
3721
|
+
SELECT 1 FROM information_schema.columns
|
|
3722
|
+
WHERE table_schema = 'public'
|
|
3723
|
+
AND table_name = ${table}
|
|
3724
|
+
AND column_name = ${name}
|
|
3725
|
+
) AS exists
|
|
3726
|
+
`.execute(db)).rows[0]?.exists ?? false;
|
|
3727
|
+
};
|
|
3728
|
+
if (!await colExists("execution_runs", "init_failure")) await sql`
|
|
3729
|
+
ALTER TABLE public.execution_runs
|
|
3730
|
+
ADD COLUMN init_failure JSONB DEFAULT NULL
|
|
3731
|
+
`.execute(db);
|
|
3732
|
+
if (!await colExists("execution_jobs", "init_failure")) await sql`
|
|
3733
|
+
ALTER TABLE public.execution_jobs
|
|
3734
|
+
ADD COLUMN init_failure JSONB DEFAULT NULL
|
|
3735
|
+
`.execute(db);
|
|
3736
|
+
}
|
|
3737
|
+
async function down$7(db) {
|
|
3738
|
+
await sql`
|
|
3739
|
+
ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS init_failure
|
|
3740
|
+
`.execute(db);
|
|
3741
|
+
await sql`
|
|
3742
|
+
ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS init_failure
|
|
3743
|
+
`.execute(db);
|
|
3744
|
+
}
|
|
3745
|
+
//#endregion
|
|
3746
|
+
//#region src/db/migrations/026_event_log_lockfile_corrupt.ts
|
|
3747
|
+
var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
|
|
3748
|
+
down: () => down$6,
|
|
3749
|
+
up: () => up$6
|
|
3750
|
+
});
|
|
3751
|
+
/**
|
|
3752
|
+
* Extend the event_log.status CHECK constraint with 'lockfile_corrupt' so the
|
|
3753
|
+
* orchestrator can log a delivery whose lock file was present but unparseable.
|
|
3754
|
+
* Orchestrator-only: the Platform event_log uses a separate, narrower status set.
|
|
3755
|
+
*
|
|
3756
|
+
* Idempotent: the DROP ... IF EXISTS / re-ADD pair re-runs cleanly.
|
|
3757
|
+
*/
|
|
3758
|
+
async function up$6(db) {
|
|
3759
|
+
await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
|
|
3760
|
+
await sql`
|
|
3761
|
+
ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
|
|
3762
|
+
CHECK ((status = ANY (ARRAY[
|
|
3763
|
+
'received'::text, 'processed'::text, 'duplicate'::text,
|
|
3764
|
+
'lockfile_missing'::text, 'lockfile_corrupt'::text, 'failed'::text
|
|
3765
|
+
])))
|
|
3766
|
+
`.execute(db);
|
|
3767
|
+
}
|
|
3768
|
+
async function down$6(db) {
|
|
3769
|
+
await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
|
|
3770
|
+
await sql`
|
|
3771
|
+
ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
|
|
3772
|
+
CHECK ((status = ANY (ARRAY[
|
|
3773
|
+
'received'::text, 'processed'::text, 'duplicate'::text,
|
|
3774
|
+
'lockfile_missing'::text, 'failed'::text
|
|
3775
|
+
])))
|
|
3776
|
+
`.execute(db);
|
|
3777
|
+
}
|
|
3778
|
+
//#endregion
|
|
3779
|
+
//#region src/db/migrations/027_workflow_timeout.ts
|
|
3780
|
+
var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
|
|
3781
|
+
down: () => down$5,
|
|
3782
|
+
up: () => up$5
|
|
3783
|
+
});
|
|
3784
|
+
/**
|
|
3785
|
+
* Add `workflow_timeout_ms integer` to `execution_runs`.
|
|
3786
|
+
*
|
|
3787
|
+
* Persists the workflow-level wall-clock timeout (in milliseconds) read from
|
|
3788
|
+
* the lock workflow at run creation. NULL means no workflow-level cap is
|
|
3789
|
+
* configured. The WorkflowDeadlineDetector reads this column to find runs
|
|
3790
|
+
* whose `started_at + workflow_timeout_ms` has passed and cancels them with
|
|
3791
|
+
* the distinct workflow-timeout reason.
|
|
3792
|
+
*
|
|
3793
|
+
* Typed INTEGER to match the existing `*_ms` columns (`duration_ms`,
|
|
3794
|
+
* `concurrency_timeout_ms`), which keeps the pg read representation a plain
|
|
3795
|
+
* number rather than the BIGINT-as-string shape. INTEGER caps the timeout at
|
|
3796
|
+
* ~24.8 days, far beyond any sane workflow wall-clock budget.
|
|
3797
|
+
*
|
|
3798
|
+
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
3799
|
+
*/
|
|
3800
|
+
async function up$5(db) {
|
|
3801
|
+
await sql`
|
|
3802
|
+
ALTER TABLE public.execution_runs
|
|
3803
|
+
ADD COLUMN IF NOT EXISTS workflow_timeout_ms INTEGER DEFAULT NULL
|
|
3804
|
+
`.execute(db);
|
|
3805
|
+
}
|
|
3806
|
+
async function down$5(db) {
|
|
3807
|
+
await sql`
|
|
3808
|
+
ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_timeout_ms
|
|
3809
|
+
`.execute(db);
|
|
3810
|
+
}
|
|
3811
|
+
//#endregion
|
|
3812
|
+
//#region src/db/migrations/028_org_settings_user_cache.ts
|
|
3813
|
+
var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
|
|
3814
|
+
down: () => down$4,
|
|
3815
|
+
up: () => up$4
|
|
3816
|
+
});
|
|
3817
|
+
/**
|
|
3818
|
+
* Add `org_settings.user_cache_quota_bytes bigint` and
|
|
3819
|
+
* `org_settings.user_cache_ttl_ms bigint`, both NULLABLE.
|
|
3820
|
+
*
|
|
3821
|
+
* These make the user-facing cache per-org byte quota and per-entry TTL
|
|
3822
|
+
* cluster-configurable (runtime-editable per `customer_id` via the admin
|
|
3823
|
+
* route + `kici-admin org-settings user-cache` CLI). A NULL value means
|
|
3824
|
+
* "use the cluster-wide default" — the `KICI_USER_CACHE_QUOTA_BYTES` /
|
|
3825
|
+
* `KICI_USER_CACHE_TTL_MS` env vars (5 GiB / 7 days) resolved in config.ts.
|
|
3826
|
+
*
|
|
3827
|
+
* BIGINT because a quota in bytes (5 GiB = 5_368_709_120) and a TTL in ms
|
|
3828
|
+
* (7 days = 604_800_000) both exceed the safe range only at extreme values,
|
|
3829
|
+
* but a quota can legitimately reach tens of GiB; BIGINT keeps headroom and
|
|
3830
|
+
* matches the sibling `log_bytes` bigint columns.
|
|
3831
|
+
*
|
|
3832
|
+
* Idempotent: a re-run on a DB that already has either column skips it.
|
|
3833
|
+
*/
|
|
3834
|
+
async function columnExists(db, column) {
|
|
3835
|
+
return (await sql`
|
|
3836
|
+
SELECT EXISTS (
|
|
3837
|
+
SELECT 1 FROM information_schema.columns
|
|
3838
|
+
WHERE table_schema = 'public'
|
|
3839
|
+
AND table_name = 'org_settings'
|
|
3840
|
+
AND column_name = ${column}
|
|
3841
|
+
) AS exists
|
|
3842
|
+
`.execute(db)).rows[0]?.exists ?? false;
|
|
3843
|
+
}
|
|
3844
|
+
async function up$4(db) {
|
|
3845
|
+
if (!await columnExists(db, "user_cache_quota_bytes")) await sql`
|
|
3846
|
+
ALTER TABLE public.org_settings
|
|
3847
|
+
ADD COLUMN user_cache_quota_bytes bigint
|
|
3848
|
+
`.execute(db);
|
|
3849
|
+
if (!await columnExists(db, "user_cache_ttl_ms")) await sql`
|
|
3850
|
+
ALTER TABLE public.org_settings
|
|
3851
|
+
ADD COLUMN user_cache_ttl_ms bigint
|
|
3852
|
+
`.execute(db);
|
|
3853
|
+
}
|
|
3854
|
+
async function down$4(db) {
|
|
3855
|
+
await sql`
|
|
3856
|
+
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS user_cache_quota_bytes
|
|
3857
|
+
`.execute(db);
|
|
3858
|
+
await sql`
|
|
3859
|
+
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS user_cache_ttl_ms
|
|
3860
|
+
`.execute(db);
|
|
3861
|
+
}
|
|
3862
|
+
//#endregion
|
|
3863
|
+
//#region src/db/migrations/029_dispatch_queue_attempts.ts
|
|
3864
|
+
var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
|
|
3865
|
+
down: () => down$3,
|
|
3866
|
+
up: () => up$3
|
|
3867
|
+
});
|
|
3868
|
+
/**
|
|
3869
|
+
* Add `dispatch_queue.dispatch_attempts INT NOT NULL DEFAULT 0`.
|
|
3870
|
+
*
|
|
3871
|
+
* Counts how many times a job has been returned to `pending` for
|
|
3872
|
+
* re-dispatch after a failed delivery attempt (agent sent job.reject, or
|
|
3873
|
+
* a scaler-managed agent disconnected before the job started). The
|
|
3874
|
+
* dispatcher fails the job permanently once the counter reaches
|
|
3875
|
+
* MAX_DISPATCH_ATTEMPTS, bounding requeue loops; `expires_at` remains the
|
|
3876
|
+
* time-based backstop.
|
|
3877
|
+
*
|
|
3878
|
+
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
3879
|
+
*/
|
|
3880
|
+
async function up$3(db) {
|
|
3881
|
+
if (!((await sql`
|
|
3882
|
+
SELECT EXISTS (
|
|
3883
|
+
SELECT 1 FROM information_schema.columns
|
|
3884
|
+
WHERE table_schema = 'public'
|
|
3885
|
+
AND table_name = 'dispatch_queue'
|
|
3886
|
+
AND column_name = 'dispatch_attempts'
|
|
3887
|
+
) AS exists
|
|
3888
|
+
`.execute(db)).rows[0]?.exists ?? false)) await sql`
|
|
3889
|
+
ALTER TABLE public.dispatch_queue
|
|
3890
|
+
ADD COLUMN dispatch_attempts INT NOT NULL DEFAULT 0
|
|
3891
|
+
`.execute(db);
|
|
3892
|
+
}
|
|
3893
|
+
async function down$3(db) {
|
|
3894
|
+
await sql`
|
|
3895
|
+
ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS dispatch_attempts
|
|
3896
|
+
`.execute(db);
|
|
3897
|
+
}
|
|
3898
|
+
//#endregion
|
|
3899
|
+
//#region src/db/migrations/030_held_runs_env_set_null.ts
|
|
3900
|
+
var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
|
|
3901
|
+
down: () => down$2,
|
|
3902
|
+
up: () => up$2
|
|
3903
|
+
});
|
|
3904
|
+
/**
|
|
3905
|
+
* held_runs.environment_id becomes nullable with ON DELETE SET NULL so
|
|
3906
|
+
* terminal held-run history survives environment deletion (a null
|
|
3907
|
+
* environment_id means the environment was since deleted). Pending held
|
|
3908
|
+
* runs still block deletion — enforced in EnvironmentStore.delete.
|
|
3909
|
+
*
|
|
3910
|
+
* Idempotent: dropping the NOT NULL and the constraint are both no-ops on a
|
|
3911
|
+
* re-run, and the constraint is re-created with the SET NULL action.
|
|
3912
|
+
*/
|
|
3913
|
+
async function up$2(db) {
|
|
3914
|
+
await sql`ALTER TABLE public.held_runs ALTER COLUMN environment_id DROP NOT NULL`.execute(db);
|
|
3915
|
+
await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
|
|
3916
|
+
await sql`ALTER TABLE public.held_runs
|
|
3917
|
+
ADD CONSTRAINT held_runs_environment_id_fkey
|
|
3918
|
+
FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL`.execute(db);
|
|
3919
|
+
}
|
|
3920
|
+
async function down$2(db) {
|
|
3921
|
+
await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
|
|
3922
|
+
await sql`ALTER TABLE public.held_runs
|
|
3923
|
+
ADD CONSTRAINT held_runs_environment_id_fkey
|
|
3924
|
+
FOREIGN KEY (environment_id) REFERENCES public.environments(id)`.execute(db);
|
|
3925
|
+
await sql`ALTER TABLE public.held_runs ALTER COLUMN environment_id SET NOT NULL`.execute(db);
|
|
3926
|
+
}
|
|
3927
|
+
//#endregion
|
|
3928
|
+
//#region src/db/migrations/031_dispatch_queue_ack_deadline.ts
|
|
3929
|
+
var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
|
|
3930
|
+
down: () => down$1,
|
|
3931
|
+
up: () => up$1
|
|
3932
|
+
});
|
|
3933
|
+
/**
|
|
3934
|
+
* Add `dispatch_queue.ack_deadline TIMESTAMPTZ` and
|
|
3935
|
+
* `dispatch_queue.ack_agent_id TEXT` persisting the per-dispatch
|
|
3936
|
+
* acknowledgment deadline for HA-safe lost-dispatch detection.
|
|
3937
|
+
*
|
|
3938
|
+
* The dispatcher stamps both when a job.dispatch is sent and clears them
|
|
3939
|
+
* when the agent answers (job.ack / job.reject / job.status running). A
|
|
3940
|
+
* `dispatched` row past its deadline is requeued — by the owning coord's
|
|
3941
|
+
* in-memory timer, or by the leader-gated sweep
|
|
3942
|
+
* (`Dispatcher.sweepExpiredAckDeadlines`) when the owning coord crashed.
|
|
3943
|
+
* On coord boot, `Dispatcher.recoverState()` re-arms timers from the
|
|
3944
|
+
* persisted deadlines.
|
|
3945
|
+
*
|
|
3946
|
+
* Idempotent: re-running on a DB that already has either column is a no-op.
|
|
3947
|
+
*/
|
|
3948
|
+
async function up$1(db) {
|
|
3949
|
+
const colExists = async (name) => {
|
|
3950
|
+
return (await sql`
|
|
3951
|
+
SELECT EXISTS (
|
|
3952
|
+
SELECT 1 FROM information_schema.columns
|
|
3953
|
+
WHERE table_schema = 'public'
|
|
3954
|
+
AND table_name = 'dispatch_queue'
|
|
3955
|
+
AND column_name = ${name}
|
|
3956
|
+
) AS exists
|
|
3957
|
+
`.execute(db)).rows[0]?.exists ?? false;
|
|
3958
|
+
};
|
|
3959
|
+
if (!await colExists("ack_deadline")) await sql`
|
|
3960
|
+
ALTER TABLE public.dispatch_queue
|
|
3961
|
+
ADD COLUMN ack_deadline TIMESTAMPTZ
|
|
3962
|
+
`.execute(db);
|
|
3963
|
+
if (!await colExists("ack_agent_id")) await sql`
|
|
3964
|
+
ALTER TABLE public.dispatch_queue
|
|
3965
|
+
ADD COLUMN ack_agent_id TEXT
|
|
3966
|
+
`.execute(db);
|
|
3967
|
+
await sql`
|
|
3968
|
+
CREATE INDEX IF NOT EXISTS idx_dispatch_queue_ack_deadline
|
|
3969
|
+
ON public.dispatch_queue (ack_deadline)
|
|
3970
|
+
WHERE ack_deadline IS NOT NULL
|
|
3971
|
+
`.execute(db);
|
|
3972
|
+
}
|
|
3973
|
+
async function down$1(db) {
|
|
3974
|
+
await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_ack_deadline`.execute(db);
|
|
3975
|
+
await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_agent_id`.execute(db);
|
|
3976
|
+
await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_deadline`.execute(db);
|
|
3977
|
+
}
|
|
3978
|
+
//#endregion
|
|
3979
|
+
//#region src/db/migrations/032_org_settings_dispatch_ack_timeout.ts
|
|
3980
|
+
var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll({
|
|
3981
|
+
down: () => down,
|
|
3982
|
+
up: () => up
|
|
3983
|
+
});
|
|
3984
|
+
/**
|
|
3985
|
+
* Add `org_settings.dispatch_ack_timeout_ms BIGINT` (nullable).
|
|
3986
|
+
*
|
|
3987
|
+
* Per-org override of the dispatch-acknowledgment deadline. NULL falls
|
|
3988
|
+
* back to the cluster-wide default (`KICI_DISPATCH_ACK_TIMEOUT_MS`,
|
|
3989
|
+
* default 10s). Operators raise it on high-latency networks via
|
|
3990
|
+
* `kici-admin org-settings`.
|
|
3991
|
+
*
|
|
3992
|
+
* Idempotent: a re-run on a DB that already has the column is a no-op.
|
|
3993
|
+
*/
|
|
3994
|
+
async function up(db) {
|
|
3995
|
+
if ((await sql`
|
|
3996
|
+
SELECT EXISTS (
|
|
3997
|
+
SELECT 1 FROM information_schema.columns
|
|
3998
|
+
WHERE table_schema = 'public'
|
|
3999
|
+
AND table_name = 'org_settings'
|
|
4000
|
+
AND column_name = 'dispatch_ack_timeout_ms'
|
|
4001
|
+
) AS exists
|
|
4002
|
+
`.execute(db)).rows[0]?.exists) return;
|
|
4003
|
+
await sql`
|
|
4004
|
+
ALTER TABLE public.org_settings
|
|
4005
|
+
ADD COLUMN dispatch_ack_timeout_ms BIGINT
|
|
4006
|
+
`.execute(db);
|
|
4007
|
+
}
|
|
4008
|
+
async function down(db) {
|
|
4009
|
+
await sql`
|
|
4010
|
+
ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dispatch_ack_timeout_ms
|
|
4011
|
+
`.execute(db);
|
|
4012
|
+
}
|
|
4013
|
+
//#endregion
|
|
3699
4014
|
//#region src/db/migration-provider.ts
|
|
3700
4015
|
function createMigrationProvider() {
|
|
3701
4016
|
return { async getMigrations() {
|
|
@@ -3723,7 +4038,15 @@ function createMigrationProvider() {
|
|
|
3723
4038
|
"021_check_run_tracking": _021_check_run_tracking_exports,
|
|
3724
4039
|
"022_scaler_manager_state": _022_scaler_manager_state_exports,
|
|
3725
4040
|
"023_dispatch_queue_recovery_deadline": _023_dispatch_queue_recovery_deadline_exports,
|
|
3726
|
-
"024_dispatch_queue_provisioning_error": _024_dispatch_queue_provisioning_error_exports
|
|
4041
|
+
"024_dispatch_queue_provisioning_error": _024_dispatch_queue_provisioning_error_exports,
|
|
4042
|
+
"025_init_failure": _025_init_failure_exports,
|
|
4043
|
+
"026_event_log_lockfile_corrupt": _026_event_log_lockfile_corrupt_exports,
|
|
4044
|
+
"027_workflow_timeout": _027_workflow_timeout_exports,
|
|
4045
|
+
"028_org_settings_user_cache": _028_org_settings_user_cache_exports,
|
|
4046
|
+
"029_dispatch_queue_attempts": _029_dispatch_queue_attempts_exports,
|
|
4047
|
+
"030_held_runs_env_set_null": _030_held_runs_env_set_null_exports,
|
|
4048
|
+
"031_dispatch_queue_ack_deadline": _031_dispatch_queue_ack_deadline_exports,
|
|
4049
|
+
"032_org_settings_dispatch_ack_timeout": _032_org_settings_dispatch_ack_timeout_exports
|
|
3727
4050
|
};
|
|
3728
4051
|
} };
|
|
3729
4052
|
}
|
|
@@ -3762,6 +4085,8 @@ async function runMigrations(opts) {
|
|
|
3762
4085
|
const applied = (results ?? []).filter((r) => r.status === "Success");
|
|
3763
4086
|
if (applied.length === 0) logger$5.info("Database schema is up to date");
|
|
3764
4087
|
else logger$5.info(`Applied ${applied.length} migration(s)`);
|
|
4088
|
+
const hash = await computeMigrationsHash(createMigrationProvider());
|
|
4089
|
+
await storeMigrationContentHash(opts.pool, hash);
|
|
3765
4090
|
return results ?? [];
|
|
3766
4091
|
} finally {
|
|
3767
4092
|
await client.query("SELECT pg_advisory_unlock($1)", [ADVISORY_LOCK_KEY]);
|
|
@@ -3854,7 +4179,6 @@ function registerDbCommands(program, getClient) {
|
|
|
3854
4179
|
pool
|
|
3855
4180
|
})).filter((r) => r.status === "Success").length;
|
|
3856
4181
|
const hash = await computeMigrationsHash(createMigrationProvider());
|
|
3857
|
-
await storeMigrationContentHash(pool, hash);
|
|
3858
4182
|
console.log(`db fresh: ${dbName} — applied ${applied} migration(s), content hash ${hash.slice(0, 12)}...`);
|
|
3859
4183
|
} finally {
|
|
3860
4184
|
await kdb.destroy();
|
|
@@ -3865,7 +4189,7 @@ function registerDbCommands(program, getClient) {
|
|
|
3865
4189
|
process.exit(1);
|
|
3866
4190
|
}
|
|
3867
4191
|
});
|
|
3868
|
-
db.command("ensure <name>").description("CREATE DATABASE IF NOT EXISTS (idempotent)").option("--database-url <url>", "Admin DB URL (else KICI_DATABASE_URL / DATABASE_URL)").option("--owner <role>", "DB owner role (default: URL user). Pass when the admin connection is privileged but the new DB should be owned by a separate non-privileged role.").option("--revoke-connect-public", "After ensure, REVOKE CONNECT ON DATABASE \"<name>\" FROM PUBLIC (recommended on shared clusters).").action(async (name, opts) => {
|
|
4192
|
+
db.command("ensure <name>").description("CREATE DATABASE IF NOT EXISTS (idempotent)").option("--database-url <url>", "Admin DB URL (else KICI_DATABASE_URL / DATABASE_URL)").option("--owner <role>", "DB owner role (default: URL user). Pass when the admin connection is privileged but the new DB should be owned by a separate non-privileged role.").option("--revoke-connect-public", "After ensure, REVOKE CONNECT ON DATABASE \"<name>\" FROM PUBLIC (recommended on shared clusters).").option("--grant-connect-role <role>", "After ensure (and any --revoke-connect-public), GRANT CONNECT ON DATABASE \"<name>\" TO \"<role>\". Repeatable.", (val, acc) => acc.concat([val]), []).action(async (name, opts) => {
|
|
3869
4193
|
try {
|
|
3870
4194
|
const baseUrl = resolveDatabaseUrl$1(opts.databaseUrl);
|
|
3871
4195
|
const url = new URL(baseUrl);
|
|
@@ -3874,9 +4198,10 @@ function registerDbCommands(program, getClient) {
|
|
|
3874
4198
|
logInvocation(`ensure ${name}`, targetUrl);
|
|
3875
4199
|
const outcome = await ensureDatabase(targetUrl, {
|
|
3876
4200
|
owner: opts.owner,
|
|
3877
|
-
revokeConnectFromPublic: !!opts.revokeConnectPublic
|
|
4201
|
+
revokeConnectFromPublic: !!opts.revokeConnectPublic,
|
|
4202
|
+
grantConnectToRoles: opts.grantConnectRole
|
|
3878
4203
|
});
|
|
3879
|
-
const suffix = (opts.owner ? ` (owner=${opts.owner})` : "") + (opts.revokeConnectPublic ? " [revoked CONNECT from PUBLIC]" : "");
|
|
4204
|
+
const suffix = (opts.owner ? ` (owner=${opts.owner})` : "") + (opts.revokeConnectPublic ? " [revoked CONNECT from PUBLIC]" : "") + (opts.grantConnectRole.length ? ` [granted CONNECT to: ${opts.grantConnectRole.join(", ")}]` : "");
|
|
3880
4205
|
console.log(`db ensure: ${name} — ${outcome}${suffix}`);
|
|
3881
4206
|
} catch (err) {
|
|
3882
4207
|
console.error(`Error: ${toErrorMessage(err)}`);
|
|
@@ -6236,6 +6561,23 @@ function writeManifest(instanceDir, manifest) {
|
|
|
6236
6561
|
fs.writeFileSync(file, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
6237
6562
|
return file;
|
|
6238
6563
|
}
|
|
6564
|
+
/**
|
|
6565
|
+
* Read the running kici-admin's version from the orchestrator package.json.
|
|
6566
|
+
*
|
|
6567
|
+
* `process.env.npm_package_version` is only populated under `npm run` and is
|
|
6568
|
+
* undefined when kici-admin runs as a globally-installed binary, which is the
|
|
6569
|
+
* actual install path. Reading from the package.json on disk is the only
|
|
6570
|
+
* reliable source.
|
|
6571
|
+
*/
|
|
6572
|
+
function readKiciVersion() {
|
|
6573
|
+
try {
|
|
6574
|
+
const pkgUrl = new URL("../../../../package.json", import.meta.url);
|
|
6575
|
+
const pkg = JSON.parse(fs.readFileSync(fileURLToPath(pkgUrl), "utf-8"));
|
|
6576
|
+
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
6577
|
+
} catch {
|
|
6578
|
+
return "unknown";
|
|
6579
|
+
}
|
|
6580
|
+
}
|
|
6239
6581
|
//#endregion
|
|
6240
6582
|
//#region src/cli/service/instance/index-file.ts
|
|
6241
6583
|
/**
|
|
@@ -7105,11 +7447,11 @@ var init_registry = __esmMin((() => {
|
|
|
7105
7447
|
},
|
|
7106
7448
|
shawl: { "win32-x64": {
|
|
7107
7449
|
name: "shawl",
|
|
7108
|
-
version: "1.
|
|
7450
|
+
version: "1.9.0",
|
|
7109
7451
|
platform: "win32",
|
|
7110
7452
|
arch: "x64",
|
|
7111
|
-
url: "https://github.com/mtkennerly/shawl/releases/download/v1.
|
|
7112
|
-
sha256: "
|
|
7453
|
+
url: "https://github.com/mtkennerly/shawl/releases/download/v1.9.0/shawl-v1.9.0-win64.zip",
|
|
7454
|
+
sha256: "f883c5d09c9beae2efaeabd8513e7d3f57cd1d0864cec3df4f4a7b6ee904351c",
|
|
7113
7455
|
extractPath: "shawl.exe",
|
|
7114
7456
|
archiveType: "zip"
|
|
7115
7457
|
} }
|
|
@@ -8221,7 +8563,18 @@ function startDevPostgres(containerName) {
|
|
|
8221
8563
|
if (err instanceof Error && err.message.includes("already exists")) throw err;
|
|
8222
8564
|
}
|
|
8223
8565
|
console.log(`Starting dev PostgreSQL container "${containerName}" on port ${port}...`);
|
|
8224
|
-
|
|
8566
|
+
const tmpEnvFile = path.join(fs.mkdtempSync(path.join(os.tmpdir(), "kici-dev-pg-")), "postgres.env");
|
|
8567
|
+
try {
|
|
8568
|
+
fs.writeFileSync(tmpEnvFile, `POSTGRES_PASSWORD=${password}\n`, { mode: 384 });
|
|
8569
|
+
execSync(`${runtime} run -d --name ${containerName} -p ${port}:5432 --env-file ${tmpEnvFile} -e POSTGRES_DB=kici postgres:18-trixie`, { stdio: "inherit" });
|
|
8570
|
+
} finally {
|
|
8571
|
+
try {
|
|
8572
|
+
fs.rmSync(path.dirname(tmpEnvFile), {
|
|
8573
|
+
recursive: true,
|
|
8574
|
+
force: true
|
|
8575
|
+
});
|
|
8576
|
+
} catch {}
|
|
8577
|
+
}
|
|
8225
8578
|
return `postgresql://postgres:${password}@localhost:${port}/kici`;
|
|
8226
8579
|
}
|
|
8227
8580
|
function registerOrchestratorInstall(orchestrator) {
|
|
@@ -8331,7 +8684,7 @@ function registerOrchestratorInstall(orchestrator) {
|
|
|
8331
8684
|
logDir,
|
|
8332
8685
|
installBase: getInstallBase(platform, serviceName),
|
|
8333
8686
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8334
|
-
kiciVersion:
|
|
8687
|
+
kiciVersion: readKiciVersion()
|
|
8335
8688
|
});
|
|
8336
8689
|
try {
|
|
8337
8690
|
appendIndexEntry(kiciRoot, {
|
|
@@ -8837,7 +9190,7 @@ function registerAgentInstall(agent) {
|
|
|
8837
9190
|
logDir,
|
|
8838
9191
|
installBase: getInstallBase(platform, serviceName),
|
|
8839
9192
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8840
|
-
kiciVersion:
|
|
9193
|
+
kiciVersion: readKiciVersion()
|
|
8841
9194
|
});
|
|
8842
9195
|
try {
|
|
8843
9196
|
appendIndexEntry(kiciRoot, {
|
|
@@ -9625,6 +9978,9 @@ function formatSettings(s, format) {
|
|
|
9625
9978
|
lines.push(`Denied source repos: ${s.deniedRepos === null ? "(none)" : formatList(s.deniedRepos)}`);
|
|
9626
9979
|
lines.push(`Elevated authors: ${s.elevatedRepos === null ? "(none)" : formatList(s.elevatedRepos)}`);
|
|
9627
9980
|
lines.push(`Allow http registries: ${s.allowHttpNpmRegistries}`);
|
|
9981
|
+
lines.push(`User-cache quota: ${s.userCacheQuotaBytes === null ? "(cluster default)" : `${s.userCacheQuotaBytes} bytes`}`);
|
|
9982
|
+
lines.push(`User-cache TTL: ${s.userCacheTtlMs === null ? "(cluster default)" : `${s.userCacheTtlMs} ms`}`);
|
|
9983
|
+
lines.push(`Dispatch ack timeout: ${s.dispatchAckTimeoutMs === null ? "(cluster default)" : `${s.dispatchAckTimeoutMs} ms`}`);
|
|
9628
9984
|
if (s.createdAt) lines.push(`Created at: ${s.createdAt}`);
|
|
9629
9985
|
if (s.updatedAt) lines.push(`Updated at: ${s.updatedAt}`);
|
|
9630
9986
|
return lines.join("\n");
|
|
@@ -9699,6 +10055,117 @@ function registerOrgSettingsCommands(program, getClient) {
|
|
|
9699
10055
|
process.exit(1);
|
|
9700
10056
|
}
|
|
9701
10057
|
});
|
|
10058
|
+
registerUserCacheCommands(orgSettings, getClient);
|
|
10059
|
+
registerDispatchAckCommands(orgSettings, getClient);
|
|
10060
|
+
}
|
|
10061
|
+
/**
|
|
10062
|
+
* `kici-admin org-settings dispatch-ack <show|set|reset>`.
|
|
10063
|
+
*
|
|
10064
|
+
* The per-org dispatch-acknowledgment deadline (ms). A null (unset) value
|
|
10065
|
+
* means the cluster-wide default applies (`KICI_DISPATCH_ACK_TIMEOUT_MS`,
|
|
10066
|
+
* default 10s). Operators raise it on high-latency networks.
|
|
10067
|
+
*/
|
|
10068
|
+
function registerDispatchAckCommands(orgSettings, getClient) {
|
|
10069
|
+
const da = orgSettings.command("dispatch-ack").description("Manage the per-org dispatch-acknowledgment deadline (null = cluster default)");
|
|
10070
|
+
da.command("show").description("Print the current per-org dispatch-acknowledgment deadline").option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (opts) => {
|
|
10071
|
+
const customerId = resolveCustomerId(opts);
|
|
10072
|
+
try {
|
|
10073
|
+
const settings = await fetchSettings(getClient(), customerId);
|
|
10074
|
+
console.log(formatSettings(settings, opts.format));
|
|
10075
|
+
} catch (err) {
|
|
10076
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
10077
|
+
process.exit(1);
|
|
10078
|
+
}
|
|
10079
|
+
});
|
|
10080
|
+
da.command("set <value>").description("Set the per-org dispatch-acknowledgment deadline (integer milliseconds, >= 1000)").option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (value, opts) => {
|
|
10081
|
+
const n = Number(value);
|
|
10082
|
+
if (!Number.isInteger(n) || n < 1e3) {
|
|
10083
|
+
console.error("Error: value must be an integer >= 1000 (milliseconds)");
|
|
10084
|
+
process.exit(1);
|
|
10085
|
+
}
|
|
10086
|
+
const customerId = resolveCustomerId(opts);
|
|
10087
|
+
try {
|
|
10088
|
+
const updated = await patchSettings(getClient(), {
|
|
10089
|
+
customerId,
|
|
10090
|
+
dispatchAckTimeoutMs: n
|
|
10091
|
+
});
|
|
10092
|
+
console.log(formatSettings(updated, opts.format));
|
|
10093
|
+
} catch (err) {
|
|
10094
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
10095
|
+
process.exit(1);
|
|
10096
|
+
}
|
|
10097
|
+
});
|
|
10098
|
+
da.command("reset").description("Clear the per-org dispatch-ack deadline override (fall back to the cluster default)").option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (opts) => {
|
|
10099
|
+
const customerId = resolveCustomerId(opts);
|
|
10100
|
+
try {
|
|
10101
|
+
const updated = await patchSettings(getClient(), {
|
|
10102
|
+
customerId,
|
|
10103
|
+
dispatchAckTimeoutMs: null
|
|
10104
|
+
});
|
|
10105
|
+
console.log(formatSettings(updated, opts.format));
|
|
10106
|
+
} catch (err) {
|
|
10107
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
10108
|
+
process.exit(1);
|
|
10109
|
+
}
|
|
10110
|
+
});
|
|
10111
|
+
}
|
|
10112
|
+
/**
|
|
10113
|
+
* `kici-admin org-settings user-cache <show|set-quota|set-ttl|reset-quota|reset-ttl>`.
|
|
10114
|
+
*
|
|
10115
|
+
* The per-org byte quota and per-entry TTL for the user-facing cache. A null
|
|
10116
|
+
* (unset) value means the cluster-wide default applies (the
|
|
10117
|
+
* `KICI_USER_CACHE_QUOTA_BYTES` / `KICI_USER_CACHE_TTL_MS` env vars).
|
|
10118
|
+
*/
|
|
10119
|
+
function registerUserCacheCommands(orgSettings, getClient) {
|
|
10120
|
+
const uc = orgSettings.command("user-cache").description("Manage per-org user-facing cache quota + entry TTL (null = cluster default)");
|
|
10121
|
+
uc.command("show").description("Print the current per-org user-cache quota + TTL settings").option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (opts) => {
|
|
10122
|
+
const customerId = resolveCustomerId(opts);
|
|
10123
|
+
try {
|
|
10124
|
+
const settings = await fetchSettings(getClient(), customerId);
|
|
10125
|
+
console.log(formatSettings(settings, opts.format));
|
|
10126
|
+
} catch (err) {
|
|
10127
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
10128
|
+
process.exit(1);
|
|
10129
|
+
}
|
|
10130
|
+
});
|
|
10131
|
+
registerUserCacheSetter(uc, getClient, "quota");
|
|
10132
|
+
registerUserCacheSetter(uc, getClient, "ttl");
|
|
10133
|
+
}
|
|
10134
|
+
/** Register `set-<knob>` and `reset-<knob>` for the byte-quota / ms-TTL knobs. */
|
|
10135
|
+
function registerUserCacheSetter(uc, getClient, knob) {
|
|
10136
|
+
const field = knob === "quota" ? "userCacheQuotaBytes" : "userCacheTtlMs";
|
|
10137
|
+
const unit = knob === "quota" ? "bytes" : "milliseconds";
|
|
10138
|
+
uc.command(`set-${knob} <value>`).description(`Set the per-org user-cache ${knob} (positive integer ${unit})`).option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (value, opts) => {
|
|
10139
|
+
const n = Number(value);
|
|
10140
|
+
if (!Number.isInteger(n) || n <= 0) {
|
|
10141
|
+
console.error(`Error: value must be a positive integer (${unit})`);
|
|
10142
|
+
process.exit(1);
|
|
10143
|
+
}
|
|
10144
|
+
const customerId = resolveCustomerId(opts);
|
|
10145
|
+
try {
|
|
10146
|
+
const updated = await patchSettings(getClient(), {
|
|
10147
|
+
customerId,
|
|
10148
|
+
[field]: n
|
|
10149
|
+
});
|
|
10150
|
+
console.log(formatSettings(updated, opts.format));
|
|
10151
|
+
} catch (err) {
|
|
10152
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
10153
|
+
process.exit(1);
|
|
10154
|
+
}
|
|
10155
|
+
});
|
|
10156
|
+
uc.command(`reset-${knob}`).description(`Clear the per-org user-cache ${knob} override (fall back to the cluster default)`).option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (opts) => {
|
|
10157
|
+
const customerId = resolveCustomerId(opts);
|
|
10158
|
+
try {
|
|
10159
|
+
const updated = await patchSettings(getClient(), {
|
|
10160
|
+
customerId,
|
|
10161
|
+
[field]: null
|
|
10162
|
+
});
|
|
10163
|
+
console.log(formatSettings(updated, opts.format));
|
|
10164
|
+
} catch (err) {
|
|
10165
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
10166
|
+
process.exit(1);
|
|
10167
|
+
}
|
|
10168
|
+
});
|
|
9702
10169
|
}
|
|
9703
10170
|
/** Register `<prefix>-add` and `<prefix>-remove` commands bound to a list field. */
|
|
9704
10171
|
function registerListMutators(gw, getClient, prefix, field) {
|
|
@@ -10120,8 +10587,10 @@ function printShowEnvironment(res) {
|
|
|
10120
10587
|
}
|
|
10121
10588
|
function registerEnvironmentCommands(program, getClient) {
|
|
10122
10589
|
const env = program.command("environment").description("Environment management (dual-mode)");
|
|
10123
|
-
env.command("create").description("Upsert an environment (idempotent by org+name)").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Environment name").option("--type <t>", "Environment type (fixed|glob|template)", "fixed").option("--enabled <bool>", "Enabled flag (true|false)", "true").option("--branch-restrictions <json>", "JSON array of allowed branches (e.g. '[\"main\"]')").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (or empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
10590
|
+
env.command("create").description("Upsert an environment (idempotent by org+name)").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Environment name").option("--type <t>", "Environment type (fixed|glob|template)", "fixed").option("--glob-pattern <pattern>", "Glob pattern matched against declared environment names (required with --type glob)").option("--enabled <bool>", "Enabled flag (true|false)", "true").option("--branch-restrictions <json>", "JSON array of allowed branches (e.g. '[\"main\"]')").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (or empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
10124
10591
|
try {
|
|
10592
|
+
if (opts.type === "glob" && !opts.globPattern) throw new Error("--type glob requires --glob-pattern <pattern>");
|
|
10593
|
+
if (opts.type !== "glob" && opts.globPattern !== void 0) throw new Error("--glob-pattern requires --type glob");
|
|
10125
10594
|
const branchRestrictions = parseJsonOption(opts.branchRestrictions, "--branch-restrictions");
|
|
10126
10595
|
const requiredReviewers = parseCsvOption(opts.requiredReviewers);
|
|
10127
10596
|
const waitTimerSeconds = parseIntOption$3(opts.waitTimer, "--wait-timer");
|
|
@@ -10132,6 +10601,7 @@ function registerEnvironmentCommands(program, getClient) {
|
|
|
10132
10601
|
name: opts.name,
|
|
10133
10602
|
type: opts.type,
|
|
10134
10603
|
enabled,
|
|
10604
|
+
globPattern: opts.globPattern,
|
|
10135
10605
|
branchRestrictions,
|
|
10136
10606
|
requiredReviewers,
|
|
10137
10607
|
waitTimerSeconds,
|
|
@@ -10166,7 +10636,7 @@ function registerEnvironmentCommands(program, getClient) {
|
|
|
10166
10636
|
process.exit(1);
|
|
10167
10637
|
}
|
|
10168
10638
|
});
|
|
10169
|
-
env.command("set-policy").description("Update policy fields on an environment (only provided fields change)").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Environment name").option("--branch-restrictions <json>", "JSON array of allowed branches").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted, or \"null\" to clear)").option("--enabled <bool>", "Enabled flag (true|false)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
10639
|
+
env.command("set-policy").description("Update policy fields on an environment (only provided fields change)").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Environment name").option("--branch-restrictions <json>", "JSON array of allowed branches").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted, or \"null\" to clear)").option("--enabled <bool>", "Enabled flag (true|false)").option("--allow-local-execution <bool>", "Allow CLI/test runs to resolve this env (true|false)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
10170
10640
|
try {
|
|
10171
10641
|
const payload = {
|
|
10172
10642
|
orgId: opts.org,
|
|
@@ -10178,6 +10648,7 @@ function registerEnvironmentCommands(program, getClient) {
|
|
|
10178
10648
|
if (opts.holdExpiry !== void 0) payload.holdExpirySeconds = parseIntOption$3(opts.holdExpiry, "--hold-expiry");
|
|
10179
10649
|
if (opts.minimumTrust !== void 0) payload.minimumTrust = opts.minimumTrust === "null" ? null : opts.minimumTrust;
|
|
10180
10650
|
if (opts.enabled !== void 0) payload.enabled = opts.enabled === "false" ? false : true;
|
|
10651
|
+
if (opts.allowLocalExecution !== void 0) payload.allowLocalExecution = opts.allowLocalExecution === "false" ? false : true;
|
|
10181
10652
|
const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
|
|
10182
10653
|
if (dbUrl) await setEnvironmentPolicyDirect(dbUrl, payload);
|
|
10183
10654
|
else await getClient().patch(`/api/v1/admin/environments/${encodeURIComponent(opts.env)}/policy`, payload);
|
|
@@ -10213,6 +10684,23 @@ function registerEnvironmentCommands(program, getClient) {
|
|
|
10213
10684
|
process.exit(1);
|
|
10214
10685
|
}
|
|
10215
10686
|
});
|
|
10687
|
+
env.command("delete").description("Delete an environment (cascades bindings, variables, overrides; held-run history survives; pending held runs block with a clear error, resolved holds do not)").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Environment name").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
10688
|
+
try {
|
|
10689
|
+
const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
|
|
10690
|
+
let deleted;
|
|
10691
|
+
if (dbUrl) ({deleted} = await deleteEnvironmentDirect(dbUrl, {
|
|
10692
|
+
orgId: opts.org,
|
|
10693
|
+
name: opts.name
|
|
10694
|
+
}));
|
|
10695
|
+
else deleted = (await getClient().delete(`/api/v1/admin/environments/${encodeURIComponent(opts.name)}?orgId=${encodeURIComponent(opts.org)}`)).deleted;
|
|
10696
|
+
if (!deleted) throw new Error(`environment not found (org=${opts.org}, name=${opts.name})`);
|
|
10697
|
+
if (opts.json) console.log(JSON.stringify({ deleted: true }));
|
|
10698
|
+
else console.log(`environment delete: deleted=true${dbUrl ? " (direct)" : ""}`);
|
|
10699
|
+
} catch (err) {
|
|
10700
|
+
console.error(`Error: ${toErrorMessage(err)}`);
|
|
10701
|
+
process.exit(1);
|
|
10702
|
+
}
|
|
10703
|
+
});
|
|
10216
10704
|
env.command("create-template").description("Create or update an environment template + its seed variables").requiredOption("--org <id>", "Org ID").requiredOption("--template <name>", "Template name").option("--type <t>", "Environment type (defaults to \"template\")", "template").option("--branch-restrictions <json>", "JSON array of allowed branches").option("--required-reviewers <csv>", "CSV of required reviewer user IDs").option("--wait-timer <seconds>", "Wait timer (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted)").option("--variables <json>", "JSON object of env variables to seed (e.g. '{\"K\":\"V\"}')").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
|
|
10217
10705
|
try {
|
|
10218
10706
|
const branchRestrictions = parseJsonOption(opts.branchRestrictions, "--branch-restrictions");
|