@opengeni/core 2.5.3 → 2.6.4-canary.0

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.
Files changed (46) hide show
  1. package/dist/access/index.d.ts +24 -0
  2. package/dist/billing/limits.d.ts +5 -0
  3. package/dist/canonical-human-identities.js +2 -2
  4. package/dist/{chunk-ZVZJTMSV.js → chunk-OF65T3PM.js} +2 -2
  5. package/dist/{chunk-YGOMUGYS.js → chunk-QO5GVFFO.js} +17 -8
  6. package/dist/{chunk-YGOMUGYS.js.map → chunk-QO5GVFFO.js.map} +1 -1
  7. package/dist/dependencies.d.ts +10 -1
  8. package/dist/domain/company-brain-governed-writes.d.ts +15 -6
  9. package/dist/domain/company-profile-agent-admin.d.ts +3 -2
  10. package/dist/domain/environments.d.ts +1 -1
  11. package/dist/domain/memory-slack-delivery.d.ts +4 -1
  12. package/dist/domain/personal-connection-delegations.d.ts +1 -0
  13. package/dist/domain/pr-review.d.ts +1 -1
  14. package/dist/domain/scheduled-tasks.d.ts +12 -0
  15. package/dist/domain/sessions.d.ts +37 -11
  16. package/dist/domain/workspace-members.d.ts +8 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +1706 -667
  19. package/dist/index.js.map +1 -1
  20. package/dist/managed-auth-session-sets.d.ts +18 -0
  21. package/dist/managed-auth-session-sets.js +3 -1
  22. package/dist/model-catalog.d.ts +89 -0
  23. package/dist/sandbox/fleet.d.ts +6 -4
  24. package/dist/sandbox/routing.d.ts +7 -2
  25. package/dist/sandbox/runtime-settings.d.ts +17 -1
  26. package/package.json +10 -10
  27. package/src/access/index.ts +140 -5
  28. package/src/application/user-resource-grants.ts +31 -2
  29. package/src/billing/limits.ts +57 -24
  30. package/src/dependencies.ts +15 -1
  31. package/src/domain/company-brain-governed-writes.ts +29 -13
  32. package/src/domain/company-profile-agent-admin.ts +3 -2
  33. package/src/domain/environments.ts +6 -34
  34. package/src/domain/memory-slack-delivery.ts +30 -0
  35. package/src/domain/personal-connection-delegations.ts +40 -7
  36. package/src/domain/remember.ts +5 -6
  37. package/src/domain/scheduled-tasks.ts +146 -1
  38. package/src/domain/sessions.ts +912 -358
  39. package/src/domain/workspace-members.ts +34 -2
  40. package/src/index.ts +1 -0
  41. package/src/managed-auth-session-sets.ts +38 -11
  42. package/src/model-catalog.ts +565 -0
  43. package/src/sandbox/fleet.ts +20 -17
  44. package/src/sandbox/routing.ts +18 -4
  45. package/src/sandbox/runtime-settings.ts +32 -0
  46. /package/dist/{chunk-ZVZJTMSV.js.map → chunk-OF65T3PM.js.map} +0 -0
@@ -4,6 +4,16 @@ import { type Database } from "@opengeni/db";
4
4
  import type { Context } from "hono";
5
5
  import type { ManagedAuth } from "../managed-auth-type.js";
6
6
  import type { ManagedAuthSessionAdapter } from "../managed-auth-session-sets.js";
7
+ export type AccountScopedApiKeyWorkspaceAuthority = Readonly<{
8
+ accountId: string;
9
+ permissions: Permission[];
10
+ }>;
11
+ /**
12
+ * Return account-scoped API-key workspace authority only for the exact
13
+ * AccessContext object stamped by successful API-key authentication. Subject
14
+ * shape alone is deliberately insufficient.
15
+ */
16
+ export declare function accountScopedApiKeyWorkspaceAuthority(context: AccessContext): AccountScopedApiKeyWorkspaceAuthority | null;
7
17
  /**
8
18
  * Opaque, request-local proof that the canonical access resolver authorized the
9
19
  * exact account administrator named by the stamp. The random id is audit and
@@ -44,6 +54,8 @@ export type AccessGrantAuthorization = {
44
54
  * principal, and for any future path that does not verify a cookie.
45
55
  */
46
56
  canonicalManagedHumanSession: boolean;
57
+ /** Exact in-process single-user local bootstrap, never a delegated bearer. */
58
+ canonicalLocalHumanSession: boolean;
47
59
  };
48
60
  export declare function accessGrantAuthorizationFromContext(context: AccessContext, grant: AccessGrant): AccessGrantAuthorization;
49
61
  /**
@@ -56,6 +68,18 @@ export declare function accessGrantAuthorizationFromContext(context: AccessConte
56
68
  * access resolver are present in `resolvedAccessGrantAuthorizations`.
57
69
  */
58
70
  export declare function requireAccountAdminAuthorizationStamp(authorization: AccessGrantAuthorization): AccountAdminAuthorizationStamp;
71
+ /**
72
+ * Resolve the exact built-in single-user local administrator for an account.
73
+ *
74
+ * This is intentionally narrower than checking `context.mode === "local"` or
75
+ * the `dev` subject name. Only the in-process local bootstrap branch can place
76
+ * the resolved context in `canonicalLocalHumanContexts`, so delegated bearer
77
+ * tokens and caller-constructed contexts cannot borrow this authority.
78
+ */
79
+ export declare function requireCanonicalLocalAccountAdministrator(c: Context, deps: AccessDeps, accountId: string): Promise<{
80
+ subjectId: string;
81
+ authorization: AccessGrantAuthorization;
82
+ }>;
59
83
  export declare function requireAccessGrantAuthorization(c: Context, deps: AccessDeps, workspaceId: string, permission?: Permission): Promise<AccessGrantAuthorization>;
60
84
  export declare function requirePermission(grant: AccessGrant, permission: Permission): void;
61
85
  /**
@@ -1,3 +1,4 @@
1
+ import { type Settings } from "@opengeni/config";
1
2
  import type { LimitAction, LimitDecision, SessionTurnSource, TurnInitiator, TurnInitiatorContext } from "@opengeni/contracts";
2
3
  import type { ApiRouteDeps } from "../dependencies.js";
3
4
  export type LimitDependencies = Pick<ApiRouteDeps, "db" | "settings">;
@@ -8,6 +9,10 @@ export type LimitCheckInput = {
8
9
  quantity?: number;
9
10
  model?: string | null;
10
11
  };
12
+ export declare function modelFundingForAdmission(settings: Settings, model: string | null | undefined, codexBilled: boolean): {
13
+ fundedWithoutCredits: boolean;
14
+ countsTowardTokenCap: boolean;
15
+ };
11
16
  export declare function requireLimit(deps: LimitDependencies, input: LimitCheckInput): Promise<void>;
12
17
  export declare function checkLimit(deps: LimitDependencies, input: LimitCheckInput): Promise<LimitDecision>;
13
18
  export declare function recordWorkspaceUsage(deps: LimitDependencies, input: {
@@ -3,8 +3,8 @@ import {
3
3
  getManagedAuthRequestActorLeaseStamp,
4
4
  getManagedSession,
5
5
  markManagedAuthRequestActorTransitionApplied
6
- } from "./chunk-ZVZJTMSV.js";
7
- import "./chunk-YGOMUGYS.js";
6
+ } from "./chunk-OF65T3PM.js";
7
+ import "./chunk-QO5GVFFO.js";
8
8
 
9
9
  // src/canonical-human-identities.ts
10
10
  import { HTTPException } from "hono/http-exception";
@@ -4,7 +4,7 @@ import {
4
4
  ManagedAuthActorChangeError,
5
5
  managedAuthSha256,
6
6
  resolveManagedAuthSelectedSession
7
- } from "./chunk-YGOMUGYS.js";
7
+ } from "./chunk-QO5GVFFO.js";
8
8
 
9
9
  // src/managed-session.ts
10
10
  import {
@@ -366,4 +366,4 @@ export {
366
366
  getManagedAuthRequestActorAdmissionStamp,
367
367
  getManagedAuthRequestActorLeaseStamp
368
368
  };
369
- //# sourceMappingURL=chunk-ZVZJTMSV.js.map
369
+ //# sourceMappingURL=chunk-OF65T3PM.js.map
@@ -142,25 +142,33 @@ async function authenticateAndAdoptManagedAuthSession(input) {
142
142
  credentials: { email: input.email, password: input.password },
143
143
  headers: input.isolatedHeaders
144
144
  });
145
+ return await adoptManagedAuthSession({
146
+ ...input,
147
+ authorityHash: managedAuthSha256(input.authority),
148
+ transactionSecretHash: managedAuthSha256(input.transactionSecret),
149
+ authSessionId: created.authSessionId
150
+ });
151
+ }
152
+ async function adoptManagedAuthSession(input) {
145
153
  let completed;
146
154
  try {
147
155
  completed = await completeManagedAuthLoginTransaction(input.db, {
148
- authorityHash: managedAuthSha256(input.authority),
156
+ authorityHash: input.authorityHash,
149
157
  csrfHash: input.csrfHash,
150
158
  operationId: input.operationId,
151
159
  requestDigest: input.requestDigest,
152
160
  expectedGeneration: input.expectedGeneration,
153
161
  expectedActorEpoch: input.expectedActorEpoch,
154
162
  transactionId: input.transactionId,
155
- transactionSecretHash: managedAuthSha256(input.transactionSecret),
156
- authSessionId: created.authSessionId,
163
+ transactionSecretHash: input.transactionSecretHash,
164
+ authSessionId: input.authSessionId,
157
165
  mode: input.mode
158
166
  });
159
167
  } catch (error) {
160
168
  let receipt;
161
169
  try {
162
170
  receipt = await getManagedAuthSessionSetOperationReceipt(input.db, {
163
- authorityHash: managedAuthSha256(input.authority),
171
+ authorityHash: input.authorityHash,
164
172
  operationId: input.operationId,
165
173
  requestDigest: input.requestDigest
166
174
  });
@@ -168,14 +176,14 @@ async function authenticateAndAdoptManagedAuthSession(input) {
168
176
  throw new ManagedAuthCompletionOutcomeUnknownError({ cause: receiptError });
169
177
  }
170
178
  if (receipt) {
171
- await reconcileCreatedManagedAuthSession(input, created.authSessionId);
179
+ await reconcileCreatedManagedAuthSession(input, input.authSessionId);
172
180
  return receipt;
173
181
  }
174
- await input.adapter.revokeSession(created).catch(() => void 0);
182
+ await input.adapter.revokeSession({ authSessionId: input.authSessionId }).catch(() => void 0);
175
183
  throw error;
176
184
  }
177
185
  try {
178
- await reconcileCreatedManagedAuthSession(input, created.authSessionId);
186
+ await reconcileCreatedManagedAuthSession(input, input.authSessionId);
179
187
  } catch (error) {
180
188
  throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });
181
189
  }
@@ -221,6 +229,7 @@ export {
221
229
  requireManagedAuthMutationAdmission,
222
230
  resolveManagedAuthSelectedSession,
223
231
  authenticateAndAdoptManagedAuthSession,
232
+ adoptManagedAuthSession,
224
233
  isolatedManagedAuthHeaders
225
234
  };
226
- //# sourceMappingURL=chunk-YGOMUGYS.js.map
235
+ //# sourceMappingURL=chunk-QO5GVFFO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/managed-auth-session-sets.ts"],"sourcesContent":["import { createHash, createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type {\n ManagedAuthSessionSetMode,\n ManagedAuthSessionSetProjection,\n} from \"@opengeni/contracts/managed-auth-session-sets\";\nimport {\n completeManagedAuthLoginTransaction,\n getManagedAuthSessionSetOperationReceipt,\n getManagedAuthSessionSetSnapshot,\n type Database,\n type ManagedAuthDatabaseProjection,\n type ManagedAuthSelectedSession,\n} from \"@opengeni/db\";\n\nexport const MANAGED_AUTH_SESSION_SET_COOKIE = \"opengeni.session_set\" as const;\nexport const MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE = \"opengeni.login_transaction\" as const;\nexport const MANAGED_AUTH_CSRF_HEADER = \"x-opengeni-session-csrf\" as const;\nexport const MANAGED_AUTH_ACTOR_EPOCH_HEADER = \"x-opengeni-actor-epoch\" as const;\nexport const MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE_PATH =\n \"/v1/auth/session-set/transactions\" as const;\n\nexport type ManagedAuthResolvedSession = {\n session: { id: string; userId: string; [key: string]: unknown };\n user: {\n id: string;\n email: string;\n name: string;\n emailVerified: boolean;\n [key: string]: unknown;\n };\n};\n\n/** Provider-neutral boundary; provider credentials and tokens never cross its output. */\nexport interface ManagedAuthSessionAdapter {\n authenticate(input: {\n provider: \"email_password\";\n transactionId: string;\n credentials: { email: string; password: string };\n headers: Headers;\n }): Promise<{ authSessionId: string }>;\n /** Verify an ambient provider cookie without sliding expiry or emitting cookies. */\n resolveAmbientSession(headers: Headers): Promise<ManagedAuthResolvedSession | null>;\n resolveSelectedSession(\n input: ManagedAuthSelectedSession,\n ): Promise<ManagedAuthResolvedSession | null>;\n refreshSelectedSession(\n input: ManagedAuthSelectedSession,\n ): Promise<ManagedAuthResolvedSession | null>;\n revokeSession(input: { authSessionId: string }): Promise<void>;\n /** Dual-mode exact selected-session cookie plus stale provider-cache invalidations. */\n createLegacySelectedSessionCookies(\n input: ManagedAuthSelectedSession | null,\n currentCookieHeader?: string | null,\n ): Promise<string[]>;\n}\n\nexport class ManagedAuthActorChangeError extends Error {\n readonly name = \"ManagedAuthActorChangeError\";\n readonly code = \"actor_change_required\";\n constructor() {\n super(\"The selected browser actor changed\");\n }\n}\n\nexport class ManagedAuthRequestAdmissionError extends Error {\n readonly name = \"ManagedAuthRequestAdmissionError\";\n readonly code = \"origin_rejected\";\n}\n\nexport class ManagedAuthCompletionOutcomeUnknownError extends Error {\n readonly name = \"ManagedAuthCompletionOutcomeUnknownError\";\n readonly code = \"operation_outcome_unknown\";\n constructor(options?: ErrorOptions) {\n super(\"The managed authentication completion outcome is unknown\", options);\n }\n}\n\nexport function requireManagedAuthActorFence(input: {\n mode: ManagedAuthSessionSetMode;\n actorEpoch: string;\n expectedActorEpoch: string | null;\n selectedAuthSessionId: string | null;\n legacyAmbientSessionId?: string | null;\n}): void {\n if (\n (input.expectedActorEpoch !== null && input.expectedActorEpoch !== input.actorEpoch) ||\n (input.expectedActorEpoch === null &&\n (input.mode === \"broker\" ||\n input.actorEpoch !== \"1\" ||\n (input.selectedAuthSessionId !== null &&\n input.legacyAmbientSessionId !== input.selectedAuthSessionId)))\n ) {\n throw new ManagedAuthActorChangeError();\n }\n}\n\nexport function managedAuthRandomAuthority(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function managedAuthSha256(value: string): string {\n return createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n}\n\nexport function managedAuthCsrfHash(authority: string): string {\n return managedAuthSha256(`opengeni:managed-auth:csrf-authority:v1\\n${authority}`);\n}\n\nexport function managedAuthCsrfToken(\n signingSecret: string,\n authority: string,\n generation: string,\n): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:csrf:v1\\n${authority}\\n${generation}`, \"utf8\")\n .digest(\"base64url\");\n}\n\nexport function managedAuthTransactionSecret(\n signingSecret: string,\n authority: string,\n operationId: string,\n): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:transaction:v1\\n${authority}\\n${operationId}`, \"utf8\")\n .digest(\"base64url\");\n}\n\nexport function managedAuthDerivedUuid(namespace: string, value: string): string {\n const bytes = createHash(\"sha256\")\n .update(`${namespace}\\n${value}`, \"utf8\")\n .digest()\n .subarray(0, 16);\n bytes[6] = (bytes[6]! & 0x0f) | 0x50;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = bytes.toString(\"hex\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(\",\")}]`;\n return `{${Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`)\n .join(\",\")}}`;\n}\n\nexport function managedAuthRequestDigest(value: unknown): string {\n return managedAuthSha256(canonicalJson(value));\n}\n\nexport function managedAuthSecretRequestDigest(signingSecret: string, value: unknown): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:request:v1\\n${canonicalJson(value)}`, \"utf8\")\n .digest(\"hex\");\n}\n\nexport function withManagedAuthCsrfToken(\n projection: ManagedAuthDatabaseProjection,\n signingSecret: string,\n authority: string,\n): ManagedAuthSessionSetProjection {\n return {\n ...projection,\n csrfToken: managedAuthCsrfToken(signingSecret, authority, projection.generation),\n };\n}\n\nfunction equalSecret(left: string, right: string): boolean {\n const leftBytes = Buffer.from(left, \"utf8\");\n const rightBytes = Buffer.from(right, \"utf8\");\n return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes);\n}\n\nexport function requireManagedAuthMutationAdmission(input: {\n request: Request;\n allowedOrigins: readonly string[];\n authority: string;\n signingSecret: string;\n expectedGeneration: string;\n}): void {\n const origin = input.request.headers.get(\"origin\");\n const fetchSite = input.request.headers.get(\"sec-fetch-site\");\n const contentType = input.request.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim();\n const csrf = input.request.headers.get(MANAGED_AUTH_CSRF_HEADER);\n const allowed = new Set(input.allowedOrigins.map((candidate) => new URL(candidate).origin));\n const expectedCsrf = managedAuthCsrfToken(\n input.signingSecret,\n input.authority,\n input.expectedGeneration,\n );\n if (\n !origin ||\n !allowed.has(origin) ||\n fetchSite !== \"same-origin\" ||\n contentType !== \"application/json\" ||\n !csrf ||\n !equalSecret(csrf, expectedCsrf)\n ) {\n throw new ManagedAuthRequestAdmissionError(\"Browser session-set mutation admission failed\");\n }\n}\n\nexport async function resolveManagedAuthSelectedSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n authority: string;\n mode: ManagedAuthSessionSetMode;\n expectedActorEpoch: string | null;\n legacyAmbientSessionId?: string | null;\n allowRecovery?: boolean;\n}): Promise<{\n session: ManagedAuthResolvedSession | null;\n projection: ManagedAuthDatabaseProjection;\n} | null> {\n const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n mode: input.mode,\n includeInternal: true,\n allowRecovery: input.allowRecovery ?? false,\n readOnly: true,\n });\n if (!snapshot) return null;\n if (snapshot.projection.state === \"actor_change_required\") {\n throw new ManagedAuthActorChangeError();\n }\n requireManagedAuthActorFence({\n mode: input.mode,\n actorEpoch: snapshot.projection.actorEpoch,\n expectedActorEpoch: input.expectedActorEpoch,\n selectedAuthSessionId: snapshot.selected?.authSessionId ?? null,\n legacyAmbientSessionId: input.legacyAmbientSessionId ?? null,\n });\n if (!snapshot.selected) return { session: null, projection: snapshot.projection };\n const resolved = await input.adapter.resolveSelectedSession(snapshot.selected);\n if (\n !resolved ||\n resolved.session.id !== snapshot.selected.authSessionId ||\n resolved.user.id !== snapshot.selected.authUserId\n ) {\n return { session: null, projection: snapshot.projection };\n }\n return { session: resolved, projection: snapshot.projection };\n}\n\nexport async function authenticateAndAdoptManagedAuthSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n isolatedHeaders: Headers;\n authority: string;\n csrfHash: string;\n operationId: string;\n requestDigest: string;\n expectedGeneration: string;\n expectedActorEpoch: string;\n transactionId: string;\n transactionSecret: string;\n email: string;\n password: string;\n mode: ManagedAuthSessionSetMode;\n}): Promise<{ projection: ManagedAuthDatabaseProjection; returnIntent: string | null }> {\n try {\n const existing = await getManagedAuthSessionSetOperationReceipt(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n });\n if (existing) return existing;\n } catch (error) {\n // Provider authentication creates a durable session. Do not perform it\n // while exact-replay reconciliation is unavailable.\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });\n }\n const created = await input.adapter.authenticate({\n provider: \"email_password\",\n transactionId: input.transactionId,\n credentials: { email: input.email, password: input.password },\n headers: input.isolatedHeaders,\n });\n let completed: { projection: ManagedAuthDatabaseProjection; returnIntent: string | null };\n try {\n completed = await completeManagedAuthLoginTransaction(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n csrfHash: input.csrfHash,\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n expectedGeneration: input.expectedGeneration,\n expectedActorEpoch: input.expectedActorEpoch,\n transactionId: input.transactionId,\n transactionSecretHash: managedAuthSha256(input.transactionSecret),\n authSessionId: created.authSessionId,\n mode: input.mode,\n });\n } catch (error) {\n let receipt: Awaited<ReturnType<typeof getManagedAuthSessionSetOperationReceipt>>;\n try {\n receipt = await getManagedAuthSessionSetOperationReceipt(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n });\n } catch (receiptError) {\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: receiptError });\n }\n if (receipt) {\n await reconcileCreatedManagedAuthSession(input, created.authSessionId);\n return receipt;\n }\n await input.adapter.revokeSession(created).catch(() => undefined);\n throw error;\n }\n try {\n await reconcileCreatedManagedAuthSession(input, created.authSessionId);\n } catch (error) {\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });\n }\n return completed;\n}\n\nasync function reconcileCreatedManagedAuthSession(\n input: Pick<\n Parameters<typeof authenticateAndAdoptManagedAuthSession>[0],\n \"db\" | \"adapter\" | \"authority\" | \"mode\"\n >,\n authSessionId: string,\n): Promise<void> {\n const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n mode: input.mode,\n includeInternal: true,\n readOnly: true,\n });\n if (snapshot?.internalSlots.some((slot) => slot.authSessionId === authSessionId)) return;\n await input.adapter.revokeSession({ authSessionId });\n}\n\nexport function isolatedManagedAuthHeaders(request: Request): Headers {\n const headers = new Headers(request.headers);\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n headers.delete(\"x-forwarded-user\");\n return headers;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/managed-auth-session-sets.ts"],"sourcesContent":["import { createHash, createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type {\n ManagedAuthSessionSetMode,\n ManagedAuthSessionSetProjection,\n} from \"@opengeni/contracts/managed-auth-session-sets\";\nimport {\n completeManagedAuthLoginTransaction,\n getManagedAuthSessionSetOperationReceipt,\n getManagedAuthSessionSetSnapshot,\n type Database,\n type ManagedAuthDatabaseProjection,\n type ManagedAuthSelectedSession,\n} from \"@opengeni/db\";\n\nexport const MANAGED_AUTH_SESSION_SET_COOKIE = \"opengeni.session_set\" as const;\nexport const MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE = \"opengeni.login_transaction\" as const;\nexport const MANAGED_AUTH_CSRF_HEADER = \"x-opengeni-session-csrf\" as const;\nexport const MANAGED_AUTH_ACTOR_EPOCH_HEADER = \"x-opengeni-actor-epoch\" as const;\nexport const MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE_PATH =\n \"/v1/auth/session-set/transactions\" as const;\n\nexport type ManagedAuthResolvedSession = {\n session: { id: string; userId: string; [key: string]: unknown };\n user: {\n id: string;\n email: string;\n name: string;\n emailVerified: boolean;\n [key: string]: unknown;\n };\n};\n\n/** Provider-neutral boundary; provider credentials and tokens never cross its output. */\nexport interface ManagedAuthSessionAdapter {\n authenticate(input: {\n provider: \"email_password\";\n transactionId: string;\n credentials: { email: string; password: string };\n headers: Headers;\n }): Promise<{ authSessionId: string }>;\n /** Verify an ambient provider cookie without sliding expiry or emitting cookies. */\n resolveAmbientSession(headers: Headers): Promise<ManagedAuthResolvedSession | null>;\n resolveSelectedSession(\n input: ManagedAuthSelectedSession,\n ): Promise<ManagedAuthResolvedSession | null>;\n refreshSelectedSession(\n input: ManagedAuthSelectedSession,\n ): Promise<ManagedAuthResolvedSession | null>;\n revokeSession(input: { authSessionId: string }): Promise<void>;\n /** Dual-mode exact selected-session cookie plus stale provider-cache invalidations. */\n createLegacySelectedSessionCookies(\n input: ManagedAuthSelectedSession | null,\n currentCookieHeader?: string | null,\n ): Promise<string[]>;\n}\n\nexport class ManagedAuthActorChangeError extends Error {\n readonly name = \"ManagedAuthActorChangeError\";\n readonly code = \"actor_change_required\";\n constructor() {\n super(\"The selected browser actor changed\");\n }\n}\n\nexport class ManagedAuthRequestAdmissionError extends Error {\n readonly name = \"ManagedAuthRequestAdmissionError\";\n readonly code = \"origin_rejected\";\n}\n\nexport class ManagedAuthCompletionOutcomeUnknownError extends Error {\n readonly name = \"ManagedAuthCompletionOutcomeUnknownError\";\n readonly code = \"operation_outcome_unknown\";\n constructor(options?: ErrorOptions) {\n super(\"The managed authentication completion outcome is unknown\", options);\n }\n}\n\nexport function requireManagedAuthActorFence(input: {\n mode: ManagedAuthSessionSetMode;\n actorEpoch: string;\n expectedActorEpoch: string | null;\n selectedAuthSessionId: string | null;\n legacyAmbientSessionId?: string | null;\n}): void {\n if (\n (input.expectedActorEpoch !== null && input.expectedActorEpoch !== input.actorEpoch) ||\n (input.expectedActorEpoch === null &&\n (input.mode === \"broker\" ||\n input.actorEpoch !== \"1\" ||\n (input.selectedAuthSessionId !== null &&\n input.legacyAmbientSessionId !== input.selectedAuthSessionId)))\n ) {\n throw new ManagedAuthActorChangeError();\n }\n}\n\nexport function managedAuthRandomAuthority(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function managedAuthSha256(value: string): string {\n return createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n}\n\nexport function managedAuthCsrfHash(authority: string): string {\n return managedAuthSha256(`opengeni:managed-auth:csrf-authority:v1\\n${authority}`);\n}\n\nexport function managedAuthCsrfToken(\n signingSecret: string,\n authority: string,\n generation: string,\n): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:csrf:v1\\n${authority}\\n${generation}`, \"utf8\")\n .digest(\"base64url\");\n}\n\nexport function managedAuthTransactionSecret(\n signingSecret: string,\n authority: string,\n operationId: string,\n): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:transaction:v1\\n${authority}\\n${operationId}`, \"utf8\")\n .digest(\"base64url\");\n}\n\nexport function managedAuthDerivedUuid(namespace: string, value: string): string {\n const bytes = createHash(\"sha256\")\n .update(`${namespace}\\n${value}`, \"utf8\")\n .digest()\n .subarray(0, 16);\n bytes[6] = (bytes[6]! & 0x0f) | 0x50;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = bytes.toString(\"hex\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(\",\")}]`;\n return `{${Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`)\n .join(\",\")}}`;\n}\n\nexport function managedAuthRequestDigest(value: unknown): string {\n return managedAuthSha256(canonicalJson(value));\n}\n\nexport function managedAuthSecretRequestDigest(signingSecret: string, value: unknown): string {\n return createHmac(\"sha256\", signingSecret)\n .update(`opengeni:managed-auth:request:v1\\n${canonicalJson(value)}`, \"utf8\")\n .digest(\"hex\");\n}\n\nexport function withManagedAuthCsrfToken(\n projection: ManagedAuthDatabaseProjection,\n signingSecret: string,\n authority: string,\n): ManagedAuthSessionSetProjection {\n return {\n ...projection,\n csrfToken: managedAuthCsrfToken(signingSecret, authority, projection.generation),\n };\n}\n\nfunction equalSecret(left: string, right: string): boolean {\n const leftBytes = Buffer.from(left, \"utf8\");\n const rightBytes = Buffer.from(right, \"utf8\");\n return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes);\n}\n\nexport function requireManagedAuthMutationAdmission(input: {\n request: Request;\n allowedOrigins: readonly string[];\n authority: string;\n signingSecret: string;\n expectedGeneration: string;\n}): void {\n const origin = input.request.headers.get(\"origin\");\n const fetchSite = input.request.headers.get(\"sec-fetch-site\");\n const contentType = input.request.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim();\n const csrf = input.request.headers.get(MANAGED_AUTH_CSRF_HEADER);\n const allowed = new Set(input.allowedOrigins.map((candidate) => new URL(candidate).origin));\n const expectedCsrf = managedAuthCsrfToken(\n input.signingSecret,\n input.authority,\n input.expectedGeneration,\n );\n if (\n !origin ||\n !allowed.has(origin) ||\n fetchSite !== \"same-origin\" ||\n contentType !== \"application/json\" ||\n !csrf ||\n !equalSecret(csrf, expectedCsrf)\n ) {\n throw new ManagedAuthRequestAdmissionError(\"Browser session-set mutation admission failed\");\n }\n}\n\nexport async function resolveManagedAuthSelectedSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n authority: string;\n mode: ManagedAuthSessionSetMode;\n expectedActorEpoch: string | null;\n legacyAmbientSessionId?: string | null;\n allowRecovery?: boolean;\n}): Promise<{\n session: ManagedAuthResolvedSession | null;\n projection: ManagedAuthDatabaseProjection;\n} | null> {\n const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n mode: input.mode,\n includeInternal: true,\n allowRecovery: input.allowRecovery ?? false,\n readOnly: true,\n });\n if (!snapshot) return null;\n if (snapshot.projection.state === \"actor_change_required\") {\n throw new ManagedAuthActorChangeError();\n }\n requireManagedAuthActorFence({\n mode: input.mode,\n actorEpoch: snapshot.projection.actorEpoch,\n expectedActorEpoch: input.expectedActorEpoch,\n selectedAuthSessionId: snapshot.selected?.authSessionId ?? null,\n legacyAmbientSessionId: input.legacyAmbientSessionId ?? null,\n });\n if (!snapshot.selected) return { session: null, projection: snapshot.projection };\n const resolved = await input.adapter.resolveSelectedSession(snapshot.selected);\n if (\n !resolved ||\n resolved.session.id !== snapshot.selected.authSessionId ||\n resolved.user.id !== snapshot.selected.authUserId\n ) {\n return { session: null, projection: snapshot.projection };\n }\n return { session: resolved, projection: snapshot.projection };\n}\n\nexport async function authenticateAndAdoptManagedAuthSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n isolatedHeaders: Headers;\n authority: string;\n csrfHash: string;\n operationId: string;\n requestDigest: string;\n expectedGeneration: string;\n expectedActorEpoch: string;\n transactionId: string;\n transactionSecret: string;\n email: string;\n password: string;\n mode: ManagedAuthSessionSetMode;\n}): Promise<{ projection: ManagedAuthDatabaseProjection; returnIntent: string | null }> {\n try {\n const existing = await getManagedAuthSessionSetOperationReceipt(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n });\n if (existing) return existing;\n } catch (error) {\n // Provider authentication creates a durable session. Do not perform it\n // while exact-replay reconciliation is unavailable.\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });\n }\n const created = await input.adapter.authenticate({\n provider: \"email_password\",\n transactionId: input.transactionId,\n credentials: { email: input.email, password: input.password },\n headers: input.isolatedHeaders,\n });\n return await adoptManagedAuthSession({\n ...input,\n authorityHash: managedAuthSha256(input.authority),\n transactionSecretHash: managedAuthSha256(input.transactionSecret),\n authSessionId: created.authSessionId,\n });\n}\n\nexport async function adoptManagedAuthSession(input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n authority: string;\n authorityHash: string;\n csrfHash: string;\n operationId: string;\n requestDigest: string;\n expectedGeneration: string;\n expectedActorEpoch: string;\n transactionId: string;\n transactionSecretHash: string;\n authSessionId: string;\n mode: ManagedAuthSessionSetMode;\n}): Promise<{ projection: ManagedAuthDatabaseProjection; returnIntent: string | null }> {\n let completed: { projection: ManagedAuthDatabaseProjection; returnIntent: string | null };\n try {\n completed = await completeManagedAuthLoginTransaction(input.db, {\n authorityHash: input.authorityHash,\n csrfHash: input.csrfHash,\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n expectedGeneration: input.expectedGeneration,\n expectedActorEpoch: input.expectedActorEpoch,\n transactionId: input.transactionId,\n transactionSecretHash: input.transactionSecretHash,\n authSessionId: input.authSessionId,\n mode: input.mode,\n });\n } catch (error) {\n let receipt: Awaited<ReturnType<typeof getManagedAuthSessionSetOperationReceipt>>;\n try {\n receipt = await getManagedAuthSessionSetOperationReceipt(input.db, {\n authorityHash: input.authorityHash,\n operationId: input.operationId,\n requestDigest: input.requestDigest,\n });\n } catch (receiptError) {\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: receiptError });\n }\n if (receipt) {\n await reconcileCreatedManagedAuthSession(input, input.authSessionId);\n return receipt;\n }\n await input.adapter\n .revokeSession({ authSessionId: input.authSessionId })\n .catch(() => undefined);\n throw error;\n }\n try {\n await reconcileCreatedManagedAuthSession(input, input.authSessionId);\n } catch (error) {\n throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });\n }\n return completed;\n}\n\nasync function reconcileCreatedManagedAuthSession(\n input: {\n db: Database;\n adapter: ManagedAuthSessionAdapter;\n authority: string;\n mode: ManagedAuthSessionSetMode;\n },\n authSessionId: string,\n): Promise<void> {\n const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {\n authorityHash: managedAuthSha256(input.authority),\n mode: input.mode,\n includeInternal: true,\n readOnly: true,\n });\n if (snapshot?.internalSlots.some((slot) => slot.authSessionId === authSessionId)) return;\n await input.adapter.revokeSession({ authSessionId });\n}\n\nexport function isolatedManagedAuthHeaders(request: Request): Headers {\n const headers = new Headers(request.headers);\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n headers.delete(\"x-forwarded-user\");\n return headers;\n}\n"],"mappings":";AAAA,SAAS,YAAY,YAAY,aAAa,uBAAuB;AAKrE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAEA,IAAM,kCAAkC;AACxC,IAAM,wCAAwC;AAC9C,IAAM,2BAA2B;AACjC,IAAM,kCAAkC;AACxC,IAAM,6CACX;AAqCK,IAAM,8BAAN,cAA0C,MAAM;AAAA,EAC5C,OAAO;AAAA,EACP,OAAO;AAAA,EAChB,cAAc;AACZ,UAAM,oCAAoC;AAAA,EAC5C;AACF;AAEO,IAAM,mCAAN,cAA+C,MAAM;AAAA,EACjD,OAAO;AAAA,EACP,OAAO;AAClB;AAEO,IAAM,2CAAN,cAAuD,MAAM;AAAA,EACzD,OAAO;AAAA,EACP,OAAO;AAAA,EAChB,YAAY,SAAwB;AAClC,UAAM,4DAA4D,OAAO;AAAA,EAC3E;AACF;AAEO,SAAS,6BAA6B,OAMpC;AACP,MACG,MAAM,uBAAuB,QAAQ,MAAM,uBAAuB,MAAM,cACxE,MAAM,uBAAuB,SAC3B,MAAM,SAAS,YACd,MAAM,eAAe,OACpB,MAAM,0BAA0B,QAC/B,MAAM,2BAA2B,MAAM,wBAC7C;AACA,UAAM,IAAI,4BAA4B;AAAA,EACxC;AACF;AAEO,SAAS,6BAAqC;AACnD,SAAO,YAAY,EAAE,EAAE,SAAS,WAAW;AAC7C;AAEO,SAAS,kBAAkB,OAAuB;AACvD,SAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,MAAM,EAAE,OAAO,KAAK;AAChE;AAEO,SAAS,oBAAoB,WAA2B;AAC7D,SAAO,kBAAkB;AAAA,EAA4C,SAAS,EAAE;AAClF;AAEO,SAAS,qBACd,eACA,WACA,YACQ;AACR,SAAO,WAAW,UAAU,aAAa,EACtC,OAAO;AAAA,EAAkC,SAAS;AAAA,EAAK,UAAU,IAAI,MAAM,EAC3E,OAAO,WAAW;AACvB;AAEO,SAAS,6BACd,eACA,WACA,aACQ;AACR,SAAO,WAAW,UAAU,aAAa,EACtC,OAAO;AAAA,EAAyC,SAAS;AAAA,EAAK,WAAW,IAAI,MAAM,EACnF,OAAO,WAAW;AACvB;AAEO,SAAS,uBAAuB,WAAmB,OAAuB;AAC/E,QAAM,QAAQ,WAAW,QAAQ,EAC9B,OAAO,GAAG,SAAS;AAAA,EAAK,KAAK,IAAI,MAAM,EACvC,OAAO,EACP,SAAS,GAAG,EAAE;AACjB,QAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAChC,QAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAChC,QAAM,MAAM,MAAM,SAAS,KAAK;AAChC,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;AAC1G;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK;AAC5E,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,aAAa,EAAE,KAAK,GAAG,CAAC;AACvE,SAAO,IAAI,OAAO,QAAQ,KAAgC,EACvD,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,KAAK,cAAc,KAAK,CAAC,EACnD,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,cAAc,KAAK,CAAC,EAAE,EACtE,KAAK,GAAG,CAAC;AACd;AAEO,SAAS,yBAAyB,OAAwB;AAC/D,SAAO,kBAAkB,cAAc,KAAK,CAAC;AAC/C;AAEO,SAAS,+BAA+B,eAAuB,OAAwB;AAC5F,SAAO,WAAW,UAAU,aAAa,EACtC,OAAO;AAAA,EAAqC,cAAc,KAAK,CAAC,IAAI,MAAM,EAC1E,OAAO,KAAK;AACjB;AAEO,SAAS,yBACd,YACA,eACA,WACiC;AACjC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,qBAAqB,eAAe,WAAW,WAAW,UAAU;AAAA,EACjF;AACF;AAEA,SAAS,YAAY,MAAc,OAAwB;AACzD,QAAM,YAAY,OAAO,KAAK,MAAM,MAAM;AAC1C,QAAM,aAAa,OAAO,KAAK,OAAO,MAAM;AAC5C,SAAO,UAAU,WAAW,WAAW,UAAU,gBAAgB,WAAW,UAAU;AACxF;AAEO,SAAS,oCAAoC,OAM3C;AACP,QAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI,QAAQ;AACjD,QAAM,YAAY,MAAM,QAAQ,QAAQ,IAAI,gBAAgB;AAC5D,QAAM,cAAc,MAAM,QAAQ,QAAQ,IAAI,cAAc,GAAG,MAAM,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK;AACtF,QAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,wBAAwB;AAC/D,QAAM,UAAU,IAAI,IAAI,MAAM,eAAe,IAAI,CAAC,cAAc,IAAI,IAAI,SAAS,EAAE,MAAM,CAAC;AAC1F,QAAM,eAAe;AAAA,IACnB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACA,MACE,CAAC,UACD,CAAC,QAAQ,IAAI,MAAM,KACnB,cAAc,iBACd,gBAAgB,sBAChB,CAAC,QACD,CAAC,YAAY,MAAM,YAAY,GAC/B;AACA,UAAM,IAAI,iCAAiC,+CAA+C;AAAA,EAC5F;AACF;AAEA,eAAsB,kCAAkC,OAW9C;AACR,QAAM,WAAW,MAAM,iCAAiC,MAAM,IAAI;AAAA,IAChE,eAAe,kBAAkB,MAAM,SAAS;AAAA,IAChD,MAAM,MAAM;AAAA,IACZ,iBAAiB;AAAA,IACjB,eAAe,MAAM,iBAAiB;AAAA,IACtC,UAAU;AAAA,EACZ,CAAC;AACD,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,WAAW,UAAU,yBAAyB;AACzD,UAAM,IAAI,4BAA4B;AAAA,EACxC;AACA,+BAA6B;AAAA,IAC3B,MAAM,MAAM;AAAA,IACZ,YAAY,SAAS,WAAW;AAAA,IAChC,oBAAoB,MAAM;AAAA,IAC1B,uBAAuB,SAAS,UAAU,iBAAiB;AAAA,IAC3D,wBAAwB,MAAM,0BAA0B;AAAA,EAC1D,CAAC;AACD,MAAI,CAAC,SAAS,SAAU,QAAO,EAAE,SAAS,MAAM,YAAY,SAAS,WAAW;AAChF,QAAM,WAAW,MAAM,MAAM,QAAQ,uBAAuB,SAAS,QAAQ;AAC7E,MACE,CAAC,YACD,SAAS,QAAQ,OAAO,SAAS,SAAS,iBAC1C,SAAS,KAAK,OAAO,SAAS,SAAS,YACvC;AACA,WAAO,EAAE,SAAS,MAAM,YAAY,SAAS,WAAW;AAAA,EAC1D;AACA,SAAO,EAAE,SAAS,UAAU,YAAY,SAAS,WAAW;AAC9D;AAEA,eAAsB,uCAAuC,OAe2B;AACtF,MAAI;AACF,UAAM,WAAW,MAAM,yCAAyC,MAAM,IAAI;AAAA,MACxE,eAAe,kBAAkB,MAAM,SAAS;AAAA,MAChD,aAAa,MAAM;AAAA,MACnB,eAAe,MAAM;AAAA,IACvB,CAAC;AACD,QAAI,SAAU,QAAO;AAAA,EACvB,SAAS,OAAO;AAGd,UAAM,IAAI,yCAAyC,EAAE,OAAO,MAAM,CAAC;AAAA,EACrE;AACA,QAAM,UAAU,MAAM,MAAM,QAAQ,aAAa;AAAA,IAC/C,UAAU;AAAA,IACV,eAAe,MAAM;AAAA,IACrB,aAAa,EAAE,OAAO,MAAM,OAAO,UAAU,MAAM,SAAS;AAAA,IAC5D,SAAS,MAAM;AAAA,EACjB,CAAC;AACD,SAAO,MAAM,wBAAwB;AAAA,IACnC,GAAG;AAAA,IACH,eAAe,kBAAkB,MAAM,SAAS;AAAA,IAChD,uBAAuB,kBAAkB,MAAM,iBAAiB;AAAA,IAChE,eAAe,QAAQ;AAAA,EACzB,CAAC;AACH;AAEA,eAAsB,wBAAwB,OAc0C;AACtF,MAAI;AACJ,MAAI;AACF,gBAAY,MAAM,oCAAoC,MAAM,IAAI;AAAA,MAC9D,eAAe,MAAM;AAAA,MACrB,UAAU,MAAM;AAAA,MAChB,aAAa,MAAM;AAAA,MACnB,eAAe,MAAM;AAAA,MACrB,oBAAoB,MAAM;AAAA,MAC1B,oBAAoB,MAAM;AAAA,MAC1B,eAAe,MAAM;AAAA,MACrB,uBAAuB,MAAM;AAAA,MAC7B,eAAe,MAAM;AAAA,MACrB,MAAM,MAAM;AAAA,IACd,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,yCAAyC,MAAM,IAAI;AAAA,QACjE,eAAe,MAAM;AAAA,QACrB,aAAa,MAAM;AAAA,QACnB,eAAe,MAAM;AAAA,MACvB,CAAC;AAAA,IACH,SAAS,cAAc;AACrB,YAAM,IAAI,yCAAyC,EAAE,OAAO,aAAa,CAAC;AAAA,IAC5E;AACA,QAAI,SAAS;AACX,YAAM,mCAAmC,OAAO,MAAM,aAAa;AACnE,aAAO;AAAA,IACT;AACA,UAAM,MAAM,QACT,cAAc,EAAE,eAAe,MAAM,cAAc,CAAC,EACpD,MAAM,MAAM,MAAS;AACxB,UAAM;AAAA,EACR;AACA,MAAI;AACF,UAAM,mCAAmC,OAAO,MAAM,aAAa;AAAA,EACrE,SAAS,OAAO;AACd,UAAM,IAAI,yCAAyC,EAAE,OAAO,MAAM,CAAC;AAAA,EACrE;AACA,SAAO;AACT;AAEA,eAAe,mCACb,OAMA,eACe;AACf,QAAM,WAAW,MAAM,iCAAiC,MAAM,IAAI;AAAA,IAChE,eAAe,kBAAkB,MAAM,SAAS;AAAA,IAChD,MAAM,MAAM;AAAA,IACZ,iBAAiB;AAAA,IACjB,UAAU;AAAA,EACZ,CAAC;AACD,MAAI,UAAU,cAAc,KAAK,CAAC,SAAS,KAAK,kBAAkB,aAAa,EAAG;AAClF,QAAM,MAAM,QAAQ,cAAc,EAAE,cAAc,CAAC;AACrD;AAEO,SAAS,2BAA2B,SAA2B;AACpE,QAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,UAAQ,OAAO,QAAQ;AACvB,UAAQ,OAAO,eAAe;AAC9B,UAAQ,OAAO,kBAAkB;AACjC,SAAO;AACT;","names":[]}
@@ -10,6 +10,7 @@ import type { ManagedAuthSessionAdapter } from "./managed-auth-session-sets.js";
10
10
  import type { ApiSandboxClient, ResumeBoxByIdInput, ResumedSandboxSession } from "./sandbox-types.js";
11
11
  import type { TranscriptionSegmenter, TranscriptionService } from "./transcription.js";
12
12
  import type { EditableArtifactApplicationPort } from "./editable-artifact-live.js";
13
+ import type { ResolvedCatalogSettings } from "./model-catalog.js";
13
14
  import type { EditableArtifactAgentApplication, EditableArtifactDurableExportService, EditableArtifactOfficeImportPort } from "./editable-artifacts.js";
14
15
  export type SessionWorkflowClient = {
15
16
  triggerAutomationRun?: (input: {
@@ -114,6 +115,13 @@ export type ManagedEmailTransport = {
114
115
  };
115
116
  export type AppDependencies = {
116
117
  settings: Settings;
118
+ /**
119
+ * Original deployment settings when `settings` is already overlaid with a
120
+ * deployment/workspace catalog snapshot. Model-bearing request adapters set
121
+ * this marker so core admission never feeds a synthetic reviewed provider
122
+ * back through deployment validation.
123
+ */
124
+ catalogSourceSettings?: Settings;
117
125
  db: Database;
118
126
  /**
119
127
  * Host-composed editable artifact engine. Standalone startup binds the same
@@ -202,6 +210,7 @@ export type AppDependencies = {
202
210
  };
203
211
  export type ObjectStorageDependency = ReturnType<typeof createObjectStorage>;
204
212
  export type ApiRouteDeps = AppDependencies & {
213
+ resolveCatalogSettings: () => Promise<ResolvedCatalogSettings>;
205
214
  managedEmailTransport: ManagedEmailTransport;
206
215
  objectStorage: ObjectStorageDependency;
207
216
  githubStateSecret: string;
@@ -216,7 +225,7 @@ export type ApiRouteDeps = AppDependencies & {
216
225
  * the canonical admission path without constructing unrelated HTTP, document,
217
226
  * or sandbox services. The public API still passes its `ApiRouteDeps` superset.
218
227
  */
219
- export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit"> & {
228
+ export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "catalogSourceSettings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit"> & {
220
229
  workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
221
230
  objectStorage: ObjectStorageDependency;
222
231
  };
@@ -15,9 +15,8 @@ export type CompanyBrainGovernedWriteRouterOptions = {
15
15
  activate?: typeof activateGovernedLearningDecision;
16
16
  /**
17
17
  * Destinations the router may activate automatically from a final eligible
18
- * decision. Defaults to preferences only: mandatory instruction policy keeps
19
- * requiring human-authoritative activation even under `automatic`, so its
20
- * decision receipt is recorded but the inactive draft stays for review.
18
+ * decision. Defaults to Skills and instruction policy. Both still pass
19
+ * through the evaluator and destination-owned activation lifecycle.
21
20
  */
22
21
  automaticDestinations?: ReadonlyArray<GovernedLearningActivationDestination>;
23
22
  /**
@@ -33,6 +32,17 @@ export type CompanyBrainGovernedWriteRouterOptions = {
33
32
  }) => Promise<GovernedLearningSlackPublicationResult>;
34
33
  };
35
34
  export declare const DEFAULT_AUTOMATIC_LEARNING_DESTINATIONS: ReadonlyArray<GovernedLearningActivationDestination>;
35
+ /**
36
+ * Start a non-authoritative post-activation notification without making the
37
+ * durable activation receipt wait for its settlement. The callback is invoked
38
+ * synchronously so immediate enqueue work begins before the router returns;
39
+ * both synchronous throws and later promise rejections are contained.
40
+ *
41
+ * Exact retries intentionally dispatch again: the publication sink owns an
42
+ * activation-receipt idempotency key, while the activation receipt remains the
43
+ * caller-facing source of truth even if notification delivery stalls forever.
44
+ */
45
+ export declare function dispatchBestEffortGovernedLearningNotification(notify: () => Promise<unknown>): void;
36
46
  /**
37
47
  * Transport-neutral facade for explicit governed Company Brain proposals.
38
48
  * It intentionally exposes no generic remember call, selector, activation,
@@ -59,9 +69,8 @@ export declare function derivedGovernedLearningOperationId(operationId: string,
59
69
  * snapshot. `suggest` records the content-free decision receipt only. Under
60
70
  * `automatic`, a final `automaticEligible` receipt is handed to the activation
61
71
  * controller, which revalidates current authority and applies the change only
62
- * through the destination-owned lifecycle. By default only preferences may
63
- * activate automatically; mandatory instruction policy always keeps a human
64
- * activation boundary. Evaluation or activation failure
72
+ * through the destination-owned lifecycle. Eligible Skills and instruction
73
+ * policies may activate automatically. Evaluation or activation failure
65
74
  * never rolls back the durable proposal; it is reported as a bounded
66
75
  * `learningFailure` and the proposal remains for human review.
67
76
  */
@@ -9,8 +9,9 @@ export type CompanyProfileAgentAdminRouterOptions = {
9
9
  /**
10
10
  * Explicit organization administration is intentionally separate from derived
11
11
  * workspace learning. The database capabilities own exact-attempt admission,
12
- * current organization-owner authority, canonical human confirmation,
13
- * tenant isolation, CAS, and immutable receipts.
12
+ * current organization-owner authority, the separate organization policy,
13
+ * canonical review when required, tenant isolation, CAS, and immutable
14
+ * receipts.
14
15
  */
15
16
  export declare function createCompanyProfileAgentAdminRouter(options: CompanyProfileAgentAdminRouterOptions): {
16
17
  propose: (input: {
@@ -1,5 +1,5 @@
1
1
  import { type Settings } from "@opengeni/config";
2
- import type { AccessGrant, VariableSet } from "@opengeni/contracts";
2
+ import { type AccessGrant, type VariableSet } from "@opengeni/contracts";
3
3
  import { type Database } from "@opengeni/db";
4
4
  export declare const MAX_ENVIRONMENTS_PER_WORKSPACE = 25;
5
5
  export declare const MAX_VARIABLES_PER_ENVIRONMENT = 100;
@@ -1,5 +1,5 @@
1
1
  import type { MemorySlackPublicationDistribution } from "@opengeni/contracts";
2
- import { type Database, type EnqueueMemorySlackPublicationResult, type MemoryEmbedder, type MemorySlackPublicationActor, type SaveWorkspaceMemoryInput, type SaveWorkspaceMemoryResult } from "@opengeni/db";
2
+ import { type CorrectWorkspaceMemoryInput, type CorrectWorkspaceMemoryResult, type Database, type EnqueueMemorySlackPublicationResult, type MemoryEmbedder, type MemorySlackPublicationActor, type SaveWorkspaceMemoryInput, type SaveWorkspaceMemoryResult } from "@opengeni/db";
3
3
  import { type MemorySlackOrigin, type MemorySlackPublicationDecision } from "./memory-slack-publication.js";
4
4
  export type MemorySlackPublicationCommitRequest = {
5
5
  distribution: MemorySlackPublicationDistribution;
@@ -14,3 +14,6 @@ export type MemorySlackPublicationCommitResult = {
14
14
  export declare function saveWorkspaceMemoryWithSlackPublication(db: Database, input: SaveWorkspaceMemoryInput, publication: MemorySlackPublicationCommitRequest | null, embedder?: MemoryEmbedder): Promise<SaveWorkspaceMemoryResult & {
15
15
  slackPublication: MemorySlackPublicationCommitResult;
16
16
  }>;
17
+ export declare function correctWorkspaceMemoryWithSlackPublication(db: Database, input: CorrectWorkspaceMemoryInput, publication: MemorySlackPublicationCommitRequest | null, embedder?: MemoryEmbedder): Promise<CorrectWorkspaceMemoryResult & {
18
+ slackPublication: MemorySlackPublicationCommitResult;
19
+ }>;
@@ -47,6 +47,7 @@ export declare function personalConnectionDelegationsFromVisibleConnections(inpu
47
47
  export declare function personalConnectionDelegationsFromParent(input: {
48
48
  servers: McpServerConfig[];
49
49
  parentDelegations: McpPersonalConnectionDelegation[];
50
+ personalGitHubResources?: ResourceRef[];
50
51
  targetSessionId?: string;
51
52
  rejectActivatedConnections?: boolean;
52
53
  }): McpPersonalConnectionDelegation[];
@@ -81,7 +81,7 @@ export declare const prReviewAutomationAdapter: {
81
81
  optional?: boolean | undefined;
82
82
  }[];
83
83
  firstPartyMcpTools: ("artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_publish" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_set" | "goal_update" | "goal_wait" | "instruction_policy_propose" | "interaction_discover" | "interaction_request_human" | "knowledge_correct" | "knowledge_propose" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
84
- firstPartyMcpPermissions: ("account:admin" | "account:read" | "api_keys:manage" | "artifacts:publish" | "artifacts:read" | "billing:manage" | "billing:read" | "codemode:call" | "connections:read" | "connections:write" | "documents:manage" | "documents:search" | "enrollments:manage" | "enrollments:read" | "environments:manage" | "environments:use" | "files:read" | "files:upload" | "files:write" | "github:manage" | "github:use" | "goals:manage" | "mcp_servers:attach" | "members:manage" | "rigs:manage" | "rigs:use" | "scheduled_tasks:manage" | "scheduled_tasks:run" | "secrets:list" | "secrets:read" | "secrets:write" | "sessions:control" | "sessions:create" | "sessions:read" | "stream:acknowledge" | "stream:control" | "stream:view" | "terminal:attach" | "variable-sets:attach" | "variable-sets:list" | "variable-sets:manage" | "variable-sets:read" | "variable-sets:use" | "variable-sets:write" | "workspace:admin" | "workspace:create" | "workspace:read")[];
84
+ firstPartyMcpPermissions: ("account:admin" | "account:read" | "api_keys:manage" | "artifacts:publish" | "artifacts:read" | "billing:manage" | "billing:read" | "capabilities:manage" | "codemode:call" | "connections:read" | "connections:write" | "documents:manage" | "documents:search" | "enrollments:manage" | "enrollments:read" | "environments:manage" | "environments:use" | "files:read" | "files:upload" | "files:write" | "github:manage" | "github:use" | "goals:manage" | "mcp_servers:attach" | "members:manage" | "rigs:manage" | "rigs:use" | "scheduled_tasks:manage" | "scheduled_tasks:run" | "secrets:list" | "secrets:read" | "secrets:write" | "sessions:control" | "sessions:create" | "sessions:read" | "stream:acknowledge" | "stream:control" | "stream:view" | "terminal:attach" | "variable-sets:attach" | "variable-sets:list" | "variable-sets:manage" | "variable-sets:read" | "variable-sets:use" | "variable-sets:write" | "workspace:admin" | "workspace:create" | "workspace:read")[];
85
85
  model: string | null;
86
86
  reasoningEffort: "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh" | null;
87
87
  sandboxBackend: "blaxel" | "cloudflare" | "daytona" | "docker" | "e2b" | "local" | "modal" | "none" | "opensandbox" | "runloop" | "selfhosted" | "vercel" | null;
@@ -48,6 +48,18 @@ export declare function validateScheduledTaskTarget(input: {
48
48
  agentConfig: ScheduledTaskAgentConfig;
49
49
  missingTargetStatus?: 404 | 422;
50
50
  }): Promise<Session | null>;
51
+ export declare function validateScheduledTaskMachineTarget(input: {
52
+ settings: Settings;
53
+ db: Database;
54
+ grant: AccessGrant;
55
+ runMode: ScheduledTask["runMode"];
56
+ agentConfig: ScheduledTaskAgentConfig;
57
+ requireOnline?: boolean;
58
+ }): Promise<{
59
+ sandboxId: string;
60
+ enrollmentId: string;
61
+ sandboxOs: Session["sandboxOs"];
62
+ } | null>;
51
63
  export declare function scheduledTaskForGrant(task: ScheduledTask, grant: AccessGrant): ScheduledTask;
52
64
  export declare function scheduledTaskRunForGrant<T extends {
53
65
  sessionId: string | null;
@@ -66,6 +66,15 @@ export type CreateSessionRequestOutcome = CreateSessionOutcome & {
66
66
  /** Billing telemetry is recorded after the committed session start. */
67
67
  usageRecording: "recorded" | "failed";
68
68
  };
69
+ type AgentChildSessionCreatePresentation = {
70
+ /** Model-authored title candidate from the first-party `session_create` tool.
71
+ * This is deliberately separate from the public REST request contract. */
72
+ automaticTitleCandidate?: string | null;
73
+ };
74
+ /** @internal Exported for the keyed-create repair regression. */
75
+ export declare function freezeAgentChildAutomaticTitleInCreatorContext(context: TurnInitiatorContext | undefined, title: string | null | undefined): TurnInitiatorContext | undefined;
76
+ /** @internal Keyed repair must use the committed winner, not the retry payload. */
77
+ export declare function initialAutomaticTitleForSessionStart(session: Pick<Session, "createdByContext">, requestedTitle: string | null | undefined): string | null;
69
78
  export declare function createAndStartSessionWithOutcome(input: {
70
79
  requestedSessionId?: string;
71
80
  db: Database;
@@ -74,6 +83,16 @@ export declare function createAndStartSessionWithOutcome(input: {
74
83
  /** Internal database-only composition seam. The exact session shell and this
75
84
  * linkage commit together before its first event/turn can be initialized. */
76
85
  beforeCreateCommit?: (tx: Database, sessionId: string) => Promise<void>;
86
+ /** The custom workspace model was frozen by an earlier accepted boundary or
87
+ * inherited from an existing session, so retirement must not invalidate it. */
88
+ retainWorkspaceGatewayModel?: boolean;
89
+ /** Provider-neutral successor to retainWorkspaceGatewayModel. */
90
+ retainWorkspaceCustomModel?: boolean;
91
+ /** The selected workspace Gateway product is backed by a mutable custom row,
92
+ * rather than deployment-curated Gateway membership. */
93
+ workspaceGatewayCustomModel?: boolean;
94
+ /** Provider-neutral successor to workspaceGatewayCustomModel. */
95
+ workspaceCustomModel?: boolean;
77
96
  accountId: string;
78
97
  workspaceId: string;
79
98
  visibility?: "user_private" | "workspace_shared";
@@ -107,6 +126,9 @@ export declare function createAndStartSessionWithOutcome(input: {
107
126
  rigVersionId?: string | null;
108
127
  channelId?: string | null;
109
128
  goal?: GoalSpec | null;
129
+ /** Trusted sensitive-safe automatic title for an agent-created child. The
130
+ * atomic initializer commits the row mutation and `session.title_set`. */
131
+ initialAutomaticTitle?: string | null;
110
132
  instructions?: string | null;
111
133
  policyRole?: string | null;
112
134
  firstPartyMcpPermissions?: Permission[] | null;
@@ -201,7 +223,16 @@ export declare function requireQueuedTurnForApi(db: Database, workspaceId: strin
201
223
  * `session_send_message` tool so the two surfaces cannot drift. Callers own
202
224
  * resource/tool validation and the per-message usage limit before calling.
203
225
  */
204
- export declare function postUserMessageTurn(input: {
226
+ type PostUserMessageTurnResult = {
227
+ accepted: SessionEvent;
228
+ turn: SessionTurn;
229
+ draft: ComposerDraft | null;
230
+ receipt: SessionCommandReceipt;
231
+ routing: SessionPromptRouting;
232
+ interruptionCount: number;
233
+ replay: boolean;
234
+ };
235
+ type PostUserMessageTurnInput = {
205
236
  db: Database;
206
237
  bus: EventBus;
207
238
  workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
@@ -229,19 +260,13 @@ export declare function postUserMessageTurn(input: {
229
260
  commandActor?: SessionCommandActor;
230
261
  controlEtag?: string | null;
231
262
  expectedDraftRevision?: number | null;
263
+ boundaryRequestHash?: string;
232
264
  reasoningEffortFallback?: Settings["openaiReasoningEffort"];
233
265
  turnExecutionPolicy: TurnExecutionPolicyV1;
234
266
  recordAgentRunUsage?: boolean;
235
267
  schedulePostCommit?: (task: () => Promise<void>) => void;
236
- }): Promise<{
237
- accepted: SessionEvent;
238
- turn: SessionTurn;
239
- draft: ComposerDraft | null;
240
- receipt: SessionCommandReceipt;
241
- routing: SessionPromptRouting;
242
- interruptionCount: number;
243
- replay: boolean;
244
- }>;
268
+ };
269
+ export declare function postUserMessageTurn(input: PostUserMessageTurnInput): Promise<PostUserMessageTurnResult>;
245
270
  /**
246
271
  * Full create-session flow shared by `POST /sessions` and the first-party MCP
247
272
  * `session_create` tool: payload validation, resource/tool/variableSet
@@ -257,7 +282,7 @@ export declare function resolveSessionCreateVisibility(input: {
257
282
  visibilityProvided: boolean;
258
283
  parentVisibility: "user_private" | "workspace_shared" | null;
259
284
  }): "user_private" | "workspace_shared";
260
- export declare function createSessionForRequestWithOutcome(deps: ApiRouteDeps, grant: AccessGrant, workspaceId: string, rawPayload: unknown, authorization?: AccessGrantAuthorization): Promise<CreateSessionRequestOutcome>;
285
+ export declare function createSessionForRequestWithOutcome(unresolvedDeps: ApiRouteDeps, grant: AccessGrant, workspaceId: string, rawPayload: unknown, authorization?: AccessGrantAuthorization, agentChildPresentation?: AgentChildSessionCreatePresentation): Promise<CreateSessionRequestOutcome>;
261
286
  /** @internal Fixed public projection; the committed session outcome remains authoritative. */
262
287
  export declare function reportSessionUsageRecordingFailure(_error: unknown): void;
263
288
  /** Backward-compatible entity-returning request path for REST and core callers. */
@@ -348,3 +373,4 @@ export declare function updateSessionToolPolicy(deps: {
348
373
  sessionAuthorization?: SessionAuthorizationPort | null;
349
374
  }, grant: AccessGrant, sessionId: string, request: UpdateSessionToolPolicyRequest): Promise<Session>;
350
375
  export declare function readSessionLineage(deps: Pick<ApiRouteDeps, "db" | "sessionAuthorization">, grant: AccessGrant, sessionId: string): Promise<import("@opengeni/db").SessionLineage>;
376
+ export {};
@@ -1,4 +1,4 @@
1
- import type { WorkspaceMember } from "@opengeni/contracts";
1
+ import type { Permission, WorkspaceMember } from "@opengeni/contracts";
2
2
  /** A member can manage other members (directly or via the admin wildcard). */
3
3
  export declare function memberCanAdminister(member: Pick<WorkspaceMember, "permissions">): boolean;
4
4
  /** Only `user:` subjects are people; `api_key:` subjects belong to API keys. */
@@ -21,6 +21,13 @@ export declare function assertWorkspaceMemberRemovable(input: {
21
21
  subjectId: string;
22
22
  callerSubjectId: string;
23
23
  }): void;
24
+ /** Keep scoped member edits from orphaning the workspace or changing the caller's own grant. */
25
+ export declare function assertWorkspaceMemberUpdateAllowed(input: {
26
+ members: WorkspaceMember[];
27
+ subjectId: string;
28
+ callerSubjectId: string;
29
+ nextPermissions: Permission[];
30
+ }): void;
24
31
  /**
25
32
  * Guard the workspace-delete path before any external/DB mutation. Refuses
26
33
  * (409) to delete the account's last workspace, and refuses while any session
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from "./sandbox-types.js";
4
4
  export * from "./managed-auth-type.js";
5
5
  export { getManagedAuthRequestActorAbortSignal, getManagedAuthRequestActorAdmissionStamp, getManagedAuthRequestActorEpoch, getManagedAuthRequestActorLeaseStamp, getManagedSession, ManagedAuthActorLeaseOutcomeUnknownError, markManagedAuthRequestActorTransitionApplied, releaseManagedAuthRequestActorLease, validateManagedAuthRequestActorLease, type ManagedAuthActorAdmissionStamp, type ManagedAuthActorMutationLeaseStamp, } from "./managed-session.js";
6
6
  export * from "./transcription.js";
7
+ export * from "./model-catalog.js";
7
8
  export * from "./sandbox/fleet.js";
8
9
  export * from "./sandbox/routing.js";
9
10
  export * from "./sandbox/runtime-settings.js";