@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
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generatePassword,
|
|
3
|
+
isValidTotpInput,
|
|
4
|
+
secretNameKey,
|
|
5
|
+
type VaultFieldInput,
|
|
6
|
+
type VaultFieldKind,
|
|
7
|
+
type VaultItemType,
|
|
8
|
+
} from "@opengeni/contracts";
|
|
9
|
+
import {
|
|
10
|
+
getProviderVaultItemRef,
|
|
11
|
+
VaultError,
|
|
12
|
+
type Database,
|
|
13
|
+
type VaultDbContext,
|
|
14
|
+
type VaultFieldRow,
|
|
15
|
+
type VaultRow,
|
|
16
|
+
} from "@opengeni/db";
|
|
17
|
+
import {
|
|
18
|
+
isVaultProviderError,
|
|
19
|
+
type ProviderCallBudget,
|
|
20
|
+
type ProviderWriteField,
|
|
21
|
+
type VaultProvider,
|
|
22
|
+
type VaultProviderRegistry,
|
|
23
|
+
} from "@opengeni/vaults";
|
|
24
|
+
import { vaultErrorCodeForProvider } from "./provider-registry";
|
|
25
|
+
import { syncLinkedProviderVault } from "./provider-sync";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Edits of items in a read-write connected vault (OP-3): the change is written
|
|
29
|
+
* to the provider (1Password `items.get` → patch → `items.put`, with the
|
|
30
|
+
* mirrored version as the expected version), then the metadata mirror is
|
|
31
|
+
* refreshed. Values never touch Opengeni storage.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/** One field change; the REST `VaultFieldInput` and the agent `secret_save` field both fit. */
|
|
35
|
+
export interface ProviderFieldChange {
|
|
36
|
+
fieldId?: string | undefined;
|
|
37
|
+
name: string;
|
|
38
|
+
kind?: VaultFieldKind | undefined;
|
|
39
|
+
value?: string | undefined;
|
|
40
|
+
generate?: VaultFieldInput["generate"] | undefined;
|
|
41
|
+
fromReference?: string | undefined;
|
|
42
|
+
fileBase64?: string | undefined;
|
|
43
|
+
restoreVersion?: number | undefined;
|
|
44
|
+
remove?: true | undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ProviderItemChange {
|
|
48
|
+
name?: string | undefined;
|
|
49
|
+
type?: VaultItemType | undefined;
|
|
50
|
+
websites?: string[] | undefined;
|
|
51
|
+
fields?: readonly ProviderFieldChange[] | undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ProviderWriteDeps {
|
|
55
|
+
db: Database;
|
|
56
|
+
context: VaultDbContext;
|
|
57
|
+
providers: VaultProviderRegistry;
|
|
58
|
+
/** Resolves `fromReference` field inputs (audited as a use by the caller). */
|
|
59
|
+
resolveReference: (raw: string) => Promise<string>;
|
|
60
|
+
budget?: ProviderCallBudget;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const TEXT_FIELD_NAMES = ["username", "user", "email", "login", "account"];
|
|
64
|
+
|
|
65
|
+
function defaultKind(name: string): VaultFieldKind {
|
|
66
|
+
return TEXT_FIELD_NAMES.includes(secretNameKey(name)) ? "text" : "concealed";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A connected vault the caller may change items in. */
|
|
70
|
+
export function assertProviderVaultWritable(vault: VaultRow): void {
|
|
71
|
+
if (vault.source === "opengeni") {
|
|
72
|
+
throw new VaultError("vault_permission_denied", "not a connected vault");
|
|
73
|
+
}
|
|
74
|
+
if (vault.mode !== "read_write") {
|
|
75
|
+
throw new VaultError("vault_read_only", "vault is read-only", { vaultId: vault.id });
|
|
76
|
+
}
|
|
77
|
+
if (vault.ownerKind === "user" && !vault.ownedByCaller) {
|
|
78
|
+
throw new VaultError("vault_not_found", "vault not found", { vaultId: vault.id });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function providerFieldWrites(
|
|
83
|
+
fields: readonly ProviderFieldChange[],
|
|
84
|
+
existing: readonly VaultFieldRow[],
|
|
85
|
+
resolveReference: (raw: string) => Promise<string>,
|
|
86
|
+
generated: string[],
|
|
87
|
+
): Promise<ProviderWriteField[]> {
|
|
88
|
+
const writes: ProviderWriteField[] = [];
|
|
89
|
+
for (const input of fields) {
|
|
90
|
+
const current = existing.find(
|
|
91
|
+
(field) =>
|
|
92
|
+
(input.fieldId !== undefined && field.id === input.fieldId) ||
|
|
93
|
+
secretNameKey(field.name) === secretNameKey(input.name),
|
|
94
|
+
);
|
|
95
|
+
const kind: VaultFieldKind = input.kind ?? current?.kind ?? defaultKind(input.name);
|
|
96
|
+
const base: ProviderWriteField = {
|
|
97
|
+
...(current?.providerFieldRef ? { externalFieldId: current.providerFieldRef } : {}),
|
|
98
|
+
name: input.name,
|
|
99
|
+
kind,
|
|
100
|
+
};
|
|
101
|
+
if (input.remove) {
|
|
102
|
+
writes.push({ ...base, remove: true });
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (input.restoreVersion !== undefined) {
|
|
106
|
+
throw new VaultError(
|
|
107
|
+
"provider_unavailable",
|
|
108
|
+
"connected vaults keep their history in the provider; restore it there",
|
|
109
|
+
{ field: input.name },
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
if (input.fileBase64 !== undefined || kind === "file") {
|
|
113
|
+
throw new VaultError(
|
|
114
|
+
"provider_unavailable",
|
|
115
|
+
"files in connected vaults are read-only in Opengeni",
|
|
116
|
+
{ field: input.name },
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
let value: string;
|
|
120
|
+
if (input.generate !== undefined) {
|
|
121
|
+
value = generatePassword(input.generate);
|
|
122
|
+
generated.push(input.name);
|
|
123
|
+
} else if (input.fromReference !== undefined)
|
|
124
|
+
value = await resolveReference(input.fromReference);
|
|
125
|
+
else value = input.value ?? "";
|
|
126
|
+
if (kind === "totp") {
|
|
127
|
+
if (!isValidTotpInput(value)) {
|
|
128
|
+
throw new VaultError(
|
|
129
|
+
"invalid_secret_name",
|
|
130
|
+
`${input.name} is not a valid two-factor setup key or otpauth:// link`,
|
|
131
|
+
{ field: input.name },
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
value = value.trim();
|
|
135
|
+
}
|
|
136
|
+
writes.push({ ...base, value });
|
|
137
|
+
}
|
|
138
|
+
return writes;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function providerFailure(error: unknown): never {
|
|
142
|
+
if (isVaultProviderError(error)) {
|
|
143
|
+
throw new VaultError(vaultErrorCodeForProvider(error.code, "write"), error.message, {
|
|
144
|
+
...(error.retryAfterMs ? { retryAfterMs: error.retryAfterMs } : {}),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function providerFor(deps: ProviderWriteDeps, vault: VaultRow): Promise<VaultProvider> {
|
|
151
|
+
try {
|
|
152
|
+
return await deps.providers.forVault({
|
|
153
|
+
source: vault.source,
|
|
154
|
+
providerConnectionId: vault.providerConnectionId,
|
|
155
|
+
});
|
|
156
|
+
} catch (error) {
|
|
157
|
+
return providerFailure(error);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function refreshAndFind(
|
|
162
|
+
deps: ProviderWriteDeps,
|
|
163
|
+
vault: VaultRow,
|
|
164
|
+
providerItemRef: string,
|
|
165
|
+
): Promise<string> {
|
|
166
|
+
await syncLinkedProviderVault({
|
|
167
|
+
db: deps.db,
|
|
168
|
+
context: deps.context,
|
|
169
|
+
vaultId: vault.id,
|
|
170
|
+
providers: deps.providers,
|
|
171
|
+
force: true,
|
|
172
|
+
...(deps.budget ? { budget: deps.budget } : {}),
|
|
173
|
+
});
|
|
174
|
+
try {
|
|
175
|
+
const ref = await getProviderVaultItemRef(deps.db, deps.context, {
|
|
176
|
+
vaultId: vault.id,
|
|
177
|
+
providerItemRef,
|
|
178
|
+
});
|
|
179
|
+
return ref.itemId;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if (error instanceof VaultError && error.code === "vault_item_not_found") {
|
|
182
|
+
throw new VaultError(
|
|
183
|
+
"provider_unavailable",
|
|
184
|
+
"saved in the provider; Opengeni will show it after the next sync",
|
|
185
|
+
{ vaultId: vault.id },
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Create (existing = null) or update an item in a connected read-write vault; returns its item id. */
|
|
193
|
+
export async function writeProviderVaultItem(
|
|
194
|
+
deps: ProviderWriteDeps,
|
|
195
|
+
input: {
|
|
196
|
+
vault: VaultRow;
|
|
197
|
+
existing: {
|
|
198
|
+
itemId: string;
|
|
199
|
+
name: string;
|
|
200
|
+
type: VaultItemType;
|
|
201
|
+
websites: string[];
|
|
202
|
+
fields: VaultFieldRow[];
|
|
203
|
+
expectedGeneration?: number | undefined;
|
|
204
|
+
} | null;
|
|
205
|
+
change: ProviderItemChange;
|
|
206
|
+
/** Receives the names of fields whose values were generated. */
|
|
207
|
+
generated?: string[];
|
|
208
|
+
},
|
|
209
|
+
): Promise<string> {
|
|
210
|
+
const { vault, existing, change } = input;
|
|
211
|
+
assertProviderVaultWritable(vault);
|
|
212
|
+
if ((change.type ?? existing?.type) === "passkey") {
|
|
213
|
+
throw new VaultError("vault_permission_denied", "passkeys live only in Opengeni vaults");
|
|
214
|
+
}
|
|
215
|
+
let externalItemId: string | undefined;
|
|
216
|
+
let expectedVersion: string | null | undefined;
|
|
217
|
+
if (existing) {
|
|
218
|
+
const ref = await getProviderVaultItemRef(deps.db, deps.context, {
|
|
219
|
+
vaultId: vault.id,
|
|
220
|
+
itemId: existing.itemId,
|
|
221
|
+
});
|
|
222
|
+
if (
|
|
223
|
+
existing.expectedGeneration !== undefined &&
|
|
224
|
+
existing.expectedGeneration !== ref.generation
|
|
225
|
+
) {
|
|
226
|
+
throw new VaultError("vault_generation_conflict", "the item changed; reload and retry", {
|
|
227
|
+
itemId: existing.itemId,
|
|
228
|
+
generation: ref.generation,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
externalItemId = ref.providerItemRef;
|
|
232
|
+
expectedVersion = ref.providerVersion;
|
|
233
|
+
}
|
|
234
|
+
const fields = await providerFieldWrites(
|
|
235
|
+
change.fields ?? [],
|
|
236
|
+
existing?.fields ?? [],
|
|
237
|
+
deps.resolveReference,
|
|
238
|
+
input.generated ?? [],
|
|
239
|
+
);
|
|
240
|
+
const provider = await providerFor(deps, vault);
|
|
241
|
+
let written;
|
|
242
|
+
try {
|
|
243
|
+
written = await provider.writeItem(
|
|
244
|
+
{ connectionId: vault.providerConnectionId, budget: deps.budget ?? { take() {} } },
|
|
245
|
+
vault.providerVaultRef ?? "",
|
|
246
|
+
{
|
|
247
|
+
...(externalItemId ? { externalItemId, expectedVersion: expectedVersion ?? null } : {}),
|
|
248
|
+
name: change.name ?? existing?.name ?? "",
|
|
249
|
+
type: change.type ?? existing?.type ?? "login",
|
|
250
|
+
websites: change.websites ?? existing?.websites ?? [],
|
|
251
|
+
fields,
|
|
252
|
+
},
|
|
253
|
+
);
|
|
254
|
+
} catch (error) {
|
|
255
|
+
return providerFailure(error);
|
|
256
|
+
}
|
|
257
|
+
return await refreshAndFind(deps, vault, written.externalItemId);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Archive an item in a connected read-write vault (the provider keeps it recoverable). */
|
|
261
|
+
export async function archiveProviderVaultItem(
|
|
262
|
+
deps: ProviderWriteDeps,
|
|
263
|
+
input: { vault: VaultRow; itemId: string },
|
|
264
|
+
): Promise<void> {
|
|
265
|
+
assertProviderVaultWritable(input.vault);
|
|
266
|
+
const ref = await getProviderVaultItemRef(deps.db, deps.context, {
|
|
267
|
+
vaultId: input.vault.id,
|
|
268
|
+
itemId: input.itemId,
|
|
269
|
+
});
|
|
270
|
+
const provider = await providerFor(deps, input.vault);
|
|
271
|
+
try {
|
|
272
|
+
await provider.archiveItem(
|
|
273
|
+
{ connectionId: input.vault.providerConnectionId, budget: deps.budget ?? { take() {} } },
|
|
274
|
+
input.vault.providerVaultRef ?? "",
|
|
275
|
+
ref.providerItemRef,
|
|
276
|
+
);
|
|
277
|
+
} catch (error) {
|
|
278
|
+
providerFailure(error);
|
|
279
|
+
}
|
|
280
|
+
await syncLinkedProviderVault({
|
|
281
|
+
db: deps.db,
|
|
282
|
+
context: deps.context,
|
|
283
|
+
vaultId: input.vault.id,
|
|
284
|
+
providers: deps.providers,
|
|
285
|
+
force: true,
|
|
286
|
+
...(deps.budget ? { budget: deps.budget } : {}),
|
|
287
|
+
});
|
|
288
|
+
}
|