@opengeni/vaults 3.1.3-canary.38890816741001 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/{chunk-7S23LHTK.js → chunk-BD43JBPC.js} +9 -2
- package/dist/chunk-BD43JBPC.js.map +1 -0
- package/dist/{chunk-VKPGG2FW.js → chunk-BEKN77JO.js} +2 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +736 -2
- package/dist/index.js.map +1 -1
- package/dist/provider-capabilities.d.ts +4 -0
- package/dist/provider-pages.d.ts +56 -0
- package/dist/provider.d.ts +59 -3
- package/dist/remote-provider.d.ts +117 -0
- package/dist/testing/fake-provider.js +2 -2
- package/dist/testing/index.js +2 -2
- package/package.json +2 -2
- package/src/index.ts +3 -0
- package/src/provider-capabilities.ts +64 -0
- package/src/provider-pages.ts +206 -0
- package/src/provider.ts +84 -2
- package/src/remote-provider.ts +784 -0
- package/dist/chunk-7S23LHTK.js.map +0 -1
- /package/dist/{chunk-VKPGG2FW.js.map → chunk-BEKN77JO.js.map} +0 -0
package/README.md
CHANGED
|
@@ -12,6 +12,12 @@ This package owns:
|
|
|
12
12
|
and the in-memory fake), plus `VaultProviderError` and its codes;
|
|
13
13
|
- `createVaultProviderRegistry`, which picks the provider for a vault;
|
|
14
14
|
- `createProviderCallBudget`, the per-attempt provider call budget;
|
|
15
|
+
- `createRemoteVaultProvider`, the adapter for vaults served over Opengeni's
|
|
16
|
+
signed remote protocol (`opengeni.vault.v1`): an embedder's receiver built
|
|
17
|
+
with `@opengeni/sdk/external-vault-receiver`, or the customer-run
|
|
18
|
+
`@opengeni/vaults-bitwarden-bridge`. The caller supplies the bounded HTTP
|
|
19
|
+
transport (`createFetchRemoteVaultTransport` adapts a pinned fetch) and the
|
|
20
|
+
trusted `ctx.authority`;
|
|
15
21
|
- the shell splice contract (`spliceShellCommand`, `dialectFromShell`) used
|
|
16
22
|
by `exec_command` and `run_on` to turn references into per-command
|
|
17
23
|
environment variables;
|
|
@@ -20,3 +26,11 @@ This package owns:
|
|
|
20
26
|
|
|
21
27
|
Providers never see principals: access is decided before a provider is called.
|
|
22
28
|
Provider errors always map to a `VaultProviderErrorCode`; nothing is swallowed.
|
|
29
|
+
|
|
30
|
+
Listings are read with `listProviderVaults` and `listProviderItems` (bounded
|
|
31
|
+
enumeration for discovery), or with `readProviderVaultInventory` and
|
|
32
|
+
`readProviderItemInventory`, which also report whether the listing is
|
|
33
|
+
`consistent`: one response, or every page under one snapshot. Only a
|
|
34
|
+
consistent inventory may remove items from a mirror. A multi-page listing
|
|
35
|
+
without a snapshot proves only what it contains, so a vault served without
|
|
36
|
+
snapshots is mirrored only while its listing fits in one page.
|
|
@@ -11,7 +11,10 @@ var VAULT_PROVIDER_ERROR_CODES = [
|
|
|
11
11
|
* write into a 1Password vault the service account can only read). The vault
|
|
12
12
|
* service reports `vault_read_only` for writes, `vault_permission_denied` otherwise.
|
|
13
13
|
*/
|
|
14
|
-
"provider_permission_denied"
|
|
14
|
+
"provider_permission_denied",
|
|
15
|
+
"provider_locked",
|
|
16
|
+
"provider_inventory_incomplete",
|
|
17
|
+
"provider_outcome_unknown"
|
|
15
18
|
];
|
|
16
19
|
var VaultProviderError = class extends Error {
|
|
17
20
|
code;
|
|
@@ -33,6 +36,10 @@ function createVaultProviderRegistry(factories) {
|
|
|
33
36
|
return factories.onepassword(vault.providerConnectionId);
|
|
34
37
|
}
|
|
35
38
|
if (vault.source === "host" && factories.host) return factories.host();
|
|
39
|
+
if (vault.source !== "opengeni" && vault.source !== "host" && vault.source !== "onepassword") {
|
|
40
|
+
const factory = factories[vault.source];
|
|
41
|
+
if (factory) return factory(vault.providerConnectionId);
|
|
42
|
+
}
|
|
36
43
|
throw new VaultProviderError(
|
|
37
44
|
"provider_unavailable",
|
|
38
45
|
vault.source === "opengeni" ? "hosted vaults are read from the database, not a provider" : `no ${vault.source} vault provider is configured`
|
|
@@ -65,4 +72,4 @@ export {
|
|
|
65
72
|
EMPTY_VAULT_PROVIDER_REGISTRY,
|
|
66
73
|
createProviderCallBudget
|
|
67
74
|
};
|
|
68
|
-
//# sourceMappingURL=chunk-
|
|
75
|
+
//# sourceMappingURL=chunk-BD43JBPC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts"],"sourcesContent":["import type {\n ConnectionCredentialsPort,\n SecretMaterial,\n VaultFieldKind,\n VaultItemType,\n VaultSource,\n VaultProviderOperations,\n VaultProviderFreshness,\n} from \"@opengeni/contracts\";\n\nexport interface VaultProviderCapabilities {\n write: boolean;\n createVault: boolean;\n totp: boolean;\n files: boolean;\n groupGrants: boolean;\n /** Passkeys live only in Opengeni-hosted vaults (D20). */\n passkeys: false;\n /** Additive: older in-process providers retain the legacy capability flags. */\n operations?: VaultProviderOperations;\n}\nexport interface ProviderVault {\n externalVaultId: string;\n name: string;\n contentVersion: string | null;\n itemCount: number | null;\n writeAccess?: \"read_only\" | \"read_write\" | \"unknown\";\n operations?: VaultProviderOperations;\n}\nexport interface ProviderFieldMeta {\n externalFieldId: string;\n name: string;\n kind: VaultFieldKind;\n}\nexport interface ProviderItemMeta {\n externalItemId: string;\n name: string;\n type: VaultItemType;\n websites: string[];\n fields: ProviderFieldMeta[];\n version: string | null;\n updatedAt: string | null;\n}\nexport interface ProviderFieldValue {\n externalFieldId: string;\n material: SecretMaterial;\n}\nexport interface ProviderWriteField {\n externalFieldId?: string;\n name: string;\n kind: VaultFieldKind;\n value?: string;\n remove?: true;\n}\nexport interface ProviderWriteItem {\n externalItemId?: string;\n expectedVersion?: string | null;\n name: string;\n type: VaultItemType;\n websites: string[];\n fields: ProviderWriteField[];\n}\nexport type ProviderCallOperation = \"list\" | \"read\" | \"write\" | \"admin\";\nexport interface ProviderCallBudget {\n /** Throws VaultProviderError(\"provider_rate_limited\") when exhausted. */\n take(op: ProviderCallOperation): void;\n}\nexport interface VaultProviderContext {\n connectionId: string | null;\n budget: ProviderCallBudget;\n signal?: AbortSignal;\n /** Trusted native scope, supplied by the authorized registry, never model arguments. */\n authority?: VaultProviderAuthority;\n /** Last successful mirror-check identity; changes invalidate attempt value caches. */\n cacheEpoch?: string | null;\n /** Recheck upstream, without retrying a mutation or bypassing provider throttling. */\n forceRefresh?: boolean;\n /** Stable caller operation identity when available. No automatic replay is implied. */\n idempotencyKey?: string;\n /** Runtime-only observation; never supplied by an agent or persisted with values. */\n onFreshness?: (freshness: VaultProviderFreshness) => void;\n}\n\nexport interface VaultProviderAuthority {\n accountId: string;\n workspaceId: string;\n subjectId: string | null;\n /** Where the encrypted connection is owned, not a replacement for the calling workspace. */\n connectionWorkspaceId: string;\n sessionId?: string;\n turnId?: string;\n attemptId?: string;\n siteId?: string;\n}\n\nexport interface ProviderPageRequest {\n cursor?: string;\n limit: number;\n snapshot?: string;\n}\n\nexport interface ProviderPage<T> {\n items: T[];\n nextCursor: string | null;\n /**\n * Null only when upstream cannot supply snapshot consistency. A single page\n * needs none, but a multi-page listing without a snapshot proves only what\n * it contains: Opengeni lists it for discovery, yet never replaces a mirror\n * from it (that would drop items skipped while the pages were read). Every\n * page of one listing carries the same snapshot.\n */\n snapshot: string | null;\n freshness?: VaultProviderFreshness;\n}\n\nexport interface VaultProvider {\n readonly id: Exclude<VaultSource, \"opengeni\"> | \"fake\";\n capabilities(): VaultProviderCapabilities;\n validate(ctx: VaultProviderContext): Promise<{\n accountName: string | null;\n /** Stable identity, when supplied by the upstream account or bridge. */\n accountId?: string;\n }>;\n /**\n * One complete response, trusted as a consistent inventory. An adapter\n * that pages upstream should implement `listVaultPage`/`listItemPage`, so\n * page consistency is checked, rather than join pages here.\n */\n listVaults(ctx: VaultProviderContext): Promise<ProviderVault[]>;\n listItems(ctx: VaultProviderContext, externalVaultId: string): Promise<ProviderItemMeta[]>;\n listVaultPage?(\n ctx: VaultProviderContext,\n page: ProviderPageRequest,\n ): Promise<ProviderPage<ProviderVault>>;\n listItemPage?(\n ctx: VaultProviderContext,\n externalVaultId: string,\n page: ProviderPageRequest,\n ): Promise<ProviderPage<ProviderItemMeta>>;\n readFields(\n ctx: VaultProviderContext,\n externalVaultId: string,\n externalItemId: string,\n externalFieldIds: readonly string[],\n ): Promise<ProviderFieldValue[]>;\n writeItem(\n ctx: VaultProviderContext,\n externalVaultId: string,\n item: ProviderWriteItem,\n ): Promise<ProviderItemMeta>;\n archiveItem(\n ctx: VaultProviderContext,\n externalVaultId: string,\n externalItemId: string,\n ): Promise<void>;\n createVault?(\n ctx: VaultProviderContext,\n input: { name: string; description?: string; allowAdminsAccess: boolean; groupId?: string },\n ): Promise<ProviderVault>;\n}\n\nexport const VAULT_PROVIDER_ERROR_CODES = [\n \"provider_auth_invalid\",\n \"provider_auth_expired\",\n \"provider_rate_limited\",\n \"provider_unavailable\",\n \"provider_conflict\",\n \"provider_not_found\",\n /**\n * The provider refused the operation for this credential (for example a\n * write into a 1Password vault the service account can only read). The vault\n * service reports `vault_read_only` for writes, `vault_permission_denied` otherwise.\n */\n \"provider_permission_denied\",\n \"provider_locked\",\n \"provider_inventory_incomplete\",\n \"provider_outcome_unknown\",\n] as const;\nexport type VaultProviderErrorCode = (typeof VAULT_PROVIDER_ERROR_CODES)[number];\n\nexport class VaultProviderError extends Error {\n readonly code: VaultProviderErrorCode;\n readonly retryAfterMs: number | undefined;\n constructor(code: VaultProviderErrorCode, message: string, retryAfterMs?: number) {\n super(message);\n this.name = \"VaultProviderError\";\n this.code = code;\n this.retryAfterMs = retryAfterMs;\n }\n}\n\nexport function isVaultProviderError(error: unknown): error is VaultProviderError {\n return error instanceof VaultProviderError;\n}\n\n/**\n * The embedder's connection-credential port with its password-manager leg\n * (design §10.9, OP-6). `@opengeni/contracts` cannot name `VaultProvider`\n * (this package depends on it), so the leg is added here; core and worker\n * dependencies use this type. A host provider is linked as a vault with\n * `source: \"host\"` and resolved through `createVaultProviderRegistry({ host })`.\n */\nexport type VaultConnectionCredentialsPort = ConnectionCredentialsPort & {\n vaultProvider?: VaultProvider | null;\n};\n\nexport interface VaultProviderRegistry {\n /** onepassword: loads the connection credential and the SDK lazily; host: the embedder port; fake: tests/dev. */\n forVault(vault: {\n source: VaultSource;\n providerConnectionId: string | null;\n }): Promise<VaultProvider>;\n}\n\n/**\n * A registry over fixed provider factories. Missing providers raise\n * `provider_unavailable`; `opengeni` (hosted) vaults never reach a provider.\n */\nexport function createVaultProviderRegistry(factories: {\n onepassword?: (connectionId: string | null) => Promise<VaultProvider>;\n host?: () => Promise<VaultProvider>;\n external?: (connectionId: string | null) => Promise<VaultProvider>;\n protonpass?: (connectionId: string | null) => Promise<VaultProvider>;\n keeper?: (connectionId: string | null) => Promise<VaultProvider>;\n bitwarden?: (connectionId: string | null) => Promise<VaultProvider>;\n}): VaultProviderRegistry {\n return {\n async forVault(vault) {\n if (vault.source === \"onepassword\" && factories.onepassword) {\n return factories.onepassword(vault.providerConnectionId);\n }\n if (vault.source === \"host\" && factories.host) return factories.host();\n if (\n vault.source !== \"opengeni\" &&\n vault.source !== \"host\" &&\n vault.source !== \"onepassword\"\n ) {\n const factory = factories[vault.source];\n if (factory) return factory(vault.providerConnectionId);\n }\n throw new VaultProviderError(\n \"provider_unavailable\",\n vault.source === \"opengeni\"\n ? \"hosted vaults are read from the database, not a provider\"\n : `no ${vault.source} vault provider is configured`,\n );\n },\n };\n}\n\n/** A registry with no providers: every provider vault is unavailable. */\nexport const EMPTY_VAULT_PROVIDER_REGISTRY: VaultProviderRegistry = createVaultProviderRegistry({});\n\n/**\n * A simple counting budget: at most `limit` calls of any kind (Q-18 uses 50\n * reads per attempt). Exhaustion raises `provider_rate_limited`.\n */\nexport function createProviderCallBudget(limit: number): ProviderCallBudget & { used(): number } {\n let used = 0;\n return {\n take(op) {\n if (used >= limit) {\n throw new VaultProviderError(\n \"provider_rate_limited\",\n `this attempt used its ${limit} vault provider calls (last: ${op})`,\n );\n }\n used += 1;\n },\n used: () => used,\n };\n}\n"],"mappings":";AAiKO,IAAM,6BAA6B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACnC;AAAA,EACA;AAAA,EACT,YAAY,MAA8B,SAAiB,cAAuB;AAChF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,eAAe;AAAA,EACtB;AACF;AAEO,SAAS,qBAAqB,OAA6C;AAChF,SAAO,iBAAiB;AAC1B;AAyBO,SAAS,4BAA4B,WAOlB;AACxB,SAAO;AAAA,IACL,MAAM,SAAS,OAAO;AACpB,UAAI,MAAM,WAAW,iBAAiB,UAAU,aAAa;AAC3D,eAAO,UAAU,YAAY,MAAM,oBAAoB;AAAA,MACzD;AACA,UAAI,MAAM,WAAW,UAAU,UAAU,KAAM,QAAO,UAAU,KAAK;AACrE,UACE,MAAM,WAAW,cACjB,MAAM,WAAW,UACjB,MAAM,WAAW,eACjB;AACA,cAAM,UAAU,UAAU,MAAM,MAAM;AACtC,YAAI,QAAS,QAAO,QAAQ,MAAM,oBAAoB;AAAA,MACxD;AACA,YAAM,IAAI;AAAA,QACR;AAAA,QACA,MAAM,WAAW,aACb,6DACA,MAAM,MAAM,MAAM;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,gCAAuD,4BAA4B,CAAC,CAAC;AAM3F,SAAS,yBAAyB,OAAwD;AAC/F,MAAI,OAAO;AACX,SAAO;AAAA,IACL,KAAK,IAAI;AACP,UAAI,QAAQ,OAAO;AACjB,cAAM,IAAI;AAAA,UACR;AAAA,UACA,yBAAyB,KAAK,gCAAgC,EAAE;AAAA,QAClE;AAAA,MACF;AACA,cAAQ;AAAA,IACV;AAAA,IACA,MAAM,MAAM;AAAA,EACd;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VaultProviderError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BD43JBPC.js";
|
|
4
4
|
|
|
5
5
|
// src/testing/fake-provider.ts
|
|
6
6
|
import { parseTotpInput } from "@opengeni/contracts";
|
|
@@ -226,4 +226,4 @@ function createFakeVaultProvider(seed = {}) {
|
|
|
226
226
|
export {
|
|
227
227
|
createFakeVaultProvider
|
|
228
228
|
};
|
|
229
|
-
//# sourceMappingURL=chunk-
|
|
229
|
+
//# sourceMappingURL=chunk-BEKN77JO.js.map
|