@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.
- package/README.md +4 -4
- package/dist/access/index.d.ts +131 -7
- package/dist/access/service-initiator.d.ts +3 -0
- package/dist/application/archived-session-imports.d.ts +6 -0
- package/dist/application/composer-submit.d.ts +1 -1
- package/dist/application/connect-operation.d.ts +6 -0
- package/dist/application/external-workspace-members.d.ts +13 -1
- package/dist/application/modal-native-live-declaration-join.d.ts +37 -0
- package/dist/application/modal-native-original-configuration.d.ts +79 -0
- package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
- package/dist/application/new-session-drafts.d.ts +29 -2
- package/dist/application/organization-privacy.d.ts +57 -0
- package/dist/application/prepared-mcp-connection.d.ts +31 -0
- package/dist/application/sandbox-recovery.d.ts +58 -0
- package/dist/application/session-commands.d.ts +3 -0
- package/dist/application/session-tenancy.d.ts +13 -4
- package/dist/billing/agent-run-admission.d.ts +21 -0
- package/dist/billing/limits.d.ts +27 -1
- package/dist/billing/model-call-admission.d.ts +34 -0
- package/dist/billing/model-usage-settlement.d.ts +112 -0
- package/dist/canonical-human-identities.js +1 -1
- package/dist/{chunk-VCZFFEPB.js → chunk-7T2SZ7BI.js} +16 -2
- package/dist/chunk-7T2SZ7BI.js.map +1 -0
- package/dist/{chunk-ZYCNLYGH.js → chunk-OMJFIIWK.js} +178 -12
- package/dist/chunk-OMJFIIWK.js.map +1 -0
- package/dist/{chunk-H7X52RI2.js → chunk-QI2M2B2K.js} +83 -8
- package/dist/chunk-QI2M2B2K.js.map +1 -0
- package/dist/{chunk-OF65T3PM.js → chunk-TTWTXQB2.js} +94 -6
- package/dist/chunk-TTWTXQB2.js.map +1 -0
- package/dist/codex-model-availability.d.ts +55 -0
- package/dist/default-session-model.d.ts +192 -0
- package/dist/dependencies.d.ts +41 -7
- package/dist/developer-setup-credential-ceiling.d.ts +10 -0
- package/dist/domain/agent-config-resolution.d.ts +49 -0
- package/dist/domain/automations.d.ts +8 -1
- package/dist/domain/capabilities.d.ts +112 -8
- package/dist/domain/connection-account-selection-error.d.ts +8 -0
- package/dist/domain/connector-tool-permissions.d.ts +62 -0
- package/dist/domain/direct-model-provider.d.ts +3 -0
- package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
- package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
- package/dist/domain/editable-artifacts/ports.d.ts +10 -0
- package/dist/domain/editable-artifacts/service.d.ts +3 -1
- package/dist/domain/editable-artifacts/types.d.ts +1 -1
- package/dist/domain/encryption-key.d.ts +12 -0
- package/dist/domain/insights-timing.d.ts +16 -0
- package/dist/domain/insights-usage.d.ts +27 -0
- package/dist/domain/insights.d.ts +21 -3
- package/dist/domain/knowledge-files.d.ts +1 -1
- package/dist/domain/knowledge-preparation.d.ts +10 -0
- package/dist/domain/knowledge-preparation.test.d.ts +1 -0
- package/dist/domain/knowledge-search.d.ts +15 -76
- package/dist/domain/mcp-account-bindings.d.ts +17 -0
- package/dist/domain/mcp-account-routes.d.ts +21 -0
- package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
- package/dist/domain/organization-integration-catalog.d.ts +15 -0
- package/dist/domain/personal-connection-delegations.d.ts +73 -12
- package/dist/domain/pr-review.d.ts +121 -6
- package/dist/domain/realtime-voice-billing.d.ts +103 -0
- package/dist/domain/resources.d.ts +17 -1
- package/dist/domain/scheduled-task-access.d.ts +265 -0
- package/dist/domain/scheduled-task-account-audit.d.ts +27 -0
- package/dist/domain/scheduled-task-audience.d.ts +70 -0
- package/dist/domain/scheduled-tasks.d.ts +61 -18
- package/dist/domain/session-connection-accounts.d.ts +53 -0
- package/dist/domain/session-file-access.d.ts +4 -0
- package/dist/domain/session-native-connection-replacement.d.ts +14 -0
- package/dist/domain/session-start-timing.d.ts +7 -0
- package/dist/domain/session-tool-policy.d.ts +102 -4
- package/dist/domain/sessions.d.ts +179 -15
- package/dist/domain/site-audience.d.ts +52 -0
- package/dist/domain/skills.d.ts +29 -1
- package/dist/domain/slack-bot.d.ts +46 -1
- package/dist/domain/slack-publication-secret-safety.d.ts +1 -1
- package/dist/domain/vaults/index.d.ts +7 -0
- package/dist/domain/vaults/mapping.d.ts +25 -0
- package/dist/domain/vaults/provider-registry.d.ts +72 -0
- package/dist/domain/vaults/provider-sync.d.ts +176 -0
- package/dist/domain/vaults/provider-writes.d.ts +57 -0
- package/dist/domain/vaults/secret-resolver.d.ts +34 -0
- package/dist/domain/vaults/types.d.ts +24 -0
- package/dist/domain/vaults/vault-service.d.ts +35 -0
- package/dist/domain/voice-input-billing.d.ts +77 -0
- package/dist/domain/web-search-billing.d.ts +51 -0
- package/dist/domain/workspace-credits.d.ts +7 -0
- package/dist/editable-artifact-live/application.d.ts +2 -1
- package/dist/editable-artifact-live/server.d.ts +5 -1
- package/dist/editable-artifact-live/ticket.d.ts +2 -1
- package/dist/editable-artifact-live/types.d.ts +9 -0
- package/dist/editable-artifact-live.js +2 -2
- package/dist/editable-artifacts.js +10 -2
- package/dist/goal-admission.d.ts +627 -0
- package/dist/host-session-usage-limit.d.ts +15 -0
- package/dist/index.d.ts +43 -8
- package/dist/index.js +22682 -11743
- package/dist/index.js.map +1 -1
- package/dist/managed-session.d.ts +110 -7
- package/dist/model-call.d.ts +58 -0
- package/dist/model-catalog.d.ts +29 -3
- package/dist/model-provider-credentials.d.ts +43 -0
- package/dist/product-usage-metrics.d.ts +30 -0
- package/dist/rigs/index.d.ts +1 -13
- package/dist/sandbox/fleet.d.ts +58 -4
- package/dist/sandbox/routing.d.ts +42 -2
- package/dist/sandbox/runtime-settings.d.ts +27 -17
- package/dist/session-authorization.d.ts +10 -0
- package/dist/session-usage-limit-metrics.d.ts +60 -0
- package/dist/session-usage-limits.d.ts +89 -0
- package/dist/site-agent-clamp.d.ts +71 -0
- package/dist/site-session-origin.d.ts +39 -2
- package/dist/transcription.d.ts +120 -3
- package/dist/turn-surface.d.ts +20 -0
- package/dist/user-presence.d.ts +32 -0
- package/dist/workflow-wake-contract.d.ts +13 -1
- package/package.json +15 -22
- package/src/access/index.ts +961 -38
- package/src/access/service-initiator.ts +50 -0
- package/src/application/api-integration-servers.ts +9 -0
- package/src/application/archived-session-imports.ts +161 -0
- package/src/application/composer-submit.ts +3 -2
- package/src/application/connect-authority.ts +3 -3
- package/src/application/connect-operation.ts +37 -3
- package/src/application/external-continuation.ts +20 -3
- package/src/application/external-link-work-admission.ts +3 -0
- package/src/application/external-workspace-members.ts +51 -3
- package/src/application/modal-native-live-declaration-join.ts +196 -0
- package/src/application/modal-native-original-configuration.ts +261 -0
- package/src/application/modal-native-worker-host-transport.ts +263 -0
- package/src/application/new-session-drafts.ts +172 -55
- package/src/application/organization-privacy.ts +161 -0
- package/src/application/prepared-mcp-connection.ts +133 -0
- package/src/application/sandbox-recovery.ts +78 -0
- package/src/application/session-commands.ts +73 -1
- package/src/application/session-mcp-credential-rotation.ts +61 -18
- package/src/application/session-tenancy.ts +262 -44
- package/src/application/user-resource-grants.ts +1 -29
- package/src/billing/agent-run-admission.ts +117 -0
- package/src/billing/limits.ts +138 -14
- package/src/billing/model-call-admission.ts +118 -0
- package/src/billing/model-usage-settlement.ts +472 -0
- package/src/codex-model-availability.ts +264 -0
- package/src/default-session-model.ts +692 -0
- package/src/dependencies.ts +48 -6
- package/src/developer-setup-credential-ceiling.ts +60 -0
- package/src/domain/agent-config-resolution.ts +148 -0
- package/src/domain/automations.ts +76 -2
- package/src/domain/capabilities.ts +830 -181
- package/src/domain/connection-account-selection-error.ts +19 -0
- package/src/domain/connector-tool-permissions.ts +572 -0
- package/src/domain/direct-model-provider.ts +62 -0
- package/src/domain/editable-artifacts/agent-application.ts +44 -6
- package/src/domain/editable-artifacts/durable-export.ts +100 -5
- package/src/domain/editable-artifacts/in-memory.ts +6 -0
- package/src/domain/editable-artifacts/ports.ts +11 -0
- package/src/domain/editable-artifacts/service.ts +20 -0
- package/src/domain/editable-artifacts/types.ts +1 -1
- package/src/domain/encryption-key.ts +26 -0
- package/src/domain/file-owner.ts +16 -1
- package/src/domain/github-action-policies.ts +1 -1
- package/src/domain/github-skill-source.ts +3 -1
- package/src/domain/insights-timing.ts +95 -0
- package/src/domain/insights-usage.ts +67 -0
- package/src/domain/insights.ts +167 -43
- package/src/domain/knowledge-files.ts +10 -3
- package/src/domain/knowledge-messages.ts +1 -0
- package/src/domain/knowledge-preparation.test.ts +276 -0
- package/src/domain/knowledge-preparation.ts +147 -0
- package/src/domain/knowledge-search.test.ts +617 -5
- package/src/domain/knowledge-search.ts +240 -23
- package/src/domain/mcp-account-bindings.ts +169 -0
- package/src/domain/mcp-account-routes.ts +152 -0
- package/src/domain/native-mcp-connection-admission.ts +14 -0
- package/src/domain/organization-integration-catalog.ts +88 -0
- package/src/domain/personal-connection-delegations.ts +399 -257
- package/src/domain/pr-review.ts +24 -8
- package/src/domain/realtime-voice-billing.ts +425 -0
- package/src/domain/resources.ts +50 -4
- package/src/domain/scheduled-task-access.ts +1089 -0
- package/src/domain/scheduled-task-account-audit.ts +90 -0
- package/src/domain/scheduled-task-audience.ts +249 -0
- package/src/domain/scheduled-tasks.ts +1313 -374
- package/src/domain/session-connection-accounts.ts +239 -0
- package/src/domain/session-file-access.ts +47 -0
- package/src/domain/session-native-connection-replacement.ts +64 -0
- package/src/domain/session-start-timing.ts +60 -0
- package/src/domain/session-tool-policy.ts +489 -14
- package/src/domain/sessions.ts +2254 -717
- package/src/domain/site-audience.ts +130 -0
- package/src/domain/skills.ts +9 -0
- package/src/domain/slack-bot.ts +141 -4
- package/src/domain/slack-publication-secret-safety.ts +1 -1
- package/src/domain/vaults/index.ts +19 -0
- package/src/domain/vaults/mapping.ts +190 -0
- package/src/domain/vaults/provider-registry.ts +201 -0
- package/src/domain/vaults/provider-sync.ts +531 -0
- package/src/domain/vaults/provider-writes.ts +288 -0
- package/src/domain/vaults/secret-resolver.ts +464 -0
- package/src/domain/vaults/types.ts +26 -0
- package/src/domain/vaults/vault-service.ts +1316 -0
- package/src/domain/voice-input-billing.ts +330 -0
- package/src/domain/web-search-billing.ts +169 -0
- package/src/domain/workspace-credits.ts +13 -0
- package/src/editable-artifact-live/application.ts +8 -1
- package/src/editable-artifact-live/server.ts +154 -6
- package/src/editable-artifact-live/ticket.ts +86 -1
- package/src/editable-artifact-live/types.ts +10 -0
- package/src/goal-admission.ts +220 -0
- package/src/host-session-usage-limit.ts +25 -0
- package/src/index.ts +75 -11
- package/src/managed-session.ts +137 -6
- package/src/model-call.ts +79 -0
- package/src/model-catalog.ts +345 -91
- package/src/model-provider-credentials.ts +394 -0
- package/src/product-usage-metrics.ts +101 -0
- package/src/rigs/index.ts +23 -111
- package/src/sandbox/fleet.ts +253 -28
- package/src/sandbox/routing.ts +204 -43
- package/src/sandbox/runtime-settings.ts +159 -85
- package/src/session-authorization.ts +172 -23
- package/src/session-usage-limit-metrics.ts +95 -0
- package/src/session-usage-limits.ts +415 -0
- package/src/site-agent-clamp.ts +226 -0
- package/src/site-session-origin.ts +84 -5
- package/src/transcription.ts +123 -4
- package/src/turn-surface.ts +47 -0
- package/src/user-presence.ts +134 -0
- package/src/workflow-wake-contract.ts +14 -1
- package/dist/application/host-mcp-owner.d.ts +0 -6
- package/dist/application/host-mcp-resolvers.d.ts +0 -13
- package/dist/chunk-5WZYFL45.js +0 -266
- package/dist/chunk-5WZYFL45.js.map +0 -1
- package/dist/chunk-H7X52RI2.js.map +0 -1
- package/dist/chunk-OF65T3PM.js.map +0 -1
- package/dist/chunk-VCZFFEPB.js.map +0 -1
- package/dist/chunk-ZYCNLYGH.js.map +0 -1
- package/dist/domain/connection-authority.d.ts +0 -97
- package/dist/domain/connection-authority.js +0 -169
- package/dist/domain/connection-authority.js.map +0 -1
- package/dist/domain/environments.d.ts +0 -33
- package/dist/domain/host-mcp-authority-source-admission.d.ts +0 -10
- package/dist/domain/host-mcp-task-admission.d.ts +0 -18
- package/dist/domain/packs.d.ts +0 -59
- package/dist/domain/product-integration-pack.d.ts +0 -44
- package/dist/domain/product-integration-skill.gen.d.ts +0 -5
- package/dist/remote-mcp-credentials.d.ts +0 -23
- package/dist/remote-mcp-credentials.js +0 -11
- package/dist/remote-mcp-credentials.js.map +0 -1
- package/src/application/host-mcp-owner.ts +0 -41
- package/src/application/host-mcp-resolvers.ts +0 -84
- package/src/domain/connection-authority.ts +0 -329
- package/src/domain/environments.ts +0 -120
- package/src/domain/host-mcp-authority-source-admission.ts +0 -25
- package/src/domain/host-mcp-task-admission.ts +0 -121
- package/src/domain/packs.ts +0 -699
- package/src/domain/product-integration-pack.ts +0 -42
- package/src/domain/product-integration-skill.gen.ts +0 -52
- 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
|
|
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>;
|