@opengeni/core 0.28.0 → 1.0.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 (224) hide show
  1. package/README.md +1 -1
  2. package/dist/access/external-actor-authority.d.ts +47 -0
  3. package/dist/access/index.d.ts +182 -3
  4. package/dist/access/service-initiator.d.ts +3 -0
  5. package/dist/application/api-integration-servers.d.ts +20 -0
  6. package/dist/application/archived-session-imports.d.ts +6 -0
  7. package/dist/application/composer-submit.d.ts +24 -0
  8. package/dist/application/connect-authority.d.ts +13 -0
  9. package/dist/application/connect-operation.d.ts +31 -0
  10. package/dist/application/external-continuation.d.ts +15 -0
  11. package/dist/application/external-identity-lifecycle.d.ts +20 -0
  12. package/dist/application/external-link-work-admission.d.ts +12 -0
  13. package/dist/application/external-workspace-members.d.ts +34 -0
  14. package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
  15. package/dist/application/new-session-drafts.d.ts +39 -2
  16. package/dist/application/sandbox-recovery.d.ts +58 -0
  17. package/dist/application/session-commands.d.ts +26 -13
  18. package/dist/application/session-mcp-credential-rotation.d.ts +29 -0
  19. package/dist/application/session-tenancy.d.ts +19 -0
  20. package/dist/application/user-resource-grants.d.ts +20 -0
  21. package/dist/billing/limits.d.ts +11 -0
  22. package/dist/canonical-human-identities.d.ts +7 -2
  23. package/dist/canonical-human-identities.js +17 -4
  24. package/dist/canonical-human-identities.js.map +1 -1
  25. package/dist/{chunk-6WKPWE5S.js → chunk-2MKMRGSY.js} +108 -24
  26. package/dist/chunk-2MKMRGSY.js.map +1 -0
  27. package/dist/{chunk-NYPMQ7NO.js → chunk-GVO3N37G.js} +205 -37
  28. package/dist/chunk-GVO3N37G.js.map +1 -0
  29. package/dist/{chunk-JJU6I5XD.js → chunk-LCQXNR62.js} +36 -10
  30. package/dist/chunk-LCQXNR62.js.map +1 -0
  31. package/dist/chunk-MM6N7CTO.js +387 -0
  32. package/dist/chunk-MM6N7CTO.js.map +1 -0
  33. package/dist/chunk-QO5GVFFO.js +235 -0
  34. package/dist/chunk-QO5GVFFO.js.map +1 -0
  35. package/dist/codex-model-availability.d.ts +14 -0
  36. package/dist/default-session-model.d.ts +139 -0
  37. package/dist/dependencies.d.ts +87 -4
  38. package/dist/developer-setup-credential-ceiling.d.ts +10 -0
  39. package/dist/domain/agent-config-resolution.d.ts +49 -0
  40. package/dist/domain/automations.d.ts +58 -0
  41. package/dist/domain/capabilities.d.ts +22 -4
  42. package/dist/domain/company-profile-agent-admin.d.ts +25 -0
  43. package/dist/domain/connection-account-selection-error.d.ts +8 -0
  44. package/dist/domain/connector-tool-permissions.d.ts +36 -0
  45. package/dist/domain/direct-model-provider.d.ts +3 -0
  46. package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
  47. package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
  48. package/dist/domain/editable-artifacts/ports.d.ts +10 -0
  49. package/dist/domain/editable-artifacts/service.d.ts +4 -3
  50. package/dist/domain/environments.d.ts +5 -9
  51. package/dist/domain/external-creation-attribution.d.ts +6 -0
  52. package/dist/domain/file-owner.d.ts +8 -0
  53. package/dist/domain/github-action-policies.d.ts +36 -0
  54. package/dist/domain/github-repository-bindings.d.ts +117 -0
  55. package/dist/domain/github-skill-source.d.ts +5 -0
  56. package/dist/domain/governed-learning-slack-publication.d.ts +45 -0
  57. package/dist/domain/insights-timing.d.ts +16 -0
  58. package/dist/domain/insights-usage.d.ts +27 -0
  59. package/dist/domain/insights.d.ts +28 -1
  60. package/dist/domain/knowledge-files.d.ts +20 -0
  61. package/dist/domain/knowledge-messages.d.ts +39 -0
  62. package/dist/domain/knowledge-messages.test.d.ts +1 -0
  63. package/dist/domain/knowledge-preparation.d.ts +10 -0
  64. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  65. package/dist/domain/knowledge-search.d.ts +15 -0
  66. package/dist/domain/knowledge-search.test.d.ts +1 -0
  67. package/dist/domain/knowledge.d.ts +9 -0
  68. package/dist/domain/mcp-account-bindings.d.ts +19 -0
  69. package/dist/domain/mcp-account-routes.d.ts +21 -0
  70. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  71. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  72. package/dist/domain/organization-membership-lifecycle.d.ts +1 -0
  73. package/dist/domain/personal-connection-delegations.d.ts +87 -4
  74. package/dist/domain/pr-review.d.ts +249 -0
  75. package/dist/domain/resources.d.ts +24 -3
  76. package/dist/domain/scheduled-task-access.d.ts +247 -0
  77. package/dist/domain/scheduled-tasks.d.ts +103 -6
  78. package/dist/domain/session-connection-accounts.d.ts +16 -0
  79. package/dist/domain/session-file-access.d.ts +4 -0
  80. package/dist/domain/session-native-connection-replacement.d.ts +14 -0
  81. package/dist/domain/session-start-timing.d.ts +7 -0
  82. package/dist/domain/session-tool-policy.d.ts +93 -4
  83. package/dist/domain/sessions.d.ts +275 -28
  84. package/dist/domain/skill-imports.d.ts +1 -0
  85. package/dist/domain/skill-search.d.ts +30 -0
  86. package/dist/domain/skills.d.ts +117 -0
  87. package/dist/domain/slack-bot.d.ts +46 -1
  88. package/dist/domain/workspace-members.d.ts +8 -1
  89. package/dist/editable-artifact-live/application.d.ts +12 -3
  90. package/dist/editable-artifact-live/ports.d.ts +0 -1
  91. package/dist/editable-artifact-live/server.d.ts +5 -2
  92. package/dist/editable-artifact-live/ticket.d.ts +2 -2
  93. package/dist/editable-artifact-live/types.d.ts +14 -2
  94. package/dist/editable-artifact-live.js +2 -2
  95. package/dist/editable-artifacts.js +10 -4
  96. package/dist/index.d.ts +49 -3
  97. package/dist/index.js +18826 -6847
  98. package/dist/index.js.map +1 -1
  99. package/dist/managed-auth-session-sets.d.ts +131 -0
  100. package/dist/managed-auth-session-sets.js +51 -0
  101. package/dist/managed-auth-session-sets.js.map +1 -0
  102. package/dist/managed-session.d.ts +98 -11
  103. package/dist/model-catalog.d.ts +117 -0
  104. package/dist/product-usage-metrics.d.ts +30 -0
  105. package/dist/rigs/index.d.ts +22 -5
  106. package/dist/rigs/provider-images.d.ts +1 -1
  107. package/dist/sandbox/fleet.d.ts +59 -10
  108. package/dist/sandbox/routing.d.ts +22 -2
  109. package/dist/sandbox/runtime-settings.d.ts +56 -0
  110. package/dist/session-authorization.d.ts +38 -1
  111. package/dist/site-session-origin.d.ts +9 -0
  112. package/dist/transcription.d.ts +12 -1
  113. package/dist/turn-surface.d.ts +18 -0
  114. package/dist/user-presence.d.ts +32 -0
  115. package/package.json +18 -11
  116. package/src/access/external-actor-authority.ts +94 -0
  117. package/src/access/index.ts +1386 -44
  118. package/src/access/service-initiator.ts +50 -0
  119. package/src/application/api-integration-servers.ts +215 -0
  120. package/src/application/archived-session-imports.ts +161 -0
  121. package/src/application/composer-submit.ts +77 -0
  122. package/src/application/connect-authority.ts +77 -0
  123. package/src/application/connect-operation.ts +80 -0
  124. package/src/application/external-continuation.ts +129 -0
  125. package/src/application/external-identity-lifecycle.ts +48 -0
  126. package/src/application/external-link-work-admission.ts +90 -0
  127. package/src/application/external-workspace-members.ts +232 -0
  128. package/src/application/modal-native-worker-host-transport.ts +263 -0
  129. package/src/application/new-session-drafts.ts +222 -29
  130. package/src/application/sandbox-recovery.ts +78 -0
  131. package/src/application/session-commands.ts +430 -73
  132. package/src/application/session-mcp-credential-rotation.ts +217 -0
  133. package/src/application/session-tenancy.ts +445 -0
  134. package/src/application/user-resource-grants.ts +154 -0
  135. package/src/billing/limits.ts +103 -24
  136. package/src/canonical-human-identities.ts +22 -3
  137. package/src/codex-model-availability.ts +136 -0
  138. package/src/default-session-model.ts +656 -0
  139. package/src/dependencies.ts +97 -5
  140. package/src/developer-setup-credential-ceiling.ts +60 -0
  141. package/src/domain/agent-config-resolution.ts +148 -0
  142. package/src/domain/automations.ts +270 -0
  143. package/src/domain/capabilities.ts +244 -151
  144. package/src/domain/company-profile-agent-admin.ts +56 -0
  145. package/src/domain/connection-account-selection-error.ts +19 -0
  146. package/src/domain/connector-tool-permissions.ts +371 -0
  147. package/src/domain/direct-model-provider.ts +62 -0
  148. package/src/domain/editable-artifacts/agent-application.ts +61 -15
  149. package/src/domain/editable-artifacts/durable-export.ts +100 -5
  150. package/src/domain/editable-artifacts/in-memory.ts +6 -0
  151. package/src/domain/editable-artifacts/ports.ts +11 -0
  152. package/src/domain/editable-artifacts/service.ts +32 -1
  153. package/src/domain/editable-artifacts/snapshot-compaction.ts +9 -5
  154. package/src/domain/editable-artifacts/snapshot-verifier-genesis.ts +10 -8
  155. package/src/domain/editable-artifacts/snapshot-verifier.ts +10 -3
  156. package/src/domain/environments.ts +25 -45
  157. package/src/domain/external-creation-attribution.ts +22 -0
  158. package/src/domain/file-owner.ts +67 -0
  159. package/src/domain/github-action-policies.ts +169 -0
  160. package/src/domain/github-repository-bindings.ts +295 -0
  161. package/src/domain/github-skill-source.ts +233 -0
  162. package/src/domain/governed-learning-slack-publication.ts +157 -0
  163. package/src/domain/insights-timing.ts +95 -0
  164. package/src/domain/insights-usage.ts +67 -0
  165. package/src/domain/insights.ts +270 -169
  166. package/src/domain/knowledge-files.ts +46 -0
  167. package/src/domain/knowledge-messages.test.ts +91 -0
  168. package/src/domain/knowledge-messages.ts +106 -0
  169. package/src/domain/knowledge-preparation.test.ts +276 -0
  170. package/src/domain/knowledge-preparation.ts +147 -0
  171. package/src/domain/knowledge-search.test.ts +561 -0
  172. package/src/domain/knowledge-search.ts +256 -0
  173. package/src/domain/knowledge.ts +133 -0
  174. package/src/domain/mcp-account-bindings.ts +171 -0
  175. package/src/domain/mcp-account-routes.ts +121 -0
  176. package/src/domain/native-mcp-connection-admission.ts +14 -0
  177. package/src/domain/organization-integration-catalog.ts +88 -0
  178. package/src/domain/organization-membership-lifecycle.ts +10 -0
  179. package/src/domain/personal-connection-delegations.ts +758 -115
  180. package/src/domain/pr-review.ts +687 -0
  181. package/src/domain/resources.ts +182 -25
  182. package/src/domain/scheduled-task-access.ts +1052 -0
  183. package/src/domain/scheduled-tasks.ts +1952 -215
  184. package/src/domain/session-connection-accounts.ts +67 -0
  185. package/src/domain/session-file-access.ts +47 -0
  186. package/src/domain/session-native-connection-replacement.ts +64 -0
  187. package/src/domain/session-start-timing.ts +55 -0
  188. package/src/domain/session-tool-policy.ts +443 -19
  189. package/src/domain/sessions.ts +3417 -619
  190. package/src/domain/skill-imports.ts +137 -17
  191. package/src/domain/skill-search.ts +221 -0
  192. package/src/domain/skills.ts +104 -0
  193. package/src/domain/slack-bot.ts +128 -3
  194. package/src/domain/workspace-members.ts +34 -2
  195. package/src/editable-artifact-live/application.ts +29 -4
  196. package/src/editable-artifact-live/ports.ts +0 -1
  197. package/src/editable-artifact-live/server.ts +167 -13
  198. package/src/editable-artifact-live/ticket.ts +87 -6
  199. package/src/editable-artifact-live/types.ts +16 -2
  200. package/src/editable-artifact-live/wire.ts +0 -10
  201. package/src/index.ts +69 -4
  202. package/src/managed-auth-session-sets.ts +371 -0
  203. package/src/managed-session.ts +520 -2
  204. package/src/model-catalog.ts +873 -0
  205. package/src/product-usage-metrics.ts +101 -0
  206. package/src/rigs/index.ts +179 -63
  207. package/src/rigs/provider-images.ts +2 -3
  208. package/src/sandbox/fleet.ts +471 -59
  209. package/src/sandbox/routing.ts +160 -33
  210. package/src/sandbox/runtime-settings.ts +281 -0
  211. package/src/session-authorization.ts +262 -78
  212. package/src/site-session-origin.ts +22 -0
  213. package/src/transcription.ts +13 -1
  214. package/src/turn-surface.ts +45 -0
  215. package/src/user-presence.ts +134 -0
  216. package/dist/chunk-6WKPWE5S.js.map +0 -1
  217. package/dist/chunk-IBOEYG6N.js +0 -34
  218. package/dist/chunk-IBOEYG6N.js.map +0 -1
  219. package/dist/chunk-JJU6I5XD.js.map +0 -1
  220. package/dist/chunk-NYPMQ7NO.js.map +0 -1
  221. package/dist/domain/durable-learning-slack-publication.d.ts +0 -72
  222. package/dist/domain/packs.d.ts +0 -55
  223. package/src/domain/durable-learning-slack-publication.ts +0 -202
  224. package/src/domain/packs.ts +0 -556
@@ -0,0 +1,235 @@
1
+ // src/managed-auth-session-sets.ts
2
+ import { createHash, createHmac, randomBytes, timingSafeEqual } from "crypto";
3
+ import {
4
+ completeManagedAuthLoginTransaction,
5
+ getManagedAuthSessionSetOperationReceipt,
6
+ getManagedAuthSessionSetSnapshot
7
+ } from "@opengeni/db";
8
+ var MANAGED_AUTH_SESSION_SET_COOKIE = "opengeni.session_set";
9
+ var MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE = "opengeni.login_transaction";
10
+ var MANAGED_AUTH_CSRF_HEADER = "x-opengeni-session-csrf";
11
+ var MANAGED_AUTH_ACTOR_EPOCH_HEADER = "x-opengeni-actor-epoch";
12
+ var MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE_PATH = "/v1/auth/session-set/transactions";
13
+ var ManagedAuthActorChangeError = class extends Error {
14
+ name = "ManagedAuthActorChangeError";
15
+ code = "actor_change_required";
16
+ constructor() {
17
+ super("The selected browser actor changed");
18
+ }
19
+ };
20
+ var ManagedAuthRequestAdmissionError = class extends Error {
21
+ name = "ManagedAuthRequestAdmissionError";
22
+ code = "origin_rejected";
23
+ };
24
+ var ManagedAuthCompletionOutcomeUnknownError = class extends Error {
25
+ name = "ManagedAuthCompletionOutcomeUnknownError";
26
+ code = "operation_outcome_unknown";
27
+ constructor(options) {
28
+ super("The managed authentication completion outcome is unknown", options);
29
+ }
30
+ };
31
+ function requireManagedAuthActorFence(input) {
32
+ if (input.expectedActorEpoch !== null && input.expectedActorEpoch !== input.actorEpoch || input.expectedActorEpoch === null && (input.mode === "broker" || input.actorEpoch !== "1" || input.selectedAuthSessionId !== null && input.legacyAmbientSessionId !== input.selectedAuthSessionId)) {
33
+ throw new ManagedAuthActorChangeError();
34
+ }
35
+ }
36
+ function managedAuthRandomAuthority() {
37
+ return randomBytes(32).toString("base64url");
38
+ }
39
+ function managedAuthSha256(value) {
40
+ return createHash("sha256").update(value, "utf8").digest("hex");
41
+ }
42
+ function managedAuthCsrfHash(authority) {
43
+ return managedAuthSha256(`opengeni:managed-auth:csrf-authority:v1
44
+ ${authority}`);
45
+ }
46
+ function managedAuthCsrfToken(signingSecret, authority, generation) {
47
+ return createHmac("sha256", signingSecret).update(`opengeni:managed-auth:csrf:v1
48
+ ${authority}
49
+ ${generation}`, "utf8").digest("base64url");
50
+ }
51
+ function managedAuthTransactionSecret(signingSecret, authority, operationId) {
52
+ return createHmac("sha256", signingSecret).update(`opengeni:managed-auth:transaction:v1
53
+ ${authority}
54
+ ${operationId}`, "utf8").digest("base64url");
55
+ }
56
+ function managedAuthDerivedUuid(namespace, value) {
57
+ const bytes = createHash("sha256").update(`${namespace}
58
+ ${value}`, "utf8").digest().subarray(0, 16);
59
+ bytes[6] = bytes[6] & 15 | 80;
60
+ bytes[8] = bytes[8] & 63 | 128;
61
+ const hex = bytes.toString("hex");
62
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
63
+ }
64
+ function canonicalJson(value) {
65
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
66
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
67
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`).join(",")}}`;
68
+ }
69
+ function managedAuthRequestDigest(value) {
70
+ return managedAuthSha256(canonicalJson(value));
71
+ }
72
+ function managedAuthSecretRequestDigest(signingSecret, value) {
73
+ return createHmac("sha256", signingSecret).update(`opengeni:managed-auth:request:v1
74
+ ${canonicalJson(value)}`, "utf8").digest("hex");
75
+ }
76
+ function withManagedAuthCsrfToken(projection, signingSecret, authority) {
77
+ return {
78
+ ...projection,
79
+ csrfToken: managedAuthCsrfToken(signingSecret, authority, projection.generation)
80
+ };
81
+ }
82
+ function equalSecret(left, right) {
83
+ const leftBytes = Buffer.from(left, "utf8");
84
+ const rightBytes = Buffer.from(right, "utf8");
85
+ return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes);
86
+ }
87
+ function requireManagedAuthMutationAdmission(input) {
88
+ const origin = input.request.headers.get("origin");
89
+ const fetchSite = input.request.headers.get("sec-fetch-site");
90
+ const contentType = input.request.headers.get("content-type")?.split(";", 1)[0]?.trim();
91
+ const csrf = input.request.headers.get(MANAGED_AUTH_CSRF_HEADER);
92
+ const allowed = new Set(input.allowedOrigins.map((candidate) => new URL(candidate).origin));
93
+ const expectedCsrf = managedAuthCsrfToken(
94
+ input.signingSecret,
95
+ input.authority,
96
+ input.expectedGeneration
97
+ );
98
+ if (!origin || !allowed.has(origin) || fetchSite !== "same-origin" || contentType !== "application/json" || !csrf || !equalSecret(csrf, expectedCsrf)) {
99
+ throw new ManagedAuthRequestAdmissionError("Browser session-set mutation admission failed");
100
+ }
101
+ }
102
+ async function resolveManagedAuthSelectedSession(input) {
103
+ const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {
104
+ authorityHash: managedAuthSha256(input.authority),
105
+ mode: input.mode,
106
+ includeInternal: true,
107
+ allowRecovery: input.allowRecovery ?? false,
108
+ readOnly: true
109
+ });
110
+ if (!snapshot) return null;
111
+ if (snapshot.projection.state === "actor_change_required") {
112
+ throw new ManagedAuthActorChangeError();
113
+ }
114
+ requireManagedAuthActorFence({
115
+ mode: input.mode,
116
+ actorEpoch: snapshot.projection.actorEpoch,
117
+ expectedActorEpoch: input.expectedActorEpoch,
118
+ selectedAuthSessionId: snapshot.selected?.authSessionId ?? null,
119
+ legacyAmbientSessionId: input.legacyAmbientSessionId ?? null
120
+ });
121
+ if (!snapshot.selected) return { session: null, projection: snapshot.projection };
122
+ const resolved = await input.adapter.resolveSelectedSession(snapshot.selected);
123
+ if (!resolved || resolved.session.id !== snapshot.selected.authSessionId || resolved.user.id !== snapshot.selected.authUserId) {
124
+ return { session: null, projection: snapshot.projection };
125
+ }
126
+ return { session: resolved, projection: snapshot.projection };
127
+ }
128
+ async function authenticateAndAdoptManagedAuthSession(input) {
129
+ try {
130
+ const existing = await getManagedAuthSessionSetOperationReceipt(input.db, {
131
+ authorityHash: managedAuthSha256(input.authority),
132
+ operationId: input.operationId,
133
+ requestDigest: input.requestDigest
134
+ });
135
+ if (existing) return existing;
136
+ } catch (error) {
137
+ throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });
138
+ }
139
+ const created = await input.adapter.authenticate({
140
+ provider: "email_password",
141
+ transactionId: input.transactionId,
142
+ credentials: { email: input.email, password: input.password },
143
+ headers: input.isolatedHeaders
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) {
153
+ let completed;
154
+ try {
155
+ completed = await completeManagedAuthLoginTransaction(input.db, {
156
+ authorityHash: input.authorityHash,
157
+ csrfHash: input.csrfHash,
158
+ operationId: input.operationId,
159
+ requestDigest: input.requestDigest,
160
+ expectedGeneration: input.expectedGeneration,
161
+ expectedActorEpoch: input.expectedActorEpoch,
162
+ transactionId: input.transactionId,
163
+ transactionSecretHash: input.transactionSecretHash,
164
+ authSessionId: input.authSessionId,
165
+ mode: input.mode
166
+ });
167
+ } catch (error) {
168
+ let receipt;
169
+ try {
170
+ receipt = await getManagedAuthSessionSetOperationReceipt(input.db, {
171
+ authorityHash: input.authorityHash,
172
+ operationId: input.operationId,
173
+ requestDigest: input.requestDigest
174
+ });
175
+ } catch (receiptError) {
176
+ throw new ManagedAuthCompletionOutcomeUnknownError({ cause: receiptError });
177
+ }
178
+ if (receipt) {
179
+ await reconcileCreatedManagedAuthSession(input, input.authSessionId);
180
+ return receipt;
181
+ }
182
+ await input.adapter.revokeSession({ authSessionId: input.authSessionId }).catch(() => void 0);
183
+ throw error;
184
+ }
185
+ try {
186
+ await reconcileCreatedManagedAuthSession(input, input.authSessionId);
187
+ } catch (error) {
188
+ throw new ManagedAuthCompletionOutcomeUnknownError({ cause: error });
189
+ }
190
+ return completed;
191
+ }
192
+ async function reconcileCreatedManagedAuthSession(input, authSessionId) {
193
+ const snapshot = await getManagedAuthSessionSetSnapshot(input.db, {
194
+ authorityHash: managedAuthSha256(input.authority),
195
+ mode: input.mode,
196
+ includeInternal: true,
197
+ readOnly: true
198
+ });
199
+ if (snapshot?.internalSlots.some((slot) => slot.authSessionId === authSessionId)) return;
200
+ await input.adapter.revokeSession({ authSessionId });
201
+ }
202
+ function isolatedManagedAuthHeaders(request) {
203
+ const headers = new Headers(request.headers);
204
+ headers.delete("cookie");
205
+ headers.delete("authorization");
206
+ headers.delete("x-forwarded-user");
207
+ return headers;
208
+ }
209
+
210
+ export {
211
+ MANAGED_AUTH_SESSION_SET_COOKIE,
212
+ MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE,
213
+ MANAGED_AUTH_CSRF_HEADER,
214
+ MANAGED_AUTH_ACTOR_EPOCH_HEADER,
215
+ MANAGED_AUTH_LOGIN_TRANSACTION_COOKIE_PATH,
216
+ ManagedAuthActorChangeError,
217
+ ManagedAuthRequestAdmissionError,
218
+ ManagedAuthCompletionOutcomeUnknownError,
219
+ requireManagedAuthActorFence,
220
+ managedAuthRandomAuthority,
221
+ managedAuthSha256,
222
+ managedAuthCsrfHash,
223
+ managedAuthCsrfToken,
224
+ managedAuthTransactionSecret,
225
+ managedAuthDerivedUuid,
226
+ managedAuthRequestDigest,
227
+ managedAuthSecretRequestDigest,
228
+ withManagedAuthCsrfToken,
229
+ requireManagedAuthMutationAdmission,
230
+ resolveManagedAuthSelectedSession,
231
+ authenticateAndAdoptManagedAuthSession,
232
+ adoptManagedAuthSession,
233
+ isolatedManagedAuthHeaders
234
+ };
235
+ //# sourceMappingURL=chunk-QO5GVFFO.js.map
@@ -0,0 +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 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":"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","names":[]}
@@ -0,0 +1,14 @@
1
+ import { fetchCodexModels } from "@opengeni/codex";
2
+ import { type Settings } from "@opengeni/config";
3
+ import { buildCodexTokenResolver, getCodexRotationSettings, listCodexAccountStatuses, loadCodexCredentialForRun, type Database } from "@opengeni/db";
4
+ import type { ModelAvailabilityObservation } from "./model-catalog.js";
5
+ type Dependencies = {
6
+ listAccounts: typeof listCodexAccountStatuses;
7
+ getRotation: typeof getCodexRotationSettings;
8
+ loadCredential: typeof loadCodexCredentialForRun;
9
+ fetchModels: typeof fetchCodexModels;
10
+ getToken: (db: Database, settings: Settings, workspaceId: string, credentialId: string) => ReturnType<ReturnType<typeof buildCodexTokenResolver>["getToken"]>;
11
+ };
12
+ /** Live provider support is separate from deployment membership and model permissions. */
13
+ export declare function loadWorkspaceCodexModelAvailability(db: Database, settings: Settings, workspaceId: string, deps?: Dependencies): Promise<Record<string, ModelAvailabilityObservation>>;
14
+ export {};
@@ -0,0 +1,139 @@
1
+ import { type ConfiguredModel, type Settings } from "@opengeni/config";
2
+ import { type DefaultModelSelection, type ReasoningEffort, type ScheduledTask, type WorkspaceSessionDefaults, type XaiProviderAccountAuthoritySnapshotV1, type ClaudeProviderAccountAuthoritySnapshotV1 } from "@opengeni/contracts";
3
+ import { type Database } from "@opengeni/db";
4
+ import { type WorkspaceModelSelection, type WorkspaceModelSelectionInput } from "./model-catalog.js";
5
+ /** The model's own default effort, matching the web picker's choice. */
6
+ export declare function defaultReasoningEffortForConfiguredModel(model: ConfiguredModel, fallback: ReasoningEffort): ReasoningEffort;
7
+ /** The highest supported effort at or below `preferred`. */
8
+ export declare function clampReasoningEffortForConfiguredModel(model: ConfiguredModel, preferred: ReasoningEffort, fallback: ReasoningEffort): ReasoningEffort;
9
+ export type DefaultSessionModelInput = {
10
+ /** Catalog-resolved settings: `openaiModel` is the deployment default. */
11
+ settings: Settings;
12
+ /** This workspace's selection, in operator catalog order. */
13
+ selections: readonly WorkspaceModelSelection[];
14
+ workspaceDefaults: WorkspaceSessionDefaults | null;
15
+ /**
16
+ * True while the organization holds a positive OpenGeni credit balance from
17
+ * any source, the verified-signup trial grant included (see
18
+ * `organizationHoldsCredits`).
19
+ */
20
+ creditsAvailable: boolean;
21
+ };
22
+ /**
23
+ * Default model policy for a new chat or scheduled task that names no model.
24
+ *
25
+ * Precedence, first match wins:
26
+ *
27
+ * 1. `workspace`: the saved workspace default (`settings.sessionDefaults`)
28
+ * while it is selectable in this workspace, its saved effort clamped to
29
+ * what the model supports today.
30
+ * 2. `subscription`: the first selectable connected-subscription model
31
+ * (ChatGPT/Codex, then SuperGrok) in operator catalog order. The
32
+ * deployment default wins inside this step when it is itself a selectable
33
+ * subscription model.
34
+ * 3. `credits`: while the organization holds a positive OpenGeni credit
35
+ * balance (a purchase, a grant, or the verified-signup trial grant), the
36
+ * configured credits default (`OPENGENI_CREDITS_DEFAULT_MODEL`, effort
37
+ * clamped to what the model supports), or the first selectable
38
+ * credits-billed model when that one is not selectable. When the
39
+ * deployment default is already a selectable credits-billed model it is
40
+ * never replaced: it keeps the deployment effort, except that it takes the
41
+ * credits default effort when it is the credits default model itself.
42
+ * 4. `deployment`: the deployment default with the deployment reasoning effort
43
+ * when stably admissible; otherwise the first stably admissible catalog
44
+ * model with its own default effort. With no admitted models, retain the
45
+ * deployment hint and let fresh creation refuse it.
46
+ *
47
+ * An explicit model on the request, the scheduled task, or the person's
48
+ * new-chat draft is never passed through this function.
49
+ */
50
+ export declare function selectDefaultSessionModel(input: DefaultSessionModelInput): DefaultModelSelection;
51
+ /**
52
+ * The default this workspace would use while its organization holds a
53
+ * positive OpenGeni credit balance. Null when the deployment does not bill
54
+ * credits.
55
+ */
56
+ export declare function creditsDefaultSessionModel(input: {
57
+ settings: Settings;
58
+ selections: readonly WorkspaceModelSelection[];
59
+ workspaceSettings: unknown;
60
+ }): DefaultModelSelection | null;
61
+ /**
62
+ * Resolve the default for an already-loaded workspace selection. The credit
63
+ * ledger is read only when it can change the answer.
64
+ */
65
+ export declare function resolveDefaultSessionModelForSelections(db: Database, input: {
66
+ settings: Settings;
67
+ accountId: string;
68
+ workspaceSettings: unknown;
69
+ selections: readonly WorkspaceModelSelection[];
70
+ }): Promise<DefaultModelSelection>;
71
+ export type WorkspaceModelSelectionContext = {
72
+ accountId: string;
73
+ workspaceId: string;
74
+ /**
75
+ * The subject whose connected-subscription authority applies: the
76
+ * authenticated caller for direct creates, or a scheduled task's immutable
77
+ * execution owner. Never another member.
78
+ */
79
+ subjectId: string;
80
+ /**
81
+ * An already-frozen SuperGrok authority (a scheduled task's snapshot).
82
+ * Omitted means the subject's current acceptance authority, exactly as a
83
+ * direct Send resolves it.
84
+ */
85
+ xaiAuthoritySnapshot?: XaiProviderAccountAuthoritySnapshotV1 | undefined;
86
+ /** Already accepted Claude pool; never replace it with current selection. */
87
+ claudeAuthoritySnapshot?: ClaudeProviderAccountAuthoritySnapshotV1 | undefined;
88
+ };
89
+ /**
90
+ * Readiness for the subject's current or already accepted Claude pool observes
91
+ * metadata only; quota is handled by the runtime allocator. This is not an
92
+ * authorization: callers must supply their authenticated or frozen subject.
93
+ */
94
+ export declare function loadWorkspaceClaudeSubscriptionReadiness(db: Database, settings: Settings, context: WorkspaceModelSelectionContext): Promise<{
95
+ workspace: boolean;
96
+ organization: boolean;
97
+ }>;
98
+ /** Load the same inputs the workspace model catalog route evaluates. */
99
+ export declare function loadWorkspaceModelSelectionInput(db: Database, settings: Settings, context: WorkspaceModelSelectionContext, options?: {
100
+ observeAvailability?: boolean;
101
+ }): Promise<WorkspaceModelSelectionInput>;
102
+ /**
103
+ * Caller-scoped stable fresh admission; never re-admit already accepted work.
104
+ * Live discovery is opt-in: its token refresh can mutate connection readiness,
105
+ * so a health hint must not change the billing rail of an explicit create.
106
+ */
107
+ export declare function resolveCallerWorkspaceModelSelections(db: Database, settings: Settings, context: WorkspaceModelSelectionContext, options?: {
108
+ observeAvailability?: boolean;
109
+ }): Promise<WorkspaceModelSelection[]>;
110
+ /** Transient selectability for existing consumers; not fresh-create admission. */
111
+ export declare function selectableWorkspaceModel(selections: readonly WorkspaceModelSelection[], modelId: string): WorkspaceModelSelection | undefined;
112
+ /** Same stable decision used by client config and direct fresh session creation. */
113
+ export declare function admissibleWorkspaceModel(selections: readonly WorkspaceModelSelection[], modelId: string): WorkspaceModelSelection | undefined;
114
+ /**
115
+ * Server-side default for new work that names no model: API and Slack session
116
+ * creates, new-chat drafts that follow the default, and scheduled-task
117
+ * occurrences. The result is resolved once and then frozen by the accepted
118
+ * session or occurrence like any other model choice.
119
+ */
120
+ export declare function resolveDefaultSessionModel(db: Database, settings: Settings, context: WorkspaceModelSelectionContext & {
121
+ workspaceSettings?: unknown;
122
+ }): Promise<DefaultModelSelection>;
123
+ /**
124
+ * The default a scheduled occurrence uses when its task names no model and the
125
+ * occurrence creates its own session: resolved under the task's immutable
126
+ * execution owner (or its creator for a workspace/service task) and the task's
127
+ * frozen SuperGrok authority, never another member's. The worker stamps the
128
+ * result onto the accepted execution, so retries and recovery replay it; the
129
+ * API's manual-trigger limit check uses the same resolution so it gates the
130
+ * model that will run.
131
+ */
132
+ export declare function resolveScheduledTaskDefaultModel(db: Database, settings: Settings, task: Pick<ScheduledTask, "id" | "accountId" | "workspaceId" | "ownerSubjectId" | "createdBy">): Promise<DefaultModelSelection>;
133
+ /**
134
+ * The model a manual trigger's limit pre-check evaluates, matching what the
135
+ * occurrence will run: the task's explicit model, else the target or reusable
136
+ * session's model when that session exists, else the resolved scheduled
137
+ * default. The worker still resolves authoritatively at dispatch.
138
+ */
139
+ export declare function resolveScheduledTaskPreflightModel(db: Database, settings: Settings, task: Pick<ScheduledTask, "id" | "accountId" | "workspaceId" | "ownerSubjectId" | "createdBy" | "agentConfig" | "runMode" | "targetSessionId" | "reusableSessionId">): Promise<string>;
@@ -1,16 +1,24 @@
1
1
  import type { Settings } from "@opengeni/config";
2
2
  import type { ConnectionCredentialsPort, Document, DocumentAuthorityKind, GitHubAppApiPort, ScheduledTask, ScheduledTaskTriggerType, SessionAuthorizationPort, TurnInitiator } from "@opengeni/contracts";
3
- import type { Database } from "@opengeni/db";
3
+ import type { Database, SessionWorkflowWakeDeliveryResult } from "@opengeni/db";
4
4
  import type { DocumentServices } from "@opengeni/documents";
5
5
  import type { EventBus } from "@opengeni/events";
6
6
  import type { Observability } from "@opengeni/observability";
7
+ import type { UserPresenceRecorder } from "./user-presence.js";
7
8
  import type { createObjectStorage } from "@opengeni/storage";
8
9
  import type { ManagedAuth } from "./managed-auth-type.js";
10
+ import type { ManagedAuthSessionAdapter } from "./managed-auth-session-sets.js";
9
11
  import type { ApiSandboxClient, ResumeBoxByIdInput, ResumedSandboxSession } from "./sandbox-types.js";
10
12
  import type { TranscriptionSegmenter, TranscriptionService } from "./transcription.js";
11
13
  import type { EditableArtifactApplicationPort } from "./editable-artifact-live.js";
14
+ import type { ResolvedCatalogSettings } from "./model-catalog.js";
12
15
  import type { EditableArtifactAgentApplication, EditableArtifactDurableExportService, EditableArtifactOfficeImportPort } from "./editable-artifacts.js";
13
16
  export type SessionWorkflowClient = {
17
+ triggerAutomationRun?: (input: {
18
+ accountId: string;
19
+ workspaceId: string;
20
+ runId: string;
21
+ }) => Promise<void>;
14
22
  signalUserMessage: (input: {
15
23
  sessionId: string;
16
24
  eventId: string;
@@ -23,7 +31,9 @@ export type SessionWorkflowClient = {
23
31
  workflowId: string;
24
32
  wakeRevision: number;
25
33
  interruptionRequested?: boolean;
26
- }) => Promise<void>;
34
+ /** Called after transport acceptance, before the fallible durable ACK. */
35
+ onSignalAccepted?: () => void;
36
+ }) => Promise<SessionWorkflowWakeDeliveryResult | void>;
27
37
  /** Trigger one bounded drain of already-committed workflow-wake revisions. */
28
38
  requestSessionWorkflowWakeDispatch: () => Promise<void>;
29
39
  signalCodexCapacity?: (input: {
@@ -44,6 +54,12 @@ export type SessionWorkflowClient = {
44
54
  }) => Promise<void>;
45
55
  syncScheduledTask: (input: {
46
56
  task: ScheduledTask;
57
+ /**
58
+ * Compensate under the same per-schedule writer lock. Return the error to
59
+ * throw only after this transaction commits; lock/commit failures bypass
60
+ * that receipt. A failing compensation must roll back its own savepoint.
61
+ */
62
+ onFailure?: (tx: Database, error: unknown) => Promise<Error>;
47
63
  }) => Promise<void>;
48
64
  deleteScheduledTaskSchedule: (input: {
49
65
  temporalScheduleId: string;
@@ -53,6 +69,8 @@ export type SessionWorkflowClient = {
53
69
  agentRunUsageIdempotencyKey: string;
54
70
  triggerWorkflowId: string;
55
71
  initiator: TurnInitiator;
72
+ /** Server-frozen caller ceiling for this run, independent of task ownership. */
73
+ credentialRestriction?: "developer_setup";
56
74
  triggerType?: Extract<ScheduledTaskTriggerType, "manual" | "initial" | "provider_event" | "retry" | "repair">;
57
75
  }) => Promise<void>;
58
76
  startRigVerification: (input: {
@@ -73,8 +91,48 @@ export type DocumentIndexClient = {
73
91
  authoritySubjectId: string | null;
74
92
  }) => Promise<Document | void>;
75
93
  };
94
+ export type ManagedEmailMessage = {
95
+ kind: "email_verification" | "password_reset" | "organization_user_setup" | "sign_in_method_changed";
96
+ from: string;
97
+ to: string;
98
+ subject: string;
99
+ text: string;
100
+ html: string;
101
+ idempotencyKey?: string;
102
+ };
103
+ export type ManagedEmailDeliveryResult = {
104
+ status: "sent";
105
+ providerMessageId: string | null;
106
+ } | {
107
+ status: "failed";
108
+ errorClass: string;
109
+ } | {
110
+ status: "outcome_unknown";
111
+ errorClass: string;
112
+ };
113
+ /** Provider-neutral, injectable boundary for every managed-auth email. */
114
+ export type ManagedEmailTransport = {
115
+ /** Effective provider sender; frozen into any idempotent payload digest. */
116
+ readonly sender: string;
117
+ /**
118
+ * Stable non-secret provider/account/policy namespace plus the provider's
119
+ * guaranteed key-retention window. Both are durably fenced before I/O.
120
+ */
121
+ readonly idempotency: {
122
+ readonly scope: string;
123
+ readonly retentionSeconds: number;
124
+ };
125
+ send(message: ManagedEmailMessage): Promise<ManagedEmailDeliveryResult>;
126
+ };
76
127
  export type AppDependencies = {
77
128
  settings: Settings;
129
+ /**
130
+ * Original deployment settings when `settings` is already overlaid with a
131
+ * deployment/workspace catalog snapshot. Model-bearing request adapters set
132
+ * this marker so core admission never feeds a synthetic reviewed provider
133
+ * back through deployment validation.
134
+ */
135
+ catalogSourceSettings?: Settings;
78
136
  db: Database;
79
137
  /**
80
138
  * Host-composed editable artifact engine. Standalone startup binds the same
@@ -90,13 +148,22 @@ export type AppDependencies = {
90
148
  editableArtifactOfficeImports?: EditableArtifactOfficeImportPort;
91
149
  bus: EventBus;
92
150
  workflowClient: SessionWorkflowClient;
93
- /** Injectable structural seam for replayable prompt fanout and wake work. */
151
+ /**
152
+ * Injectable structural seam for replayable post-commit fanout and wake work.
153
+ * The historical name is retained for host compatibility; every interactive
154
+ * session command now uses this boundary, not only prompt submission.
155
+ */
94
156
  schedulePromptPostCommit?: (task: () => Promise<void>) => void;
95
157
  /** Optional provider override for deterministic API/object-storage tests. */
96
158
  objectStorage?: ObjectStorageDependency;
97
159
  documentIndexer?: DocumentIndexClient;
98
160
  documentServices?: DocumentServices;
99
161
  observability?: Observability;
162
+ /**
163
+ * Throttled server-side presence for canonical managed browser sessions
164
+ * (`createUserPresenceRecorder`). Analytics only; never an authorization input.
165
+ */
166
+ userPresence?: UserPresenceRecorder | null;
100
167
  readinessChecks?: Partial<Record<"db" | "nats" | "temporal", () => Promise<void> | void>>;
101
168
  githubStateSecret?: string;
102
169
  /**
@@ -105,6 +172,8 @@ export type AppDependencies = {
105
172
  * App credentials; standalone deployments fall back to @opengeni/github.
106
173
  */
107
174
  githubAppApi?: GitHubAppApiPort;
175
+ /** Optional provider seam for the separately registered OpenGeni Lens App. */
176
+ prReviewGithubAppApi?: GitHubAppApiPort;
108
177
  /**
109
178
  * Optional host-owned connection credential seam. API-side consumers use
110
179
  * the MCP leg for Codemode/Code Mode; worker consumers bind the same port
@@ -118,8 +187,18 @@ export type AppDependencies = {
118
187
  */
119
188
  sessionAuthorization?: SessionAuthorizationPort | null;
120
189
  managedAuth?: ManagedAuth | null;
190
+ /** Provider-neutral browser login-slot adapter; required by dual/broker managed auth. */
191
+ managedAuthSessionAdapter?: ManagedAuthSessionAdapter | null;
192
+ /** Injectable managed-email transport; standalone API defaults to Resend or local capture. */
193
+ managedEmailTransport?: ManagedEmailTransport;
121
194
  /** Injectable Codex HTTP transport for deterministic API/provider tests. */
122
195
  codexFetch?: typeof fetch;
196
+ /** Injectable transport for customer OpenAI/Azure connection checks. */
197
+ directModelFetch?: typeof fetch;
198
+ /** Injectable GitHub transport for deterministic personal-OAuth tests. */
199
+ githubPersonalFetch?: typeof fetch;
200
+ /** Injectable credential-free GitHub transport for public repository verification tests. */
201
+ githubAnonymousFetch?: typeof fetch;
123
202
  /** Injectable xAI OAuth/subscription transport for deterministic API/provider tests. */
124
203
  xaiFetch?: typeof fetch;
125
204
  /** Injectable Slack Web API transport for deterministic bot-connection tests. */
@@ -130,6 +209,8 @@ export type AppDependencies = {
130
209
  fikenFetch?: typeof fetch;
131
210
  /** Injectable Integration Definition OAuth/API transport for deterministic tests. */
132
211
  apiIntegrationOAuthFetch?: typeof fetch;
212
+ /** Injectable specification/introspection transport, still network-policy checked. */
213
+ apiIntegrationSourceFetch?: typeof fetch;
133
214
  atlassianFetch?: typeof fetch;
134
215
  /** Injectable MCP OAuth setup deadline for deterministic stalled-provider tests. */
135
216
  oauthStartDeadlineMs?: number;
@@ -151,6 +232,8 @@ export type AppDependencies = {
151
232
  };
152
233
  export type ObjectStorageDependency = ReturnType<typeof createObjectStorage>;
153
234
  export type ApiRouteDeps = AppDependencies & {
235
+ resolveCatalogSettings: () => Promise<ResolvedCatalogSettings>;
236
+ managedEmailTransport: ManagedEmailTransport;
154
237
  objectStorage: ObjectStorageDependency;
155
238
  githubStateSecret: string;
156
239
  documentIndexer: DocumentIndexClient;
@@ -164,7 +247,7 @@ export type ApiRouteDeps = AppDependencies & {
164
247
  * the canonical admission path without constructing unrelated HTTP, document,
165
248
  * or sandbox services. The public API still passes its `ApiRouteDeps` superset.
166
249
  */
167
- export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit"> & {
250
+ export type AcceptSessionUserMessageDependencies = Pick<AppDependencies, "settings" | "catalogSourceSettings" | "db" | "bus" | "sessionAuthorization" | "schedulePromptPostCommit" | "observability"> & {
168
251
  workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
169
252
  objectStorage: ObjectStorageDependency;
170
253
  };
@@ -0,0 +1,10 @@
1
+ import { type AccessGrant, type Permission, type TurnExecutionPolicyV1 } from "@opengeni/contracts";
2
+ import { type AccessGrantAuthorization } from "./access/index.js";
3
+ /** The policy must be server-frozen, never supplied as request metadata. */
4
+ export declare function requireDeveloperSetupDelegatedPermissions(policy: TurnExecutionPolicyV1, permissions: readonly Permission[] | undefined): void;
5
+ /** Only pass server-owned persisted session/turn metadata, never request JSON. */
6
+ export declare function withDeveloperSetupCredentialRestriction(policy: TurnExecutionPolicyV1, source: {
7
+ grant?: AccessGrant;
8
+ authorization?: AccessGrantAuthorization | undefined;
9
+ trustedMetadata?: readonly unknown[];
10
+ }): TurnExecutionPolicyV1;