@jeffusion/bungee-core 5.6.0 → 5.6.1
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/main.js +163 -71
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -8126,10 +8126,10 @@ function parseNormalizeCompileAggregate(input, options) {
|
|
|
8126
8126
|
if (!hasLogicalConfiguration) {
|
|
8127
8127
|
context.add("required", "logical_configuration", "Required field is missing");
|
|
8128
8128
|
}
|
|
8129
|
-
|
|
8129
|
+
let pluginActivations = parsePluginActivations(root.plugin_activations, "plugin_activations" in root, context, options?.availablePlugins ?? (options ? new Set(options.pluginSchemas.keys()) : undefined));
|
|
8130
8130
|
if (options?.pluginDependencies) {
|
|
8131
8131
|
try {
|
|
8132
|
-
options.pluginDependencies.
|
|
8132
|
+
pluginActivations = options.pluginDependencies.closure(pluginActivations.map(({ plugin_name }) => plugin_name)).map((plugin_name) => ({ plugin_name })).sort(comparePluginNames);
|
|
8133
8133
|
} catch (error) {
|
|
8134
8134
|
context.add("invalid_value", "plugin_activations", error instanceof Error ? error.message : String(error));
|
|
8135
8135
|
}
|
|
@@ -12455,7 +12455,7 @@ class PluginDependencyGraph {
|
|
|
12455
12455
|
}
|
|
12456
12456
|
}
|
|
12457
12457
|
function updatePluginActivations(graph, activated, name, enable) {
|
|
12458
|
-
const active = new Set(activated);
|
|
12458
|
+
const active = new Set(graph.closure(activated));
|
|
12459
12459
|
graph.dependenciesOf(name);
|
|
12460
12460
|
if (enable) {
|
|
12461
12461
|
for (const dependency of graph.closure([name]))
|
|
@@ -12479,7 +12479,7 @@ var package_default;
|
|
|
12479
12479
|
var init_package = __esm(() => {
|
|
12480
12480
|
package_default = {
|
|
12481
12481
|
name: "@jeffusion/bungee-core",
|
|
12482
|
-
version: "5.6.
|
|
12482
|
+
version: "5.6.1",
|
|
12483
12483
|
description: "Bungee reverse proxy core engine",
|
|
12484
12484
|
main: "./dist/main.js",
|
|
12485
12485
|
types: "./dist/main.d.ts",
|
|
@@ -222853,10 +222853,38 @@ var init_drain_workers = __esm(() => {
|
|
|
222853
222853
|
function validStatus(value) {
|
|
222854
222854
|
return typeof value.retired_id === "string" && RETIRED_ID.test(value.retired_id) && Number.isSafeInteger(value.pending) && value.pending >= 0 && typeof value.complete === "boolean" && Number.isSafeInteger(value.remaining_ms) && value.remaining_ms >= 0 && (!value.complete || value.pending === 0);
|
|
222855
222855
|
}
|
|
222856
|
+
function waitBeforePoll(scheduler, delay, signal) {
|
|
222857
|
+
return new Promise((resolve) => {
|
|
222858
|
+
let settled = false;
|
|
222859
|
+
let timeout;
|
|
222860
|
+
const finish = (value) => {
|
|
222861
|
+
if (settled)
|
|
222862
|
+
return;
|
|
222863
|
+
settled = true;
|
|
222864
|
+
bestEffort(() => timeout?.cancel());
|
|
222865
|
+
signal?.removeEventListener("abort", abort);
|
|
222866
|
+
resolve(value);
|
|
222867
|
+
};
|
|
222868
|
+
const abort = () => finish("cancelled");
|
|
222869
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
222870
|
+
if (signal?.aborted) {
|
|
222871
|
+
abort();
|
|
222872
|
+
return;
|
|
222873
|
+
}
|
|
222874
|
+
try {
|
|
222875
|
+
timeout = scheduler.schedule(delay, () => finish("poll"));
|
|
222876
|
+
} catch {
|
|
222877
|
+
finish("unavailable");
|
|
222878
|
+
}
|
|
222879
|
+
if (settled)
|
|
222880
|
+
bestEffort(() => timeout?.cancel());
|
|
222881
|
+
});
|
|
222882
|
+
}
|
|
222856
222883
|
async function waitForAdmissionHandoff(prepared, scheduler, hasRetiredWorkers, signal) {
|
|
222857
222884
|
if (!hasRetiredWorkers && prepared.handoffStatus === undefined)
|
|
222858
222885
|
return { kind: "complete" };
|
|
222859
222886
|
let retiredId = null;
|
|
222887
|
+
let statusFailures = 0;
|
|
222860
222888
|
while (true) {
|
|
222861
222889
|
if (signal?.aborted)
|
|
222862
222890
|
return { kind: "unknown", reason: "cancelled" };
|
|
@@ -222873,26 +222901,19 @@ async function waitForAdmissionHandoff(prepared, scheduler, hasRetiredWorkers, s
|
|
|
222873
222901
|
return { kind: "complete" };
|
|
222874
222902
|
if (status.remaining_ms === 0)
|
|
222875
222903
|
return { kind: "unknown", reason: "expired" };
|
|
222876
|
-
const resumed = await
|
|
222877
|
-
|
|
222878
|
-
|
|
222879
|
-
|
|
222880
|
-
|
|
222881
|
-
settled = true;
|
|
222882
|
-
timeout.cancel();
|
|
222883
|
-
signal?.removeEventListener("abort", abort);
|
|
222884
|
-
resolve(value);
|
|
222885
|
-
};
|
|
222886
|
-
const timeout = scheduler.schedule(Math.max(1, Math.min(100, status.remaining_ms)), () => finish(true));
|
|
222887
|
-
const abort = () => finish(false);
|
|
222888
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
222889
|
-
if (signal?.aborted)
|
|
222890
|
-
abort();
|
|
222891
|
-
});
|
|
222892
|
-
if (!resumed)
|
|
222904
|
+
const resumed = await waitBeforePoll(scheduler, Math.max(1, Math.min(100, status.remaining_ms)), signal);
|
|
222905
|
+
if (resumed !== "poll")
|
|
222906
|
+
return { kind: "unknown", reason: resumed };
|
|
222907
|
+
} catch (error) {
|
|
222908
|
+
if (signal?.aborted)
|
|
222893
222909
|
return { kind: "unknown", reason: "cancelled" };
|
|
222894
|
-
|
|
222895
|
-
|
|
222910
|
+
const code = typeof error === "object" && error !== null ? error.code : undefined;
|
|
222911
|
+
const retryable = code === undefined || ["network", "timeout", "unavailable", "control_recovering", "outcome_unknown"].includes(String(code));
|
|
222912
|
+
if (!retryable || ++statusFailures > 2)
|
|
222913
|
+
return { kind: "unknown", reason: "unavailable" };
|
|
222914
|
+
const resumed = await waitBeforePoll(scheduler, 100, signal);
|
|
222915
|
+
if (resumed !== "poll")
|
|
222916
|
+
return { kind: "unknown", reason: resumed };
|
|
222896
222917
|
}
|
|
222897
222918
|
}
|
|
222898
222919
|
}
|
|
@@ -223026,14 +223047,15 @@ function command(active, attempt, pluginCatalogHash) {
|
|
|
223026
223047
|
function failureDetail(failures) {
|
|
223027
223048
|
return failures.map(({ slot, code }) => `${slot}:${code}`).join(", ").slice(0, 512) || "publication failed";
|
|
223028
223049
|
}
|
|
223029
|
-
function publicationPhase(options, active, phase, boundary) {
|
|
223050
|
+
function publicationPhase(options, active, phase, boundary, handoffReason) {
|
|
223030
223051
|
try {
|
|
223031
223052
|
(options.stderr ?? process.stderr).write(`${JSON.stringify({
|
|
223032
223053
|
event: "publication_phase",
|
|
223033
223054
|
phase,
|
|
223034
223055
|
boundary,
|
|
223035
223056
|
mutation_id: active.operation.mutation_id,
|
|
223036
|
-
revision: active.snapshot.revision
|
|
223057
|
+
revision: active.snapshot.revision,
|
|
223058
|
+
...handoffReason === undefined ? {} : { handoff_reason: handoffReason }
|
|
223037
223059
|
})}
|
|
223038
223060
|
`);
|
|
223039
223061
|
} catch {}
|
|
@@ -223324,10 +223346,22 @@ async function runPublication(options, active, oldWorkers) {
|
|
|
223324
223346
|
}
|
|
223325
223347
|
throw error;
|
|
223326
223348
|
}
|
|
223327
|
-
|
|
223349
|
+
publicationPhase(options, refreshed, "admission.handoff", "enter");
|
|
223350
|
+
let handoff;
|
|
223351
|
+
try {
|
|
223352
|
+
handoff = await waitForAdmissionHandoff(preparedAdmission, options.scheduler, oldWorkers.length > 0, options.signal);
|
|
223353
|
+
} finally {
|
|
223354
|
+
publicationPhase(options, refreshed, "admission.handoff", "exit", handoff?.kind === "unknown" ? handoff.reason : undefined);
|
|
223355
|
+
}
|
|
223328
223356
|
if (handoff.kind === "unknown")
|
|
223329
223357
|
return retiredOutcomeUnknown(options, oldWorkers, new Error(`retired ingress handoff is unknown: ${handoff.reason}`));
|
|
223330
|
-
|
|
223358
|
+
publicationPhase(options, refreshed, "drainWorkers", "enter");
|
|
223359
|
+
let drainEvidence;
|
|
223360
|
+
try {
|
|
223361
|
+
drainEvidence = await drainWorkersUntilKnown(oldWorkers, options.scheduler, publicationPolicy, () => throwIfPublicationCancelled(options.signal, admissionCommitMayHaveBeenSent));
|
|
223362
|
+
} finally {
|
|
223363
|
+
publicationPhase(options, refreshed, "drainWorkers", "exit");
|
|
223364
|
+
}
|
|
223331
223365
|
throwIfPublicationCancelled(options.signal, admissionCommitMayHaveBeenSent);
|
|
223332
223366
|
const failuresDuringDrain = drainFailures(drainEvidence);
|
|
223333
223367
|
const recoveringWithoutOldOwnership = options.recoveringMaster && oldWorkers.length === 0 && await options.confirmPreviousWorkersExited?.(options.owned.serving()) !== true;
|
|
@@ -225434,7 +225468,7 @@ async function togglePluginActivation(request, pluginName, enable, options) {
|
|
|
225434
225468
|
return json({ error: "unauthorized" }, 401);
|
|
225435
225469
|
const activations = active.aggregate.plugin_activations;
|
|
225436
225470
|
const activated = activations.some((activation) => activation.plugin_name === pluginName);
|
|
225437
|
-
if (activated === enable)
|
|
225471
|
+
if (!options.pluginDependencies && activated === enable)
|
|
225438
225472
|
return unchangedMutationResponse(options, active.revision);
|
|
225439
225473
|
let nextActivations;
|
|
225440
225474
|
if (options.pluginDependencies) {
|
|
@@ -225447,6 +225481,8 @@ async function togglePluginActivation(request, pluginName, enable, options) {
|
|
|
225447
225481
|
} else {
|
|
225448
225482
|
nextActivations = enable ? [...activations, { plugin_name: pluginName }].sort((left, right) => left.plugin_name.localeCompare(right.plugin_name)) : activations.filter((activation) => activation.plugin_name !== pluginName);
|
|
225449
225483
|
}
|
|
225484
|
+
if (nextActivations.length === activations.length && nextActivations.every((value, index) => value.plugin_name === activations[index]?.plugin_name))
|
|
225485
|
+
return unchangedMutationResponse(options, active.revision);
|
|
225450
225486
|
const next = { ...active.aggregate, plugin_activations: nextActivations };
|
|
225451
225487
|
return commitConfigurationMutation(request, options, {
|
|
225452
225488
|
active,
|
|
@@ -225481,12 +225517,15 @@ async function importConfig(request, options) {
|
|
|
225481
225517
|
const active = activeResult;
|
|
225482
225518
|
if (!await options.managementAuth?.recheck(request) || !matchesCurrentAuth(request, active, options))
|
|
225483
225519
|
return json({ error: "unauthorized" }, 401);
|
|
225484
|
-
const
|
|
225520
|
+
const exported = parseNormalizeCompileAggregate(envelope.aggregate);
|
|
225521
|
+
if (!exported.ok)
|
|
225522
|
+
return json({ error: "invalid_configuration", errors: exported.errors }, 422);
|
|
225523
|
+
if (envelope.content_hash !== hashConfigurationContent(exported.value))
|
|
225524
|
+
return json({ error: "invalid_snapshot" }, 400);
|
|
225525
|
+
const parsed = options.parseAggregate(exported.value);
|
|
225485
225526
|
if (!parsed.ok)
|
|
225486
225527
|
return json({ error: "invalid_configuration", errors: parsed.errors }, 422);
|
|
225487
225528
|
freezeJson3(parsed.value);
|
|
225488
|
-
if (envelope.content_hash !== hashConfigurationContent(parsed.value))
|
|
225489
|
-
return json({ error: "invalid_snapshot" }, 400);
|
|
225490
225529
|
return commitConfigurationMutation(request, options, {
|
|
225491
225530
|
active,
|
|
225492
225531
|
next: parsed.value,
|
|
@@ -225727,6 +225766,7 @@ var init_control_api = __esm(() => {
|
|
|
225727
225766
|
init_config_storage();
|
|
225728
225767
|
init_repository_validation();
|
|
225729
225768
|
init_content_hash();
|
|
225769
|
+
init_aggregate();
|
|
225730
225770
|
init_plugin_name();
|
|
225731
225771
|
init_logger();
|
|
225732
225772
|
init_error_chain();
|
|
@@ -228420,6 +228460,39 @@ var init_master_plugin_catalog_api = __esm(() => {
|
|
|
228420
228460
|
];
|
|
228421
228461
|
});
|
|
228422
228462
|
|
|
228463
|
+
// src/master-runtime/reconcile-plugin-dependencies.ts
|
|
228464
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
228465
|
+
function reconcilePluginDependencies(repository, options, workerCount, now, managementProviders) {
|
|
228466
|
+
const current = repository.getSnapshot();
|
|
228467
|
+
if (!options.pluginDependencies)
|
|
228468
|
+
return current;
|
|
228469
|
+
const required = options.pluginDependencies.closure(current.aggregate.plugin_activations.map((value) => value.plugin_name));
|
|
228470
|
+
if (required.length === current.aggregate.plugin_activations.length)
|
|
228471
|
+
return current;
|
|
228472
|
+
const parsed = parseNormalizeCompileAggregate(current.aggregate, options);
|
|
228473
|
+
if (!parsed.ok)
|
|
228474
|
+
throw new ConfigRepositoryError("invalid_configuration", "configuration dependency reconciliation failed", parsed.errors);
|
|
228475
|
+
const active = new Set(current.aggregate.plugin_activations.map((value) => value.plugin_name));
|
|
228476
|
+
if (required.some((name) => managementProviders.has(name) && !active.has(name))) {
|
|
228477
|
+
throw new ConfigRepositoryError("invalid_configuration", "dependency activation changes management authentication; enable the provider through management setup before upgrading");
|
|
228478
|
+
}
|
|
228479
|
+
const result = repository.commit({
|
|
228480
|
+
mutation_id: randomUUID17(),
|
|
228481
|
+
expected_revision: current.revision,
|
|
228482
|
+
aggregate: parsed.value,
|
|
228483
|
+
kind: "config",
|
|
228484
|
+
created_at: now,
|
|
228485
|
+
target_worker_slots: Array.from({ length: workerCount }, (_, slot) => slot)
|
|
228486
|
+
});
|
|
228487
|
+
if (result.kind !== "committed") {
|
|
228488
|
+
throw new ConfigRepositoryError("invalid_operation", `configuration dependency reconciliation blocked: ${result.kind}`);
|
|
228489
|
+
}
|
|
228490
|
+
return result.snapshot;
|
|
228491
|
+
}
|
|
228492
|
+
var init_reconcile_plugin_dependencies = __esm(() => {
|
|
228493
|
+
init_config_storage();
|
|
228494
|
+
});
|
|
228495
|
+
|
|
228423
228496
|
// src/ui/assets.ts
|
|
228424
228497
|
function decodeBase64Asset(content) {
|
|
228425
228498
|
return new Blob([Uint8Array.from(atob(content), (character) => character.charCodeAt(0))]);
|
|
@@ -228917,7 +228990,7 @@ var init_daemon_control2 = __esm(() => {
|
|
|
228917
228990
|
|
|
228918
228991
|
// src/master-runtime/composition.ts
|
|
228919
228992
|
import { AsyncLocalStorage } from "async_hooks";
|
|
228920
|
-
import { randomUUID as
|
|
228993
|
+
import { randomUUID as randomUUID18, createHash as createHash6 } from "crypto";
|
|
228921
228994
|
import { resolve as resolve14 } from "path";
|
|
228922
228995
|
function cleanupWorkersAfterStartupFailure(factory, disposition) {
|
|
228923
228996
|
if (disposition === undefined || disposition.kind === "shutdown_safe_empty") {
|
|
@@ -229098,7 +229171,7 @@ class DurableRouteProtections {
|
|
|
229098
229171
|
const previous = this.state?.get(name), value = { plugin: name, routeIds: [...routeIds] };
|
|
229099
229172
|
if (this.state && JSON.stringify(previous?.value) !== JSON.stringify(value))
|
|
229100
229173
|
this.state.execute({
|
|
229101
|
-
commandId:
|
|
229174
|
+
commandId: randomUUID18(),
|
|
229102
229175
|
mutations: [{ key: name, expectedVersion: previous?.version ?? 0, value }]
|
|
229103
229176
|
});
|
|
229104
229177
|
if (routeIds.length)
|
|
@@ -229153,7 +229226,7 @@ async function startMasterComposition(dependencies, daemonBootstrap = null) {
|
|
|
229153
229226
|
if (createClaim === undefined || bootstrap.claimControllerWithCapability === undefined) {
|
|
229154
229227
|
throw new MasterRuntimeError("startup_incomplete", "supervision claim is unavailable");
|
|
229155
229228
|
}
|
|
229156
|
-
supervisionState = bootstrap.claimControllerWithCapability(createClaim(configLock, accessLock),
|
|
229229
|
+
supervisionState = bootstrap.claimControllerWithCapability(createClaim(configLock, accessLock), randomUUID18(), dependencies.clock.now());
|
|
229157
229230
|
await bootstrap.close();
|
|
229158
229231
|
resources.repository = null;
|
|
229159
229232
|
}
|
|
@@ -229182,6 +229255,10 @@ async function startMasterComposition(dependencies, daemonBootstrap = null) {
|
|
|
229182
229255
|
if (dependencies.createIngressController !== undefined && supervisionState === null) {
|
|
229183
229256
|
throw new MasterRuntimeError("startup_incomplete", "supervision state was not claimed");
|
|
229184
229257
|
}
|
|
229258
|
+
if (compileOptions.pluginDependencies) {
|
|
229259
|
+
const managementProviders = new Set((catalog.records?.() ?? []).filter((record) => record.manifest.management).map((record) => record.name));
|
|
229260
|
+
reconcilePluginDependencies(resources.repository, compileOptions, options.workerCount, dependencies.clock.now(), managementProviders);
|
|
229261
|
+
}
|
|
229185
229262
|
const configDatabase = resources.repository.getDatabase?.();
|
|
229186
229263
|
const accessDatabase = resources.stats?.getDatabase?.();
|
|
229187
229264
|
const secretStores = configDatabase === undefined ? {
|
|
@@ -229198,10 +229275,10 @@ async function startMasterComposition(dependencies, daemonBootstrap = null) {
|
|
|
229198
229275
|
const rpcIdentityState = durableState?.forNamespace("core-master-state-rpc");
|
|
229199
229276
|
let rpcIdentity = rpcIdentityState?.get("identity");
|
|
229200
229277
|
if (rpcIdentityState && !rpcIdentity) {
|
|
229201
|
-
rpcIdentity = rpcIdentityState.execute({ commandId:
|
|
229278
|
+
rpcIdentity = rpcIdentityState.execute({ commandId: randomUUID18(), mutations: [{ key: "identity", expectedVersion: 0, value: { process_instance_id: supervisionState?.instance_id ?? randomUUID18(), boot_nonce: randomUUID18() } }] })[0];
|
|
229202
229279
|
}
|
|
229203
229280
|
const stableIdentity = rpcIdentity?.value;
|
|
229204
|
-
const masterStateIdentity = { role: "ingress", process_instance_id: stableIdentity?.process_instance_id ??
|
|
229281
|
+
const masterStateIdentity = { role: "ingress", process_instance_id: stableIdentity?.process_instance_id ?? randomUUID18(), boot_nonce: stableIdentity?.boot_nonce ?? randomUUID18() };
|
|
229205
229282
|
let publishPolicy = async () => false;
|
|
229206
229283
|
const managementOrigin = parseManagementOrigin(process.env.BUNGEE_PUBLIC_ORIGIN);
|
|
229207
229284
|
const trustedProxyAddresses = parseTrustedManagementProxies(process.env.BUNGEE_TRUSTED_MANAGEMENT_PROXIES);
|
|
@@ -229296,7 +229373,7 @@ async function startMasterComposition(dependencies, daemonBootstrap = null) {
|
|
|
229296
229373
|
stateLeases.set(record.key, record.value);
|
|
229297
229374
|
const saveStateLease = (id, lease) => {
|
|
229298
229375
|
const previous = leaseState?.get(id);
|
|
229299
|
-
leaseState?.execute({ commandId:
|
|
229376
|
+
leaseState?.execute({ commandId: randomUUID18(), mutations: [{ key: id, expectedVersion: previous?.version ?? 0, value: lease ? { ...lease } : null }] });
|
|
229300
229377
|
if (lease)
|
|
229301
229378
|
stateLeases.set(id, lease);
|
|
229302
229379
|
else
|
|
@@ -229371,7 +229448,7 @@ async function startMasterComposition(dependencies, daemonBootstrap = null) {
|
|
|
229371
229448
|
if (!lease)
|
|
229372
229449
|
saveStateLease(id, { worker: workerId, principal, plugin: call.plugin });
|
|
229373
229450
|
if (!requestLease)
|
|
229374
|
-
requestLeaseState?.execute({ commandId:
|
|
229451
|
+
requestLeaseState?.execute({ commandId: randomUUID18(), mutations: [{ key: requestLeaseId, expectedVersion: 0, value: { worker: workerId, principal, plugin: call.plugin } }] });
|
|
229375
229452
|
}
|
|
229376
229453
|
if (call.method === "settle")
|
|
229377
229454
|
await resources.ingressController.freezePluginKey(call.plugin, call.target.principal.keyId);
|
|
@@ -230747,6 +230824,7 @@ var init_composition = __esm(() => {
|
|
|
230747
230824
|
init_plugin_control();
|
|
230748
230825
|
init_master_http_bridge();
|
|
230749
230826
|
init_master_plugin_catalog_api();
|
|
230827
|
+
init_reconcile_plugin_dependencies();
|
|
230750
230828
|
init_server();
|
|
230751
230829
|
init_daemon_control2();
|
|
230752
230830
|
NO_INGRESS_STARTUP_FAILURE_DISPOSITION = Object.freeze({
|
|
@@ -230837,7 +230915,7 @@ var init_headers = __esm(() => {
|
|
|
230837
230915
|
});
|
|
230838
230916
|
|
|
230839
230917
|
// src/public-listener/forwarding.ts
|
|
230840
|
-
import { randomUUID as
|
|
230918
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
230841
230919
|
function errorResponse4(status) {
|
|
230842
230920
|
const error = status === 503 ? "service_unavailable" : status === 502 ? "bad_gateway" : "client_closed_request";
|
|
230843
230921
|
const headers = new Headers(JSON_HEADERS6);
|
|
@@ -230859,7 +230937,7 @@ async function forwardToSelectedWorker(request, options, trustedPeer) {
|
|
|
230859
230937
|
});
|
|
230860
230938
|
}
|
|
230861
230939
|
const principal = options.authenticate?.(request) ?? ANONYMOUS_PRINCIPAL;
|
|
230862
|
-
const identity = { requestId:
|
|
230940
|
+
const identity = { requestId: randomUUID19(), principal };
|
|
230863
230941
|
const lease = options.admission.acquire();
|
|
230864
230942
|
const worker = lease.worker;
|
|
230865
230943
|
if (worker === null) {
|
|
@@ -230893,7 +230971,7 @@ async function forwardToSelectedWorker(request, options, trustedPeer) {
|
|
|
230893
230971
|
try {
|
|
230894
230972
|
logger.warn({ ingressForwarding: {
|
|
230895
230973
|
phase: "private_response_headers",
|
|
230896
|
-
correlation_id:
|
|
230974
|
+
correlation_id: randomUUID19(),
|
|
230897
230975
|
error_code: errorCode,
|
|
230898
230976
|
elapsed_ms: Math.max(0, Math.round(performance.now() - startedAt))
|
|
230899
230977
|
} }, "Ingress private request forwarding failed");
|
|
@@ -231157,7 +231235,7 @@ var init_admission_registry2 = __esm(() => {
|
|
|
231157
231235
|
});
|
|
231158
231236
|
|
|
231159
231237
|
// src/ingress/supervision-http.ts
|
|
231160
|
-
import { randomUUID as
|
|
231238
|
+
import { randomUUID as randomUUID20 } from "crypto";
|
|
231161
231239
|
function optionalAdmission(value) {
|
|
231162
231240
|
return value === null ? null : parseAdmissionSet(value);
|
|
231163
231241
|
}
|
|
@@ -231716,7 +231794,7 @@ class IngressControllerClient {
|
|
|
231716
231794
|
}
|
|
231717
231795
|
return value;
|
|
231718
231796
|
}
|
|
231719
|
-
async challenge(authority, requestId =
|
|
231797
|
+
async challenge(authority, requestId = randomUUID20(), sequence = 1, signal) {
|
|
231720
231798
|
if (signal?.aborted)
|
|
231721
231799
|
throw signal.reason;
|
|
231722
231800
|
this.statusRequestSequence = Math.max(this.statusRequestSequence, sequence + 1);
|
|
@@ -231731,7 +231809,7 @@ class IngressControllerClient {
|
|
|
231731
231809
|
async status(authority, sequence = this.statusRequestSequence, signal) {
|
|
231732
231810
|
if (signal?.aborted)
|
|
231733
231811
|
throw signal.reason;
|
|
231734
|
-
const requestId =
|
|
231812
|
+
const requestId = randomUUID20();
|
|
231735
231813
|
const message = signSupervisionMessage({
|
|
231736
231814
|
protocol: "bungee-supervision-v1",
|
|
231737
231815
|
kind: "status",
|
|
@@ -231749,13 +231827,13 @@ class IngressControllerClient {
|
|
|
231749
231827
|
throw signal.reason;
|
|
231750
231828
|
return this.verifyStatus(response, authority, requestId);
|
|
231751
231829
|
}
|
|
231752
|
-
async fence(authority, sequence, requestId =
|
|
231830
|
+
async fence(authority, sequence, requestId = randomUUID20(), signal) {
|
|
231753
231831
|
const response = await this.command(authority, sequence, "/admission/fence", null, requestId, signal);
|
|
231754
231832
|
if (signal?.aborted)
|
|
231755
231833
|
throw signal.reason;
|
|
231756
231834
|
return this.verifyStatus(response, authority, requestId);
|
|
231757
231835
|
}
|
|
231758
|
-
async attach(challenge, authority, sequence = 1, requestId =
|
|
231836
|
+
async attach(challenge, authority, sequence = 1, requestId = randomUUID20(), signal) {
|
|
231759
231837
|
if (signal?.aborted)
|
|
231760
231838
|
throw signal.reason;
|
|
231761
231839
|
this.statusRequestSequence = Math.max(this.statusRequestSequence, sequence + 1);
|
|
@@ -231774,7 +231852,7 @@ class IngressControllerClient {
|
|
|
231774
231852
|
throw signal.reason;
|
|
231775
231853
|
return this.verifyStatus(response, authority, requestId);
|
|
231776
231854
|
}
|
|
231777
|
-
async lease(authority, leaseExpiresAt, sequence, requestId =
|
|
231855
|
+
async lease(authority, leaseExpiresAt, sequence, requestId = randomUUID20(), signal) {
|
|
231778
231856
|
if (signal?.aborted)
|
|
231779
231857
|
throw signal.reason;
|
|
231780
231858
|
this.statusRequestSequence = Math.max(this.statusRequestSequence, sequence + 1);
|
|
@@ -231793,7 +231871,7 @@ class IngressControllerClient {
|
|
|
231793
231871
|
throw signal.reason;
|
|
231794
231872
|
return this.verifyStatus(response, authority, requestId);
|
|
231795
231873
|
}
|
|
231796
|
-
async command(authority, sequence, path, body, requestId =
|
|
231874
|
+
async command(authority, sequence, path, body, requestId = randomUUID20(), signal) {
|
|
231797
231875
|
if (signal?.aborted)
|
|
231798
231876
|
throw signal.reason;
|
|
231799
231877
|
this.statusRequestSequence = Math.max(this.statusRequestSequence, sequence + 1);
|
|
@@ -232251,7 +232329,7 @@ var init_ingress2 = __esm(async () => {
|
|
|
232251
232329
|
});
|
|
232252
232330
|
|
|
232253
232331
|
// src/master-runtime/supervised-worker-client.ts
|
|
232254
|
-
import { randomUUID as
|
|
232332
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
232255
232333
|
function plain8(value) {
|
|
232256
232334
|
if (typeof value !== "object" || value === null || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
|
|
232257
232335
|
throw new WorkerControllerClientError("protocol", "supervision response must be a plain object");
|
|
@@ -232730,7 +232808,7 @@ class WorkerControllerClient {
|
|
|
232730
232808
|
try {
|
|
232731
232809
|
if (this.stopped || this.terminating || controller.signal.aborted || Date.now() >= deadline)
|
|
232732
232810
|
throw new WorkerControllerClientError("timeout", "worker runtime snapshot timed out");
|
|
232733
|
-
const requestId =
|
|
232811
|
+
const requestId = randomUUID21();
|
|
232734
232812
|
const sequence = this.nextSequence();
|
|
232735
232813
|
const message = signSupervisionMessage({
|
|
232736
232814
|
protocol: "bungee-supervision-v1",
|
|
@@ -232756,7 +232834,7 @@ class WorkerControllerClient {
|
|
|
232756
232834
|
}, controller.signal, deadline).finally(finish);
|
|
232757
232835
|
}
|
|
232758
232836
|
async challenge(signal = this.ordinaryAbort.signal) {
|
|
232759
|
-
const requestId =
|
|
232837
|
+
const requestId = randomUUID21();
|
|
232760
232838
|
const sequence = this.nextSequence();
|
|
232761
232839
|
const response = plain8(await this.fetchJson("/__supervision/challenge", {
|
|
232762
232840
|
controller_epoch: this.options.authority.controller_epoch,
|
|
@@ -232772,7 +232850,7 @@ class WorkerControllerClient {
|
|
|
232772
232850
|
}
|
|
232773
232851
|
async attachOnce(signal = this.ordinaryAbort.signal) {
|
|
232774
232852
|
const challengeNonce = await this.challenge(signal);
|
|
232775
|
-
const attachId =
|
|
232853
|
+
const attachId = randomUUID21();
|
|
232776
232854
|
const attachSequence = this.nextSequence();
|
|
232777
232855
|
const attach = signSupervisionMessage({
|
|
232778
232856
|
protocol: "bungee-supervision-v1",
|
|
@@ -232799,7 +232877,7 @@ class WorkerControllerClient {
|
|
|
232799
232877
|
throw error;
|
|
232800
232878
|
}
|
|
232801
232879
|
}
|
|
232802
|
-
const leaseId =
|
|
232880
|
+
const leaseId = randomUUID21();
|
|
232803
232881
|
const leaseSequence = this.nextSequence();
|
|
232804
232882
|
const leaseStartedAt = performance.now();
|
|
232805
232883
|
const lease = signSupervisionMessage({
|
|
@@ -232844,7 +232922,7 @@ class WorkerControllerClient {
|
|
|
232844
232922
|
}, delayMs);
|
|
232845
232923
|
}
|
|
232846
232924
|
async renewOnce(signal = this.ordinaryAbort.signal) {
|
|
232847
|
-
const requestId =
|
|
232925
|
+
const requestId = randomUUID21();
|
|
232848
232926
|
const sequence = this.nextSequence();
|
|
232849
232927
|
const leaseStartedAt = performance.now();
|
|
232850
232928
|
const lease = signSupervisionMessage({
|
|
@@ -232889,12 +232967,11 @@ class WorkerControllerClient {
|
|
|
232889
232967
|
return this.enqueueRenewal((signal) => this.renewOnce(signal));
|
|
232890
232968
|
}
|
|
232891
232969
|
status(timeoutMs = this.timeoutMs) {
|
|
232892
|
-
const
|
|
232893
|
-
const deadline = performance.now() + budget;
|
|
232970
|
+
const deadline = performance.now() + timeoutMs;
|
|
232894
232971
|
return this.enqueue(() => deadline <= performance.now() ? Promise.reject(new WorkerControllerClientError("timeout", "worker status deadline expired")) : this.statusOnce(this.ordinaryAbort.signal, deadline));
|
|
232895
232972
|
}
|
|
232896
232973
|
async statusOnce(signal = this.ordinaryAbort.signal, deadline) {
|
|
232897
|
-
const requestId =
|
|
232974
|
+
const requestId = randomUUID21();
|
|
232898
232975
|
const sequence = this.nextSequence();
|
|
232899
232976
|
const message = signSupervisionMessage({
|
|
232900
232977
|
protocol: "bungee-supervision-v1",
|
|
@@ -232927,7 +233004,7 @@ class WorkerControllerClient {
|
|
|
232927
233004
|
});
|
|
232928
233005
|
}
|
|
232929
233006
|
async commandOnce(path, body, signal, allowTerminating = false, deadline) {
|
|
232930
|
-
const requestId =
|
|
233007
|
+
const requestId = randomUUID21();
|
|
232931
233008
|
const sequence = this.nextSequence();
|
|
232932
233009
|
const message = signSupervisionMessage({
|
|
232933
233010
|
protocol: "bungee-supervision-v1",
|
|
@@ -232976,7 +233053,7 @@ class WorkerControllerClient {
|
|
|
232976
233053
|
for (const controller of this.runtimeControllers)
|
|
232977
233054
|
controller.abort("disconnected");
|
|
232978
233055
|
if (expireLease && !this.terminating && this.state === "attached") {
|
|
232979
|
-
const requestId =
|
|
233056
|
+
const requestId = randomUUID21();
|
|
232980
233057
|
const sequence = this.nextSequence();
|
|
232981
233058
|
const lease = signSupervisionMessage({
|
|
232982
233059
|
protocol: "bungee-supervision-v1",
|
|
@@ -233214,6 +233291,7 @@ class SupervisedConfigWorkerProcessAdapter {
|
|
|
233214
233291
|
stopped = false;
|
|
233215
233292
|
drainPoll = null;
|
|
233216
233293
|
drainCommand = null;
|
|
233294
|
+
drainStatusFailureReported = false;
|
|
233217
233295
|
exitPublication = null;
|
|
233218
233296
|
kernelBootId;
|
|
233219
233297
|
constructor(options) {
|
|
@@ -233416,7 +233494,23 @@ class SupervisedConfigWorkerProcessAdapter {
|
|
|
233416
233494
|
return status;
|
|
233417
233495
|
}
|
|
233418
233496
|
async drainStatus(timeoutMs) {
|
|
233419
|
-
const
|
|
233497
|
+
const startedAt = performance.now();
|
|
233498
|
+
let status;
|
|
233499
|
+
try {
|
|
233500
|
+
status = await this.status(timeoutMs);
|
|
233501
|
+
this.drainStatusFailureReported = false;
|
|
233502
|
+
} catch (error) {
|
|
233503
|
+
if (!this.drainStatusFailureReported) {
|
|
233504
|
+
this.drainStatusFailureReported = true;
|
|
233505
|
+
recordShutdownFailure("worker_drain_status", {
|
|
233506
|
+
pid: this.pid,
|
|
233507
|
+
origin: this.origin,
|
|
233508
|
+
elapsedMs: shutdownElapsedMs(startedAt),
|
|
233509
|
+
...timeoutMs === undefined ? {} : { timeoutMs }
|
|
233510
|
+
}, error);
|
|
233511
|
+
}
|
|
233512
|
+
throw error;
|
|
233513
|
+
}
|
|
233420
233514
|
if (status.evidence.kind === "draining" && status.evidence.message?.status === "worker-draining") {
|
|
233421
233515
|
return status.evidence.message;
|
|
233422
233516
|
}
|
|
@@ -235409,7 +235503,7 @@ var init_management_listener = __esm(() => {
|
|
|
235409
235503
|
});
|
|
235410
235504
|
|
|
235411
235505
|
// src/ingress/master-controller.ts
|
|
235412
|
-
import { randomUUID as
|
|
235506
|
+
import { randomUUID as randomUUID22 } from "crypto";
|
|
235413
235507
|
import { spawn as spawnChild2 } from "child_process";
|
|
235414
235508
|
function immutableRegistry(registry) {
|
|
235415
235509
|
const immutableAdmission = (set) => set === null ? null : Object.freeze({
|
|
@@ -235493,7 +235587,7 @@ class MasterIngressController {
|
|
|
235493
235587
|
requirePositive(this.startupTimeoutMs, "startupTimeoutMs");
|
|
235494
235588
|
requirePositive(this.leaseDurationMs, "leaseDurationMs");
|
|
235495
235589
|
this.authority = { controller_epoch: options.controllerEpoch, controller_id: options.controllerId };
|
|
235496
|
-
this.childCredential = deriveSupervisionProcessKey(options.rootKey, options.instanceId, "ingress",
|
|
235590
|
+
this.childCredential = deriveSupervisionProcessKey(options.rootKey, options.instanceId, "ingress", randomUUID22(), randomUUID22());
|
|
235497
235591
|
this.fetch = options.fetch ?? fetch;
|
|
235498
235592
|
this.identityControl = options.processIdentity ?? DEFAULT_INGRESS_PROCESS_IDENTITY;
|
|
235499
235593
|
this.probeSleep = options.probeSleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
@@ -235988,8 +236082,6 @@ class MasterIngressController {
|
|
|
235988
236082
|
evidence.lastProbe = probe;
|
|
235989
236083
|
if (probe === "dead" || probe === "mismatch")
|
|
235990
236084
|
return probe;
|
|
235991
|
-
if (probe === "unknown")
|
|
235992
|
-
return "unverified";
|
|
235993
236085
|
const remaining = deadline - this.now();
|
|
235994
236086
|
if (remaining <= 0)
|
|
235995
236087
|
break;
|
|
@@ -236050,7 +236142,7 @@ class MasterIngressController {
|
|
|
236050
236142
|
const lifecycle = this.lifecycleGeneration;
|
|
236051
236143
|
if (!this.isRecoveryEligible(lifecycle))
|
|
236052
236144
|
return null;
|
|
236053
|
-
this.childCredential = deriveSupervisionProcessKey(this.options.rootKey, this.options.instanceId, "ingress",
|
|
236145
|
+
this.childCredential = deriveSupervisionProcessKey(this.options.rootKey, this.options.instanceId, "ingress", randomUUID22(), randomUUID22());
|
|
236054
236146
|
const childEnvironment = { ...this.options.environment ?? process.env };
|
|
236055
236147
|
for (const name of [
|
|
236056
236148
|
"BUNGEE_PLUGIN_SECRETS_KEY",
|
|
@@ -236080,9 +236172,9 @@ class MasterIngressController {
|
|
|
236080
236172
|
throw this.mapDiscoveryFailure(cause);
|
|
236081
236173
|
}
|
|
236082
236174
|
this.assertRecoveryEligible(lifecycle);
|
|
236083
|
-
const challenge = await client.challenge(this.authority,
|
|
236175
|
+
const challenge = await client.challenge(this.authority, randomUUID22(), 1, signal);
|
|
236084
236176
|
this.assertRecoveryEligible(lifecycle);
|
|
236085
|
-
await client.attach(challenge, this.authority, this.nextSequence(signal),
|
|
236177
|
+
await client.attach(challenge, this.authority, this.nextSequence(signal), randomUUID22(), signal);
|
|
236086
236178
|
this.assertRecoveryEligible(lifecycle);
|
|
236087
236179
|
const attachedStatus = await client.status(this.authority, this.nextSequence(signal), signal);
|
|
236088
236180
|
this.assertRecoveryEligible(lifecycle);
|
|
@@ -236393,10 +236485,10 @@ class MasterIngressController {
|
|
|
236393
236485
|
await client.identity(signal);
|
|
236394
236486
|
if (!this.isRecoveryEligible(lifecycle))
|
|
236395
236487
|
return null;
|
|
236396
|
-
const challenge = await client.challenge(this.authority,
|
|
236488
|
+
const challenge = await client.challenge(this.authority, randomUUID22(), 1, signal);
|
|
236397
236489
|
if (!this.isRecoveryEligible(lifecycle))
|
|
236398
236490
|
return null;
|
|
236399
|
-
await client.attach(challenge, this.authority, this.nextSequence(signal),
|
|
236491
|
+
await client.attach(challenge, this.authority, this.nextSequence(signal), randomUUID22(), signal);
|
|
236400
236492
|
if (!this.isRecoveryEligible(lifecycle))
|
|
236401
236493
|
return null;
|
|
236402
236494
|
const attachedStatus = await client.status(this.authority, this.nextSequence(signal), signal);
|
|
@@ -237103,7 +237195,7 @@ var init_master_controller = __esm(() => {
|
|
|
237103
237195
|
});
|
|
237104
237196
|
|
|
237105
237197
|
// src/master.ts
|
|
237106
|
-
import { randomUUID as
|
|
237198
|
+
import { randomUUID as randomUUID23 } from "crypto";
|
|
237107
237199
|
import { resolve as resolve17 } from "path";
|
|
237108
237200
|
function environment() {
|
|
237109
237201
|
return Object.fromEntries(Object.entries(process.env).filter((entry) => entry[1] !== undefined));
|
|
@@ -237187,7 +237279,7 @@ var init_master = __esm(async () => {
|
|
|
237187
237279
|
deriveTransportSecret: deriveWorkerTransportSecret,
|
|
237188
237280
|
resolveWorkerLaunch,
|
|
237189
237281
|
createWorkerFactory: (options) => new SupervisedConfigWorkerFactory(options),
|
|
237190
|
-
createMasterGeneration:
|
|
237282
|
+
createMasterGeneration: randomUUID23,
|
|
237191
237283
|
createCoordinator: (options) => new MasterConfigPublicationCoordinator(options),
|
|
237192
237284
|
createManagementListener,
|
|
237193
237285
|
createControllerClaim: mintControllerClaimCapability,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jeffusion/bungee-core",
|
|
3
|
-
"version": "5.6.
|
|
3
|
+
"version": "5.6.1",
|
|
4
4
|
"description": "Bungee reverse proxy core engine",
|
|
5
5
|
"main": "./dist/main.js",
|
|
6
6
|
"types": "./dist/main.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"test": "bun test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@jeffusion/bungee-types": "^5.6.
|
|
15
|
+
"@jeffusion/bungee-types": "^5.6.1",
|
|
16
16
|
"@types/lodash-es": "^4.17.12",
|
|
17
17
|
"acorn": "^8.15.0",
|
|
18
18
|
"canonicalize": "3.0.0",
|