@opengeni/core 3.0.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/README.md +4 -4
  2. package/dist/access/index.d.ts +131 -7
  3. package/dist/access/service-initiator.d.ts +3 -0
  4. package/dist/application/archived-session-imports.d.ts +6 -0
  5. package/dist/application/composer-submit.d.ts +1 -1
  6. package/dist/application/connect-operation.d.ts +6 -0
  7. package/dist/application/external-workspace-members.d.ts +13 -1
  8. package/dist/application/modal-native-live-declaration-join.d.ts +37 -0
  9. package/dist/application/modal-native-original-configuration.d.ts +79 -0
  10. package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
  11. package/dist/application/new-session-drafts.d.ts +29 -2
  12. package/dist/application/organization-privacy.d.ts +57 -0
  13. package/dist/application/prepared-mcp-connection.d.ts +31 -0
  14. package/dist/application/sandbox-recovery.d.ts +58 -0
  15. package/dist/application/session-commands.d.ts +3 -0
  16. package/dist/application/session-tenancy.d.ts +13 -4
  17. package/dist/billing/agent-run-admission.d.ts +21 -0
  18. package/dist/billing/limits.d.ts +27 -1
  19. package/dist/billing/model-call-admission.d.ts +34 -0
  20. package/dist/billing/model-usage-settlement.d.ts +112 -0
  21. package/dist/canonical-human-identities.js +1 -1
  22. package/dist/{chunk-VCZFFEPB.js → chunk-7T2SZ7BI.js} +16 -2
  23. package/dist/chunk-7T2SZ7BI.js.map +1 -0
  24. package/dist/{chunk-ZYCNLYGH.js → chunk-OMJFIIWK.js} +178 -12
  25. package/dist/chunk-OMJFIIWK.js.map +1 -0
  26. package/dist/{chunk-H7X52RI2.js → chunk-QI2M2B2K.js} +83 -8
  27. package/dist/chunk-QI2M2B2K.js.map +1 -0
  28. package/dist/{chunk-OF65T3PM.js → chunk-TTWTXQB2.js} +94 -6
  29. package/dist/chunk-TTWTXQB2.js.map +1 -0
  30. package/dist/codex-model-availability.d.ts +55 -0
  31. package/dist/default-session-model.d.ts +192 -0
  32. package/dist/dependencies.d.ts +41 -7
  33. package/dist/developer-setup-credential-ceiling.d.ts +10 -0
  34. package/dist/domain/agent-config-resolution.d.ts +49 -0
  35. package/dist/domain/automations.d.ts +8 -1
  36. package/dist/domain/capabilities.d.ts +112 -8
  37. package/dist/domain/connection-account-selection-error.d.ts +8 -0
  38. package/dist/domain/connector-tool-permissions.d.ts +62 -0
  39. package/dist/domain/direct-model-provider.d.ts +3 -0
  40. package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
  41. package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
  42. package/dist/domain/editable-artifacts/ports.d.ts +10 -0
  43. package/dist/domain/editable-artifacts/service.d.ts +3 -1
  44. package/dist/domain/editable-artifacts/types.d.ts +1 -1
  45. package/dist/domain/encryption-key.d.ts +12 -0
  46. package/dist/domain/insights-timing.d.ts +16 -0
  47. package/dist/domain/insights-usage.d.ts +27 -0
  48. package/dist/domain/insights.d.ts +21 -3
  49. package/dist/domain/knowledge-files.d.ts +1 -1
  50. package/dist/domain/knowledge-preparation.d.ts +10 -0
  51. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  52. package/dist/domain/knowledge-search.d.ts +15 -76
  53. package/dist/domain/mcp-account-bindings.d.ts +17 -0
  54. package/dist/domain/mcp-account-routes.d.ts +21 -0
  55. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  56. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  57. package/dist/domain/personal-connection-delegations.d.ts +73 -12
  58. package/dist/domain/pr-review.d.ts +121 -6
  59. package/dist/domain/realtime-voice-billing.d.ts +103 -0
  60. package/dist/domain/resources.d.ts +17 -1
  61. package/dist/domain/scheduled-task-access.d.ts +265 -0
  62. package/dist/domain/scheduled-task-account-audit.d.ts +27 -0
  63. package/dist/domain/scheduled-task-audience.d.ts +70 -0
  64. package/dist/domain/scheduled-tasks.d.ts +61 -18
  65. package/dist/domain/session-connection-accounts.d.ts +53 -0
  66. package/dist/domain/session-file-access.d.ts +4 -0
  67. package/dist/domain/session-native-connection-replacement.d.ts +14 -0
  68. package/dist/domain/session-start-timing.d.ts +7 -0
  69. package/dist/domain/session-tool-policy.d.ts +102 -4
  70. package/dist/domain/sessions.d.ts +179 -15
  71. package/dist/domain/site-audience.d.ts +52 -0
  72. package/dist/domain/skills.d.ts +29 -1
  73. package/dist/domain/slack-bot.d.ts +46 -1
  74. package/dist/domain/slack-publication-secret-safety.d.ts +1 -1
  75. package/dist/domain/vaults/index.d.ts +7 -0
  76. package/dist/domain/vaults/mapping.d.ts +25 -0
  77. package/dist/domain/vaults/provider-registry.d.ts +72 -0
  78. package/dist/domain/vaults/provider-sync.d.ts +176 -0
  79. package/dist/domain/vaults/provider-writes.d.ts +57 -0
  80. package/dist/domain/vaults/secret-resolver.d.ts +34 -0
  81. package/dist/domain/vaults/types.d.ts +24 -0
  82. package/dist/domain/vaults/vault-service.d.ts +35 -0
  83. package/dist/domain/voice-input-billing.d.ts +77 -0
  84. package/dist/domain/web-search-billing.d.ts +51 -0
  85. package/dist/domain/workspace-credits.d.ts +7 -0
  86. package/dist/editable-artifact-live/application.d.ts +2 -1
  87. package/dist/editable-artifact-live/server.d.ts +5 -1
  88. package/dist/editable-artifact-live/ticket.d.ts +2 -1
  89. package/dist/editable-artifact-live/types.d.ts +9 -0
  90. package/dist/editable-artifact-live.js +2 -2
  91. package/dist/editable-artifacts.js +10 -2
  92. package/dist/goal-admission.d.ts +627 -0
  93. package/dist/host-session-usage-limit.d.ts +15 -0
  94. package/dist/index.d.ts +43 -8
  95. package/dist/index.js +22682 -11743
  96. package/dist/index.js.map +1 -1
  97. package/dist/managed-session.d.ts +110 -7
  98. package/dist/model-call.d.ts +58 -0
  99. package/dist/model-catalog.d.ts +29 -3
  100. package/dist/model-provider-credentials.d.ts +43 -0
  101. package/dist/product-usage-metrics.d.ts +30 -0
  102. package/dist/rigs/index.d.ts +1 -13
  103. package/dist/sandbox/fleet.d.ts +58 -4
  104. package/dist/sandbox/routing.d.ts +42 -2
  105. package/dist/sandbox/runtime-settings.d.ts +27 -17
  106. package/dist/session-authorization.d.ts +10 -0
  107. package/dist/session-usage-limit-metrics.d.ts +60 -0
  108. package/dist/session-usage-limits.d.ts +89 -0
  109. package/dist/site-agent-clamp.d.ts +71 -0
  110. package/dist/site-session-origin.d.ts +39 -2
  111. package/dist/transcription.d.ts +120 -3
  112. package/dist/turn-surface.d.ts +20 -0
  113. package/dist/user-presence.d.ts +32 -0
  114. package/dist/workflow-wake-contract.d.ts +13 -1
  115. package/package.json +15 -22
  116. package/src/access/index.ts +961 -38
  117. package/src/access/service-initiator.ts +50 -0
  118. package/src/application/api-integration-servers.ts +9 -0
  119. package/src/application/archived-session-imports.ts +161 -0
  120. package/src/application/composer-submit.ts +3 -2
  121. package/src/application/connect-authority.ts +3 -3
  122. package/src/application/connect-operation.ts +37 -3
  123. package/src/application/external-continuation.ts +20 -3
  124. package/src/application/external-link-work-admission.ts +3 -0
  125. package/src/application/external-workspace-members.ts +51 -3
  126. package/src/application/modal-native-live-declaration-join.ts +196 -0
  127. package/src/application/modal-native-original-configuration.ts +261 -0
  128. package/src/application/modal-native-worker-host-transport.ts +263 -0
  129. package/src/application/new-session-drafts.ts +172 -55
  130. package/src/application/organization-privacy.ts +161 -0
  131. package/src/application/prepared-mcp-connection.ts +133 -0
  132. package/src/application/sandbox-recovery.ts +78 -0
  133. package/src/application/session-commands.ts +73 -1
  134. package/src/application/session-mcp-credential-rotation.ts +61 -18
  135. package/src/application/session-tenancy.ts +262 -44
  136. package/src/application/user-resource-grants.ts +1 -29
  137. package/src/billing/agent-run-admission.ts +117 -0
  138. package/src/billing/limits.ts +138 -14
  139. package/src/billing/model-call-admission.ts +118 -0
  140. package/src/billing/model-usage-settlement.ts +472 -0
  141. package/src/codex-model-availability.ts +264 -0
  142. package/src/default-session-model.ts +692 -0
  143. package/src/dependencies.ts +48 -6
  144. package/src/developer-setup-credential-ceiling.ts +60 -0
  145. package/src/domain/agent-config-resolution.ts +148 -0
  146. package/src/domain/automations.ts +76 -2
  147. package/src/domain/capabilities.ts +830 -181
  148. package/src/domain/connection-account-selection-error.ts +19 -0
  149. package/src/domain/connector-tool-permissions.ts +572 -0
  150. package/src/domain/direct-model-provider.ts +62 -0
  151. package/src/domain/editable-artifacts/agent-application.ts +44 -6
  152. package/src/domain/editable-artifacts/durable-export.ts +100 -5
  153. package/src/domain/editable-artifacts/in-memory.ts +6 -0
  154. package/src/domain/editable-artifacts/ports.ts +11 -0
  155. package/src/domain/editable-artifacts/service.ts +20 -0
  156. package/src/domain/editable-artifacts/types.ts +1 -1
  157. package/src/domain/encryption-key.ts +26 -0
  158. package/src/domain/file-owner.ts +16 -1
  159. package/src/domain/github-action-policies.ts +1 -1
  160. package/src/domain/github-skill-source.ts +3 -1
  161. package/src/domain/insights-timing.ts +95 -0
  162. package/src/domain/insights-usage.ts +67 -0
  163. package/src/domain/insights.ts +167 -43
  164. package/src/domain/knowledge-files.ts +10 -3
  165. package/src/domain/knowledge-messages.ts +1 -0
  166. package/src/domain/knowledge-preparation.test.ts +276 -0
  167. package/src/domain/knowledge-preparation.ts +147 -0
  168. package/src/domain/knowledge-search.test.ts +617 -5
  169. package/src/domain/knowledge-search.ts +240 -23
  170. package/src/domain/mcp-account-bindings.ts +169 -0
  171. package/src/domain/mcp-account-routes.ts +152 -0
  172. package/src/domain/native-mcp-connection-admission.ts +14 -0
  173. package/src/domain/organization-integration-catalog.ts +88 -0
  174. package/src/domain/personal-connection-delegations.ts +399 -257
  175. package/src/domain/pr-review.ts +24 -8
  176. package/src/domain/realtime-voice-billing.ts +425 -0
  177. package/src/domain/resources.ts +50 -4
  178. package/src/domain/scheduled-task-access.ts +1089 -0
  179. package/src/domain/scheduled-task-account-audit.ts +90 -0
  180. package/src/domain/scheduled-task-audience.ts +249 -0
  181. package/src/domain/scheduled-tasks.ts +1313 -374
  182. package/src/domain/session-connection-accounts.ts +239 -0
  183. package/src/domain/session-file-access.ts +47 -0
  184. package/src/domain/session-native-connection-replacement.ts +64 -0
  185. package/src/domain/session-start-timing.ts +60 -0
  186. package/src/domain/session-tool-policy.ts +489 -14
  187. package/src/domain/sessions.ts +2254 -717
  188. package/src/domain/site-audience.ts +130 -0
  189. package/src/domain/skills.ts +9 -0
  190. package/src/domain/slack-bot.ts +141 -4
  191. package/src/domain/slack-publication-secret-safety.ts +1 -1
  192. package/src/domain/vaults/index.ts +19 -0
  193. package/src/domain/vaults/mapping.ts +190 -0
  194. package/src/domain/vaults/provider-registry.ts +201 -0
  195. package/src/domain/vaults/provider-sync.ts +531 -0
  196. package/src/domain/vaults/provider-writes.ts +288 -0
  197. package/src/domain/vaults/secret-resolver.ts +464 -0
  198. package/src/domain/vaults/types.ts +26 -0
  199. package/src/domain/vaults/vault-service.ts +1316 -0
  200. package/src/domain/voice-input-billing.ts +330 -0
  201. package/src/domain/web-search-billing.ts +169 -0
  202. package/src/domain/workspace-credits.ts +13 -0
  203. package/src/editable-artifact-live/application.ts +8 -1
  204. package/src/editable-artifact-live/server.ts +154 -6
  205. package/src/editable-artifact-live/ticket.ts +86 -1
  206. package/src/editable-artifact-live/types.ts +10 -0
  207. package/src/goal-admission.ts +220 -0
  208. package/src/host-session-usage-limit.ts +25 -0
  209. package/src/index.ts +75 -11
  210. package/src/managed-session.ts +137 -6
  211. package/src/model-call.ts +79 -0
  212. package/src/model-catalog.ts +345 -91
  213. package/src/model-provider-credentials.ts +394 -0
  214. package/src/product-usage-metrics.ts +101 -0
  215. package/src/rigs/index.ts +23 -111
  216. package/src/sandbox/fleet.ts +253 -28
  217. package/src/sandbox/routing.ts +204 -43
  218. package/src/sandbox/runtime-settings.ts +159 -85
  219. package/src/session-authorization.ts +172 -23
  220. package/src/session-usage-limit-metrics.ts +95 -0
  221. package/src/session-usage-limits.ts +415 -0
  222. package/src/site-agent-clamp.ts +226 -0
  223. package/src/site-session-origin.ts +84 -5
  224. package/src/transcription.ts +123 -4
  225. package/src/turn-surface.ts +47 -0
  226. package/src/user-presence.ts +134 -0
  227. package/src/workflow-wake-contract.ts +14 -1
  228. package/dist/application/host-mcp-owner.d.ts +0 -6
  229. package/dist/application/host-mcp-resolvers.d.ts +0 -13
  230. package/dist/chunk-5WZYFL45.js +0 -266
  231. package/dist/chunk-5WZYFL45.js.map +0 -1
  232. package/dist/chunk-H7X52RI2.js.map +0 -1
  233. package/dist/chunk-OF65T3PM.js.map +0 -1
  234. package/dist/chunk-VCZFFEPB.js.map +0 -1
  235. package/dist/chunk-ZYCNLYGH.js.map +0 -1
  236. package/dist/domain/connection-authority.d.ts +0 -97
  237. package/dist/domain/connection-authority.js +0 -169
  238. package/dist/domain/connection-authority.js.map +0 -1
  239. package/dist/domain/environments.d.ts +0 -33
  240. package/dist/domain/host-mcp-authority-source-admission.d.ts +0 -10
  241. package/dist/domain/host-mcp-task-admission.d.ts +0 -18
  242. package/dist/domain/packs.d.ts +0 -59
  243. package/dist/domain/product-integration-pack.d.ts +0 -44
  244. package/dist/domain/product-integration-skill.gen.d.ts +0 -5
  245. package/dist/remote-mcp-credentials.d.ts +0 -23
  246. package/dist/remote-mcp-credentials.js +0 -11
  247. package/dist/remote-mcp-credentials.js.map +0 -1
  248. package/src/application/host-mcp-owner.ts +0 -41
  249. package/src/application/host-mcp-resolvers.ts +0 -84
  250. package/src/domain/connection-authority.ts +0 -329
  251. package/src/domain/environments.ts +0 -120
  252. package/src/domain/host-mcp-authority-source-admission.ts +0 -25
  253. package/src/domain/host-mcp-task-admission.ts +0 -121
  254. package/src/domain/packs.ts +0 -699
  255. package/src/domain/product-integration-pack.ts +0 -42
  256. package/src/domain/product-integration-skill.gen.ts +0 -52
  257. package/src/remote-mcp-credentials.ts +0 -361
@@ -1,5 +1,6 @@
1
- import { type AccessGrant, type ConnectionMetadata, type OpenGeniSlackBotConnectionMetadata as OpenGeniSlackBotMetadata, type Session } from "@opengeni/contracts";
1
+ import { type AccessGrant, type ConnectionMetadata, type FirstPartyMcpToolName, type OpenGeniSlackBotConnectionMetadata as OpenGeniSlackBotMetadata, type ScheduledTask, type ScheduledTaskAgentConfig, type Session } from "@opengeni/contracts";
2
2
  import { type ConnectionMetadataWithVerification, type Database } from "@opengeni/db";
3
+ import { type AccessGrantAuthorization } from "../access/index.js";
3
4
  export declare function openGeniSlackBotMetadata(metadata: Record<string, unknown>): OpenGeniSlackBotMetadata | null;
4
5
  export declare function isOpenGeniSlackBotConnection(connection: ConnectionMetadata & Partial<Pick<ConnectionMetadataWithVerification, "verifiedInstallAt" | "verifiedInstallVersion">>): boolean;
5
6
  export declare function hasReservedOpenGeniSlackBotMetadata(metadata: Record<string, unknown> | null | undefined): boolean;
@@ -17,3 +18,47 @@ export declare function scheduledSlackBotConnectionId(metadata: Record<string, u
17
18
  * an authorization mechanism for a workspace-shared bot credential.
18
19
  */
19
20
  export declare function isTrustedScheduledSlackBotSession(session: Pick<Session, "createdBy" | "createdByContext" | "metadata">): boolean;
21
+ /**
22
+ * Proves, with the bot's own token, that it may post in the chosen channel:
23
+ * the bot is a member and the channel is active and not shared with another
24
+ * organization. Supplied only by the HTTP routes a person uses to edit tasks.
25
+ */
26
+ export type ScheduledTaskSlackChannelVerifier = (input: {
27
+ connectionId: string;
28
+ channelId: string;
29
+ }) => Promise<void>;
30
+ /**
31
+ * Whether this request is a signed-in person acting for themselves: never an
32
+ * agent attempt, a service, an API key, or a request carrying service
33
+ * provenance. The same rule gates Agent learning settings.
34
+ */
35
+ export declare function isAuthenticatedPersonAuthorization(authorization: AccessGrantAuthorization | undefined): boolean;
36
+ /**
37
+ * A scheduled task may post as the Opengeni workspace bot only to the one
38
+ * Slack channel a person chose on the task. Choosing or changing that channel
39
+ * therefore needs a signed-in person with `connections:write`, and the bot's
40
+ * membership is verified at that moment. Keeping or clearing the existing
41
+ * channel needs neither, so an agent editing other task fields cannot redirect
42
+ * posts but also does not have to re-prove the person's choice. Clearing is the
43
+ * safe direction and is never refused, even for a task that continues one chat.
44
+ */
45
+ export declare function validateScheduledTaskSlackChannel(input: {
46
+ grant: AccessGrant;
47
+ authorization?: AccessGrantAuthorization | undefined;
48
+ previous: Pick<ScheduledTaskAgentConfig, "slackBotConnectionId" | "slackBotChannelId"> | null;
49
+ next: Pick<ScheduledTaskAgentConfig, "slackBotConnectionId" | "slackBotChannelId">;
50
+ runMode: ScheduledTask["runMode"];
51
+ /**
52
+ * Null unless the task already created the reusable chat its runs continue.
53
+ * Otherwise reports whether that chat was created with the posting tools,
54
+ * which are fixed at creation.
55
+ */
56
+ reusableSessionCanPost: (() => Promise<boolean>) | null;
57
+ verifySlackChannel?: ScheduledTaskSlackChannelVerifier | undefined;
58
+ }): Promise<void>;
59
+ /**
60
+ * Add the bot posting tools to a generated scheduled run when, and only when,
61
+ * a person chose the task's Slack channel. The deployment ceiling still
62
+ * applies: an operator who disallowed these tools keeps them off.
63
+ */
64
+ export declare function withScheduledSlackBotPostingTools(tools: readonly FirstPartyMcpToolName[], agentConfig: Pick<ScheduledTaskAgentConfig, "slackBotConnectionId" | "slackBotChannelId">, allowedTools: readonly FirstPartyMcpToolName[]): FirstPartyMcpToolName[];
@@ -3,6 +3,6 @@ export declare const SLACK_PUBLICATION_CREDENTIAL_OMISSION = "[credential omitte
3
3
  * Deterministic, sink-local protection for text that is about to be persisted
4
4
  * as a Slack publication projection or rendered to Slack. It intentionally
5
5
  * does not scan or mutate canonical Memory, durable-learning receipts, model
6
- * context, history, events, or any other internal OpenGeni content path.
6
+ * context, history, events, or any other internal Opengeni content path.
7
7
  */
8
8
  export declare function sanitizeSlackPublicationText(value: string): string;
@@ -0,0 +1,7 @@
1
+ /** Vaults and secret references: the only import point for the vault domain. */
2
+ export { buildMissingSecretAskCard } from "@opengeni/contracts";
3
+ export { isVaultError, VaultError, vaultErrorFromDatabase } from "@opengeni/db";
4
+ export { toVaultItem, toVaultItemSummary, toVaultSummary, vaultCanManage, vaultCanWrite, vaultItemReferences, type VaultCallerAuthority, } from "./mapping.js";
5
+ export { chooseSecretCandidate, createSecretResolver, type SecretResolverOptions, } from "./secret-resolver.js";
6
+ export type { VaultRequestActor, VaultServiceDeps } from "./types.js";
7
+ export { createVaultService, vaultActorIsApiKey, type VaultService } from "./vault-service.js";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Vault rows (encrypted, as the 0739 routines return them) to the public
3
+ * contract shapes. Only text-kind field values are decrypted for display;
4
+ * every other kind stays server-side until an audited reveal or a resolve.
5
+ */
6
+ import { type VaultItem, type VaultItemReferences, type VaultItemSummary, type VaultSummary } from "@opengeni/contracts";
7
+ import { type VaultItemRow, type VaultRow } from "@opengeni/db";
8
+ /** What the caller may do beyond reading; decided by the route's grant. */
9
+ export type VaultCallerAuthority = {
10
+ /** `secrets:write` */
11
+ write: boolean;
12
+ /** `account:admin` on the organization */
13
+ accountAdmin: boolean;
14
+ };
15
+ export declare function vaultCanWrite(row: VaultRow, authority: VaultCallerAuthority): boolean;
16
+ export declare function vaultCanManage(row: VaultRow, authority: VaultCallerAuthority): boolean;
17
+ export declare function toVaultSummary(row: VaultRow, authority: VaultCallerAuthority): VaultSummary;
18
+ /**
19
+ * Ready references for an item. Every reference names the vault and the field
20
+ * (`{{secret:Vault/Item/field}}`), so it cannot become ambiguous when another
21
+ * reachable vault gains an item with the same name.
22
+ */
23
+ export declare function vaultItemReferences(item: Pick<VaultItemRow, "id" | "name" | "vaultName" | "fields" | "primaryFieldId">): VaultItemReferences;
24
+ export declare function toVaultItemSummary(row: VaultItemRow, key: Uint8Array | null): VaultItemSummary;
25
+ export declare function toVaultItem(row: VaultItemRow, key: Uint8Array | null): VaultItem;
@@ -0,0 +1,72 @@
1
+ import type { Settings } from "@opengeni/config";
2
+ import type { ConnectionMetadata, VaultErrorCode } from "@opengeni/contracts";
3
+ import { type Database } from "@opengeni/db";
4
+ import { type VaultProvider, type VaultProviderErrorCode, type VaultProviderRegistry } from "@opengeni/vaults";
5
+ /**
6
+ * Provider error codes as vault API error codes (§10B.1.1). `provider_not_found`
7
+ * is the vault (or, for reads, the field); `provider_permission_denied` is
8
+ * `vault_read_only` for writes and `vault_permission_denied` otherwise.
9
+ */
10
+ export declare function vaultErrorCodeForProvider(code: VaultProviderErrorCode, operation: "read" | "write" | "vault"): VaultErrorCode;
11
+ /**
12
+ * 1Password service-account connections (design §10.9). The token lives in
13
+ * the existing encrypted connection-credential store as `{ token }` (no
14
+ * `headers`, so the egress broker can never inject it); metadata carries only
15
+ * `{ credentialRole, planTier, ownership, accountName, label, verifiedAt }`.
16
+ */
17
+ export declare const ONEPASSWORD_PROVIDER_DOMAIN = "1password.com";
18
+ export declare const ONEPASSWORD_CREDENTIAL_ROLE = "onepassword_service_account";
19
+ export type OnePasswordPlanTier = "family" | "teams" | "business";
20
+ export type OnePasswordConnectionOwnership = "user" | "workspace" | "organization";
21
+ export type OnePasswordConnectionMetadata = {
22
+ credentialRole: typeof ONEPASSWORD_CREDENTIAL_ROLE;
23
+ planTier: OnePasswordPlanTier;
24
+ ownership: OnePasswordConnectionOwnership;
25
+ /** Sign-in host from the token, for example "my.1password.com". */
26
+ accountName: string | null;
27
+ label: string | null;
28
+ verifiedAt: string;
29
+ };
30
+ export declare function onePasswordConnectionMetadata(metadata: Record<string, unknown> | null | undefined): OnePasswordConnectionMetadata | null;
31
+ export declare function isOnePasswordConnection(connection: ConnectionMetadata): boolean;
32
+ /**
33
+ * Builds a provider for one stored token. Supplied by apps/api and apps/worker
34
+ * as `(input) => import("@opengeni/vaults-onepassword").then(...)`, so core
35
+ * never loads the 1Password SDK (OP-5).
36
+ */
37
+ export type OnePasswordVaultProviderFactory = (input: {
38
+ token: string;
39
+ planTier: OnePasswordPlanTier;
40
+ allowFakeTokens: boolean;
41
+ }) => Promise<VaultProvider>;
42
+ export declare function onePasswordCredentialBundle(token: string): Record<string, unknown>;
43
+ /**
44
+ * Decrypts the token of one 1Password connection the caller can use from
45
+ * `workspaceId`: one in this workspace (shared, or personal to `subjectId`),
46
+ * or one added in another workspace that still serves vaults reached here
47
+ * (the caller's own personal connection, or a shared connection behind an
48
+ * organization vault). The token goes only to the provider factory; it is
49
+ * never logged or returned to a client.
50
+ */
51
+ export declare function loadOnePasswordConnectionToken(db: Database, settings: Settings, input: {
52
+ workspaceId: string;
53
+ connectionId: string;
54
+ subjectId: string | null;
55
+ }): Promise<{
56
+ token: string;
57
+ metadata: OnePasswordConnectionMetadata;
58
+ }>;
59
+ /**
60
+ * The provider registry for one workspace request or attempt:
61
+ * - `onepassword` vaults load their connection token and the SDK lazily;
62
+ * - `host` vaults use the embedder's `connectionCredentials.vaultProvider`.
63
+ */
64
+ export declare function createWorkspaceVaultProviderRegistry(input: {
65
+ db: Database;
66
+ settings: Settings;
67
+ workspaceId: string;
68
+ /** The acting subject; personal 1Password connections resolve only for their owner. */
69
+ subjectId: string | null;
70
+ hostVaultProvider?: VaultProvider | null;
71
+ onePasswordVaultProvider?: OnePasswordVaultProviderFactory | null;
72
+ }): VaultProviderRegistry;
@@ -0,0 +1,176 @@
1
+ import { type VaultFieldKind, type VaultItemType, type VaultSyncStatus } from "@opengeni/contracts";
2
+ import { type Database, type VaultDbContext } from "@opengeni/db";
3
+ import { type ProviderItemMeta, type VaultProvider, type VaultProviderContext, type VaultProviderErrorCode, type VaultProviderRegistry } from "@opengeni/vaults";
4
+ /**
5
+ * Provider vault metadata mirror (design §10.9, OP-1/OP-4). A linked
6
+ * 1Password or host vault keeps a metadata-only mirror (item names, types,
7
+ * websites, field names and kinds); values are always read live. A sync costs
8
+ * one `listVaults` call and skips `listItems` entirely when the provider's
9
+ * `contentVersion` is unchanged, so FAMILY-plan quotas are not burnt on
10
+ * no-op refreshes.
11
+ *
12
+ * The engine is storage-agnostic: the vault service binds `ProviderMirrorStore`
13
+ * to its tables (`vault_items`, `vault_item_fields`, `vaults.sync_status`,
14
+ * `vaults.rate_limited_until`).
15
+ */
16
+ export interface ProviderMirrorField {
17
+ externalFieldId: string;
18
+ name: string;
19
+ kind: VaultFieldKind;
20
+ position: number;
21
+ }
22
+ export interface ProviderMirrorItem {
23
+ externalItemId: string;
24
+ /** Valid, vault-unique (case-insensitive) secret name. */
25
+ name: string;
26
+ /** The provider's own name, kept when it had to be sanitized or de-duplicated. */
27
+ providerName: string;
28
+ type: VaultItemType;
29
+ websites: string[];
30
+ fields: ProviderMirrorField[];
31
+ primaryExternalFieldId: string | null;
32
+ hasTotp: boolean;
33
+ version: string | null;
34
+ updatedAt: string | null;
35
+ }
36
+ export interface ProviderMirrorPlan {
37
+ contentVersion: string | null;
38
+ items: ProviderMirrorItem[];
39
+ /** Items beyond `VAULT_LIMITS.itemsPerVault` that were not mirrored. */
40
+ truncated: number;
41
+ }
42
+ export interface ProviderSyncStatusUpdate {
43
+ syncStatus: VaultSyncStatus;
44
+ syncErrorCode: VaultProviderErrorCode | null;
45
+ syncErrorMessage: string | null;
46
+ rateLimitedUntil: Date | null;
47
+ /** Set only when the provider was reached and the mirror is current. */
48
+ lastSyncedAt: Date | null;
49
+ }
50
+ export interface ProviderMirrorStore {
51
+ /** Replace the mirror for this vault in one transaction (upsert by external id, drop missing). */
52
+ replaceMirror(plan: ProviderMirrorPlan): Promise<void>;
53
+ setSyncStatus(update: ProviderSyncStatusUpdate): Promise<void>;
54
+ }
55
+ export interface ProviderVaultSyncTarget {
56
+ externalVaultId: string;
57
+ /** `contentVersion` recorded by the last successful mirror, if any. */
58
+ mirroredContentVersion: string | null;
59
+ rateLimitedUntil: Date | null;
60
+ }
61
+ export type ProviderVaultSyncResult = {
62
+ status: "synced";
63
+ contentVersion: string | null;
64
+ itemCount: number;
65
+ truncated: number;
66
+ } | {
67
+ status: "unchanged";
68
+ contentVersion: string | null;
69
+ } | {
70
+ status: "skipped_rate_limited";
71
+ rateLimitedUntil: Date;
72
+ } | {
73
+ status: "failed";
74
+ syncStatus: VaultSyncStatus;
75
+ code: VaultProviderErrorCode;
76
+ rateLimitedUntil: Date | null;
77
+ };
78
+ /** When the provider gives no retry hint, back off this long after a 429. */
79
+ export declare const PROVIDER_RATE_LIMIT_DEFAULT_BACKOFF_MS: number;
80
+ /** Map a provider item name onto a valid secret name (Q-10). */
81
+ export declare function providerSecretName(raw: string, fallback?: string): string;
82
+ /** Appends " (2)", " (3)" … until the name is unique case-insensitively. */
83
+ export declare function uniqueProviderName(name: string, taken: Set<string>): string;
84
+ /**
85
+ * The field a bare `vault/item` reference resolves to: the item type's default
86
+ * (§10B.2), then password → value → credential → note by name, then the first
87
+ * concealed field. TOTP fields are never primary (they have `/otp`).
88
+ */
89
+ export declare function providerPrimaryFieldId(item: Pick<ProviderItemMeta, "type" | "fields">): string | null;
90
+ /**
91
+ * Deterministic mirror projection. Items are ordered by provider name then
92
+ * external id before de-duplication, so the same provider state always yields
93
+ * the same Opengeni names; field names are de-duplicated within each item.
94
+ */
95
+ export declare function planProviderMirror(items: readonly ProviderItemMeta[], contentVersion: string | null): ProviderMirrorPlan;
96
+ /** Sync status for a provider failure; rate limits persist `rateLimitedUntil`. */
97
+ export declare function providerSyncFailure(error: unknown, now: Date): ProviderSyncStatusUpdate & {
98
+ syncErrorCode: VaultProviderErrorCode;
99
+ };
100
+ /**
101
+ * Refresh one linked vault's mirror. While `rateLimitedUntil` is in the future
102
+ * the provider is not called at all unless `force` is set.
103
+ */
104
+ export declare function syncProviderVault(input: {
105
+ provider: VaultProvider;
106
+ ctx: VaultProviderContext;
107
+ target: ProviderVaultSyncTarget;
108
+ store: ProviderMirrorStore;
109
+ now?: () => Date;
110
+ /** Re-list items even when `contentVersion` is unchanged. */
111
+ force?: boolean;
112
+ }): Promise<ProviderVaultSyncResult>;
113
+ /** Binds the mirror store to the 0739 routines for one connected vault. */
114
+ export declare function databaseProviderMirrorStore(db: Database, context: VaultDbContext, vaultId: string): ProviderMirrorStore;
115
+ /**
116
+ * Sync one linked vault the caller reaches: load its provider refs and mirror
117
+ * version, resolve its provider, refresh the mirror and record sync status.
118
+ */
119
+ export declare function syncLinkedProviderVault(input: {
120
+ db: Database;
121
+ context: VaultDbContext;
122
+ vaultId: string;
123
+ providers: VaultProviderRegistry;
124
+ budget?: VaultProviderContext["budget"];
125
+ force?: boolean;
126
+ now?: () => Date;
127
+ }): Promise<ProviderVaultSyncResult>;
128
+ /** How stale a linked vault's mirror may be before a search refreshes it. */
129
+ export declare const LINKED_VAULT_SEARCH_MAX_AGE_MS: number;
130
+ /** How stale it may be before a reference that found nothing refreshes it. */
131
+ export declare const LINKED_VAULT_MISS_MAX_AGE_MS: number;
132
+ /** How long a search or resolution waits for refreshes before answering. */
133
+ export declare const LINKED_VAULT_REFRESH_WAIT_MS = 8000;
134
+ /**
135
+ * How long a person opening a linked vault waits for its stale mirror to
136
+ * refresh before the page shows what is mirrored; a slower refresh finishes in
137
+ * the background and the next load shows it.
138
+ */
139
+ export declare const LINKED_VAULT_OPEN_WAIT_MS = 3000;
140
+ /** The vault fields a freshness check needs (a `VaultRow` has them all). */
141
+ export type LinkedVaultFreshness = {
142
+ id: string;
143
+ source: string;
144
+ syncStatus: VaultSyncStatus;
145
+ lastSyncedAt: string | null;
146
+ rateLimitedUntil: string | null;
147
+ updatedAt: string;
148
+ };
149
+ /**
150
+ * Whether a linked vault's mirror is older than `maxAgeMs`. A vault whose last
151
+ * sync failed counts from that failure (it is recorded as `updatedAt`), so a
152
+ * broken connection is retried once per `maxAgeMs`, not on every call. A vault
153
+ * under a provider rate limit is never stale until the limit lifts.
154
+ */
155
+ export declare function linkedVaultNeedsRefresh(vault: LinkedVaultFreshness, maxAgeMs: number, now: Date): boolean;
156
+ /**
157
+ * Bring stale linked vault mirrors up to date, so items added in the provider
158
+ * (for example straight in 1Password) are found without anyone pressing Sync.
159
+ *
160
+ * Each refresh is the ordinary non-forced sync: one `listVaults` call, and an
161
+ * item listing only when the provider says the vault changed. Refreshes of the
162
+ * same vault share one call per process. The caller waits at most `waitMs`;
163
+ * slower refreshes finish in the background and record their own status.
164
+ * Never throws: failures are recorded as the vault's sync status.
165
+ *
166
+ * Returns the ids of the vaults whose mirror changed before the wait ended.
167
+ */
168
+ export declare function refreshStaleLinkedVaults(input: {
169
+ db: Database;
170
+ context: VaultDbContext;
171
+ vaults: readonly LinkedVaultFreshness[];
172
+ providers: VaultProviderRegistry;
173
+ maxAgeMs: number;
174
+ waitMs?: number;
175
+ now?: () => Date;
176
+ }): Promise<string[]>;
@@ -0,0 +1,57 @@
1
+ import { type VaultFieldInput, type VaultFieldKind, type VaultItemType } from "@opengeni/contracts";
2
+ import { type Database, type VaultDbContext, type VaultFieldRow, type VaultRow } from "@opengeni/db";
3
+ import { type ProviderCallBudget, type VaultProviderRegistry } from "@opengeni/vaults";
4
+ /**
5
+ * Edits of items in a read-write connected vault (OP-3): the change is written
6
+ * to the provider (1Password `items.get` → patch → `items.put`, with the
7
+ * mirrored version as the expected version), then the metadata mirror is
8
+ * refreshed. Values never touch Opengeni storage.
9
+ */
10
+ /** One field change; the REST `VaultFieldInput` and the agent `secret_save` field both fit. */
11
+ export interface ProviderFieldChange {
12
+ fieldId?: string | undefined;
13
+ name: string;
14
+ kind?: VaultFieldKind | undefined;
15
+ value?: string | undefined;
16
+ generate?: VaultFieldInput["generate"] | undefined;
17
+ fromReference?: string | undefined;
18
+ fileBase64?: string | undefined;
19
+ restoreVersion?: number | undefined;
20
+ remove?: true | undefined;
21
+ }
22
+ export interface ProviderItemChange {
23
+ name?: string | undefined;
24
+ type?: VaultItemType | undefined;
25
+ websites?: string[] | undefined;
26
+ fields?: readonly ProviderFieldChange[] | undefined;
27
+ }
28
+ export interface ProviderWriteDeps {
29
+ db: Database;
30
+ context: VaultDbContext;
31
+ providers: VaultProviderRegistry;
32
+ /** Resolves `fromReference` field inputs (audited as a use by the caller). */
33
+ resolveReference: (raw: string) => Promise<string>;
34
+ budget?: ProviderCallBudget;
35
+ }
36
+ /** A connected vault the caller may change items in. */
37
+ export declare function assertProviderVaultWritable(vault: VaultRow): void;
38
+ /** Create (existing = null) or update an item in a connected read-write vault; returns its item id. */
39
+ export declare function writeProviderVaultItem(deps: ProviderWriteDeps, input: {
40
+ vault: VaultRow;
41
+ existing: {
42
+ itemId: string;
43
+ name: string;
44
+ type: VaultItemType;
45
+ websites: string[];
46
+ fields: VaultFieldRow[];
47
+ expectedGeneration?: number | undefined;
48
+ } | null;
49
+ change: ProviderItemChange;
50
+ /** Receives the names of fields whose values were generated. */
51
+ generated?: string[];
52
+ }): Promise<string>;
53
+ /** Archive an item in a connected read-write vault (the provider keeps it recoverable). */
54
+ export declare function archiveProviderVaultItem(deps: ProviderWriteDeps, input: {
55
+ vault: VaultRow;
56
+ itemId: string;
57
+ }): Promise<void>;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The hosted secret resolver (§10B.2). One database roundtrip returns the
3
+ * principal's facts and every candidate for every reference; candidates are
4
+ * chosen here (archived dropped, lowest tier, names over aliases, otherwise
5
+ * ambiguous), provider values are fetched, hosted values decrypted, and the
6
+ * batch is recorded. A call resolves all of its references or none (I2).
7
+ */
8
+ import { type SecretPrincipal, type SecretReference, type SecretReferenceFailure, type SecretResolver } from "@opengeni/contracts";
9
+ import { type SecretReferenceCandidate, type SecretResolutionMeta } from "@opengeni/db";
10
+ import { type ProviderCallBudget, type VaultProviderRegistry } from "@opengeni/vaults";
11
+ import type { VaultServiceDeps } from "./types.js";
12
+ export type SecretResolverOptions = {
13
+ /** `agent.capabilities.secrets`; when false the resolver refuses every reference. */
14
+ capabilityEnabled: boolean;
15
+ /** Provider calls allowed for this attempt (Q-18); a fresh 50-call budget by default. */
16
+ attemptBudget?: ProviderCallBudget;
17
+ /**
18
+ * Connected vaults for callers that only learn the acting human from the
19
+ * lookup itself (browser and computer routes, `run_on`, the tool gateway):
20
+ * 1Password connection tokens load for that subject. `deps.providers` wins.
21
+ */
22
+ providersForSubject?: (subjectId: string | null) => VaultProviderRegistry;
23
+ };
24
+ /**
25
+ * Choose one candidate per reference (§10B.2): drop archived items, keep the
26
+ * lowest tier, prefer names over aliases; more than one remaining target is
27
+ * ambiguous and returns ready references to choose from.
28
+ */
29
+ export declare function chooseSecretCandidate(reference: SecretReference, candidates: readonly SecretReferenceCandidate[], meta: SecretResolutionMeta): {
30
+ candidate: SecretReferenceCandidate;
31
+ } | {
32
+ failure: SecretReferenceFailure;
33
+ };
34
+ export declare function createSecretResolver(deps: VaultServiceDeps, principal: SecretPrincipal, opts: SecretResolverOptions): SecretResolver;
@@ -0,0 +1,24 @@
1
+ import type { AccessGrant, SecretClock } from "@opengeni/contracts";
2
+ import type { Database } from "@opengeni/db";
3
+ import type { VaultProviderRegistry } from "@opengeni/vaults";
4
+ export interface VaultServiceDeps {
5
+ db: Database;
6
+ /**
7
+ * The variable-set envelope key (`OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY`);
8
+ * null when unconfigured, which fails value reads and writes with
9
+ * `encryption_key_missing`.
10
+ */
11
+ encryptionKey: Uint8Array | null;
12
+ /** Provider vaults (1Password, host); none configured by default. */
13
+ providers?: VaultProviderRegistry;
14
+ clock?: SecretClock;
15
+ }
16
+ /**
17
+ * A person or API key calling the vault API. Routes check the permission each
18
+ * operation needs; the actor carries what the service needs on top of that.
19
+ */
20
+ export interface VaultRequestActor {
21
+ grant: AccessGrant;
22
+ /** The caller holds `account:admin` on the organization (organization vaults). */
23
+ accountAdmin: boolean;
24
+ }
@@ -0,0 +1,35 @@
1
+ import { type CreateVaultItemRequest, type CreateVaultRequest, type ListVaultItemsQuery, type MoveVaultItemRequest, type RevealVaultFieldRequest, type RevealVaultFieldResponse, type SecretDeleteInput, type SecretDeleteOutput, type SecretGetInput, type SecretMoveInput, type SecretMoveOutput, type SecretPrincipal, type SecretSaveInput, type SecretSaveOutput, type SecretSearchInput, type SecretSearchOutput, type SessionSecretsView, type UpdateVaultItemRequest, type UpdateVaultRequest, type VaultFieldVersionMeta, type VaultItem, type VaultItemSummary, type VaultPolicy, type VaultSummary } from "@opengeni/contracts";
2
+ import type { VaultRequestActor, VaultServiceDeps } from "./types.js";
3
+ export interface VaultService {
4
+ list(actor: VaultRequestActor, workspaceId: string): Promise<VaultSummary[]>;
5
+ get(actor: VaultRequestActor, workspaceId: string, vaultId: string): Promise<VaultSummary>;
6
+ create(actor: VaultRequestActor, workspaceId: string, req: CreateVaultRequest): Promise<VaultSummary>;
7
+ update(actor: VaultRequestActor, workspaceId: string, vaultId: string, req: UpdateVaultRequest): Promise<VaultSummary>;
8
+ remove(actor: VaultRequestActor, workspaceId: string, vaultId: string, confirmName: string): Promise<void>;
9
+ listItems(actor: VaultRequestActor, workspaceId: string, vaultId: string, q: ListVaultItemsQuery): Promise<{
10
+ items: VaultItemSummary[];
11
+ nextCursor: string | null;
12
+ }>;
13
+ getItem(actor: VaultRequestActor, workspaceId: string, itemId: string): Promise<VaultItem>;
14
+ createItem(actor: VaultRequestActor, workspaceId: string, vaultId: string, req: CreateVaultItemRequest): Promise<VaultItem>;
15
+ updateItem(actor: VaultRequestActor, workspaceId: string, itemId: string, req: UpdateVaultItemRequest): Promise<VaultItem>;
16
+ archiveItem(actor: VaultRequestActor, workspaceId: string, itemId: string): Promise<void>;
17
+ restoreItem(actor: VaultRequestActor, workspaceId: string, itemId: string): Promise<VaultItem>;
18
+ deleteItemPermanently(actor: VaultRequestActor, workspaceId: string, itemId: string): Promise<void>;
19
+ moveItem(actor: VaultRequestActor, workspaceId: string, itemId: string, req: MoveVaultItemRequest): Promise<VaultItem>;
20
+ revealField(actor: VaultRequestActor, workspaceId: string, fieldId: string, req: RevealVaultFieldRequest & {
21
+ itemId?: string;
22
+ }): Promise<RevealVaultFieldResponse>;
23
+ listFieldVersions(actor: VaultRequestActor, workspaceId: string, fieldId: string): Promise<VaultFieldVersionMeta[]>;
24
+ restoreFieldVersion(actor: VaultRequestActor, workspaceId: string, itemId: string, fieldId: string, version: number): Promise<VaultItem>;
25
+ sessionSecrets(actor: VaultRequestActor, workspaceId: string, sessionId: string): Promise<SessionSecretsView>;
26
+ setSessionPolicy(actor: VaultRequestActor, workspaceId: string, sessionId: string, policy: VaultPolicy): Promise<SessionSecretsView>;
27
+ searchForAgent(principal: SecretPrincipal, input: SecretSearchInput): Promise<SecretSearchOutput>;
28
+ saveForAgent(principal: SecretPrincipal, input: SecretSaveInput): Promise<SecretSaveOutput>;
29
+ moveForAgent(principal: SecretPrincipal, input: SecretMoveInput): Promise<SecretMoveOutput>;
30
+ archiveForAgent(principal: SecretPrincipal, input: SecretDeleteInput): Promise<SecretDeleteOutput>;
31
+ readForAgent(principal: SecretPrincipal, input: SecretGetInput, permissions: readonly string[]): Promise<RevealVaultFieldResponse>;
32
+ }
33
+ /** API keys and configured keys are not people. */
34
+ export declare function vaultActorIsApiKey(actor: VaultRequestActor): boolean;
35
+ export declare function createVaultService(deps: VaultServiceDeps): VaultService;
@@ -0,0 +1,77 @@
1
+ import { type Settings, type VoiceInputPricing, type VoiceInputUsage } from "@opengeni/config";
2
+ import { type Database } from "@opengeni/db";
3
+ import { type TranscriptionBilling, type TranscriptionBillingContext } from "../transcription.js";
4
+ /** Credit debit type and usage source for deployment-funded voice input. */
5
+ export declare const VOICE_INPUT_DEBIT_TYPE = "voice_transcription_debit";
6
+ export declare const VOICE_INPUT_SOURCE_TYPE = "voice_transcription";
7
+ /** How the billed quantity was measured; recorded on the ledger entry. */
8
+ export type VoiceInputBillingBasis = "provider_tokens" | "provider_duration" | "server_duration" | "reconciled_receipt";
9
+ /**
10
+ * Pick the billed measurement. Provider usage wins when this deployment can
11
+ * price it (token usage with token rates, or a reported duration). Otherwise
12
+ * the duration the server measured from WAV bytes it produced bills. Every
13
+ * deployment-funded call carries that server duration, so an unpriced usage
14
+ * shape never leaves a call unbillable. A client-reported duration is never a
15
+ * billing input.
16
+ */
17
+ export declare function voiceInputBillableUsage(input: {
18
+ pricing: VoiceInputPricing;
19
+ usage: VoiceInputUsage | null;
20
+ trustedDurationSeconds?: number | undefined;
21
+ }): {
22
+ usage: VoiceInputUsage;
23
+ basis: VoiceInputBillingBasis;
24
+ };
25
+ /**
26
+ * Same admission shape as knowledge-search and session admission:
27
+ * voice-spendable credits (general plus signup, not model-scoped promotional
28
+ * credits) must be positive, the workspace/member
29
+ * allowance must not be exhausted, and a static monthly cost cap applies.
30
+ * Admission is a read, not a reservation; settlement is post-use and may take
31
+ * an account below zero by at most the concurrent in-flight calls.
32
+ */
33
+ export declare function createVoiceInputBilling(deps: {
34
+ db: Database;
35
+ settings: Settings;
36
+ /** Reconciliation is best-effort at admission; failures are reported here. */
37
+ onReconcileError?: (error: unknown, scope: {
38
+ accountId: string;
39
+ workspaceId: string;
40
+ }) => void;
41
+ /** Minimum spacing of admission-time reconciliation per workspace (default 5 min). */
42
+ reconcileIntervalMilliseconds?: number;
43
+ }): TranscriptionBilling;
44
+ /**
45
+ * Two commits, in order: the `model.cost` usage receipt (Insights spend,
46
+ * monthly cost cap, member-allowance attribution), then the post-use credit
47
+ * debit. The receipt is the first-writer authority for the amount and the
48
+ * durable record of the charge: if the debit commit fails, the receipt stays
49
+ * and {@link reconcileUnsettledVoiceInputCharges} applies the same debit (same
50
+ * idempotency key) on the workspace's next admission. A retried unit settles
51
+ * exactly once at the originally recorded price.
52
+ */
53
+ export declare function settleVoiceInputUsage(db: Database, input: {
54
+ accountId: string;
55
+ workspaceId: string;
56
+ providerId: string;
57
+ model: string;
58
+ billing: TranscriptionBillingContext;
59
+ usage: VoiceInputUsage;
60
+ basis: VoiceInputBillingBasis;
61
+ providerCostMicros: number;
62
+ creditCostMicros: number;
63
+ }): Promise<{
64
+ creditCostMicros: number;
65
+ }>;
66
+ /**
67
+ * Apply the debit for every voice usage receipt in this workspace whose debit
68
+ * never committed. Idempotent with the inline settlement (same key), bounded
69
+ * per call, and safe to run concurrently.
70
+ */
71
+ export declare function reconcileUnsettledVoiceInputCharges(db: Database, input: {
72
+ accountId: string;
73
+ workspaceId: string;
74
+ minAgeMilliseconds?: number;
75
+ }): Promise<{
76
+ reconciled: number;
77
+ }>;
@@ -0,0 +1,51 @@
1
+ import { type Settings } from "@opengeni/config";
2
+ import { type Database } from "@opengeni/db";
3
+ /** Credit ledger type and usage source for deployment-funded web search calls. */
4
+ export declare const WEB_SEARCH_DEBIT_TYPE = "web_search_debit";
5
+ export declare const WEB_SEARCH_SOURCE_TYPE = "web_search";
6
+ /** Same rule as other deployment-funded resources: Stripe or managed limits. */
7
+ export { webSearchCreditBillingActive } from "@opengeni/config";
8
+ /** Exact attempt that called the tool. Every charge is attributed to its turn. */
9
+ export type WebSearchCallScope = {
10
+ accountId: string;
11
+ workspaceId: string;
12
+ sessionId: string;
13
+ turnId: string;
14
+ attemptId: string;
15
+ };
16
+ export type WebSearchCallCost = {
17
+ /** Model tool-call or Codemode operation identity, unique within the attempt. */
18
+ operationId: string;
19
+ operation: "search" | "fetch";
20
+ provider: string;
21
+ providerMicros: number;
22
+ creditMicros: number;
23
+ marginBps: number;
24
+ basis: "provider_reported" | "configured_price" | "list_price";
25
+ };
26
+ export declare class WebSearchBillingRefusedError extends Error {
27
+ readonly code: "insufficient_credits" | "allowance_exhausted" | "credits_disabled";
28
+ constructor(code: "insufficient_credits" | "allowance_exhausted" | "credits_disabled", message: string);
29
+ }
30
+ /** Model-facing refusal when the workspace turned Opengeni credits off. */
31
+ export declare const WEB_SEARCH_CREDITS_DISABLED_MESSAGE = "Web search uses Opengeni credits, which are turned off in this workspace.";
32
+ /**
33
+ * Admission and post-use settlement for paid web search, matching paid
34
+ * Knowledge queries and voice input: admission reads the workspace credit
35
+ * switch, general credits and the workspace/member allowance (a read, not a
36
+ * reservation); settlement records a durable usage receipt and the idempotent
37
+ * debit in one transaction. Calls that cost nothing (free providers, or
38
+ * billing inactive) are never refused. A workspace that turned Opengeni
39
+ * credits off is refused paid calls, and settlement skips the debit (and the
40
+ * cost receipt) for a call that was in flight when the switch turned off or
41
+ * that was admitted as free but reported a provider cost.
42
+ */
43
+ export declare function createWebSearchBilling(deps: {
44
+ db: Database;
45
+ settings: Settings;
46
+ }): {
47
+ active: boolean;
48
+ admit(scope: WebSearchCallScope, expectedProviderMicros: number): Promise<void>;
49
+ settle(scope: WebSearchCallScope, cost: WebSearchCallCost): Promise<void>;
50
+ };
51
+ export type WebSearchBilling = ReturnType<typeof createWebSearchBilling>;
@@ -0,0 +1,7 @@
1
+ import { type Database } from "@opengeni/db";
2
+ /**
3
+ * True when the workspace turned Opengeni credits off. Every meter that would
4
+ * spend credits (credit-billed models, voice, web search, knowledge
5
+ * embeddings) honors this one switch.
6
+ */
7
+ export declare function workspaceCreditsDisabled(db: Database, workspaceId: string): Promise<boolean>;