@moxxy/e2e 0.27.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.
package/src/node.ts ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Node-only identity persistence for `@moxxy/e2e`. Kept off the `.` export so the
3
+ * RN bundle never pulls `node:fs`. The secret key is stored once per install at
4
+ * `~/.moxxy/proxy-identity.key` (mode 0600, atomic write — same invariant the
5
+ * vault/sessions use), and the public key is derived from it on load.
6
+ */
7
+ import { readFile } from 'node:fs/promises';
8
+ import { moxxyPath, writeFileAtomic } from '@moxxy/sdk/server';
9
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
10
+ import { generateIdentity, publicKeyFromSecret, type Identity } from './identity.js';
11
+
12
+ /** Default on-disk location of the agent's proxy identity secret key. */
13
+ export function defaultIdentityPath(): string {
14
+ return moxxyPath('proxy-identity.key');
15
+ }
16
+
17
+ /**
18
+ * Load the agent identity from disk, generating and persisting a fresh one on
19
+ * first run. The returned identity is stable across restarts, so the agent keeps
20
+ * the same uuid subdomain and the same pinned fingerprint.
21
+ */
22
+ export async function loadOrCreateIdentity(path: string = defaultIdentityPath()): Promise<Identity> {
23
+ let hex: string | null = null;
24
+ try {
25
+ hex = (await readFile(path, 'utf8')).trim();
26
+ } catch (err) {
27
+ // Missing file → first run (generate below). Anything else (e.g. EACCES) is real.
28
+ if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;
29
+ }
30
+ if (hex !== null) {
31
+ try {
32
+ const secretKey = hexToBytes(hex);
33
+ if (secretKey.length === 32) {
34
+ return { secretKey, publicKey: publicKeyFromSecret(secretKey) };
35
+ }
36
+ } catch {
37
+ // Malformed contents → fall through and regenerate.
38
+ }
39
+ }
40
+ const identity = generateIdentity();
41
+ await writeFileAtomic(path, bytesToHex(identity.secretKey), { mode: 0o600 });
42
+ return identity;
43
+ }