neozip-cli 0.90.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.
- package/AGENTS.md +93 -0
- package/CHANGELOG.md +58 -1
- package/DOCUMENTATION.md +22 -30
- package/README.md +104 -42
- package/dist/src/account/account-state.js +95 -0
- package/dist/src/account/format-account-status.js +62 -0
- package/dist/src/account/identity-provision.js +79 -0
- package/dist/src/account/identity-wrap.js +106 -0
- package/dist/src/account/profile-crypto.js +85 -0
- package/dist/src/account/profile-store.js +129 -0
- package/dist/src/account/require-account.js +32 -0
- package/dist/src/account/types.js +3 -0
- package/dist/src/account/wallet-evm.js +46 -0
- package/dist/src/account/wallet-setup.js +33 -0
- package/dist/src/archive/crypto-self.js +117 -0
- package/dist/src/archive/identity-key.js +217 -0
- package/dist/src/archive/recipient-lookup.js +61 -0
- package/dist/src/cli/output.js +100 -0
- package/dist/src/cli/params.js +122 -0
- package/dist/src/cli/schema.js +186 -0
- package/dist/src/cli/validate.js +119 -0
- package/dist/src/commands/mintTimestampProof.js +26 -14
- package/dist/src/config/ConfigSetup.js +82 -423
- package/dist/src/connect/command.js +364 -0
- package/dist/src/connection/bootstrap.js +50 -0
- package/dist/src/connection/cli-guidance.js +101 -0
- package/dist/src/connection/cli-prefs.js +180 -0
- package/dist/src/connection/cli-settings.js +140 -0
- package/dist/src/connection/cli-types.js +14 -0
- package/dist/src/connection/coordinator.js +83 -0
- package/dist/src/connection/credentials.js +33 -0
- package/dist/src/connection/crypto.js +96 -0
- package/dist/src/connection/dump.js +117 -0
- package/dist/src/connection/funding.js +187 -0
- package/dist/src/connection/incomplete-setup.js +89 -0
- package/dist/src/connection/interactive.js +871 -0
- package/dist/src/connection/legacy-profile-reader.js +87 -0
- package/dist/src/connection/magic-link.js +142 -0
- package/dist/src/connection/migrate.js +115 -0
- package/dist/src/connection/onboarding.js +616 -0
- package/dist/src/connection/origin.js +69 -0
- package/dist/src/connection/phase.js +101 -0
- package/dist/src/connection/phone.js +26 -0
- package/dist/src/connection/promote-active.js +56 -0
- package/dist/src/connection/reset.js +56 -0
- package/dist/src/connection/status-report.js +52 -0
- package/dist/src/connection/store.js +406 -0
- package/dist/src/connection/token-auth.js +44 -0
- package/dist/src/connection/types.js +3 -0
- package/dist/src/connection/wallet-json-migration.js +155 -0
- package/dist/src/connection/wallet-login.js +65 -0
- package/dist/src/connection/wallet-setup.js +83 -0
- package/dist/src/constants/wallet-identity.js +14 -0
- package/dist/src/exit-codes.js +54 -10
- package/dist/src/neolist.js +93 -9
- package/dist/src/neounzip.js +217 -59
- package/dist/src/neozip/blockchain.js +18 -18
- package/dist/src/neozip/createZip.js +114 -91
- package/dist/src/neozip/upgradeZip.js +14 -11
- package/dist/src/neozip.js +252 -75
- package/dist/src/skills/command.js +256 -0
- package/dist/src/skills/locate.js +99 -0
- package/dist/src/util/mask.js +34 -0
- package/dist/src/util/token-service-fetch.js +26 -0
- package/env.example +18 -85
- package/package.json +89 -82
- package/skills/neozip-connect/SKILL.md +95 -0
- package/skills/neozip-create/SKILL.md +57 -0
- package/skills/neozip-extract/SKILL.md +58 -0
- package/skills/neozip-legacy/SKILL.md +48 -0
- package/skills/neozip-list/SKILL.md +56 -0
- package/skills/neozip-shared/SKILL.md +60 -0
- package/dist/src/commands/verifyEmail.js +0 -146
- package/dist/src/config/ConfigStore.js +0 -406
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.provisionWalletIdentityKey = provisionWalletIdentityKey;
|
|
4
|
+
exports.refreshIdentityFromCryptoSelf = refreshIdentityFromCryptoSelf;
|
|
5
|
+
const identity_key_1 = require("../archive/identity-key");
|
|
6
|
+
const crypto_self_1 = require("../archive/crypto-self");
|
|
7
|
+
const identity_wrap_1 = require("./identity-wrap");
|
|
8
|
+
const token_service_1 = require("neozip-blockchain/token-service");
|
|
9
|
+
const wallet_evm_1 = require("./wallet-evm");
|
|
10
|
+
async function provisionWalletIdentityKey(params) {
|
|
11
|
+
const existing = await (0, token_service_1.getIdentityKeyBundle)(params.baseUrl, params.accessToken, params.walletId);
|
|
12
|
+
if (existing.found) {
|
|
13
|
+
return {
|
|
14
|
+
identityKeyId: existing.identityKeyId,
|
|
15
|
+
x25519PublicKey: existing.x25519PublicKey,
|
|
16
|
+
provisioned: false,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const eoaPriv = (0, wallet_evm_1.rawEoaBytes)(params.evmPrivateKey);
|
|
20
|
+
try {
|
|
21
|
+
const wrap = (0, identity_wrap_1.wrapNewX25519Keypair)({
|
|
22
|
+
rawEoaPrivBytes: eoaPriv,
|
|
23
|
+
evmAddress: params.evmAddress,
|
|
24
|
+
});
|
|
25
|
+
const bundleBody = {
|
|
26
|
+
x25519PublicKeyB64: wrap.x25519PublicKeyB64,
|
|
27
|
+
...wrap.bundle,
|
|
28
|
+
};
|
|
29
|
+
const challenge = await (0, token_service_1.requestIdentityKeyInitChallenge)(params.baseUrl, params.accessToken, params.walletId, bundleBody);
|
|
30
|
+
const expectedMessage = (0, identity_wrap_1.buildIdentityKeyInitMessage)({
|
|
31
|
+
walletId: params.walletId,
|
|
32
|
+
challengeId: challenge.challengeId,
|
|
33
|
+
evmAddress: params.evmAddress,
|
|
34
|
+
formatVersion: wrap.bundle.wrapFormatVersion,
|
|
35
|
+
x25519PublicKeyB64: wrap.x25519PublicKeyB64,
|
|
36
|
+
wrappedSha256Hex: wrap.wrappedSha256Hex,
|
|
37
|
+
});
|
|
38
|
+
if (challenge.message !== expectedMessage) {
|
|
39
|
+
throw new identity_key_1.IdentityKeyTamperError("Server init message does not match canonical form expected by this client.");
|
|
40
|
+
}
|
|
41
|
+
const evmSignature = await (0, wallet_evm_1.signEvmMessage)(params.evmPrivateKey, challenge.message);
|
|
42
|
+
try {
|
|
43
|
+
const completed = await (0, token_service_1.completeIdentityKeyInit)(params.baseUrl, params.accessToken, params.walletId, bundleBody, challenge.challengeId, evmSignature);
|
|
44
|
+
return {
|
|
45
|
+
identityKeyId: completed.identityKeyId,
|
|
46
|
+
x25519PublicKey: completed.x25519PublicKey,
|
|
47
|
+
provisioned: true,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err instanceof token_service_1.IdentityKeyConflictError) {
|
|
52
|
+
const reloaded = await (0, token_service_1.getIdentityKeyBundle)(params.baseUrl, params.accessToken, params.walletId);
|
|
53
|
+
if (reloaded.found) {
|
|
54
|
+
return {
|
|
55
|
+
identityKeyId: reloaded.identityKeyId,
|
|
56
|
+
x25519PublicKey: reloaded.x25519PublicKey,
|
|
57
|
+
provisioned: false,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
eoaPriv.fill(0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Sync profile metadata with live /crypto/self when token is available. */
|
|
69
|
+
async function refreshIdentityFromCryptoSelf(config) {
|
|
70
|
+
const self = await (0, crypto_self_1.fetchCryptoSelf)(config);
|
|
71
|
+
if (!self.ok) {
|
|
72
|
+
return { identityKeyId: null, walletId: null };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
identityKeyId: self.data.identityKeyId,
|
|
76
|
+
walletId: self.data.walletId,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=identity-provision.js.map
|
|
@@ -0,0 +1,106 @@
|
|
|
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.buildIdentityKeyInitMessage = buildIdentityKeyInitMessage;
|
|
37
|
+
exports.wrapNewX25519Keypair = wrapNewX25519Keypair;
|
|
38
|
+
const crypto = __importStar(require("node:crypto"));
|
|
39
|
+
const wallet_identity_1 = require("../constants/wallet-identity");
|
|
40
|
+
function buildCanonicalAad(params) {
|
|
41
|
+
const lowerAddr = params.evmAddress.toLowerCase();
|
|
42
|
+
const addrBytes = Buffer.from(lowerAddr, "ascii");
|
|
43
|
+
return Buffer.concat([
|
|
44
|
+
addrBytes,
|
|
45
|
+
Buffer.from([wallet_identity_1.WRAP_FORMAT_VERSION]),
|
|
46
|
+
params.x25519SpkiDer,
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
function deriveKek(rawEoaPrivBytes, saltB64) {
|
|
50
|
+
const salt = Buffer.from(saltB64, "base64");
|
|
51
|
+
if (salt.length !== wallet_identity_1.WRAP_KDF_SALT_LEN) {
|
|
52
|
+
throw new Error(`Wrap KDF salt must be ${wallet_identity_1.WRAP_KDF_SALT_LEN} bytes`);
|
|
53
|
+
}
|
|
54
|
+
return Buffer.from(crypto.hkdfSync("sha256", rawEoaPrivBytes, salt, wallet_identity_1.WRAP_KDF_INFO, 32));
|
|
55
|
+
}
|
|
56
|
+
function sha256Hex(buf) {
|
|
57
|
+
return crypto.createHash("sha256").update(buf).digest("hex");
|
|
58
|
+
}
|
|
59
|
+
function buildIdentityKeyInitMessage(params) {
|
|
60
|
+
return [
|
|
61
|
+
"NeoZip Token Service identity key init",
|
|
62
|
+
`walletId:${params.walletId}`,
|
|
63
|
+
`challenge:${params.challengeId}`,
|
|
64
|
+
`address:${params.evmAddress.toLowerCase()}`,
|
|
65
|
+
`formatVersion:${params.formatVersion}`,
|
|
66
|
+
`x25519:${params.x25519PublicKeyB64}`,
|
|
67
|
+
`wrappedSha256:${params.wrappedSha256Hex}`,
|
|
68
|
+
].join("\n");
|
|
69
|
+
}
|
|
70
|
+
function wrapNewX25519Keypair(params) {
|
|
71
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync("x25519");
|
|
72
|
+
const spkiDer = publicKey.export({ type: "spki", format: "der" });
|
|
73
|
+
const pkcs8Der = privateKey.export({ type: "pkcs8", format: "der" });
|
|
74
|
+
const rawPriv = pkcs8Der.subarray(pkcs8Der.length - 32);
|
|
75
|
+
const saltB64 = crypto.randomBytes(wallet_identity_1.WRAP_KDF_SALT_LEN).toString("base64");
|
|
76
|
+
const ivB64 = crypto.randomBytes(wallet_identity_1.WRAP_IV_LEN).toString("base64");
|
|
77
|
+
const aad = buildCanonicalAad({
|
|
78
|
+
evmAddress: params.evmAddress,
|
|
79
|
+
x25519SpkiDer: spkiDer,
|
|
80
|
+
});
|
|
81
|
+
const kek = deriveKek(params.rawEoaPrivBytes, saltB64);
|
|
82
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
83
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", kek, iv);
|
|
84
|
+
cipher.setAAD(aad);
|
|
85
|
+
const ct = Buffer.concat([cipher.update(rawPriv), cipher.final()]);
|
|
86
|
+
const tag = cipher.getAuthTag();
|
|
87
|
+
const wrapped = Buffer.concat([ct, tag]);
|
|
88
|
+
kek.fill(0);
|
|
89
|
+
rawPriv.fill(0);
|
|
90
|
+
pkcs8Der.fill(0);
|
|
91
|
+
const bundle = {
|
|
92
|
+
wrappedPrivateKeyB64: wrapped.toString("base64"),
|
|
93
|
+
wrapFormatVersion: wallet_identity_1.WRAP_FORMAT_VERSION,
|
|
94
|
+
wrapKdfInfo: wallet_identity_1.WRAP_KDF_INFO,
|
|
95
|
+
wrapKdfSaltB64: saltB64,
|
|
96
|
+
wrapAead: wallet_identity_1.WRAP_AEAD,
|
|
97
|
+
wrapIvB64: ivB64,
|
|
98
|
+
wrapAadB64: aad.toString("base64"),
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
bundle,
|
|
102
|
+
x25519PublicKeyB64: spkiDer.toString("base64"),
|
|
103
|
+
wrappedSha256Hex: sha256Hex(wrapped),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=identity-wrap.js.map
|
|
@@ -0,0 +1,85 @@
|
|
|
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.deriveProfileKey = deriveProfileKey;
|
|
37
|
+
exports.encryptJson = encryptJson;
|
|
38
|
+
exports.decryptJson = decryptJson;
|
|
39
|
+
const crypto = __importStar(require("node:crypto"));
|
|
40
|
+
const os = __importStar(require("node:os"));
|
|
41
|
+
const PROFILE_KDF_INFO = "NeoZip/McpProfileSecrets/v1";
|
|
42
|
+
const PROFILE_KDF_SALT = Buffer.from("NeoZipMcpProfileStoreSalt-v1", "utf8");
|
|
43
|
+
function deriveProfileKey() {
|
|
44
|
+
const passphrase = process.env.NEOZIP_UNLOCK_PASSPHRASE?.trim() ||
|
|
45
|
+
`${os.hostname()}:${os.userInfo().username}:neozip-mcp-profile`;
|
|
46
|
+
const okm = crypto.hkdfSync("sha256", Buffer.from(passphrase, "utf8"), PROFILE_KDF_SALT, PROFILE_KDF_INFO, 32);
|
|
47
|
+
return Buffer.from(okm);
|
|
48
|
+
}
|
|
49
|
+
function encryptJson(payload) {
|
|
50
|
+
const key = deriveProfileKey();
|
|
51
|
+
const iv = crypto.randomBytes(12);
|
|
52
|
+
const plaintext = Buffer.from(JSON.stringify(payload), "utf8");
|
|
53
|
+
try {
|
|
54
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
|
|
55
|
+
const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
56
|
+
const tag = cipher.getAuthTag();
|
|
57
|
+
return JSON.stringify({
|
|
58
|
+
v: 1,
|
|
59
|
+
iv: iv.toString("base64"),
|
|
60
|
+
tag: tag.toString("base64"),
|
|
61
|
+
data: ct.toString("base64"),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
key.fill(0);
|
|
66
|
+
plaintext.fill(0);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function decryptJson(encrypted) {
|
|
70
|
+
const key = deriveProfileKey();
|
|
71
|
+
const parsed = JSON.parse(encrypted);
|
|
72
|
+
const iv = Buffer.from(parsed.iv, "base64");
|
|
73
|
+
const tag = Buffer.from(parsed.tag, "base64");
|
|
74
|
+
const ct = Buffer.from(parsed.data, "base64");
|
|
75
|
+
try {
|
|
76
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
|
|
77
|
+
decipher.setAuthTag(tag);
|
|
78
|
+
const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
|
|
79
|
+
return JSON.parse(pt.toString("utf8"));
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
key.fill(0);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=profile-crypto.js.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.savePhoneVerified = exports.saveIdentityProvision = exports.saveWalletLink = exports.saveEvmWallet = exports.saveAccessToken = void 0;
|
|
4
|
+
exports.getMcpProfileDir = getMcpProfileDir;
|
|
5
|
+
exports.listProfiles = listProfiles;
|
|
6
|
+
exports.getActiveProfileId = getActiveProfileId;
|
|
7
|
+
exports.getActiveProfile = getActiveProfile;
|
|
8
|
+
exports.selectProfile = selectProfile;
|
|
9
|
+
exports.createProfile = createProfile;
|
|
10
|
+
exports.updateProfile = updateProfile;
|
|
11
|
+
exports.removeProfile = removeProfile;
|
|
12
|
+
exports.readSecrets = readSecrets;
|
|
13
|
+
exports.readActiveSecrets = readActiveSecrets;
|
|
14
|
+
exports.logoutProfile = logoutProfile;
|
|
15
|
+
exports.clearProfileCredentialsFromEnv = clearProfileCredentialsFromEnv;
|
|
16
|
+
exports.applyActiveProfileToEnv = applyActiveProfileToEnv;
|
|
17
|
+
const store_1 = require("../connection/store");
|
|
18
|
+
Object.defineProperty(exports, "saveAccessToken", { enumerable: true, get: function () { return store_1.saveAccessToken; } });
|
|
19
|
+
Object.defineProperty(exports, "saveEvmWallet", { enumerable: true, get: function () { return store_1.saveEvmWallet; } });
|
|
20
|
+
Object.defineProperty(exports, "saveIdentityProvision", { enumerable: true, get: function () { return store_1.saveIdentityProvision; } });
|
|
21
|
+
Object.defineProperty(exports, "savePhoneVerified", { enumerable: true, get: function () { return store_1.savePhoneVerified; } });
|
|
22
|
+
Object.defineProperty(exports, "saveWalletLink", { enumerable: true, get: function () { return store_1.saveWalletLink; } });
|
|
23
|
+
const migrate_1 = require("../connection/migrate");
|
|
24
|
+
function getMcpProfileDir() {
|
|
25
|
+
return (0, store_1.getConnectionDir)();
|
|
26
|
+
}
|
|
27
|
+
function ensureMigrated() {
|
|
28
|
+
if ((0, migrate_1.hasLegacyMcpProfiles)()) {
|
|
29
|
+
(0, migrate_1.migrateFromMcpProfileStore)();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function toProfile(meta) {
|
|
33
|
+
if (!meta)
|
|
34
|
+
return null;
|
|
35
|
+
return {
|
|
36
|
+
id: meta.id,
|
|
37
|
+
label: meta.label,
|
|
38
|
+
tokenServiceUrl: meta.tokenServiceOrigin,
|
|
39
|
+
email: meta.email,
|
|
40
|
+
emailVerified: meta.emailVerified,
|
|
41
|
+
evmAddress: meta.evmAddress,
|
|
42
|
+
walletId: meta.walletId,
|
|
43
|
+
linkId: meta.linkId,
|
|
44
|
+
identityKeyId: meta.identityKeyId,
|
|
45
|
+
x25519Fingerprint: meta.x25519Fingerprint,
|
|
46
|
+
createdAt: meta.createdAt,
|
|
47
|
+
updatedAt: meta.updatedAt,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function toSecrets(secrets) {
|
|
51
|
+
if (!secrets)
|
|
52
|
+
return null;
|
|
53
|
+
return {
|
|
54
|
+
accessToken: secrets.accessToken,
|
|
55
|
+
evmPrivateKey: secrets.evmPrivateKeyHex,
|
|
56
|
+
accessTokenObtainedAt: secrets.accessTokenObtainedAt,
|
|
57
|
+
accessTokenExpiresAt: secrets.accessTokenExpiresAt,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function listProfiles() {
|
|
61
|
+
ensureMigrated();
|
|
62
|
+
return (0, store_1.listConnections)().map((c) => ({
|
|
63
|
+
id: c.id,
|
|
64
|
+
label: c.label,
|
|
65
|
+
tokenServiceUrl: c.tokenServiceOrigin,
|
|
66
|
+
email: c.email,
|
|
67
|
+
emailVerified: c.emailVerified,
|
|
68
|
+
evmAddress: c.evmAddress,
|
|
69
|
+
walletId: c.walletId,
|
|
70
|
+
linkId: c.linkId,
|
|
71
|
+
identityKeyId: c.identityKeyId,
|
|
72
|
+
x25519Fingerprint: c.x25519Fingerprint,
|
|
73
|
+
createdAt: c.createdAt,
|
|
74
|
+
updatedAt: c.updatedAt,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
function getActiveProfileId() {
|
|
78
|
+
ensureMigrated();
|
|
79
|
+
return (0, store_1.getActiveConnectionId)();
|
|
80
|
+
}
|
|
81
|
+
function getActiveProfile() {
|
|
82
|
+
ensureMigrated();
|
|
83
|
+
return toProfile((0, store_1.getActiveConnection)());
|
|
84
|
+
}
|
|
85
|
+
function selectProfile(profileId) {
|
|
86
|
+
ensureMigrated();
|
|
87
|
+
return toProfile((0, store_1.selectConnection)(profileId));
|
|
88
|
+
}
|
|
89
|
+
function createProfile(input) {
|
|
90
|
+
ensureMigrated();
|
|
91
|
+
return toProfile((0, store_1.createConnection)({ label: input.label, tokenServiceUrl: input.tokenServiceUrl }));
|
|
92
|
+
}
|
|
93
|
+
function updateProfile(profileId, patch) {
|
|
94
|
+
ensureMigrated();
|
|
95
|
+
const mapped = { ...patch };
|
|
96
|
+
if (patch.tokenServiceUrl) {
|
|
97
|
+
mapped.tokenServiceOrigin = patch.tokenServiceUrl;
|
|
98
|
+
delete mapped.tokenServiceUrl;
|
|
99
|
+
}
|
|
100
|
+
return toProfile((0, store_1.updateConnection)(profileId, mapped));
|
|
101
|
+
}
|
|
102
|
+
function removeProfile(_profileId, confirm) {
|
|
103
|
+
if (!confirm) {
|
|
104
|
+
throw new Error("Set confirm: true to delete the profile and its secrets.");
|
|
105
|
+
}
|
|
106
|
+
throw new Error("Profile removal via account_remove is deprecated. Use neozip connect logout.");
|
|
107
|
+
}
|
|
108
|
+
function readSecrets(profileId) {
|
|
109
|
+
ensureMigrated();
|
|
110
|
+
return toSecrets((0, store_1.readConnectionSecrets)(profileId));
|
|
111
|
+
}
|
|
112
|
+
function readActiveSecrets() {
|
|
113
|
+
ensureMigrated();
|
|
114
|
+
return toSecrets((0, store_1.readActiveConnectionSecrets)());
|
|
115
|
+
}
|
|
116
|
+
function logoutProfile(profileId) {
|
|
117
|
+
ensureMigrated();
|
|
118
|
+
const out = (0, store_1.logoutConnection)(profileId);
|
|
119
|
+
return { ...out, profileId: out.connectionId };
|
|
120
|
+
}
|
|
121
|
+
function clearProfileCredentialsFromEnv() {
|
|
122
|
+
(0, store_1.clearConnectionCredentialsFromEnv)();
|
|
123
|
+
}
|
|
124
|
+
function applyActiveProfileToEnv() {
|
|
125
|
+
ensureMigrated();
|
|
126
|
+
const out = (0, store_1.applyActiveConnectionToEnv)();
|
|
127
|
+
return { applied: out.applied, profileId: out.connectionId };
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=profile-store.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireAccountReady = requireAccountReady;
|
|
4
|
+
const phase_1 = require("../connection/phase");
|
|
5
|
+
const store_1 = require("../connection/store");
|
|
6
|
+
const token_auth_1 = require("../connection/token-auth");
|
|
7
|
+
async function requireAccountReady(context) {
|
|
8
|
+
const phase = (0, phase_1.computeConnectionPhase)();
|
|
9
|
+
const meta = (0, store_1.getActiveConnection)();
|
|
10
|
+
const secrets = (0, store_1.readActiveConnectionSecrets)();
|
|
11
|
+
if (secrets?.accessToken?.trim() && (0, token_auth_1.isAccessTokenExpired)(secrets)) {
|
|
12
|
+
return [
|
|
13
|
+
`${context} requires a valid Token Service access token.`,
|
|
14
|
+
(0, token_auth_1.formatTokenReauthGuidance)(meta?.email),
|
|
15
|
+
].join("\n\n");
|
|
16
|
+
}
|
|
17
|
+
if (phase !== "ready") {
|
|
18
|
+
const nextCmd = (0, phase_1.nextConnectCommand)(phase, {
|
|
19
|
+
email: meta?.email,
|
|
20
|
+
phoneE164: meta?.phoneE164,
|
|
21
|
+
});
|
|
22
|
+
const parts = [
|
|
23
|
+
`${context} requires a fully initialized NeoZip account (phase: ${phase}).`,
|
|
24
|
+
];
|
|
25
|
+
if (nextCmd)
|
|
26
|
+
parts.push(`Run: ${nextCmd}`);
|
|
27
|
+
parts.push("Reload MCP after setup so credentials load into this session.");
|
|
28
|
+
return parts.join(" ");
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=require-account.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateEvmIdentity = generateEvmIdentity;
|
|
4
|
+
exports.evmIdentityFromMnemonic = evmIdentityFromMnemonic;
|
|
5
|
+
exports.evmIdentityFromPrivateKey = evmIdentityFromPrivateKey;
|
|
6
|
+
exports.signEvmMessage = signEvmMessage;
|
|
7
|
+
exports.rawEoaBytes = rawEoaBytes;
|
|
8
|
+
const ethers_1 = require("ethers");
|
|
9
|
+
function generateEvmIdentity() {
|
|
10
|
+
const wallet = ethers_1.Wallet.createRandom();
|
|
11
|
+
return {
|
|
12
|
+
address: wallet.address,
|
|
13
|
+
privateKey: wallet.privateKey,
|
|
14
|
+
mnemonic: wallet.mnemonic?.phrase ?? null,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function evmIdentityFromMnemonic(mnemonic) {
|
|
18
|
+
const phrase = mnemonic.trim().split(/\s+/).join(" ");
|
|
19
|
+
const wallet = ethers_1.Wallet.fromPhrase(phrase);
|
|
20
|
+
return {
|
|
21
|
+
address: wallet.address,
|
|
22
|
+
privateKey: wallet.privateKey,
|
|
23
|
+
mnemonic: wallet.mnemonic?.phrase ?? phrase,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function evmIdentityFromPrivateKey(privateKey) {
|
|
27
|
+
const raw = privateKey.trim();
|
|
28
|
+
const normalized = raw.startsWith("0x") ? raw : `0x${raw}`;
|
|
29
|
+
const wallet = new ethers_1.Wallet(normalized);
|
|
30
|
+
return {
|
|
31
|
+
address: wallet.address,
|
|
32
|
+
privateKey: wallet.privateKey,
|
|
33
|
+
mnemonic: null,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function signEvmMessage(privateKey, message) {
|
|
37
|
+
const wallet = new ethers_1.Wallet(privateKey);
|
|
38
|
+
return wallet.signMessage(message);
|
|
39
|
+
}
|
|
40
|
+
function rawEoaBytes(privateKey) {
|
|
41
|
+
const stripped = privateKey.startsWith("0x")
|
|
42
|
+
? privateKey.slice(2)
|
|
43
|
+
: privateKey;
|
|
44
|
+
return Buffer.from(stripped, "hex");
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=wallet-evm.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runWalletEnsureAndAttach = runWalletEnsureAndAttach;
|
|
4
|
+
/**
|
|
5
|
+
* Local orchestration for linking the Data Wallet to a Token Service account.
|
|
6
|
+
*
|
|
7
|
+
* The individual HTTP calls live in `neozip-blockchain/token-service`; this
|
|
8
|
+
* module composes the challenge/complete pairs around a local EVM signer, since
|
|
9
|
+
* signing requires the wallet's private key, which never leaves the CLI host.
|
|
10
|
+
*/
|
|
11
|
+
const token_service_1 = require("neozip-blockchain/token-service");
|
|
12
|
+
const wallet_evm_1 = require("./wallet-evm");
|
|
13
|
+
/**
|
|
14
|
+
* Ensure a wallet record exists for `evmAddress` and attach it to the
|
|
15
|
+
* authenticated account as the primary wallet, signing both challenges locally.
|
|
16
|
+
*/
|
|
17
|
+
async function runWalletEnsureAndAttach(baseUrl, accessToken, evmPrivateKey, evmAddress) {
|
|
18
|
+
const ensureCh = await (0, token_service_1.requestWalletEnsureChallenge)(baseUrl, evmAddress);
|
|
19
|
+
const ensureSig = await (0, wallet_evm_1.signEvmMessage)(evmPrivateKey, ensureCh.message);
|
|
20
|
+
const ensured = await (0, token_service_1.completeWalletEnsure)(baseUrl, {
|
|
21
|
+
evmAddress,
|
|
22
|
+
challengeId: ensureCh.challengeId,
|
|
23
|
+
evmSignature: ensureSig,
|
|
24
|
+
});
|
|
25
|
+
const attachCh = await (0, token_service_1.requestWalletAttachChallenge)(baseUrl, accessToken, ensured.walletId);
|
|
26
|
+
const attachSig = await (0, wallet_evm_1.signEvmMessage)(evmPrivateKey, attachCh.message);
|
|
27
|
+
const { linkId } = await (0, token_service_1.completeWalletAttach)(baseUrl, accessToken, ensured.walletId, {
|
|
28
|
+
challengeId: attachCh.challengeId,
|
|
29
|
+
evmSignature: attachSig,
|
|
30
|
+
});
|
|
31
|
+
return { walletId: ensured.walletId, evmAddress: ensured.evmAddress, linkId };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=wallet-setup.js.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchCryptoSelf = fetchCryptoSelf;
|
|
4
|
+
const recipient_lookup_1 = require("./recipient-lookup");
|
|
5
|
+
const token_auth_1 = require("../connection/token-auth");
|
|
6
|
+
const store_1 = require("../connection/store");
|
|
7
|
+
function pickString(obj, key) {
|
|
8
|
+
const v = obj[key];
|
|
9
|
+
return typeof v === "string" && v.length > 0 ? v : null;
|
|
10
|
+
}
|
|
11
|
+
function parseCryptoSelfBody(parsed, status) {
|
|
12
|
+
if (parsed.success !== true) {
|
|
13
|
+
const err = typeof parsed.error === "string"
|
|
14
|
+
? parsed.error
|
|
15
|
+
: "Unexpected /crypto/self response";
|
|
16
|
+
const hint = typeof parsed.hint === "string" ? parsed.hint : undefined;
|
|
17
|
+
return { ok: false, status, error: err, hint };
|
|
18
|
+
}
|
|
19
|
+
const cryptoRaw = parsed.crypto;
|
|
20
|
+
if (!cryptoRaw || typeof cryptoRaw !== "object") {
|
|
21
|
+
return { ok: false, status, error: "crypto/self missing crypto object" };
|
|
22
|
+
}
|
|
23
|
+
const c = cryptoRaw;
|
|
24
|
+
const walletId = typeof c.walletId === "number" ? c.walletId : Number(c.walletId);
|
|
25
|
+
const identityKeyIdRaw = c.identityKeyId;
|
|
26
|
+
const identityKeyId = typeof identityKeyIdRaw === "number"
|
|
27
|
+
? identityKeyIdRaw
|
|
28
|
+
: identityKeyIdRaw == null
|
|
29
|
+
? null
|
|
30
|
+
: Number.isFinite(Number(identityKeyIdRaw))
|
|
31
|
+
? Number(identityKeyIdRaw)
|
|
32
|
+
: null;
|
|
33
|
+
const evmAddress = pickString(c, "evmAddress");
|
|
34
|
+
const x25519PublicKey = pickString(c, "x25519PublicKey");
|
|
35
|
+
if (!Number.isFinite(walletId) || !evmAddress || !x25519PublicKey) {
|
|
36
|
+
return { ok: false, status, error: "crypto/self crypto object incomplete" };
|
|
37
|
+
}
|
|
38
|
+
const recipientSuites = Array.isArray(c.recipientSuites)
|
|
39
|
+
? c.recipientSuites.filter((s) => typeof s === "string")
|
|
40
|
+
: [];
|
|
41
|
+
return {
|
|
42
|
+
ok: true,
|
|
43
|
+
data: {
|
|
44
|
+
userId: typeof parsed.userId === "number"
|
|
45
|
+
? parsed.userId
|
|
46
|
+
: Number(parsed.userId),
|
|
47
|
+
email: typeof parsed.email === "string" ? parsed.email : "",
|
|
48
|
+
phoneE164: typeof parsed.phoneE164 === "string" ? parsed.phoneE164 : null,
|
|
49
|
+
phoneVerified: parsed.phoneVerified === true,
|
|
50
|
+
walletId,
|
|
51
|
+
identityKeyId,
|
|
52
|
+
evmAddress,
|
|
53
|
+
x25519PublicKey,
|
|
54
|
+
cryptoProvisionedAt: typeof c.cryptoProvisionedAt === "string"
|
|
55
|
+
? c.cryptoProvisionedAt
|
|
56
|
+
: null,
|
|
57
|
+
mlkem768PublicKeyB64: typeof c.mlkem768PublicKeyB64 === "string"
|
|
58
|
+
? c.mlkem768PublicKeyB64
|
|
59
|
+
: null,
|
|
60
|
+
recipientSuites,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function fetchCryptoSelf(config, options) {
|
|
65
|
+
const accessToken = config.tokenServiceAccessToken?.trim();
|
|
66
|
+
if (!accessToken) {
|
|
67
|
+
return {
|
|
68
|
+
ok: false,
|
|
69
|
+
status: 0,
|
|
70
|
+
error: "NEOZIP_TOKEN_SERVICE_ACCESS_TOKEN not configured. Complete token_service_verify and set the token in MCP env.",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const baseUrl = (0, recipient_lookup_1.resolveTokenServiceBaseUrl)(config, options?.serverUrl);
|
|
74
|
+
const response = await fetch(`${baseUrl}/crypto/self`, {
|
|
75
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
76
|
+
});
|
|
77
|
+
const ct = response.headers.get("content-type") || "";
|
|
78
|
+
if (!ct.includes("json")) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
status: response.status,
|
|
82
|
+
error: `Token Service returned non-JSON (HTTP ${response.status})`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
let parsed;
|
|
86
|
+
try {
|
|
87
|
+
parsed = (await response.json());
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
status: response.status,
|
|
93
|
+
error: `Invalid JSON from Token Service (HTTP ${response.status})`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (response.status === 404) {
|
|
97
|
+
const err = typeof parsed.error === "string"
|
|
98
|
+
? parsed.error
|
|
99
|
+
: "Identity key not found";
|
|
100
|
+
const hint = typeof parsed.hint === "string" ? parsed.hint : undefined;
|
|
101
|
+
return { ok: false, status: 404, error: err, hint };
|
|
102
|
+
}
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const err = typeof parsed.error === "string"
|
|
105
|
+
? parsed.error
|
|
106
|
+
: `HTTP ${response.status}`;
|
|
107
|
+
const authHint = (0, token_auth_1.tokenServiceAuthErrorMessage)(response.status, (0, store_1.getActiveConnection)()?.email);
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
status: response.status,
|
|
111
|
+
error: authHint ?? err,
|
|
112
|
+
hint: authHint ? 'Re-run neozip connect verify.' : undefined,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return parseCryptoSelfBody(parsed, response.status);
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=crypto-self.js.map
|