@n24q02m/hull 0.4.0-beta.9 → 0.5.0-beta.1

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 (169) hide show
  1. package/README.md +47 -16
  2. package/build/cli/build-cli.d.ts +5 -6
  3. package/build/cli/build-cli.d.ts.map +1 -1
  4. package/build/cli/build-cli.js +4 -61
  5. package/build/cli/build-cli.js.map +1 -1
  6. package/build/crypto/index.d.ts +1 -1
  7. package/build/crypto/index.d.ts.map +1 -1
  8. package/build/crypto/index.js +1 -1
  9. package/build/crypto/index.js.map +1 -1
  10. package/build/crypto/kdf.d.ts +0 -13
  11. package/build/crypto/kdf.d.ts.map +1 -1
  12. package/build/crypto/kdf.js +3 -18
  13. package/build/crypto/kdf.js.map +1 -1
  14. package/build/index.d.ts +1 -11
  15. package/build/index.d.ts.map +1 -1
  16. package/build/index.js +4 -16
  17. package/build/index.js.map +1 -1
  18. package/build/storage/account-registry.d.ts +53 -0
  19. package/build/storage/account-registry.d.ts.map +1 -0
  20. package/build/storage/account-registry.js +148 -0
  21. package/build/storage/account-registry.js.map +1 -0
  22. package/build/storage/backends.d.ts +0 -26
  23. package/build/storage/backends.d.ts.map +1 -1
  24. package/build/storage/backends.js +0 -65
  25. package/build/storage/backends.js.map +1 -1
  26. package/build/storage/config-file.d.ts +2 -19
  27. package/build/storage/config-file.d.ts.map +1 -1
  28. package/build/storage/config-file.js +2 -23
  29. package/build/storage/config-file.js.map +1 -1
  30. package/build/storage/credential-store.d.ts +1 -9
  31. package/build/storage/credential-store.d.ts.map +1 -1
  32. package/build/storage/credential-store.js +4 -16
  33. package/build/storage/credential-store.js.map +1 -1
  34. package/build/storage/data-dir.d.ts +2 -2
  35. package/build/storage/data-dir.js +2 -2
  36. package/build/storage/encryption.d.ts.map +1 -1
  37. package/build/storage/encryption.js +4 -0
  38. package/build/storage/encryption.js.map +1 -1
  39. package/build/storage/index.d.ts +5 -3
  40. package/build/storage/index.d.ts.map +1 -1
  41. package/build/storage/index.js +5 -3
  42. package/build/storage/index.js.map +1 -1
  43. package/build/storage/key-pool-crypto.d.ts +44 -0
  44. package/build/storage/key-pool-crypto.d.ts.map +1 -0
  45. package/build/storage/key-pool-crypto.js +132 -0
  46. package/build/storage/key-pool-crypto.js.map +1 -0
  47. package/build/storage/key-pool-store.d.ts +134 -0
  48. package/build/storage/key-pool-store.d.ts.map +1 -0
  49. package/build/storage/key-pool-store.js +470 -0
  50. package/build/storage/key-pool-store.js.map +1 -0
  51. package/build/storage/key-pool.d.ts +172 -0
  52. package/build/storage/key-pool.d.ts.map +1 -0
  53. package/build/storage/key-pool.js +374 -0
  54. package/build/storage/key-pool.js.map +1 -0
  55. package/build/storage/resolver.js +1 -1
  56. package/build/storage/resolver.js.map +1 -1
  57. package/build/token-auth/index.d.ts +1 -1
  58. package/build/token-auth/index.js +1 -1
  59. package/build/transport/index.d.ts +1 -2
  60. package/build/transport/index.d.ts.map +1 -1
  61. package/build/transport/index.js +1 -2
  62. package/build/transport/index.js.map +1 -1
  63. package/build/transport/local-server.d.ts +12 -128
  64. package/build/transport/local-server.d.ts.map +1 -1
  65. package/build/transport/local-server.js +20 -262
  66. package/build/transport/local-server.js.map +1 -1
  67. package/build/transport/streamable-http.d.ts +6 -7
  68. package/build/transport/streamable-http.d.ts.map +1 -1
  69. package/build/transport/streamable-http.js +6 -6
  70. package/build/transport/streamable-http.js.map +1 -1
  71. package/build/util/browser.d.ts.map +1 -0
  72. package/build/{relay → util}/browser.js +2 -2
  73. package/build/util/browser.js.map +1 -0
  74. package/package.json +4 -21
  75. package/build/auth/credential-form.d.ts +0 -163
  76. package/build/auth/credential-form.d.ts.map +0 -1
  77. package/build/auth/credential-form.js +0 -1869
  78. package/build/auth/credential-form.js.map +0 -1
  79. package/build/auth/delegated-oauth-app.d.ts +0 -90
  80. package/build/auth/delegated-oauth-app.d.ts.map +0 -1
  81. package/build/auth/delegated-oauth-app.js +0 -881
  82. package/build/auth/delegated-oauth-app.js.map +0 -1
  83. package/build/auth/index.d.ts +0 -12
  84. package/build/auth/index.d.ts.map +0 -1
  85. package/build/auth/index.js +0 -12
  86. package/build/auth/index.js.map +0 -1
  87. package/build/auth/local-oauth-app.d.ts +0 -152
  88. package/build/auth/local-oauth-app.d.ts.map +0 -1
  89. package/build/auth/local-oauth-app.js +0 -975
  90. package/build/auth/local-oauth-app.js.map +0 -1
  91. package/build/auth/relay-login.d.ts +0 -46
  92. package/build/auth/relay-login.d.ts.map +0 -1
  93. package/build/auth/relay-login.js +0 -197
  94. package/build/auth/relay-login.js.map +0 -1
  95. package/build/auth/router.d.ts +0 -18
  96. package/build/auth/router.d.ts.map +0 -1
  97. package/build/auth/router.js +0 -62
  98. package/build/auth/router.js.map +0 -1
  99. package/build/auth/session-store.d.ts +0 -49
  100. package/build/auth/session-store.d.ts.map +0 -1
  101. package/build/auth/session-store.js +0 -94
  102. package/build/auth/session-store.js.map +0 -1
  103. package/build/auth/stable-sub.d.ts +0 -27
  104. package/build/auth/stable-sub.d.ts.map +0 -1
  105. package/build/auth/stable-sub.js +0 -38
  106. package/build/auth/stable-sub.js.map +0 -1
  107. package/build/auth/well-known.d.ts +0 -4
  108. package/build/auth/well-known.d.ts.map +0 -1
  109. package/build/auth/well-known.js +0 -26
  110. package/build/auth/well-known.js.map +0 -1
  111. package/build/oauth/cache.d.ts +0 -22
  112. package/build/oauth/cache.d.ts.map +0 -1
  113. package/build/oauth/cache.js +0 -24
  114. package/build/oauth/cache.js.map +0 -1
  115. package/build/oauth/index.d.ts +0 -6
  116. package/build/oauth/index.d.ts.map +0 -1
  117. package/build/oauth/index.js +0 -6
  118. package/build/oauth/index.js.map +0 -1
  119. package/build/oauth/jwt-issuer.d.ts +0 -87
  120. package/build/oauth/jwt-issuer.d.ts.map +0 -1
  121. package/build/oauth/jwt-issuer.js +0 -205
  122. package/build/oauth/jwt-issuer.js.map +0 -1
  123. package/build/oauth/pkce.d.ts +0 -10
  124. package/build/oauth/pkce.d.ts.map +0 -1
  125. package/build/oauth/pkce.js +0 -34
  126. package/build/oauth/pkce.js.map +0 -1
  127. package/build/oauth/provider.d.ts +0 -52
  128. package/build/oauth/provider.d.ts.map +0 -1
  129. package/build/oauth/provider.js +0 -98
  130. package/build/oauth/provider.js.map +0 -1
  131. package/build/oauth/user-store.d.ts +0 -25
  132. package/build/oauth/user-store.d.ts.map +0 -1
  133. package/build/oauth/user-store.js +0 -85
  134. package/build/oauth/user-store.js.map +0 -1
  135. package/build/relay/browser.d.ts.map +0 -1
  136. package/build/relay/browser.js.map +0 -1
  137. package/build/relay/client.d.ts +0 -36
  138. package/build/relay/client.d.ts.map +0 -1
  139. package/build/relay/client.js +0 -135
  140. package/build/relay/client.js.map +0 -1
  141. package/build/relay/session.d.ts +0 -12
  142. package/build/relay/session.d.ts.map +0 -1
  143. package/build/relay/session.js +0 -55
  144. package/build/relay/session.js.map +0 -1
  145. package/build/relay/tool-helpers.d.ts +0 -85
  146. package/build/relay/tool-helpers.d.ts.map +0 -1
  147. package/build/relay/tool-helpers.js +0 -103
  148. package/build/relay/tool-helpers.js.map +0 -1
  149. package/build/relay/wordlist.d.ts +0 -2
  150. package/build/relay/wordlist.d.ts.map +0 -1
  151. package/build/relay/wordlist.js +0 -7782
  152. package/build/relay/wordlist.js.map +0 -1
  153. package/build/schema/types.d.ts +0 -67
  154. package/build/schema/types.d.ts.map +0 -1
  155. package/build/schema/types.js +0 -2
  156. package/build/schema/types.js.map +0 -1
  157. package/build/storage/mode.d.ts +0 -23
  158. package/build/storage/mode.d.ts.map +0 -1
  159. package/build/storage/mode.js +0 -46
  160. package/build/storage/mode.js.map +0 -1
  161. package/build/storage/session-lock.d.ts +0 -19
  162. package/build/storage/session-lock.d.ts.map +0 -1
  163. package/build/storage/session-lock.js +0 -105
  164. package/build/storage/session-lock.js.map +0 -1
  165. package/build/transport/oauth-middleware.d.ts +0 -45
  166. package/build/transport/oauth-middleware.d.ts.map +0 -1
  167. package/build/transport/oauth-middleware.js +0 -86
  168. package/build/transport/oauth-middleware.js.map +0 -1
  169. /package/build/{relay → util}/browser.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EACL,cAAc,EACd,WAAW,EAEX,eAAe,EACf,cAAc,EAEf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACzF,qEAAqE;AACrE,yEAAyE;AACzE,uEAAuE;AACvE,OAAO,EACL,kBAAkB,IAAI,YAAY,EAClC,gBAAgB,IAAI,UAAU,EAC9B,iBAAiB,IAAI,WAAW,EACjC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAwB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAChG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC9F,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,OAAO,EAAmB,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACtF,OAAO,EAA0C,aAAa,EAAE,MAAM,eAAe,CAAA;AACrF,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAElB,UAAU,EACV,gBAAgB,EACjB,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EACL,cAAc,EAEd,eAAe,EACf,cAAc,EAEf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACzF,qEAAqE;AACrE,yEAAyE;AACzE,uEAAuE;AACvE,OAAO,EACL,kBAAkB,IAAI,YAAY,EAClC,gBAAgB,IAAI,UAAU,EAC9B,iBAAiB,IAAI,WAAW,EACjC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAwB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAChG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC9F,OAAO,EACL,YAAY,EAGZ,qBAAqB,EAErB,uBAAuB,EACvB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,wBAAwB,EAExB,OAAO,EAEP,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EAEpB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACpB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACb,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAGL,eAAe,EAEf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAGhB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACtF,OAAO,EAA0C,aAAa,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Encryption at rest for pooled provider credentials.
3
+ *
4
+ * The provider pool lives in `~/.hull/hull.db`, so every API key is sealed
5
+ * with AES-256-GCM under a 32-byte machine key at `~/.hull/.credential-key`
6
+ * (created 0600 on first use, never overwritten). Envelope:
7
+ *
8
+ * v1:<base64 nonce>:<base64 ciphertext || 16-byte tag>
9
+ *
10
+ * `packages/core-py/src/hull_core/credentials/crypto.py` writes and reads the
11
+ * same envelope with the same key file, so either stack can open a pool the
12
+ * other created; both test suites pin one shared vector.
13
+ */
14
+ export declare const SECRET_KEY_LENGTH = 32;
15
+ export declare const SECRET_NONCE_LENGTH = 12;
16
+ export declare class CredentialCryptoError extends Error {
17
+ constructor(message: string);
18
+ }
19
+ /**
20
+ * Read the 32-byte credential key, minting it 0600 on first use.
21
+ *
22
+ * Creation is exclusive (`wx`): two processes racing on the first use converge
23
+ * on the winner's key instead of the later write winning. A pre-existing file
24
+ * of any other length is refused, never replaced.
25
+ */
26
+ export declare function loadOrCreateKey(path: string): Buffer;
27
+ /** Seal `plaintext` into a `v1:<nonce>:<ciphertext+tag>` envelope. */
28
+ export declare function encryptSecret(key: Buffer, plaintext: string, nonce?: Buffer): string;
29
+ /** Open an envelope produced by {@link encryptSecret}; never echoes it. */
30
+ export declare function decryptSecret(key: Buffer, envelope: string): string;
31
+ /** Display-only tail of a key (`…abcd`); never enough to reconstruct it. */
32
+ export declare function keyHint(apiKey: string): string;
33
+ /** Constant-time equality used for duplicate detection; never logs either value. */
34
+ export declare function secretsEqual(left: string, right: string): boolean;
35
+ /** Lazy key-file holder used by {@link CredentialStore}. */
36
+ export declare class SecretCipher {
37
+ readonly keyPath: string;
38
+ private cachedKey;
39
+ constructor(keyPath: string);
40
+ get key(): Buffer;
41
+ encrypt(plaintext: string): string;
42
+ decrypt(envelope: string): string;
43
+ }
44
+ //# sourceMappingURL=key-pool-crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-pool-crypto.d.ts","sourceRoot":"","sources":["../../src/storage/key-pool-crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,eAAO,MAAM,iBAAiB,KAAK,CAAA;AACnC,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAIrC,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAaD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBpD;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAyC,GAC/C,MAAM,CASR;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6BnE;AAED,4EAA4E;AAC5E,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAIjE;AAED,4DAA4D;AAC5D,qBAAa,YAAY;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,SAAS,CAAsB;IAEvC,YAAY,OAAO,EAAE,MAAM,EAE1B;IAED,IAAI,GAAG,IAAI,MAAM,CAGhB;IAED,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjC;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhC;CACF"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Encryption at rest for pooled provider credentials.
3
+ *
4
+ * The provider pool lives in `~/.hull/hull.db`, so every API key is sealed
5
+ * with AES-256-GCM under a 32-byte machine key at `~/.hull/.credential-key`
6
+ * (created 0600 on first use, never overwritten). Envelope:
7
+ *
8
+ * v1:<base64 nonce>:<base64 ciphertext || 16-byte tag>
9
+ *
10
+ * `packages/core-py/src/hull_core/credentials/crypto.py` writes and reads the
11
+ * same envelope with the same key file, so either stack can open a pool the
12
+ * other created; both test suites pin one shared vector.
13
+ */
14
+ import { createCipheriv, createDecipheriv, randomBytes, timingSafeEqual } from 'node:crypto';
15
+ import { closeSync, fsyncSync, mkdirSync, openSync, readFileSync, writeSync } from 'node:fs';
16
+ import { dirname } from 'node:path';
17
+ export const SECRET_KEY_LENGTH = 32;
18
+ export const SECRET_NONCE_LENGTH = 12;
19
+ const ENVELOPE_PREFIX = 'v1';
20
+ const TAG_LENGTH = 16;
21
+ export class CredentialCryptoError extends Error {
22
+ constructor(message) {
23
+ super(message);
24
+ this.name = 'CredentialCryptoError';
25
+ }
26
+ }
27
+ function checkedKey(key) {
28
+ if (key.length !== SECRET_KEY_LENGTH) {
29
+ throw new CredentialCryptoError(`credential key must be exactly ${SECRET_KEY_LENGTH} raw bytes (found ${key.length}); ` +
30
+ 'hull will not overwrite or delete it. Move it aside to mint a fresh key, then re-add the ' +
31
+ 'provider credentials — the old envelopes cannot be recovered without the original key.');
32
+ }
33
+ return key;
34
+ }
35
+ /**
36
+ * Read the 32-byte credential key, minting it 0600 on first use.
37
+ *
38
+ * Creation is exclusive (`wx`): two processes racing on the first use converge
39
+ * on the winner's key instead of the later write winning. A pre-existing file
40
+ * of any other length is refused, never replaced.
41
+ */
42
+ export function loadOrCreateKey(path) {
43
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
44
+ let fd;
45
+ try {
46
+ fd = openSync(path, 'wx', 0o600);
47
+ }
48
+ catch (error) {
49
+ if (error.code !== 'EEXIST')
50
+ throw error;
51
+ return checkedKey(readFileSync(path));
52
+ }
53
+ const key = randomBytes(SECRET_KEY_LENGTH);
54
+ try {
55
+ writeSync(fd, key);
56
+ fsyncSync(fd);
57
+ }
58
+ finally {
59
+ closeSync(fd);
60
+ }
61
+ return key;
62
+ }
63
+ /** Seal `plaintext` into a `v1:<nonce>:<ciphertext+tag>` envelope. */
64
+ export function encryptSecret(key, plaintext, nonce = randomBytes(SECRET_NONCE_LENGTH)) {
65
+ checkedKey(key);
66
+ if (nonce.length !== SECRET_NONCE_LENGTH) {
67
+ throw new Error(`nonce must be exactly ${SECRET_NONCE_LENGTH} bytes`);
68
+ }
69
+ const cipher = createCipheriv('aes-256-gcm', key, nonce);
70
+ const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
71
+ const payload = Buffer.concat([ciphertext, cipher.getAuthTag()]);
72
+ return `${ENVELOPE_PREFIX}:${nonce.toString('base64')}:${payload.toString('base64')}`;
73
+ }
74
+ /** Open an envelope produced by {@link encryptSecret}; never echoes it. */
75
+ export function decryptSecret(key, envelope) {
76
+ checkedKey(key);
77
+ const parts = envelope.split(':');
78
+ if (parts.length !== 3 || parts[0] !== ENVELOPE_PREFIX) {
79
+ throw new CredentialCryptoError('credential secret is not a v1 hull envelope');
80
+ }
81
+ const nonce = Buffer.from(parts[1], 'base64');
82
+ const payload = Buffer.from(parts[2], 'base64');
83
+ // Node's base64 decoder is lenient; round-tripping rejects `@@@`-style junk.
84
+ if (nonce.toString('base64') !== parts[1] ||
85
+ payload.toString('base64') !== parts[2] ||
86
+ nonce.length !== SECRET_NONCE_LENGTH ||
87
+ payload.length <= TAG_LENGTH) {
88
+ throw new CredentialCryptoError('credential secret envelope is corrupt');
89
+ }
90
+ try {
91
+ const decipher = createDecipheriv('aes-256-gcm', key, nonce);
92
+ decipher.setAuthTag(payload.subarray(payload.length - TAG_LENGTH));
93
+ const plaintext = Buffer.concat([
94
+ decipher.update(payload.subarray(0, payload.length - TAG_LENGTH)),
95
+ decipher.final()
96
+ ]);
97
+ return plaintext.toString('utf8');
98
+ }
99
+ catch {
100
+ // Wrong key or damaged row: the message carries neither envelope nor plaintext.
101
+ throw new CredentialCryptoError('credential secret is corrupt or the key changed');
102
+ }
103
+ }
104
+ /** Display-only tail of a key (`…abcd`); never enough to reconstruct it. */
105
+ export function keyHint(apiKey) {
106
+ return apiKey.length >= 8 ? `…${apiKey.slice(-4)}` : '…';
107
+ }
108
+ /** Constant-time equality used for duplicate detection; never logs either value. */
109
+ export function secretsEqual(left, right) {
110
+ const a = Buffer.from(left, 'utf8');
111
+ const b = Buffer.from(right, 'utf8');
112
+ return a.length === b.length && timingSafeEqual(a, b);
113
+ }
114
+ /** Lazy key-file holder used by {@link CredentialStore}. */
115
+ export class SecretCipher {
116
+ constructor(keyPath) {
117
+ this.cachedKey = null;
118
+ this.keyPath = keyPath;
119
+ }
120
+ get key() {
121
+ if (this.cachedKey === null)
122
+ this.cachedKey = loadOrCreateKey(this.keyPath);
123
+ return this.cachedKey;
124
+ }
125
+ encrypt(plaintext) {
126
+ return encryptSecret(this.key, plaintext);
127
+ }
128
+ decrypt(envelope) {
129
+ return decryptSecret(this.key, envelope);
130
+ }
131
+ }
132
+ //# sourceMappingURL=key-pool-crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-pool-crypto.js","sourceRoot":"","sources":["../../src/storage/key-pool-crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * SQLite-backed provider key pool and account registry (`~/.hull/hull.db`).
3
+ *
4
+ * Mirrors `packages/core-py/src/hull_core/credentials/store.py`, including the
5
+ * table DDL and the shared `v1:` secret envelope, so either stack can open a
6
+ * pool the other created. The tables are additive and migration-safe:
7
+ * `CREATE TABLE/INDEX IF NOT EXISTS` only, no `ALTER`, so a database written by
8
+ * an older hull (only the `kv` table) keeps working and older hull ignores the
9
+ * new tables.
10
+ *
11
+ * Scope rules:
12
+ * - A pool is one provider identity; `account_id IS NULL` is that provider's
13
+ * default pool and a named account has its own pool. Rotation never hops
14
+ * across accounts.
15
+ * - Entries are ordered by `priority` then insertion order.
16
+ * - Rotation state lives in the database, not process memory, so two tasks (or
17
+ * two processes) never reuse a credential that is cooling down or leased.
18
+ */
19
+ import { AccountRegistry } from './account-registry.js';
20
+ import { type Account, type Credential, type CredentialHealth, KeyPool, type KeyPoolOptions, type MigrationResult } from './key-pool.js';
21
+ import { SecretCipher } from './key-pool-crypto.js';
22
+ export declare const KEY_POOL_SCHEMA = "\nCREATE TABLE IF NOT EXISTS provider_accounts (\n account_id TEXT PRIMARY KEY,\n provider TEXT NOT NULL,\n name TEXT NOT NULL,\n email TEXT,\n workspace TEXT,\n labels TEXT NOT NULL DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS provider_accounts_name\n ON provider_accounts(provider, name);\n\nCREATE TABLE IF NOT EXISTS provider_credentials (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n provider TEXT NOT NULL,\n account_id TEXT,\n label TEXT,\n base_url TEXT NOT NULL,\n model TEXT,\n secret TEXT NOT NULL,\n key_hint TEXT NOT NULL,\n priority INTEGER NOT NULL DEFAULT 0,\n disabled INTEGER NOT NULL DEFAULT 0,\n last_status INTEGER,\n failure_count INTEGER NOT NULL DEFAULT 0,\n cooldown_until REAL NOT NULL DEFAULT 0,\n lease_until REAL NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))\n);\n\n\nCREATE INDEX IF NOT EXISTS provider_credentials_pool\n ON provider_credentials(provider, account_id, priority, id);\n";
23
+ export interface AccountRow {
24
+ account_id: string;
25
+ provider: string;
26
+ name: string;
27
+ email: string | null;
28
+ workspace: string | null;
29
+ labels: string;
30
+ }
31
+ /** A `[models.<task>]`-shaped cell, as products and configs already carry it. */
32
+ export interface ModelCellLike {
33
+ readonly baseUrl: string;
34
+ readonly apiKey?: string | null;
35
+ readonly model?: string | null;
36
+ readonly provider?: string | null;
37
+ readonly account?: string | null;
38
+ }
39
+ export interface AddCredentialInput {
40
+ readonly provider: string;
41
+ readonly apiKey: string;
42
+ readonly baseUrl: string;
43
+ readonly model?: string | null;
44
+ readonly accountId?: string | null;
45
+ readonly label?: string | null;
46
+ readonly priority?: number | null;
47
+ }
48
+ export interface CredentialStoreOptions {
49
+ readonly cipher?: SecretCipher;
50
+ readonly now?: () => number;
51
+ }
52
+ export interface PoolDiagnostics {
53
+ readonly total: number;
54
+ readonly disabled: number;
55
+ readonly coolingDown: number;
56
+ readonly leased: number;
57
+ readonly retryAfter: number | null;
58
+ }
59
+ /** The instance database every hull surface already uses: `~/.hull/hull.db`. */
60
+ export declare function defaultHullDbPath(): string;
61
+ /** Key file that seals this database's credentials (same directory as the DB). */
62
+ export declare function credentialKeyPath(dbPath: string): string;
63
+ /** Ordered provider credential pool plus named accounts, on local SQLite. */
64
+ export declare class CredentialStore {
65
+ readonly path: string;
66
+ private readonly db;
67
+ private readonly cipher;
68
+ private readonly clock;
69
+ constructor(dbPath?: string, options?: CredentialStoreOptions);
70
+ now(): number;
71
+ close(): void;
72
+ private toCredential;
73
+ private toHealth;
74
+ private row;
75
+ private requireAccount;
76
+ private rejectDuplicate;
77
+ addCredential(input: AddCredentialInput): Credential;
78
+ removeCredential(credentialId: number): void;
79
+ setPriority(credentialId: number, priority: number): void;
80
+ /** Clear disabled/cooldown/failure state after an operator fixes the key. */
81
+ enable(credentialId: number): void;
82
+ disable(credentialId: number): void;
83
+ /** Clear rotation state for one provider (or every provider); returns rows matched. */
84
+ resetHealth(provider?: string): number;
85
+ /** Every decrypted entry (all accounts), ordered by provider/priority/id. */
86
+ credentials(provider?: string): Credential[];
87
+ /** The rotation pool for one provider/account scope, in priority order. */
88
+ poolCredentials(provider: string, accountId?: string | null): Credential[];
89
+ /** Masked state of every entry, including disabled and cooling ones. */
90
+ health(provider?: string): CredentialHealth[];
91
+ poolHealth(provider: string, accountId?: string | null): CredentialHealth[];
92
+ getCredential(credentialId: number): Credential;
93
+ diagnose(provider: string, accountId?: string | null): PoolDiagnostics;
94
+ /** Atomically lease the highest-priority usable entry, or return null. */
95
+ leaseFirst(provider: string, accountId: string | null, options: {
96
+ now: number;
97
+ leaseSeconds: number;
98
+ exclude?: number[];
99
+ }): Credential | null;
100
+ releaseLease(credentialId: number): void;
101
+ recordSuccess(credentialId: number): void;
102
+ recordFailure(credentialId: number, status: number | null, options?: {
103
+ now?: number;
104
+ cooldownUntil?: number | null;
105
+ disable?: boolean;
106
+ }): void;
107
+ accounts(): AccountRegistry;
108
+ accountRows(): AccountRow[];
109
+ accountRow(accountId: string): AccountRow | undefined;
110
+ accountRowsByName(name: string): AccountRow[];
111
+ insertAccount(account: Account): void;
112
+ updateAccountRow(accountId: string, values: {
113
+ name: string;
114
+ email: string | null;
115
+ workspace: string | null;
116
+ labelsJson: string;
117
+ }): void;
118
+ deleteAccountRow(accountId: string, options?: {
119
+ dropCredentials?: boolean;
120
+ }): void;
121
+ pool(provider: string, options?: KeyPoolOptions): KeyPool;
122
+ /** Resolve a `[models.<task>]`-shaped cell's `provider`/`account` pointers. */
123
+ poolForCell(cell: ModelCellLike, options?: KeyPoolOptions): KeyPool;
124
+ /**
125
+ * Seed the pool from the pre-pool single-key config, idempotently. Every
126
+ * distinct `(baseUrl, apiKey)` becomes one entry in insertion order; running
127
+ * it again skips what is already stored.
128
+ */
129
+ migrateModelCells(cells: Iterable<ModelCellLike>, options?: {
130
+ provider?: string | null;
131
+ accountId?: string | null;
132
+ }): MigrationResult;
133
+ }
134
+ //# sourceMappingURL=key-pool-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-pool-store.d.ts","sourceRoot":"","sources":["../../src/storage/key-pool-store.ts"],"names":[],"mappings":"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"}