@opengeni/api-router 3.1.3-canary.38890816741001 → 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.
@@ -311,7 +311,11 @@ export function registerVaultRoutes(app: Hono, deps: ApiRouteDeps): void {
311
311
  const payload = await parseRequestJson(c, MoveVaultItemRequest);
312
312
  const itemId = c.req.param("itemId")!;
313
313
  await itemInVault(actor, workspaceId, c.req.param("vaultId")!, itemId);
314
- return c.json(await vaults().moveItem(actor, workspaceId, itemId, payload));
314
+ // A connected source or target is read, written and archived through this
315
+ // request's providers, like every other connected read and write.
316
+ return c.json(
317
+ await vaultsWithProviders(actor, workspaceId).moveItem(actor, workspaceId, itemId, payload),
318
+ );
315
319
  }),
316
320
  );
317
321
 
@@ -0,0 +1,54 @@
1
+ type ShutdownSignal = "SIGINT" | "SIGTERM";
2
+ type ShutdownProcess = {
3
+ on(signal: ShutdownSignal, handler: () => void): unknown;
4
+ off(signal: ShutdownSignal, handler: () => void): unknown;
5
+ exit(code: number): void;
6
+ };
7
+
8
+ /** Standalone process boundary; embedded hosts keep owning their explicit close(). */
9
+ export function installApiShutdownHandlers(input: {
10
+ close: () => Promise<void>;
11
+ process?: ShutdownProcess;
12
+ timeoutMs?: number;
13
+ onFailure?: () => void;
14
+ }): () => void {
15
+ const runtime = input.process ?? process;
16
+ let started = false;
17
+ let finished = false;
18
+ let deadline: ReturnType<typeof setTimeout> | undefined;
19
+ const dispose = () => {
20
+ runtime.off("SIGINT", shutdown);
21
+ runtime.off("SIGTERM", shutdown);
22
+ };
23
+ const finish = (code: number) => {
24
+ if (finished) return;
25
+ finished = true;
26
+ clearTimeout(deadline);
27
+ dispose();
28
+ if (code !== 0) {
29
+ try {
30
+ input.onFailure?.();
31
+ } catch {
32
+ /* Observability cannot prevent exit. */
33
+ }
34
+ }
35
+ runtime.exit(code);
36
+ };
37
+ function shutdown() {
38
+ if (started) return;
39
+ started = true;
40
+ deadline = setTimeout(() => finish(1), input.timeoutMs ?? 30_000);
41
+ deadline.unref?.();
42
+ // Catch synchronous close failures as well. Duplicate signals never start a
43
+ // second logout or race the connection pool's credential/session cleanup.
44
+ void Promise.resolve()
45
+ .then(input.close)
46
+ .then(
47
+ () => finish(0),
48
+ () => finish(1),
49
+ );
50
+ }
51
+ runtime.on("SIGINT", shutdown);
52
+ runtime.on("SIGTERM", shutdown);
53
+ return dispose;
54
+ }
@@ -65,7 +65,9 @@ export function workspaceGatewaySecretArguments(input: {
65
65
  settings: Settings;
66
66
  grant: AccessGrant;
67
67
  /** Connected vaults (1Password, host) for the resolved acting subject. */
68
- providersForSubject?: ((subjectId: string | null) => VaultProviderRegistry) | undefined;
68
+ providersForSubject?:
69
+ | ((subjectId: string | null, site?: SiteSecretContext | null) => VaultProviderRegistry)
70
+ | undefined;
69
71
  }): ToolGatewayArgumentResolver {
70
72
  const encryptionKey = environmentsEncryptionKeyBytes(input.settings) ?? null;
71
73
  return async (call) => {
@@ -92,7 +94,12 @@ export function workspaceGatewaySecretArguments(input: {
92
94
  workspaceGatewaySecretPrincipal(input.grant, site),
93
95
  {
94
96
  capabilityEnabled: true,
95
- ...(input.providersForSubject ? { providersForSubject: input.providersForSubject } : {}),
97
+ ...(input.providersForSubject
98
+ ? {
99
+ providersForSubject: (subjectId: string | null) =>
100
+ input.providersForSubject!(subjectId, site),
101
+ }
102
+ : {}),
96
103
  },
97
104
  );
98
105
  const hook = createSecretArgumentResolver({
@@ -993,8 +993,12 @@ async function prepareWorkspaceToolGatewayForGrantInternal(
993
993
  db: routeDeps.db,
994
994
  settings: gatewaySettings,
995
995
  grant,
996
- providersForSubject: (subjectId) =>
997
- vaultProviderRegistryFor(routeDeps, { workspaceId: grant.workspaceId, subjectId }),
996
+ providersForSubject: (subjectId, site) =>
997
+ vaultProviderRegistryFor(routeDeps, {
998
+ workspaceId: grant.workspaceId,
999
+ subjectId,
1000
+ ...(site ? { executionContext: { siteId: site.siteId } } : {}),
1001
+ }),
998
1002
  }),
999
1003
  mapDefinition: (definition) => {
1000
1004
  // Raw/local providers have no native credential revision. The legacy