@opengeni/config 0.7.22 → 0.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/config",
3
- "version": "0.7.22",
3
+ "version": "0.8.1",
4
4
  "description": "OpenGeni runtime configuration: settings resolution, deployment knobs, and config validation shared across the server packages.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@opengeni/codex": "^0.2.9",
37
- "@opengeni/contracts": "^0.26.1",
37
+ "@opengeni/contracts": "^0.27.0",
38
38
  "zod": "^4.2.1"
39
39
  },
40
40
  "engines": {
package/src/index.ts CHANGED
@@ -269,6 +269,7 @@ const SettingsSchema = z.object({
269
269
  integrationsOauthClientsJson: z.string().default("{}"),
270
270
  slackClientId: z.string().optional(),
271
271
  slackClientSecret: z.string().optional(),
272
+ slackSigningSecret: z.string().optional(),
272
273
  googleDriveClientId: z.string().optional(),
273
274
  googleDriveClientSecret: z.string().optional(),
274
275
  // Undefined is meaningful: the migration boundary persists the product
@@ -328,6 +329,9 @@ const SettingsSchema = z.object({
328
329
  apiPort: z.coerce.number().int().positive().default(8000),
329
330
  workerHttpPort: z.coerce.number().int().positive().default(8001),
330
331
  opengeniMcpUrl: z.string().url().optional(),
332
+ // Origins allowed to send browser cookies cross-origin. Other origins may
333
+ // call the public API with bearer credentials, but never receive credentialed
334
+ // CORS responses.
331
335
  corsAllowOriginRegex: z.string().default(String.raw`^https?://(localhost|127\.0\.0\.1)(:\d+)?$`),
332
336
  openaiProvider: z.enum(["openai", "azure"]).default("openai"),
333
337
  openaiApiKey: z.string().optional(),
@@ -1016,7 +1020,11 @@ export function resolveVoiceInputProviderRegistry(settings: Settings): VoiceInpu
1016
1020
  // subscription turns. VOICE_INPUT_CODEX_EXPERIMENTAL is retained for
1017
1021
  // back-compat docs/env but no longer gates inclusion.
1018
1022
  if (!settings.codexSubscriptionEnabled) continue;
1019
- providers.push({ id: "codex-subscription", kind: "codex-subscription", experimental: true });
1023
+ providers.push({
1024
+ id: "codex-subscription",
1025
+ kind: "codex-subscription",
1026
+ experimental: true,
1027
+ });
1020
1028
  }
1021
1029
  }
1022
1030
  return providers;
@@ -1588,6 +1596,7 @@ export function getSettings(): Settings {
1588
1596
  integrationsOauthClientsJson: optional("OPENGENI_INTEGRATIONS_OAUTH_CLIENTS_JSON"),
1589
1597
  slackClientId: optional("OPENGENI_SLACK_CLIENT_ID"),
1590
1598
  slackClientSecret: optional("OPENGENI_SLACK_CLIENT_SECRET"),
1599
+ slackSigningSecret: optional("OPENGENI_SLACK_SIGNING_SECRET"),
1591
1600
  googleDriveClientId: optional("OPENGENI_GOOGLE_DRIVE_CLIENT_ID"),
1592
1601
  googleDriveClientSecret: optional("OPENGENI_GOOGLE_DRIVE_CLIENT_SECRET"),
1593
1602
  maxNestedAgentDepth: optional("OPENGENI_MAX_NESTED_AGENT_DEPTH"),
@@ -1820,6 +1829,23 @@ export function getSettings(): Settings {
1820
1829
  return settings;
1821
1830
  }
1822
1831
 
1832
+ const LOCAL_FIRST_PARTY_DELEGATION_SECRET = "opengeni-local-first-party-delegation-secret-v1";
1833
+
1834
+ /**
1835
+ * First-party session tools need a shared HMAC identity even in the unauthenticated
1836
+ * local product mode. A fixed local-only value is no broader than that mode's
1837
+ * existing access boundary, while configured and managed deployments continue to
1838
+ * require an operator-provided secret.
1839
+ */
1840
+ export function resolveFirstPartyDelegationSecret(settings: Settings): string | undefined {
1841
+ const explicit = settings.delegationSecret?.trim();
1842
+ if (explicit) return explicit;
1843
+ return settings.productAccessMode === "local" &&
1844
+ (settings.environment === "local" || settings.environment === "test")
1845
+ ? LOCAL_FIRST_PARTY_DELEGATION_SECRET
1846
+ : undefined;
1847
+ }
1848
+
1823
1849
  /**
1824
1850
  * The Modal sandbox idle timeout (seconds) the provider actually passes as
1825
1851
  * idleTimeoutMs (sandbox-file-persistence). When the operator did not pin
@@ -2271,8 +2297,16 @@ function builtinCredentialSource(settings: Settings): CredentialSourceV1 {
2271
2297
  }
2272
2298
 
2273
2299
  function staticRequestMetadataForDigest(provider: ResolvedModelProvider): {
2274
- headers: Array<{ name: string; classification: "public" | "secret"; value?: string }>;
2275
- query: Array<{ name: string; classification: "public" | "secret"; value?: string }>;
2300
+ headers: Array<{
2301
+ name: string;
2302
+ classification: "public" | "secret";
2303
+ value?: string;
2304
+ }>;
2305
+ query: Array<{
2306
+ name: string;
2307
+ classification: "public" | "secret";
2308
+ value?: string;
2309
+ }>;
2276
2310
  } {
2277
2311
  const publicHeaders = new Set(provider.publicDefaultHeaderNames ?? []);
2278
2312
  const publicQuery = new Set(provider.publicDefaultQueryNames ?? []);
@@ -2450,7 +2484,10 @@ export function withCodexCatalogProvider(settings: Settings): Settings {
2450
2484
  };
2451
2485
  }),
2452
2486
  };
2453
- return { ...settings, modelProvidersJson: JSON.stringify([...providers, provider]) };
2487
+ return {
2488
+ ...settings,
2489
+ modelProvidersJson: JSON.stringify([...providers, provider]),
2490
+ };
2454
2491
  }
2455
2492
 
2456
2493
  /**
@@ -2656,7 +2693,9 @@ export function configuredModels(settings: Settings): ConfiguredModel[] {
2656
2693
  : { contextWindowTokens: model.contextWindowTokens }),
2657
2694
  ...(model.effectiveContextWindowTokens === undefined
2658
2695
  ? {}
2659
- : { effectiveContextWindowTokens: model.effectiveContextWindowTokens }),
2696
+ : {
2697
+ effectiveContextWindowTokens: model.effectiveContextWindowTokens,
2698
+ }),
2660
2699
  ...(model.autoCompactTokenLimit === undefined
2661
2700
  ? {}
2662
2701
  : { autoCompactTokenLimit: model.autoCompactTokenLimit }),
@@ -3435,7 +3474,9 @@ export function parseMcpServers(raw: string | undefined): unknown[] | undefined
3435
3474
  return parsed;
3436
3475
  } catch (error) {
3437
3476
  const message = error instanceof Error ? error.message : String(error);
3438
- throw new Error(`OPENGENI_MCP_SERVERS must be a JSON array: ${message}`, { cause: error });
3477
+ throw new Error(`OPENGENI_MCP_SERVERS must be a JSON array: ${message}`, {
3478
+ cause: error,
3479
+ });
3439
3480
  }
3440
3481
  }
3441
3482
 
@@ -3821,6 +3862,11 @@ function validateSettings(settings: Settings): void {
3821
3862
  );
3822
3863
  }
3823
3864
  if (settings.slackClientId) {
3865
+ if (!settings.slackSigningSecret) {
3866
+ throw new Error(
3867
+ "OPENGENI_SLACK_SIGNING_SECRET is required when the OpenGeni Slack app is configured",
3868
+ );
3869
+ }
3824
3870
  if (!settings.publicBaseUrl) {
3825
3871
  throw new Error(
3826
3872
  "OPENGENI_PUBLIC_BASE_URL is required when the OpenGeni Slack app is configured",