@huaweidevtools/aishell-dsh-credentials-store 0.0.1-beta.1 → 0.0.1-beta.3

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 (74) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +62 -14
  3. package/lib/accounts.d.ts +187 -0
  4. package/lib/accounts.d.ts.map +1 -0
  5. package/lib/accounts.js +298 -0
  6. package/lib/accounts.js.map +1 -0
  7. package/lib/index-CsXaUaRH.d.ts +211 -0
  8. package/lib/index-CsXaUaRH.d.ts.map +1 -0
  9. package/lib/index.d.ts +3 -208
  10. package/lib/index.js +26 -28
  11. package/lib/index.js.map +1 -1
  12. package/lib/paths-DtFRzop6.js +46 -0
  13. package/lib/paths-DtFRzop6.js.map +1 -0
  14. package/lib/paths.d.ts +56 -0
  15. package/lib/paths.d.ts.map +1 -0
  16. package/lib/paths.js +3 -0
  17. package/lib/scope-CFetnbG3.d.ts +71 -0
  18. package/lib/scope-CFetnbG3.d.ts.map +1 -0
  19. package/lib/scope-QmrHZaZt.js +96 -0
  20. package/lib/scope-QmrHZaZt.js.map +1 -0
  21. package/lib/scope.d.ts +2 -0
  22. package/lib/scope.js +3 -0
  23. package/lib/signer-BPR0UAF0.js +66 -0
  24. package/lib/signer-BPR0UAF0.js.map +1 -0
  25. package/lib/signer-Et0DIH6o.d.ts +40 -0
  26. package/lib/signer-Et0DIH6o.d.ts.map +1 -0
  27. package/lib/signer.d.ts +2 -40
  28. package/lib/signer.js +2 -65
  29. package/lib/types/accounts.d.ts +231 -0
  30. package/lib/types/accounts.d.ts.map +1 -0
  31. package/lib/types/accounts.js +384 -0
  32. package/lib/types/accounts.js.map +1 -0
  33. package/lib/types/backends/fingerprint.d.ts +41 -0
  34. package/lib/types/backends/fingerprint.d.ts.map +1 -0
  35. package/lib/types/backends/fingerprint.js +135 -0
  36. package/lib/types/backends/fingerprint.js.map +1 -0
  37. package/lib/types/backends/keyring.d.ts +69 -0
  38. package/lib/types/backends/keyring.d.ts.map +1 -0
  39. package/lib/types/backends/keyring.js +107 -0
  40. package/lib/types/backends/keyring.js.map +1 -0
  41. package/lib/types/backends/memory.d.ts +22 -0
  42. package/lib/types/backends/memory.d.ts.map +1 -0
  43. package/lib/types/backends/memory.js +35 -0
  44. package/lib/types/backends/memory.js.map +1 -0
  45. package/lib/types/failover.d.ts +136 -0
  46. package/lib/types/failover.d.ts.map +1 -0
  47. package/lib/types/failover.js +242 -0
  48. package/lib/types/failover.js.map +1 -0
  49. package/lib/types/index.d.ts +70 -0
  50. package/lib/types/index.d.ts.map +1 -0
  51. package/lib/types/index.js +73 -0
  52. package/lib/types/index.js.map +1 -0
  53. package/lib/types/paths.d.ts +50 -0
  54. package/lib/types/paths.d.ts.map +1 -0
  55. package/lib/types/paths.js +59 -0
  56. package/lib/types/paths.js.map +1 -0
  57. package/lib/types/scope.d.ts +65 -0
  58. package/lib/types/scope.d.ts.map +1 -0
  59. package/lib/types/scope.js +102 -0
  60. package/lib/types/scope.js.map +1 -0
  61. package/lib/types/signer.d.ts +36 -0
  62. package/lib/types/signer.d.ts.map +1 -0
  63. package/lib/types/signer.js +81 -0
  64. package/lib/types/signer.js.map +1 -0
  65. package/lib/types/verify.d.ts +114 -0
  66. package/lib/types/verify.d.ts.map +1 -0
  67. package/lib/types/verify.js +240 -0
  68. package/lib/types/verify.js.map +1 -0
  69. package/lib/verify.d.ts +72 -0
  70. package/lib/verify.d.ts.map +1 -0
  71. package/lib/verify.js +172 -0
  72. package/lib/verify.js.map +1 -0
  73. package/package.json +21 -8
  74. package/lib/index.d.ts.map +0 -1
@@ -0,0 +1,211 @@
1
+ //#region src/backends/keyring.d.ts
2
+
3
+ type KeyringEntry = {
4
+ getPassword: () => string | null;
5
+ setPassword: (value: string) => void;
6
+ deletePassword: () => void;
7
+ };
8
+ /** Entry options bag; only the Linux store pin is used (see the module note). */
9
+ type KeyringEntryOptions = {
10
+ linux?: {
11
+ store?: 'secret-service' | 'keyutils';
12
+ };
13
+ };
14
+ type KeyringModule = {
15
+ Entry: new (service: string, account: string, options?: KeyringEntryOptions) => KeyringEntry;
16
+ };
17
+ /** @internal Test hook: inject a mock keyring module (vi.mock cannot intercept createRequire). */
18
+ declare function __setKeyringModule(mock: KeyringModule | undefined): void;
19
+ /**
20
+ * OS-keyring {@link CredentialsStore}. Constructed with a shared service name;
21
+ * every entry is stored under `new Entry(service, account, { linux: { store:
22
+ * 'secret-service' } })`.
23
+ *
24
+ * Construction probes the keyring once — if the native module cannot be loaded
25
+ * (no prebuilt binding for this platform), or the Linux Secret Service is
26
+ * unavailable, it throws and {@link createCredentialsStore} falls back to the
27
+ * next backend. Without the pin the absent-service case does not throw; see
28
+ * the module note.
29
+ */
30
+ declare class KeyringBackend implements CredentialsStore {
31
+ private readonly serviceName;
32
+ private readonly options;
33
+ private readonly Entry;
34
+ constructor(_config?: CredentialsStoreConfig);
35
+ get(account: string): string | undefined;
36
+ set(account: string, value: string): void;
37
+ delete(account: string): void;
38
+ has(account: string): boolean;
39
+ } //#endregion
40
+ //#region src/backends/fingerprint.d.ts
41
+ /**
42
+ * Encrypted-file {@link CredentialsStore}. Each account is one entry in a
43
+ * single JSON map, encrypted as one file under the resolved credentials
44
+ * directory, named by the build's credential scope (see `../scope.ts`).
45
+ *
46
+ * Construction probes the machine ID + crypto — if `node-machine-id` cannot
47
+ * resolve a UUID, construction throws and the factory falls back to
48
+ * {@link MemoryBackend}.
49
+ */
50
+ declare class FingerprintBackend implements CredentialsStore {
51
+ private readonly filePath;
52
+ private readonly fileDir;
53
+ constructor(config?: CredentialsStoreConfig);
54
+ /**
55
+ * Load + decrypt the file into a fresh map. Not cached — credentials are
56
+ * read, used, and dropped so plaintext does not linger in memory between
57
+ * operations. The file I/O + scrypt decrypt per call is acceptable: this is
58
+ * not a hot path (once per chat request, not per token).
59
+ */
60
+ private load;
61
+ /** Encrypt + write the map to disk with owner-only permissions. */
62
+ private persist;
63
+ get(account: string): string | undefined;
64
+ set(account: string, value: string): void;
65
+ delete(account: string): void;
66
+ has(account: string): boolean;
67
+ }
68
+
69
+ //#endregion
70
+ //#region src/backends/memory.d.ts
71
+ //# sourceMappingURL=fingerprint.d.ts.map
72
+ /** Process-scoped {@link CredentialsStore}; entries vanish on exit. */
73
+ declare class MemoryBackend implements CredentialsStore {
74
+ private readonly entries;
75
+ constructor(_config?: CredentialsStoreConfig);
76
+ get(account: string): string | undefined;
77
+ set(account: string, value: string): void;
78
+ delete(account: string): void;
79
+ has(account: string): boolean;
80
+ }
81
+
82
+ //#endregion
83
+ //#region src/failover.d.ts
84
+ //# sourceMappingURL=memory.d.ts.map
85
+
86
+ /** Options for {@link FailoverStore}. */
87
+ interface FailoverStoreOptions {
88
+ /**
89
+ * Builds the store that takes over when the primary fails a write. Called
90
+ * at most once, lazily, on first need — a read miss or the first failed
91
+ * write — so a healthy keyring never pays for constructing it. Must not
92
+ * throw: the factory's closure ends in MemoryBackend.
93
+ */
94
+ readonly createFallback: () => CredentialsStore;
95
+ }
96
+ /**
97
+ * A {@link CredentialsStore} that delegates to a primary until the primary
98
+ * fails a write, then fails over — for the life of this store — to a
99
+ * fallback supplied by {@link FailoverStoreOptions.createFallback}.
100
+ *
101
+ * Stickiness is per instance, not per process: each plugin that consumes
102
+ * credentials builds its own store, so one instance failing over does not stop
103
+ * another from trying the primary. That is intended — the flag only exists to
104
+ * avoid re-hitting a primary already known to be unwritable from *this* store,
105
+ * and a second instance's attempt is one probe rather than a policy decision.
106
+ * Correctness across instances comes from the persisted record, not the flag.
107
+ *
108
+ * Constructed by {@link createCredentialsStore} around a KeyringBackend whose
109
+ * construction probe passed; not meant for direct use by upper layers.
110
+ */
111
+ declare class FailoverStore implements CredentialsStore {
112
+ private readonly primary;
113
+ private readonly createFallback;
114
+ private fallback;
115
+ /** Set by the first failed primary write; routes writes thereafter. */
116
+ private failedOver;
117
+ constructor(primary: CredentialsStore, options: FailoverStoreOptions);
118
+ /** The lazily built fallback; constructed at most once per store. */
119
+ private get fallbackStore();
120
+ /**
121
+ * Drop the tombstone for `account`, if any.
122
+ *
123
+ * Paired with the value purge on every path that hands authority back to the
124
+ * primary. Best-effort: a tombstone that outlives its purpose costs one extra
125
+ * fallback lookup, which must never fail a write the keyring has accepted.
126
+ */
127
+ private clearTombstone;
128
+ get(account: string): string | undefined;
129
+ has(account: string): boolean;
130
+ set(account: string, value: string): void;
131
+ delete(account: string): void;
132
+ /**
133
+ * Record the deletion, or report its failure.
134
+ *
135
+ * Unlike the best-effort cleanups above, a tombstone that cannot be written
136
+ * means the delete silently did not happen and the credential will read back
137
+ * later. That is a failed clear, so it throws rather than being swallowed.
138
+ */
139
+ private writeTombstone;
140
+ } //#endregion
141
+ //#region src/index.d.ts
142
+
143
+ //# sourceMappingURL=failover.d.ts.map
144
+ /**
145
+ * Credential storage abstraction for aishell DSH plugins.
146
+ *
147
+ * Upper layers (aishell-llm's adapter, aishell-credentials' host half)
148
+ * call {@link createCredentialsStore} and get a {@link CredentialsStore} —
149
+ * they never learn which backend is serving. The factory probes backends in
150
+ * priority order (OS keyring first, process memory last) and returns the
151
+ * first that answers. New backends (fingerprint + encrypted file, etc.) slot
152
+ * into the chain without touching callers. A keyring that answers the probe
153
+ * but later rejects writes fails over to the next backend on first failure.
154
+ *
155
+ * This is a tool library, not a DSH plugin — no `dsh.client`, no
156
+ * `cordis.patch.yml`, no `apply`. DSH's own `ctx.credentials` is untouched;
157
+ * user-configured models and `.credentials.yaml` keep working.
158
+ *
159
+ * @module @huaweidevtools/aishell-dsh-credentials-store
160
+ */
161
+ /** Options shared by every backend / the factory. */
162
+ interface CredentialsStoreConfig {
163
+ /**
164
+ * Explicit directory for the fingerprint encrypted-file backend. When set,
165
+ * overrides the default `$DSH_HOME/credentials` resolution. Callers rarely
166
+ * need this — the host's `DSH_HOME` already places credentials alongside
167
+ * its other data.
168
+ */
169
+ readonly credentialsDir?: string;
170
+ }
171
+ /**
172
+ * Read/write a named credential. Backends are synchronous and per-call — no
173
+ * cache, so a credential changed from outside is visible on the next `get`.
174
+ * Absent credentials read as `undefined` / `has === false`; a backend that
175
+ * cannot serve (e.g. no D-Bus secret service) degrades the same way rather
176
+ * than throwing on read.
177
+ */
178
+ interface CredentialsStore {
179
+ /** Read one credential; `undefined` when absent or backend unavailable. */
180
+ get(account: string): string | undefined;
181
+ /** Store one credential. Rejects an empty value; throws on backend errors. */
182
+ set(account: string, value: string): void;
183
+ /** Remove one credential; absent is a no-op. Throws on backend errors. */
184
+ delete(account: string): void;
185
+ /** Whether a credential is currently stored; `false` when absent or backend unavailable. */
186
+ has(account: string): boolean;
187
+ }
188
+ /**
189
+ * Probe backends in priority order and return the first that answers.
190
+ *
191
+ * Priority: OS keyring (durable, cross-process) → machine-fingerprint
192
+ * encrypted file (durable, same-machine) → process memory (volatile,
193
+ * last resort). A backend that cannot initialize — no D-Bus secret service
194
+ * on a headless Linux box, keychain locked, etc. — is skipped, not fatal.
195
+ *
196
+ * A keyring that passes the construction probe but is later found unwritable
197
+ * (GNOME login keyring locked: reads come back null, writes fail — the probe
198
+ * cannot see this) is wrapped in a {@link FailoverStore}: its first failed
199
+ * write fails the whole process over to the fingerprint backend, so saving
200
+ * credentials works instead of erroring. The wrapper also records which
201
+ * accounts the keyring must not answer for, so a credential saved while the
202
+ * collection was locked is not shadowed by the keyring's stale copy once it
203
+ * unlocks.
204
+ *
205
+ * @returns the highest-priority backend that could initialize.
206
+ */
207
+ declare function createCredentialsStore(config?: CredentialsStoreConfig): CredentialsStore;
208
+
209
+ //#endregion
210
+ export { CredentialsStore, CredentialsStoreConfig, FailoverStore, FingerprintBackend, KeyringBackend, MemoryBackend, __setKeyringModule, createCredentialsStore };
211
+ //# sourceMappingURL=index-CsXaUaRH.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CsXaUaRH.d.ts","names":[],"sources":["../../src/backends/keyring.ts","../../src/backends/fingerprint.ts","../../src/backends/memory.ts","../../src/failover.ts","../../src/index.ts"],"sourcesContent":null,"mappings":";;KAuCK,YAAA;;;;;;KAMA,mBAAA;;ICyCQ,KAAA,CAAA,EAAA,gBAAmB,GAAA,UAAA;EAAA,CAAA;CAAA;KDxC3B,aAAA,GCwCsC;EAAgB,KAAA,EAAA,KAAA,OAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EDvCD,mBCuCC,EAAA,GDvCuB,YCuCvB;;;iBDlC3C,kBAAA,OAAyB;;AErCzC;;;;AAAsD;;;;;ACqFtD;cH5Ba,cAAA,YAA0B;;;;wBAKhB;;;;;;;;;;;;;;;AALvB;AAA4B,cCcf,kBAAA,YAA8B,gBDdf,CAAA;EAAA,iBAKL,QAAA;EAA2B,iBALX,OAAA;EAAgB,WAAA,CAAA,MAAA,CAAA,ECkBjC,sBDlBiC;;;;;;;;;;;;;ECc1C,GAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAmB,OAAA;;;;;;;cCvEnB,aAAA,YAAyB;;wBAGf;;;;;;;;;AFsDvB;;;UG4BiB,oBAAA;;;;;;;iCAOgB;;;;;;;;;;;ACnFjC;;;;;;cDqGa,aAAA,YAAyB;;ECpFrB,iBAAA,cAAgB;;;;uBD2FV,2BAA2B;;;;;;;;;;;;;;;;AC7DlD;;;;AAA6F;;;;;;;;AJvClB;AAO1D;AAMO;;;;AAEsE;;AAK9F;;;;;;;;;UI5BiB,sBAAA;;;AJgDjB;;;;EAAuD,SAAA,cAAA,CAAA,EAAA,MAAA;;;;;;;;;UI/BtC,gBAAA;;;;EH6CJ,GAAA,CAAA,OAAA,EAAA,MAAA,EAAmB,KAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAA;EAAA,MAIV,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAA2B;EAJU,GAAA,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;;;;ACvE3D;;;;AAAsD;;;;;ACqFtD;;;;;;;iBC7BgB,sBAAA,UAA+B,yBAA8B"}
package/lib/index.d.ts CHANGED
@@ -1,208 +1,3 @@
1
- //#region src/backends/keyring.d.ts
2
-
3
- type KeyringEntry = {
4
- getPassword: () => string | null;
5
- setPassword: (value: string) => void;
6
- deletePassword: () => void;
7
- };
8
- type KeyringModule = {
9
- Entry: new (service: string, account: string) => KeyringEntry;
10
- };
11
- /** @internal Test hook: inject a mock keyring module (vi.mock cannot intercept createRequire). */
12
- declare function __setKeyringModule(mock: KeyringModule | undefined): void;
13
- /**
14
- * OS-keyring {@link CredentialsStore}. Constructed with a shared service name;
15
- * every entry is stored under `new Entry(service, account)`.
16
- *
17
- * Construction probes the keyring once — if the native module cannot be loaded
18
- * (no prebuilt binding for this platform) or cannot reach a secret service it
19
- * throws, and {@link createCredentialsStore} falls back to the next backend.
20
- */
21
- declare class KeyringBackend implements CredentialsStore {
22
- private readonly serviceName;
23
- private readonly Entry;
24
- constructor(config?: CredentialsStoreConfig);
25
- get(account: string): string | undefined;
26
- set(account: string, value: string): void;
27
- delete(account: string): void;
28
- has(account: string): boolean;
29
- } //#endregion
30
- //#region src/backends/fingerprint.d.ts
31
-
32
- /**
33
- * Encrypted-file {@link CredentialsStore}. Each account is one entry in a
34
- * single JSON map, encrypted as one file under the resolved credentials
35
- * directory (`$DSH_HOME/credentials/credentials.enc` by default).
36
- *
37
- * Construction probes the machine ID + crypto — if `node-machine-id` cannot
38
- * resolve a UUID, construction throws and the factory falls back to
39
- * {@link MemoryBackend}.
40
- */
41
- declare class FingerprintBackend implements CredentialsStore {
42
- private readonly filePath;
43
- private readonly fileDir;
44
- constructor(config?: CredentialsStoreConfig);
45
- /**
46
- * Load + decrypt the file into a fresh map. Not cached — credentials are
47
- * read, used, and dropped so plaintext does not linger in memory between
48
- * operations. The file I/O + scrypt decrypt per call is acceptable: this is
49
- * not a hot path (once per chat request, not per token).
50
- */
51
- private load;
52
- /** Encrypt + write the map to disk with owner-only permissions. */
53
- private persist;
54
- get(account: string): string | undefined;
55
- set(account: string, value: string): void;
56
- delete(account: string): void;
57
- has(account: string): boolean;
58
- } //#endregion
59
- //#region src/backends/memory.d.ts
60
-
61
- //# sourceMappingURL=fingerprint.d.ts.map
62
- /** Process-scoped {@link CredentialsStore}; entries vanish on exit. */
63
- declare class MemoryBackend implements CredentialsStore {
64
- private readonly entries;
65
- constructor(_config?: CredentialsStoreConfig);
66
- get(account: string): string | undefined;
67
- set(account: string, value: string): void;
68
- delete(account: string): void;
69
- has(account: string): boolean;
70
- }
71
-
72
- //#endregion
73
- //#region src/failover.d.ts
74
- //# sourceMappingURL=memory.d.ts.map
75
-
76
- /** Options for {@link FailoverStore}. */
77
- interface FailoverStoreOptions {
78
- /**
79
- * Builds the store that takes over when the primary fails a write. Called
80
- * at most once, lazily, on first need — a read miss or the first failed
81
- * write — so a healthy keyring never pays for constructing it. Must not
82
- * throw: the factory's closure ends in MemoryBackend.
83
- */
84
- readonly createFallback: () => CredentialsStore;
85
- }
86
- /**
87
- * A {@link CredentialsStore} that delegates to a primary until the primary
88
- * fails a write, then fails over — for the life of this store — to a
89
- * fallback supplied by {@link FailoverStoreOptions.createFallback}.
90
- *
91
- * Stickiness is per instance, not per process: each plugin that consumes
92
- * credentials builds its own store, so one instance failing over does not stop
93
- * another from trying the primary. That is intended — the flag only exists to
94
- * avoid re-hitting a primary already known to be unwritable from *this* store,
95
- * and a second instance's attempt is one probe rather than a policy decision.
96
- * Correctness across instances comes from the persisted record, not the flag.
97
- *
98
- * Constructed by {@link createCredentialsStore} around a KeyringBackend whose
99
- * construction probe passed; not meant for direct use by upper layers.
100
- */
101
- declare class FailoverStore implements CredentialsStore {
102
- private readonly primary;
103
- private readonly createFallback;
104
- private fallback;
105
- /** Set by the first failed primary write; routes writes thereafter. */
106
- private failedOver;
107
- constructor(primary: CredentialsStore, options: FailoverStoreOptions);
108
- /** The lazily built fallback; constructed at most once per store. */
109
- private get fallbackStore();
110
- /**
111
- * Drop the tombstone for `account`, if any.
112
- *
113
- * Paired with the value purge on every path that hands authority back to the
114
- * primary. Best-effort: a tombstone that outlives its purpose costs one extra
115
- * fallback lookup, which must never fail a write the keyring has accepted.
116
- */
117
- private clearTombstone;
118
- get(account: string): string | undefined;
119
- has(account: string): boolean;
120
- set(account: string, value: string): void;
121
- delete(account: string): void;
122
- /**
123
- * Record the deletion, or report its failure.
124
- *
125
- * Unlike the best-effort cleanups above, a tombstone that cannot be written
126
- * means the delete silently did not happen and the credential will read back
127
- * later. That is a failed clear, so it throws rather than being swallowed.
128
- */
129
- private writeTombstone;
130
- } //#endregion
131
- //#region src/index.d.ts
132
-
133
- //# sourceMappingURL=failover.d.ts.map
134
- /**
135
- * Credential storage abstraction for aishell DSH plugins.
136
- *
137
- * Upper layers (aishell-llm's adapter, aishell-credentials' host half)
138
- * call {@link createCredentialsStore} and get a {@link CredentialsStore} —
139
- * they never learn which backend is serving. The factory probes backends in
140
- * priority order (OS keyring first, process memory last) and returns the
141
- * first that answers. New backends (fingerprint + encrypted file, etc.) slot
142
- * into the chain without touching callers. A keyring that answers the probe
143
- * but later rejects writes fails over to the next backend on first failure.
144
- *
145
- * This is a tool library, not a DSH plugin — no `dsh.client`, no
146
- * `cordis.patch.yml`, no `apply`. DSH's own `ctx.credentials` is untouched;
147
- * user-configured models and `.credentials.yaml` keep working.
148
- *
149
- * @module @huaweidevtools/aishell-dsh-credentials-store
150
- */
151
- /** Options shared by every backend / the factory. */
152
- interface CredentialsStoreConfig {
153
- /**
154
- * Backend-scoped identity. For the OS-keyring backend this is the keyring
155
- * service name; every entry is stored under `new Entry(service, account)`.
156
- * Defaults to `'aishell-dsh'`.
157
- */
158
- readonly service?: string;
159
- /**
160
- * Explicit directory for the fingerprint encrypted-file backend. When set,
161
- * overrides the default `$DSH_HOME/credentials` resolution. Callers rarely
162
- * need this — the host's `DSH_HOME` already places credentials alongside
163
- * its other data.
164
- */
165
- readonly credentialsDir?: string;
166
- }
167
- /**
168
- * Read/write a named credential. Backends are synchronous and per-call — no
169
- * cache, so a credential changed from outside is visible on the next `get`.
170
- * Absent credentials read as `undefined` / `has === false`; a backend that
171
- * cannot serve (e.g. no D-Bus secret service) degrades the same way rather
172
- * than throwing on read.
173
- */
174
- interface CredentialsStore {
175
- /** Read one credential; `undefined` when absent or backend unavailable. */
176
- get(account: string): string | undefined;
177
- /** Store one credential. Rejects an empty value; throws on backend errors. */
178
- set(account: string, value: string): void;
179
- /** Remove one credential; absent is a no-op. Throws on backend errors. */
180
- delete(account: string): void;
181
- /** Whether a credential is currently stored; `false` when absent or backend unavailable. */
182
- has(account: string): boolean;
183
- }
184
- /**
185
- * Probe backends in priority order and return the first that answers.
186
- *
187
- * Priority: OS keyring (durable, cross-process) → machine-fingerprint
188
- * encrypted file (durable, same-machine) → process memory (volatile,
189
- * last resort). A backend that cannot initialize — no D-Bus secret service
190
- * on a headless Linux box, keychain locked, etc. — is skipped, not fatal.
191
- *
192
- * A keyring that passes the construction probe but is later found unwritable
193
- * (GNOME login keyring locked: reads come back null, writes fail — the probe
194
- * cannot see this) is wrapped in a {@link FailoverStore}: its first failed
195
- * write fails the whole process over to the fingerprint backend, so saving
196
- * credentials works instead of erroring. The wrapper also records which
197
- * accounts the keyring must not answer for, so a credential saved while the
198
- * collection was locked is not shadowed by the keyring's stale copy once it
199
- * unlocks.
200
- *
201
- * @param config - optional service name override.
202
- * @returns the highest-priority backend that could initialize.
203
- */
204
- declare function createCredentialsStore(config?: CredentialsStoreConfig): CredentialsStore;
205
-
206
- //#endregion
207
- export { CredentialsStore, CredentialsStoreConfig, FailoverStore, FingerprintBackend, KeyringBackend, MemoryBackend, __setKeyringModule, createCredentialsStore };
208
- //# sourceMappingURL=index.d.ts.map
1
+ import { CREDENTIALS_FILE_NAME$1 as CREDENTIALS_FILE_NAME, CREDENTIAL_SCOPE$1 as CREDENTIAL_SCOPE, DEFAULT_SCOPE$1 as DEFAULT_SCOPE, KEYRING_SERVICE$1 as KEYRING_SERVICE } from "./scope-CFetnbG3.js";
2
+ import { CredentialsStore, CredentialsStoreConfig, FailoverStore, FingerprintBackend, KeyringBackend, MemoryBackend, __setKeyringModule, createCredentialsStore } from "./index-CsXaUaRH.js";
3
+ export { CREDENTIALS_FILE_NAME, CREDENTIAL_SCOPE, CredentialsStore, CredentialsStoreConfig, DEFAULT_SCOPE, FailoverStore, FingerprintBackend, KEYRING_SERVICE, KeyringBackend, MemoryBackend, __setKeyringModule, createCredentialsStore };
package/lib/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { createRequire } from "node:module";
1
+ import { CREDENTIALS_FILE_NAME, CREDENTIAL_SCOPE, DEFAULT_SCOPE, KEYRING_SERVICE } from "./scope-QmrHZaZt.js";
2
+ import { credentialsDir } from "./paths-DtFRzop6.js";
2
3
  import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from "node:crypto";
4
+ import { createRequire } from "node:module";
3
5
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
- import { homedir } from "node:os";
5
6
  import { join } from "node:path";
6
7
  import machineIdModule from "node-machine-id";
7
8
 
@@ -18,21 +19,25 @@ function loadKeyring() {
18
19
  }
19
20
  /**
20
21
  * OS-keyring {@link CredentialsStore}. Constructed with a shared service name;
21
- * every entry is stored under `new Entry(service, account)`.
22
+ * every entry is stored under `new Entry(service, account, { linux: { store:
23
+ * 'secret-service' } })`.
22
24
  *
23
25
  * Construction probes the keyring once — if the native module cannot be loaded
24
- * (no prebuilt binding for this platform) or cannot reach a secret service it
25
- * throws, and {@link createCredentialsStore} falls back to the next backend.
26
+ * (no prebuilt binding for this platform), or the Linux Secret Service is
27
+ * unavailable, it throws and {@link createCredentialsStore} falls back to the
28
+ * next backend. Without the pin the absent-service case does not throw; see
29
+ * the module note.
26
30
  */
27
31
  var KeyringBackend = class {
28
- constructor(config = {}) {
29
- this.serviceName = config.service ?? "aishell-dsh";
32
+ constructor(_config = {}) {
33
+ this.serviceName = KEYRING_SERVICE;
34
+ this.options = { linux: { store: "secret-service" } };
30
35
  this.Entry = loadKeyring().Entry;
31
- new this.Entry(this.serviceName, "__probe__").getPassword();
36
+ new this.Entry(this.serviceName, "__probe__", this.options).getPassword();
32
37
  }
33
38
  get(account) {
34
39
  try {
35
- const value = new this.Entry(this.serviceName, account).getPassword();
40
+ const value = new this.Entry(this.serviceName, account, this.options).getPassword();
36
41
  return value ?? void 0;
37
42
  } catch {
38
43
  return void 0;
@@ -40,18 +45,18 @@ var KeyringBackend = class {
40
45
  }
41
46
  set(account, value) {
42
47
  if (value.length === 0) throw new Error("credential value must be non-empty");
43
- new this.Entry(this.serviceName, account).setPassword(value);
48
+ new this.Entry(this.serviceName, account, this.options).setPassword(value);
44
49
  }
45
50
  delete(account) {
46
51
  try {
47
- new this.Entry(this.serviceName, account).deletePassword();
52
+ new this.Entry(this.serviceName, account, this.options).deletePassword();
48
53
  } catch (error) {
49
54
  if (!String(error).includes("not found") && !String(error).includes("no entry")) throw error;
50
55
  }
51
56
  }
52
57
  has(account) {
53
58
  try {
54
- return new this.Entry(this.serviceName, account).getPassword() !== null;
59
+ return new this.Entry(this.serviceName, account, this.options).getPassword() !== null;
55
60
  } catch {
56
61
  return false;
57
62
  }
@@ -98,26 +103,20 @@ function fingerprintDecrypt(data) {
98
103
  /**
99
104
  * Resolve the directory holding the encrypted credentials file.
100
105
  *
101
- * Priority: an explicit `config.credentialsDir` override → the host's
102
- * `DSH_HOME` (so credentials live alongside the rest of that host's data —
103
- * `~/.aishell/credentials` for the desktop app, `~/.dsh/credentials` for the
104
- * dsh CLI) → a standalone `~/.aishell-dsh` fallback for headless / library
105
- * use where no DSH host is involved.
106
+ * An explicit `config.credentialsDir` wins; otherwise `<DSH_HOME>/credentials`,
107
+ * resolved by the shared `paths` module so the terraform cache in
108
+ * `aishell-deploy` cannot drift to a different home.
106
109
  *
107
- * The `service` config still names the keyring service (and the fallback
108
- * directory name when neither `credentialsDir` nor `DSH_HOME` is set).
110
+ * Builds are separated by the *file name* — see `../scope.ts` — not by the
111
+ * directory.
109
112
  */
110
113
  function resolveCredentialsDir(config) {
111
- if (config.credentialsDir !== void 0) return config.credentialsDir;
112
- const dshHome = process.env.DSH_HOME;
113
- if (dshHome !== void 0 && dshHome.trim() !== "") return join(dshHome, "credentials");
114
- const dirName = config.service ?? "aishell-dsh";
115
- return join(homedir(), `.${dirName}`);
114
+ return config.credentialsDir ?? credentialsDir();
116
115
  }
117
116
  /**
118
117
  * Encrypted-file {@link CredentialsStore}. Each account is one entry in a
119
118
  * single JSON map, encrypted as one file under the resolved credentials
120
- * directory (`$DSH_HOME/credentials/credentials.enc` by default).
119
+ * directory, named by the build's credential scope (see `../scope.ts`).
121
120
  *
122
121
  * Construction probes the machine ID + crypto — if `node-machine-id` cannot
123
122
  * resolve a UUID, construction throws and the factory falls back to
@@ -126,7 +125,7 @@ function resolveCredentialsDir(config) {
126
125
  var FingerprintBackend = class {
127
126
  constructor(config = {}) {
128
127
  this.fileDir = resolveCredentialsDir(config);
129
- this.filePath = join(this.fileDir, "credentials.enc");
128
+ this.filePath = join(this.fileDir, CREDENTIALS_FILE_NAME);
130
129
  deriveKey();
131
130
  }
132
131
  /**
@@ -330,7 +329,6 @@ var FailoverStore = class {
330
329
  * collection was locked is not shadowed by the keyring's stale copy once it
331
330
  * unlocks.
332
331
  *
333
- * @param config - optional service name override.
334
332
  * @returns the highest-priority backend that could initialize.
335
333
  */
336
334
  function createCredentialsStore(config = {}) {
@@ -353,5 +351,5 @@ function createFallbackStore(config) {
353
351
  }
354
352
 
355
353
  //#endregion
356
- export { FailoverStore, FingerprintBackend, KeyringBackend, MemoryBackend, __setKeyringModule, createCredentialsStore };
354
+ export { CREDENTIALS_FILE_NAME, CREDENTIAL_SCOPE, DEFAULT_SCOPE, FailoverStore, FingerprintBackend, KEYRING_SERVICE, KeyringBackend, MemoryBackend, __setKeyringModule, createCredentialsStore };
357
355
  //# sourceMappingURL=index.js.map