epistery 2.0.3 → 2.1.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 (47) hide show
  1. package/.test.env +25 -0
  2. package/cli/epistery.mjs +9 -10
  3. package/client/wallet.js +30 -7
  4. package/client/witness.js +29 -12
  5. package/dist/chains/registry.d.ts +2 -2
  6. package/dist/chains/registry.d.ts.map +1 -1
  7. package/dist/chains/registry.js +4 -4
  8. package/dist/chains/registry.js.map +1 -1
  9. package/dist/epistery.d.ts +1 -1
  10. package/dist/epistery.d.ts.map +1 -1
  11. package/dist/epistery.js +4 -4
  12. package/dist/epistery.js.map +1 -1
  13. package/dist/utils/CliWallet.d.ts +9 -5
  14. package/dist/utils/CliWallet.d.ts.map +1 -1
  15. package/dist/utils/CliWallet.js +18 -13
  16. package/dist/utils/CliWallet.js.map +1 -1
  17. package/dist/utils/Config.d.ts +101 -48
  18. package/dist/utils/Config.d.ts.map +1 -1
  19. package/dist/utils/Config.js +257 -116
  20. package/dist/utils/Config.js.map +1 -1
  21. package/dist/utils/Utils.d.ts +10 -2
  22. package/dist/utils/Utils.d.ts.map +1 -1
  23. package/dist/utils/Utils.js +18 -9
  24. package/dist/utils/Utils.js.map +1 -1
  25. package/docs/RivetSignerConfigAuthority.md +219 -0
  26. package/index.mjs +10 -9
  27. package/package.json +1 -1
  28. package/routes/auth.mjs +6 -6
  29. package/routes/domain.mjs +2 -2
  30. package/routes/fido.mjs +4 -4
  31. package/src/chains/registry.ts +4 -4
  32. package/src/epistery.ts +4 -4
  33. package/src/utils/CliWallet.ts +18 -13
  34. package/src/utils/Config.ts +289 -106
  35. package/src/utils/Utils.ts +19 -9
  36. package/test/config/.epistery/127.0.0.1/config.ini +15 -0
  37. package/test/config/.epistery/config.ini +14 -0
  38. package/test/config/.epistery/localhost/config.ini +16 -0
  39. package/test/config/.epistery/no-pending-claim.local/config.ini +15 -0
  40. package/test/config/.epistery/test-claim-1782325887560.local/config.ini +20 -0
  41. package/test/config/.epistery/test-idempotent-1782325887610.local/config.ini +20 -0
  42. package/test/config/.epistery/test-init-1782325888110.local/config.ini +16 -0
  43. package/test/routes/auth.test.ts +7 -3
  44. package/test/routes/identity.test.ts +0 -41
  45. package/test/routes/status.test.ts +5 -39
  46. package/test/setup.ts +9 -9
  47. package/test/utils.ts +9 -3
@@ -1,19 +1,44 @@
1
1
  /**
2
- * Epistery Config - Path-based configuration system
2
+ * Epistery Config async path-based configuration store.
3
3
  *
4
- * Provides unified, filesystem-like config management:
4
+ * Filesystem-like config management, now async so the same interface can be
5
+ * served by a remote authority:
5
6
  * - setPath('/') → ~/.epistery/config.ini
6
7
  * - setPath('/domain') → ~/.epistery/domain/config.ini
7
8
  * - setPath('/.ssl/domain') → ~/.epistery/.ssl/domain/config.ini
8
9
  *
10
+ * `Config` is a thin facade that picks a backend at construction:
11
+ * - if the local bootstrap ~/.epistery/config.ini has [authority] url=…,
12
+ * or EPISTERY_CONFIG_URL is set → RemoteConfig (talks to epistery-authority)
13
+ * - otherwise → LocalConfig (the filesystem store; unchanged semantics)
14
+ *
15
+ * Every IO method is async because a remote/HSM custodian cannot answer
16
+ * synchronously. `data` holds the snapshot from the last awaited load()/setPath().
17
+ *
9
18
  * Usage:
10
19
  * const config = new Config('epistery');
11
- * config.setPath('/wiki.rootz.global');
12
- * config.load();
20
+ * await config.setPath('/wiki.rootz.global'); // loads
13
21
  * config.data.verified = true;
14
- * config.save();
22
+ * await config.save();
23
+ */
24
+ export interface ConfigStore {
25
+ data: any;
26
+ getPath(): string;
27
+ setPath(path: string): Promise<void>;
28
+ load(): Promise<void>;
29
+ read(path: string): Promise<any>;
30
+ save(): Promise<void>;
31
+ readFile(filename: string): Promise<Buffer>;
32
+ writeFile(filename: string, data: string | Buffer): Promise<void>;
33
+ exists(): Promise<boolean>;
34
+ listPaths(): Promise<string[]>;
35
+ }
36
+ /**
37
+ * LocalConfig — the filesystem backend under ~/.epistery. This is the original
38
+ * Config behavior, with all IO made async. It is also what the epistery-authority
39
+ * server mounts as its own storage backend (one implementation, not two).
15
40
  */
16
- export declare class Config {
41
+ export declare class LocalConfig implements ConfigStore {
17
42
  readonly rootName: string;
18
43
  readonly homeDir: string;
19
44
  readonly configDir: string;
@@ -22,50 +47,78 @@ export declare class Config {
22
47
  private currentFile;
23
48
  data: any;
24
49
  constructor(rootName?: string);
25
- /**
26
- * Set current working path and load config (like cd)
27
- * Examples: '/', 'domain', '/domain', '/.ssl/domain'
28
- * Leading slash is optional and will be added if not present
29
- * Automatically loads the config at the specified path
30
- */
31
- setPath(path: string): void;
32
- /**
33
- * Get current path
34
- */
50
+ private initializeSync;
35
51
  getPath(): string;
52
+ setPath(path: string): Promise<void>;
53
+ load(): Promise<void>;
54
+ read(path: string): Promise<any>;
55
+ save(): Promise<void>;
56
+ readFile(filename: string): Promise<Buffer>;
57
+ writeFile(filename: string, data: string | Buffer): Promise<void>;
58
+ exists(): Promise<boolean>;
59
+ listPaths(): Promise<string[]>;
60
+ }
61
+ /**
62
+ * RemoteConfig — HTTP client to an epistery-authority server. Implements the
63
+ * same ConfigStore interface; the authority mounts a LocalConfig behind it.
64
+ *
65
+ * Auth is the rivet key-exchange: the machine signs a challenge with its
66
+ * device key, and the authority issues a bearer token (see epistery-authority
67
+ * lib/auth.mjs). In Phase 1 config data (including the wallet mnemonic) is
68
+ * still served; Phase 2 splits public from secret and adds /sign/*.
69
+ */
70
+ export declare class RemoteConfig implements ConfigStore {
71
+ private readonly baseUrl;
72
+ private readonly machineAddress;
73
+ private readonly signChallenge;
74
+ data: any;
75
+ private currentPath;
76
+ private token;
77
+ constructor(baseUrl: string, machineAddress: string, signChallenge: (message: string) => Promise<string>);
78
+ getPath(): string;
79
+ private authenticate;
80
+ private authedFetch;
81
+ setPath(path: string): Promise<void>;
82
+ load(): Promise<void>;
83
+ read(path: string): Promise<any>;
84
+ save(): Promise<void>;
85
+ private filePrefix;
86
+ readFile(filename: string): Promise<Buffer>;
87
+ writeFile(filename: string, data: string | Buffer): Promise<void>;
88
+ exists(): Promise<boolean>;
89
+ listPaths(): Promise<string[]>;
90
+ }
91
+ /**
92
+ * Config — the public facade. `new Config()` selects the backend synchronously
93
+ * (reading only the local bootstrap), then delegates every async operation.
94
+ * Existing call sites change only by adding `await`.
95
+ */
96
+ export declare class Config implements ConfigStore {
97
+ private readonly backend;
98
+ private readonly local;
99
+ constructor(rootName?: string);
100
+ /** Read the local bootstrap config.ini synchronously (authority selection only). */
101
+ private static readBootstrap;
102
+ private static resolveAuthorityUrl;
36
103
  /**
37
- * Initialize config at current path
38
- */
39
- private initialize;
40
- /**
41
- * Load config from current path
42
- */
43
- load(): void;
44
- /**
45
- * Read config from arbitrary path without changing current path
46
- * @param path Path to read from (e.g., '/', '/domain')
47
- * @returns Parsed config data from that path
48
- */
49
- read(path: string): any;
50
- /**
51
- * Save config to current path
52
- */
53
- save(): void;
54
- /**
55
- * Read file from current path directory
56
- */
57
- readFile(filename: string): Buffer;
58
- /**
59
- * Write file to current path directory
60
- */
61
- writeFile(filename: string, data: string | Buffer): void;
62
- /**
63
- * Check if config exists at current path
64
- */
65
- exists(): boolean;
66
- /**
67
- * List all subdirectories at current path
104
+ * Build the machine signer used to authenticate to the authority. The machine
105
+ * rivet key lives in the local bootstrap [authority] section (Phase 1). A
106
+ * future TPM-backed key replaces this without changing the call site.
68
107
  */
69
- listPaths(): string[];
108
+ private static machineSigner;
109
+ get rootName(): string;
110
+ get homeDir(): string;
111
+ get configDir(): string;
112
+ get data(): any;
113
+ set data(v: any);
114
+ getPath(): string;
115
+ setPath(path: string): Promise<void>;
116
+ load(): Promise<void>;
117
+ read(path: string): Promise<any>;
118
+ save(): Promise<void>;
119
+ readFile(filename: string): Promise<Buffer>;
120
+ writeFile(filename: string, data: string | Buffer): Promise<void>;
121
+ exists(): Promise<boolean>;
122
+ listPaths(): Promise<string[]>;
70
123
  }
71
124
  //# sourceMappingURL=Config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../src/utils/Config.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,qBAAa,MAAM;IACjB,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,SAAS,EAAE,MAAM,CAAC;IAElC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAErB,IAAI,EAAE,GAAG,CAAM;gBAEV,QAAQ,GAAE,MAAmB;IAczC;;;;;OAKG;IACI,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAsBlC;;OAEG;IACI,OAAO,IAAI,MAAM;IAIxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACI,IAAI,IAAI,IAAI;IAUnB;;;;OAIG;IACI,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;IAwB9B;;OAEG;IACI,IAAI,IAAI,IAAI;IASnB;;OAEG;IACI,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAIzC;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO/D;;OAEG;IACI,MAAM,IAAI,OAAO;IAIxB;;OAEG;IACI,SAAS,IAAI,MAAM,EAAE;CAS7B"}
1
+ {"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../src/utils/Config.ts"],"names":[],"mappings":"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"}
@@ -3,26 +3,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Config = void 0;
6
+ exports.Config = exports.RemoteConfig = exports.LocalConfig = void 0;
7
7
  const fs_1 = __importDefault(require("fs"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
8
9
  const path_1 = require("path");
9
10
  const ini_1 = __importDefault(require("ini"));
11
+ const ethers_1 = require("ethers");
12
+ /** Normalize a path: leading slash, no trailing slash, lowercase. */
13
+ function normalizePath(path) {
14
+ path = path.trim();
15
+ if (!path.startsWith('/'))
16
+ path = '/' + path;
17
+ if (path.length > 1 && path.endsWith('/'))
18
+ path = path.slice(0, -1);
19
+ return path.toLowerCase();
20
+ }
10
21
  /**
11
- * Epistery Config - Path-based configuration system
12
- *
13
- * Provides unified, filesystem-like config management:
14
- * - setPath('/') → ~/.epistery/config.ini
15
- * - setPath('/domain') → ~/.epistery/domain/config.ini
16
- * - setPath('/.ssl/domain') → ~/.epistery/.ssl/domain/config.ini
17
- *
18
- * Usage:
19
- * const config = new Config('epistery');
20
- * config.setPath('/wiki.rootz.global');
21
- * config.load();
22
- * config.data.verified = true;
23
- * config.save();
22
+ * LocalConfig the filesystem backend under ~/.epistery. This is the original
23
+ * Config behavior, with all IO made async. It is also what the epistery-authority
24
+ * server mounts as its own storage backend (one implementation, not two).
24
25
  */
25
- class Config {
26
+ class LocalConfig {
26
27
  constructor(rootName = 'epistery') {
27
28
  this.currentPath = '/';
28
29
  this.data = {};
@@ -31,137 +32,270 @@ class Config {
31
32
  this.configDir = (0, path_1.join)(this.homeDir, '.' + this.rootName);
32
33
  this.currentDir = this.configDir;
33
34
  this.currentFile = (0, path_1.join)(this.configDir, 'config.ini');
34
- // Initialize root config if it doesn't exist
35
+ // Bootstrap is synchronous: seed the root config so the very first run has
36
+ // somewhere to read the authority URL from. Only this seed stays sync; all
37
+ // subsequent IO is async.
35
38
  if (!fs_1.default.existsSync(this.currentFile)) {
36
- this.initialize();
39
+ this.initializeSync();
37
40
  }
38
41
  }
39
- /**
40
- * Set current working path and load config (like cd)
41
- * Examples: '/', 'domain', '/domain', '/.ssl/domain'
42
- * Leading slash is optional and will be added if not present
43
- * Automatically loads the config at the specified path
44
- */
45
- setPath(path) {
46
- // Normalize path: ensure leading slash, remove trailing slash, lowercase
47
- path = path.trim();
48
- if (!path.startsWith('/'))
49
- path = '/' + path;
50
- if (path.length > 1 && path.endsWith('/'))
51
- path = path.slice(0, -1);
52
- path = path.toLowerCase();
42
+ initializeSync() {
43
+ if (!fs_1.default.existsSync(this.currentDir)) {
44
+ fs_1.default.mkdirSync(this.currentDir, { recursive: true });
45
+ }
46
+ const defaultContent = this.currentPath === '/' ? defaultIni : '';
47
+ fs_1.default.writeFileSync(this.currentFile, defaultContent);
48
+ this.data = ini_1.default.decode(defaultContent);
49
+ }
50
+ getPath() {
51
+ return this.currentPath;
52
+ }
53
+ async setPath(path) {
54
+ path = normalizePath(path);
53
55
  this.currentPath = path;
54
- // Calculate directory and file paths
55
56
  if (path === '/') {
56
57
  this.currentDir = this.configDir;
57
58
  this.currentFile = (0, path_1.join)(this.configDir, 'config.ini');
58
59
  }
59
60
  else {
60
- this.currentDir = (0, path_1.join)(this.configDir, path.slice(1)); // Remove leading /
61
+ this.currentDir = (0, path_1.join)(this.configDir, path.slice(1));
61
62
  this.currentFile = (0, path_1.join)(this.currentDir, 'config.ini');
62
63
  }
63
- // Automatically load the config at this path
64
- this.load();
65
- }
66
- /**
67
- * Get current path
68
- */
69
- getPath() {
70
- return this.currentPath;
64
+ await this.load();
71
65
  }
72
- /**
73
- * Initialize config at current path
74
- */
75
- initialize() {
76
- if (!fs_1.default.existsSync(this.currentDir)) {
77
- fs_1.default.mkdirSync(this.currentDir, { recursive: true });
66
+ async load() {
67
+ try {
68
+ const fileData = await promises_1.default.readFile(this.currentFile, 'utf8');
69
+ this.data = ini_1.default.decode(fileData);
78
70
  }
79
- // Write default config for root, empty for paths
80
- const defaultContent = this.currentPath === '/' ? defaultIni : '';
81
- fs_1.default.writeFileSync(this.currentFile, defaultContent);
82
- this.data = ini_1.default.decode(defaultContent);
83
- }
84
- /**
85
- * Load config from current path
86
- */
87
- load() {
88
- if (!fs_1.default.existsSync(this.currentFile)) {
71
+ catch {
89
72
  this.data = {};
90
- return;
91
73
  }
92
- const fileData = fs_1.default.readFileSync(this.currentFile, 'utf8');
93
- this.data = ini_1.default.decode(fileData);
94
74
  }
95
- /**
96
- * Read config from arbitrary path without changing current path
97
- * @param path Path to read from (e.g., '/', '/domain')
98
- * @returns Parsed config data from that path
99
- */
100
- read(path) {
101
- // Normalize path
102
- path = path.trim();
103
- if (!path.startsWith('/'))
104
- path = '/' + path;
105
- if (path.length > 1 && path.endsWith('/'))
106
- path = path.slice(0, -1);
107
- path = path.toLowerCase();
108
- // Calculate file location
109
- let configFile;
110
- if (path === '/') {
111
- configFile = (0, path_1.join)(this.configDir, 'config.ini');
112
- }
113
- else {
114
- configFile = (0, path_1.join)(this.configDir, path.slice(1), 'config.ini');
75
+ async read(path) {
76
+ path = normalizePath(path);
77
+ const configFile = path === '/'
78
+ ? (0, path_1.join)(this.configDir, 'config.ini')
79
+ : (0, path_1.join)(this.configDir, path.slice(1), 'config.ini');
80
+ try {
81
+ const fileData = await promises_1.default.readFile(configFile, 'utf8');
82
+ return ini_1.default.decode(fileData);
115
83
  }
116
- // Read and parse
117
- if (!fs_1.default.existsSync(configFile)) {
84
+ catch {
118
85
  return {};
119
86
  }
120
- const fileData = fs_1.default.readFileSync(configFile, 'utf8');
121
- return ini_1.default.decode(fileData);
122
87
  }
123
- /**
124
- * Save config to current path
125
- */
126
- save() {
127
- if (!fs_1.default.existsSync(this.currentDir)) {
128
- fs_1.default.mkdirSync(this.currentDir, { recursive: true });
88
+ async save() {
89
+ await promises_1.default.mkdir(this.currentDir, { recursive: true });
90
+ await promises_1.default.writeFile(this.currentFile, ini_1.default.stringify(this.data));
91
+ }
92
+ async readFile(filename) {
93
+ return promises_1.default.readFile((0, path_1.join)(this.currentDir, filename));
94
+ }
95
+ async writeFile(filename, data) {
96
+ await promises_1.default.mkdir(this.currentDir, { recursive: true });
97
+ await promises_1.default.writeFile((0, path_1.join)(this.currentDir, filename), data);
98
+ }
99
+ async exists() {
100
+ try {
101
+ await promises_1.default.access(this.currentFile);
102
+ return true;
103
+ }
104
+ catch {
105
+ return false;
129
106
  }
130
- const text = ini_1.default.stringify(this.data);
131
- fs_1.default.writeFileSync(this.currentFile, text);
132
107
  }
133
- /**
134
- * Read file from current path directory
135
- */
136
- readFile(filename) {
137
- return fs_1.default.readFileSync((0, path_1.join)(this.currentDir, filename));
108
+ async listPaths() {
109
+ try {
110
+ const entries = await promises_1.default.readdir(this.currentDir, { withFileTypes: true });
111
+ return entries.filter(e => e.isDirectory()).map(e => e.name);
112
+ }
113
+ catch {
114
+ return [];
115
+ }
138
116
  }
139
- /**
140
- * Write file to current path directory
141
- */
142
- writeFile(filename, data) {
143
- if (!fs_1.default.existsSync(this.currentDir)) {
144
- fs_1.default.mkdirSync(this.currentDir, { recursive: true });
117
+ }
118
+ exports.LocalConfig = LocalConfig;
119
+ /**
120
+ * RemoteConfig — HTTP client to an epistery-authority server. Implements the
121
+ * same ConfigStore interface; the authority mounts a LocalConfig behind it.
122
+ *
123
+ * Auth is the rivet key-exchange: the machine signs a challenge with its
124
+ * device key, and the authority issues a bearer token (see epistery-authority
125
+ * lib/auth.mjs). In Phase 1 config data (including the wallet mnemonic) is
126
+ * still served; Phase 2 splits public from secret and adds /sign/*.
127
+ */
128
+ class RemoteConfig {
129
+ constructor(baseUrl, machineAddress, signChallenge) {
130
+ this.baseUrl = baseUrl;
131
+ this.machineAddress = machineAddress;
132
+ this.signChallenge = signChallenge;
133
+ this.data = {};
134
+ this.currentPath = '/';
135
+ this.token = null;
136
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
137
+ }
138
+ getPath() {
139
+ return this.currentPath;
140
+ }
141
+ async authenticate() {
142
+ const fetch = globalThis.fetch;
143
+ const cRes = await fetch(`${this.baseUrl}/auth/challenge`, {
144
+ method: 'POST',
145
+ headers: { 'content-type': 'application/json' },
146
+ body: JSON.stringify({ machineAddress: this.machineAddress }),
147
+ });
148
+ if (!cRes.ok)
149
+ throw new Error(`authority challenge failed: ${cRes.status}`);
150
+ const { challenge } = await cRes.json();
151
+ const message = `Epistery Key Exchange - ${this.machineAddress} - ${challenge}`;
152
+ const signature = await this.signChallenge(message);
153
+ const vRes = await fetch(`${this.baseUrl}/auth/verify`, {
154
+ method: 'POST',
155
+ headers: { 'content-type': 'application/json' },
156
+ body: JSON.stringify({ machineAddress: this.machineAddress, message, signature }),
157
+ });
158
+ if (!vRes.ok)
159
+ throw new Error(`authority verify failed: ${vRes.status}`);
160
+ this.token = (await vRes.json()).token;
161
+ }
162
+ async authedFetch(pathAndQuery, init = {}) {
163
+ const fetch = globalThis.fetch;
164
+ if (!this.token)
165
+ await this.authenticate();
166
+ const withAuth = () => ({ ...init, headers: { ...(init.headers || {}), authorization: `Bearer ${this.token}` } });
167
+ let res = await fetch(this.baseUrl + pathAndQuery, withAuth());
168
+ if (res.status === 401) {
169
+ this.token = null; // expired — re-auth once
170
+ await this.authenticate();
171
+ res = await fetch(this.baseUrl + pathAndQuery, withAuth());
145
172
  }
146
- fs_1.default.writeFileSync((0, path_1.join)(this.currentDir, filename), data);
173
+ return res;
147
174
  }
148
- /**
149
- * Check if config exists at current path
150
- */
151
- exists() {
152
- return fs_1.default.existsSync(this.currentFile);
175
+ async setPath(path) {
176
+ this.currentPath = normalizePath(path);
177
+ await this.load();
178
+ }
179
+ async load() {
180
+ this.data = await this.read(this.currentPath);
181
+ }
182
+ async read(path) {
183
+ path = normalizePath(path);
184
+ const res = await this.authedFetch(`/config${path === '/' ? '/' : path}`);
185
+ if (!res.ok)
186
+ return {};
187
+ return (await res.json()).data || {};
188
+ }
189
+ async save() {
190
+ const path = this.currentPath;
191
+ const res = await this.authedFetch(`/config${path === '/' ? '/' : path}`, {
192
+ method: 'PUT',
193
+ headers: { 'content-type': 'application/json' },
194
+ body: JSON.stringify({ data: this.data }),
195
+ });
196
+ if (!res.ok)
197
+ throw new Error(`authority save failed: ${res.status}`);
198
+ }
199
+ filePrefix() {
200
+ return this.currentPath === '/' ? '' : this.currentPath;
201
+ }
202
+ async readFile(filename) {
203
+ const res = await this.authedFetch(`/file${this.filePrefix()}/${filename}`);
204
+ if (!res.ok)
205
+ throw new Error(`authority file read failed: ${res.status}`);
206
+ return Buffer.from(await res.arrayBuffer());
207
+ }
208
+ async writeFile(filename, data) {
209
+ const res = await this.authedFetch(`/file${this.filePrefix()}/${filename}`, {
210
+ method: 'PUT',
211
+ headers: { 'content-type': 'application/octet-stream' },
212
+ body: data,
213
+ });
214
+ if (!res.ok)
215
+ throw new Error(`authority file write failed: ${res.status}`);
216
+ }
217
+ async exists() {
218
+ const data = await this.read(this.currentPath);
219
+ return !!data && Object.keys(data).length > 0;
220
+ }
221
+ async listPaths() {
222
+ const res = await this.authedFetch(`/paths${this.currentPath === '/' ? '/' : this.currentPath}`);
223
+ if (!res.ok)
224
+ return [];
225
+ return (await res.json()).paths || [];
226
+ }
227
+ }
228
+ exports.RemoteConfig = RemoteConfig;
229
+ /**
230
+ * Config — the public facade. `new Config()` selects the backend synchronously
231
+ * (reading only the local bootstrap), then delegates every async operation.
232
+ * Existing call sites change only by adding `await`.
233
+ */
234
+ class Config {
235
+ constructor(rootName = 'epistery') {
236
+ this.local = new LocalConfig(rootName);
237
+ const authorityUrl = Config.resolveAuthorityUrl(rootName);
238
+ if (authorityUrl) {
239
+ const { machineAddress, sign } = Config.machineSigner(rootName);
240
+ this.backend = new RemoteConfig(authorityUrl, machineAddress, sign);
241
+ }
242
+ else {
243
+ this.backend = this.local;
244
+ }
245
+ }
246
+ /** Read the local bootstrap config.ini synchronously (authority selection only). */
247
+ static readBootstrap(rootName) {
248
+ const homeDir = (process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME) || '';
249
+ const file = (0, path_1.join)(homeDir, '.' + rootName, 'config.ini');
250
+ try {
251
+ return ini_1.default.decode(fs_1.default.readFileSync(file, 'utf8'));
252
+ }
253
+ catch {
254
+ return {};
255
+ }
256
+ }
257
+ static resolveAuthorityUrl(rootName) {
258
+ if (process.env.EPISTERY_CONFIG_URL)
259
+ return process.env.EPISTERY_CONFIG_URL;
260
+ const boot = Config.readBootstrap(rootName);
261
+ return boot?.authority?.url || null;
153
262
  }
154
263
  /**
155
- * List all subdirectories at current path
264
+ * Build the machine signer used to authenticate to the authority. The machine
265
+ * rivet key lives in the local bootstrap [authority] section (Phase 1). A
266
+ * future TPM-backed key replaces this without changing the call site.
156
267
  */
157
- listPaths() {
158
- if (!fs_1.default.existsSync(this.currentDir)) {
159
- return [];
268
+ static machineSigner(rootName) {
269
+ const boot = Config.readBootstrap(rootName);
270
+ const a = boot?.authority || {};
271
+ let wallet;
272
+ if (a.machineMnemonic) {
273
+ wallet = ethers_1.ethers.Wallet.fromMnemonic(a.machineMnemonic);
274
+ }
275
+ else if (a.machineKey) {
276
+ wallet = new ethers_1.ethers.Wallet(a.machineKey);
160
277
  }
161
- return fs_1.default.readdirSync(this.currentDir, { withFileTypes: true })
162
- .filter(dirent => dirent.isDirectory())
163
- .map(dirent => dirent.name);
278
+ else {
279
+ throw new Error('Config: [authority] url is set but no machine credential ([authority] machineMnemonic or machineKey) is configured to authenticate to it.');
280
+ }
281
+ return { machineAddress: wallet.address, sign: (m) => wallet.signMessage(m) };
164
282
  }
283
+ // Local-machine facts (always the bootstrap LocalConfig, even in remote mode):
284
+ // these are filesystem paths some callers need (e.g. CliWallet session dir).
285
+ get rootName() { return this.local.rootName; }
286
+ get homeDir() { return this.local.homeDir; }
287
+ get configDir() { return this.local.configDir; }
288
+ get data() { return this.backend.data; }
289
+ set data(v) { this.backend.data = v; }
290
+ getPath() { return this.backend.getPath(); }
291
+ setPath(path) { return this.backend.setPath(path); }
292
+ load() { return this.backend.load(); }
293
+ read(path) { return this.backend.read(path); }
294
+ save() { return this.backend.save(); }
295
+ readFile(filename) { return this.backend.readFile(filename); }
296
+ writeFile(filename, data) { return this.backend.writeFile(filename, data); }
297
+ exists() { return this.backend.exists(); }
298
+ listPaths() { return this.backend.listPaths(); }
165
299
  }
166
300
  exports.Config = Config;
167
301
  const defaultIni = `[profile]
@@ -204,5 +338,12 @@ nativeCurrencyDecimals=18
204
338
  ; minPriorityFeeGwei=25 ; Polygon RPC floor (don't lower)
205
339
  ; [default.rpc.81.policy]
206
340
  ; maxGasPriceGwei=1000 ; legacy-chain analogue (JOC)
341
+
342
+ ; Shared Configuration Authority (optional). When set, Config reads/writes
343
+ ; through the epistery-authority server instead of the local filesystem, so
344
+ ; this host becomes a stateless pool member. EPISTERY_CONFIG_URL overrides url.
345
+ ; [authority]
346
+ ; url=https://epistery-authority-1.internal:4500
347
+ ; machineMnemonic=... ; this machine's rivet (or machineKey=0x…)
207
348
  `;
208
349
  //# sourceMappingURL=Config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Config.js","sourceRoot":"","sources":["../../src/utils/Config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Config.js","sourceRoot":"","sources":["../../src/utils/Config.ts"],"names":[],"mappings":"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"}