vana-cli 0.26.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 +7 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server-start.d.ts +10 -1
- package/dist/cli/server-start.d.ts.map +1 -1
- package/dist/cli/server-start.js +153 -5
- package/dist/cli/server-start.js.map +1 -1
- package/dist/personal-server/local/config.d.ts +5 -0
- package/dist/personal-server/local/config.d.ts.map +1 -1
- package/dist/personal-server/local/config.js +4 -2
- package/dist/personal-server/local/config.js.map +1 -1
- 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 +22 -2
- package/dist/personal-server/local/owner-binding.d.ts.map +1 -1
- package/dist/personal-server/local/owner-binding.js +23 -14
- package/dist/personal-server/local/owner-binding.js.map +1 -1
- 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 +138 -20
- package/dist/personal-server/local/server.d.ts +25 -0
- package/dist/personal-server/local/server.d.ts.map +1 -1
- package/dist/personal-server/local/server.js +80 -4
- package/dist/personal-server/local/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -21,13 +21,33 @@ export interface OwnerBindingDeps {
|
|
|
21
21
|
onConfirmationUrl?: (url: string) => void;
|
|
22
22
|
timeoutMs?: number;
|
|
23
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>;
|
|
24
44
|
/**
|
|
25
45
|
* Get the owner-binding signature through Account's signing exchange: Account
|
|
26
|
-
* never signs silently for the CLI, so the person confirms in the browser
|
|
27
|
-
* and the result comes back to a one-time loopback listener.
|
|
46
|
+
* never signs it silently for the CLI, so the person confirms in the browser.
|
|
28
47
|
*/
|
|
29
48
|
export declare function runOwnerBindingExchange(input: {
|
|
30
49
|
accountUrl: string;
|
|
31
50
|
accessToken: string;
|
|
32
51
|
}, deps: OwnerBindingDeps): Promise<OwnerBinding>;
|
|
52
|
+
export declare function describeFailure(step: string, response: Response): Promise<string>;
|
|
33
53
|
//# sourceMappingURL=owner-binding.d.ts.map
|
|
@@ -1 +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;;;;GAIG;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,
|
|
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"}
|
|
@@ -58,11 +58,11 @@ async function startLoopbackCallback(expectedState) {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* and
|
|
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
64
|
*/
|
|
65
|
-
export async function
|
|
65
|
+
export async function runSigningExchange(input, deps) {
|
|
66
66
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
67
67
|
const account = input.accountUrl.replace(/\/+$/, "");
|
|
68
68
|
const state = base64url(crypto.randomBytes(32));
|
|
@@ -77,7 +77,8 @@ export async function runOwnerBindingExchange(input, deps) {
|
|
|
77
77
|
authorization: `Bearer ${input.accessToken}`,
|
|
78
78
|
},
|
|
79
79
|
body: JSON.stringify({
|
|
80
|
-
intent:
|
|
80
|
+
intent: input.intent,
|
|
81
|
+
...(input.payload ? { payload: input.payload } : {}),
|
|
81
82
|
redirectUri: callback.redirectUri,
|
|
82
83
|
state,
|
|
83
84
|
codeChallenge,
|
|
@@ -85,7 +86,7 @@ export async function runOwnerBindingExchange(input, deps) {
|
|
|
85
86
|
}),
|
|
86
87
|
});
|
|
87
88
|
if (!created.ok) {
|
|
88
|
-
throw new Error(await describeFailure(
|
|
89
|
+
throw new Error(await describeFailure(`start the ${input.step}`, created));
|
|
89
90
|
}
|
|
90
91
|
const { confirmationUrl } = (await created.json());
|
|
91
92
|
if (!confirmationUrl) {
|
|
@@ -118,23 +119,31 @@ export async function runOwnerBindingExchange(input, deps) {
|
|
|
118
119
|
}),
|
|
119
120
|
});
|
|
120
121
|
if (!redeemed.ok) {
|
|
121
|
-
throw new Error(await describeFailure(
|
|
122
|
+
throw new Error(await describeFailure(`finish the ${input.step}`, redeemed));
|
|
122
123
|
}
|
|
123
124
|
const body = (await redeemed.json());
|
|
124
125
|
if (body.status !== "signed" || !body.signature || !body.signerAddress) {
|
|
125
|
-
throw new Error(
|
|
126
|
+
throw new Error(`Account answered the ${input.step} without a signature.`);
|
|
126
127
|
}
|
|
127
|
-
return
|
|
128
|
-
signature: body.signature,
|
|
129
|
-
signerAddress: body.signerAddress,
|
|
130
|
-
trustToken: body.desktopSigningTrustToken ?? null,
|
|
131
|
-
};
|
|
128
|
+
return body;
|
|
132
129
|
}
|
|
133
130
|
finally {
|
|
134
131
|
callback.close();
|
|
135
132
|
}
|
|
136
133
|
}
|
|
137
|
-
|
|
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) {
|
|
138
147
|
let code = "";
|
|
139
148
|
try {
|
|
140
149
|
const body = (await response.json());
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"owner-binding.js","sourceRoot":"","sources":["../../../src/personal-server/local/owner-binding.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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describeFailure, runSigningExchange, } from "./owner-binding.js";
|
|
2
|
+
export const SERVER_REGISTRATION_INTENT = "personal_server.server_registration.v1";
|
|
3
|
+
const SIGN_PATH = "/api/v1/intents/personal-server-registration/sign";
|
|
4
|
+
/** Account needs the browser: the silent path is closed for this owner or client. */
|
|
5
|
+
export class RegistrationNeedsBrowserError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
constructor(code) {
|
|
8
|
+
super(`Registering needs you to confirm in a browser (${code}). Run without --no-input.`);
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** The fields Account signs, from the server's own registration request. */
|
|
13
|
+
export function registrationPayload(request) {
|
|
14
|
+
const message = request.typedData?.message;
|
|
15
|
+
const domain = request.typedData?.domain;
|
|
16
|
+
if (!(message?.serverAddress && message.publicKey && message.serverUrl)) {
|
|
17
|
+
throw new Error("The server's registration request is incomplete.");
|
|
18
|
+
}
|
|
19
|
+
const chainId = Number(domain?.chainId);
|
|
20
|
+
return {
|
|
21
|
+
serverAddress: message.serverAddress,
|
|
22
|
+
serverPublicKey: message.publicKey,
|
|
23
|
+
serverUrl: message.serverUrl,
|
|
24
|
+
...(Number.isInteger(chainId) ? { chainId } : {}),
|
|
25
|
+
...(typeof domain?.verifyingContract === "string"
|
|
26
|
+
? { verifyingContract: domain.verifyingContract }
|
|
27
|
+
: {}),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Have Account sign the server's registration as its owner. Account signs
|
|
32
|
+
* silently when the owner's wallet lives in Account and the trust token from
|
|
33
|
+
* the owner confirmation is valid, as it does for Desktop; otherwise the
|
|
34
|
+
* person confirms in the browser.
|
|
35
|
+
*/
|
|
36
|
+
export async function signServerRegistration(input, deps) {
|
|
37
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
38
|
+
const account = input.accountUrl.replace(/\/+$/, "");
|
|
39
|
+
const payload = registrationPayload(input.request);
|
|
40
|
+
const response = await fetchImpl(`${account}${SIGN_PATH}`, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
"content-type": "application/json",
|
|
44
|
+
authorization: `Bearer ${input.accessToken}`,
|
|
45
|
+
...(input.trustToken
|
|
46
|
+
? { "x-vana-desktop-trust-token": input.trustToken }
|
|
47
|
+
: {}),
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify({ intent: SERVER_REGISTRATION_INTENT, ...payload }),
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error(await describeFailure("sign the registration", response));
|
|
53
|
+
}
|
|
54
|
+
const body = (await response.json());
|
|
55
|
+
if (body.status === "signed" && body.signature) {
|
|
56
|
+
return {
|
|
57
|
+
signature: body.signature,
|
|
58
|
+
signerAddress: body.signerAddress ?? null,
|
|
59
|
+
via: "silent",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (body.status !== "confirmation_required") {
|
|
63
|
+
throw new Error(`Account did not sign the registration (${body.code ?? body.status ?? "unknown"}).`);
|
|
64
|
+
}
|
|
65
|
+
if (!input.allowBrowser) {
|
|
66
|
+
throw new RegistrationNeedsBrowserError(body.code ?? "confirmation_required");
|
|
67
|
+
}
|
|
68
|
+
const redeemed = await runSigningExchange({
|
|
69
|
+
accountUrl: input.accountUrl,
|
|
70
|
+
accessToken: input.accessToken,
|
|
71
|
+
intent: SERVER_REGISTRATION_INTENT,
|
|
72
|
+
payload,
|
|
73
|
+
step: "registration",
|
|
74
|
+
}, deps);
|
|
75
|
+
return {
|
|
76
|
+
signature: redeemed.signature,
|
|
77
|
+
signerAddress: redeemed.signerAddress ?? null,
|
|
78
|
+
via: "browser",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=registration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.js","sourceRoot":"","sources":["../../../src/personal-server/local/registration.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
// The Personal Server process `vana server start` runs, modeled on Vana
|
|
2
2
|
// Desktop's sidecar (apps/desktop/personal-server/index.js in unity-surfaces).
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
// process list or environment:
|
|
4
|
+
// The first JSON line on stdin is its configuration, so the owner signature
|
|
5
|
+
// never appears in the process list or environment:
|
|
6
6
|
// { rootPath, port, ownerSignature, ownerAddress, network: { gatewayUrl, chainId,
|
|
7
|
-
// contracts, storageApiUrl } }
|
|
8
|
-
//
|
|
9
|
-
//
|
|
7
|
+
// contracts, storageApiUrl }, tunnel: { binaryPath, serverAddr, serverPort } | null }
|
|
8
|
+
// Later lines are commands from the CLI, which holds the Account session:
|
|
9
|
+
// { type: "prepare-registration" } -> registration-request
|
|
10
|
+
// { type: "submit-registration", signature } -> registration-submitted
|
|
11
|
+
// It writes one JSON object per line on stdout: ready, public, tunnel,
|
|
12
|
+
// registration-request, registration-submitted, command-failed, error,
|
|
13
|
+
// stopped. Logs go to stderr.
|
|
10
14
|
|
|
11
15
|
import { readFile, rename, writeFile } from "node:fs/promises";
|
|
12
16
|
import { join } from "node:path";
|
|
@@ -42,10 +46,12 @@ function applyDerived(persisted, derived) {
|
|
|
42
46
|
return merged;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
// Everything that follows from the network
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
+
// Everything that follows from the network and the tunnel client. Without a
|
|
50
|
+
// tunnel client the server is local only: nothing outside can reach it, so
|
|
51
|
+
// it is never registered and has nothing to sync. With one, the server
|
|
52
|
+
// reserves its public URL but dials the relay only once registered, and sync
|
|
53
|
+
// waits for registration too.
|
|
54
|
+
function derivedConfig(network, tunnel) {
|
|
49
55
|
return {
|
|
50
56
|
devUi: { enabled: true },
|
|
51
57
|
gateway: {
|
|
@@ -61,29 +67,134 @@ function derivedConfig(network) {
|
|
|
61
67
|
backend: "vana",
|
|
62
68
|
config: { vana: { apiUrl: network.storageApiUrl } },
|
|
63
69
|
},
|
|
64
|
-
sync: { enabled:
|
|
65
|
-
tunnel:
|
|
70
|
+
sync: { enabled: Boolean(tunnel) },
|
|
71
|
+
tunnel: tunnel
|
|
72
|
+
? {
|
|
73
|
+
enabled: true,
|
|
74
|
+
serverAddr: tunnel.serverAddr,
|
|
75
|
+
serverPort: tunnel.serverPort,
|
|
76
|
+
binaryPath: tunnel.binaryPath,
|
|
77
|
+
}
|
|
78
|
+
: { enabled: false },
|
|
66
79
|
};
|
|
67
80
|
}
|
|
68
81
|
|
|
82
|
+
const lines = readline
|
|
83
|
+
.createInterface({ input: process.stdin })
|
|
84
|
+
[Symbol.asyncIterator]();
|
|
85
|
+
|
|
69
86
|
async function readInput() {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
return JSON.parse(line);
|
|
75
|
-
}
|
|
87
|
+
for (;;) {
|
|
88
|
+
const { value, done } = await lines.next();
|
|
89
|
+
if (done) throw new Error("No configuration on stdin.");
|
|
90
|
+
if (value.trim()) return JSON.parse(value);
|
|
76
91
|
}
|
|
77
|
-
throw new Error("No configuration on stdin.");
|
|
78
92
|
}
|
|
79
93
|
|
|
80
94
|
let ps = null;
|
|
81
95
|
|
|
96
|
+
// Only a tunnel URL may be registered: without one the server offers its
|
|
97
|
+
// localhost origin, which no app could ever reach.
|
|
98
|
+
function publicState(info) {
|
|
99
|
+
const tunnel = info.details?.tunnel ?? null;
|
|
100
|
+
return {
|
|
101
|
+
registered: Boolean(info.registration?.registered),
|
|
102
|
+
serverAddress: info.server?.address ?? null,
|
|
103
|
+
serverUrl: info.urls?.public ?? null,
|
|
104
|
+
tunnel: tunnel
|
|
105
|
+
? {
|
|
106
|
+
status: tunnel.status ?? null,
|
|
107
|
+
routable: tunnel.routable !== false,
|
|
108
|
+
warning: tunnel.warning ?? null,
|
|
109
|
+
}
|
|
110
|
+
: null,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let watching = false;
|
|
115
|
+
|
|
116
|
+
// The server dials the relay on its own once it sees the registration (it
|
|
117
|
+
// polls the gateway); report when the public URL answers, as Desktop does.
|
|
118
|
+
async function watchTunnel() {
|
|
119
|
+
if (watching) return;
|
|
120
|
+
watching = true;
|
|
121
|
+
const started = Date.now();
|
|
122
|
+
let last = null;
|
|
123
|
+
while (Date.now() - started < 10 * 60_000) {
|
|
124
|
+
try {
|
|
125
|
+
last = publicState(await ps.info());
|
|
126
|
+
if (last.tunnel?.status === "connected" && last.tunnel.routable) {
|
|
127
|
+
send({ type: "tunnel", status: "connected", url: last.serverUrl });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
process.stderr.write(`[entry] tunnel check failed: ${error}\n`);
|
|
132
|
+
}
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, 3_000));
|
|
134
|
+
}
|
|
135
|
+
send({
|
|
136
|
+
type: "tunnel",
|
|
137
|
+
status: last?.tunnel?.status ?? "unknown",
|
|
138
|
+
url: last?.serverUrl ?? null,
|
|
139
|
+
warning: last?.tunnel?.warning ?? "The tunnel did not connect in time.",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Typed data can carry bigints, which JSON.stringify refuses.
|
|
144
|
+
const plain = (value) =>
|
|
145
|
+
JSON.parse(
|
|
146
|
+
JSON.stringify(value, (_key, item) =>
|
|
147
|
+
typeof item === "bigint" ? item.toString() : item,
|
|
148
|
+
),
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
async function handleCommands() {
|
|
152
|
+
for (;;) {
|
|
153
|
+
const { value, done } = await lines.next();
|
|
154
|
+
if (done) return;
|
|
155
|
+
if (!value.trim()) continue;
|
|
156
|
+
let command;
|
|
157
|
+
try {
|
|
158
|
+
command = JSON.parse(value);
|
|
159
|
+
} catch {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
if (command.type === "prepare-registration") {
|
|
164
|
+
const { serverUrl } = publicState(await ps.info());
|
|
165
|
+
if (!serverUrl) throw new Error("The server has no public URL.");
|
|
166
|
+
const request = await ps.prepareRegistration({ serverUrl });
|
|
167
|
+
send({
|
|
168
|
+
type: "registration-request",
|
|
169
|
+
request: { typedData: plain(request.typedData) },
|
|
170
|
+
});
|
|
171
|
+
} else if (command.type === "submit-registration") {
|
|
172
|
+
const result = await ps.submitRegistration({
|
|
173
|
+
signature: command.signature,
|
|
174
|
+
});
|
|
175
|
+
send({
|
|
176
|
+
type: "registration-submitted",
|
|
177
|
+
serverId: result?.serverId ?? null,
|
|
178
|
+
alreadyRegistered: Boolean(result?.alreadyRegistered),
|
|
179
|
+
});
|
|
180
|
+
void watchTunnel();
|
|
181
|
+
}
|
|
182
|
+
} catch (error) {
|
|
183
|
+
send({
|
|
184
|
+
type: "command-failed",
|
|
185
|
+
command: command.type,
|
|
186
|
+
message: error instanceof Error ? error.message : String(error),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
82
192
|
async function main() {
|
|
83
193
|
const input = await readInput();
|
|
84
|
-
const { rootPath, port, ownerSignature, ownerAddress, network } =
|
|
194
|
+
const { rootPath, port, ownerSignature, ownerAddress, network, tunnel } =
|
|
195
|
+
input;
|
|
85
196
|
const configPath = join(rootPath, "server.json");
|
|
86
|
-
const derived = derivedConfig(network);
|
|
197
|
+
const derived = derivedConfig(network, tunnel ?? null);
|
|
87
198
|
|
|
88
199
|
// Persist the derived block the way Desktop does, so a network change can
|
|
89
200
|
// never leave an old gateway or storage host behind in server.json.
|
|
@@ -129,6 +240,13 @@ async function main() {
|
|
|
129
240
|
port,
|
|
130
241
|
url: info.urls?.local ?? `http://localhost:${port}`,
|
|
131
242
|
});
|
|
243
|
+
void handleCommands();
|
|
244
|
+
if (!tunnel) return;
|
|
245
|
+
|
|
246
|
+
// Waits for the gateway registration check and the tunnel URL reservation.
|
|
247
|
+
const state = publicState(await ps.ready({ publicUrl: true }));
|
|
248
|
+
send({ type: "public", ...state });
|
|
249
|
+
if (state.registered) void watchTunnel();
|
|
132
250
|
}
|
|
133
251
|
|
|
134
252
|
async function shutdown(signal) {
|
|
@@ -15,14 +15,25 @@ export declare function choosePort(requested?: number): Promise<number | null>;
|
|
|
15
15
|
* taken over; a live one means a server is already running from that dir.
|
|
16
16
|
*/
|
|
17
17
|
export declare function acquireDataDirLock(dir: string): Promise<() => Promise<void>>;
|
|
18
|
+
/** One JSON line the server process writes on stdout. */
|
|
19
|
+
export interface ServerMessage {
|
|
20
|
+
type: string;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
18
23
|
export interface LocalServerHandle {
|
|
19
24
|
url: string;
|
|
20
25
|
port: number;
|
|
21
26
|
accessToken: string;
|
|
22
27
|
/** Resolves when the server process exits, for whatever reason. */
|
|
23
28
|
exited: Promise<number | null>;
|
|
29
|
+
/** Send one command line to the server process. */
|
|
30
|
+
send(command: Record<string, unknown>): void;
|
|
31
|
+
/** Every message from now on; returns an unsubscribe. */
|
|
32
|
+
onMessage(listener: (message: ServerMessage) => void): () => void;
|
|
24
33
|
stop(): Promise<void>;
|
|
25
34
|
}
|
|
35
|
+
/** The next message of one of `types`, or a timeout error. */
|
|
36
|
+
export declare function nextMessage(handle: Pick<LocalServerHandle, "onMessage" | "exited">, types: string[], timeoutMs: number): Promise<ServerMessage>;
|
|
26
37
|
/**
|
|
27
38
|
* Start the pinned Personal Server as a foreground child process on the
|
|
28
39
|
* managed Node, local only, and wait until it answers.
|
|
@@ -34,6 +45,20 @@ export declare function startLocalServer(input: {
|
|
|
34
45
|
binding: OwnerBinding;
|
|
35
46
|
port: number;
|
|
36
47
|
logPath: string;
|
|
48
|
+
/** A tunnel client to run; absent = local only. */
|
|
49
|
+
frpcPath?: string | null;
|
|
37
50
|
readyTimeoutMs?: number;
|
|
38
51
|
}): Promise<LocalServerHandle>;
|
|
52
|
+
/** What the CLI remembers about a server it registered. */
|
|
53
|
+
export interface PublicMarker {
|
|
54
|
+
serverAddress: string;
|
|
55
|
+
serverUrl: string;
|
|
56
|
+
registeredAt: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A registered server stays public: registrations cannot be removed, so once
|
|
60
|
+
* apps may look for it, every later start brings its tunnel back.
|
|
61
|
+
*/
|
|
62
|
+
export declare function readPublicMarker(network: VanaNetworkName): PublicMarker | null;
|
|
63
|
+
export declare function writePublicMarker(network: VanaNetworkName, marker: PublicMarker): Promise<void>;
|
|
39
64
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/personal-server/local/server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,mEAAmE;AACnE,wBAAsB,kBAAkB,CACtC,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,aAAa,EAAE,CAAC,CA+B1B;AAWD,qFAAqF;AACrF,wBAAsB,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ3E;AAWD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CA8B9B;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE;IAC5C,OAAO,EAAE,eAAe,CAAC;IACzB,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/personal-server/local/server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,mEAAmE;AACnE,wBAAsB,kBAAkB,CACtC,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,aAAa,EAAE,CAAC,CA+B1B;AAWD,qFAAqF;AACrF,wBAAsB,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ3E;AAWD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CA8B9B;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/B,mDAAmD;IACnD,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7C,yDAAyD;IACzD,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CACzB,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,QAAQ,CAAC,EACvD,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CAoBxB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE;IAC5C,OAAO,EAAE,eAAe,CAAC;IACzB,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqJ7B;AAED,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,GACvB,YAAY,GAAG,IAAI,CAgBrB;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAMf"}
|