@opengeni/worker-bundle 3.1.2 → 3.2.2

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.
@@ -0,0 +1,85 @@
1
+ // src/external-vault-providers.ts
2
+ import { pinnedFetch } from "@opengeni/network";
3
+ import { VaultProviderError } from "@opengeni/vaults";
4
+ function createNativeExternalVaultFactories(settings, options = {}) {
5
+ const factories = {
6
+ keeper: keeperFactory(settings, options.keeper ?? {})
7
+ };
8
+ const cliPath = settings.protonPassCliPath;
9
+ if (cliPath) factories.protonpass = protonPassFactory(cliPath, options.protonpass ?? {});
10
+ return factories;
11
+ }
12
+ async function closeNativeExternalVaultProviders() {
13
+ const pools = [...protonPools.values()];
14
+ protonPools.clear();
15
+ await Promise.all(pools.map(async (pool) => (await pool.catch(() => null))?.close()));
16
+ }
17
+ function mismatch() {
18
+ throw new VaultProviderError(
19
+ "provider_unavailable",
20
+ "The configured adapter does not match this connection."
21
+ );
22
+ }
23
+ function nativeKeeperFetch(settings, pinned = {}) {
24
+ return (input, init) => pinnedFetch(input, init, settings, {
25
+ ...pinned,
26
+ label: "Keeper Secrets Manager",
27
+ requireHttpsOutsideLocalTest: true
28
+ });
29
+ }
30
+ function keeperFactory(settings, seams) {
31
+ const fetch = nativeKeeperFetch(settings);
32
+ return async (input) => {
33
+ const credentials = input.credentials;
34
+ if (credentials.provider !== "keeper") mismatch();
35
+ const persist = input.persistCredentials;
36
+ const { openKeeperConnection } = await import("@opengeni/vaults-keeper");
37
+ const opened = await openKeeperConnection({
38
+ credentials: "oneTimeToken" in credentials ? {
39
+ oneTimeToken: credentials.oneTimeToken,
40
+ ...credentials.hostname ? { hostname: credentials.hostname } : {}
41
+ } : { configuration: credentials.configuration },
42
+ // Without it openKeeperConnection refuses: a redeemed token or rotated
43
+ // key must never live only in memory.
44
+ ...persist ? {
45
+ persistConfiguration: (configuration) => persist({ provider: "keeper", configuration })
46
+ } : {},
47
+ ...input.operations ? { operations: input.operations } : {},
48
+ // Cancels a pending bootstrap; a stored configuration opens without a request.
49
+ ...input.signal ? { signal: input.signal } : {},
50
+ fetch,
51
+ ...seams
52
+ });
53
+ const stored = {
54
+ provider: "keeper",
55
+ configuration: opened.configuration
56
+ };
57
+ return { provider: opened.provider, credentials: stored };
58
+ };
59
+ }
60
+ var protonPools = /* @__PURE__ */ new Map();
61
+ function protonPassFactory(binaryPath, seams) {
62
+ return async (input) => {
63
+ const credentials = input.credentials;
64
+ if (credentials.provider !== "protonpass") mismatch();
65
+ let pool = protonPools.get(binaryPath);
66
+ if (!pool) {
67
+ pool = import("@opengeni/vaults-protonpass").then(
68
+ ({ createProtonPassProviderPool }) => createProtonPassProviderPool({ ...seams, binaryPath })
69
+ );
70
+ protonPools.set(binaryPath, pool);
71
+ pool.catch(() => protonPools.delete(binaryPath));
72
+ }
73
+ const provider = (await pool).provider(credentials.token, {
74
+ ...input.connectionId === void 0 ? {} : { connectionId: input.connectionId },
75
+ ...input.operations ? { operations: input.operations } : {}
76
+ });
77
+ return { provider, credentials: { provider: "protonpass", token: credentials.token } };
78
+ };
79
+ }
80
+
81
+ export {
82
+ createNativeExternalVaultFactories,
83
+ closeNativeExternalVaultProviders
84
+ };
85
+ //# sourceMappingURL=chunk-K225DMA7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/external-vault-providers.ts"],"sourcesContent":["import type { Settings } from \"@opengeni/config\";\nimport type {\n ExternalVaultProviderFactories,\n ExternalVaultProviderFactory,\n StoredVaultProviderCredentials,\n} from \"@opengeni/core\";\nimport { pinnedFetch, type PinnedFetchOptions } from \"@opengeni/network\";\nimport { VaultProviderError } from \"@opengeni/vaults\";\nimport type { KeeperRuntimeOptions } from \"@opengeni/vaults-keeper\";\nimport type { ProtonPassProviderPool } from \"@opengeni/vaults-protonpass\";\n\n/** Test seams only; production passes nothing. */\nexport type NativeExternalVaultOptions = {\n keeper?: Pick<KeeperRuntimeOptions, \"queryFunction\" | \"fetchFile\" | \"sdk\">;\n /** Applies when this call creates the pool for its CLI path. */\n protonpass?: { stateRoot?: string; hostEnv?: Readonly<Record<string, string | undefined>> };\n};\n\n/**\n * Native external vault adapters that run inside this server: Keeper Secrets\n * Manager always, Proton Pass only when the operator installed `pass-cli`\n * (`OPENGENI_PROTON_PASS_CLI_PATH`). Both packages load through `import()`\n * on first use (packages/vaults-keeper/test/import-guard.test.ts). Keep this\n * file identical to apps/api/src/integrations/external-vault-providers.ts.\n */\nexport function createNativeExternalVaultFactories(\n settings: Settings,\n options: NativeExternalVaultOptions = {},\n): ExternalVaultProviderFactories {\n const factories: ExternalVaultProviderFactories = {\n keeper: keeperFactory(settings, options.keeper ?? {}),\n };\n const cliPath = settings.protonPassCliPath;\n if (cliPath) factories.protonpass = protonPassFactory(cliPath, options.protonpass ?? {});\n return factories;\n}\n\n/** Logs out every pooled Proton Pass CLI session and wipes its state (graceful shutdown). */\nexport async function closeNativeExternalVaultProviders(): Promise<void> {\n const pools = [...protonPools.values()];\n protonPools.clear();\n await Promise.all(pools.map(async (pool) => (await pool.catch(() => null))?.close()));\n}\n\nfunction mismatch(): never {\n throw new VaultProviderError(\n \"provider_unavailable\",\n \"The configured adapter does not match this connection.\",\n );\n}\n\n/**\n * The fetch every Keeper request and file download uses: DNS-pinned and\n * policy-checked (no private or special-use targets). The adapter adds\n * HTTPS-only, no redirects, deadlines, size bounds and the caller's abort.\n */\nexport function nativeKeeperFetch(\n settings: Settings,\n pinned: Pick<PinnedFetchOptions, \"dnsLookup\" | \"fetchImpl\" | \"agentFactory\"> = {},\n) {\n return (input: string | URL, init: RequestInit) =>\n pinnedFetch(input, init, settings, {\n ...pinned,\n label: \"Keeper Secrets Manager\",\n requireHttpsOutsideLocalTest: true,\n });\n}\n\nfunction keeperFactory(\n settings: Settings,\n seams: NonNullable<NativeExternalVaultOptions[\"keeper\"]>,\n): ExternalVaultProviderFactory {\n const fetch = nativeKeeperFetch(settings);\n return async (input) => {\n const credentials = input.credentials;\n if (credentials.provider !== \"keeper\") mismatch();\n const persist = input.persistCredentials;\n const { openKeeperConnection } = await import(\"@opengeni/vaults-keeper\");\n const opened = await openKeeperConnection({\n credentials:\n \"oneTimeToken\" in credentials\n ? {\n oneTimeToken: credentials.oneTimeToken,\n ...(credentials.hostname ? { hostname: credentials.hostname } : {}),\n }\n : { configuration: credentials.configuration },\n // Without it openKeeperConnection refuses: a redeemed token or rotated\n // key must never live only in memory.\n ...(persist\n ? {\n persistConfiguration: (configuration: Record<string, string>) =>\n persist({ provider: \"keeper\", configuration }),\n }\n : {}),\n ...(input.operations ? { operations: input.operations } : {}),\n // Cancels a pending bootstrap; a stored configuration opens without a request.\n ...(input.signal ? { signal: input.signal } : {}),\n fetch,\n ...seams,\n });\n const stored: StoredVaultProviderCredentials = {\n provider: \"keeper\",\n configuration: opened.configuration,\n };\n return { provider: opened.provider, credentials: stored };\n };\n}\n\n/** One pool per CLI path per process, so repeated factory creation never leaks sessions. */\nconst protonPools = new Map<string, Promise<ProtonPassProviderPool>>();\n\nfunction protonPassFactory(\n binaryPath: string,\n seams: NonNullable<NativeExternalVaultOptions[\"protonpass\"]>,\n): ExternalVaultProviderFactory {\n return async (input) => {\n const credentials = input.credentials;\n if (credentials.provider !== \"protonpass\") mismatch();\n let pool = protonPools.get(binaryPath);\n if (!pool) {\n pool = import(\"@opengeni/vaults-protonpass\").then(({ createProtonPassProviderPool }) =>\n createProtonPassProviderPool({ ...seams, binaryPath }),\n );\n protonPools.set(binaryPath, pool);\n pool.catch(() => protonPools.delete(binaryPath));\n }\n // Sessions are scoped to the connection, so two connections never share\n // CLI state even with the same token. Without a connection id (a setup\n // probe) the provider gets an isolated session of its own.\n const provider = (await pool).provider(credentials.token, {\n ...(input.connectionId === undefined ? {} : { connectionId: input.connectionId }),\n ...(input.operations ? { operations: input.operations } : {}),\n });\n return { provider, credentials: { provider: \"protonpass\", token: credentials.token } };\n };\n}\n"],"mappings":";AAMA,SAAS,mBAA4C;AACrD,SAAS,0BAA0B;AAkB5B,SAAS,mCACd,UACA,UAAsC,CAAC,GACP;AAChC,QAAM,YAA4C;AAAA,IAChD,QAAQ,cAAc,UAAU,QAAQ,UAAU,CAAC,CAAC;AAAA,EACtD;AACA,QAAM,UAAU,SAAS;AACzB,MAAI,QAAS,WAAU,aAAa,kBAAkB,SAAS,QAAQ,cAAc,CAAC,CAAC;AACvF,SAAO;AACT;AAGA,eAAsB,oCAAmD;AACvE,QAAM,QAAQ,CAAC,GAAG,YAAY,OAAO,CAAC;AACtC,cAAY,MAAM;AAClB,QAAM,QAAQ,IAAI,MAAM,IAAI,OAAO,UAAU,MAAM,KAAK,MAAM,MAAM,IAAI,IAAI,MAAM,CAAC,CAAC;AACtF;AAEA,SAAS,WAAkB;AACzB,QAAM,IAAI;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACF;AAOO,SAAS,kBACd,UACA,SAA+E,CAAC,GAChF;AACA,SAAO,CAAC,OAAqB,SAC3B,YAAY,OAAO,MAAM,UAAU;AAAA,IACjC,GAAG;AAAA,IACH,OAAO;AAAA,IACP,8BAA8B;AAAA,EAChC,CAAC;AACL;AAEA,SAAS,cACP,UACA,OAC8B;AAC9B,QAAM,QAAQ,kBAAkB,QAAQ;AACxC,SAAO,OAAO,UAAU;AACtB,UAAM,cAAc,MAAM;AAC1B,QAAI,YAAY,aAAa,SAAU,UAAS;AAChD,UAAM,UAAU,MAAM;AACtB,UAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,yBAAyB;AACvE,UAAM,SAAS,MAAM,qBAAqB;AAAA,MACxC,aACE,kBAAkB,cACd;AAAA,QACE,cAAc,YAAY;AAAA,QAC1B,GAAI,YAAY,WAAW,EAAE,UAAU,YAAY,SAAS,IAAI,CAAC;AAAA,MACnE,IACA,EAAE,eAAe,YAAY,cAAc;AAAA;AAAA;AAAA,MAGjD,GAAI,UACA;AAAA,QACE,sBAAsB,CAAC,kBACrB,QAAQ,EAAE,UAAU,UAAU,cAAc,CAAC;AAAA,MACjD,IACA,CAAC;AAAA,MACL,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA;AAAA,MAE3D,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,MAC/C;AAAA,MACA,GAAG;AAAA,IACL,CAAC;AACD,UAAM,SAAyC;AAAA,MAC7C,UAAU;AAAA,MACV,eAAe,OAAO;AAAA,IACxB;AACA,WAAO,EAAE,UAAU,OAAO,UAAU,aAAa,OAAO;AAAA,EAC1D;AACF;AAGA,IAAM,cAAc,oBAAI,IAA6C;AAErE,SAAS,kBACP,YACA,OAC8B;AAC9B,SAAO,OAAO,UAAU;AACtB,UAAM,cAAc,MAAM;AAC1B,QAAI,YAAY,aAAa,aAAc,UAAS;AACpD,QAAI,OAAO,YAAY,IAAI,UAAU;AACrC,QAAI,CAAC,MAAM;AACT,aAAO,OAAO,6BAA6B,EAAE;AAAA,QAAK,CAAC,EAAE,6BAA6B,MAChF,6BAA6B,EAAE,GAAG,OAAO,WAAW,CAAC;AAAA,MACvD;AACA,kBAAY,IAAI,YAAY,IAAI;AAChC,WAAK,MAAM,MAAM,YAAY,OAAO,UAAU,CAAC;AAAA,IACjD;AAIA,UAAM,YAAY,MAAM,MAAM,SAAS,YAAY,OAAO;AAAA,MACxD,GAAI,MAAM,iBAAiB,SAAY,CAAC,IAAI,EAAE,cAAc,MAAM,aAAa;AAAA,MAC/E,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,IAC7D,CAAC;AACD,WAAO,EAAE,UAAU,aAAa,EAAE,UAAU,cAAc,OAAO,YAAY,MAAM,EAAE;AAAA,EACvF;AACF;","names":[]}
@@ -3138,6 +3138,9 @@ async function terminateDrainableBox(db, settings, row, observability, terminate
3138
3138
  minIntervalMs: 0,
3139
3139
  pointInTimeCapture: providerWorkspaceCaptureIsPointInTime(backend, lease.resumeState),
3140
3140
  deadlineMandatoryCaptureLeadMs: sandboxDeadlineMandatoryCaptureLeadMs(settings),
3141
+ // An unknown-outcome setup request of a closed attempt never settles
3142
+ // on a live box; after the idle grace it no longer pins the drain.
3143
+ abandonedSetupCaptureAfterMs: Math.max(settings.sandboxIdleGraceMs, 6e4),
3141
3144
  providerReplaySafe: capturePolicy?.takeover === "same_request",
3142
3145
  takeoverSafe: capturePolicy !== null && capturePolicy.takeover !== "exclusive"
3143
3146
  });
@@ -3743,4 +3746,4 @@ export {
3743
3746
  terminateProviderBox,
3744
3747
  sandboxLeaseTelemetryKey2 as sandboxLeaseTelemetryKey
3745
3748
  };
3746
- //# sourceMappingURL=chunk-MVESOYFC.js.map
3749
+ //# sourceMappingURL=chunk-O7HT4LHX.js.map