@centient/secrets 0.8.0 → 0.10.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 (97) hide show
  1. package/README.md +70 -2
  2. package/dist/cli/secrets-cli.d.ts.map +1 -1
  3. package/dist/cli/secrets-cli.js +191 -32
  4. package/dist/cli/secrets-cli.js.map +1 -1
  5. package/dist/crypto/darwin-keychain.d.ts +394 -0
  6. package/dist/crypto/darwin-keychain.d.ts.map +1 -0
  7. package/dist/crypto/darwin-keychain.js +793 -0
  8. package/dist/crypto/darwin-keychain.js.map +1 -0
  9. package/dist/crypto/vault-common.d.ts +55 -12
  10. package/dist/crypto/vault-common.d.ts.map +1 -1
  11. package/dist/crypto/vault-common.js +74 -71
  12. package/dist/crypto/vault-common.js.map +1 -1
  13. package/dist/environment/EnvironmentManager.d.ts.map +1 -1
  14. package/dist/environment/EnvironmentManager.js +5 -10
  15. package/dist/environment/EnvironmentManager.js.map +1 -1
  16. package/dist/index.d.ts +21 -7
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +24 -6
  19. package/dist/index.js.map +1 -1
  20. package/dist/key-providers/keychain-provider.d.ts +30 -2
  21. package/dist/key-providers/keychain-provider.d.ts.map +1 -1
  22. package/dist/key-providers/keychain-provider.js +29 -5
  23. package/dist/key-providers/keychain-provider.js.map +1 -1
  24. package/dist/key-providers/onepassword-provider.d.ts +65 -5
  25. package/dist/key-providers/onepassword-provider.d.ts.map +1 -1
  26. package/dist/key-providers/onepassword-provider.js +159 -67
  27. package/dist/key-providers/onepassword-provider.js.map +1 -1
  28. package/dist/key-providers/op-cli.d.ts +78 -0
  29. package/dist/key-providers/op-cli.d.ts.map +1 -0
  30. package/dist/key-providers/op-cli.js +123 -0
  31. package/dist/key-providers/op-cli.js.map +1 -0
  32. package/dist/key-providers/passphrase-provider.d.ts +20 -0
  33. package/dist/key-providers/passphrase-provider.d.ts.map +1 -1
  34. package/dist/key-providers/passphrase-provider.js +49 -0
  35. package/dist/key-providers/passphrase-provider.js.map +1 -1
  36. package/dist/key-providers/probe.d.ts +46 -0
  37. package/dist/key-providers/probe.d.ts.map +1 -0
  38. package/dist/key-providers/probe.js +70 -0
  39. package/dist/key-providers/probe.js.map +1 -0
  40. package/dist/key-providers/types.d.ts +51 -1
  41. package/dist/key-providers/types.d.ts.map +1 -1
  42. package/dist/platform/agent-detect.d.ts +39 -3
  43. package/dist/platform/agent-detect.d.ts.map +1 -1
  44. package/dist/platform/agent-detect.js +55 -9
  45. package/dist/platform/agent-detect.js.map +1 -1
  46. package/dist/platform/session-context.d.ts +77 -0
  47. package/dist/platform/session-context.d.ts.map +1 -0
  48. package/dist/platform/session-context.js +83 -0
  49. package/dist/platform/session-context.js.map +1 -0
  50. package/dist/secret-state.d.ts +54 -0
  51. package/dist/secret-state.d.ts.map +1 -0
  52. package/dist/secret-state.js +2 -0
  53. package/dist/secret-state.js.map +1 -0
  54. package/dist/vault/policy.d.ts +35 -4
  55. package/dist/vault/policy.d.ts.map +1 -1
  56. package/dist/vault/policy.js +65 -6
  57. package/dist/vault/policy.js.map +1 -1
  58. package/dist/vault/session-vault-errors.d.ts +72 -4
  59. package/dist/vault/session-vault-errors.d.ts.map +1 -1
  60. package/dist/vault/session-vault-errors.js +95 -4
  61. package/dist/vault/session-vault-errors.js.map +1 -1
  62. package/dist/vault/session-vault.d.ts +102 -2
  63. package/dist/vault/session-vault.d.ts.map +1 -1
  64. package/dist/vault/session-vault.js +236 -38
  65. package/dist/vault/session-vault.js.map +1 -1
  66. package/dist/vault/types.d.ts +42 -1
  67. package/dist/vault/types.d.ts.map +1 -1
  68. package/dist/vault/types.js.map +1 -1
  69. package/dist/vault/vault-env.d.ts +14 -0
  70. package/dist/vault/vault-env.d.ts.map +1 -1
  71. package/dist/vault/vault-env.js +15 -0
  72. package/dist/vault/vault-env.js.map +1 -1
  73. package/dist/vault/vault-gpg.d.ts +5 -1
  74. package/dist/vault/vault-gpg.d.ts.map +1 -1
  75. package/dist/vault/vault-gpg.js +9 -8
  76. package/dist/vault/vault-gpg.js.map +1 -1
  77. package/dist/vault/vault-libsecret.d.ts +24 -2
  78. package/dist/vault/vault-libsecret.d.ts.map +1 -1
  79. package/dist/vault/vault-libsecret.js +54 -10
  80. package/dist/vault/vault-libsecret.js.map +1 -1
  81. package/dist/vault/vault-onepassword.d.ts +118 -0
  82. package/dist/vault/vault-onepassword.d.ts.map +1 -0
  83. package/dist/vault/vault-onepassword.js +270 -0
  84. package/dist/vault/vault-onepassword.js.map +1 -0
  85. package/dist/vault/vault-utils.d.ts +33 -0
  86. package/dist/vault/vault-utils.d.ts.map +1 -1
  87. package/dist/vault/vault-utils.js +61 -0
  88. package/dist/vault/vault-utils.js.map +1 -1
  89. package/dist/vault/vault-windows.d.ts +5 -1
  90. package/dist/vault/vault-windows.d.ts.map +1 -1
  91. package/dist/vault/vault-windows.js +9 -8
  92. package/dist/vault/vault-windows.js.map +1 -1
  93. package/dist/vault/vault.d.ts +116 -4
  94. package/dist/vault/vault.d.ts.map +1 -1
  95. package/dist/vault/vault.js +288 -22
  96. package/dist/vault/vault.js.map +1 -1
  97. package/package.json +1 -1
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,MAAM,mBAAmB,CAAC;AAGtF,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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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Shared 1Password `op` CLI helper (ADR-004 §6).
3
+ *
4
+ * Two independent layers call `op` for different purposes — `OnePasswordProvider`
5
+ * for the vault *encryption key* (ADR-001) and `OnePasswordVault` for credential
6
+ * *values* (ADR-004) — and before this module each carried its own copy of the
7
+ * availability probe and its own `execFileSync` invocation. One source of truth
8
+ * for how `op` is invoked, how long it may take, and what "available and
9
+ * authenticated" means (P6).
10
+ *
11
+ * No dependency on `@1password/sdk` — `execFileSync` only, matching ADR-001's
12
+ * zero-new-runtime-deps position.
13
+ */
14
+ /** Probe calls (`--version`, `account list`) — fast or the CLI is unusable. */
15
+ export declare const OP_PROBE_TIMEOUT_MS = 5000;
16
+ /** Metadata reads (`item get`, `item list`) — a network round-trip. */
17
+ export declare const OP_READ_TIMEOUT_MS = 15000;
18
+ /** Mutations and secret reads — desktop-app approval may sit in front of these. */
19
+ export declare const OP_WRITE_TIMEOUT_MS = 30000;
20
+ /** Options for {@link runOp}. */
21
+ export interface RunOpOptions {
22
+ /**
23
+ * Data piped to `op` on **stdin**. This is the argv-safe path for secret
24
+ * values (ADR-004 §4): anything passed here is invisible to `ps`, unlike an
25
+ * `field=value` argv element.
26
+ */
27
+ input?: string;
28
+ /** Wall-clock timeout. Defaults to {@link OP_READ_TIMEOUT_MS}. */
29
+ timeoutMs?: number;
30
+ }
31
+ /** A failed `op` invocation, with whatever the CLI wrote to stderr. */
32
+ export declare class OpCliError extends Error {
33
+ /** The argv `op` was called with — never contains secret values. */
34
+ readonly args: readonly string[];
35
+ /** `op`'s stderr, trimmed; empty when the process produced none. */
36
+ readonly stderr: string;
37
+ /** The underlying spawn/exit error. Narrows `Error.cause` to this value. */
38
+ readonly cause: unknown;
39
+ constructor(
40
+ /** The argv `op` was called with — never contains secret values. */
41
+ args: readonly string[],
42
+ /** `op`'s stderr, trimmed; empty when the process produced none. */
43
+ stderr: string,
44
+ /** The underlying spawn/exit error. Narrows `Error.cause` to this value. */
45
+ cause: unknown);
46
+ /**
47
+ * True when the failure is 1Password reporting the item simply is not there,
48
+ * as opposed to an auth, network, or configuration problem.
49
+ *
50
+ * The distinction is load-bearing for ADR-004 §7: a not-found is a normal
51
+ * `null`/`false` return, while an unexpected failure additionally warrants a
52
+ * one-time stderr warning so a misconfiguration cannot stay silent (P2).
53
+ * `op` has no stable exit code for this, so the message is the only signal.
54
+ */
55
+ get isNotFound(): boolean;
56
+ }
57
+ /**
58
+ * Invoke `op` and return its stdout, trimmed.
59
+ *
60
+ * @param args - argv after the binary. **Never** put a secret value here — pass
61
+ * it via {@link RunOpOptions.input} instead (ADR-004 §4).
62
+ * @throws {@link OpCliError} on spawn failure, non-zero exit, or timeout.
63
+ */
64
+ export declare function runOp(args: readonly string[], opts?: RunOpOptions): string;
65
+ /**
66
+ * Whether the `op` CLI is present **and** authenticated.
67
+ *
68
+ * True when the binary is on `PATH` and either `OP_SERVICE_ACCOUNT_TOKEN` is
69
+ * set (headless/CI mode, which needs no further check) or at least one account
70
+ * is configured (desktop app or a prior `op signin`).
71
+ *
72
+ * This answers only "can we talk to 1Password?" — it says nothing about whether
73
+ * a caller *should*. ADR-004's credential backend is opt-in precisely because
74
+ * `op` being installed must never by itself route secrets into 1Password (§1);
75
+ * that selection decision belongs to the caller, not here.
76
+ */
77
+ export declare function detectOpCli(): boolean;
78
+ //# sourceMappingURL=op-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"op-cli.d.ts","sourceRoot":"","sources":["../../src/key-providers/op-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,OAAQ,CAAC;AAEzC,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAM1C,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,uEAAuE;AACvE,qBAAa,UAAW,SAAQ,KAAK;IAEjC,oEAAoE;aACpD,IAAI,EAAE,SAAS,MAAM,EAAE;IACvC,oEAAoE;aACpD,MAAM,EAAE,MAAM;IAC9B,4EAA4E;aACnD,KAAK,EAAE,OAAO;;IALvC,oEAAoE;IACpD,IAAI,EAAE,SAAS,MAAM,EAAE;IACvC,oEAAoE;IACpD,MAAM,EAAE,MAAM;IAC9B,4EAA4E;IACnD,KAAK,EAAE,OAAO;IASzC;;;;;;;;OAQG;IACH,IAAI,UAAU,IAAI,OAAO,CAIxB;CACF;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,GAAE,YAAiB,GAAG,MAAM,CAY9E;AAeD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAkBrC"}