@skrr-ai/auth-core 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/cjs/aead.d.ts +24 -0
- package/dist/cjs/aead.js +65 -0
- package/dist/cjs/authExpiredDetector.d.ts +65 -0
- package/dist/cjs/authExpiredDetector.js +89 -0
- package/dist/cjs/authHelper.d.ts +51 -0
- package/dist/cjs/authHelper.js +321 -0
- package/dist/cjs/credentialEnvelope.d.ts +85 -0
- package/dist/cjs/credentialEnvelope.js +230 -0
- package/dist/cjs/credentialEnvelopeBridge.d.ts +116 -0
- package/dist/cjs/credentialEnvelopeBridge.js +637 -0
- package/dist/cjs/credentialResolver.d.ts +278 -0
- package/dist/cjs/credentialResolver.js +423 -0
- package/dist/cjs/daemonPair.d.ts +172 -0
- package/dist/cjs/daemonPair.js +495 -0
- package/dist/cjs/daemonScopes.d.ts +74 -0
- package/dist/cjs/daemonScopes.js +84 -0
- package/dist/cjs/deviceIdentityBridge.d.ts +113 -0
- package/dist/cjs/deviceIdentityBridge.js +591 -0
- package/dist/cjs/deviceKey.d.ts +167 -0
- package/dist/cjs/deviceKey.js +332 -0
- package/dist/cjs/fdToken.d.ts +17 -0
- package/dist/cjs/fdToken.js +238 -0
- package/dist/cjs/harnessTrust.d.ts +72 -0
- package/dist/cjs/harnessTrust.js +103 -0
- package/dist/cjs/headers-helper.d.ts +25 -0
- package/dist/cjs/headers-helper.js +323 -0
- package/dist/cjs/index.d.ts +37 -0
- package/dist/cjs/index.js +305 -0
- package/dist/cjs/jwtUtils.d.ts +35 -0
- package/dist/cjs/jwtUtils.js +61 -0
- package/dist/cjs/kek/index.d.ts +89 -0
- package/dist/cjs/kek/index.js +208 -0
- package/dist/cjs/kek/linux.d.ts +92 -0
- package/dist/cjs/kek/linux.js +596 -0
- package/dist/cjs/kek/macos.d.ts +112 -0
- package/dist/cjs/kek/macos.js +599 -0
- package/dist/cjs/kek/types.d.ts +111 -0
- package/dist/cjs/kek/types.js +43 -0
- package/dist/cjs/kek/windows.d.ts +71 -0
- package/dist/cjs/kek/windows.js +350 -0
- package/dist/cjs/kek/zeroize-registry.d.ts +44 -0
- package/dist/cjs/kek/zeroize-registry.js +63 -0
- package/dist/cjs/legacyStatePreflight.d.ts +67 -0
- package/dist/cjs/legacyStatePreflight.js +78 -0
- package/dist/cjs/localIdentity.d.ts +54 -0
- package/dist/cjs/localIdentity.js +57 -0
- package/dist/cjs/loginLocalhost.d.ts +115 -0
- package/dist/cjs/loginLocalhost.js +368 -0
- package/dist/cjs/loginWithLocalhost.d.ts +131 -0
- package/dist/cjs/loginWithLocalhost.js +359 -0
- package/dist/cjs/machineId.d.ts +35 -0
- package/dist/cjs/machineId.js +239 -0
- package/dist/cjs/messages.d.ts +9 -0
- package/dist/cjs/messages.js +44 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/pkce.d.ts +62 -0
- package/dist/cjs/pkce.js +158 -0
- package/dist/cjs/recoveryCode.d.ts +61 -0
- package/dist/cjs/recoveryCode.js +213 -0
- package/dist/cjs/refresh.d.ts +215 -0
- package/dist/cjs/refresh.js +877 -0
- package/dist/cjs/refreshClassification.d.ts +53 -0
- package/dist/cjs/refreshClassification.js +105 -0
- package/dist/cjs/refreshScheduler.d.ts +53 -0
- package/dist/cjs/refreshScheduler.js +332 -0
- package/dist/cjs/runtime.d.ts +149 -0
- package/dist/cjs/runtime.js +136 -0
- package/dist/cjs/spawnEnv.d.ts +76 -0
- package/dist/cjs/spawnEnv.js +153 -0
- package/dist/cjs/ttlParser.d.ts +54 -0
- package/dist/cjs/ttlParser.js +87 -0
- package/dist/cjs/types.d.ts +91 -0
- package/dist/cjs/types.js +26 -0
- package/dist/esm/aead.d.ts +24 -0
- package/dist/esm/aead.js +57 -0
- package/dist/esm/authExpiredDetector.d.ts +65 -0
- package/dist/esm/authExpiredDetector.js +85 -0
- package/dist/esm/authHelper.d.ts +51 -0
- package/dist/esm/authHelper.js +311 -0
- package/dist/esm/credentialEnvelope.d.ts +85 -0
- package/dist/esm/credentialEnvelope.js +213 -0
- package/dist/esm/credentialEnvelopeBridge.d.ts +116 -0
- package/dist/esm/credentialEnvelopeBridge.js +620 -0
- package/dist/esm/credentialResolver.d.ts +278 -0
- package/dist/esm/credentialResolver.js +414 -0
- package/dist/esm/daemonPair.d.ts +172 -0
- package/dist/esm/daemonPair.js +476 -0
- package/dist/esm/daemonScopes.d.ts +74 -0
- package/dist/esm/daemonScopes.js +80 -0
- package/dist/esm/deviceIdentityBridge.d.ts +113 -0
- package/dist/esm/deviceIdentityBridge.js +572 -0
- package/dist/esm/deviceKey.d.ts +167 -0
- package/dist/esm/deviceKey.js +320 -0
- package/dist/esm/fdToken.d.ts +17 -0
- package/dist/esm/fdToken.js +231 -0
- package/dist/esm/harnessTrust.d.ts +72 -0
- package/dist/esm/harnessTrust.js +97 -0
- package/dist/esm/headers-helper.d.ts +25 -0
- package/dist/esm/headers-helper.js +316 -0
- package/dist/esm/index.d.ts +37 -0
- package/dist/esm/index.js +144 -0
- package/dist/esm/jwtUtils.d.ts +35 -0
- package/dist/esm/jwtUtils.js +57 -0
- package/dist/esm/kek/index.d.ts +89 -0
- package/dist/esm/kek/index.js +162 -0
- package/dist/esm/kek/linux.d.ts +92 -0
- package/dist/esm/kek/linux.js +585 -0
- package/dist/esm/kek/macos.d.ts +112 -0
- package/dist/esm/kek/macos.js +586 -0
- package/dist/esm/kek/types.d.ts +111 -0
- package/dist/esm/kek/types.js +39 -0
- package/dist/esm/kek/windows.d.ts +71 -0
- package/dist/esm/kek/windows.js +344 -0
- package/dist/esm/kek/zeroize-registry.d.ts +44 -0
- package/dist/esm/kek/zeroize-registry.js +58 -0
- package/dist/esm/legacyStatePreflight.d.ts +67 -0
- package/dist/esm/legacyStatePreflight.js +71 -0
- package/dist/esm/localIdentity.d.ts +54 -0
- package/dist/esm/localIdentity.js +54 -0
- package/dist/esm/loginLocalhost.d.ts +115 -0
- package/dist/esm/loginLocalhost.js +355 -0
- package/dist/esm/loginWithLocalhost.d.ts +131 -0
- package/dist/esm/loginWithLocalhost.js +353 -0
- package/dist/esm/machineId.d.ts +35 -0
- package/dist/esm/machineId.js +231 -0
- package/dist/esm/messages.d.ts +9 -0
- package/dist/esm/messages.js +40 -0
- package/dist/esm/pkce.d.ts +62 -0
- package/dist/esm/pkce.js +148 -0
- package/dist/esm/recoveryCode.d.ts +61 -0
- package/dist/esm/recoveryCode.js +207 -0
- package/dist/esm/refresh.d.ts +215 -0
- package/dist/esm/refresh.js +863 -0
- package/dist/esm/refreshClassification.d.ts +53 -0
- package/dist/esm/refreshClassification.js +106 -0
- package/dist/esm/refreshScheduler.d.ts +53 -0
- package/dist/esm/refreshScheduler.js +329 -0
- package/dist/esm/runtime.d.ts +149 -0
- package/dist/esm/runtime.js +121 -0
- package/dist/esm/spawnEnv.d.ts +76 -0
- package/dist/esm/spawnEnv.js +149 -0
- package/dist/esm/ttlParser.d.ts +54 -0
- package/dist/esm/ttlParser.js +83 -0
- package/dist/esm/types.d.ts +91 -0
- package/dist/esm/types.js +21 -0
- package/package.json +82 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kek/index.ts — platform selector for the Key Encryption Key strategy.
|
|
3
|
+
*
|
|
4
|
+
* Resolves a single KEK implementation based on `process.platform` at
|
|
5
|
+
* call time. The returned strategy may report `available=false` (e.g.,
|
|
6
|
+
* the native binding hasn't shipped on the current platform yet) — the
|
|
7
|
+
* daemon's integration code MUST honor that and fall through to the
|
|
8
|
+
* legacy plaintext path with a `cred_envelope.kek_unavailable` event.
|
|
9
|
+
*
|
|
10
|
+
* Test seam: `__setKekStrategyForTest()` lets unit tests inject a
|
|
11
|
+
* synthetic strategy with a deterministic in-memory KEK so the
|
|
12
|
+
* dual-read / re-encrypt-on-migration paths can be exercised without a
|
|
13
|
+
* real platform binding.
|
|
14
|
+
*/
|
|
15
|
+
import type { KekStrategy } from './types.js';
|
|
16
|
+
export type { KekStrategy } from './types.js';
|
|
17
|
+
export { KekUnavailableError } from './types.js';
|
|
18
|
+
export { MacosKek } from './macos.js';
|
|
19
|
+
export { LinuxKek } from './linux.js';
|
|
20
|
+
export { WindowsKek } from './windows.js';
|
|
21
|
+
export { zeroizeKekCaches, registerZeroizeHook } from './zeroize-registry.js';
|
|
22
|
+
/**
|
|
23
|
+
* @internal Test-only seam — inject a synthetic KEK strategy that wraps
|
|
24
|
+
* with a fixed in-memory key. Resets to platform default when called
|
|
25
|
+
* with `null`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function __setKekStrategyForTest(strategy: KekStrategy | null): void;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the KEK strategy for the current process. Returns the test
|
|
30
|
+
* override when set; otherwise selects by `process.platform`.
|
|
31
|
+
*
|
|
32
|
+
* Idempotent and side-effect-free — the strategy is constructed fresh
|
|
33
|
+
* on each call. Implementations must keep their own caches if probing
|
|
34
|
+
* is expensive (none of the current stubs do).
|
|
35
|
+
*/
|
|
36
|
+
export declare function getKekStrategy(): KekStrategy;
|
|
37
|
+
/**
|
|
38
|
+
* In-memory KEK strategy backed by a fixed buffer. Useful for tests and
|
|
39
|
+
* for a future `--kek=file:<path>` opt-in for users who explicitly
|
|
40
|
+
* waive platform-native protection (e.g., headless CI on a hardened
|
|
41
|
+
* VM where DPAPI isn't reachable). Do NOT default to this in production
|
|
42
|
+
* paths — it provides no protection beyond filesystem permissions on
|
|
43
|
+
* whatever holds the buffer.
|
|
44
|
+
*/
|
|
45
|
+
export declare class InMemoryKek implements KekStrategy {
|
|
46
|
+
readonly id = "in-memory-test";
|
|
47
|
+
private readonly key;
|
|
48
|
+
constructor(key: Buffer);
|
|
49
|
+
/**
|
|
50
|
+
* Stable backend identifier surfaced via `KekStrategy.kind`. Distinct
|
|
51
|
+
* from the MacosKek shellout / NAPI kinds so telemetry filters can
|
|
52
|
+
* exclude in-memory test traffic from fleet dashboards.
|
|
53
|
+
*/
|
|
54
|
+
get kind(): string;
|
|
55
|
+
available(): Promise<boolean>;
|
|
56
|
+
wrap(dek: Buffer, aad?: Buffer): Promise<Buffer>;
|
|
57
|
+
unwrap(wrapped: Buffer, aad?: Buffer): Promise<Buffer>;
|
|
58
|
+
unwrapExisting(wrapped: Buffer, aad?: Buffer): Promise<Buffer>;
|
|
59
|
+
describe(): string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Test double for the KEK-UNAVAILABLE branch — the twin of `InMemoryKek`.
|
|
63
|
+
*
|
|
64
|
+
* It exists because "no KEK on this platform" cannot be expressed by passing
|
|
65
|
+
* `null` to `__setKekStrategyForTest`. `null` means "use the platform
|
|
66
|
+
* default", and the platform defaults do not agree: `LinuxKek` essentially
|
|
67
|
+
* always resolves (tier-3 derives a KEK from machine identity when libsecret
|
|
68
|
+
* is absent), `MacosKek` resolves only when a login keychain can be found —
|
|
69
|
+
* which a test that sandboxes `HOME` accidentally prevents — and `WindowsKek`
|
|
70
|
+
* is still a stub. A suite that wants the unavailable branch and passes `null`
|
|
71
|
+
* is therefore not testing that branch; it is testing which machine it landed
|
|
72
|
+
* on, and it flips from green to red when the machine changes.
|
|
73
|
+
*
|
|
74
|
+
* That is not hypothetical: four daemon suites asserting fail-closed behaviour
|
|
75
|
+
* passed on macOS purely because their temp `HOME` hid the keychain, and went
|
|
76
|
+
* red the first time CI ever executed them on Linux.
|
|
77
|
+
*
|
|
78
|
+
* `wrap`/`unwrap` throw rather than returning junk, matching the contract in
|
|
79
|
+
* `types.ts`: a strategy that reports unavailable must never silently produce
|
|
80
|
+
* ciphertext a caller could mistake for protected material.
|
|
81
|
+
*/
|
|
82
|
+
export declare class UnavailableKek implements KekStrategy {
|
|
83
|
+
readonly id = "unavailable-test";
|
|
84
|
+
get kind(): string;
|
|
85
|
+
available(): Promise<boolean>;
|
|
86
|
+
wrap(): Promise<Buffer>;
|
|
87
|
+
unwrap(): Promise<Buffer>;
|
|
88
|
+
describe(): string;
|
|
89
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { KekUnavailableError } from './types.js';
|
|
2
|
+
import { MacosKek } from './macos.js';
|
|
3
|
+
import { LinuxKek } from './linux.js';
|
|
4
|
+
import { WindowsKek } from './windows.js';
|
|
5
|
+
export { KekUnavailableError } from './types.js';
|
|
6
|
+
export { MacosKek } from './macos.js';
|
|
7
|
+
export { LinuxKek } from './linux.js';
|
|
8
|
+
export { WindowsKek } from './windows.js';
|
|
9
|
+
export { zeroizeKekCaches, registerZeroizeHook } from './zeroize-registry.js';
|
|
10
|
+
/**
|
|
11
|
+
* Strategy used when the current platform has no implementation. Always
|
|
12
|
+
* unavailable; never throws on probe. Provides an honest `id` so fleet
|
|
13
|
+
* telemetry can distinguish "we have no KEK on this platform" from
|
|
14
|
+
* "the platform's KEK probe failed."
|
|
15
|
+
*/
|
|
16
|
+
class UnsupportedPlatformKek {
|
|
17
|
+
id;
|
|
18
|
+
platform;
|
|
19
|
+
constructor(platform) {
|
|
20
|
+
this.platform = platform;
|
|
21
|
+
this.id = `unsupported-${platform}`;
|
|
22
|
+
}
|
|
23
|
+
async available() {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
async wrap() {
|
|
27
|
+
throw new KekUnavailableError(this.id, `KEK unsupported on platform ${this.platform}`);
|
|
28
|
+
}
|
|
29
|
+
async unwrap() {
|
|
30
|
+
throw new KekUnavailableError(this.id, `KEK unsupported on platform ${this.platform}`);
|
|
31
|
+
}
|
|
32
|
+
describe() {
|
|
33
|
+
return `unsupported platform: ${this.platform}`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
let _override = null;
|
|
37
|
+
/**
|
|
38
|
+
* @internal Test-only seam — inject a synthetic KEK strategy that wraps
|
|
39
|
+
* with a fixed in-memory key. Resets to platform default when called
|
|
40
|
+
* with `null`.
|
|
41
|
+
*/
|
|
42
|
+
export function __setKekStrategyForTest(strategy) {
|
|
43
|
+
_override = strategy;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the KEK strategy for the current process. Returns the test
|
|
47
|
+
* override when set; otherwise selects by `process.platform`.
|
|
48
|
+
*
|
|
49
|
+
* Idempotent and side-effect-free — the strategy is constructed fresh
|
|
50
|
+
* on each call. Implementations must keep their own caches if probing
|
|
51
|
+
* is expensive (none of the current stubs do).
|
|
52
|
+
*/
|
|
53
|
+
export function getKekStrategy() {
|
|
54
|
+
if (_override)
|
|
55
|
+
return _override;
|
|
56
|
+
switch (process.platform) {
|
|
57
|
+
case 'darwin':
|
|
58
|
+
// C5 (shipped): macOS uses the `security(1)` shellout backend with
|
|
59
|
+
// a Secure Enclave NAPI binding preferred when present. Backend
|
|
60
|
+
// selection happens inside MacosKek; no dispatch change required.
|
|
61
|
+
return new MacosKek();
|
|
62
|
+
case 'linux':
|
|
63
|
+
// TODO(L12): Linux libsecret + machine-id-derived KEK is still a
|
|
64
|
+
// stub. Planned approach: shellout to `secret-tool`, modeled after
|
|
65
|
+
// the macOS shellout pattern shipped in C5. See
|
|
66
|
+
// `docs/daemon-auth-l12-kek-platform-bindings.md` §5.
|
|
67
|
+
return new LinuxKek();
|
|
68
|
+
case 'win32':
|
|
69
|
+
// TODO(L12): Windows DPAPI KEK is still a stub. Planned approach:
|
|
70
|
+
// PowerShell shellout invoking ProtectedData.Protect (or a future
|
|
71
|
+
// dpapi NAPI binding). See
|
|
72
|
+
// `docs/daemon-auth-l12-kek-platform-bindings.md` §5.
|
|
73
|
+
return new WindowsKek();
|
|
74
|
+
default:
|
|
75
|
+
return new UnsupportedPlatformKek(process.platform);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* In-memory KEK strategy backed by a fixed buffer. Useful for tests and
|
|
80
|
+
* for a future `--kek=file:<path>` opt-in for users who explicitly
|
|
81
|
+
* waive platform-native protection (e.g., headless CI on a hardened
|
|
82
|
+
* VM where DPAPI isn't reachable). Do NOT default to this in production
|
|
83
|
+
* paths — it provides no protection beyond filesystem permissions on
|
|
84
|
+
* whatever holds the buffer.
|
|
85
|
+
*/
|
|
86
|
+
export class InMemoryKek {
|
|
87
|
+
id = 'in-memory-test';
|
|
88
|
+
key;
|
|
89
|
+
constructor(key) {
|
|
90
|
+
if (!Buffer.isBuffer(key) || key.length !== 32) {
|
|
91
|
+
throw new TypeError('InMemoryKek: key must be a 32-byte Buffer');
|
|
92
|
+
}
|
|
93
|
+
this.key = Buffer.from(key);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Stable backend identifier surfaced via `KekStrategy.kind`. Distinct
|
|
97
|
+
* from the MacosKek shellout / NAPI kinds so telemetry filters can
|
|
98
|
+
* exclude in-memory test traffic from fleet dashboards.
|
|
99
|
+
*/
|
|
100
|
+
get kind() {
|
|
101
|
+
return 'in-memory-test';
|
|
102
|
+
}
|
|
103
|
+
async available() {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
async wrap(dek, aad) {
|
|
107
|
+
const { sealBuffer, serialize } = await import('../credentialEnvelope.js');
|
|
108
|
+
return Buffer.from(serialize(sealBuffer(dek, this.key, aad)), 'utf-8');
|
|
109
|
+
}
|
|
110
|
+
async unwrap(wrapped, aad) {
|
|
111
|
+
const { deserialize, openBuffer } = await import('../credentialEnvelope.js');
|
|
112
|
+
const sealed = deserialize(wrapped.toString('utf-8'));
|
|
113
|
+
if (!sealed)
|
|
114
|
+
throw new KekUnavailableError(this.id, 'InMemoryKek: malformed wrapped blob');
|
|
115
|
+
return openBuffer(sealed, this.key, aad);
|
|
116
|
+
}
|
|
117
|
+
async unwrapExisting(wrapped, aad) {
|
|
118
|
+
return this.unwrap(wrapped, aad);
|
|
119
|
+
}
|
|
120
|
+
describe() {
|
|
121
|
+
return 'in-memory test KEK (NOT FOR PRODUCTION)';
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Test double for the KEK-UNAVAILABLE branch — the twin of `InMemoryKek`.
|
|
126
|
+
*
|
|
127
|
+
* It exists because "no KEK on this platform" cannot be expressed by passing
|
|
128
|
+
* `null` to `__setKekStrategyForTest`. `null` means "use the platform
|
|
129
|
+
* default", and the platform defaults do not agree: `LinuxKek` essentially
|
|
130
|
+
* always resolves (tier-3 derives a KEK from machine identity when libsecret
|
|
131
|
+
* is absent), `MacosKek` resolves only when a login keychain can be found —
|
|
132
|
+
* which a test that sandboxes `HOME` accidentally prevents — and `WindowsKek`
|
|
133
|
+
* is still a stub. A suite that wants the unavailable branch and passes `null`
|
|
134
|
+
* is therefore not testing that branch; it is testing which machine it landed
|
|
135
|
+
* on, and it flips from green to red when the machine changes.
|
|
136
|
+
*
|
|
137
|
+
* That is not hypothetical: four daemon suites asserting fail-closed behaviour
|
|
138
|
+
* passed on macOS purely because their temp `HOME` hid the keychain, and went
|
|
139
|
+
* red the first time CI ever executed them on Linux.
|
|
140
|
+
*
|
|
141
|
+
* `wrap`/`unwrap` throw rather than returning junk, matching the contract in
|
|
142
|
+
* `types.ts`: a strategy that reports unavailable must never silently produce
|
|
143
|
+
* ciphertext a caller could mistake for protected material.
|
|
144
|
+
*/
|
|
145
|
+
export class UnavailableKek {
|
|
146
|
+
id = 'unavailable-test';
|
|
147
|
+
get kind() {
|
|
148
|
+
return 'unavailable-test';
|
|
149
|
+
}
|
|
150
|
+
async available() {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
async wrap() {
|
|
154
|
+
throw new KekUnavailableError(this.id, 'UnavailableKek: wrap called while unavailable');
|
|
155
|
+
}
|
|
156
|
+
async unwrap() {
|
|
157
|
+
throw new KekUnavailableError(this.id, 'UnavailableKek: unwrap called while unavailable');
|
|
158
|
+
}
|
|
159
|
+
describe() {
|
|
160
|
+
return 'unavailable test KEK (forces the kek_unavailable branch)';
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { KekStrategy } from './types.js';
|
|
2
|
+
/** Stable telemetry kind strings — one per backend tier. */
|
|
3
|
+
declare const KIND_LIBSECRET = "linux-libsecret-shellout";
|
|
4
|
+
declare const KIND_HKDF = "linux-machineid-hkdf";
|
|
5
|
+
/**
|
|
6
|
+
* Type for the execFile mock. Accepts an optional `input` in options so
|
|
7
|
+
* tests can assert the stdin payload passed to `secret-tool store`.
|
|
8
|
+
*/
|
|
9
|
+
type ExecFileLike = (file: string, args: readonly string[], options?: {
|
|
10
|
+
encoding?: BufferEncoding;
|
|
11
|
+
input?: string;
|
|
12
|
+
}) => Promise<{
|
|
13
|
+
stdout: string;
|
|
14
|
+
stderr: string;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* @internal Test seam — inject a mock execFile for hermetic tests so the
|
|
18
|
+
* suite never touches the real Secret Service. Reset to `null` to restore
|
|
19
|
+
* the real `child_process.execFile`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function __setExecFileForTest(fn: ExecFileLike | null): void;
|
|
22
|
+
type ReadFileSyncLike = (path: string, encoding: BufferEncoding) => string;
|
|
23
|
+
/**
|
|
24
|
+
* @internal Test seam — inject a mock readFileSync so Tier-3 derivation
|
|
25
|
+
* tests can drive deterministic IKM without writing to /proc or /etc.
|
|
26
|
+
* Reset to `null` to restore the real `fs.readFileSync`. Pass `null` to
|
|
27
|
+
* also clear the tier selection + KEK cache so the next call re-probes.
|
|
28
|
+
*/
|
|
29
|
+
export declare function __setFsForTest(fn: ReadFileSyncLike | null): void;
|
|
30
|
+
/**
|
|
31
|
+
* Zero out and drop every in-process master-KEK cache buffer (both the
|
|
32
|
+
* Tier-2 by-service map and the Tier-3 single buffer).
|
|
33
|
+
*
|
|
34
|
+
* Must be called on:
|
|
35
|
+
* - Daemon shutdown (SIGTERM / SIGINT) so the KEK does not linger in
|
|
36
|
+
* memory across the process exit window where coredumps could land.
|
|
37
|
+
* - KEK rotation, after the new KEK has been resolved.
|
|
38
|
+
* - Logout flows that wipe at-rest credentials.
|
|
39
|
+
*
|
|
40
|
+
* Idempotent — safe to call when the caches are already empty.
|
|
41
|
+
*/
|
|
42
|
+
export declare function zeroizeLinuxKekCache(): void;
|
|
43
|
+
/** @internal Test seam — clear the in-process master-KEK cache + tier
|
|
44
|
+
* selection. Routes through the production zeroize helper so the
|
|
45
|
+
* test-reset path exercises the same buffer-fill that ships in
|
|
46
|
+
* production, and additionally clears `_tierSelection` so a subsequent
|
|
47
|
+
* test re-probes (otherwise Tier-3 caching across tests poisons later
|
|
48
|
+
* cases). */
|
|
49
|
+
export declare function __resetKekCacheForTest(): void;
|
|
50
|
+
export declare class LinuxKek implements KekStrategy {
|
|
51
|
+
readonly id = "linux-libsecret-machineid";
|
|
52
|
+
private _lastKind;
|
|
53
|
+
private readonly service;
|
|
54
|
+
private readonly account;
|
|
55
|
+
/**
|
|
56
|
+
* Construct a Linux KEK strategy.
|
|
57
|
+
*
|
|
58
|
+
* @param opts.service Optional Secret Service `service` attribute used
|
|
59
|
+
* by Tier-2 `secret-tool lookup`/`store`. Defaults to
|
|
60
|
+
* `'ai.skrr.daemon.kek'`. Override only for test isolation /
|
|
61
|
+
* smoke tests; production callers should use the default so different
|
|
62
|
+
* daemon processes on the same host share the same KEK and can unwrap
|
|
63
|
+
* each other's persisted credentials. Ignored on the Tier-3 (HKDF)
|
|
64
|
+
* path. Callers that override are responsible for cleaning up the
|
|
65
|
+
* corresponding Secret Service entry when done.
|
|
66
|
+
* @param opts.account Optional Secret Service `account` attribute.
|
|
67
|
+
* Defaults to `'master-kek-v1'`. Same scoping rules as `service`.
|
|
68
|
+
*/
|
|
69
|
+
constructor(opts?: {
|
|
70
|
+
service?: string;
|
|
71
|
+
account?: string;
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* Telemetry kind of the most recent successful wrap/unwrap. `null` before
|
|
75
|
+
* any call. After the first successful wrap or unwrap, one of:
|
|
76
|
+
* - `'linux-libsecret-shellout'` (Tier-2)
|
|
77
|
+
* - `'linux-machineid-hkdf'` (Tier-3)
|
|
78
|
+
*/
|
|
79
|
+
get kind(): typeof KIND_LIBSECRET | typeof KIND_HKDF | null;
|
|
80
|
+
/**
|
|
81
|
+
* `available()` is true on Linux when EITHER backend can satisfy a
|
|
82
|
+
* wrap: libsecret is reachable, or `/etc/machine-id` exists so Tier-3
|
|
83
|
+
* derivation can succeed. Probe results are cached for the process
|
|
84
|
+
* lifetime.
|
|
85
|
+
*/
|
|
86
|
+
available(): Promise<boolean>;
|
|
87
|
+
wrap(dek: Buffer, aad?: Buffer): Promise<Buffer>;
|
|
88
|
+
unwrap(wrapped: Buffer, aad?: Buffer): Promise<Buffer>;
|
|
89
|
+
unwrapExisting(wrapped: Buffer, aad?: Buffer): Promise<Buffer>;
|
|
90
|
+
describe(): string;
|
|
91
|
+
}
|
|
92
|
+
export {};
|