@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.
Files changed (152) hide show
  1. package/README.md +424 -8
  2. package/dist/audit/hmac-chain.d.ts +117 -0
  3. package/dist/audit/hmac-chain.d.ts.map +1 -0
  4. package/dist/audit/hmac-chain.js +811 -0
  5. package/dist/audit/hmac-chain.js.map +1 -0
  6. package/dist/audit/ocsf.d.ts +108 -0
  7. package/dist/audit/ocsf.d.ts.map +1 -0
  8. package/dist/audit/ocsf.js +204 -0
  9. package/dist/audit/ocsf.js.map +1 -0
  10. package/dist/cli/hidden-prompt.d.ts.map +1 -1
  11. package/dist/cli/hidden-prompt.js +55 -10
  12. package/dist/cli/hidden-prompt.js.map +1 -1
  13. package/dist/cli/messages.d.ts +40 -8
  14. package/dist/cli/messages.d.ts.map +1 -1
  15. package/dist/cli/messages.js +34 -8
  16. package/dist/cli/messages.js.map +1 -1
  17. package/dist/cli/secrets-cli.d.ts.map +1 -1
  18. package/dist/cli/secrets-cli.js +191 -32
  19. package/dist/cli/secrets-cli.js.map +1 -1
  20. package/dist/client.d.ts +26 -0
  21. package/dist/client.d.ts.map +1 -0
  22. package/dist/client.js +129 -0
  23. package/dist/client.js.map +1 -0
  24. package/dist/compatibility.d.ts +199 -0
  25. package/dist/compatibility.d.ts.map +1 -0
  26. package/dist/compatibility.js +419 -0
  27. package/dist/compatibility.js.map +1 -0
  28. package/dist/crypto/darwin-keychain.d.ts +394 -0
  29. package/dist/crypto/darwin-keychain.d.ts.map +1 -0
  30. package/dist/crypto/darwin-keychain.js +793 -0
  31. package/dist/crypto/darwin-keychain.js.map +1 -0
  32. package/dist/crypto/vault-common.d.ts +55 -12
  33. package/dist/crypto/vault-common.d.ts.map +1 -1
  34. package/dist/crypto/vault-common.js +74 -71
  35. package/dist/crypto/vault-common.js.map +1 -1
  36. package/dist/environment/EnvironmentManager.d.ts.map +1 -1
  37. package/dist/environment/EnvironmentManager.js +5 -10
  38. package/dist/environment/EnvironmentManager.js.map +1 -1
  39. package/dist/index.d.ts +37 -9
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +38 -6
  42. package/dist/index.js.map +1 -1
  43. package/dist/key-providers/keychain-provider.d.ts +30 -2
  44. package/dist/key-providers/keychain-provider.d.ts.map +1 -1
  45. package/dist/key-providers/keychain-provider.js +29 -5
  46. package/dist/key-providers/keychain-provider.js.map +1 -1
  47. package/dist/key-providers/onepassword-provider.d.ts +65 -5
  48. package/dist/key-providers/onepassword-provider.d.ts.map +1 -1
  49. package/dist/key-providers/onepassword-provider.js +159 -67
  50. package/dist/key-providers/onepassword-provider.js.map +1 -1
  51. package/dist/key-providers/op-cli.d.ts +78 -0
  52. package/dist/key-providers/op-cli.d.ts.map +1 -0
  53. package/dist/key-providers/op-cli.js +123 -0
  54. package/dist/key-providers/op-cli.js.map +1 -0
  55. package/dist/key-providers/passphrase-provider.d.ts +20 -0
  56. package/dist/key-providers/passphrase-provider.d.ts.map +1 -1
  57. package/dist/key-providers/passphrase-provider.js +49 -0
  58. package/dist/key-providers/passphrase-provider.js.map +1 -1
  59. package/dist/key-providers/probe.d.ts +46 -0
  60. package/dist/key-providers/probe.d.ts.map +1 -0
  61. package/dist/key-providers/probe.js +70 -0
  62. package/dist/key-providers/probe.js.map +1 -0
  63. package/dist/key-providers/types.d.ts +51 -1
  64. package/dist/key-providers/types.d.ts.map +1 -1
  65. package/dist/platform/agent-detect.d.ts +39 -3
  66. package/dist/platform/agent-detect.d.ts.map +1 -1
  67. package/dist/platform/agent-detect.js +55 -9
  68. package/dist/platform/agent-detect.js.map +1 -1
  69. package/dist/platform/session-context.d.ts +77 -0
  70. package/dist/platform/session-context.d.ts.map +1 -0
  71. package/dist/platform/session-context.js +83 -0
  72. package/dist/platform/session-context.js.map +1 -0
  73. package/dist/policies/audit-trail.d.ts +25 -0
  74. package/dist/policies/audit-trail.d.ts.map +1 -0
  75. package/dist/policies/audit-trail.js +31 -0
  76. package/dist/policies/audit-trail.js.map +1 -0
  77. package/dist/secret-state.d.ts +54 -0
  78. package/dist/secret-state.d.ts.map +1 -0
  79. package/dist/secret-state.js +2 -0
  80. package/dist/secret-state.js.map +1 -0
  81. package/dist/sinks/index.d.ts +9 -0
  82. package/dist/sinks/index.d.ts.map +1 -0
  83. package/dist/sinks/index.js +5 -0
  84. package/dist/sinks/index.js.map +1 -0
  85. package/dist/sinks/jsonl.d.ts +16 -0
  86. package/dist/sinks/jsonl.d.ts.map +1 -0
  87. package/dist/sinks/jsonl.js +51 -0
  88. package/dist/sinks/jsonl.js.map +1 -0
  89. package/dist/sinks/otel.d.ts +22 -0
  90. package/dist/sinks/otel.d.ts.map +1 -0
  91. package/dist/sinks/otel.js +155 -0
  92. package/dist/sinks/otel.js.map +1 -0
  93. package/dist/sinks/queue.d.ts +12 -0
  94. package/dist/sinks/queue.d.ts.map +1 -0
  95. package/dist/sinks/queue.js +89 -0
  96. package/dist/sinks/queue.js.map +1 -0
  97. package/dist/sinks/syslog.d.ts +17 -0
  98. package/dist/sinks/syslog.d.ts.map +1 -0
  99. package/dist/sinks/syslog.js +103 -0
  100. package/dist/sinks/syslog.js.map +1 -0
  101. package/dist/sinks/types.d.ts +27 -0
  102. package/dist/sinks/types.d.ts.map +1 -0
  103. package/dist/sinks/types.js +18 -0
  104. package/dist/sinks/types.js.map +1 -0
  105. package/dist/vault/policy.d.ts +64 -34
  106. package/dist/vault/policy.d.ts.map +1 -1
  107. package/dist/vault/policy.js +109 -67
  108. package/dist/vault/policy.js.map +1 -1
  109. package/dist/vault/session-vault-errors.d.ts +72 -4
  110. package/dist/vault/session-vault-errors.d.ts.map +1 -1
  111. package/dist/vault/session-vault-errors.js +95 -4
  112. package/dist/vault/session-vault-errors.js.map +1 -1
  113. package/dist/vault/session-vault.d.ts +145 -2
  114. package/dist/vault/session-vault.d.ts.map +1 -1
  115. package/dist/vault/session-vault.js +548 -72
  116. package/dist/vault/session-vault.js.map +1 -1
  117. package/dist/vault/sidecar.d.ts +9 -0
  118. package/dist/vault/sidecar.d.ts.map +1 -1
  119. package/dist/vault/sidecar.js +72 -3
  120. package/dist/vault/sidecar.js.map +1 -1
  121. package/dist/vault/types.d.ts +58 -10
  122. package/dist/vault/types.d.ts.map +1 -1
  123. package/dist/vault/types.js.map +1 -1
  124. package/dist/vault/vault-env.d.ts +43 -50
  125. package/dist/vault/vault-env.d.ts.map +1 -1
  126. package/dist/vault/vault-env.js +141 -62
  127. package/dist/vault/vault-env.js.map +1 -1
  128. package/dist/vault/vault-gpg.d.ts +6 -1
  129. package/dist/vault/vault-gpg.d.ts.map +1 -1
  130. package/dist/vault/vault-gpg.js +10 -8
  131. package/dist/vault/vault-gpg.js.map +1 -1
  132. package/dist/vault/vault-libsecret.d.ts +6 -1
  133. package/dist/vault/vault-libsecret.d.ts.map +1 -1
  134. package/dist/vault/vault-libsecret.js +16 -14
  135. package/dist/vault/vault-libsecret.js.map +1 -1
  136. package/dist/vault/vault-onepassword.d.ts +119 -0
  137. package/dist/vault/vault-onepassword.d.ts.map +1 -0
  138. package/dist/vault/vault-onepassword.js +271 -0
  139. package/dist/vault/vault-onepassword.js.map +1 -0
  140. package/dist/vault/vault-utils.d.ts +37 -3
  141. package/dist/vault/vault-utils.d.ts.map +1 -1
  142. package/dist/vault/vault-utils.js +65 -3
  143. package/dist/vault/vault-utils.js.map +1 -1
  144. package/dist/vault/vault-windows.d.ts +7 -2
  145. package/dist/vault/vault-windows.d.ts.map +1 -1
  146. package/dist/vault/vault-windows.js +21 -16
  147. package/dist/vault/vault-windows.js.map +1 -1
  148. package/dist/vault/vault.d.ts +120 -9
  149. package/dist/vault/vault.d.ts.map +1 -1
  150. package/dist/vault/vault.js +222 -139
  151. package/dist/vault/vault.js.map +1 -1
  152. package/package.json +8 -2
package/dist/index.js CHANGED
@@ -2,28 +2,60 @@
2
2
  export { encrypt, decrypt, encryptObject, decryptObject } from "./crypto/vault-common.js";
3
3
  export { ALGORITHM, IV_LENGTH, AUTH_TAG_LENGTH, KEY_LENGTH } from "./crypto/vault-common.js";
4
4
  // Credential vault
5
- export { storeCredential, getCredential, deleteCredential, listCredentials, getActiveVaultType, isSessionValid } from "./vault/vault.js";
5
+ export { storeCredential, getCredential, deleteCredential, listCredentials, getActiveVaultType, isSessionValid, KeychainVault, AUTH_KEYCHAIN_SERVICE } from "./vault/vault.js";
6
+ export { EnvVault, ENV_VAULT_PREFIX, credentialKeyToEnvName, } from "./vault/vault-env.js";
7
+ export { createSecretsClient } from "./client.js";
8
+ export { probeBackendState, probeVaultBackendState } from "./vault/vault.js";
9
+ export { probeKeyProviderState, probeKeyProvider } from "./key-providers/probe.js";
10
+ // Compatibility floor (#214) — the provider-published list of behavioural gaps
11
+ // an OLD version of this package silently has, so a consumer's `doctor` can
12
+ // grade its own installed version. Pure, total, advisory: nothing here runs at
13
+ // import, nothing throws, and no vault path consults it. A graded floor, never
14
+ // a boot-time refusal.
15
+ export { SECRETS_PACKAGE_VERSION, MIN_ASSESSABLE_VERSION, COMPATIBILITY_FLOOR, assessCompatibility, assessPin, lowestVersionInRange, } from "./compatibility.js";
6
16
  // Platform detection
7
17
  export { isTTY, canUnicode, isHeadless, canLaunchBrowser, isCIEnvironment, isDockerContainer, isSSHSession } from "./platform/platform.js";
8
18
  export { isAgentEnvironment } from "./platform/agent-detect.js";
19
+ // Session-context detection (#188) — session vs sessionless, NOT platform.
20
+ // A launchd system-domain daemon and an SSH login have no security session:
21
+ // no consent UI can render, and the keychain search list cannot be trusted.
22
+ export { detectSessionContext, isSessionlessContext, SESSION_CONTEXT_OVERRIDE_ENV } from "./platform/session-context.js";
23
+ // Hardened macOS Keychain core (#188) — the single place in this package that
24
+ // spawns `security`. Discriminated results throughout; explicit-target reads
25
+ // in a sessionless context; `-U` replace-in-place and `-T /usr/bin/security`
26
+ // reader preauthorization on every write.
27
+ export { SYSTEM_KEYCHAIN_PATH, SECURITY_BINARY, readKeychainCredential, readSystemKeychainCredential, readSearchListCredential, writeKeychainCredential, writeSystemKeychainCredential, writeDefaultKeychainCredential, deleteKeychainCredential, storedWithinReaderReach,
28
+ // Credential STATE (readability — runs the reader's own read, discards the
29
+ // value). The `probe*Entry` trio below answers PRESENCE only and must not be
30
+ // used as credential state.
31
+ probeKeychainCredentialState, probeKeychainEntry, probeSystemKeychainEntry, probeSearchListEntry, migrateLoginCredentialToSystem, keychainSearchList, privilegedWriteCommand, shellQuote, classifyKeychainRead, toSecretState, dumpKeychain, } from "./crypto/darwin-keychain.js";
9
32
  // Environment management
10
33
  export { getEnvironmentManager, EnvironmentManager } from "./environment/EnvironmentManager.js";
11
34
  // CLI
12
35
  export { runSecrets } from "./cli/secrets-cli.js";
36
+ // Auth CLI message catalog — public so a consuming CLI imports it instead of
37
+ // forking a copy that drifts (#217 C6-34). `./cli/messages.ts` states its scope.
38
+ export { AUTH_MESSAGES } from "./cli/messages.js";
13
39
  // Key storage helpers (legacy — prefer key-providers for vault key access)
14
40
  export { getKeyFromKeychain, storeKeyInKeychain, storeStringInKeychain, getStringFromKeychain, deleteFromKeychain } from "./crypto/vault-common.js";
15
41
  export { KeychainProvider, DEFAULT_KEYCHAIN_SERVICE, DEFAULT_KEYCHAIN_ACCOUNT, } from "./key-providers/keychain-provider.js";
16
42
  export { OnePasswordProvider } from "./key-providers/onepassword-provider.js";
43
+ export { detectOpCli, runOp, OpCliError, OP_PROBE_TIMEOUT_MS, OP_READ_TIMEOUT_MS, OP_WRITE_TIMEOUT_MS } from "./key-providers/op-cli.js";
44
+ export { OnePasswordVault, DEFAULT_OP_TAG, OP_LIST_CACHE_TTL_MS } from "./vault/vault-onepassword.js";
17
45
  export { PassphraseProvider, DEFAULT_PASSPHRASE_KDF_PARAMS, DEFAULT_PASSPHRASE_VAULT_PATH, PASSPHRASE_KDF, PASSPHRASE_METADATA_VERSION, PASSPHRASE_SALT_LENGTH, PASSPHRASE_VERIFIER_ALGORITHM, PASSPHRASE_VERIFIER_CONTEXT, derivePassphraseKey, passphraseMetadataPathForVault, } from "./key-providers/passphrase-provider.js";
18
46
  export { resolveKeyProvider, getProviderByType, loadConfig, saveSecretsConfig } from "./key-providers/resolve.js";
19
- // Validation
20
- export { isValidKey } from "./vault/vault-utils.js";
47
+ // Validation — the credential-key grammar, enforced on every vault path (#168).
48
+ // `InvalidCredentialKeyError` is re-exported from the VaultError block below.
49
+ export { isValidKey, isValidKeyPrefix, assertValidKey, assertValidKeyPrefix, } from "./vault/vault-utils.js";
21
50
  // Policy
22
- export { setSecretsPolicies, getActivePolicies, auditTrail, rejectedEventType } from "./vault/policy.js";
51
+ export { setSecretsPolicies, getActivePolicies, rejectedEventType } from "./vault/policy.js";
52
+ export { auditTrail } from "./policies/audit-trail.js";
53
+ export { OCSF_SCHEMA_VERSION, OCSF_IAM_CATEGORY_UID, OCSF_ENTITY_MANAGEMENT_CLASS_UID, toCredentialAuditEvent, } from "./audit/ocsf.js";
54
+ export { AuditChainError, canonicalizeAuditEvent, createHmacAuditChain, verifyHmacAuditChain, } from "./audit/hmac-chain.js";
23
55
  // Session-backed vault (envelope encryption, single unlock per session)
24
56
  // Recommended for long-running processes (daemons) holding N credentials;
25
57
  // supersedes per-item `getCredential` calls for those consumers. See
26
58
  // packages/secrets/docs/session-vault.md and issue #40 for the threat model.
27
- export { openVault, VAULT_SCHEMA_VERSION, VAULT_AAD_PREFIX, DEFAULT_VAULT_PATH, DEFAULT_SIDECAR_PATH } from "./vault/session-vault.js";
28
- export { VaultError, VaultUnlockError, VaultDecryptError, VaultRollbackError, VaultClosedError, VaultLockError, } from "./vault/session-vault.js";
59
+ export { createVault, openVault, rekeyVault, VAULT_SCHEMA_VERSION, VAULT_AAD_PREFIX, DEFAULT_VAULT_PATH, DEFAULT_SIDECAR_PATH } from "./vault/session-vault.js";
60
+ export { VaultError, VaultUnlockError, VaultDecryptError, VaultRollbackError, VaultClosedError, VaultLockError, VaultRestoreError, InvalidCredentialKeyError, } from "./vault/session-vault.js";
29
61
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE7F,mBAAmB;AACnB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGzI,qBAAqB;AACrB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3I,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,yBAAyB;AACzB,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEhG,MAAM;AACN,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,2EAA2E;AAC3E,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAIpJ,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,6BAA6B,EAC7B,cAAc,EACd,2BAA2B,EAC3B,sBAAsB,EACtB,6BAA6B,EAC7B,2BAA2B,EAC3B,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,wCAAwC,CAAC;AAOhD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGlH,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,SAAS;AACT,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGzG,wEAAwE;AACxE,0EAA0E;AAC1E,qEAAqE;AACrE,6EAA6E;AAC7E,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACvI,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,22 @@
1
1
  /**
2
2
  * Key Provider — macOS Keychain
3
3
  *
4
- * Wraps the existing getKeyFromKeychain / storeKeyInKeychain functions
5
- * from vault-common.ts as a KeyProvider implementation.
4
+ * Wraps the getKeyFromKeychain / storeKeyInKeychain functions from
5
+ * vault-common.ts as a KeyProvider implementation. Those in turn delegate to
6
+ * the hardened `security` core in `crypto/darwin-keychain.ts` (#188), so the
7
+ * vault MASTER KEY inherits the same posture as credential values: explicit
8
+ * System-keychain reads in a sessionless context, `-U` replace-in-place
9
+ * writes, and `-T /usr/bin/security` reader preauthorization.
10
+ *
11
+ * Fixing only the value layer would have been half a fix — the master key
12
+ * would have become unreadable in exactly the contexts the values had just
13
+ * become readable in.
6
14
  *
7
15
  * Only available on macOS (darwin). Uses the `security` CLI to interact
8
16
  * with the system Keychain, which prompts for Touch ID or system password.
9
17
  */
18
+ import type { KeychainDeps } from "../crypto/darwin-keychain.js";
19
+ import type { SecretState } from "../secret-state.js";
10
20
  import type { KeyProvider, KeyProviderType } from "./types.js";
11
21
  /**
12
22
  * Default Keychain item coordinates. These are the historical values every
@@ -29,11 +39,18 @@ export interface KeychainProviderOptions {
29
39
  service?: string;
30
40
  /** Keychain account name. Defaults to {@link DEFAULT_KEYCHAIN_ACCOUNT}. */
31
41
  account?: string;
42
+ /**
43
+ * Injection seam for the `security` CLI and the platform/environment that
44
+ * decide the read path (#188). Omitted in production; supplied by tests so
45
+ * the exact argv is assertable without touching a real keychain.
46
+ */
47
+ deps?: Partial<KeychainDeps>;
32
48
  }
33
49
  export declare class KeychainProvider implements KeyProvider {
34
50
  readonly name: KeyProviderType;
35
51
  private readonly service;
36
52
  private readonly account;
53
+ private readonly deps;
37
54
  /**
38
55
  * @param options - Optional per-consumer Keychain item coordinates. With no
39
56
  * options the provider targets the historical `centient-vault`/`vault-key`
@@ -45,5 +62,16 @@ export declare class KeychainProvider implements KeyProvider {
45
62
  getKey(): Buffer | null;
46
63
  storeKey(key: Buffer): boolean;
47
64
  deleteKey(): boolean;
65
+ /**
66
+ * The five-way state of the vault master key, value-free (#188).
67
+ *
68
+ * Runs the SAME read {@link getKey} would run in this context, then discards
69
+ * the key and returns only the value-free {@link SecretState}. A
70
+ * metadata-only lookup would answer presence, not readability — and a key
71
+ * that is present but sits behind an ACL this context cannot satisfy is
72
+ * exactly the case a caller needs told apart from "no key stored". `found`
73
+ * here means the reader will get bytes.
74
+ */
75
+ probeKey(): SecretState;
48
76
  }
49
77
  //# sourceMappingURL=keychain-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keychain-provider.d.ts","sourceRoot":"","sources":["../../src/key-providers/keychain-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM/D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,wBAAwB,cAAc,CAAC;AAMpD;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAMD,qBAAa,gBAAiB,YAAW,WAAW;IAClD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAc;IAE5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC;;;;OAIG;gBACS,OAAO,GAAE,uBAA4B;IAKjD,wCAAwC;IACxC,MAAM,CAAC,MAAM,IAAI,OAAO;IAIxB,MAAM,IAAI,MAAM,GAAG,IAAI;IAIvB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI9B,SAAS,IAAI,OAAO;CAGrB"}
1
+ {"version":3,"file":"keychain-provider.d.ts","sourceRoot":"","sources":["../../src/key-providers/keychain-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM/D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,wBAAwB,cAAc,CAAC;AAMpD;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9B;AAMD,qBAAa,gBAAiB,YAAW,WAAW;IAClD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAc;IAE5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAwB;IAE7C;;;;OAIG;gBACS,OAAO,GAAE,uBAA4B;IAMjD,wCAAwC;IACxC,MAAM,CAAC,MAAM,IAAI,OAAO;IAIxB,MAAM,IAAI,MAAM,GAAG,IAAI;IAIvB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI9B,SAAS,IAAI,OAAO;IAIpB;;;;;;;;;OASG;IACH,QAAQ,IAAI,WAAW;CAGxB"}
@@ -1,13 +1,22 @@
1
1
  /**
2
2
  * Key Provider — macOS Keychain
3
3
  *
4
- * Wraps the existing getKeyFromKeychain / storeKeyInKeychain functions
5
- * from vault-common.ts as a KeyProvider implementation.
4
+ * Wraps the getKeyFromKeychain / storeKeyInKeychain functions from
5
+ * vault-common.ts as a KeyProvider implementation. Those in turn delegate to
6
+ * the hardened `security` core in `crypto/darwin-keychain.ts` (#188), so the
7
+ * vault MASTER KEY inherits the same posture as credential values: explicit
8
+ * System-keychain reads in a sessionless context, `-U` replace-in-place
9
+ * writes, and `-T /usr/bin/security` reader preauthorization.
10
+ *
11
+ * Fixing only the value layer would have been half a fix — the master key
12
+ * would have become unreadable in exactly the contexts the values had just
13
+ * become readable in.
6
14
  *
7
15
  * Only available on macOS (darwin). Uses the `security` CLI to interact
8
16
  * with the system Keychain, which prompts for Touch ID or system password.
9
17
  */
10
18
  import { getKeyFromKeychain, storeKeyInKeychain, deleteFromKeychain, } from "../crypto/vault-common.js";
19
+ import { probeKeychainCredentialState } from "../crypto/darwin-keychain.js";
11
20
  // =============================================================================
12
21
  // Constants
13
22
  // =============================================================================
@@ -25,6 +34,7 @@ export class KeychainProvider {
25
34
  name = "keychain";
26
35
  service;
27
36
  account;
37
+ deps;
28
38
  /**
29
39
  * @param options - Optional per-consumer Keychain item coordinates. With no
30
40
  * options the provider targets the historical `centient-vault`/`vault-key`
@@ -33,19 +43,33 @@ export class KeychainProvider {
33
43
  constructor(options = {}) {
34
44
  this.service = options.service ?? DEFAULT_KEYCHAIN_SERVICE;
35
45
  this.account = options.account ?? DEFAULT_KEYCHAIN_ACCOUNT;
46
+ this.deps = options.deps ?? {};
36
47
  }
37
48
  /** Returns true if running on macOS. */
38
49
  static detect() {
39
50
  return process.platform === "darwin";
40
51
  }
41
52
  getKey() {
42
- return getKeyFromKeychain(this.service, this.account);
53
+ return getKeyFromKeychain(this.service, this.account, this.deps);
43
54
  }
44
55
  storeKey(key) {
45
- return storeKeyInKeychain(this.service, this.account, key);
56
+ return storeKeyInKeychain(this.service, this.account, key, this.deps);
46
57
  }
47
58
  deleteKey() {
48
- return deleteFromKeychain(this.service, this.account);
59
+ return deleteFromKeychain(this.service, this.account, this.deps);
60
+ }
61
+ /**
62
+ * The five-way state of the vault master key, value-free (#188).
63
+ *
64
+ * Runs the SAME read {@link getKey} would run in this context, then discards
65
+ * the key and returns only the value-free {@link SecretState}. A
66
+ * metadata-only lookup would answer presence, not readability — and a key
67
+ * that is present but sits behind an ACL this context cannot satisfy is
68
+ * exactly the case a caller needs told apart from "no key stored". `found`
69
+ * here means the reader will get bytes.
70
+ */
71
+ probeKey() {
72
+ return probeKeychainCredentialState(this.service, this.account, this.deps);
49
73
  }
50
74
  }
51
75
  //# sourceMappingURL=keychain-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keychain-provider.js","sourceRoot":"","sources":["../../src/key-providers/keychain-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AAGnC,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,gBAAgB,CAAC;AACzD,MAAM,CAAC,MAAM,wBAAwB,GAAG,WAAW,CAAC;AAsBpD,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAoB,UAAU,CAAC;IAE3B,OAAO,CAAS;IAChB,OAAO,CAAS;IAEjC;;;;OAIG;IACH,YAAY,UAAmC,EAAE;QAC/C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC;QAC3D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC;IAC7D,CAAC;IAED,wCAAwC;IACxC,MAAM,CAAC,MAAM;QACX,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACvC,CAAC;IAED,MAAM;QACJ,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,QAAQ,CAAC,GAAW;QAClB,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7D,CAAC;IAED,SAAS;QACP,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;CACF"}
1
+ {"version":3,"file":"keychain-provider.js","sourceRoot":"","sources":["../../src/key-providers/keychain-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAK5E,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,gBAAgB,CAAC;AACzD,MAAM,CAAC,MAAM,wBAAwB,GAAG,WAAW,CAAC;AA4BpD,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAoB,UAAU,CAAC;IAE3B,OAAO,CAAS;IAChB,OAAO,CAAS;IAChB,IAAI,CAAwB;IAE7C;;;;OAIG;IACH,YAAY,UAAmC,EAAE;QAC/C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC;QAC3D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAwB,CAAC;QAC3D,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,wCAAwC;IACxC,MAAM,CAAC,MAAM;QACX,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACvC,CAAC;IAED,MAAM;QACJ,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC;IAED,QAAQ,CAAC,GAAW;QAClB,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxE,CAAC;IAED,SAAS;QACP,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC;IAED;;;;;;;;;OASG;IACH,QAAQ;QACN,OAAO,4BAA4B,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7E,CAAC;CACF"}
@@ -9,9 +9,21 @@
9
9
  * 3. CLI session — user ran `op signin` (OP_SESSION_* env var)
10
10
  *
11
11
  * The `op` CLI handles auth selection internally; this provider just
12
- * shells out to `op read` / `op item create` / `op item edit`.
12
+ * shells out to `op read` / `op item create` through the shared `op-cli.ts`
13
+ * helper (ADR-004 §6), which it co-owns with the credential-value backend
14
+ * `OnePasswordVault`.
13
15
  *
14
- * No dependency on @1password/sdk — uses execFileSync only.
16
+ * No dependency on @1password/sdk — `execFileSync` only.
17
+ *
18
+ * **Key material never reaches argv (#102).** `storeKey` builds the item JSON
19
+ * in-process and pipes it to `op item create -` via `runOp`'s `input` option —
20
+ * the argv-safe seam ADR-004 §4 specifies and `OnePasswordVault.store` already
21
+ * uses. Nothing readable in `ps` / `/proc/<pid>/cmdline` carries the key. This
22
+ * closes ADR-001's "Process argument visibility" negative, which had the hex
23
+ * key in a `password=<hex>` argv element for the life of the call.
24
+ *
25
+ * `getKey` uses `op read`, whose only argv is a non-secret `op://` reference —
26
+ * the value comes back on stdout, so that path was never exposed.
15
27
  */
16
28
  import type { KeyProvider, KeyProviderType, OnePasswordConfig } from "./types.js";
17
29
  export declare class OnePasswordProvider implements KeyProvider {
@@ -29,10 +41,58 @@ export declare class OnePasswordProvider implements KeyProvider {
29
41
  */
30
42
  static detect(): boolean;
31
43
  getKey(): Buffer | null;
44
+ /**
45
+ * Store the vault key. Overwrites any existing item.
46
+ *
47
+ * The hex travels on **stdin** inside an item template and never appears in
48
+ * argv (#102): the template goes to `op item create -` through `runOp`'s
49
+ * `input` option, the argv-safe seam ADR-004 §4 specifies. Item ids, titles
50
+ * and vault names are not secret and stay on the command line.
51
+ *
52
+ * ## Ordering: create first, delete the old item last
53
+ *
54
+ * `op item edit` has no stdin template form, so the overwrite cannot be an
55
+ * edit-in-place without putting `password=<hex>` back in argv. The write is
56
+ * therefore a replace — but a **non-destructive** one, sequenced so no window
57
+ * exists in which the master key is absent from 1Password:
58
+ *
59
+ * 1. Resolve the existing item's id (absent ⇒ plain create, no step 3).
60
+ * 2. Create the replacement under the **same canonical title** — `op`
61
+ * permits duplicate titles — and capture the new item's id.
62
+ * Create fails ⇒ the old item is untouched and this returns false.
63
+ * 3. Delete the **old** item by id. Delete fails ⇒ roll back by deleting
64
+ * the **new** item by id, leaving the old one in place, and return false.
65
+ *
66
+ * The key is only ever removed from 1Password after its replacement durably
67
+ * exists. Nothing here renames, so there is no window where a rename failure
68
+ * strands the item under a title `getKey` cannot read.
69
+ *
70
+ * **Residual window (double failure).** If step 3's delete fails *and* the
71
+ * rollback delete of the new item also fails, both items remain and this
72
+ * returns false. That is not a loss: no key is destroyed, and {@link getKey}
73
+ * does not silently pick one — `op read` on an ambiguous title fails, so the
74
+ * caller gets a loud failure rather than a wrong key. The operator resolves
75
+ * it by deleting whichever item is stale.
76
+ */
32
77
  storeKey(key: Buffer): boolean;
33
78
  deleteKey(): boolean;
34
- private itemExists;
35
- private createItem;
36
- private updateItem;
79
+ /**
80
+ * The id of the existing key item, or null when there is none.
81
+ *
82
+ * @throws when 1Password cannot be asked, or answers with an item whose id
83
+ * we cannot read. Both are "unknown", not "absent" — and {@link storeKey}
84
+ * must not treat unknown as absent, or a transient read failure would end
85
+ * with two items under one title.
86
+ */
87
+ private findItemId;
88
+ /**
89
+ * Delete an item by id or title, treating "no such item" as the desired end
90
+ * state.
91
+ *
92
+ * Unlike {@link deleteKey}, an auth or network failure is **rethrown** — the
93
+ * {@link storeKey} path needs to distinguish "the old item is gone" from
94
+ * "we could not remove it", because only the second case must roll back.
95
+ */
96
+ private deleteItem;
37
97
  }
38
98
  //# sourceMappingURL=onepassword-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"onepassword-provider.d.ts","sourceRoot":"","sources":["../../src/key-providers/onepassword-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAclF,qBAAa,mBAAoB,YAAW,WAAW;IACrD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,MAAM,CAAC,EAAE,iBAAiB;IAKtC;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,IAAI,OAAO;IA8BxB,MAAM,IAAI,MAAM,GAAG,IAAI;IAkBvB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAU9B,SAAS,IAAI,OAAO;IAkBpB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,UAAU;IAmBlB,OAAO,CAAC,UAAU;CAgBnB"}
1
+ {"version":3,"file":"onepassword-provider.d.ts","sourceRoot":"","sources":["../../src/key-providers/onepassword-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAqBlF,qBAAa,mBAAoB,YAAW,WAAW;IACrD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,MAAM,CAAC,EAAE,iBAAiB;IAKtC;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,IAAI,OAAO;IAIxB,MAAM,IAAI,MAAM,GAAG,IAAI;IAcvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAsD9B,SAAS,IAAI,OAAO;IAcpB;;;;;;;OAOG;IACH,OAAO,CAAC,UAAU;IAsBlB;;;;;;;OAOG;IACH,OAAO,CAAC,UAAU;CAUnB"}
@@ -9,11 +9,23 @@
9
9
  * 3. CLI session — user ran `op signin` (OP_SESSION_* env var)
10
10
  *
11
11
  * The `op` CLI handles auth selection internally; this provider just
12
- * shells out to `op read` / `op item create` / `op item edit`.
12
+ * shells out to `op read` / `op item create` through the shared `op-cli.ts`
13
+ * helper (ADR-004 §6), which it co-owns with the credential-value backend
14
+ * `OnePasswordVault`.
13
15
  *
14
- * No dependency on @1password/sdk — uses execFileSync only.
16
+ * No dependency on @1password/sdk — `execFileSync` only.
17
+ *
18
+ * **Key material never reaches argv (#102).** `storeKey` builds the item JSON
19
+ * in-process and pipes it to `op item create -` via `runOp`'s `input` option —
20
+ * the argv-safe seam ADR-004 §4 specifies and `OnePasswordVault.store` already
21
+ * uses. Nothing readable in `ps` / `/proc/<pid>/cmdline` carries the key. This
22
+ * closes ADR-001's "Process argument visibility" negative, which had the hex
23
+ * key in a `password=<hex>` argv element for the life of the call.
24
+ *
25
+ * `getKey` uses `op read`, whose only argv is a non-secret `op://` reference —
26
+ * the value comes back on stdout, so that path was never exposed.
15
27
  */
16
- import { execFileSync } from "child_process";
28
+ import { detectOpCli, runOp, OpCliError, OP_READ_TIMEOUT_MS, OP_WRITE_TIMEOUT_MS, } from "./op-cli.js";
17
29
  // =============================================================================
18
30
  // Defaults
19
31
  // =============================================================================
@@ -40,38 +52,12 @@ export class OnePasswordProvider {
40
52
  * is configured (desktop app / prior sign-in).
41
53
  */
42
54
  static detect() {
43
- // Check op binary exists
44
- try {
45
- execFileSync("op", ["--version"], {
46
- stdio: ["pipe", "pipe", "pipe"],
47
- timeout: 5000,
48
- });
49
- }
50
- catch {
51
- return false;
52
- }
53
- // Service account mode — no further checks needed
54
- if (process.env.OP_SERVICE_ACCOUNT_TOKEN) {
55
- return true;
56
- }
57
- // Interactive mode — check for configured accounts
58
- try {
59
- const output = execFileSync("op", ["account", "list", "--format=json"], { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000 }).trim();
60
- // Returns "[]" when no accounts are configured
61
- return output !== "[]" && output.length > 2;
62
- }
63
- catch {
64
- return false;
65
- }
55
+ return detectOpCli();
66
56
  }
67
57
  getKey() {
68
58
  try {
69
59
  const ref = `op://${this.vault}/${this.item}/${FIELD_NAME}`;
70
- const result = execFileSync("op", ["read", ref], {
71
- encoding: "utf8",
72
- stdio: ["pipe", "pipe", "pipe"],
73
- timeout: 30000,
74
- }).trim();
60
+ const result = runOp(["read", ref], { timeoutMs: OP_WRITE_TIMEOUT_MS });
75
61
  if (!result)
76
62
  return null;
77
63
  const buf = Buffer.from(result, "hex");
@@ -84,63 +70,169 @@ export class OnePasswordProvider {
84
70
  return null;
85
71
  }
86
72
  }
73
+ /**
74
+ * Store the vault key. Overwrites any existing item.
75
+ *
76
+ * The hex travels on **stdin** inside an item template and never appears in
77
+ * argv (#102): the template goes to `op item create -` through `runOp`'s
78
+ * `input` option, the argv-safe seam ADR-004 §4 specifies. Item ids, titles
79
+ * and vault names are not secret and stay on the command line.
80
+ *
81
+ * ## Ordering: create first, delete the old item last
82
+ *
83
+ * `op item edit` has no stdin template form, so the overwrite cannot be an
84
+ * edit-in-place without putting `password=<hex>` back in argv. The write is
85
+ * therefore a replace — but a **non-destructive** one, sequenced so no window
86
+ * exists in which the master key is absent from 1Password:
87
+ *
88
+ * 1. Resolve the existing item's id (absent ⇒ plain create, no step 3).
89
+ * 2. Create the replacement under the **same canonical title** — `op`
90
+ * permits duplicate titles — and capture the new item's id.
91
+ * Create fails ⇒ the old item is untouched and this returns false.
92
+ * 3. Delete the **old** item by id. Delete fails ⇒ roll back by deleting
93
+ * the **new** item by id, leaving the old one in place, and return false.
94
+ *
95
+ * The key is only ever removed from 1Password after its replacement durably
96
+ * exists. Nothing here renames, so there is no window where a rename failure
97
+ * strands the item under a title `getKey` cannot read.
98
+ *
99
+ * **Residual window (double failure).** If step 3's delete fails *and* the
100
+ * rollback delete of the new item also fails, both items remain and this
101
+ * returns false. That is not a loss: no key is destroyed, and {@link getKey}
102
+ * does not silently pick one — `op read` on an ambiguous title fails, so the
103
+ * caller gets a loud failure rather than a wrong key. The operator resolves
104
+ * it by deleting whichever item is stale.
105
+ */
87
106
  storeKey(key) {
88
- const keyHex = key.toString("hex");
89
- // Check if item already exists
90
- if (this.itemExists()) {
91
- return this.updateItem(keyHex);
92
- }
93
- return this.createItem(keyHex);
94
- }
95
- deleteKey() {
107
+ const item = {
108
+ title: this.item,
109
+ category: "PASSWORD",
110
+ vault: { name: this.vault },
111
+ fields: [
112
+ { id: FIELD_NAME, type: "CONCEALED", value: key.toString("hex") },
113
+ ],
114
+ };
115
+ // Step 1. What is already there? A failure to answer that is a failure to
116
+ // store: creating blind would risk leaving two items under one title.
117
+ let oldId;
96
118
  try {
97
- execFileSync("op", ["item", "delete", this.item, "--vault", this.vault], { stdio: ["pipe", "pipe", "pipe"], timeout: 30000 });
98
- return true;
119
+ oldId = this.findItemId();
99
120
  }
100
121
  catch {
101
- // Item may not exist — treat as success
102
- return true;
122
+ return false;
103
123
  }
104
- }
105
- // ---------------------------------------------------------------------------
106
- // Private helpers
107
- // ---------------------------------------------------------------------------
108
- itemExists() {
124
+ // Step 2. Write the replacement. Until this succeeds nothing is removed.
125
+ let newId;
109
126
  try {
110
- execFileSync("op", ["item", "get", this.item, "--vault", this.vault, "--format=json"], { stdio: ["pipe", "pipe", "pipe"], timeout: 15000 });
111
- return true;
127
+ const created = runOp(["item", "create", "--format=json", "-"], {
128
+ input: JSON.stringify(item),
129
+ timeoutMs: OP_WRITE_TIMEOUT_MS,
130
+ });
131
+ newId = parseItemId(created);
112
132
  }
113
133
  catch {
114
134
  return false;
115
135
  }
116
- }
117
- createItem(keyHex) {
136
+ if (oldId === null)
137
+ return true;
138
+ // Step 3. Retire the superseded item, by id so the duplicate title cannot
139
+ // make the delete ambiguous.
118
140
  try {
119
- execFileSync("op", [
120
- "item", "create",
121
- "--category", "Password",
122
- "--title", this.item,
123
- "--vault", this.vault,
124
- `${FIELD_NAME}=${keyHex}`,
125
- ], { stdio: ["pipe", "pipe", "pipe"], timeout: 30000 });
141
+ this.deleteItem(oldId);
126
142
  return true;
127
143
  }
128
144
  catch {
145
+ // Roll back: the store did not complete, so the vault should look as it
146
+ // did before. Deleting the new item leaves the old key readable.
147
+ if (newId !== null) {
148
+ try {
149
+ this.deleteItem(newId);
150
+ }
151
+ catch {
152
+ // Double failure — see "Residual window" above. Both items remain;
153
+ // getKey fails loudly on the ambiguous title rather than returning a
154
+ // key that may be the wrong one, and neither key is lost.
155
+ }
156
+ }
129
157
  return false;
130
158
  }
131
159
  }
132
- updateItem(keyHex) {
160
+ deleteKey() {
133
161
  try {
134
- execFileSync("op", [
135
- "item", "edit", this.item,
136
- "--vault", this.vault,
137
- `${FIELD_NAME}=${keyHex}`,
138
- ], { stdio: ["pipe", "pipe", "pipe"], timeout: 30000 });
139
- return true;
162
+ this.deleteItem(this.item);
140
163
  }
141
164
  catch {
142
- return false;
165
+ // Unchanged from before #102: this entry point reports success for any
166
+ // failure, not just a missing item.
167
+ }
168
+ return true;
169
+ }
170
+ // ---------------------------------------------------------------------------
171
+ // Private helpers
172
+ // ---------------------------------------------------------------------------
173
+ /**
174
+ * The id of the existing key item, or null when there is none.
175
+ *
176
+ * @throws when 1Password cannot be asked, or answers with an item whose id
177
+ * we cannot read. Both are "unknown", not "absent" — and {@link storeKey}
178
+ * must not treat unknown as absent, or a transient read failure would end
179
+ * with two items under one title.
180
+ */
181
+ findItemId() {
182
+ let raw;
183
+ try {
184
+ raw = runOp(["item", "get", this.item, "--vault", this.vault, "--format=json"], { timeoutMs: OP_READ_TIMEOUT_MS });
143
185
  }
186
+ catch (err) {
187
+ if (err instanceof OpCliError && err.isNotFound)
188
+ return null;
189
+ throw err;
190
+ }
191
+ const id = parseItemId(raw);
192
+ if (id === null) {
193
+ throw new Error(`op item get ${this.item} returned no readable item id — refusing to ` +
194
+ "create a second item under the same title");
195
+ }
196
+ return id;
197
+ }
198
+ /**
199
+ * Delete an item by id or title, treating "no such item" as the desired end
200
+ * state.
201
+ *
202
+ * Unlike {@link deleteKey}, an auth or network failure is **rethrown** — the
203
+ * {@link storeKey} path needs to distinguish "the old item is gone" from
204
+ * "we could not remove it", because only the second case must roll back.
205
+ */
206
+ deleteItem(ref) {
207
+ try {
208
+ runOp(["item", "delete", ref, "--vault", this.vault], {
209
+ timeoutMs: OP_WRITE_TIMEOUT_MS,
210
+ });
211
+ }
212
+ catch (err) {
213
+ if (err instanceof OpCliError && err.isNotFound)
214
+ return;
215
+ throw err;
216
+ }
217
+ }
218
+ }
219
+ // =============================================================================
220
+ // Helpers
221
+ // =============================================================================
222
+ /** The `id` of an item in `op … --format=json` output, or null if unreadable. */
223
+ function parseItemId(raw) {
224
+ if (raw === "")
225
+ return null;
226
+ let parsed;
227
+ try {
228
+ parsed = JSON.parse(raw);
229
+ }
230
+ catch {
231
+ return null;
144
232
  }
233
+ if (typeof parsed !== "object" || parsed === null)
234
+ return null;
235
+ const id = parsed.id;
236
+ return typeof id === "string" && id.length > 0 ? id : null;
145
237
  }
146
238
  //# sourceMappingURL=onepassword-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"onepassword-provider.js","sourceRoot":"","sources":["../../src/key-providers/onepassword-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"onepassword-provider.js","sourceRoot":"","sources":["../../src/key-providers/onepassword-provider.ts"],"names":[],"mappings":"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"}