neozip-cli 0.80.0 → 0.95.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 (74) hide show
  1. package/AGENTS.md +93 -0
  2. package/CHANGELOG.md +117 -12
  3. package/DOCUMENTATION.md +33 -38
  4. package/README.md +137 -63
  5. package/dist/src/account/account-state.js +95 -0
  6. package/dist/src/account/format-account-status.js +62 -0
  7. package/dist/src/account/identity-provision.js +79 -0
  8. package/dist/src/account/identity-wrap.js +106 -0
  9. package/dist/src/account/profile-crypto.js +85 -0
  10. package/dist/src/account/profile-store.js +129 -0
  11. package/dist/src/account/require-account.js +32 -0
  12. package/dist/src/account/types.js +3 -0
  13. package/dist/src/account/wallet-evm.js +46 -0
  14. package/dist/src/account/wallet-setup.js +33 -0
  15. package/dist/src/archive/crypto-self.js +117 -0
  16. package/dist/src/archive/identity-key.js +217 -0
  17. package/dist/src/archive/recipient-lookup.js +61 -0
  18. package/dist/src/cli/output.js +100 -0
  19. package/dist/src/cli/params.js +122 -0
  20. package/dist/src/cli/schema.js +186 -0
  21. package/dist/src/cli/validate.js +119 -0
  22. package/dist/src/commands/mintTimestampProof.js +26 -14
  23. package/dist/src/config/ConfigSetup.js +82 -423
  24. package/dist/src/connect/command.js +364 -0
  25. package/dist/src/connection/bootstrap.js +50 -0
  26. package/dist/src/connection/cli-guidance.js +101 -0
  27. package/dist/src/connection/cli-prefs.js +180 -0
  28. package/dist/src/connection/cli-settings.js +140 -0
  29. package/dist/src/connection/cli-types.js +14 -0
  30. package/dist/src/connection/coordinator.js +83 -0
  31. package/dist/src/connection/credentials.js +33 -0
  32. package/dist/src/connection/crypto.js +96 -0
  33. package/dist/src/connection/dump.js +117 -0
  34. package/dist/src/connection/funding.js +187 -0
  35. package/dist/src/connection/incomplete-setup.js +89 -0
  36. package/dist/src/connection/interactive.js +871 -0
  37. package/dist/src/connection/legacy-profile-reader.js +87 -0
  38. package/dist/src/connection/magic-link.js +142 -0
  39. package/dist/src/connection/migrate.js +115 -0
  40. package/dist/src/connection/onboarding.js +616 -0
  41. package/dist/src/connection/origin.js +69 -0
  42. package/dist/src/connection/phase.js +101 -0
  43. package/dist/src/connection/phone.js +26 -0
  44. package/dist/src/connection/promote-active.js +56 -0
  45. package/dist/src/connection/reset.js +56 -0
  46. package/dist/src/connection/status-report.js +52 -0
  47. package/dist/src/connection/store.js +406 -0
  48. package/dist/src/connection/token-auth.js +44 -0
  49. package/dist/src/connection/types.js +3 -0
  50. package/dist/src/connection/wallet-json-migration.js +155 -0
  51. package/dist/src/connection/wallet-login.js +65 -0
  52. package/dist/src/connection/wallet-setup.js +83 -0
  53. package/dist/src/constants/wallet-identity.js +14 -0
  54. package/dist/src/exit-codes.js +54 -10
  55. package/dist/src/neolist.js +100 -10
  56. package/dist/src/neounzip.js +236 -65
  57. package/dist/src/neozip/blockchain.js +18 -18
  58. package/dist/src/neozip/createZip.js +118 -94
  59. package/dist/src/neozip/upgradeZip.js +14 -11
  60. package/dist/src/neozip.js +269 -91
  61. package/dist/src/skills/command.js +256 -0
  62. package/dist/src/skills/locate.js +99 -0
  63. package/dist/src/util/mask.js +34 -0
  64. package/dist/src/util/token-service-fetch.js +26 -0
  65. package/env.example +18 -85
  66. package/package.json +89 -73
  67. package/skills/neozip-connect/SKILL.md +95 -0
  68. package/skills/neozip-create/SKILL.md +57 -0
  69. package/skills/neozip-extract/SKILL.md +58 -0
  70. package/skills/neozip-legacy/SKILL.md +48 -0
  71. package/skills/neozip-list/SKILL.md +56 -0
  72. package/skills/neozip-shared/SKILL.md +60 -0
  73. package/dist/src/commands/verifyEmail.js +0 -146
  74. package/dist/src/config/ConfigStore.js +0 -406
@@ -0,0 +1,406 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getConnectionDir = getConnectionDir;
37
+ exports.readConnectionPublic = readConnectionPublic;
38
+ exports.readConnectionSecrets = readConnectionSecrets;
39
+ exports.listConnectionIds = listConnectionIds;
40
+ exports.listConnections = listConnections;
41
+ exports.getActiveConnectionId = getActiveConnectionId;
42
+ exports.getActiveConnection = getActiveConnection;
43
+ exports.readActiveConnectionSecrets = readActiveConnectionSecrets;
44
+ exports.createConnection = createConnection;
45
+ exports.selectConnection = selectConnection;
46
+ exports.ensureActiveConnection = ensureActiveConnection;
47
+ exports.updateConnection = updateConnection;
48
+ exports.saveAccessToken = saveAccessToken;
49
+ exports.saveEvmWallet = saveEvmWallet;
50
+ exports.saveWalletLink = saveWalletLink;
51
+ exports.saveIdentityProvision = saveIdentityProvision;
52
+ exports.savePhoneVerified = savePhoneVerified;
53
+ exports.logoutConnection = logoutConnection;
54
+ exports.deleteConnection = deleteConnection;
55
+ exports.clearConnectionCredentialsFromEnv = clearConnectionCredentialsFromEnv;
56
+ exports.applyActiveConnectionToEnv = applyActiveConnectionToEnv;
57
+ exports.connectionPathFor = connectionPathFor;
58
+ const crypto = __importStar(require("node:crypto"));
59
+ const fs = __importStar(require("node:fs"));
60
+ const os = __importStar(require("node:os"));
61
+ const path = __importStar(require("node:path"));
62
+ const mask_1 = require("../util/mask");
63
+ const crypto_1 = require("./crypto");
64
+ const origin_1 = require("./origin");
65
+ function getConnectionDir() {
66
+ return (process.env.NEOZIP_CONNECTION_DIR?.trim() ||
67
+ path.join(os.homedir(), ".neozip", "connection"));
68
+ }
69
+ const MANIFEST_PATH = () => path.join(getConnectionDir(), "manifest.json");
70
+ const CONNECTIONS_DIR = () => path.join(getConnectionDir(), "connections");
71
+ function ensureDir() {
72
+ fs.mkdirSync(getConnectionDir(), { recursive: true, mode: 0o700 });
73
+ fs.mkdirSync(CONNECTIONS_DIR(), { recursive: true, mode: 0o700 });
74
+ }
75
+ function connectionDir(id) {
76
+ return path.join(CONNECTIONS_DIR(), id);
77
+ }
78
+ function publicPath(id) {
79
+ return path.join(connectionDir(id), "public.json");
80
+ }
81
+ function secretsPath(id) {
82
+ return path.join(connectionDir(id), "secrets.enc");
83
+ }
84
+ function readManifest() {
85
+ if (!fs.existsSync(MANIFEST_PATH())) {
86
+ return { version: 1, activeConnectionId: null, workspaces: {} };
87
+ }
88
+ return JSON.parse(fs.readFileSync(MANIFEST_PATH(), "utf8"));
89
+ }
90
+ function writeManifest(manifest) {
91
+ ensureDir();
92
+ fs.writeFileSync(MANIFEST_PATH(), JSON.stringify(manifest, null, 2) + "\n", {
93
+ mode: 0o600,
94
+ });
95
+ }
96
+ function workspaceKey(origin) {
97
+ return (0, origin_1.normalizeTokenServiceOrigin)(origin) || "__unbound__";
98
+ }
99
+ function getWorkspace(manifest, origin) {
100
+ const key = workspaceKey(origin);
101
+ if (!manifest.workspaces[key]) {
102
+ manifest.workspaces[key] = { connectionIds: [], activeConnectionId: null };
103
+ }
104
+ return manifest.workspaces[key];
105
+ }
106
+ function readConnectionPublicRecord(id) {
107
+ const p = publicPath(id);
108
+ if (!fs.existsSync(p))
109
+ return null;
110
+ return JSON.parse(fs.readFileSync(p, "utf8"));
111
+ }
112
+ /** Merge a patch into existing public.json without dropping desktop or future unknown keys. */
113
+ function mergeConnectionPublic(existing, patch) {
114
+ const { id: _ignored, ...restPatch } = patch;
115
+ return {
116
+ ...existing,
117
+ ...restPatch,
118
+ id: existing.id,
119
+ updatedAt: new Date().toISOString(),
120
+ };
121
+ }
122
+ function readConnectionPublic(id) {
123
+ return readConnectionPublicRecord(id);
124
+ }
125
+ function readConnectionSecrets(id) {
126
+ const sp = secretsPath(id);
127
+ if (!fs.existsSync(sp))
128
+ return null;
129
+ try {
130
+ return (0, crypto_1.decryptSecrets)(fs.readFileSync(sp, "utf8"));
131
+ }
132
+ catch {
133
+ return null;
134
+ }
135
+ }
136
+ function listConnectionIds() {
137
+ if (!fs.existsSync(CONNECTIONS_DIR()))
138
+ return [];
139
+ return fs
140
+ .readdirSync(CONNECTIONS_DIR(), { withFileTypes: true })
141
+ .filter((d) => d.isDirectory())
142
+ .map((d) => d.name);
143
+ }
144
+ function listConnections() {
145
+ return listConnectionIds()
146
+ .map((id) => readConnectionPublic(id))
147
+ .filter((c) => c !== null);
148
+ }
149
+ function getActiveConnectionId() {
150
+ const manifest = readManifest();
151
+ if (manifest.activeConnectionId)
152
+ return manifest.activeConnectionId;
153
+ return null;
154
+ }
155
+ function getActiveConnection() {
156
+ const id = getActiveConnectionId();
157
+ if (!id)
158
+ return null;
159
+ return readConnectionPublic(id);
160
+ }
161
+ function readActiveConnectionSecrets() {
162
+ const id = getActiveConnectionId();
163
+ if (!id)
164
+ return null;
165
+ return readConnectionSecrets(id);
166
+ }
167
+ function writeConnectionPublic(meta) {
168
+ ensureDir();
169
+ const dir = connectionDir(meta.id);
170
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
171
+ fs.writeFileSync(publicPath(meta.id), JSON.stringify(meta, null, 2) + "\n", {
172
+ mode: 0o600,
173
+ });
174
+ }
175
+ function writeConnectionSecrets(id, secrets) {
176
+ ensureDir();
177
+ fs.writeFileSync(secretsPath(id), (0, crypto_1.encryptSecrets)(secrets), { mode: 0o600 });
178
+ }
179
+ function registerInWorkspace(manifest, origin, id) {
180
+ const ws = getWorkspace(manifest, origin);
181
+ if (!ws.connectionIds.includes(id)) {
182
+ ws.connectionIds.push(id);
183
+ }
184
+ ws.activeConnectionId = id;
185
+ manifest.activeConnectionId = id;
186
+ }
187
+ function createConnection(input) {
188
+ const now = new Date().toISOString();
189
+ const origin = (0, origin_1.resolveTokenServiceOrigin)(input.tokenServiceUrl);
190
+ const meta = {
191
+ id: crypto.randomUUID(),
192
+ label: input.label?.trim() || "default",
193
+ tokenServiceOrigin: origin,
194
+ email: null,
195
+ emailVerified: false,
196
+ emailVerifiedAt: null,
197
+ evmAddress: null,
198
+ walletId: null,
199
+ linkId: null,
200
+ identityKeyId: null,
201
+ x25519PublicKeySpkiB64: null,
202
+ x25519Fingerprint: null,
203
+ onboardingCompleteAt: null,
204
+ createdAt: now,
205
+ updatedAt: now,
206
+ };
207
+ writeConnectionPublic(meta);
208
+ writeConnectionSecrets(meta.id, {
209
+ accessToken: null,
210
+ accessTokenObtainedAt: null,
211
+ accessTokenExpiresAt: null,
212
+ evmPrivateKeyHex: null,
213
+ });
214
+ const manifest = readManifest();
215
+ registerInWorkspace(manifest, origin, meta.id);
216
+ writeManifest(manifest);
217
+ return meta;
218
+ }
219
+ function selectConnection(connectionId) {
220
+ const meta = readConnectionPublic(connectionId);
221
+ if (!meta)
222
+ throw new Error(`Connection not found: ${connectionId}`);
223
+ const manifest = readManifest();
224
+ registerInWorkspace(manifest, meta.tokenServiceOrigin, connectionId);
225
+ writeManifest(manifest);
226
+ return meta;
227
+ }
228
+ function ensureActiveConnection(input) {
229
+ const active = getActiveConnection();
230
+ if (active)
231
+ return active;
232
+ const origin = (0, origin_1.resolveTokenServiceOrigin)(input?.tokenServiceUrl);
233
+ const manifest = readManifest();
234
+ const ws = manifest.workspaces[workspaceKey(origin)];
235
+ if (ws?.activeConnectionId) {
236
+ const existing = readConnectionPublic(ws.activeConnectionId);
237
+ if (existing) {
238
+ manifest.activeConnectionId = existing.id;
239
+ writeManifest(manifest);
240
+ return existing;
241
+ }
242
+ }
243
+ return createConnection({
244
+ label: input?.label,
245
+ tokenServiceUrl: input?.tokenServiceUrl,
246
+ });
247
+ }
248
+ function updateConnection(connectionId, patch) {
249
+ const existing = readConnectionPublicRecord(connectionId);
250
+ if (!existing)
251
+ throw new Error(`Connection not found: ${connectionId}`);
252
+ const updated = mergeConnectionPublic(existing, patch);
253
+ writeConnectionPublic(updated);
254
+ return updated;
255
+ }
256
+ function saveAccessToken(connectionId, accessToken, email, expiresAt) {
257
+ const secrets = readConnectionSecrets(connectionId) ?? emptySecrets();
258
+ secrets.accessToken = accessToken;
259
+ secrets.accessTokenObtainedAt = Date.now();
260
+ secrets.accessTokenExpiresAt = expiresAt ?? null;
261
+ writeConnectionSecrets(connectionId, secrets);
262
+ const now = new Date().toISOString();
263
+ return updateConnection(connectionId, {
264
+ email: email.trim().toLowerCase(),
265
+ emailVerified: true,
266
+ emailVerifiedAt: now,
267
+ });
268
+ }
269
+ function saveEvmWallet(connectionId, evmPrivateKeyHex, evmAddress) {
270
+ const secrets = readConnectionSecrets(connectionId) ?? emptySecrets();
271
+ secrets.evmPrivateKeyHex = evmPrivateKeyHex.replace(/^0x/i, "");
272
+ writeConnectionSecrets(connectionId, secrets);
273
+ return updateConnection(connectionId, { evmAddress });
274
+ }
275
+ function saveWalletLink(connectionId, walletId, linkId, evmAddress) {
276
+ return updateConnection(connectionId, { walletId, linkId, evmAddress });
277
+ }
278
+ function saveIdentityProvision(connectionId, identityKeyId, x25519PublicKeySpkiB64) {
279
+ const now = new Date().toISOString();
280
+ return updateConnection(connectionId, {
281
+ identityKeyId,
282
+ x25519PublicKeySpkiB64,
283
+ x25519Fingerprint: (0, mask_1.maskPublicKey)(x25519PublicKeySpkiB64),
284
+ onboardingCompleteAt: now,
285
+ });
286
+ }
287
+ function savePhoneVerified(connectionId, phoneE164) {
288
+ const now = new Date().toISOString();
289
+ return updateConnection(connectionId, {
290
+ phoneE164: phoneE164.trim(),
291
+ phoneVerifiedAt: now,
292
+ });
293
+ }
294
+ function emptySecrets() {
295
+ return {
296
+ accessToken: null,
297
+ accessTokenObtainedAt: null,
298
+ accessTokenExpiresAt: null,
299
+ evmPrivateKeyHex: null,
300
+ };
301
+ }
302
+ function logoutConnection(connectionId) {
303
+ const id = connectionId?.trim() || getActiveConnectionId();
304
+ if (!id) {
305
+ throw new Error("No connection to log out. Run neozip connect first.");
306
+ }
307
+ const meta = readConnectionPublic(id);
308
+ if (!meta)
309
+ throw new Error(`Connection not found: ${id}`);
310
+ writeConnectionSecrets(id, emptySecrets());
311
+ updateConnection(id, {
312
+ email: null,
313
+ emailVerified: false,
314
+ emailVerifiedAt: null,
315
+ evmAddress: null,
316
+ walletId: null,
317
+ linkId: null,
318
+ identityKeyId: null,
319
+ x25519PublicKeySpkiB64: null,
320
+ x25519Fingerprint: null,
321
+ onboardingCompleteAt: null,
322
+ phoneE164: null,
323
+ phoneVerifiedAt: null,
324
+ });
325
+ const manifest = readManifest();
326
+ const wasActive = manifest.activeConnectionId === id;
327
+ if (wasActive) {
328
+ manifest.activeConnectionId = null;
329
+ const ws = manifest.workspaces[workspaceKey(meta.tokenServiceOrigin)];
330
+ if (ws)
331
+ ws.activeConnectionId = null;
332
+ writeManifest(manifest);
333
+ }
334
+ return { connectionId: id, label: meta.label, wasActive };
335
+ }
336
+ function pickNextActiveConnectionId(manifest) {
337
+ for (const ws of Object.values(manifest.workspaces)) {
338
+ if (ws.activeConnectionId && readConnectionPublic(ws.activeConnectionId)) {
339
+ return ws.activeConnectionId;
340
+ }
341
+ for (const id of ws.connectionIds) {
342
+ if (readConnectionPublic(id))
343
+ return id;
344
+ }
345
+ }
346
+ return null;
347
+ }
348
+ /** Remove a connection and its secrets from disk. */
349
+ function deleteConnection(connectionId) {
350
+ const id = connectionId.trim();
351
+ const meta = readConnectionPublic(id);
352
+ if (!meta)
353
+ throw new Error(`Connection not found: ${id}`);
354
+ const dir = connectionDir(id);
355
+ if (fs.existsSync(dir)) {
356
+ fs.rmSync(dir, { recursive: true, force: true });
357
+ }
358
+ const manifest = readManifest();
359
+ const wsKey = workspaceKey(meta.tokenServiceOrigin);
360
+ const ws = manifest.workspaces[wsKey];
361
+ if (ws) {
362
+ ws.connectionIds = ws.connectionIds.filter((existingId) => existingId !== id);
363
+ if (ws.activeConnectionId === id) {
364
+ ws.activeConnectionId = ws.connectionIds[0] ?? null;
365
+ }
366
+ if (ws.connectionIds.length === 0) {
367
+ delete manifest.workspaces[wsKey];
368
+ }
369
+ }
370
+ if (manifest.activeConnectionId === id) {
371
+ manifest.activeConnectionId = pickNextActiveConnectionId(manifest);
372
+ }
373
+ writeManifest(manifest);
374
+ return {
375
+ connectionId: id,
376
+ label: meta.label,
377
+ newActiveConnectionId: manifest.activeConnectionId,
378
+ };
379
+ }
380
+ function clearConnectionCredentialsFromEnv() {
381
+ delete process.env.NEOZIP_TOKEN_SERVICE_ACCESS_TOKEN;
382
+ delete process.env.NEOZIP_WALLET_PASSKEY;
383
+ delete process.env.NEOZIP_RECIPIENT_EMAIL;
384
+ }
385
+ /** Merge active connection into env when env does not override. */
386
+ function applyActiveConnectionToEnv() {
387
+ const meta = getActiveConnection();
388
+ const secrets = readActiveConnectionSecrets();
389
+ if (!meta || !secrets) {
390
+ return { applied: false, connectionId: null };
391
+ }
392
+ if (!process.env.NEOZIP_TOKEN_SERVICE_ACCESS_TOKEN && secrets.accessToken) {
393
+ process.env.NEOZIP_TOKEN_SERVICE_ACCESS_TOKEN = secrets.accessToken;
394
+ }
395
+ if (!process.env.NEOZIP_WALLET_PASSKEY && secrets.evmPrivateKeyHex) {
396
+ process.env.NEOZIP_WALLET_PASSKEY = secrets.evmPrivateKeyHex;
397
+ }
398
+ if (!process.env.NEOZIP_RECIPIENT_EMAIL && meta.email) {
399
+ process.env.NEOZIP_RECIPIENT_EMAIL = meta.email;
400
+ }
401
+ return { applied: true, connectionId: meta.id };
402
+ }
403
+ function connectionPathFor(id) {
404
+ return connectionDir(id);
405
+ }
406
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseAccessTokenExpiry = parseAccessTokenExpiry;
4
+ exports.isAccessTokenExpired = isAccessTokenExpired;
5
+ exports.formatTokenReauthGuidance = formatTokenReauthGuidance;
6
+ exports.tokenServiceAuthErrorMessage = tokenServiceAuthErrorMessage;
7
+ /** Grace period before stored expiry to avoid edge-of-window 401s. */
8
+ const TOKEN_EXPIRY_GRACE_MS = 60000;
9
+ function parseAccessTokenExpiry(parsed) {
10
+ const expiresAt = parsed.expiresAt;
11
+ if (typeof expiresAt === "number" && Number.isFinite(expiresAt)) {
12
+ return expiresAt > 1e12 ? expiresAt : expiresAt * 1000;
13
+ }
14
+ const expiresIn = parsed.expiresIn;
15
+ if (typeof expiresIn === "number" && Number.isFinite(expiresIn)) {
16
+ return Date.now() + expiresIn * 1000;
17
+ }
18
+ return null;
19
+ }
20
+ function isAccessTokenExpired(secrets, now = Date.now()) {
21
+ const expiresAt = secrets?.accessTokenExpiresAt;
22
+ if (expiresAt == null)
23
+ return false;
24
+ return now >= expiresAt - TOKEN_EXPIRY_GRACE_MS;
25
+ }
26
+ function formatTokenReauthGuidance(email) {
27
+ const refreshCmd = email?.trim()
28
+ ? `neozip connect refresh --email ${email.trim().toLowerCase()}`
29
+ : "neozip connect refresh";
30
+ return [
31
+ "Token Service access token expired or rejected.",
32
+ "Refresh it (a 6-digit code is emailed to you):",
33
+ ` ${refreshCmd}`,
34
+ ` ${refreshCmd} --code 123456`,
35
+ "When the refresh completes, reload MCP in Cursor Settings if you use it.",
36
+ ].join("\n");
37
+ }
38
+ /** User-facing message for Token Service auth failures (401/403). */
39
+ function tokenServiceAuthErrorMessage(status, email) {
40
+ if (status !== 401 && status !== 403)
41
+ return null;
42
+ return formatTokenReauthGuidance(email);
43
+ }
44
+ //# sourceMappingURL=token-auth.js.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.walletJsonExists = walletJsonExists;
37
+ exports.loadWalletJson = loadWalletJson;
38
+ exports.archiveWalletJson = archiveWalletJson;
39
+ exports.migrateFromWalletJson = migrateFromWalletJson;
40
+ const fs = __importStar(require("node:fs"));
41
+ const os = __importStar(require("node:os"));
42
+ const path = __importStar(require("node:path"));
43
+ const ethers_1 = require("ethers");
44
+ const store_1 = require("./store");
45
+ const WALLET_JSON = path.join(os.homedir(), '.neozip', 'wallet.json');
46
+ const WALLET_JSON_MIGRATED = `${WALLET_JSON}.migrated`;
47
+ const LEGACY_RPC_KEY_TO_NETWORK = {
48
+ baseSepolia: 'base-sepolia',
49
+ baseMainnet: 'base-mainnet',
50
+ };
51
+ function walletJsonExists() {
52
+ return fs.existsSync(WALLET_JSON);
53
+ }
54
+ function loadWalletJson() {
55
+ if (!walletJsonExists()) {
56
+ return null;
57
+ }
58
+ try {
59
+ return JSON.parse(fs.readFileSync(WALLET_JSON, 'utf8'));
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ function archiveWalletJson() {
66
+ if (!walletJsonExists()) {
67
+ return false;
68
+ }
69
+ try {
70
+ if (fs.existsSync(WALLET_JSON_MIGRATED)) {
71
+ fs.unlinkSync(WALLET_JSON_MIGRATED);
72
+ }
73
+ fs.renameSync(WALLET_JSON, WALLET_JSON_MIGRATED);
74
+ return true;
75
+ }
76
+ catch {
77
+ return false;
78
+ }
79
+ }
80
+ function migrateFromWalletJson() {
81
+ const legacy = loadWalletJson();
82
+ if (!legacy) {
83
+ return { migratedPrefs: false, importedKey: false, archived: false, messages: [] };
84
+ }
85
+ const messages = [];
86
+ let migratedPrefs = false;
87
+ let importedKey = false;
88
+ const connectionId = (0, store_1.getActiveConnectionId)();
89
+ const meta = (0, store_1.getActiveConnection)();
90
+ const secrets = (0, store_1.readActiveConnectionSecrets)();
91
+ if (connectionId && meta) {
92
+ const patch = {};
93
+ if (legacy.wallet?.network && !meta.defaultNetwork) {
94
+ patch.defaultNetwork = legacy.wallet.network;
95
+ migratedPrefs = true;
96
+ }
97
+ if (legacy.rpc && Object.keys(legacy.rpc).length > 0) {
98
+ const rpcOverrides = { ...(meta.rpcOverrides ?? {}) };
99
+ for (const [key, url] of Object.entries(legacy.rpc)) {
100
+ if (!url?.trim())
101
+ continue;
102
+ const networkKey = LEGACY_RPC_KEY_TO_NETWORK[key] ?? key;
103
+ if (!rpcOverrides[networkKey]) {
104
+ rpcOverrides[networkKey] = url.trim();
105
+ migratedPrefs = true;
106
+ }
107
+ }
108
+ if (Object.keys(rpcOverrides).length > 0) {
109
+ patch.rpcOverrides = rpcOverrides;
110
+ }
111
+ }
112
+ if (legacy.gas && !meta.gas) {
113
+ patch.gas = legacy.gas;
114
+ migratedPrefs = true;
115
+ }
116
+ if (legacy.debug && !meta.debug) {
117
+ patch.debug = legacy.debug;
118
+ migratedPrefs = true;
119
+ }
120
+ if (Object.keys(patch).length > 0) {
121
+ (0, store_1.updateConnection)(connectionId, patch);
122
+ messages.push('Imported wallet.json preferences into active connection.');
123
+ }
124
+ const privateKey = legacy.wallet?.privateKey?.trim();
125
+ if (privateKey && !secrets?.evmPrivateKeyHex) {
126
+ if (meta.emailVerified && secrets?.accessToken) {
127
+ try {
128
+ const normalized = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;
129
+ const wallet = new ethers_1.Wallet(normalized);
130
+ (0, store_1.saveEvmWallet)(connectionId, wallet.privateKey, wallet.address);
131
+ importedKey = true;
132
+ messages.push(`Imported wallet private key (${wallet.address}). Run neozip connect finish if linking is incomplete.`);
133
+ }
134
+ catch (err) {
135
+ messages.push(`Could not import wallet key: ${err instanceof Error ? err.message : String(err)}. Run: neozip connect wallet import-key`);
136
+ }
137
+ }
138
+ else {
139
+ messages.push('wallet.json contains a private key but connection email is not verified. Run neozip connect, then: neozip connect wallet import-key --private-key 0x...');
140
+ }
141
+ }
142
+ else if (privateKey && secrets?.evmPrivateKeyHex) {
143
+ messages.push('Skipped wallet.json private key (connection store already has a wallet).');
144
+ }
145
+ }
146
+ else if (legacy.wallet?.privateKey || legacy.wallet?.network) {
147
+ messages.push('wallet.json found but no active connection. Run neozip connect first, then neozip connect migrate.');
148
+ }
149
+ const archived = migratedPrefs || importedKey ? archiveWalletJson() : false;
150
+ if (archived) {
151
+ messages.push(`Archived ${WALLET_JSON} → wallet.json.migrated`);
152
+ }
153
+ return { migratedPrefs, importedKey, archived, messages };
154
+ }
155
+ //# sourceMappingURL=wallet-json-migration.js.map
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.refreshAccessTokenViaWallet = refreshAccessTokenViaWallet;
4
+ exports.ensureFreshTokenServiceToken = ensureFreshTokenServiceToken;
5
+ /**
6
+ * Silent Token Service token renewal via the local Data Wallet (EVM) signature.
7
+ *
8
+ * The Token Service has no refresh-token grant, but it accepts a SIWE-style
9
+ * wallet-login: prove control of the Data Wallet private key (already the master
10
+ * key for the account's data wallet) and receive a fresh access token without an
11
+ * email OTP. This module performs that exchange and persists the new token,
12
+ * leaving the wallet/identity untouched.
13
+ */
14
+ const token_service_1 = require("neozip-blockchain/token-service");
15
+ const wallet_evm_1 = require("../account/wallet-evm");
16
+ const origin_1 = require("./origin");
17
+ const store_1 = require("./store");
18
+ const token_auth_1 = require("./token-auth");
19
+ /** Attempt a silent wallet-signature token renewal for the active connection. */
20
+ async function refreshAccessTokenViaWallet(options) {
21
+ const meta = (0, store_1.getActiveConnection)();
22
+ const secrets = (0, store_1.readActiveConnectionSecrets)();
23
+ const evmAddress = meta?.evmAddress?.trim();
24
+ const privateKeyHex = secrets?.evmPrivateKeyHex?.trim();
25
+ if (!meta || !evmAddress || !privateKeyHex) {
26
+ return { ok: false, reason: 'no_wallet' };
27
+ }
28
+ const origin = (0, origin_1.resolveTokenServiceOrigin)(options?.tokenServiceUrl ?? meta.tokenServiceOrigin);
29
+ const privateKey = privateKeyHex.startsWith('0x') ? privateKeyHex : `0x${privateKeyHex}`;
30
+ try {
31
+ const challenge = await (0, token_service_1.requestWalletLoginChallenge)(origin, evmAddress);
32
+ const signature = await (0, wallet_evm_1.signEvmMessage)(privateKey, challenge.message);
33
+ const out = await (0, token_service_1.walletLogin)(origin, {
34
+ evmAddress,
35
+ challengeId: challenge.challengeId,
36
+ evmSignature: signature,
37
+ });
38
+ (0, store_1.saveAccessToken)(meta.id, out.accessToken, meta.email ?? out.email ?? '', out.expiresAt);
39
+ (0, store_1.applyActiveConnectionToEnv)();
40
+ return { ok: true, expiresAt: out.expiresAt };
41
+ }
42
+ catch (err) {
43
+ if (err instanceof token_service_1.WalletLoginUnavailableError) {
44
+ return { ok: false, reason: 'unsupported', message: err.message };
45
+ }
46
+ return {
47
+ ok: false,
48
+ reason: 'error',
49
+ message: err instanceof Error ? err.message : String(err),
50
+ };
51
+ }
52
+ }
53
+ /**
54
+ * Best-effort: if the active access token is expired and a wallet is available,
55
+ * silently renew it via wallet login. Never throws; callers proceed and let the
56
+ * normal readiness checks surface any remaining problem.
57
+ */
58
+ async function ensureFreshTokenServiceToken(options) {
59
+ const secrets = (0, store_1.readActiveConnectionSecrets)();
60
+ if (!secrets?.accessToken || !(0, token_auth_1.isAccessTokenExpired)(secrets)) {
61
+ return;
62
+ }
63
+ await refreshAccessTokenViaWallet(options);
64
+ }
65
+ //# sourceMappingURL=wallet-login.js.map