@kici-dev/shared 0.1.15 → 0.1.17
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/cold-store/bucket.js +1 -1
- package/dist/cold-store/chunk-encoder.js +1 -1
- package/dist/cold-store/chunk-id.js +1 -1
- package/dist/cold-store/cold-store.js +1 -1
- package/dist/cold-store/config.js +1 -1
- package/dist/cold-store/index.js +1 -1
- package/dist/cold-store/key.js +1 -1
- package/dist/cold-store/lru.js +1 -1
- package/dist/cold-store/manifest.js +1 -1
- package/dist/cold-store/metrics.js +1 -1
- package/dist/cold-store/table-adapter.js +1 -1
- package/dist/cold-store/types.js +1 -1
- package/dist/db-admin.d.ts +11 -6
- package/dist/db-admin.js +10 -8
- package/dist/db-collation.js +1 -1
- package/dist/db.js +1 -1
- package/dist/diagnostics/bundle-archive.d.ts +28 -0
- package/dist/diagnostics/bundle-archive.js +141 -0
- package/dist/diagnostics/bundle-archive.test.d.ts +2 -0
- package/dist/diagnostics/bundle-chunks.d.ts +46 -0
- package/dist/diagnostics/bundle-chunks.js +111 -0
- package/dist/diagnostics/bundle-chunks.test.d.ts +2 -0
- package/dist/env/allowlist.d.ts +5 -1
- package/dist/env/allowlist.js +7 -3
- package/dist/env/define-env.js +1 -1
- package/dist/env/index.js +1 -1
- package/dist/env/logger-env.js +1 -1
- package/dist/graceful-shutdown.js +1 -1
- package/dist/idempotency-env-diff.js +1 -1
- package/dist/idempotency-files.js +1 -1
- package/dist/idempotency-yaml-diff.js +1 -1
- package/dist/idempotency.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -2
- package/dist/package-manager-types.js +1 -1
- package/dist/package-manager.js +1 -1
- package/dist/reconnect-delay.js +1 -1
- package/dist/ring-buffer.js +1 -1
- package/dist/routes/health.js +1 -1
- package/dist/routes/metrics.js +1 -1
- package/dist/s3-client.js +1 -1
- package/dist/telemetry/index.js +1 -1
- package/dist/telemetry/init.js +1 -1
- package/dist/telemetry/metrics.js +1 -1
- package/dist/tool-check.js +1 -1
- package/dist/ts-loader-hook.js +1 -1
- package/package.json +4 -2
- package/sbom.spdx.json +2338 -510
- /package/dist/{chunk-gOLHoazu.js → chunk-BTugEXQM.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
import { createS3Client } from "../s3-client.js";
|
|
3
3
|
import { chunkObjectKey, encodeKeySegment, tablePrefix, tenantDayPrefix } from "./key.js";
|
|
4
4
|
import { coldDaysToBucket, isLongerColdRetention } from "./bucket.js";
|
package/dist/cold-store/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
import { chunkObjectKey, encodeKeySegment, tablePrefix, tenantDayBucketPrefix, tenantDayPrefix } from "./key.js";
|
|
3
3
|
import { COLD_BUCKET_NAMES, coldDaysToBucket, isLongerColdRetention } from "./bucket.js";
|
|
4
4
|
import { computeChunkId } from "./chunk-id.js";
|
package/dist/cold-store/key.js
CHANGED
package/dist/cold-store/lru.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
export {};
|
package/dist/cold-store/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
export {};
|
package/dist/db-admin.d.ts
CHANGED
|
@@ -553,8 +553,8 @@ export interface EmitKiciEventOpts {
|
|
|
553
553
|
* e2e helpers to simulate what `agent ctx.emit()` does from inside a step
|
|
554
554
|
* execution — but without needing an actual running step. Returns the event id.
|
|
555
555
|
*
|
|
556
|
-
* Fixed `chain_depth=0` and `expires_at=NOW() + 1h` match
|
|
557
|
-
* in e2e/helpers/
|
|
556
|
+
* Fixed `chain_depth=0` and `expires_at=NOW() + 1h` match emitLocalEvent()
|
|
557
|
+
* in e2e/helpers/local-webhook.ts, which this helper supersedes.
|
|
558
558
|
*/
|
|
559
559
|
export declare function emitKiciEventDirect(databaseUrl: string, opts: EmitKiciEventOpts): Promise<{
|
|
560
560
|
eventId: string;
|
|
@@ -567,18 +567,23 @@ export interface SeedGenericWebhookSourceOpts {
|
|
|
567
567
|
/** Pre-computed routing key (caller uses `generic:${orgId}:${name}`) */
|
|
568
568
|
routingKey: string;
|
|
569
569
|
verificationMethod?: string;
|
|
570
|
-
/** 'generic' (Stripe-shaped) or '
|
|
571
|
-
|
|
570
|
+
/** 'generic' (Stripe-shaped) or 'local' (github-shaped via LocalWebhookNormalizer,
|
|
571
|
+
* a git repo present on the agent filesystem cloned via file://). */
|
|
572
|
+
providerType?: 'generic' | 'local';
|
|
573
|
+
/** For `providerType='local'`: the per-source `{ repoBasePath, cloneUrlBase? }`
|
|
574
|
+
* stored in `git_config`. The orchestrator reads `repoBasePath` from this row
|
|
575
|
+
* at registration time to build the local provider bundle. */
|
|
576
|
+
gitConfig?: Record<string, unknown>;
|
|
572
577
|
}
|
|
573
578
|
/**
|
|
574
|
-
* Upsert a row into `generic_webhook_sources
|
|
579
|
+
* Upsert a row into `generic_webhook_sources`. Uses
|
|
575
580
|
* `ON CONFLICT (routing_key) DO UPDATE` so warm-start mode (where the source
|
|
576
581
|
* may already exist from a prior run) is idempotent.
|
|
577
582
|
*
|
|
578
583
|
* IMPORTANT: callers must invoke this BEFORE the orchestrator starts, because
|
|
579
584
|
* GenericSourceManager caches sources at boot and does not reload them later.
|
|
580
585
|
* This helper supersedes seedGenericWebhookSource() in
|
|
581
|
-
* e2e/helpers/
|
|
586
|
+
* e2e/helpers/local-webhook.ts.
|
|
582
587
|
*/
|
|
583
588
|
export declare function seedGenericWebhookSourceDirect(databaseUrl: string, opts: SeedGenericWebhookSourceOpts): Promise<void>;
|
|
584
589
|
/**
|
package/dist/db-admin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-BTugEXQM.js";
|
|
2
2
|
import { createPool } from "./db.js";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import pg from "pg";
|
|
@@ -992,8 +992,8 @@ async function resetRaftStateDirect(databaseUrl) {
|
|
|
992
992
|
* e2e helpers to simulate what `agent ctx.emit()` does from inside a step
|
|
993
993
|
* execution — but without needing an actual running step. Returns the event id.
|
|
994
994
|
*
|
|
995
|
-
* Fixed `chain_depth=0` and `expires_at=NOW() + 1h` match
|
|
996
|
-
* in e2e/helpers/
|
|
995
|
+
* Fixed `chain_depth=0` and `expires_at=NOW() + 1h` match emitLocalEvent()
|
|
996
|
+
* in e2e/helpers/local-webhook.ts, which this helper supersedes.
|
|
997
997
|
*/
|
|
998
998
|
async function emitKiciEventDirect(databaseUrl, opts) {
|
|
999
999
|
const pool = createPool(databaseUrl);
|
|
@@ -1016,14 +1016,14 @@ async function emitKiciEventDirect(databaseUrl, opts) {
|
|
|
1016
1016
|
}
|
|
1017
1017
|
}
|
|
1018
1018
|
/**
|
|
1019
|
-
* Upsert a row into `generic_webhook_sources
|
|
1019
|
+
* Upsert a row into `generic_webhook_sources`. Uses
|
|
1020
1020
|
* `ON CONFLICT (routing_key) DO UPDATE` so warm-start mode (where the source
|
|
1021
1021
|
* may already exist from a prior run) is idempotent.
|
|
1022
1022
|
*
|
|
1023
1023
|
* IMPORTANT: callers must invoke this BEFORE the orchestrator starts, because
|
|
1024
1024
|
* GenericSourceManager caches sources at boot and does not reload them later.
|
|
1025
1025
|
* This helper supersedes seedGenericWebhookSource() in
|
|
1026
|
-
* e2e/helpers/
|
|
1026
|
+
* e2e/helpers/local-webhook.ts.
|
|
1027
1027
|
*/
|
|
1028
1028
|
async function seedGenericWebhookSourceDirect(databaseUrl, opts) {
|
|
1029
1029
|
const pool = createPool(databaseUrl);
|
|
@@ -1033,14 +1033,15 @@ async function seedGenericWebhookSourceDirect(databaseUrl, opts) {
|
|
|
1033
1033
|
verification_method, verification_config,
|
|
1034
1034
|
event_type_header, dedup_window_seconds,
|
|
1035
1035
|
max_payload_bytes, rate_limit_rpm, enabled,
|
|
1036
|
-
provider_type
|
|
1037
|
-
) VALUES ($1, $2, $3, $4, $5, '{}', 'x-event-type', 300, 10485760, 600, true, $6)
|
|
1036
|
+
provider_type, git_config
|
|
1037
|
+
) VALUES ($1, $2, $3, $4, $5, '{}', 'x-event-type', 300, 10485760, 600, true, $6, $7::jsonb)
|
|
1038
1038
|
ON CONFLICT (routing_key) DO UPDATE SET
|
|
1039
1039
|
customer_id = EXCLUDED.customer_id,
|
|
1040
1040
|
name = EXCLUDED.name,
|
|
1041
1041
|
verification_method = EXCLUDED.verification_method,
|
|
1042
1042
|
verification_config = EXCLUDED.verification_config,
|
|
1043
1043
|
provider_type = EXCLUDED.provider_type,
|
|
1044
|
+
git_config = EXCLUDED.git_config,
|
|
1044
1045
|
enabled = true,
|
|
1045
1046
|
deleted_at = NULL,
|
|
1046
1047
|
updated_at = NOW()`, [
|
|
@@ -1049,7 +1050,8 @@ async function seedGenericWebhookSourceDirect(databaseUrl, opts) {
|
|
|
1049
1050
|
opts.name,
|
|
1050
1051
|
opts.routingKey,
|
|
1051
1052
|
opts.verificationMethod ?? "none",
|
|
1052
|
-
opts.providerType ?? "generic"
|
|
1053
|
+
opts.providerType ?? "generic",
|
|
1054
|
+
opts.gitConfig ? JSON.stringify(opts.gitConfig) : null
|
|
1053
1055
|
]);
|
|
1054
1056
|
} finally {
|
|
1055
1057
|
await pool.end();
|
package/dist/db-collation.js
CHANGED
package/dist/db.js
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared debug-bundle archive primitives.
|
|
3
|
+
*
|
|
4
|
+
* Allowlist config redaction and windowed log-file archiving, used by the
|
|
5
|
+
* orchestrator's in-process bundle writer, the kici-admin CLI's local bundle,
|
|
6
|
+
* and the agent's fleet mini-bundle assembler. Keeping one copy means a node
|
|
7
|
+
* cannot drift from the redaction posture of its peers.
|
|
8
|
+
*/
|
|
9
|
+
import type archiver from 'archiver';
|
|
10
|
+
/** Maximum total log bytes to include in bundle (50MB). */
|
|
11
|
+
export declare const MAX_LOG_BYTES: number;
|
|
12
|
+
/**
|
|
13
|
+
* Redact config values using allowlist approach.
|
|
14
|
+
* Only known-safe fields are preserved; everything else becomes "****".
|
|
15
|
+
*/
|
|
16
|
+
export declare function redactConfig(obj: unknown, parentKey?: string): unknown;
|
|
17
|
+
/**
|
|
18
|
+
* Add log files from logDir to the archive, respecting MAX_LOG_BYTES cap
|
|
19
|
+
* and the logWindow time filter. Matches any `*.log` file in the directory,
|
|
20
|
+
* so the per-instance filename pattern produced by
|
|
21
|
+
* `buildLogFilename()` is picked up without additional configuration.
|
|
22
|
+
*
|
|
23
|
+
* Exported for reuse by the `kici-admin debug-bundle` CLI command, which
|
|
24
|
+
* runs outside the orchestrator process but still needs to include the
|
|
25
|
+
* same log files in its locally-assembled bundle.
|
|
26
|
+
*/
|
|
27
|
+
export declare function addLogsToArchive(archive: archiver.Archiver, logDir: string, logWindowHours: number): Promise<void>;
|
|
28
|
+
//# sourceMappingURL=bundle-archive.d.ts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
//#region src/diagnostics/bundle-archive.ts
|
|
5
|
+
/**
|
|
6
|
+
* Shared debug-bundle archive primitives.
|
|
7
|
+
*
|
|
8
|
+
* Allowlist config redaction and windowed log-file archiving, used by the
|
|
9
|
+
* orchestrator's in-process bundle writer, the kici-admin CLI's local bundle,
|
|
10
|
+
* and the agent's fleet mini-bundle assembler. Keeping one copy means a node
|
|
11
|
+
* cannot drift from the redaction posture of its peers.
|
|
12
|
+
*/
|
|
13
|
+
/** Maximum total log bytes to include in bundle (50MB). */
|
|
14
|
+
const MAX_LOG_BYTES = 50 * 1024 * 1024;
|
|
15
|
+
/**
|
|
16
|
+
* Config field names that are safe to include unredacted.
|
|
17
|
+
* Everything else gets replaced with "****".
|
|
18
|
+
*/
|
|
19
|
+
const SAFE_CONFIG_KEYS = new Set([
|
|
20
|
+
"mode",
|
|
21
|
+
"host",
|
|
22
|
+
"port",
|
|
23
|
+
"logLevel",
|
|
24
|
+
"region",
|
|
25
|
+
"environment",
|
|
26
|
+
"name",
|
|
27
|
+
"label",
|
|
28
|
+
"labels",
|
|
29
|
+
"enabled",
|
|
30
|
+
"disabled",
|
|
31
|
+
"timeout",
|
|
32
|
+
"interval",
|
|
33
|
+
"maxRetries",
|
|
34
|
+
"retries",
|
|
35
|
+
"workers",
|
|
36
|
+
"concurrency",
|
|
37
|
+
"maxConcurrency",
|
|
38
|
+
"batchSize",
|
|
39
|
+
"bufferSize",
|
|
40
|
+
"warmPool",
|
|
41
|
+
"cooldown",
|
|
42
|
+
"type",
|
|
43
|
+
"provider",
|
|
44
|
+
"scaler",
|
|
45
|
+
"driver",
|
|
46
|
+
"backend",
|
|
47
|
+
"protocol",
|
|
48
|
+
"scheme",
|
|
49
|
+
"path",
|
|
50
|
+
"basePath",
|
|
51
|
+
"metricsPath",
|
|
52
|
+
"healthPath",
|
|
53
|
+
"logFormat",
|
|
54
|
+
"logFile",
|
|
55
|
+
"logDir",
|
|
56
|
+
"dataDir",
|
|
57
|
+
"version",
|
|
58
|
+
"debug",
|
|
59
|
+
"verbose",
|
|
60
|
+
"quiet",
|
|
61
|
+
"tls",
|
|
62
|
+
"cors",
|
|
63
|
+
"rateLimiting",
|
|
64
|
+
"maxConnections",
|
|
65
|
+
"poolSize",
|
|
66
|
+
"minPool",
|
|
67
|
+
"maxPool",
|
|
68
|
+
"idleTimeout",
|
|
69
|
+
"connectTimeout",
|
|
70
|
+
"requestTimeout",
|
|
71
|
+
"shutdownTimeout",
|
|
72
|
+
"gracefulShutdown"
|
|
73
|
+
]);
|
|
74
|
+
/**
|
|
75
|
+
* Redact config values using allowlist approach.
|
|
76
|
+
* Only known-safe fields are preserved; everything else becomes "****".
|
|
77
|
+
*/
|
|
78
|
+
function redactConfig(obj, parentKey) {
|
|
79
|
+
if (obj === null || obj === void 0) return obj;
|
|
80
|
+
if (Array.isArray(obj)) return obj.map((item) => redactConfig(item, parentKey));
|
|
81
|
+
if (typeof obj === "object") {
|
|
82
|
+
const result = {};
|
|
83
|
+
for (const [key, value] of Object.entries(obj)) result[key] = redactConfig(value, key);
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
if (typeof obj === "string" && parentKey && !SAFE_CONFIG_KEYS.has(parentKey)) return "****";
|
|
87
|
+
if (typeof obj === "number" || typeof obj === "boolean") return obj;
|
|
88
|
+
if (typeof obj === "string" && parentKey && SAFE_CONFIG_KEYS.has(parentKey)) return obj;
|
|
89
|
+
if (typeof obj === "string") return "****";
|
|
90
|
+
return obj;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Add log files from logDir to the archive, respecting MAX_LOG_BYTES cap
|
|
94
|
+
* and the logWindow time filter. Matches any `*.log` file in the directory,
|
|
95
|
+
* so the per-instance filename pattern produced by
|
|
96
|
+
* `buildLogFilename()` is picked up without additional configuration.
|
|
97
|
+
*
|
|
98
|
+
* Exported for reuse by the `kici-admin debug-bundle` CLI command, which
|
|
99
|
+
* runs outside the orchestrator process but still needs to include the
|
|
100
|
+
* same log files in its locally-assembled bundle.
|
|
101
|
+
*/
|
|
102
|
+
async function addLogsToArchive(archive, logDir, logWindowHours) {
|
|
103
|
+
const cutoff = Date.now() - logWindowHours * 60 * 60 * 1e3;
|
|
104
|
+
const entries = fs.readdirSync(logDir).filter((f) => {
|
|
105
|
+
if (!f.endsWith(".log")) return false;
|
|
106
|
+
return fs.statSync(path.join(logDir, f)).mtimeMs >= cutoff;
|
|
107
|
+
});
|
|
108
|
+
entries.sort((a, b) => {
|
|
109
|
+
const aStat = fs.statSync(path.join(logDir, a));
|
|
110
|
+
return fs.statSync(path.join(logDir, b)).mtimeMs - aStat.mtimeMs;
|
|
111
|
+
});
|
|
112
|
+
let totalBytes = 0;
|
|
113
|
+
let totalLines = 0;
|
|
114
|
+
let errors = 0;
|
|
115
|
+
let warnings = 0;
|
|
116
|
+
for (const entry of entries) {
|
|
117
|
+
const filePath = path.join(logDir, entry);
|
|
118
|
+
const stat = fs.statSync(filePath);
|
|
119
|
+
if (totalBytes + stat.size > 52428800) break;
|
|
120
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
121
|
+
archive.append(content, { name: `logs/${entry}` });
|
|
122
|
+
totalBytes += stat.size;
|
|
123
|
+
const lines = content.split("\n");
|
|
124
|
+
totalLines += lines.length;
|
|
125
|
+
for (const line of lines) {
|
|
126
|
+
if (/\berror\b/i.test(line)) errors++;
|
|
127
|
+
if (/\bwarn(ing)?\b/i.test(line)) warnings++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const summary = {
|
|
131
|
+
totalLines,
|
|
132
|
+
errors,
|
|
133
|
+
warnings,
|
|
134
|
+
totalBytes
|
|
135
|
+
};
|
|
136
|
+
archive.append(JSON.stringify(summary, null, 2), { name: "logs/summary.json" });
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
export { MAX_LOG_BYTES, addLogsToArchive, redactConfig };
|
|
140
|
+
|
|
141
|
+
//# sourceMappingURL=bundle-archive.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel-agnostic chunked transfer for fleet bundle ZIPs.
|
|
3
|
+
*
|
|
4
|
+
* The WS frame cap (WS_MAX_PAYLOAD_BYTES = 25 MiB) forbids shipping a whole
|
|
5
|
+
* bundle in one frame, so a bundle Buffer is split into ordered base64 frames
|
|
6
|
+
* (~85 KiB raw each, matching the webhook-relay frame size) and reassembled by
|
|
7
|
+
* the receiver. Used on both the orchestrator-agent and peer channels.
|
|
8
|
+
*/
|
|
9
|
+
/** Raw bytes per chunk before base64 (matches webhook-relay's ~85 KiB frames). */
|
|
10
|
+
export declare const FLEET_CHUNK_BYTES: number;
|
|
11
|
+
export interface BundleChunkFrame {
|
|
12
|
+
seq: number;
|
|
13
|
+
dataB64: string;
|
|
14
|
+
isLast: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Split a Buffer into ordered base64 frames. An empty buffer yields one final frame. */
|
|
17
|
+
export declare function chunkBuffer(buf: Buffer, chunkBytes?: number): BundleChunkFrame[];
|
|
18
|
+
/**
|
|
19
|
+
* Correlation core for any "send a request, await a chunked response" channel.
|
|
20
|
+
*
|
|
21
|
+
* Key-agnostic so both the orchestrator-agent channel (keyed by requestId) and
|
|
22
|
+
* the peer channel (keyed by messageId) share one implementation. Pending
|
|
23
|
+
* requests reject on timeout, on an error frame, or on disconnect. No
|
|
24
|
+
* orchestrator-initiated request/response primitive existed before fleet
|
|
25
|
+
* collection; this is it.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ChunkRequestWaiter {
|
|
28
|
+
private pending;
|
|
29
|
+
/** Register a pending request `id` that rejects after `timeoutMs`. */
|
|
30
|
+
add(id: string, timeoutMs: number): Promise<Buffer>;
|
|
31
|
+
/** Accumulate a chunk; resolves the pending request on the final frame. */
|
|
32
|
+
onChunk(id: string, seq: number, dataB64: string, isLast: boolean): void;
|
|
33
|
+
/** Reject the pending request `id` with `message`. */
|
|
34
|
+
onError(id: string, message: string): void;
|
|
35
|
+
/** Reject every pending request — used when the underlying connection drops. */
|
|
36
|
+
rejectAll(reason: string): void;
|
|
37
|
+
}
|
|
38
|
+
/** Reassembles ordered frames into a Buffer. Throws on gaps/reordering. */
|
|
39
|
+
export declare class BundleChunkAssembler {
|
|
40
|
+
private parts;
|
|
41
|
+
private next;
|
|
42
|
+
private done;
|
|
43
|
+
/** Returns the assembled Buffer on the final frame, otherwise undefined. */
|
|
44
|
+
accept(seq: number, dataB64: string, isLast: boolean): Buffer | undefined;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=bundle-chunks.d.ts.map
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
|
+
//#region src/diagnostics/bundle-chunks.ts
|
|
3
|
+
/**
|
|
4
|
+
* Channel-agnostic chunked transfer for fleet bundle ZIPs.
|
|
5
|
+
*
|
|
6
|
+
* The WS frame cap (WS_MAX_PAYLOAD_BYTES = 25 MiB) forbids shipping a whole
|
|
7
|
+
* bundle in one frame, so a bundle Buffer is split into ordered base64 frames
|
|
8
|
+
* (~85 KiB raw each, matching the webhook-relay frame size) and reassembled by
|
|
9
|
+
* the receiver. Used on both the orchestrator-agent and peer channels.
|
|
10
|
+
*/
|
|
11
|
+
/** Raw bytes per chunk before base64 (matches webhook-relay's ~85 KiB frames). */
|
|
12
|
+
const FLEET_CHUNK_BYTES = 85 * 1024;
|
|
13
|
+
/** Split a Buffer into ordered base64 frames. An empty buffer yields one final frame. */
|
|
14
|
+
function chunkBuffer(buf, chunkBytes = FLEET_CHUNK_BYTES) {
|
|
15
|
+
const frames = [];
|
|
16
|
+
if (buf.length === 0) return [{
|
|
17
|
+
seq: 0,
|
|
18
|
+
dataB64: "",
|
|
19
|
+
isLast: true
|
|
20
|
+
}];
|
|
21
|
+
for (let offset = 0, seq = 0; offset < buf.length; offset += chunkBytes, seq++) {
|
|
22
|
+
const slice = buf.subarray(offset, Math.min(offset + chunkBytes, buf.length));
|
|
23
|
+
frames.push({
|
|
24
|
+
seq,
|
|
25
|
+
dataB64: slice.toString("base64"),
|
|
26
|
+
isLast: offset + chunkBytes >= buf.length
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return frames;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Correlation core for any "send a request, await a chunked response" channel.
|
|
33
|
+
*
|
|
34
|
+
* Key-agnostic so both the orchestrator-agent channel (keyed by requestId) and
|
|
35
|
+
* the peer channel (keyed by messageId) share one implementation. Pending
|
|
36
|
+
* requests reject on timeout, on an error frame, or on disconnect. No
|
|
37
|
+
* orchestrator-initiated request/response primitive existed before fleet
|
|
38
|
+
* collection; this is it.
|
|
39
|
+
*/
|
|
40
|
+
var ChunkRequestWaiter = class {
|
|
41
|
+
pending = /* @__PURE__ */ new Map();
|
|
42
|
+
/** Register a pending request `id` that rejects after `timeoutMs`. */
|
|
43
|
+
add(id, timeoutMs) {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
const timer = setTimeout(() => {
|
|
46
|
+
this.pending.delete(id);
|
|
47
|
+
reject(/* @__PURE__ */ new Error(`chunk request ${id} timed out after ${timeoutMs}ms`));
|
|
48
|
+
}, timeoutMs);
|
|
49
|
+
this.pending.set(id, {
|
|
50
|
+
asm: new BundleChunkAssembler(),
|
|
51
|
+
resolve,
|
|
52
|
+
reject,
|
|
53
|
+
timer
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Accumulate a chunk; resolves the pending request on the final frame. */
|
|
58
|
+
onChunk(id, seq, dataB64, isLast) {
|
|
59
|
+
const p = this.pending.get(id);
|
|
60
|
+
if (!p) return;
|
|
61
|
+
try {
|
|
62
|
+
const done = p.asm.accept(seq, dataB64, isLast);
|
|
63
|
+
if (done) {
|
|
64
|
+
clearTimeout(p.timer);
|
|
65
|
+
this.pending.delete(id);
|
|
66
|
+
p.resolve(done);
|
|
67
|
+
}
|
|
68
|
+
} catch (err) {
|
|
69
|
+
clearTimeout(p.timer);
|
|
70
|
+
this.pending.delete(id);
|
|
71
|
+
p.reject(err instanceof Error ? err : new Error(String(err)));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Reject the pending request `id` with `message`. */
|
|
75
|
+
onError(id, message) {
|
|
76
|
+
const p = this.pending.get(id);
|
|
77
|
+
if (!p) return;
|
|
78
|
+
clearTimeout(p.timer);
|
|
79
|
+
this.pending.delete(id);
|
|
80
|
+
p.reject(new Error(message));
|
|
81
|
+
}
|
|
82
|
+
/** Reject every pending request — used when the underlying connection drops. */
|
|
83
|
+
rejectAll(reason) {
|
|
84
|
+
for (const [, p] of this.pending) {
|
|
85
|
+
clearTimeout(p.timer);
|
|
86
|
+
p.reject(new Error(reason));
|
|
87
|
+
}
|
|
88
|
+
this.pending.clear();
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
/** Reassembles ordered frames into a Buffer. Throws on gaps/reordering. */
|
|
92
|
+
var BundleChunkAssembler = class {
|
|
93
|
+
parts = [];
|
|
94
|
+
next = 0;
|
|
95
|
+
done = false;
|
|
96
|
+
/** Returns the assembled Buffer on the final frame, otherwise undefined. */
|
|
97
|
+
accept(seq, dataB64, isLast) {
|
|
98
|
+
if (this.done) throw new Error("bundle chunk received after final frame");
|
|
99
|
+
if (seq !== this.next) throw new Error(`out-of-order bundle chunk: expected ${this.next}, got ${seq}`);
|
|
100
|
+
this.next++;
|
|
101
|
+
this.parts.push(Buffer.from(dataB64, "base64"));
|
|
102
|
+
if (isLast) {
|
|
103
|
+
this.done = true;
|
|
104
|
+
return Buffer.concat(this.parts);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
//#endregion
|
|
109
|
+
export { BundleChunkAssembler, ChunkRequestWaiter, FLEET_CHUNK_BYTES, chunkBuffer };
|
|
110
|
+
|
|
111
|
+
//# sourceMappingURL=bundle-chunks.js.map
|
package/dist/env/allowlist.d.ts
CHANGED
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
* - `KICI_*` — every project-internal env var.
|
|
40
40
|
* - OS basics — NODE_ENV, HOME, PATH, TZ, LANG, TMPDIR,
|
|
41
41
|
* USER, USERNAME, SHELL, COMSPEC, PWD, OLDPWD,
|
|
42
|
-
* HOSTNAME
|
|
42
|
+
* HOSTNAME, PROCESSOR_ARCHITECTURE (Windows arch
|
|
43
|
+
* hint the agent reads to pick the mise zip).
|
|
43
44
|
* - Terminal / display — COLUMNS, LINES, TERM, COLORTERM, DISPLAY,
|
|
44
45
|
* WAYLAND_DISPLAY, LOCALAPPDATA.
|
|
45
46
|
* - XDG basedir spec — XDG_*.
|
|
@@ -48,6 +49,9 @@
|
|
|
48
49
|
* GITHUB_PATH, GITHUB_STEP_SUMMARY, GITLAB_CI.
|
|
49
50
|
* - Cloud / SDK names — AWS_*, REDIS_*, OTEL_*, STRIPE_*, DOCKER_*,
|
|
50
51
|
* CONTAINER_HOST.
|
|
52
|
+
* - git tooling — GIT_* (git's own env-var family, e.g.
|
|
53
|
+
* GIT_CONFIG_GLOBAL / GIT_SSH_COMMAND, that KiCI
|
|
54
|
+
* sets to drive cloned / overlay workspaces).
|
|
51
55
|
* - Postgres libpq — PGHOST, PGPORT, PGUSER, PGPASSWORD,
|
|
52
56
|
* PGDATABASE, PGSERVICEFILE, PGSSLMODE.
|
|
53
57
|
* - Forgejo dev server — FORGEJO_URL, FORGEJO_CONTAINER (read by the
|
package/dist/env/allowlist.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
//#region src/env/allowlist.ts
|
|
3
3
|
/**
|
|
4
4
|
* Source of truth for the env-var allowlist.
|
|
@@ -41,7 +41,8 @@ import "../chunk-gOLHoazu.js";
|
|
|
41
41
|
* - `KICI_*` — every project-internal env var.
|
|
42
42
|
* - OS basics — NODE_ENV, HOME, PATH, TZ, LANG, TMPDIR,
|
|
43
43
|
* USER, USERNAME, SHELL, COMSPEC, PWD, OLDPWD,
|
|
44
|
-
* HOSTNAME
|
|
44
|
+
* HOSTNAME, PROCESSOR_ARCHITECTURE (Windows arch
|
|
45
|
+
* hint the agent reads to pick the mise zip).
|
|
45
46
|
* - Terminal / display — COLUMNS, LINES, TERM, COLORTERM, DISPLAY,
|
|
46
47
|
* WAYLAND_DISPLAY, LOCALAPPDATA.
|
|
47
48
|
* - XDG basedir spec — XDG_*.
|
|
@@ -50,6 +51,9 @@ import "../chunk-gOLHoazu.js";
|
|
|
50
51
|
* GITHUB_PATH, GITHUB_STEP_SUMMARY, GITLAB_CI.
|
|
51
52
|
* - Cloud / SDK names — AWS_*, REDIS_*, OTEL_*, STRIPE_*, DOCKER_*,
|
|
52
53
|
* CONTAINER_HOST.
|
|
54
|
+
* - git tooling — GIT_* (git's own env-var family, e.g.
|
|
55
|
+
* GIT_CONFIG_GLOBAL / GIT_SSH_COMMAND, that KiCI
|
|
56
|
+
* sets to drive cloned / overlay workspaces).
|
|
53
57
|
* - Postgres libpq — PGHOST, PGPORT, PGUSER, PGPASSWORD,
|
|
54
58
|
* PGDATABASE, PGSERVICEFILE, PGSSLMODE.
|
|
55
59
|
* - Forgejo dev server — FORGEJO_URL, FORGEJO_CONTAINER (read by the
|
|
@@ -70,7 +74,7 @@ import "../chunk-gOLHoazu.js";
|
|
|
70
74
|
* the dev proxy), HEADED (Playwright convention
|
|
71
75
|
* for `--headed` runs).
|
|
72
76
|
*/
|
|
73
|
-
const OS_SDK_ALLOWLIST_REGEX = /^(KICI_.*|NODE_ENV|HOME|PATH|TZ|LANG|TMPDIR|USER|USERNAME|SHELL|COMSPEC|PWD|OLDPWD|HOSTNAME|COLUMNS|LINES|TERM|COLORTERM|DISPLAY|WAYLAND_DISPLAY|LOCALAPPDATA|XDG_CACHE_HOME|XDG_CONFIG_HOME|XDG_DATA_HOME|XDG_RUNTIME_DIR|XDG_STATE_HOME|INIT_CWD|npm_.*|SSH_.*|CI|GITHUB_ACTIONS|GITHUB_ENV|GITHUB_OUTPUT|GITHUB_PATH|GITHUB_STEP_SUMMARY|GITLAB_CI|AWS_.*|REDIS_.*|OTEL_.*|STRIPE_.*|DOCKER_.*|CONTAINER_HOST|container|PGHOST|PGPORT|PGUSER|PGPASSWORD|PGDATABASE|PGSERVICEFILE|PGSSLMODE|FORGEJO_URL|FORGEJO_CONTAINER|KEYCLOAK_.*|VITE_.*|PLAYWRIGHT|HEADED)$/;
|
|
77
|
+
const OS_SDK_ALLOWLIST_REGEX = /^(KICI_.*|NODE_ENV|HOME|PATH|TZ|LANG|TMPDIR|USER|USERNAME|SHELL|COMSPEC|PWD|OLDPWD|HOSTNAME|PROCESSOR_ARCHITECTURE|COLUMNS|LINES|TERM|COLORTERM|DISPLAY|WAYLAND_DISPLAY|LOCALAPPDATA|XDG_CACHE_HOME|XDG_CONFIG_HOME|XDG_DATA_HOME|XDG_RUNTIME_DIR|XDG_STATE_HOME|INIT_CWD|npm_.*|SSH_.*|CI|GITHUB_ACTIONS|GITHUB_ENV|GITHUB_OUTPUT|GITHUB_PATH|GITHUB_STEP_SUMMARY|GITLAB_CI|AWS_.*|REDIS_.*|OTEL_.*|STRIPE_.*|DOCKER_.*|GIT_.*|CONTAINER_HOST|container|PGHOST|PGPORT|PGUSER|PGPASSWORD|PGDATABASE|PGSERVICEFILE|PGSSLMODE|FORGEJO_URL|FORGEJO_CONTAINER|KEYCLOAK_.*|VITE_.*|PLAYWRIGHT|HEADED)$/;
|
|
74
78
|
/**
|
|
75
79
|
* Returns true when `name` is allowed under the KiCI env-var convention:
|
|
76
80
|
* it matches the OS/SDK allowlist regex (which includes the `KICI_*`
|
package/dist/env/define-env.js
CHANGED
package/dist/env/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
import { RESERVED_NON_SCHEMA_KICI_PREFIXES, RESERVED_NON_SCHEMA_KICI_VARS, defineEnv, validateUnknownKiciVars } from "./define-env.js";
|
|
3
3
|
import { LOGGER_ENV_FIELD_SPECS, LOGGER_ENV_VARS, LoggerEnvSchema } from "./logger-env.js";
|
|
4
4
|
export { LOGGER_ENV_FIELD_SPECS, LOGGER_ENV_VARS, LoggerEnvSchema, RESERVED_NON_SCHEMA_KICI_PREFIXES, RESERVED_NON_SCHEMA_KICI_VARS, defineEnv, validateUnknownKiciVars };
|
package/dist/env/logger-env.js
CHANGED
package/dist/idempotency.js
CHANGED