@centient/secrets 0.9.0 → 0.11.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 +424 -8
- package/dist/audit/hmac-chain.d.ts +117 -0
- package/dist/audit/hmac-chain.d.ts.map +1 -0
- package/dist/audit/hmac-chain.js +811 -0
- package/dist/audit/hmac-chain.js.map +1 -0
- package/dist/audit/ocsf.d.ts +108 -0
- package/dist/audit/ocsf.d.ts.map +1 -0
- package/dist/audit/ocsf.js +204 -0
- package/dist/audit/ocsf.js.map +1 -0
- package/dist/cli/hidden-prompt.d.ts.map +1 -1
- package/dist/cli/hidden-prompt.js +55 -10
- package/dist/cli/hidden-prompt.js.map +1 -1
- package/dist/cli/messages.d.ts +40 -8
- package/dist/cli/messages.d.ts.map +1 -1
- package/dist/cli/messages.js +34 -8
- package/dist/cli/messages.js.map +1 -1
- package/dist/cli/secrets-cli.d.ts.map +1 -1
- package/dist/cli/secrets-cli.js +191 -32
- package/dist/cli/secrets-cli.js.map +1 -1
- package/dist/client.d.ts +26 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +129 -0
- package/dist/client.js.map +1 -0
- package/dist/compatibility.d.ts +199 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +419 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/crypto/darwin-keychain.d.ts +394 -0
- package/dist/crypto/darwin-keychain.d.ts.map +1 -0
- package/dist/crypto/darwin-keychain.js +793 -0
- package/dist/crypto/darwin-keychain.js.map +1 -0
- package/dist/crypto/vault-common.d.ts +55 -12
- package/dist/crypto/vault-common.d.ts.map +1 -1
- package/dist/crypto/vault-common.js +74 -71
- package/dist/crypto/vault-common.js.map +1 -1
- package/dist/environment/EnvironmentManager.d.ts.map +1 -1
- package/dist/environment/EnvironmentManager.js +5 -10
- package/dist/environment/EnvironmentManager.js.map +1 -1
- package/dist/index.d.ts +37 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -6
- package/dist/index.js.map +1 -1
- package/dist/key-providers/keychain-provider.d.ts +30 -2
- package/dist/key-providers/keychain-provider.d.ts.map +1 -1
- package/dist/key-providers/keychain-provider.js +29 -5
- package/dist/key-providers/keychain-provider.js.map +1 -1
- package/dist/key-providers/onepassword-provider.d.ts +65 -5
- package/dist/key-providers/onepassword-provider.d.ts.map +1 -1
- package/dist/key-providers/onepassword-provider.js +159 -67
- package/dist/key-providers/onepassword-provider.js.map +1 -1
- package/dist/key-providers/op-cli.d.ts +78 -0
- package/dist/key-providers/op-cli.d.ts.map +1 -0
- package/dist/key-providers/op-cli.js +123 -0
- package/dist/key-providers/op-cli.js.map +1 -0
- package/dist/key-providers/passphrase-provider.d.ts +20 -0
- package/dist/key-providers/passphrase-provider.d.ts.map +1 -1
- package/dist/key-providers/passphrase-provider.js +49 -0
- package/dist/key-providers/passphrase-provider.js.map +1 -1
- package/dist/key-providers/probe.d.ts +46 -0
- package/dist/key-providers/probe.d.ts.map +1 -0
- package/dist/key-providers/probe.js +70 -0
- package/dist/key-providers/probe.js.map +1 -0
- package/dist/key-providers/types.d.ts +51 -1
- package/dist/key-providers/types.d.ts.map +1 -1
- package/dist/platform/agent-detect.d.ts +39 -3
- package/dist/platform/agent-detect.d.ts.map +1 -1
- package/dist/platform/agent-detect.js +55 -9
- package/dist/platform/agent-detect.js.map +1 -1
- package/dist/platform/session-context.d.ts +77 -0
- package/dist/platform/session-context.d.ts.map +1 -0
- package/dist/platform/session-context.js +83 -0
- package/dist/platform/session-context.js.map +1 -0
- package/dist/policies/audit-trail.d.ts +25 -0
- package/dist/policies/audit-trail.d.ts.map +1 -0
- package/dist/policies/audit-trail.js +31 -0
- package/dist/policies/audit-trail.js.map +1 -0
- package/dist/secret-state.d.ts +54 -0
- package/dist/secret-state.d.ts.map +1 -0
- package/dist/secret-state.js +2 -0
- package/dist/secret-state.js.map +1 -0
- package/dist/sinks/index.d.ts +9 -0
- package/dist/sinks/index.d.ts.map +1 -0
- package/dist/sinks/index.js +5 -0
- package/dist/sinks/index.js.map +1 -0
- package/dist/sinks/jsonl.d.ts +16 -0
- package/dist/sinks/jsonl.d.ts.map +1 -0
- package/dist/sinks/jsonl.js +51 -0
- package/dist/sinks/jsonl.js.map +1 -0
- package/dist/sinks/otel.d.ts +22 -0
- package/dist/sinks/otel.d.ts.map +1 -0
- package/dist/sinks/otel.js +155 -0
- package/dist/sinks/otel.js.map +1 -0
- package/dist/sinks/queue.d.ts +12 -0
- package/dist/sinks/queue.d.ts.map +1 -0
- package/dist/sinks/queue.js +89 -0
- package/dist/sinks/queue.js.map +1 -0
- package/dist/sinks/syslog.d.ts +17 -0
- package/dist/sinks/syslog.d.ts.map +1 -0
- package/dist/sinks/syslog.js +103 -0
- package/dist/sinks/syslog.js.map +1 -0
- package/dist/sinks/types.d.ts +27 -0
- package/dist/sinks/types.d.ts.map +1 -0
- package/dist/sinks/types.js +18 -0
- package/dist/sinks/types.js.map +1 -0
- package/dist/vault/policy.d.ts +64 -34
- package/dist/vault/policy.d.ts.map +1 -1
- package/dist/vault/policy.js +109 -67
- package/dist/vault/policy.js.map +1 -1
- package/dist/vault/session-vault-errors.d.ts +72 -4
- package/dist/vault/session-vault-errors.d.ts.map +1 -1
- package/dist/vault/session-vault-errors.js +95 -4
- package/dist/vault/session-vault-errors.js.map +1 -1
- package/dist/vault/session-vault.d.ts +145 -2
- package/dist/vault/session-vault.d.ts.map +1 -1
- package/dist/vault/session-vault.js +548 -72
- package/dist/vault/session-vault.js.map +1 -1
- package/dist/vault/sidecar.d.ts +9 -0
- package/dist/vault/sidecar.d.ts.map +1 -1
- package/dist/vault/sidecar.js +72 -3
- package/dist/vault/sidecar.js.map +1 -1
- package/dist/vault/types.d.ts +58 -10
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/dist/vault/vault-env.d.ts +43 -50
- package/dist/vault/vault-env.d.ts.map +1 -1
- package/dist/vault/vault-env.js +141 -62
- package/dist/vault/vault-env.js.map +1 -1
- package/dist/vault/vault-gpg.d.ts +6 -1
- package/dist/vault/vault-gpg.d.ts.map +1 -1
- package/dist/vault/vault-gpg.js +10 -8
- package/dist/vault/vault-gpg.js.map +1 -1
- package/dist/vault/vault-libsecret.d.ts +6 -1
- package/dist/vault/vault-libsecret.d.ts.map +1 -1
- package/dist/vault/vault-libsecret.js +16 -14
- package/dist/vault/vault-libsecret.js.map +1 -1
- package/dist/vault/vault-onepassword.d.ts +119 -0
- package/dist/vault/vault-onepassword.d.ts.map +1 -0
- package/dist/vault/vault-onepassword.js +271 -0
- package/dist/vault/vault-onepassword.js.map +1 -0
- package/dist/vault/vault-utils.d.ts +37 -3
- package/dist/vault/vault-utils.d.ts.map +1 -1
- package/dist/vault/vault-utils.js +65 -3
- package/dist/vault/vault-utils.js.map +1 -1
- package/dist/vault/vault-windows.d.ts +7 -2
- package/dist/vault/vault-windows.d.ts.map +1 -1
- package/dist/vault/vault-windows.js +21 -16
- package/dist/vault/vault-windows.js.map +1 -1
- package/dist/vault/vault.d.ts +120 -9
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +222 -139
- package/dist/vault/vault.js.map +1 -1
- package/package.json +8 -2
package/dist/vault/vault.d.ts
CHANGED
|
@@ -8,32 +8,92 @@
|
|
|
8
8
|
* 4. GpgVault — GPG-encrypted files (Linux / WSL)
|
|
9
9
|
* 5. EnvVault — Environment variable fallback (always available)
|
|
10
10
|
*
|
|
11
|
-
* The
|
|
11
|
+
* The default backend is selected lazily on first use by calling each backend's
|
|
12
12
|
* static `detect()` method in order and choosing the first one that returns true.
|
|
13
|
+
* A successful selection is then reused for the lifetime of this module.
|
|
14
|
+
*
|
|
15
|
+
* **Explicit selection (ADR-004) sits in front of that cascade.** `secrets.backend`
|
|
16
|
+
* (or `CENTIENT_SECRETS_BACKEND`) names a backend directly and fails closed if it
|
|
17
|
+
* is unusable — it is never silently substituted. `OnePasswordVault` is reachable
|
|
18
|
+
* *only* this way: having `op` installed is not consent to route credentials into
|
|
19
|
+
* someone's 1Password vault.
|
|
13
20
|
*
|
|
14
21
|
* Session TTL: 4 hours from the last successful read/write.
|
|
15
22
|
*
|
|
16
|
-
* Error handling:
|
|
23
|
+
* Error handling: a *storage* failure is reported as `null`/`false` — the
|
|
24
|
+
* backend contract is non-throwing. Three things do throw, because they are
|
|
25
|
+
* not storage outcomes: a policy `before` hook rejecting the operation
|
|
26
|
+
* (ADR-002 §1.0.0), a backend surfacing an unexpected transport failure from
|
|
27
|
+
* `retrieve`/`listKeys`, and a malformed credential key
|
|
28
|
+
* (`InvalidCredentialKeyError`, see the key-validation section below).
|
|
17
29
|
*/
|
|
18
|
-
import type {
|
|
30
|
+
import type { KeychainDeps } from "../crypto/darwin-keychain.js";
|
|
31
|
+
import type { SecretState } from "../secret-state.js";
|
|
32
|
+
import type { VaultBackend, VaultType } from "./types.js";
|
|
19
33
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
34
|
+
* The keychain service every credential VALUE lives under. Exported because
|
|
35
|
+
* the migration helper (`migrateLoginCredentialToSystem`) and operator
|
|
36
|
+
* tooling have to name the same service — a second literal somewhere else is
|
|
37
|
+
* how a migration silently moves nothing.
|
|
22
38
|
*/
|
|
23
|
-
export declare
|
|
39
|
+
export declare const AUTH_KEYCHAIN_SERVICE = "centient-auth";
|
|
40
|
+
/**
|
|
41
|
+
* Wraps the macOS Keychain helper functions as a VaultBackend.
|
|
42
|
+
*
|
|
43
|
+
* Every method routes through `crypto/darwin-keychain.ts` (#188), so credential
|
|
44
|
+
* values inherit explicit System-keychain reads in a sessionless context,
|
|
45
|
+
* `-U` replace-in-place writes and `-T /usr/bin/security` reader
|
|
46
|
+
* preauthorization — the same posture the KeyProvider layer gets for the vault
|
|
47
|
+
* master key.
|
|
48
|
+
*
|
|
49
|
+
* Only available on macOS (darwin).
|
|
50
|
+
*/
|
|
51
|
+
export declare class KeychainVault implements VaultBackend {
|
|
52
|
+
private readonly deps;
|
|
53
|
+
readonly name = "keychain";
|
|
54
|
+
/**
|
|
55
|
+
* @param deps - Injection seam for the `security` CLI and the
|
|
56
|
+
* platform/environment that decide the read path. Omitted in production;
|
|
57
|
+
* supplied by tests so the exact argv is assertable.
|
|
58
|
+
*/
|
|
59
|
+
constructor(deps?: Partial<KeychainDeps>);
|
|
60
|
+
static detect(): boolean;
|
|
61
|
+
store(key: string, value: string): boolean;
|
|
62
|
+
retrieve(key: string): string | null;
|
|
63
|
+
delete(key: string): boolean;
|
|
64
|
+
listKeys(prefix?: string): Promise<string[]>;
|
|
65
|
+
/**
|
|
66
|
+
* The credential state probe: runs the SAME read {@link retrieve} would run
|
|
67
|
+
* in this context — same path, same explicit target — then discards the
|
|
68
|
+
* value and returns only the value-free {@link SecretState}.
|
|
69
|
+
*
|
|
70
|
+
* A metadata-only lookup would be cheaper and would leave the secret on
|
|
71
|
+
* disk, but it can only report presence: an item whose ACL does not
|
|
72
|
+
* preauthorize the reader, or that sits in a locked keychain, is present and
|
|
73
|
+
* unreadable, and calling that `found` hands a caller trusted state that is
|
|
74
|
+
* wrong in exactly the direction #188 exists to fix. `found` here means the
|
|
75
|
+
* reader will get bytes.
|
|
76
|
+
*/
|
|
77
|
+
probe(key: string): SecretState;
|
|
78
|
+
}
|
|
24
79
|
/**
|
|
25
80
|
* Returns the type identifier for the active vault backend.
|
|
26
81
|
*
|
|
27
82
|
* Useful for diagnostics and health checks to know which backend was selected
|
|
28
|
-
*
|
|
83
|
+
* on first use (e.g. "keychain", "libsecret", "gpg", "env").
|
|
29
84
|
*/
|
|
30
85
|
export declare function getActiveVaultType(): VaultType;
|
|
86
|
+
/** Legacy module-level shim over the default client. */
|
|
87
|
+
export declare function isSessionValid(): boolean;
|
|
31
88
|
/**
|
|
32
89
|
* Store a credential in the active vault backend.
|
|
33
90
|
*
|
|
34
|
-
* @param key - Logical key name (e.g. 'auth-token', 'refresh-token')
|
|
91
|
+
* @param key - Logical key name (e.g. 'auth-token', 'refresh-token').
|
|
92
|
+
* Must match the key grammar — see "Key validation" above.
|
|
35
93
|
* @param value - The credential value to store
|
|
36
94
|
* @returns true on success, false if the backend write fails
|
|
95
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar.
|
|
96
|
+
* Nothing is written and no backend is contacted.
|
|
37
97
|
*/
|
|
38
98
|
export declare function storeCredential(key: string, value: string): Promise<boolean>;
|
|
39
99
|
/**
|
|
@@ -41,6 +101,10 @@ export declare function storeCredential(key: string, value: string): Promise<boo
|
|
|
41
101
|
*
|
|
42
102
|
* @param key - Logical key name (e.g. 'auth-token')
|
|
43
103
|
* @returns The stored value, or null if not found / backend unavailable
|
|
104
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar.
|
|
105
|
+
* Deliberately not `null`: "malformed" and "not stored" are different
|
|
106
|
+
* answers, and returning the not-found shape for the first is the silent
|
|
107
|
+
* degradation this path used to have.
|
|
44
108
|
*/
|
|
45
109
|
export declare function getCredential(key: string): Promise<string | null>;
|
|
46
110
|
/**
|
|
@@ -48,6 +112,9 @@ export declare function getCredential(key: string): Promise<string | null>;
|
|
|
48
112
|
*
|
|
49
113
|
* @param key - Logical key name (e.g. 'auth-token')
|
|
50
114
|
* @returns true on success (including "already deleted"), false on unexpected error
|
|
115
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar.
|
|
116
|
+
* Not reported as an idempotent success: such a key was never storable, so
|
|
117
|
+
* "already deleted" would be a claim the vault cannot make.
|
|
51
118
|
*/
|
|
52
119
|
export declare function deleteCredential(key: string): Promise<boolean>;
|
|
53
120
|
/**
|
|
@@ -64,7 +131,15 @@ export declare function deleteCredential(key: string): Promise<boolean>;
|
|
|
64
131
|
* Note: credential keys must match `isValidKey` — lowercase alphanumeric
|
|
65
132
|
* plus hyphen and dot, first and last character alphanumeric, <=64 chars.
|
|
66
133
|
* Both `-` and `.` work as namespace separators; pick whichever convention
|
|
67
|
-
* reads best.
|
|
134
|
+
* reads best. **This is enforced, not merely documented** (#168): every
|
|
135
|
+
* function on this path rejects a non-conforming key before dispatching.
|
|
136
|
+
*
|
|
137
|
+
* A `prefix` is checked against `isValidKeyPrefix` rather than `isValidKey`,
|
|
138
|
+
* so it may end on a separator — `"soma.anthropic."` is the intended way to
|
|
139
|
+
* scope an enumeration to a namespace, and is not itself a valid key.
|
|
140
|
+
*
|
|
141
|
+
* @throws {InvalidCredentialKeyError} if `prefix` could not be the leading
|
|
142
|
+
* substring of any valid key.
|
|
68
143
|
*
|
|
69
144
|
* @example
|
|
70
145
|
* // Enumerate all soma-owned Anthropic credentials
|
|
@@ -75,4 +150,40 @@ export declare function deleteCredential(key: string): Promise<boolean>;
|
|
|
75
150
|
* }
|
|
76
151
|
*/
|
|
77
152
|
export declare function listCredentials(prefix?: string): Promise<string[]>;
|
|
153
|
+
/** A value-free answer about one credential in one backend. */
|
|
154
|
+
export interface BackendStateProbe {
|
|
155
|
+
/** Always `"value"` — distinguishes this from the key-layer probe. */
|
|
156
|
+
layer: "value";
|
|
157
|
+
/** Which backend answered. */
|
|
158
|
+
backend: VaultType;
|
|
159
|
+
state: SecretState;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Probe one credential's state in a specific backend.
|
|
163
|
+
*
|
|
164
|
+
* Backends that implement `probe()` answer directly. For the rest this falls
|
|
165
|
+
* back to a `retrieve()`-based mapping — the value is discarded immediately
|
|
166
|
+
* and never returned — which yields `found`/`absent` honestly and `failed`
|
|
167
|
+
* when the backend threw. It never invents `locked`, because a backend that
|
|
168
|
+
* did not report one cannot be assumed to have one, and it never converts a
|
|
169
|
+
* throw into `absent`.
|
|
170
|
+
*
|
|
171
|
+
* Both paths answer readability, not mere presence: the fallback runs the real
|
|
172
|
+
* `retrieve()`, and an implementing backend is required to exercise the same
|
|
173
|
+
* access path it would for a read (see `VaultBackend.probe`). `found`
|
|
174
|
+
* therefore means the reader will get bytes.
|
|
175
|
+
*
|
|
176
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar —
|
|
177
|
+
* the same rule every other vault entry point enforces (#168). Policy hooks
|
|
178
|
+
* are deliberately NOT run: a probe reads no value, so there is nothing for
|
|
179
|
+
* an access-control hook to allow or deny.
|
|
180
|
+
*/
|
|
181
|
+
export declare function probeVaultBackendState(backend: VaultBackend, type: VaultType, key: string): Promise<BackendStateProbe>;
|
|
182
|
+
/**
|
|
183
|
+
* Probe one credential's state in the backend this process actually uses.
|
|
184
|
+
*
|
|
185
|
+
* The value-layer half of the two-layer probe; see `probeKeyProviderState()`
|
|
186
|
+
* for the vault master key.
|
|
187
|
+
*/
|
|
188
|
+
export declare function probeBackendState(key: string): Promise<BackendStateProbe>;
|
|
78
189
|
//# sourceMappingURL=vault.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../src/vault/vault.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../src/vault/vault.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMtD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAe1D;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAMrD;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,YAAW,YAAY;IAQpC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPjC,QAAQ,CAAC,IAAI,cAAc;IAE3B;;;;OAIG;gBAC0B,IAAI,GAAE,OAAO,CAAC,YAAY,CAAM;IAE7D,MAAM,CAAC,MAAM,IAAI,OAAO;IAIxB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAI1C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIpC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAItB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIlD;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW;CAGhC;AA6GD;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,CAE9C;AAED,wDAAwD;AACxD,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAElB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEvE;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEpE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAExE;AAuBD,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,KAAK,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,OAAO,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,iBAAiB,CAAC,CAiC5B;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAG/E"}
|
package/dist/vault/vault.js
CHANGED
|
@@ -8,56 +8,156 @@
|
|
|
8
8
|
* 4. GpgVault — GPG-encrypted files (Linux / WSL)
|
|
9
9
|
* 5. EnvVault — Environment variable fallback (always available)
|
|
10
10
|
*
|
|
11
|
-
* The
|
|
11
|
+
* The default backend is selected lazily on first use by calling each backend's
|
|
12
12
|
* static `detect()` method in order and choosing the first one that returns true.
|
|
13
|
+
* A successful selection is then reused for the lifetime of this module.
|
|
14
|
+
*
|
|
15
|
+
* **Explicit selection (ADR-004) sits in front of that cascade.** `secrets.backend`
|
|
16
|
+
* (or `CENTIENT_SECRETS_BACKEND`) names a backend directly and fails closed if it
|
|
17
|
+
* is unusable — it is never silently substituted. `OnePasswordVault` is reachable
|
|
18
|
+
* *only* this way: having `op` installed is not consent to route credentials into
|
|
19
|
+
* someone's 1Password vault.
|
|
13
20
|
*
|
|
14
21
|
* Session TTL: 4 hours from the last successful read/write.
|
|
15
22
|
*
|
|
16
|
-
* Error handling:
|
|
23
|
+
* Error handling: a *storage* failure is reported as `null`/`false` — the
|
|
24
|
+
* backend contract is non-throwing. Three things do throw, because they are
|
|
25
|
+
* not storage outcomes: a policy `before` hook rejecting the operation
|
|
26
|
+
* (ADR-002 §1.0.0), a backend surfacing an unexpected transport failure from
|
|
27
|
+
* `retrieve`/`listKeys`, and a malformed credential key
|
|
28
|
+
* (`InvalidCredentialKeyError`, see the key-validation section below).
|
|
17
29
|
*/
|
|
18
30
|
import { storeStringInKeychain, getStringFromKeychain, deleteFromKeychain, listAccountsInKeychain, } from "../crypto/vault-common.js";
|
|
31
|
+
import { probeKeychainCredentialState } from "../crypto/darwin-keychain.js";
|
|
19
32
|
import { WindowsVault } from "./vault-windows.js";
|
|
20
33
|
import { LibsecretVault } from "./vault-libsecret.js";
|
|
21
34
|
import { GpgVault } from "./vault-gpg.js";
|
|
22
35
|
import { EnvVault } from "./vault-env.js";
|
|
23
|
-
import {
|
|
36
|
+
import { OnePasswordVault } from "./vault-onepassword.js";
|
|
37
|
+
import { loadConfig } from "../key-providers/resolve.js";
|
|
38
|
+
import { defaultPolicyRunner } from "./policy.js";
|
|
39
|
+
import { assertValidKey } from "./vault-utils.js";
|
|
40
|
+
import { createSecretsClientWithPolicyRunner } from "../client.js";
|
|
24
41
|
// =============================================================================
|
|
25
42
|
// Constants
|
|
26
43
|
// =============================================================================
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
/**
|
|
45
|
+
* The keychain service every credential VALUE lives under. Exported because
|
|
46
|
+
* the migration helper (`migrateLoginCredentialToSystem`) and operator
|
|
47
|
+
* tooling have to name the same service — a second literal somewhere else is
|
|
48
|
+
* how a migration silently moves nothing.
|
|
49
|
+
*/
|
|
50
|
+
export const AUTH_KEYCHAIN_SERVICE = "centient-auth";
|
|
29
51
|
// =============================================================================
|
|
30
52
|
// KeychainVault wrapper
|
|
31
53
|
// =============================================================================
|
|
32
54
|
/**
|
|
33
|
-
* Wraps the
|
|
55
|
+
* Wraps the macOS Keychain helper functions as a VaultBackend.
|
|
56
|
+
*
|
|
57
|
+
* Every method routes through `crypto/darwin-keychain.ts` (#188), so credential
|
|
58
|
+
* values inherit explicit System-keychain reads in a sessionless context,
|
|
59
|
+
* `-U` replace-in-place writes and `-T /usr/bin/security` reader
|
|
60
|
+
* preauthorization — the same posture the KeyProvider layer gets for the vault
|
|
61
|
+
* master key.
|
|
62
|
+
*
|
|
34
63
|
* Only available on macOS (darwin).
|
|
35
64
|
*/
|
|
36
|
-
class KeychainVault {
|
|
65
|
+
export class KeychainVault {
|
|
66
|
+
deps;
|
|
67
|
+
name = "keychain";
|
|
68
|
+
/**
|
|
69
|
+
* @param deps - Injection seam for the `security` CLI and the
|
|
70
|
+
* platform/environment that decide the read path. Omitted in production;
|
|
71
|
+
* supplied by tests so the exact argv is assertable.
|
|
72
|
+
*/
|
|
73
|
+
constructor(deps = {}) {
|
|
74
|
+
this.deps = deps;
|
|
75
|
+
}
|
|
37
76
|
static detect() {
|
|
38
77
|
return process.platform === "darwin";
|
|
39
78
|
}
|
|
40
79
|
store(key, value) {
|
|
41
|
-
return storeStringInKeychain(AUTH_KEYCHAIN_SERVICE, key, value);
|
|
80
|
+
return storeStringInKeychain(AUTH_KEYCHAIN_SERVICE, key, value, this.deps);
|
|
42
81
|
}
|
|
43
82
|
retrieve(key) {
|
|
44
|
-
return getStringFromKeychain(AUTH_KEYCHAIN_SERVICE, key);
|
|
83
|
+
return getStringFromKeychain(AUTH_KEYCHAIN_SERVICE, key, this.deps);
|
|
45
84
|
}
|
|
46
85
|
delete(key) {
|
|
47
|
-
return deleteFromKeychain(AUTH_KEYCHAIN_SERVICE, key);
|
|
86
|
+
return deleteFromKeychain(AUTH_KEYCHAIN_SERVICE, key, this.deps);
|
|
48
87
|
}
|
|
49
88
|
async listKeys(prefix) {
|
|
50
|
-
return listAccountsInKeychain(AUTH_KEYCHAIN_SERVICE, prefix);
|
|
89
|
+
return listAccountsInKeychain(AUTH_KEYCHAIN_SERVICE, prefix, this.deps);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The credential state probe: runs the SAME read {@link retrieve} would run
|
|
93
|
+
* in this context — same path, same explicit target — then discards the
|
|
94
|
+
* value and returns only the value-free {@link SecretState}.
|
|
95
|
+
*
|
|
96
|
+
* A metadata-only lookup would be cheaper and would leave the secret on
|
|
97
|
+
* disk, but it can only report presence: an item whose ACL does not
|
|
98
|
+
* preauthorize the reader, or that sits in a locked keychain, is present and
|
|
99
|
+
* unreadable, and calling that `found` hands a caller trusted state that is
|
|
100
|
+
* wrong in exactly the direction #188 exists to fix. `found` here means the
|
|
101
|
+
* reader will get bytes.
|
|
102
|
+
*/
|
|
103
|
+
probe(key) {
|
|
104
|
+
return probeKeychainCredentialState(AUTH_KEYCHAIN_SERVICE, key, this.deps);
|
|
51
105
|
}
|
|
52
106
|
}
|
|
53
107
|
// =============================================================================
|
|
54
108
|
// Cascade initialization
|
|
55
109
|
// =============================================================================
|
|
56
110
|
/**
|
|
57
|
-
*
|
|
111
|
+
* Read the explicitly-selected backend, env taking precedence over config —
|
|
112
|
+
* the same env > config order the key layer uses (ADR-001).
|
|
113
|
+
*
|
|
114
|
+
* Returns null when nothing is explicitly selected, which is the signal to run
|
|
115
|
+
* the auto-cascade unchanged.
|
|
116
|
+
*/
|
|
117
|
+
function resolveExplicitBackend() {
|
|
118
|
+
const envBackend = process.env.CENTIENT_SECRETS_BACKEND?.trim();
|
|
119
|
+
const config = loadConfig().secrets ?? {};
|
|
120
|
+
const selected = envBackend || config.backend;
|
|
121
|
+
if (!selected)
|
|
122
|
+
return null;
|
|
123
|
+
if (selected !== "1password") {
|
|
124
|
+
throw new Error(`Unknown secrets backend "${selected}". Supported explicit backends: 1password.`);
|
|
125
|
+
}
|
|
126
|
+
const envVault = process.env.CENTIENT_OP_VAULT?.trim();
|
|
127
|
+
const onePasswordBackend = {
|
|
128
|
+
...config.onePasswordBackend,
|
|
129
|
+
...(envVault ? { vault: envVault } : {}),
|
|
130
|
+
};
|
|
131
|
+
return { type: selected, onePasswordBackend };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Selects the credential-storage backend.
|
|
135
|
+
*
|
|
136
|
+
* **Explicit selection wins and fails closed** (ADR-004 §1): if config or env
|
|
137
|
+
* names a backend that then turns out to be unusable — no vault configured, `op`
|
|
138
|
+
* missing or unauthenticated — this throws rather than quietly continuing down
|
|
139
|
+
* the auto-cascade. Falling through would silently store credentials somewhere
|
|
140
|
+
* other than where the operator said, which is the whole class of surprise the
|
|
141
|
+
* opt-in model exists to prevent (P2).
|
|
142
|
+
*
|
|
143
|
+
* With no explicit selection, the historical auto-cascade runs unchanged:
|
|
58
144
|
* Keychain -> Windows -> Libsecret -> GPG -> Env
|
|
145
|
+
* 1Password is **never** auto-selected — `op` being installed is not consent to
|
|
146
|
+
* route credentials into it.
|
|
59
147
|
*/
|
|
60
148
|
function initVaultBackend() {
|
|
149
|
+
const explicit = resolveExplicitBackend();
|
|
150
|
+
if (explicit !== null) {
|
|
151
|
+
// Constructor throws on a missing vault name — the fail-closed half of §1.
|
|
152
|
+
const backend = new OnePasswordVault(explicit.onePasswordBackend);
|
|
153
|
+
if (!OnePasswordVault.detect(true)) {
|
|
154
|
+
throw new Error('secrets backend "1password" was explicitly selected, but the 1Password CLI ' +
|
|
155
|
+
"(`op`) is unavailable or not authenticated. Install `op` and sign in, or set " +
|
|
156
|
+
"OP_SERVICE_ACCOUNT_TOKEN. Refusing to fall back to another backend — an " +
|
|
157
|
+
"explicit backend choice is never silently substituted.");
|
|
158
|
+
}
|
|
159
|
+
return { backend, type: "1password" };
|
|
160
|
+
}
|
|
61
161
|
if (KeychainVault.detect())
|
|
62
162
|
return { backend: new KeychainVault(), type: "keychain" };
|
|
63
163
|
if (WindowsVault.detect())
|
|
@@ -68,31 +168,29 @@ function initVaultBackend() {
|
|
|
68
168
|
return { backend: new GpgVault(), type: "gpg" };
|
|
69
169
|
return { backend: new EnvVault(), type: "env" };
|
|
70
170
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
function touchSession() {
|
|
88
|
-
lastAccessAt = Date.now();
|
|
171
|
+
let defaultVault;
|
|
172
|
+
function getDefaultVault() {
|
|
173
|
+
if (defaultVault !== undefined)
|
|
174
|
+
return defaultVault;
|
|
175
|
+
const { backend, type } = initVaultBackend();
|
|
176
|
+
const initialized = {
|
|
177
|
+
backend,
|
|
178
|
+
type,
|
|
179
|
+
client: createSecretsClientWithPolicyRunner({
|
|
180
|
+
provider: backend,
|
|
181
|
+
providerName: type,
|
|
182
|
+
policyRunner: defaultPolicyRunner,
|
|
183
|
+
}),
|
|
184
|
+
};
|
|
185
|
+
defaultVault = initialized;
|
|
186
|
+
return initialized;
|
|
89
187
|
}
|
|
90
188
|
// =============================================================================
|
|
91
189
|
// Public API
|
|
92
190
|
//
|
|
93
191
|
// Policy-rejected operations are audited: when a `before` hook throws,
|
|
94
|
-
// the rejection propagates to the caller AND the
|
|
95
|
-
// already-entered policies fire with a `*_rejected` event (see
|
|
192
|
+
// the rejection propagates to the caller AND the rejecting policy plus the
|
|
193
|
+
// already-entered policies fire `after` with a `*_rejected` event (see
|
|
96
194
|
// `runBeforeHooks` in policy.ts), so a denied operation is never
|
|
97
195
|
// invisible to the audit trail. ADR-002 §1.0.0.
|
|
98
196
|
// =============================================================================
|
|
@@ -100,107 +198,52 @@ function touchSession() {
|
|
|
100
198
|
* Returns the type identifier for the active vault backend.
|
|
101
199
|
*
|
|
102
200
|
* Useful for diagnostics and health checks to know which backend was selected
|
|
103
|
-
*
|
|
201
|
+
* on first use (e.g. "keychain", "libsecret", "gpg", "env").
|
|
104
202
|
*/
|
|
105
203
|
export function getActiveVaultType() {
|
|
106
|
-
return
|
|
204
|
+
return getDefaultVault().type;
|
|
205
|
+
}
|
|
206
|
+
/** Legacy module-level shim over the default client. */
|
|
207
|
+
export function isSessionValid() {
|
|
208
|
+
return getDefaultVault().client.isSessionValid();
|
|
107
209
|
}
|
|
108
210
|
/**
|
|
109
211
|
* Store a credential in the active vault backend.
|
|
110
212
|
*
|
|
111
|
-
* @param key - Logical key name (e.g. 'auth-token', 'refresh-token')
|
|
213
|
+
* @param key - Logical key name (e.g. 'auth-token', 'refresh-token').
|
|
214
|
+
* Must match the key grammar — see "Key validation" above.
|
|
112
215
|
* @param value - The credential value to store
|
|
113
216
|
* @returns true on success, false if the backend write fails
|
|
217
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar.
|
|
218
|
+
* Nothing is written and no backend is contacted.
|
|
114
219
|
*/
|
|
115
220
|
export async function storeCredential(key, value) {
|
|
116
|
-
|
|
117
|
-
await runBeforeHooks({ type: "write", key }, (error) => ({
|
|
118
|
-
type: "credential_write_rejected",
|
|
119
|
-
timestamp: new Date().toISOString(),
|
|
120
|
-
backend: activeVaultType,
|
|
121
|
-
key,
|
|
122
|
-
error,
|
|
123
|
-
durationMs: performance.now() - start,
|
|
124
|
-
}));
|
|
125
|
-
const success = activeBackend.store(key, value);
|
|
126
|
-
if (success)
|
|
127
|
-
touchSession();
|
|
128
|
-
runAfterHooks({
|
|
129
|
-
type: success ? "credential_written" : "credential_write_failed",
|
|
130
|
-
timestamp: new Date().toISOString(),
|
|
131
|
-
backend: activeVaultType,
|
|
132
|
-
key,
|
|
133
|
-
durationMs: performance.now() - start,
|
|
134
|
-
});
|
|
135
|
-
return success;
|
|
221
|
+
return getDefaultVault().client.storeCredential(key, value);
|
|
136
222
|
}
|
|
137
223
|
/**
|
|
138
224
|
* Retrieve a credential from the active vault backend.
|
|
139
225
|
*
|
|
140
226
|
* @param key - Logical key name (e.g. 'auth-token')
|
|
141
227
|
* @returns The stored value, or null if not found / backend unavailable
|
|
228
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar.
|
|
229
|
+
* Deliberately not `null`: "malformed" and "not stored" are different
|
|
230
|
+
* answers, and returning the not-found shape for the first is the silent
|
|
231
|
+
* degradation this path used to have.
|
|
142
232
|
*/
|
|
143
233
|
export async function getCredential(key) {
|
|
144
|
-
|
|
145
|
-
await runBeforeHooks({ type: "read", key }, (error) => ({
|
|
146
|
-
type: "credential_read_rejected",
|
|
147
|
-
timestamp: new Date().toISOString(),
|
|
148
|
-
backend: activeVaultType,
|
|
149
|
-
key,
|
|
150
|
-
error,
|
|
151
|
-
durationMs: performance.now() - start,
|
|
152
|
-
}));
|
|
153
|
-
let value;
|
|
154
|
-
try {
|
|
155
|
-
value = activeBackend.retrieve(key);
|
|
156
|
-
}
|
|
157
|
-
catch (err) {
|
|
158
|
-
runAfterHooks({
|
|
159
|
-
type: "credential_read_failed",
|
|
160
|
-
timestamp: new Date().toISOString(),
|
|
161
|
-
backend: activeVaultType,
|
|
162
|
-
key,
|
|
163
|
-
error: err instanceof Error ? err.message : String(err),
|
|
164
|
-
durationMs: performance.now() - start,
|
|
165
|
-
});
|
|
166
|
-
throw err;
|
|
167
|
-
}
|
|
168
|
-
if (value !== null)
|
|
169
|
-
touchSession();
|
|
170
|
-
runAfterHooks({
|
|
171
|
-
type: value !== null ? "credential_read" : "credential_read_missing",
|
|
172
|
-
timestamp: new Date().toISOString(),
|
|
173
|
-
backend: activeVaultType,
|
|
174
|
-
key,
|
|
175
|
-
durationMs: performance.now() - start,
|
|
176
|
-
});
|
|
177
|
-
return value;
|
|
234
|
+
return getDefaultVault().client.getCredential(key);
|
|
178
235
|
}
|
|
179
236
|
/**
|
|
180
237
|
* Delete a credential from the active vault backend.
|
|
181
238
|
*
|
|
182
239
|
* @param key - Logical key name (e.g. 'auth-token')
|
|
183
240
|
* @returns true on success (including "already deleted"), false on unexpected error
|
|
241
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar.
|
|
242
|
+
* Not reported as an idempotent success: such a key was never storable, so
|
|
243
|
+
* "already deleted" would be a claim the vault cannot make.
|
|
184
244
|
*/
|
|
185
245
|
export async function deleteCredential(key) {
|
|
186
|
-
|
|
187
|
-
await runBeforeHooks({ type: "delete", key }, (error) => ({
|
|
188
|
-
type: "credential_delete_rejected",
|
|
189
|
-
timestamp: new Date().toISOString(),
|
|
190
|
-
backend: activeVaultType,
|
|
191
|
-
key,
|
|
192
|
-
error,
|
|
193
|
-
durationMs: performance.now() - start,
|
|
194
|
-
}));
|
|
195
|
-
const success = activeBackend.delete(key);
|
|
196
|
-
runAfterHooks({
|
|
197
|
-
type: success ? "credential_deleted" : "credential_delete_failed",
|
|
198
|
-
timestamp: new Date().toISOString(),
|
|
199
|
-
backend: activeVaultType,
|
|
200
|
-
key,
|
|
201
|
-
durationMs: performance.now() - start,
|
|
202
|
-
});
|
|
203
|
-
return success;
|
|
246
|
+
return getDefaultVault().client.deleteCredential(key);
|
|
204
247
|
}
|
|
205
248
|
/**
|
|
206
249
|
* Enumerate credential keys in the active vault backend, optionally
|
|
@@ -216,7 +259,15 @@ export async function deleteCredential(key) {
|
|
|
216
259
|
* Note: credential keys must match `isValidKey` — lowercase alphanumeric
|
|
217
260
|
* plus hyphen and dot, first and last character alphanumeric, <=64 chars.
|
|
218
261
|
* Both `-` and `.` work as namespace separators; pick whichever convention
|
|
219
|
-
* reads best.
|
|
262
|
+
* reads best. **This is enforced, not merely documented** (#168): every
|
|
263
|
+
* function on this path rejects a non-conforming key before dispatching.
|
|
264
|
+
*
|
|
265
|
+
* A `prefix` is checked against `isValidKeyPrefix` rather than `isValidKey`,
|
|
266
|
+
* so it may end on a separator — `"soma.anthropic."` is the intended way to
|
|
267
|
+
* scope an enumeration to a namespace, and is not itself a valid key.
|
|
268
|
+
*
|
|
269
|
+
* @throws {InvalidCredentialKeyError} if `prefix` could not be the leading
|
|
270
|
+
* substring of any valid key.
|
|
220
271
|
*
|
|
221
272
|
* @example
|
|
222
273
|
* // Enumerate all soma-owned Anthropic credentials
|
|
@@ -227,40 +278,72 @@ export async function deleteCredential(key) {
|
|
|
227
278
|
* }
|
|
228
279
|
*/
|
|
229
280
|
export async function listCredentials(prefix) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
281
|
+
return getDefaultVault().client.listCredentials(prefix);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Probe one credential's state in a specific backend.
|
|
285
|
+
*
|
|
286
|
+
* Backends that implement `probe()` answer directly. For the rest this falls
|
|
287
|
+
* back to a `retrieve()`-based mapping — the value is discarded immediately
|
|
288
|
+
* and never returned — which yields `found`/`absent` honestly and `failed`
|
|
289
|
+
* when the backend threw. It never invents `locked`, because a backend that
|
|
290
|
+
* did not report one cannot be assumed to have one, and it never converts a
|
|
291
|
+
* throw into `absent`.
|
|
292
|
+
*
|
|
293
|
+
* Both paths answer readability, not mere presence: the fallback runs the real
|
|
294
|
+
* `retrieve()`, and an implementing backend is required to exercise the same
|
|
295
|
+
* access path it would for a read (see `VaultBackend.probe`). `found`
|
|
296
|
+
* therefore means the reader will get bytes.
|
|
297
|
+
*
|
|
298
|
+
* @throws {InvalidCredentialKeyError} if `key` does not match the grammar —
|
|
299
|
+
* the same rule every other vault entry point enforces (#168). Policy hooks
|
|
300
|
+
* are deliberately NOT run: a probe reads no value, so there is nothing for
|
|
301
|
+
* an access-control hook to allow or deny.
|
|
302
|
+
*/
|
|
303
|
+
export async function probeVaultBackendState(backend, type, key) {
|
|
304
|
+
assertValidKey(key, "read");
|
|
305
|
+
if (typeof backend.probe === "function") {
|
|
306
|
+
try {
|
|
307
|
+
return { layer: "value", backend: type, state: await backend.probe(key) };
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
return {
|
|
311
|
+
layer: "value",
|
|
312
|
+
backend: type,
|
|
313
|
+
state: {
|
|
314
|
+
kind: "failed",
|
|
315
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
}
|
|
240
320
|
try {
|
|
241
|
-
|
|
321
|
+
const value = await backend.retrieve(key);
|
|
322
|
+
return {
|
|
323
|
+
layer: "value",
|
|
324
|
+
backend: type,
|
|
325
|
+
state: value !== null ? { kind: "found" } : { kind: "absent" },
|
|
326
|
+
};
|
|
242
327
|
}
|
|
243
328
|
catch (err) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
throw err;
|
|
329
|
+
return {
|
|
330
|
+
layer: "value",
|
|
331
|
+
backend: type,
|
|
332
|
+
state: {
|
|
333
|
+
kind: "failed",
|
|
334
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
335
|
+
},
|
|
336
|
+
};
|
|
253
337
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return keys;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Probe one credential's state in the backend this process actually uses.
|
|
341
|
+
*
|
|
342
|
+
* The value-layer half of the two-layer probe; see `probeKeyProviderState()`
|
|
343
|
+
* for the vault master key.
|
|
344
|
+
*/
|
|
345
|
+
export async function probeBackendState(key) {
|
|
346
|
+
const { backend, type } = getDefaultVault();
|
|
347
|
+
return probeVaultBackendState(backend, type, key);
|
|
265
348
|
}
|
|
266
349
|
//# sourceMappingURL=vault.js.map
|