vana-cli 0.25.0 → 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/README.md +8 -0
- package/dist/cli/auth.d.ts +2 -0
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +2 -1
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +40 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server-start.d.ts +51 -0
- package/dist/cli/server-start.d.ts.map +1 -0
- package/dist/cli/server-start.js +337 -0
- package/dist/cli/server-start.js.map +1 -0
- package/dist/personal-server/index.d.ts +1 -0
- package/dist/personal-server/index.d.ts.map +1 -1
- package/dist/personal-server/index.js +17 -2
- package/dist/personal-server/index.js.map +1 -1
- package/dist/personal-server/local/config.d.ts +28 -0
- package/dist/personal-server/local/config.d.ts.map +1 -0
- package/dist/personal-server/local/config.js +53 -0
- package/dist/personal-server/local/config.js.map +1 -0
- package/dist/personal-server/local/frpc.d.ts +59 -0
- package/dist/personal-server/local/frpc.d.ts.map +1 -0
- package/dist/personal-server/local/frpc.js +191 -0
- package/dist/personal-server/local/frpc.js.map +1 -0
- package/dist/personal-server/local/owner-binding.d.ts +53 -0
- package/dist/personal-server/local/owner-binding.d.ts.map +1 -0
- package/dist/personal-server/local/owner-binding.js +164 -0
- package/dist/personal-server/local/owner-binding.js.map +1 -0
- package/dist/personal-server/local/owner-secret.d.ts +17 -0
- package/dist/personal-server/local/owner-secret.d.ts.map +1 -0
- package/dist/personal-server/local/owner-secret.js +119 -0
- package/dist/personal-server/local/owner-secret.js.map +1 -0
- package/dist/personal-server/local/registration.d.ts +42 -0
- package/dist/personal-server/local/registration.d.ts.map +1 -0
- package/dist/personal-server/local/registration.js +81 -0
- package/dist/personal-server/local/registration.js.map +1 -0
- package/dist/personal-server/local/runtime-pkg/entry.mjs +271 -0
- package/dist/personal-server/local/runtime-pkg/package-lock.json +2342 -0
- package/dist/personal-server/local/runtime-pkg/package.json +13 -0
- package/dist/personal-server/local/runtime.d.ts +9 -0
- package/dist/personal-server/local/runtime.d.ts.map +1 -0
- package/dist/personal-server/local/runtime.js +66 -0
- package/dist/personal-server/local/runtime.js.map +1 -0
- package/dist/personal-server/local/server.d.ts +64 -0
- package/dist/personal-server/local/server.d.ts.map +1 -0
- package/dist/personal-server/local/server.js +279 -0
- package/dist/personal-server/local/server.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frpc.d.ts","sourceRoot":"","sources":["../../../src/personal-server/local/frpc.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;CACf;AAoBD;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAwBvD,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,UAM9B,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gEAAgE;IAChE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAMD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CASlB;AAqBD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAChC,OAAO,CAAC,cAAc,CAAC,CA2CzB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAO,GAC/D,OAAO,CAAC,MAAM,CAAC,CAyDjB"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import fsp from "node:fs/promises";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
import * as tar from "tar";
|
|
9
|
+
import { localServerHome } from "./config.js";
|
|
10
|
+
const execFileAsync = promisify(execFile);
|
|
11
|
+
/**
|
|
12
|
+
* The tunnel client the Personal Server runs to get its public URL. Same
|
|
13
|
+
* version the pinned server would download for itself.
|
|
14
|
+
*/
|
|
15
|
+
export const FRPC_VERSION = "0.67.0";
|
|
16
|
+
/** The Apple team that signs the CLI and Vana Desktop. */
|
|
17
|
+
export const VANA_APPLE_TEAM_ID = "G7QNBSSW44";
|
|
18
|
+
function upstream(name, ext, sha256) {
|
|
19
|
+
const base = `frp_${FRPC_VERSION}_${name}`;
|
|
20
|
+
return {
|
|
21
|
+
url: `https://github.com/fatedier/frp/releases/download/v${FRPC_VERSION}/${base}.${ext}`,
|
|
22
|
+
sha256,
|
|
23
|
+
entry: `${base}/${name.startsWith("windows") ? "frpc.exe" : "frpc"}`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function signed(name, sha256) {
|
|
27
|
+
const base = `frp_${FRPC_VERSION}_${name}`;
|
|
28
|
+
return {
|
|
29
|
+
url: `https://github.com/vana-com/vana-cli/releases/download/frpc-v${FRPC_VERSION}/${base}.tar.gz`,
|
|
30
|
+
sha256,
|
|
31
|
+
entry: `${base}/frpc`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Pinned downloads per platform. A Mac never gets upstream's build: it is
|
|
36
|
+
* ad-hoc signed, and endpoint security on managed Macs treats an ad-hoc
|
|
37
|
+
* binary run from the home directory as persistence. Macs download the copy
|
|
38
|
+
* the sign-frpc workflow signed and notarized with Vana's Developer ID.
|
|
39
|
+
*/
|
|
40
|
+
export const FRPC_ARTIFACTS = {
|
|
41
|
+
"darwin-arm64": signed("darwin_arm64", "e0a45a02b8be7d2e0e3221b1e1deb242b490a1e6a685beeff04bcd96cb42a9f1"),
|
|
42
|
+
"darwin-x64": signed("darwin_amd64", "106f023c440b395cf7d21283536a87156c69f26ebf40fd0084f11fc01de8f6a4"),
|
|
43
|
+
"linux-x64": upstream("linux_amd64", "tar.gz", "f8629ca7ca56b8e7e7a9903779b8d5c47c56ad1b75b99b2d7138477acc4c7105"),
|
|
44
|
+
"linux-arm64": upstream("linux_arm64", "tar.gz", "0e9683226acdcbbb2ac8d073f35ba8be2a8b1e7584684d2073f39d337ebd6de7"),
|
|
45
|
+
"win32-x64": upstream("windows_amd64", "zip", "8baf23e3fbd486f6ba0913501372c5ff0053efa88a8b8d391f3605ced43d2af5"),
|
|
46
|
+
};
|
|
47
|
+
/** Where Vana Desktop ships its signed frpc. */
|
|
48
|
+
export const DESKTOP_FRPC_PATHS = [
|
|
49
|
+
"/Applications/Vana.app/Contents/Resources/personal-server/dist/frpc",
|
|
50
|
+
path.join(os.homedir(), "Applications/Vana.app/Contents/Resources/personal-server/dist/frpc"),
|
|
51
|
+
];
|
|
52
|
+
function binaryName(platform) {
|
|
53
|
+
return platform === "win32" ? "frpc.exe" : "frpc";
|
|
54
|
+
}
|
|
55
|
+
export function managedFrpcDir() {
|
|
56
|
+
return path.join(localServerHome(), "frpc", FRPC_VERSION);
|
|
57
|
+
}
|
|
58
|
+
export async function signedByTeam(file, teamId) {
|
|
59
|
+
try {
|
|
60
|
+
await execFileAsync("codesign", ["--verify", "--strict", file]);
|
|
61
|
+
// `codesign -dv` reports on stderr.
|
|
62
|
+
const { stderr } = await execFileAsync("codesign", ["-dv", file]);
|
|
63
|
+
return new RegExp(`^TeamIdentifier=${teamId}$`, "m").test(stderr);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function defaultDeps() {
|
|
70
|
+
return {
|
|
71
|
+
env: process.env,
|
|
72
|
+
platform: process.platform,
|
|
73
|
+
arch: process.arch,
|
|
74
|
+
managedDir: managedFrpcDir(),
|
|
75
|
+
desktopPaths: DESKTOP_FRPC_PATHS,
|
|
76
|
+
signedByTeam,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function isFile(file) {
|
|
80
|
+
try {
|
|
81
|
+
return fs.statSync(file).isFile();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Find a tunnel client this machine may run, without downloading anything.
|
|
89
|
+
* `VANA_FRPC_PATH` wins; then the CLI's own verified install; then, on a
|
|
90
|
+
* Mac, Vana Desktop's copy when it carries Vana's signature, which saves a
|
|
91
|
+
* download.
|
|
92
|
+
*/
|
|
93
|
+
export async function resolveFrpc(overrides = {}) {
|
|
94
|
+
const deps = { ...defaultDeps(), ...overrides };
|
|
95
|
+
const fromEnv = deps.env.VANA_FRPC_PATH;
|
|
96
|
+
if (fromEnv) {
|
|
97
|
+
return isFile(fromEnv)
|
|
98
|
+
? { kind: "ready", path: fromEnv, source: "env" }
|
|
99
|
+
: {
|
|
100
|
+
kind: "unavailable",
|
|
101
|
+
reason: `VANA_FRPC_PATH (${fromEnv}) is not a file.`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const artifact = FRPC_ARTIFACTS[`${deps.platform}-${deps.arch}`];
|
|
105
|
+
const managed = path.join(deps.managedDir, binaryName(deps.platform));
|
|
106
|
+
if (artifact && isFile(managed)) {
|
|
107
|
+
try {
|
|
108
|
+
const marker = fs
|
|
109
|
+
.readFileSync(path.join(deps.managedDir, ".installed"), "utf8")
|
|
110
|
+
.trim();
|
|
111
|
+
if (marker === artifact.sha256) {
|
|
112
|
+
return { kind: "ready", path: managed, source: "managed" };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// No marker: reinstall.
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (deps.platform === "darwin") {
|
|
120
|
+
for (const candidate of deps.desktopPaths) {
|
|
121
|
+
if (isFile(candidate) &&
|
|
122
|
+
(await deps.signedByTeam(candidate, VANA_APPLE_TEAM_ID))) {
|
|
123
|
+
return { kind: "ready", path: candidate, source: "desktop" };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (artifact)
|
|
128
|
+
return { kind: "installable" };
|
|
129
|
+
return {
|
|
130
|
+
kind: "unavailable",
|
|
131
|
+
reason: `No tunnel client is pinned for ${deps.platform}-${deps.arch}. Set VANA_FRPC_PATH.`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Download the pinned frpc for this platform, check its sha256, and install
|
|
136
|
+
* it under ~/.vana/cli/personal-server/frpc/<version>.
|
|
137
|
+
*/
|
|
138
|
+
export async function installFrpc(logPath, overrides = {}) {
|
|
139
|
+
const deps = { ...defaultDeps(), ...overrides };
|
|
140
|
+
const key = `${deps.platform}-${deps.arch}`;
|
|
141
|
+
const artifact = FRPC_ARTIFACTS[key];
|
|
142
|
+
if (!artifact) {
|
|
143
|
+
throw new Error(`No tunnel client is pinned for ${key}.`);
|
|
144
|
+
}
|
|
145
|
+
await fsp.appendFile(logPath, `Downloading ${artifact.url}\n`, "utf8");
|
|
146
|
+
const response = await (overrides.fetchImpl ?? fetch)(artifact.url, {
|
|
147
|
+
headers: { "User-Agent": "vana-cli" },
|
|
148
|
+
});
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
throw new Error(`Could not download the tunnel client: ${response.status}`);
|
|
151
|
+
}
|
|
152
|
+
const archive = Buffer.from(await response.arrayBuffer());
|
|
153
|
+
const actual = crypto.createHash("sha256").update(archive).digest("hex");
|
|
154
|
+
if (actual !== artifact.sha256) {
|
|
155
|
+
throw new Error(`The tunnel client download failed its checksum (expected ${artifact.sha256}, got ${actual}).`);
|
|
156
|
+
}
|
|
157
|
+
const parent = path.dirname(deps.managedDir);
|
|
158
|
+
await fsp.mkdir(parent, { recursive: true });
|
|
159
|
+
const staging = await fsp.mkdtemp(path.join(parent, ".staging-"));
|
|
160
|
+
try {
|
|
161
|
+
const archivePath = path.join(staging, path.basename(artifact.url));
|
|
162
|
+
await fsp.writeFile(archivePath, archive);
|
|
163
|
+
if (artifact.url.endsWith(".zip")) {
|
|
164
|
+
// Windows 10+ ships a bsdtar that reads zip.
|
|
165
|
+
await execFileAsync("tar", ["-xf", archivePath, "-C", staging]);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
await tar.x({ file: archivePath, cwd: staging });
|
|
169
|
+
}
|
|
170
|
+
const installed = path.join(staging, "out");
|
|
171
|
+
await fsp.mkdir(installed);
|
|
172
|
+
const target = path.join(installed, binaryName(deps.platform));
|
|
173
|
+
await fsp.rename(path.join(staging, artifact.entry), target);
|
|
174
|
+
if (deps.platform !== "win32")
|
|
175
|
+
await fsp.chmod(target, 0o755);
|
|
176
|
+
// The hash already pins it; the signature check is what endpoint
|
|
177
|
+
// security will judge, so refuse anything it would flag.
|
|
178
|
+
if (deps.platform === "darwin" &&
|
|
179
|
+
!(await deps.signedByTeam(target, VANA_APPLE_TEAM_ID))) {
|
|
180
|
+
throw new Error("The tunnel client is not signed by Vana.");
|
|
181
|
+
}
|
|
182
|
+
await fsp.writeFile(path.join(installed, ".installed"), `${artifact.sha256}\n`);
|
|
183
|
+
await fsp.rm(deps.managedDir, { recursive: true, force: true });
|
|
184
|
+
await fsp.rename(installed, deps.managedDir);
|
|
185
|
+
return path.join(deps.managedDir, binaryName(deps.platform));
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
await fsp.rm(staging, { recursive: true, force: true });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=frpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frpc.js","sourceRoot":"","sources":["../../../src/personal-server/local/frpc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signature a Personal Server's owner makes over this exact message. The
|
|
3
|
+
* server recovers its owner from it and derives the data encryption key from
|
|
4
|
+
* it, so it is as sensitive as a key.
|
|
5
|
+
*/
|
|
6
|
+
export declare const OWNER_BINDING_MESSAGE = "vana-master-key-v1";
|
|
7
|
+
export declare const OWNER_BINDING_INTENT = "personal_server.owner_binding.v1";
|
|
8
|
+
export interface OwnerBinding {
|
|
9
|
+
signature: string;
|
|
10
|
+
signerAddress: string;
|
|
11
|
+
/**
|
|
12
|
+
* Account's proof that this owner approved this client, needed later to
|
|
13
|
+
* register the server. Present for public native clients such as the CLI.
|
|
14
|
+
*/
|
|
15
|
+
trustToken: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface OwnerBindingDeps {
|
|
18
|
+
fetchImpl?: typeof fetch;
|
|
19
|
+
openBrowser: (url: string) => void;
|
|
20
|
+
/** Called with the confirmation URL, so a person can open it by hand. */
|
|
21
|
+
onConfirmationUrl?: (url: string) => void;
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
}
|
|
24
|
+
/** What Account returns when an exchange is redeemed. */
|
|
25
|
+
export interface RedeemedExchange {
|
|
26
|
+
status?: string;
|
|
27
|
+
signature?: string;
|
|
28
|
+
signerAddress?: string;
|
|
29
|
+
desktopSigningTrustToken?: string;
|
|
30
|
+
typedData?: unknown;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Run one Account signing exchange: the person confirms in the browser, and
|
|
34
|
+
* the result comes back to a one-time loopback listener, bound to this
|
|
35
|
+
* process by state and PKCE. `step` names the request in error messages.
|
|
36
|
+
*/
|
|
37
|
+
export declare function runSigningExchange(input: {
|
|
38
|
+
accountUrl: string;
|
|
39
|
+
accessToken: string;
|
|
40
|
+
intent: string;
|
|
41
|
+
payload?: Record<string, unknown>;
|
|
42
|
+
step: string;
|
|
43
|
+
}, deps: OwnerBindingDeps): Promise<RedeemedExchange>;
|
|
44
|
+
/**
|
|
45
|
+
* Get the owner-binding signature through Account's signing exchange: Account
|
|
46
|
+
* never signs it silently for the CLI, so the person confirms in the browser.
|
|
47
|
+
*/
|
|
48
|
+
export declare function runOwnerBindingExchange(input: {
|
|
49
|
+
accountUrl: string;
|
|
50
|
+
accessToken: string;
|
|
51
|
+
}, deps: OwnerBindingDeps): Promise<OwnerBinding>;
|
|
52
|
+
export declare function describeFailure(step: string, response: Response): Promise<string>;
|
|
53
|
+
//# sourceMappingURL=owner-binding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-binding.d.ts","sourceRoot":"","sources":["../../../src/personal-server/local/owner-binding.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAC1D,eAAO,MAAM,oBAAoB,qCAAqC,CAAC;AAEvE,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmED,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd,EACD,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,gBAAgB,CAAC,CAqF3B;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAClD,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,YAAY,CAAC,CAUvB;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import http from "node:http";
|
|
3
|
+
/**
|
|
4
|
+
* The signature a Personal Server's owner makes over this exact message. The
|
|
5
|
+
* server recovers its owner from it and derives the data encryption key from
|
|
6
|
+
* it, so it is as sensitive as a key.
|
|
7
|
+
*/
|
|
8
|
+
export const OWNER_BINDING_MESSAGE = "vana-master-key-v1";
|
|
9
|
+
export const OWNER_BINDING_INTENT = "personal_server.owner_binding.v1";
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;
|
|
11
|
+
function base64url(bytes) {
|
|
12
|
+
return bytes.toString("base64url");
|
|
13
|
+
}
|
|
14
|
+
const DONE_PAGE = `<!doctype html><meta charset="utf-8"><title>Vana CLI</title>
|
|
15
|
+
<body style="font-family:system-ui;margin:4rem"><h1>Done</h1><p>You can close this tab and return to the terminal.</p></body>`;
|
|
16
|
+
const FAILED_PAGE = `<!doctype html><meta charset="utf-8"><title>Vana CLI</title>
|
|
17
|
+
<body style="font-family:system-ui;margin:4rem"><h1>That did not work</h1><p>Return to the terminal for details.</p></body>`;
|
|
18
|
+
/**
|
|
19
|
+
* Wait for Account to send the browser back to this machine with the
|
|
20
|
+
* exchange's one-time code. Listens on 127.0.0.1 only, accepts exactly one
|
|
21
|
+
* request whose state matches, and closes.
|
|
22
|
+
*/
|
|
23
|
+
async function startLoopbackCallback(expectedState) {
|
|
24
|
+
let settle = null;
|
|
25
|
+
const code = new Promise((resolve, reject) => {
|
|
26
|
+
settle = { resolve, reject };
|
|
27
|
+
});
|
|
28
|
+
const server = http.createServer((request, response) => {
|
|
29
|
+
const url = new URL(request.url ?? "/", "http://127.0.0.1");
|
|
30
|
+
if (url.pathname !== "/signing/callback") {
|
|
31
|
+
response.writeHead(404).end();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const state = url.searchParams.get("state");
|
|
35
|
+
const received = url.searchParams.get("code");
|
|
36
|
+
const error = url.searchParams.get("error");
|
|
37
|
+
if (state !== expectedState) {
|
|
38
|
+
// Not ours; keep waiting for the real callback.
|
|
39
|
+
response.writeHead(400, { "content-type": "text/html" }).end(FAILED_PAGE);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (error || !received) {
|
|
43
|
+
response.writeHead(200, { "content-type": "text/html" }).end(FAILED_PAGE);
|
|
44
|
+
settle?.reject(new Error(error === "access_denied"
|
|
45
|
+
? "The request was declined in the browser."
|
|
46
|
+
: `Account returned ${error ?? "no code"}.`));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
response.writeHead(200, { "content-type": "text/html" }).end(DONE_PAGE);
|
|
50
|
+
settle?.resolve(received);
|
|
51
|
+
});
|
|
52
|
+
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
53
|
+
const { port } = server.address();
|
|
54
|
+
return {
|
|
55
|
+
redirectUri: `http://127.0.0.1:${port}/signing/callback`,
|
|
56
|
+
code,
|
|
57
|
+
close: () => server.close(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Run one Account signing exchange: the person confirms in the browser, and
|
|
62
|
+
* the result comes back to a one-time loopback listener, bound to this
|
|
63
|
+
* process by state and PKCE. `step` names the request in error messages.
|
|
64
|
+
*/
|
|
65
|
+
export async function runSigningExchange(input, deps) {
|
|
66
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
67
|
+
const account = input.accountUrl.replace(/\/+$/, "");
|
|
68
|
+
const state = base64url(crypto.randomBytes(32));
|
|
69
|
+
const codeVerifier = base64url(crypto.randomBytes(32));
|
|
70
|
+
const codeChallenge = base64url(crypto.createHash("sha256").update(codeVerifier).digest());
|
|
71
|
+
const callback = await startLoopbackCallback(state);
|
|
72
|
+
try {
|
|
73
|
+
const created = await fetchImpl(`${account}/api/v1/signing-exchanges`, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: {
|
|
76
|
+
"content-type": "application/json",
|
|
77
|
+
authorization: `Bearer ${input.accessToken}`,
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
intent: input.intent,
|
|
81
|
+
...(input.payload ? { payload: input.payload } : {}),
|
|
82
|
+
redirectUri: callback.redirectUri,
|
|
83
|
+
state,
|
|
84
|
+
codeChallenge,
|
|
85
|
+
codeChallengeMethod: "S256",
|
|
86
|
+
}),
|
|
87
|
+
});
|
|
88
|
+
if (!created.ok) {
|
|
89
|
+
throw new Error(await describeFailure(`start the ${input.step}`, created));
|
|
90
|
+
}
|
|
91
|
+
const { confirmationUrl } = (await created.json());
|
|
92
|
+
if (!confirmationUrl) {
|
|
93
|
+
throw new Error("Account did not return a confirmation page.");
|
|
94
|
+
}
|
|
95
|
+
deps.onConfirmationUrl?.(confirmationUrl);
|
|
96
|
+
deps.openBrowser(confirmationUrl);
|
|
97
|
+
const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
98
|
+
let timer = null;
|
|
99
|
+
const code = await Promise.race([
|
|
100
|
+
callback.code,
|
|
101
|
+
new Promise((_, reject) => {
|
|
102
|
+
timer = setTimeout(() => reject(new Error("Nobody confirmed in the browser in time.")), timeoutMs);
|
|
103
|
+
}),
|
|
104
|
+
]).finally(() => {
|
|
105
|
+
if (timer)
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
});
|
|
108
|
+
const redeemed = await fetchImpl(`${account}/api/v1/signing-exchanges/redeem`, {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: {
|
|
111
|
+
"content-type": "application/json",
|
|
112
|
+
authorization: `Bearer ${input.accessToken}`,
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify({
|
|
115
|
+
code,
|
|
116
|
+
state,
|
|
117
|
+
codeVerifier,
|
|
118
|
+
redirectUri: callback.redirectUri,
|
|
119
|
+
}),
|
|
120
|
+
});
|
|
121
|
+
if (!redeemed.ok) {
|
|
122
|
+
throw new Error(await describeFailure(`finish the ${input.step}`, redeemed));
|
|
123
|
+
}
|
|
124
|
+
const body = (await redeemed.json());
|
|
125
|
+
if (body.status !== "signed" || !body.signature || !body.signerAddress) {
|
|
126
|
+
throw new Error(`Account answered the ${input.step} without a signature.`);
|
|
127
|
+
}
|
|
128
|
+
return body;
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
callback.close();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get the owner-binding signature through Account's signing exchange: Account
|
|
136
|
+
* never signs it silently for the CLI, so the person confirms in the browser.
|
|
137
|
+
*/
|
|
138
|
+
export async function runOwnerBindingExchange(input, deps) {
|
|
139
|
+
const body = await runSigningExchange({ ...input, intent: OWNER_BINDING_INTENT, step: "owner confirmation" }, deps);
|
|
140
|
+
return {
|
|
141
|
+
signature: body.signature,
|
|
142
|
+
signerAddress: body.signerAddress,
|
|
143
|
+
trustToken: body.desktopSigningTrustToken ?? null,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export async function describeFailure(step, response) {
|
|
147
|
+
let code = "";
|
|
148
|
+
try {
|
|
149
|
+
const body = (await response.json());
|
|
150
|
+
code = body.error?.code ?? "";
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Not JSON.
|
|
154
|
+
}
|
|
155
|
+
if (response.status === 401) {
|
|
156
|
+
return `Could not ${step}: your vana login is not accepted. Run \`vana login\` again.`;
|
|
157
|
+
}
|
|
158
|
+
if (code === "client_not_allowed" ||
|
|
159
|
+
code === "intent_not_allowed_for_client") {
|
|
160
|
+
return `Could not ${step}: this Vana Account does not let the CLI run a Personal Server yet (${code}).`;
|
|
161
|
+
}
|
|
162
|
+
return `Could not ${step} (HTTP ${response.status}${code ? `, ${code}` : ""}).`;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=owner-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-binding.js","sourceRoot":"","sources":["../../../src/personal-server/local/owner-binding.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,oBAAoB,CAAC;AAC1D,MAAM,CAAC,MAAM,oBAAoB,GAAG,kCAAkC,CAAC;AAoBvE,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEzC,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,SAAS,GAAG;8HAC4G,CAAC;AAC/H,MAAM,WAAW,GAAG;4HACwG,CAAC;AAE7H;;;;GAIG;AACH,KAAK,UAAU,qBAAqB,CAAC,aAAqB;IAKxD,IAAI,MAAM,GAGC,IAAI,CAAC;IAChB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnD,MAAM,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;QAC5D,IAAI,GAAG,CAAC,QAAQ,KAAK,mBAAmB,EAAE,CAAC;YACzC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;YAC5B,gDAAgD;YAChD,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAC1E,OAAO;QACT,CAAC;QACD,IAAI,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvB,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAC1E,MAAM,EAAE,MAAM,CACZ,IAAI,KAAK,CACP,KAAK,KAAK,eAAe;gBACvB,CAAC,CAAC,0CAA0C;gBAC5C,CAAC,CAAC,oBAAoB,KAAK,IAAI,SAAS,GAAG,CAC9C,CACF,CAAC;YACF,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,EAAiB,CAAC;IACjD,OAAO;QACL,WAAW,EAAE,oBAAoB,IAAI,mBAAmB;QACxD,IAAI;QACJ,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;KAC5B,CAAC;AACJ,CAAC;AAWD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAMC,EACD,IAAsB;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,SAAS,CAC7B,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAC1D,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,GAAG,OAAO,2BAA2B,EAAE;YACrE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,CAAC,WAAW,EAAE;aAC7C;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,KAAK;gBACL,aAAa;gBACb,mBAAmB,EAAE,MAAM;aAC5B,CAAC;SACH,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,MAAM,eAAe,CAAC,aAAa,KAAK,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAC1D,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAEhD,CAAC;QACF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,iBAAiB,EAAE,CAAC,eAAe,CAAC,CAAC;QAC1C,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QAElC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;QACvD,IAAI,KAAK,GAA0B,IAAI,CAAC;QACxC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC9B,QAAQ,CAAC,IAAI;YACb,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBAC/B,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC,EACnE,SAAS,CACV,CAAC;YACJ,CAAC,CAAC;SACH,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACd,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAC9B,GAAG,OAAO,kCAAkC,EAC5C;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,CAAC,WAAW,EAAE;aAC7C;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI;gBACJ,KAAK;gBACL,YAAY;gBACZ,WAAW,EAAE,QAAQ,CAAC,WAAW;aAClC,CAAC;SACH,CACF,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,MAAM,eAAe,CAAC,cAAc,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAC5D,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAqB,CAAC;QACzD,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CACb,wBAAwB,KAAK,CAAC,IAAI,uBAAuB,CAC1D,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAkD,EAClD,IAAsB;IAEtB,MAAM,IAAI,GAAG,MAAM,kBAAkB,CACnC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,oBAAoB,EAAE,EACtE,IAAI,CACL,CAAC;IACF,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,SAAmB;QACnC,aAAa,EAAE,IAAI,CAAC,aAAuB;QAC3C,UAAU,EAAE,IAAI,CAAC,wBAAwB,IAAI,IAAI;KAClD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY,EACZ,QAAkB;IAElB,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkC,CAAC;QACtE,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,OAAO,aAAa,IAAI,8DAA8D,CAAC;IACzF,CAAC;IACD,IACE,IAAI,KAAK,oBAAoB;QAC7B,IAAI,KAAK,+BAA+B,EACxC,CAAC;QACD,OAAO,aAAa,IAAI,uEAAuE,IAAI,IAAI,CAAC;IAC1G,CAAC;IACD,OAAO,aAAa,IAAI,UAAU,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AAClF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { OwnerBinding } from "./owner-binding.js";
|
|
2
|
+
/**
|
|
3
|
+
* Where the owner-binding signature is kept between starts, so starting a
|
|
4
|
+
* server does not ask for a browser confirmation every time. It derives the
|
|
5
|
+
* server's encryption key, so on macOS it lives in the keychain; elsewhere in
|
|
6
|
+
* a 0600 file, as the app key does.
|
|
7
|
+
*/
|
|
8
|
+
export interface OwnerSecretStore {
|
|
9
|
+
get(key: string): OwnerBinding | null;
|
|
10
|
+
set(key: string, binding: OwnerBinding): void;
|
|
11
|
+
delete(key: string): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function ownerSecretKey(accountUrl: string, address: string): string;
|
|
14
|
+
declare function fileStore(file?: string): OwnerSecretStore;
|
|
15
|
+
export declare function defaultOwnerSecretStore(): OwnerSecretStore;
|
|
16
|
+
export { fileStore as fileOwnerSecretStore };
|
|
17
|
+
//# sourceMappingURL=owner-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-secret.d.ts","sourceRoot":"","sources":["../../../src/personal-server/local/owner-secret.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAAC;IACtC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAID,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E;AAoED,iBAAS,SAAS,CAChB,IAAI,SAAsD,GACzD,gBAAgB,CA4BlB;AAiBD,wBAAgB,uBAAuB,IAAI,gBAAgB,CAI1D;AAED,OAAO,EAAE,SAAS,IAAI,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { localServerHome } from "./config.js";
|
|
5
|
+
const KEYCHAIN_SERVICE = "org.vana.cli.personal-server-owner";
|
|
6
|
+
export function ownerSecretKey(accountUrl, address) {
|
|
7
|
+
return `${new URL(accountUrl).host}:${address.toLowerCase()}`;
|
|
8
|
+
}
|
|
9
|
+
function parse(raw) {
|
|
10
|
+
if (!raw)
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
const value = JSON.parse(raw);
|
|
14
|
+
if (typeof value.signature === "string" &&
|
|
15
|
+
typeof value.signerAddress === "string") {
|
|
16
|
+
return {
|
|
17
|
+
signature: value.signature,
|
|
18
|
+
signerAddress: value.signerAddress,
|
|
19
|
+
trustToken: typeof value.trustToken === "string" ? value.trustToken : null,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Unreadable entry: treat as absent.
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
function keychainStore() {
|
|
29
|
+
const run = (args) => execFileSync("security", args, {
|
|
30
|
+
encoding: "utf8",
|
|
31
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
get(key) {
|
|
35
|
+
try {
|
|
36
|
+
return parse(run([
|
|
37
|
+
"find-generic-password",
|
|
38
|
+
"-s",
|
|
39
|
+
KEYCHAIN_SERVICE,
|
|
40
|
+
"-a",
|
|
41
|
+
key,
|
|
42
|
+
"-w",
|
|
43
|
+
]).trim());
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
set(key, binding) {
|
|
50
|
+
run([
|
|
51
|
+
"add-generic-password",
|
|
52
|
+
"-U",
|
|
53
|
+
"-s",
|
|
54
|
+
KEYCHAIN_SERVICE,
|
|
55
|
+
"-a",
|
|
56
|
+
key,
|
|
57
|
+
"-w",
|
|
58
|
+
JSON.stringify(binding),
|
|
59
|
+
]);
|
|
60
|
+
},
|
|
61
|
+
delete(key) {
|
|
62
|
+
try {
|
|
63
|
+
run(["delete-generic-password", "-s", KEYCHAIN_SERVICE, "-a", key]);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Already gone.
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function fileStore(file = path.join(localServerHome(), "owner-bindings.json")) {
|
|
72
|
+
const read = () => {
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const write = (entries) => {
|
|
81
|
+
fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
82
|
+
fs.writeFileSync(file, `${JSON.stringify(entries, null, 2)}\n`, {
|
|
83
|
+
mode: 0o600,
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
get: (key) => parse(read()[key]),
|
|
88
|
+
set(key, binding) {
|
|
89
|
+
write({ ...read(), [key]: JSON.stringify(binding) });
|
|
90
|
+
},
|
|
91
|
+
delete(key) {
|
|
92
|
+
const entries = read();
|
|
93
|
+
delete entries[key];
|
|
94
|
+
write(entries);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Without a default keychain (a HOME with no login keychain, a fresh
|
|
99
|
+
// account), `security add-generic-password` does not fail: it puts up a GUI
|
|
100
|
+
// dialog and waits. Asking for the default keychain never prompts.
|
|
101
|
+
function hasDefaultKeychain() {
|
|
102
|
+
try {
|
|
103
|
+
execFileSync("security", ["default-keychain"], {
|
|
104
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
105
|
+
timeout: 5_000,
|
|
106
|
+
});
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export function defaultOwnerSecretStore() {
|
|
114
|
+
return process.platform === "darwin" && hasDefaultKeychain()
|
|
115
|
+
? keychainStore()
|
|
116
|
+
: fileStore();
|
|
117
|
+
}
|
|
118
|
+
export { fileStore as fileOwnerSecretStore };
|
|
119
|
+
//# sourceMappingURL=owner-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-secret.js","sourceRoot":"","sources":["../../../src/personal-server/local/owner-secret.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type OwnerBindingDeps } from "./owner-binding.js";
|
|
2
|
+
export declare const SERVER_REGISTRATION_INTENT = "personal_server.server_registration.v1";
|
|
3
|
+
/** What the server's prepareRegistration() returns; the CLI only reads the typed data. */
|
|
4
|
+
export interface RegistrationRequest {
|
|
5
|
+
typedData: {
|
|
6
|
+
domain?: {
|
|
7
|
+
chainId?: number | string;
|
|
8
|
+
verifyingContract?: string;
|
|
9
|
+
};
|
|
10
|
+
message?: {
|
|
11
|
+
serverAddress?: string;
|
|
12
|
+
publicKey?: string;
|
|
13
|
+
serverUrl?: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Account needs the browser: the silent path is closed for this owner or client. */
|
|
18
|
+
export declare class RegistrationNeedsBrowserError extends Error {
|
|
19
|
+
readonly code: string;
|
|
20
|
+
constructor(code: string);
|
|
21
|
+
}
|
|
22
|
+
export interface RegistrationSignature {
|
|
23
|
+
signature: string;
|
|
24
|
+
signerAddress: string | null;
|
|
25
|
+
via: "silent" | "browser";
|
|
26
|
+
}
|
|
27
|
+
/** The fields Account signs, from the server's own registration request. */
|
|
28
|
+
export declare function registrationPayload(request: RegistrationRequest): Record<string, unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Have Account sign the server's registration as its owner. Account signs
|
|
31
|
+
* silently when the owner's wallet lives in Account and the trust token from
|
|
32
|
+
* the owner confirmation is valid, as it does for Desktop; otherwise the
|
|
33
|
+
* person confirms in the browser.
|
|
34
|
+
*/
|
|
35
|
+
export declare function signServerRegistration(input: {
|
|
36
|
+
accountUrl: string;
|
|
37
|
+
accessToken: string;
|
|
38
|
+
trustToken: string | null;
|
|
39
|
+
request: RegistrationRequest;
|
|
40
|
+
allowBrowser: boolean;
|
|
41
|
+
}, deps: OwnerBindingDeps): Promise<RegistrationSignature>;
|
|
42
|
+
//# sourceMappingURL=registration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.d.ts","sourceRoot":"","sources":["../../../src/personal-server/local/registration.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,0BAA0B,2CACG,CAAC;AAG3C,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE;QACT,MAAM,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACnE,OAAO,CAAC,EAAE;YACR,aAAa,CAAC,EAAE,MAAM,CAAC;YACvB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,SAAS,CAAC,EAAE,MAAM,CAAC;SACpB,CAAC;KACH,CAAC;CACH;AAED,qFAAqF;AACrF,qBAAa,6BAA8B,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;CAKlC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC3B;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBzB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;CACvB,EACD,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAyDhC"}
|