@tinycloud/cli 1.2.0-beta.1 → 1.2.0-beta.11
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 +61 -5
- package/dist/courier-entry.d.ts +3 -0
- package/dist/courier-entry.js +2132 -0
- package/dist/courier-entry.js.map +1 -0
- package/dist/index.js +2502 -1959
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +5059 -3050
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +8 -6
- package/skills/courier/SKILL.md +165 -0
- package/skills/courier/release.json +16 -0
- package/skills/tc-cli/AUTH.md +19 -0
- package/skills/tc-cli/INSTALL.md +8 -6
- package/skills/tc-cli/REFERENCE.md +97 -6
- package/skills/tc-cli/SKILL.md +1 -1
package/dist/index.js
CHANGED
|
@@ -8,6 +8,114 @@ var __export = (target, all) => {
|
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// src/lib/replication-registry.ts
|
|
12
|
+
function stopForSignal(signal) {
|
|
13
|
+
void closeReplication().finally(() => {
|
|
14
|
+
process.exit(signal === "SIGINT" ? 130 : 143);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function installSignalHandlers() {
|
|
18
|
+
if (state.installedSignalHandlers) return;
|
|
19
|
+
state.installedSignalHandlers = true;
|
|
20
|
+
state.sigintHandler = () => stopForSignal("SIGINT");
|
|
21
|
+
state.sigtermHandler = () => stopForSignal("SIGTERM");
|
|
22
|
+
process.once("SIGINT", state.sigintHandler);
|
|
23
|
+
process.once("SIGTERM", state.sigtermHandler);
|
|
24
|
+
}
|
|
25
|
+
function removeSignalHandlers() {
|
|
26
|
+
if (!state.installedSignalHandlers) return;
|
|
27
|
+
state.installedSignalHandlers = false;
|
|
28
|
+
if (state.sigintHandler) process.removeListener("SIGINT", state.sigintHandler);
|
|
29
|
+
if (state.sigtermHandler) process.removeListener("SIGTERM", state.sigtermHandler);
|
|
30
|
+
state.sigintHandler = void 0;
|
|
31
|
+
state.sigtermHandler = void 0;
|
|
32
|
+
}
|
|
33
|
+
function registerReplication(profile, control) {
|
|
34
|
+
state.controls.set(profile, control);
|
|
35
|
+
state.allControls.add(control);
|
|
36
|
+
state.generation += 1;
|
|
37
|
+
installSignalHandlers();
|
|
38
|
+
}
|
|
39
|
+
function replicationForProfile(profile) {
|
|
40
|
+
return state.controls.get(profile);
|
|
41
|
+
}
|
|
42
|
+
function registeredReplications() {
|
|
43
|
+
return state.controls;
|
|
44
|
+
}
|
|
45
|
+
function closeReplication(schedule = scheduleTimeout) {
|
|
46
|
+
if (state.closing) return state.closing;
|
|
47
|
+
removeSignalHandlers();
|
|
48
|
+
let resolveClosing;
|
|
49
|
+
let rejectClosing;
|
|
50
|
+
const closing = new Promise((resolve2, reject) => {
|
|
51
|
+
resolveClosing = resolve2;
|
|
52
|
+
rejectClosing = reject;
|
|
53
|
+
});
|
|
54
|
+
state.closing = closing;
|
|
55
|
+
void (async () => {
|
|
56
|
+
let timeout;
|
|
57
|
+
const deadline = new Promise((resolve2) => {
|
|
58
|
+
timeout = schedule(() => resolve2(true), CLOSE_TIMEOUT_MS);
|
|
59
|
+
});
|
|
60
|
+
let timedOut = false;
|
|
61
|
+
const abandonQueuedControls = () => {
|
|
62
|
+
for (const control of state.allControls) {
|
|
63
|
+
void Promise.resolve().then(() => control.close()).catch(() => void 0);
|
|
64
|
+
}
|
|
65
|
+
state.controls.clear();
|
|
66
|
+
state.allControls.clear();
|
|
67
|
+
};
|
|
68
|
+
try {
|
|
69
|
+
while (!timedOut) {
|
|
70
|
+
while (state.allControls.size > 0) {
|
|
71
|
+
const generation = state.generation;
|
|
72
|
+
const pending = [...state.allControls];
|
|
73
|
+
state.controls.clear();
|
|
74
|
+
state.allControls.clear();
|
|
75
|
+
const drained = Promise.allSettled(pending.map((control) => Promise.resolve().then(() => control.close()))).then(() => false);
|
|
76
|
+
timedOut ||= await Promise.race([drained, deadline]);
|
|
77
|
+
if (timedOut) {
|
|
78
|
+
abandonQueuedControls();
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
if (state.generation === generation && state.allControls.size === 0) break;
|
|
82
|
+
}
|
|
83
|
+
if (timedOut) break;
|
|
84
|
+
const turn = new Promise((resolve2) => setImmediate(() => resolve2(false)));
|
|
85
|
+
timedOut ||= await Promise.race([turn, deadline]);
|
|
86
|
+
if (timedOut) abandonQueuedControls();
|
|
87
|
+
else if (state.allControls.size === 0) break;
|
|
88
|
+
}
|
|
89
|
+
state.closing = void 0;
|
|
90
|
+
if (state.allControls.size === 0) removeSignalHandlers();
|
|
91
|
+
resolveClosing(timedOut);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
state.closing = void 0;
|
|
94
|
+
if (state.allControls.size === 0) removeSignalHandlers();
|
|
95
|
+
rejectClosing(error);
|
|
96
|
+
} finally {
|
|
97
|
+
clearTimeout(timeout);
|
|
98
|
+
}
|
|
99
|
+
})();
|
|
100
|
+
return closing;
|
|
101
|
+
}
|
|
102
|
+
var registryKey, globalState, state, CLOSE_TIMEOUT_MS, scheduleTimeout;
|
|
103
|
+
var init_replication_registry = __esm({
|
|
104
|
+
"src/lib/replication-registry.ts"() {
|
|
105
|
+
"use strict";
|
|
106
|
+
registryKey = /* @__PURE__ */ Symbol.for("@tinycloud/cli/replication-registry");
|
|
107
|
+
globalState = globalThis;
|
|
108
|
+
state = globalState[registryKey] ??= {
|
|
109
|
+
controls: /* @__PURE__ */ new Map(),
|
|
110
|
+
allControls: /* @__PURE__ */ new Set(),
|
|
111
|
+
installedSignalHandlers: false,
|
|
112
|
+
generation: 0
|
|
113
|
+
};
|
|
114
|
+
CLOSE_TIMEOUT_MS = 3e3;
|
|
115
|
+
scheduleTimeout = (callback, delayMs) => setTimeout(callback, delayMs);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
11
119
|
// src/config/constants.ts
|
|
12
120
|
import {
|
|
13
121
|
profilesPath,
|
|
@@ -33,8 +141,12 @@ var init_constants = __esm({
|
|
|
33
141
|
PERMISSION_DENIED: 5,
|
|
34
142
|
NETWORK_ERROR: 6,
|
|
35
143
|
NODE_ERROR: 7,
|
|
144
|
+
/** `tc secrets wait` only: the deadline passed while a secret was still missing. */
|
|
145
|
+
PENDING: 8,
|
|
36
146
|
/** A write was refused because the owner's TinyCloud storage is full. */
|
|
37
|
-
STORAGE_FULL: 10
|
|
147
|
+
STORAGE_FULL: 10,
|
|
148
|
+
/** Interrupted by SIGINT/SIGTERM (`CANCELLED`). */
|
|
149
|
+
CANCELLED: 130
|
|
38
150
|
};
|
|
39
151
|
}
|
|
40
152
|
});
|
|
@@ -119,7 +231,7 @@ function warningLine(warnings) {
|
|
|
119
231
|
return `${subject} not used (${which}). Approve access again when a command needs it; remove the old grant with tc auth grants remove <cid>.`;
|
|
120
232
|
}
|
|
121
233
|
function outputError(code3, message, hint, details = {}) {
|
|
122
|
-
const { meta, warnings = [] } = details;
|
|
234
|
+
const { meta, warnings = [], setup, recovery, progress } = details;
|
|
123
235
|
if (!shouldOutputJson()) {
|
|
124
236
|
process.stderr.write(
|
|
125
237
|
`${theme.error("\u2717")} ${theme.label(code3)}: ${message}
|
|
@@ -138,6 +250,9 @@ function outputError(code3, message, hint, details = {}) {
|
|
|
138
250
|
error: { code: code3, message }
|
|
139
251
|
};
|
|
140
252
|
if (hint) payload.error.hint = hint;
|
|
253
|
+
if (recovery) payload.error.recovery = recovery;
|
|
254
|
+
if (setup) payload.error.setup = setup;
|
|
255
|
+
if (progress) payload.error.progress = progress;
|
|
141
256
|
if (meta) payload.error.meta = meta;
|
|
142
257
|
if (warnings.length > 0) payload.error.warnings = warnings;
|
|
143
258
|
process.stderr.write(JSON.stringify(payload, null, 2) + "\n");
|
|
@@ -267,6 +382,13 @@ var init_storage = __esm({
|
|
|
267
382
|
import { readFileSync, readdirSync } from "fs";
|
|
268
383
|
import { join } from "path";
|
|
269
384
|
import { ProfileDeletedError, ProfileLockTimeoutError } from "@tinycloud/operations/state";
|
|
385
|
+
import { isSafeRecovery } from "@tinycloud/operations/recovery";
|
|
386
|
+
import {
|
|
387
|
+
buildSecretRequestUrl,
|
|
388
|
+
isSafeRequestAccessRecovery,
|
|
389
|
+
isValidSecretName,
|
|
390
|
+
SECRET_REQUEST_MAX_NAMES
|
|
391
|
+
} from "@tinycloud/operations/secret-request";
|
|
270
392
|
import { authorizationVerdictOf, parseCapabilityResource, SERVICE_LONG_TO_SHORT, validatedCapabilityOf } from "@tinycloud/sdk-core";
|
|
271
393
|
function setActiveProfileName(name) {
|
|
272
394
|
activeProfileName = name;
|
|
@@ -342,11 +464,64 @@ function handleError(error) {
|
|
|
342
464
|
meta.resource = capability.resource;
|
|
343
465
|
meta.requiredAction = capability.requiredAction;
|
|
344
466
|
}
|
|
467
|
+
const deniedNames = cliError.metadata?.deniedNames;
|
|
468
|
+
const recovery = safeCliRecovery(cliError.metadata?.recovery, {
|
|
469
|
+
deniedNames: Array.isArray(deniedNames) && deniedNames.every((name) => typeof name === "string") ? deniedNames : []
|
|
470
|
+
});
|
|
471
|
+
const setup = cliError.code === "NOT_FOUND" || cliError.code === "PERMISSION_DENIED" ? safeCliSetup(cliError.metadata?.setup) : void 0;
|
|
472
|
+
const progress = cliError.code === "NETWORK_ERROR" || cliError.code === "CANCELLED" ? safeCliProgress(cliError.metadata?.progress) : void 0;
|
|
345
473
|
outputError(cliError.code, cliError.message, hint, {
|
|
474
|
+
...recovery ? { recovery } : {},
|
|
475
|
+
...setup ? { setup } : {},
|
|
476
|
+
...progress ? { progress } : {},
|
|
346
477
|
...Object.keys(meta).length ? { meta } : {},
|
|
347
478
|
warnings: mergeWarnings(drainWarnings(), operationWarnings(cliError.metadata?.warnings))
|
|
348
479
|
});
|
|
349
|
-
process.exit(cliError.exitCode);
|
|
480
|
+
if (registeredReplications().size === 0) return process.exit(cliError.exitCode);
|
|
481
|
+
return closeReplication().then(() => process.exit(cliError.exitCode));
|
|
482
|
+
}
|
|
483
|
+
function safeCliRecovery(value, context) {
|
|
484
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || !("action" in value)) return void 0;
|
|
485
|
+
const action = value.action;
|
|
486
|
+
switch (action) {
|
|
487
|
+
case "sign_in":
|
|
488
|
+
case "complete_migration":
|
|
489
|
+
return isSafeRecovery(value, action) ? { ...value } : void 0;
|
|
490
|
+
case "request_access":
|
|
491
|
+
return isSafeRequestAccessRecovery(value, context.deniedNames) ? { ...value, names: [...value.names] } : void 0;
|
|
492
|
+
default:
|
|
493
|
+
return void 0;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function safeCliSetup(value) {
|
|
497
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
498
|
+
const setup = { ...value };
|
|
499
|
+
if (!Object.keys(setup).every((key) => SETUP_KEYS[key] === true)) return void 0;
|
|
500
|
+
const { url, names, scope, owner, action } = setup;
|
|
501
|
+
if (action !== "add_secret" || typeof url !== "string" || typeof owner !== "string") return void 0;
|
|
502
|
+
if (!Array.isArray(names) || !names.every((name) => typeof name === "string")) return void 0;
|
|
503
|
+
if (scope !== void 0 && typeof scope !== "string") return void 0;
|
|
504
|
+
try {
|
|
505
|
+
const link2 = buildSecretRequestUrl({ owner, names, ...scope !== void 0 ? { scope } : {} });
|
|
506
|
+
if (link2.url !== url || link2.owner !== owner || link2.names.length !== names.length) return void 0;
|
|
507
|
+
} catch {
|
|
508
|
+
return void 0;
|
|
509
|
+
}
|
|
510
|
+
return { url, names: [...names], ...scope !== void 0 ? { scope } : {}, owner, action };
|
|
511
|
+
}
|
|
512
|
+
function safeNameList(value) {
|
|
513
|
+
if (!Array.isArray(value) || value.length > SECRET_REQUEST_MAX_NAMES) return void 0;
|
|
514
|
+
if (!value.every((name) => typeof name === "string" && isValidSecretName(name))) return void 0;
|
|
515
|
+
if (new Set(value).size !== value.length) return void 0;
|
|
516
|
+
return [...value];
|
|
517
|
+
}
|
|
518
|
+
function safeCliProgress(value) {
|
|
519
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
520
|
+
if (!("present" in value) || !("pending" in value) || Object.keys(value).length !== 2) return void 0;
|
|
521
|
+
const present = safeNameList(value.present);
|
|
522
|
+
const pending = safeNameList(value.pending);
|
|
523
|
+
if (!present || !pending || present.some((name) => pending.includes(name))) return void 0;
|
|
524
|
+
return { present, pending };
|
|
350
525
|
}
|
|
351
526
|
function buildAuthHint(error) {
|
|
352
527
|
const capability = validatedCapabilityOf({ meta: error.metadata });
|
|
@@ -409,10 +584,11 @@ function buildNetworkHint() {
|
|
|
409
584
|
lines.push(`Or override per-command with --host or TC_HOST.`);
|
|
410
585
|
return lines.join("\n");
|
|
411
586
|
}
|
|
412
|
-
var activeProfileName, CLIError;
|
|
587
|
+
var activeProfileName, CLIError, SETUP_KEYS;
|
|
413
588
|
var init_errors = __esm({
|
|
414
589
|
"src/output/errors.ts"() {
|
|
415
590
|
"use strict";
|
|
591
|
+
init_replication_registry();
|
|
416
592
|
init_constants();
|
|
417
593
|
init_formatter();
|
|
418
594
|
init_storage();
|
|
@@ -428,6 +604,7 @@ var init_errors = __esm({
|
|
|
428
604
|
}
|
|
429
605
|
status;
|
|
430
606
|
};
|
|
607
|
+
SETUP_KEYS = { url: true, names: true, scope: true, owner: true, action: true };
|
|
431
608
|
}
|
|
432
609
|
});
|
|
433
610
|
|
|
@@ -900,11 +1077,11 @@ var init_md = __esm({
|
|
|
900
1077
|
if (len % 4)
|
|
901
1078
|
throw new Error("_sha2: outputLen should be aligned to 32bit");
|
|
902
1079
|
const outLen = len / 4;
|
|
903
|
-
const
|
|
904
|
-
if (outLen >
|
|
1080
|
+
const state2 = this.get();
|
|
1081
|
+
if (outLen > state2.length)
|
|
905
1082
|
throw new Error("_sha2: outputLen bigger than state");
|
|
906
1083
|
for (let i = 0; i < outLen; i++)
|
|
907
|
-
oview.setUint32(4 * i,
|
|
1084
|
+
oview.setUint32(4 * i, state2[i], isLE2);
|
|
908
1085
|
}
|
|
909
1086
|
digest() {
|
|
910
1087
|
const { buffer, outputLen } = this;
|
|
@@ -5464,6 +5641,8 @@ import {
|
|
|
5464
5641
|
buildPermissionRequestArtifact,
|
|
5465
5642
|
isPermissionRequestArtifact
|
|
5466
5643
|
} from "@tinycloud/operations/artifacts";
|
|
5644
|
+
import { isLocalOwnerProfile } from "@tinycloud/operations/profile";
|
|
5645
|
+
import { resolveSecretsOwner } from "@tinycloud/operations/secret-request";
|
|
5467
5646
|
import {
|
|
5468
5647
|
additionalDelegationsPath as sharedAdditionalDelegationsPath,
|
|
5469
5648
|
authRequestsPath as sharedAuthRequestsPath,
|
|
@@ -5501,14 +5680,17 @@ var init_permissions = __esm({
|
|
|
5501
5680
|
});
|
|
5502
5681
|
|
|
5503
5682
|
// src/auth/session-expired.ts
|
|
5683
|
+
import { signInRecovery } from "@tinycloud/operations/recovery";
|
|
5504
5684
|
function signInAgainHint(profileName, posture) {
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5685
|
+
const delegate = posture === "delegate-session";
|
|
5686
|
+
const { command } = signInRecovery(
|
|
5687
|
+
profileName,
|
|
5688
|
+
delegate ? "delegate-session" : posture === "local-owner-key" ? "local-owner-key" : "owner-openkey"
|
|
5689
|
+
);
|
|
5690
|
+
if (command === void 0) {
|
|
5691
|
+
return delegate ? `Have the owner approve a new scoped login for profile ${JSON.stringify(profileName)} with tc auth login --method openkey --paste --manifest <manifest.json>.` : `Sign in again to profile ${JSON.stringify(profileName)} with tc auth login.`;
|
|
5510
5692
|
}
|
|
5511
|
-
return `
|
|
5693
|
+
return delegate ? `Have the owner approve a new scoped login: ${command}. Pass the owner's code on stdin, newline-terminated.` : `Sign in again with: ${command}`;
|
|
5512
5694
|
}
|
|
5513
5695
|
function sessionExpiredError(profileName, posture) {
|
|
5514
5696
|
return new CLIError(
|
|
@@ -5543,1019 +5725,643 @@ var init_delegation_expiry = __esm({
|
|
|
5543
5725
|
}
|
|
5544
5726
|
});
|
|
5545
5727
|
|
|
5546
|
-
// src/lib/
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
selectSignerJwk: () => selectSignerJwk,
|
|
5555
|
-
storedSessionVerifiesLocally: () => storedSessionVerifiesLocally
|
|
5556
|
-
});
|
|
5557
|
-
import { TinyCloudNode, signedCompactUcanExpiry } from "@tinycloud/node-sdk";
|
|
5558
|
-
function jwkHasPrivateParameter(jwk) {
|
|
5559
|
-
if (!jwk || typeof jwk !== "object") return false;
|
|
5560
|
-
const d = jwk.d;
|
|
5561
|
-
return typeof d === "string" && d.length > 0;
|
|
5562
|
-
}
|
|
5563
|
-
function selectSignerJwk(sessionJwk, key) {
|
|
5564
|
-
if (jwkHasPrivateParameter(sessionJwk)) {
|
|
5565
|
-
return sessionJwk;
|
|
5566
|
-
}
|
|
5567
|
-
return key ?? void 0;
|
|
5568
|
-
}
|
|
5569
|
-
function signerJwkForProfile(profileName, sessionJwk, key) {
|
|
5570
|
-
const jwk = selectSignerJwk(sessionJwk, key);
|
|
5571
|
-
if (jwkHasPrivateParameter(jwk)) {
|
|
5572
|
-
return jwk;
|
|
5573
|
-
}
|
|
5574
|
-
throw new CLIError(
|
|
5575
|
-
"AUTH_REQUIRED",
|
|
5576
|
-
`Profile "${profileName}" cannot restore its session because its private key material is missing.`,
|
|
5577
|
-
ExitCode.AUTH_REQUIRED,
|
|
5578
|
-
{
|
|
5579
|
-
hint: `Sign in again with: tc --profile ${profileName} auth login --method openkey`
|
|
5580
|
-
}
|
|
5581
|
-
);
|
|
5582
|
-
}
|
|
5583
|
-
function signedLifetimePassed(delegation) {
|
|
5584
|
-
const authorization = delegation.delegationHeader?.Authorization;
|
|
5585
|
-
const expiry = typeof authorization === "string" ? signedCompactUcanExpiry(authorization) : void 0;
|
|
5586
|
-
return expiry !== void 0 && expiry.getTime() <= Date.now();
|
|
5587
|
-
}
|
|
5588
|
-
async function restoreProfileSession(node, profileName, profile, sessionData) {
|
|
5728
|
+
// src/lib/replication-log.ts
|
|
5729
|
+
import { appendFileSync, chmodSync, mkdirSync, renameSync, statSync, writeFileSync } from "fs";
|
|
5730
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
5731
|
+
function appendReplicationEvent(root, event) {
|
|
5732
|
+
mkdirSync(root, { recursive: true, mode: DIR_MODE });
|
|
5733
|
+
chmodSync(root, DIR_MODE);
|
|
5734
|
+
const path = join4(root, "events.jsonl");
|
|
5735
|
+
let size = 0;
|
|
5589
5736
|
try {
|
|
5590
|
-
|
|
5737
|
+
size = statSync(path).size;
|
|
5591
5738
|
} catch (error) {
|
|
5592
|
-
if (
|
|
5593
|
-
throw sessionExpiredError(profileName, profile === null ? void 0 : resolveProfilePosture(profile));
|
|
5594
|
-
}
|
|
5595
|
-
throw error;
|
|
5739
|
+
if (error.code !== "ENOENT") throw error;
|
|
5596
5740
|
}
|
|
5597
|
-
}
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5741
|
+
const line = `${JSON.stringify(event)}
|
|
5742
|
+
`;
|
|
5743
|
+
if (size + Buffer.byteLength(line) > MAX_LOG_BYTES) {
|
|
5744
|
+
const rotated = join4(root, "events.jsonl.1");
|
|
5745
|
+
try {
|
|
5746
|
+
renameSync(path, rotated);
|
|
5747
|
+
} catch (error) {
|
|
5748
|
+
if (error.code !== "ENOENT") throw error;
|
|
5749
|
+
}
|
|
5750
|
+
writeFileSync(path, line, { mode: LOG_MODE });
|
|
5751
|
+
} else {
|
|
5752
|
+
appendFileSync(path, line, { mode: LOG_MODE });
|
|
5753
|
+
}
|
|
5754
|
+
chmodSync(path, LOG_MODE);
|
|
5755
|
+
}
|
|
5756
|
+
function replicationLogPath(profileRoot) {
|
|
5757
|
+
return join4(profileRoot, "replication", "events.jsonl");
|
|
5758
|
+
}
|
|
5759
|
+
function createReplicationEventSink(profileRoot, options) {
|
|
5760
|
+
const pinnedNotices = /* @__PURE__ */ new Set();
|
|
5761
|
+
const missingGrantWarnings = /* @__PURE__ */ new Set();
|
|
5762
|
+
return (event) => {
|
|
5763
|
+
appendProfileReplicationEvent(profileRoot, event);
|
|
5764
|
+
if (event.type === "replication.state" && event.state === "grant_missing") {
|
|
5765
|
+
const prefix = event.replica ?? event.space ?? "configured prefix";
|
|
5766
|
+
const key = `${event.space ?? ""}\0${event.replica ?? ""}`;
|
|
5767
|
+
if (!missingGrantWarnings.has(key)) {
|
|
5768
|
+
missingGrantWarnings.add(key);
|
|
5769
|
+
process.stderr.write(`[replication] Warning: no usable kv/get+sync grant for ${prefix}; reads use the network (${event.code ?? "grant_missing"}).
|
|
5770
|
+
`);
|
|
5771
|
+
}
|
|
5772
|
+
}
|
|
5773
|
+
if (options.debug) {
|
|
5774
|
+
if (event.type === "replication.read") {
|
|
5775
|
+
const detail = event.source === "replica" ? "replica hit" : `${event.source} ${event.reason}`;
|
|
5776
|
+
const syncStatus = event.syncedBeforeRead === void 0 ? "" : ` syncedBeforeRead:${event.syncedBeforeRead}`;
|
|
5777
|
+
const syncError = event.syncError === void 0 ? "" : ` syncError:${event.syncError}`;
|
|
5778
|
+
process.stderr.write(`[replication] ${event.op} ${event.key} \u2190 ${detail} ${event.latencyMs}ms${syncStatus}${syncError}${event.stalenessMs === null ? "" : ` (synced ${Math.round(event.stalenessMs / 1e3)}s ago)`}
|
|
5779
|
+
`);
|
|
5780
|
+
} else if (event.type === "replication.write") {
|
|
5781
|
+
process.stderr.write(`[replication] ${event.op} ${event.keys.join(",")} ${event.outcome}${event.code ? ` ${event.code}` : ""}
|
|
5782
|
+
`);
|
|
5783
|
+
} else if (event.type === "replication.sync") {
|
|
5784
|
+
const pending = event.pendingCleared === void 0 ? "" : ` pendingCleared:${event.pendingCleared}`;
|
|
5785
|
+
process.stderr.write(`[replication] sync ${event.replica} ${event.outcome}${event.code ? ` ${event.code}` : ""}${pending}
|
|
5786
|
+
`);
|
|
5787
|
+
}
|
|
5788
|
+
}
|
|
5789
|
+
if (event.type === "replication.read" && (event.pendingState === "in_flight" || event.pendingState === "ambiguous") && !options.quiet && !pinnedNotices.has(event.key)) {
|
|
5790
|
+
pinnedNotices.add(event.key);
|
|
5791
|
+
process.stderr.write(`[replication] ${event.key} reads from the network: an earlier write's outcome is unknown (${event.pendingState}${event.code ? `, ${event.code}` : ""}). Review: tc replica report
|
|
5792
|
+
`);
|
|
5793
|
+
}
|
|
5609
5794
|
};
|
|
5610
5795
|
}
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
const session = await ProfileManager.getSession(ctx.profile);
|
|
5614
|
-
if (!session) return { unavailable: "session_missing" };
|
|
5615
|
-
if (typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || session.delegationHeader === null || typeof session.delegationHeader !== "object" || !("Authorization" in session.delegationHeader) || typeof session.delegationHeader.Authorization !== "string") {
|
|
5616
|
-
return { unavailable: "session_invalid" };
|
|
5617
|
-
}
|
|
5618
|
-
if (typeof session.expiresAt === "string" && Date.parse(session.expiresAt) <= Date.now()) {
|
|
5619
|
-
return { unavailable: "session_expired" };
|
|
5620
|
-
}
|
|
5621
|
-
const key = await ProfileManager.getKey(ctx.profile);
|
|
5622
|
-
try {
|
|
5623
|
-
const node = new TinyCloudNode({
|
|
5624
|
-
host: ctx.host,
|
|
5625
|
-
...profile.authMethod === "local" && profile.privateKey ? { privateKey: profile.privateKey } : {}
|
|
5626
|
-
});
|
|
5627
|
-
await restoreProfileSession(node, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
|
|
5628
|
-
return { node };
|
|
5629
|
-
} catch (error) {
|
|
5630
|
-
if (error instanceof CLIError && error.metadata?.reason === "session_expired") {
|
|
5631
|
-
return { unavailable: "session_expired" };
|
|
5632
|
-
}
|
|
5633
|
-
return { unavailable: "session_invalid" };
|
|
5634
|
-
}
|
|
5796
|
+
function appendProfileReplicationEvent(profileRoot, event) {
|
|
5797
|
+
appendReplicationEvent(dirname2(replicationLogPath(profileRoot)), event);
|
|
5635
5798
|
}
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
const key = await ProfileManager.getKey(profileName);
|
|
5644
|
-
const node = new TinyCloudNode({
|
|
5645
|
-
host: profile.host ?? DEFAULT_HOST,
|
|
5646
|
-
...local ? { privateKey: profile.privateKey } : {}
|
|
5647
|
-
});
|
|
5648
|
-
await restoreProfileSession(node, profileName, profile, persistedSessionData(profileName, profile, session, key));
|
|
5649
|
-
return true;
|
|
5650
|
-
} catch {
|
|
5651
|
-
return false;
|
|
5799
|
+
var MAX_LOG_BYTES, LOG_MODE, DIR_MODE;
|
|
5800
|
+
var init_replication_log = __esm({
|
|
5801
|
+
"src/lib/replication-log.ts"() {
|
|
5802
|
+
"use strict";
|
|
5803
|
+
MAX_LOG_BYTES = 5 * 1024 * 1024;
|
|
5804
|
+
LOG_MODE = 384;
|
|
5805
|
+
DIR_MODE = 448;
|
|
5652
5806
|
}
|
|
5807
|
+
});
|
|
5808
|
+
|
|
5809
|
+
// ../../node_modules/@noble/hashes/esm/_blake.js
|
|
5810
|
+
function G1s(a, b, c, d, x) {
|
|
5811
|
+
a = a + b + x | 0;
|
|
5812
|
+
d = rotr(d ^ a, 16);
|
|
5813
|
+
c = c + d | 0;
|
|
5814
|
+
b = rotr(b ^ c, 12);
|
|
5815
|
+
return { a, b, c, d };
|
|
5653
5816
|
}
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
);
|
|
5665
|
-
}
|
|
5666
|
-
if (profile?.authMethod === "local" && effectivePrivateKey) {
|
|
5667
|
-
const node2 = new TinyCloudNode({
|
|
5668
|
-
host: ctx.host,
|
|
5669
|
-
privateKey: effectivePrivateKey
|
|
5670
|
-
});
|
|
5671
|
-
const restoredOwnSession = Boolean(session && session.delegationHeader && session.delegationCid && session.spaceId);
|
|
5672
|
-
if (restoredOwnSession) {
|
|
5673
|
-
await restoreProfileSession(node2, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
|
|
5674
|
-
} else {
|
|
5675
|
-
await node2.signIn();
|
|
5676
|
-
}
|
|
5677
|
-
if (restoredOwnSession) {
|
|
5678
|
-
recordWarnings(await replayAdditionalDelegations(node2, ctx.profile, {
|
|
5679
|
-
host: ctx.host,
|
|
5680
|
-
ownerSpace: profile.spaceId,
|
|
5681
|
-
migrate: options?.privateKey === void 0
|
|
5682
|
-
}));
|
|
5683
|
-
}
|
|
5684
|
-
return node2;
|
|
5817
|
+
function G2s(a, b, c, d, x) {
|
|
5818
|
+
a = a + b + x | 0;
|
|
5819
|
+
d = rotr(d ^ a, 8);
|
|
5820
|
+
c = c + d | 0;
|
|
5821
|
+
b = rotr(b ^ c, 7);
|
|
5822
|
+
return { a, b, c, d };
|
|
5823
|
+
}
|
|
5824
|
+
var init_blake = __esm({
|
|
5825
|
+
"../../node_modules/@noble/hashes/esm/_blake.js"() {
|
|
5826
|
+
"use strict";
|
|
5827
|
+
init_utils();
|
|
5685
5828
|
}
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
}));
|
|
5829
|
+
});
|
|
5830
|
+
|
|
5831
|
+
// ../../node_modules/@noble/hashes/esm/blake2.js
|
|
5832
|
+
function compress(s, offset, msg, rounds, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) {
|
|
5833
|
+
let j = 0;
|
|
5834
|
+
for (let i = 0; i < rounds; i++) {
|
|
5835
|
+
({ a: v0, b: v4, c: v8, d: v12 } = G1s(v0, v4, v8, v12, msg[offset + s[j++]]));
|
|
5836
|
+
({ a: v0, b: v4, c: v8, d: v12 } = G2s(v0, v4, v8, v12, msg[offset + s[j++]]));
|
|
5837
|
+
({ a: v1, b: v5, c: v9, d: v13 } = G1s(v1, v5, v9, v13, msg[offset + s[j++]]));
|
|
5838
|
+
({ a: v1, b: v5, c: v9, d: v13 } = G2s(v1, v5, v9, v13, msg[offset + s[j++]]));
|
|
5839
|
+
({ a: v2, b: v6, c: v10, d: v14 } = G1s(v2, v6, v10, v14, msg[offset + s[j++]]));
|
|
5840
|
+
({ a: v2, b: v6, c: v10, d: v14 } = G2s(v2, v6, v10, v14, msg[offset + s[j++]]));
|
|
5841
|
+
({ a: v3, b: v7, c: v11, d: v15 } = G1s(v3, v7, v11, v15, msg[offset + s[j++]]));
|
|
5842
|
+
({ a: v3, b: v7, c: v11, d: v15 } = G2s(v3, v7, v11, v15, msg[offset + s[j++]]));
|
|
5843
|
+
({ a: v0, b: v5, c: v10, d: v15 } = G1s(v0, v5, v10, v15, msg[offset + s[j++]]));
|
|
5844
|
+
({ a: v0, b: v5, c: v10, d: v15 } = G2s(v0, v5, v10, v15, msg[offset + s[j++]]));
|
|
5845
|
+
({ a: v1, b: v6, c: v11, d: v12 } = G1s(v1, v6, v11, v12, msg[offset + s[j++]]));
|
|
5846
|
+
({ a: v1, b: v6, c: v11, d: v12 } = G2s(v1, v6, v11, v12, msg[offset + s[j++]]));
|
|
5847
|
+
({ a: v2, b: v7, c: v8, d: v13 } = G1s(v2, v7, v8, v13, msg[offset + s[j++]]));
|
|
5848
|
+
({ a: v2, b: v7, c: v8, d: v13 } = G2s(v2, v7, v8, v13, msg[offset + s[j++]]));
|
|
5849
|
+
({ a: v3, b: v4, c: v9, d: v14 } = G1s(v3, v4, v9, v14, msg[offset + s[j++]]));
|
|
5850
|
+
({ a: v3, b: v4, c: v9, d: v14 } = G2s(v3, v4, v9, v14, msg[offset + s[j++]]));
|
|
5699
5851
|
}
|
|
5700
|
-
return
|
|
5852
|
+
return { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 };
|
|
5701
5853
|
}
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5854
|
+
var BLAKE2;
|
|
5855
|
+
var init_blake2 = __esm({
|
|
5856
|
+
"../../node_modules/@noble/hashes/esm/blake2.js"() {
|
|
5857
|
+
"use strict";
|
|
5858
|
+
init_blake();
|
|
5859
|
+
init_utils();
|
|
5860
|
+
BLAKE2 = class extends Hash {
|
|
5861
|
+
constructor(blockLen, outputLen) {
|
|
5862
|
+
super();
|
|
5863
|
+
this.finished = false;
|
|
5864
|
+
this.destroyed = false;
|
|
5865
|
+
this.length = 0;
|
|
5866
|
+
this.pos = 0;
|
|
5867
|
+
anumber(blockLen);
|
|
5868
|
+
anumber(outputLen);
|
|
5869
|
+
this.blockLen = blockLen;
|
|
5870
|
+
this.outputLen = outputLen;
|
|
5871
|
+
this.buffer = new Uint8Array(blockLen);
|
|
5872
|
+
this.buffer32 = u32(this.buffer);
|
|
5873
|
+
}
|
|
5874
|
+
update(data) {
|
|
5875
|
+
aexists(this);
|
|
5876
|
+
data = toBytes(data);
|
|
5877
|
+
abytes(data);
|
|
5878
|
+
const { blockLen, buffer, buffer32 } = this;
|
|
5879
|
+
const len = data.length;
|
|
5880
|
+
const offset = data.byteOffset;
|
|
5881
|
+
const buf = data.buffer;
|
|
5882
|
+
for (let pos = 0; pos < len; ) {
|
|
5883
|
+
if (this.pos === blockLen) {
|
|
5884
|
+
swap32IfBE(buffer32);
|
|
5885
|
+
this.compress(buffer32, 0, false);
|
|
5886
|
+
swap32IfBE(buffer32);
|
|
5887
|
+
this.pos = 0;
|
|
5888
|
+
}
|
|
5889
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
5890
|
+
const dataOffset = offset + pos;
|
|
5891
|
+
if (take === blockLen && !(dataOffset % 4) && pos + take < len) {
|
|
5892
|
+
const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4));
|
|
5893
|
+
swap32IfBE(data32);
|
|
5894
|
+
for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) {
|
|
5895
|
+
this.length += blockLen;
|
|
5896
|
+
this.compress(data32, pos32, false);
|
|
5897
|
+
}
|
|
5898
|
+
swap32IfBE(data32);
|
|
5899
|
+
continue;
|
|
5900
|
+
}
|
|
5901
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
5902
|
+
this.pos += take;
|
|
5903
|
+
this.length += take;
|
|
5904
|
+
pos += take;
|
|
5905
|
+
}
|
|
5906
|
+
return this;
|
|
5907
|
+
}
|
|
5908
|
+
digestInto(out) {
|
|
5909
|
+
aexists(this);
|
|
5910
|
+
aoutput(out, this);
|
|
5911
|
+
const { pos, buffer32 } = this;
|
|
5912
|
+
this.finished = true;
|
|
5913
|
+
clean(this.buffer.subarray(pos));
|
|
5914
|
+
swap32IfBE(buffer32);
|
|
5915
|
+
this.compress(buffer32, 0, true);
|
|
5916
|
+
swap32IfBE(buffer32);
|
|
5917
|
+
const out32 = u32(out);
|
|
5918
|
+
this.get().forEach((v, i) => out32[i] = swap8IfBE(v));
|
|
5919
|
+
}
|
|
5920
|
+
digest() {
|
|
5921
|
+
const { buffer, outputLen } = this;
|
|
5922
|
+
this.digestInto(buffer);
|
|
5923
|
+
const res = buffer.slice(0, outputLen);
|
|
5924
|
+
this.destroy();
|
|
5925
|
+
return res;
|
|
5926
|
+
}
|
|
5927
|
+
_cloneInto(to) {
|
|
5928
|
+
const { buffer, length: length4, finished, destroyed, outputLen, pos } = this;
|
|
5929
|
+
to || (to = new this.constructor({ dkLen: outputLen }));
|
|
5930
|
+
to.set(...this.get());
|
|
5931
|
+
to.buffer.set(buffer);
|
|
5932
|
+
to.destroyed = destroyed;
|
|
5933
|
+
to.finished = finished;
|
|
5934
|
+
to.length = length4;
|
|
5935
|
+
to.pos = pos;
|
|
5936
|
+
to.outputLen = outputLen;
|
|
5937
|
+
return to;
|
|
5938
|
+
}
|
|
5939
|
+
clone() {
|
|
5940
|
+
return this._cloneInto();
|
|
5941
|
+
}
|
|
5735
5942
|
};
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5943
|
+
}
|
|
5944
|
+
});
|
|
5945
|
+
|
|
5946
|
+
// ../../node_modules/@noble/hashes/esm/blake3.js
|
|
5947
|
+
var B3_Flags, B3_IV, B3_SIGMA, BLAKE3, blake3;
|
|
5948
|
+
var init_blake3 = __esm({
|
|
5949
|
+
"../../node_modules/@noble/hashes/esm/blake3.js"() {
|
|
5950
|
+
"use strict";
|
|
5951
|
+
init_md();
|
|
5952
|
+
init_u64();
|
|
5953
|
+
init_blake2();
|
|
5954
|
+
init_utils();
|
|
5955
|
+
B3_Flags = {
|
|
5956
|
+
CHUNK_START: 1,
|
|
5957
|
+
CHUNK_END: 2,
|
|
5958
|
+
PARENT: 4,
|
|
5959
|
+
ROOT: 8,
|
|
5960
|
+
KEYED_HASH: 16,
|
|
5961
|
+
DERIVE_KEY_CONTEXT: 32,
|
|
5962
|
+
DERIVE_KEY_MATERIAL: 64
|
|
5963
|
+
};
|
|
5964
|
+
B3_IV = SHA256_IV.slice();
|
|
5965
|
+
B3_SIGMA = /* @__PURE__ */ (() => {
|
|
5966
|
+
const Id = Array.from({ length: 16 }, (_, i) => i);
|
|
5967
|
+
const permute = (arr) => [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8].map((i) => arr[i]);
|
|
5968
|
+
const res = [];
|
|
5969
|
+
for (let i = 0, v = Id; i < 7; i++, v = permute(v))
|
|
5970
|
+
res.push(...v);
|
|
5971
|
+
return Uint8Array.from(res);
|
|
5972
|
+
})();
|
|
5973
|
+
BLAKE3 = class _BLAKE3 extends BLAKE2 {
|
|
5974
|
+
constructor(opts = {}, flags = 0) {
|
|
5975
|
+
super(64, opts.dkLen === void 0 ? 32 : opts.dkLen);
|
|
5976
|
+
this.chunkPos = 0;
|
|
5977
|
+
this.chunksDone = 0;
|
|
5978
|
+
this.flags = 0 | 0;
|
|
5979
|
+
this.stack = [];
|
|
5980
|
+
this.posOut = 0;
|
|
5981
|
+
this.bufferOut32 = new Uint32Array(16);
|
|
5982
|
+
this.chunkOut = 0;
|
|
5983
|
+
this.enableXOF = true;
|
|
5984
|
+
const { key, context } = opts;
|
|
5985
|
+
const hasContext = context !== void 0;
|
|
5986
|
+
if (key !== void 0) {
|
|
5987
|
+
if (hasContext)
|
|
5988
|
+
throw new Error('Only "key" or "context" can be specified at same time');
|
|
5989
|
+
const k = toBytes(key).slice();
|
|
5990
|
+
abytes(k, 32);
|
|
5991
|
+
this.IV = u32(k);
|
|
5992
|
+
swap32IfBE(this.IV);
|
|
5993
|
+
this.flags = flags | B3_Flags.KEYED_HASH;
|
|
5994
|
+
} else if (hasContext) {
|
|
5995
|
+
const ctx = toBytes(context);
|
|
5996
|
+
const contextKey = new _BLAKE3({ dkLen: 32 }, B3_Flags.DERIVE_KEY_CONTEXT).update(ctx).digest();
|
|
5997
|
+
this.IV = u32(contextKey);
|
|
5998
|
+
swap32IfBE(this.IV);
|
|
5999
|
+
this.flags = flags | B3_Flags.DERIVE_KEY_MATERIAL;
|
|
6000
|
+
} else {
|
|
6001
|
+
this.IV = B3_IV.slice();
|
|
6002
|
+
this.flags = flags;
|
|
6003
|
+
}
|
|
6004
|
+
this.state = this.IV.slice();
|
|
6005
|
+
this.bufferOut = u8(this.bufferOut32);
|
|
5755
6006
|
}
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
6007
|
+
// Unused
|
|
6008
|
+
get() {
|
|
6009
|
+
return [];
|
|
6010
|
+
}
|
|
6011
|
+
set() {
|
|
6012
|
+
}
|
|
6013
|
+
b2Compress(counter, flags, buf, bufPos = 0) {
|
|
6014
|
+
const { state: s, pos } = this;
|
|
6015
|
+
const { h, l } = fromBig(BigInt(counter), true);
|
|
6016
|
+
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(B3_SIGMA, bufPos, buf, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], B3_IV[0], B3_IV[1], B3_IV[2], B3_IV[3], h, l, pos, flags);
|
|
6017
|
+
s[0] = v0 ^ v8;
|
|
6018
|
+
s[1] = v1 ^ v9;
|
|
6019
|
+
s[2] = v2 ^ v10;
|
|
6020
|
+
s[3] = v3 ^ v11;
|
|
6021
|
+
s[4] = v4 ^ v12;
|
|
6022
|
+
s[5] = v5 ^ v13;
|
|
6023
|
+
s[6] = v6 ^ v14;
|
|
6024
|
+
s[7] = v7 ^ v15;
|
|
6025
|
+
}
|
|
6026
|
+
compress(buf, bufPos = 0, isLast = false) {
|
|
6027
|
+
let flags = this.flags;
|
|
6028
|
+
if (!this.chunkPos)
|
|
6029
|
+
flags |= B3_Flags.CHUNK_START;
|
|
6030
|
+
if (this.chunkPos === 15 || isLast)
|
|
6031
|
+
flags |= B3_Flags.CHUNK_END;
|
|
6032
|
+
if (!isLast)
|
|
6033
|
+
this.pos = this.blockLen;
|
|
6034
|
+
this.b2Compress(this.chunksDone, flags, buf, bufPos);
|
|
6035
|
+
this.chunkPos += 1;
|
|
6036
|
+
if (this.chunkPos === 16 || isLast) {
|
|
6037
|
+
let chunk = this.state;
|
|
6038
|
+
this.state = this.IV.slice();
|
|
6039
|
+
for (let last, chunks = this.chunksDone + 1; isLast || !(chunks & 1); chunks >>= 1) {
|
|
6040
|
+
if (!(last = this.stack.pop()))
|
|
6041
|
+
break;
|
|
6042
|
+
this.buffer32.set(last, 0);
|
|
6043
|
+
this.buffer32.set(chunk, 8);
|
|
6044
|
+
this.pos = this.blockLen;
|
|
6045
|
+
this.b2Compress(0, this.flags | B3_Flags.PARENT, this.buffer32, 0);
|
|
6046
|
+
chunk = this.state;
|
|
6047
|
+
this.state = this.IV.slice();
|
|
6048
|
+
}
|
|
6049
|
+
this.chunksDone++;
|
|
6050
|
+
this.chunkPos = 0;
|
|
6051
|
+
this.stack.push(chunk);
|
|
6052
|
+
}
|
|
6053
|
+
this.pos = 0;
|
|
6054
|
+
}
|
|
6055
|
+
_cloneInto(to) {
|
|
6056
|
+
to = super._cloneInto(to);
|
|
6057
|
+
const { IV, flags, state: state2, chunkPos, posOut, chunkOut, stack, chunksDone } = this;
|
|
6058
|
+
to.state.set(state2.slice());
|
|
6059
|
+
to.stack = stack.map((i) => Uint32Array.from(i));
|
|
6060
|
+
to.IV.set(IV);
|
|
6061
|
+
to.flags = flags;
|
|
6062
|
+
to.chunkPos = chunkPos;
|
|
6063
|
+
to.chunksDone = chunksDone;
|
|
6064
|
+
to.posOut = posOut;
|
|
6065
|
+
to.chunkOut = chunkOut;
|
|
6066
|
+
to.enableXOF = this.enableXOF;
|
|
6067
|
+
to.bufferOut32.set(this.bufferOut32);
|
|
6068
|
+
return to;
|
|
6069
|
+
}
|
|
6070
|
+
destroy() {
|
|
6071
|
+
this.destroyed = true;
|
|
6072
|
+
clean(this.state, this.buffer32, this.IV, this.bufferOut32);
|
|
6073
|
+
clean(...this.stack);
|
|
6074
|
+
}
|
|
6075
|
+
// Same as b2Compress, but doesn't modify state and returns 16 u32 array (instead of 8)
|
|
6076
|
+
b2CompressOut() {
|
|
6077
|
+
const { state: s, pos, flags, buffer32, bufferOut32: out32 } = this;
|
|
6078
|
+
const { h, l } = fromBig(BigInt(this.chunkOut++));
|
|
6079
|
+
swap32IfBE(buffer32);
|
|
6080
|
+
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(B3_SIGMA, 0, buffer32, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], B3_IV[0], B3_IV[1], B3_IV[2], B3_IV[3], l, h, pos, flags);
|
|
6081
|
+
out32[0] = v0 ^ v8;
|
|
6082
|
+
out32[1] = v1 ^ v9;
|
|
6083
|
+
out32[2] = v2 ^ v10;
|
|
6084
|
+
out32[3] = v3 ^ v11;
|
|
6085
|
+
out32[4] = v4 ^ v12;
|
|
6086
|
+
out32[5] = v5 ^ v13;
|
|
6087
|
+
out32[6] = v6 ^ v14;
|
|
6088
|
+
out32[7] = v7 ^ v15;
|
|
6089
|
+
out32[8] = s[0] ^ v8;
|
|
6090
|
+
out32[9] = s[1] ^ v9;
|
|
6091
|
+
out32[10] = s[2] ^ v10;
|
|
6092
|
+
out32[11] = s[3] ^ v11;
|
|
6093
|
+
out32[12] = s[4] ^ v12;
|
|
6094
|
+
out32[13] = s[5] ^ v13;
|
|
6095
|
+
out32[14] = s[6] ^ v14;
|
|
6096
|
+
out32[15] = s[7] ^ v15;
|
|
6097
|
+
swap32IfBE(buffer32);
|
|
6098
|
+
swap32IfBE(out32);
|
|
6099
|
+
this.posOut = 0;
|
|
6100
|
+
}
|
|
6101
|
+
finish() {
|
|
6102
|
+
if (this.finished)
|
|
6103
|
+
return;
|
|
6104
|
+
this.finished = true;
|
|
6105
|
+
clean(this.buffer.subarray(this.pos));
|
|
6106
|
+
let flags = this.flags | B3_Flags.ROOT;
|
|
6107
|
+
if (this.stack.length) {
|
|
6108
|
+
flags |= B3_Flags.PARENT;
|
|
6109
|
+
swap32IfBE(this.buffer32);
|
|
6110
|
+
this.compress(this.buffer32, 0, true);
|
|
6111
|
+
swap32IfBE(this.buffer32);
|
|
6112
|
+
this.chunksDone = 0;
|
|
6113
|
+
this.pos = this.blockLen;
|
|
6114
|
+
} else {
|
|
6115
|
+
flags |= (!this.chunkPos ? B3_Flags.CHUNK_START : 0) | B3_Flags.CHUNK_END;
|
|
6116
|
+
}
|
|
6117
|
+
this.flags = flags;
|
|
6118
|
+
this.b2CompressOut();
|
|
6119
|
+
}
|
|
6120
|
+
writeInto(out) {
|
|
6121
|
+
aexists(this, false);
|
|
6122
|
+
abytes(out);
|
|
6123
|
+
this.finish();
|
|
6124
|
+
const { blockLen, bufferOut } = this;
|
|
6125
|
+
for (let pos = 0, len = out.length; pos < len; ) {
|
|
6126
|
+
if (this.posOut >= blockLen)
|
|
6127
|
+
this.b2CompressOut();
|
|
6128
|
+
const take = Math.min(blockLen - this.posOut, len - pos);
|
|
6129
|
+
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
|
|
6130
|
+
this.posOut += take;
|
|
6131
|
+
pos += take;
|
|
6132
|
+
}
|
|
6133
|
+
return out;
|
|
6134
|
+
}
|
|
6135
|
+
xofInto(out) {
|
|
6136
|
+
if (!this.enableXOF)
|
|
6137
|
+
throw new Error("XOF is not possible after digest call");
|
|
6138
|
+
return this.writeInto(out);
|
|
6139
|
+
}
|
|
6140
|
+
xof(bytes) {
|
|
6141
|
+
anumber(bytes);
|
|
6142
|
+
return this.xofInto(new Uint8Array(bytes));
|
|
6143
|
+
}
|
|
6144
|
+
digestInto(out) {
|
|
6145
|
+
aoutput(out, this);
|
|
6146
|
+
if (this.finished)
|
|
6147
|
+
throw new Error("digest() was already called");
|
|
6148
|
+
this.enableXOF = false;
|
|
6149
|
+
this.writeInto(out);
|
|
6150
|
+
this.destroy();
|
|
6151
|
+
return out;
|
|
6152
|
+
}
|
|
6153
|
+
digest() {
|
|
6154
|
+
return this.digestInto(new Uint8Array(this.outputLen));
|
|
6155
|
+
}
|
|
6156
|
+
};
|
|
6157
|
+
blake3 = /* @__PURE__ */ createXOFer((opts) => new BLAKE3(opts));
|
|
5768
6158
|
}
|
|
5769
|
-
|
|
6159
|
+
});
|
|
6160
|
+
|
|
6161
|
+
// ../../node_modules/@noble/curves/esm/utils.js
|
|
6162
|
+
function _abool2(value, title = "") {
|
|
6163
|
+
if (typeof value !== "boolean") {
|
|
6164
|
+
const prefix = title && `"${title}"`;
|
|
6165
|
+
throw new Error(prefix + "expected boolean, got type=" + typeof value);
|
|
6166
|
+
}
|
|
6167
|
+
return value;
|
|
5770
6168
|
}
|
|
5771
|
-
|
|
5772
|
-
const
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
}
|
|
5781
|
-
return restored;
|
|
5782
|
-
})
|
|
5783
|
-
]) {
|
|
5784
|
-
await write().catch((error) => {
|
|
5785
|
-
failures.push(failureName(error));
|
|
5786
|
-
});
|
|
6169
|
+
function _abytes2(value, length4, title = "") {
|
|
6170
|
+
const bytes = isBytes(value);
|
|
6171
|
+
const len = value?.length;
|
|
6172
|
+
const needsLen = length4 !== void 0;
|
|
6173
|
+
if (!bytes || needsLen && len !== length4) {
|
|
6174
|
+
const prefix = title && `"${title}" `;
|
|
6175
|
+
const ofLen = needsLen ? ` of length ${length4}` : "";
|
|
6176
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
6177
|
+
throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
5787
6178
|
}
|
|
5788
|
-
|
|
5789
|
-
return `Rolling back the provisional session of profile "${profileName}" failed too (${failures.join("; ")}); check \`tc --profile ${profileName} context\`.`;
|
|
6179
|
+
return value;
|
|
5790
6180
|
}
|
|
5791
|
-
function
|
|
5792
|
-
if (
|
|
5793
|
-
|
|
5794
|
-
return
|
|
6181
|
+
function hexToNumber(hex3) {
|
|
6182
|
+
if (typeof hex3 !== "string")
|
|
6183
|
+
throw new Error("hex string expected, got " + typeof hex3);
|
|
6184
|
+
return hex3 === "" ? _0n : BigInt("0x" + hex3);
|
|
5795
6185
|
}
|
|
5796
|
-
function
|
|
5797
|
-
|
|
5798
|
-
const cause = wrapError(error);
|
|
5799
|
-
return new CLIError(cause.code, `${cause.message} ${note}`, cause.exitCode, cause.metadata);
|
|
6186
|
+
function bytesToNumberBE(bytes) {
|
|
6187
|
+
return hexToNumber(bytesToHex(bytes));
|
|
5800
6188
|
}
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
}
|
|
5805
|
-
const profile = await ProfileManager.getProfile(ctx.profile).catch(() => null);
|
|
5806
|
-
if (profile?.authMethod === "local" && profile.privateKey) {
|
|
5807
|
-
return createSDKInstance(ctx);
|
|
5808
|
-
}
|
|
5809
|
-
const session = await ProfileManager.getSession(ctx.profile);
|
|
5810
|
-
if (!session) {
|
|
5811
|
-
throw new CLIError(
|
|
5812
|
-
"AUTH_REQUIRED",
|
|
5813
|
-
`Not authenticated. Run \`tc auth login\` or \`tc init\` first.`,
|
|
5814
|
-
ExitCode.AUTH_REQUIRED
|
|
5815
|
-
);
|
|
5816
|
-
}
|
|
5817
|
-
return createSDKInstance(ctx, options);
|
|
6189
|
+
function bytesToNumberLE(bytes) {
|
|
6190
|
+
abytes(bytes);
|
|
6191
|
+
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
|
|
5818
6192
|
}
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
6193
|
+
function numberToBytesBE(n, len) {
|
|
6194
|
+
return hexToBytes(n.toString(16).padStart(len * 2, "0"));
|
|
6195
|
+
}
|
|
6196
|
+
function numberToBytesLE(n, len) {
|
|
6197
|
+
return numberToBytesBE(n, len).reverse();
|
|
6198
|
+
}
|
|
6199
|
+
function ensureBytes(title, hex3, expectedLength) {
|
|
6200
|
+
let res;
|
|
6201
|
+
if (typeof hex3 === "string") {
|
|
6202
|
+
try {
|
|
6203
|
+
res = hexToBytes(hex3);
|
|
6204
|
+
} catch (e) {
|
|
6205
|
+
throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
|
|
6206
|
+
}
|
|
6207
|
+
} else if (isBytes(hex3)) {
|
|
6208
|
+
res = Uint8Array.from(hex3);
|
|
6209
|
+
} else {
|
|
6210
|
+
throw new Error(title + " must be hex string or Uint8Array");
|
|
5832
6211
|
}
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
__export(host_exports, {
|
|
5838
|
-
completeDeferredLocalDiscovery: () => completeDeferredLocalDiscovery,
|
|
5839
|
-
discoverLocalNodeHost: () => discoverLocalNodeHost,
|
|
5840
|
-
isRootAuthority: () => isRootAuthority,
|
|
5841
|
-
ownerDidFromSpaceUri: () => ownerDidFromSpaceUri,
|
|
5842
|
-
profileLocalNodeIdentityStore: () => profileLocalNodeIdentityStore,
|
|
5843
|
-
resolveHostSpace: () => resolveHostSpace,
|
|
5844
|
-
spaceNameFromUri: () => spaceNameFromUri,
|
|
5845
|
-
unhostedSpaceError: () => unhostedSpaceError
|
|
5846
|
-
});
|
|
5847
|
-
import {
|
|
5848
|
-
discoverLocalTinyCloudNode
|
|
5849
|
-
} from "@tinycloud/sdk-core";
|
|
5850
|
-
function profileLocalNodeIdentityStore(profileName) {
|
|
5851
|
-
return {
|
|
5852
|
-
get: async (url) => {
|
|
5853
|
-
const profile = await ProfileManager.getProfile(profileName).catch(
|
|
5854
|
-
() => null
|
|
5855
|
-
);
|
|
5856
|
-
return profile?.pinnedLocalNodeDids?.[url];
|
|
5857
|
-
},
|
|
5858
|
-
set: async (url, nodeDid) => {
|
|
5859
|
-
if (!await ProfileManager.profileExists(profileName)) return;
|
|
5860
|
-
await ProfileManager.updateProfile(profileName, (profile) => ({
|
|
5861
|
-
...profile,
|
|
5862
|
-
pinnedLocalNodeDids: {
|
|
5863
|
-
...profile.pinnedLocalNodeDids,
|
|
5864
|
-
[url]: nodeDid
|
|
5865
|
-
}
|
|
5866
|
-
}));
|
|
5867
|
-
}
|
|
5868
|
-
};
|
|
6212
|
+
const len = res.length;
|
|
6213
|
+
if (typeof expectedLength === "number" && len !== expectedLength)
|
|
6214
|
+
throw new Error(title + " of length " + expectedLength + " expected, got " + len);
|
|
6215
|
+
return res;
|
|
5869
6216
|
}
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
}
|
|
5878
|
-
const discovered = await discoverLocalTinyCloudNode({
|
|
5879
|
-
localNodeUrl: profile?.localNodeUrl,
|
|
5880
|
-
localLinkName: profile?.localLinkName,
|
|
5881
|
-
expectedNodeDid: profile?.expectedNodeDid,
|
|
5882
|
-
identityStore: profileLocalNodeIdentityStore(profileName)
|
|
5883
|
-
});
|
|
5884
|
-
return { host: discovered?.url ?? null, deferred: false };
|
|
6217
|
+
function equalBytes(a, b) {
|
|
6218
|
+
if (a.length !== b.length)
|
|
6219
|
+
return false;
|
|
6220
|
+
let diff = 0;
|
|
6221
|
+
for (let i = 0; i < a.length; i++)
|
|
6222
|
+
diff |= a[i] ^ b[i];
|
|
6223
|
+
return diff === 0;
|
|
5885
6224
|
}
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
if (deferred === void 0) return;
|
|
5889
|
-
delete ctx.localDiscovery;
|
|
5890
|
-
if (ctx.host !== deferred.deferredFrom) return;
|
|
5891
|
-
const discovered = await discoverLocalNodeHost(ctx.profile, { awaitStoredSession: false });
|
|
5892
|
-
if (discovered.host !== null) ctx.host = discovered.host;
|
|
6225
|
+
function copyBytes(bytes) {
|
|
6226
|
+
return Uint8Array.from(bytes);
|
|
5893
6227
|
}
|
|
5894
|
-
function
|
|
5895
|
-
|
|
5896
|
-
return trimmed.startsWith("0x") ? `0x${trimmed.slice(2).toLowerCase()}` : trimmed.toLowerCase();
|
|
6228
|
+
function inRange(n, min, max) {
|
|
6229
|
+
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
|
|
5897
6230
|
}
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
6231
|
+
function aInRange(title, n, min, max) {
|
|
6232
|
+
if (!inRange(n, min, max))
|
|
6233
|
+
throw new Error("expected valid " + title + ": " + min + " <= n < " + max + ", got " + n);
|
|
6234
|
+
}
|
|
6235
|
+
function bitLen(n) {
|
|
6236
|
+
let len;
|
|
6237
|
+
for (len = 0; n > _0n; n >>= _1n, len += 1)
|
|
6238
|
+
;
|
|
6239
|
+
return len;
|
|
6240
|
+
}
|
|
6241
|
+
function _validateObject(object3, fields, optFields = {}) {
|
|
6242
|
+
if (!object3 || typeof object3 !== "object")
|
|
6243
|
+
throw new Error("expected valid options object");
|
|
6244
|
+
function checkField(fieldName, expectedType, isOpt) {
|
|
6245
|
+
const val = object3[fieldName];
|
|
6246
|
+
if (isOpt && val === void 0)
|
|
6247
|
+
return;
|
|
6248
|
+
const current = typeof val;
|
|
6249
|
+
if (current !== expectedType || val === null)
|
|
6250
|
+
throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
|
|
5903
6251
|
}
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
6252
|
+
Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
|
|
6253
|
+
Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
|
|
6254
|
+
}
|
|
6255
|
+
function memoized(fn) {
|
|
6256
|
+
const map = /* @__PURE__ */ new WeakMap();
|
|
6257
|
+
return (arg, ...args) => {
|
|
6258
|
+
const val = map.get(arg);
|
|
6259
|
+
if (val !== void 0)
|
|
6260
|
+
return val;
|
|
6261
|
+
const computed = fn(arg, ...args);
|
|
6262
|
+
map.set(arg, computed);
|
|
6263
|
+
return computed;
|
|
6264
|
+
};
|
|
6265
|
+
}
|
|
6266
|
+
var _0n, _1n, isPosBig, bitMask, notImplemented;
|
|
6267
|
+
var init_utils2 = __esm({
|
|
6268
|
+
"../../node_modules/@noble/curves/esm/utils.js"() {
|
|
6269
|
+
"use strict";
|
|
6270
|
+
init_utils();
|
|
6271
|
+
init_utils();
|
|
6272
|
+
_0n = /* @__PURE__ */ BigInt(0);
|
|
6273
|
+
_1n = /* @__PURE__ */ BigInt(1);
|
|
6274
|
+
isPosBig = (n) => typeof n === "bigint" && _0n <= n;
|
|
6275
|
+
bitMask = (n) => (_1n << BigInt(n)) - _1n;
|
|
6276
|
+
notImplemented = () => {
|
|
6277
|
+
throw new Error("not implemented");
|
|
6278
|
+
};
|
|
5908
6279
|
}
|
|
5909
|
-
|
|
6280
|
+
});
|
|
6281
|
+
|
|
6282
|
+
// ../../node_modules/@noble/curves/esm/abstract/modular.js
|
|
6283
|
+
function mod(a, b) {
|
|
6284
|
+
const result = a % b;
|
|
6285
|
+
return result >= _0n2 ? result : b + result;
|
|
5910
6286
|
}
|
|
5911
|
-
function
|
|
5912
|
-
|
|
5913
|
-
|
|
6287
|
+
function pow2(x, power, modulo) {
|
|
6288
|
+
let res = x;
|
|
6289
|
+
while (power-- > _0n2) {
|
|
6290
|
+
res *= res;
|
|
6291
|
+
res %= modulo;
|
|
6292
|
+
}
|
|
6293
|
+
return res;
|
|
5914
6294
|
}
|
|
5915
|
-
function
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
6295
|
+
function invert(number, modulo) {
|
|
6296
|
+
if (number === _0n2)
|
|
6297
|
+
throw new Error("invert: expected non-zero number");
|
|
6298
|
+
if (modulo <= _0n2)
|
|
6299
|
+
throw new Error("invert: expected positive modulus, got " + modulo);
|
|
6300
|
+
let a = mod(number, modulo);
|
|
6301
|
+
let b = modulo;
|
|
6302
|
+
let x = _0n2, y = _1n2, u = _1n2, v = _0n2;
|
|
6303
|
+
while (a !== _0n2) {
|
|
6304
|
+
const q = b / a;
|
|
6305
|
+
const r = b % a;
|
|
6306
|
+
const m = x - u * q;
|
|
6307
|
+
const n = y - v * q;
|
|
6308
|
+
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
6309
|
+
}
|
|
6310
|
+
const gcd = b;
|
|
6311
|
+
if (gcd !== _1n2)
|
|
6312
|
+
throw new Error("invert: does not exist");
|
|
6313
|
+
return mod(x, modulo);
|
|
5919
6314
|
}
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
const ownerAddr = ownerAddressFromSpaceUri(spaceUri);
|
|
5924
|
-
if (!ownerAddr) return false;
|
|
5925
|
-
const selfAddr = await resolveLocalAddress(profile, profileName);
|
|
5926
|
-
return selfAddr !== null && selfAddr === ownerAddr;
|
|
6315
|
+
function assertIsSquare(Fp2, root, n) {
|
|
6316
|
+
if (!Fp2.eql(Fp2.sqr(root), n))
|
|
6317
|
+
throw new Error("Cannot find square root");
|
|
5927
6318
|
}
|
|
5928
|
-
function
|
|
5929
|
-
|
|
6319
|
+
function sqrt3mod4(Fp2, n) {
|
|
6320
|
+
const p1div4 = (Fp2.ORDER + _1n2) / _4n;
|
|
6321
|
+
const root = Fp2.pow(n, p1div4);
|
|
6322
|
+
assertIsSquare(Fp2, root, n);
|
|
6323
|
+
return root;
|
|
5930
6324
|
}
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
const
|
|
5934
|
-
const
|
|
5935
|
-
|
|
5936
|
-
const
|
|
5937
|
-
const
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
` tc space host ${spaceName}`,
|
|
5941
|
-
"Then retry."
|
|
5942
|
-
].join("\n") : [
|
|
5943
|
-
"You are a delegate and CANNOT host this space \u2014 only its owner can.",
|
|
5944
|
-
"Emit a host request:",
|
|
5945
|
-
` tc space host-request ${spaceName} --emit ./host-request.json`,
|
|
5946
|
-
"Send it to the owner; they run `tc space host` and confirm. Then retry."
|
|
5947
|
-
].join("\n");
|
|
5948
|
-
const message = owner ? `Space '${spaceName}' (${spaceUri}) is not hosted.` : `Space '${spaceName}' (owner ${ownerDidFromSpaceUri(spaceUri) ?? spaceUri}) is not hosted.`;
|
|
5949
|
-
return new CLIError("SPACE_NOT_HOSTED", message, ExitCode.ERROR, { hint });
|
|
6325
|
+
function sqrt5mod8(Fp2, n) {
|
|
6326
|
+
const p5div8 = (Fp2.ORDER - _5n) / _8n;
|
|
6327
|
+
const n2 = Fp2.mul(n, _2n);
|
|
6328
|
+
const v = Fp2.pow(n2, p5div8);
|
|
6329
|
+
const nv = Fp2.mul(n, v);
|
|
6330
|
+
const i = Fp2.mul(Fp2.mul(nv, _2n), v);
|
|
6331
|
+
const root = Fp2.mul(nv, Fp2.sub(i, Fp2.ONE));
|
|
6332
|
+
assertIsSquare(Fp2, root, n);
|
|
6333
|
+
return root;
|
|
5950
6334
|
}
|
|
5951
|
-
|
|
5952
|
-
const
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
6335
|
+
function sqrt9mod16(P) {
|
|
6336
|
+
const Fp_ = Field(P);
|
|
6337
|
+
const tn = tonelliShanks(P);
|
|
6338
|
+
const c1 = tn(Fp_, Fp_.neg(Fp_.ONE));
|
|
6339
|
+
const c2 = tn(Fp_, c1);
|
|
6340
|
+
const c3 = tn(Fp_, Fp_.neg(c1));
|
|
6341
|
+
const c4 = (P + _7n) / _16n;
|
|
6342
|
+
return (Fp2, n) => {
|
|
6343
|
+
let tv1 = Fp2.pow(n, c4);
|
|
6344
|
+
let tv2 = Fp2.mul(tv1, c1);
|
|
6345
|
+
const tv3 = Fp2.mul(tv1, c2);
|
|
6346
|
+
const tv4 = Fp2.mul(tv1, c3);
|
|
6347
|
+
const e1 = Fp2.eql(Fp2.sqr(tv2), n);
|
|
6348
|
+
const e2 = Fp2.eql(Fp2.sqr(tv3), n);
|
|
6349
|
+
tv1 = Fp2.cmov(tv1, tv2, e1);
|
|
6350
|
+
tv2 = Fp2.cmov(tv4, tv3, e2);
|
|
6351
|
+
const e3 = Fp2.eql(Fp2.sqr(tv2), n);
|
|
6352
|
+
const root = Fp2.cmov(tv1, tv2, e3);
|
|
6353
|
+
assertIsSquare(Fp2, root, n);
|
|
6354
|
+
return root;
|
|
6355
|
+
};
|
|
5957
6356
|
}
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
"
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
}
|
|
5967
|
-
});
|
|
5968
|
-
|
|
5969
|
-
// src/config/profiles.ts
|
|
5970
|
-
import { chmod as chmod2, lstat, readdir as readdir2, rm as rm2, rmdir } from "fs/promises";
|
|
5971
|
-
import { join as join4 } from "path";
|
|
5972
|
-
import {
|
|
5973
|
-
profilePath,
|
|
5974
|
-
readSession,
|
|
5975
|
-
recordProfileDeletion,
|
|
5976
|
-
refuseWriteToDeletedProfile as refuseWriteToDeletedProfile2,
|
|
5977
|
-
removeSession,
|
|
5978
|
-
withProfileLock as withProfileLock2,
|
|
5979
|
-
writeSession
|
|
5980
|
-
} from "@tinycloud/operations/state";
|
|
5981
|
-
var ProfileManager;
|
|
5982
|
-
var init_profiles = __esm({
|
|
5983
|
-
"src/config/profiles.ts"() {
|
|
5984
|
-
"use strict";
|
|
5985
|
-
init_constants();
|
|
5986
|
-
init_storage2();
|
|
5987
|
-
init_errors();
|
|
5988
|
-
ProfileManager = class _ProfileManager {
|
|
5989
|
-
// ── Initialization ──────────────────────────────────────────────────
|
|
5990
|
-
/**
|
|
5991
|
-
* Runs `action` holding the profile's store lock (shared with operations
|
|
5992
|
-
* and MCP). Reentrant, so the writers below can be called inside it; hold
|
|
5993
|
-
* it around a whole read-modify-write, not just each write.
|
|
5994
|
-
*/
|
|
5995
|
-
static async withLock(name, action, options) {
|
|
5996
|
-
return withProfileLock2(name, action, options);
|
|
5997
|
-
}
|
|
5998
|
-
/**
|
|
5999
|
-
* Read-modify-write of profile.json under the profile lock, so concurrent
|
|
6000
|
-
* updates (another command, a login commit) are never erased.
|
|
6001
|
-
*/
|
|
6002
|
-
static async updateProfile(name, update) {
|
|
6003
|
-
return _ProfileManager.withLock(name, async () => {
|
|
6004
|
-
const next = update(await _ProfileManager.getProfile(name));
|
|
6005
|
-
await _ProfileManager.setProfile(name, next);
|
|
6006
|
-
return next;
|
|
6007
|
-
});
|
|
6008
|
-
}
|
|
6009
|
-
/**
|
|
6010
|
-
* Creates ~/.tinycloud/ and ~/.tinycloud/profiles/ if they don't exist and
|
|
6011
|
-
* (re)sets both to 0700: older releases created them 0775.
|
|
6012
|
-
*/
|
|
6013
|
-
static async ensureConfigDir() {
|
|
6014
|
-
for (const directory of [CONFIG_DIR, PROFILES_DIR]) {
|
|
6015
|
-
await ensureDir(directory);
|
|
6016
|
-
await chmod2(directory, PRIVATE_DIR_MODE);
|
|
6017
|
-
}
|
|
6018
|
-
}
|
|
6019
|
-
/** Owner-only profile directory (0700), created or tightened before any write into it. */
|
|
6020
|
-
static async ensureProfileDir(name) {
|
|
6021
|
-
await _ProfileManager.ensureConfigDir();
|
|
6022
|
-
const profileDir = join4(PROFILES_DIR, name);
|
|
6023
|
-
await ensureDir(profileDir);
|
|
6024
|
-
await chmod2(profileDir, PRIVATE_DIR_MODE);
|
|
6025
|
-
return profileDir;
|
|
6026
|
-
}
|
|
6027
|
-
// ── Global config ───────────────────────────────────────────────────
|
|
6028
|
-
/**
|
|
6029
|
-
* Reads config.json. Returns a default config if the file is missing.
|
|
6030
|
-
*/
|
|
6031
|
-
static async getConfig() {
|
|
6032
|
-
const config = await readJson(CONFIG_FILE);
|
|
6033
|
-
if (!config) {
|
|
6034
|
-
return { defaultProfile: DEFAULT_PROFILE, version: 1 };
|
|
6035
|
-
}
|
|
6036
|
-
return config;
|
|
6037
|
-
}
|
|
6038
|
-
/**
|
|
6039
|
-
* Writes the global config to config.json.
|
|
6040
|
-
*/
|
|
6041
|
-
static async setConfig(config) {
|
|
6042
|
-
await _ProfileManager.ensureConfigDir();
|
|
6043
|
-
await writeJson(CONFIG_FILE, config);
|
|
6044
|
-
}
|
|
6045
|
-
// ── Profile CRUD ────────────────────────────────────────────────────
|
|
6046
|
-
/**
|
|
6047
|
-
* Returns the profile config for the given name.
|
|
6048
|
-
* Throws CLIError if the profile doesn't exist.
|
|
6049
|
-
*/
|
|
6050
|
-
static async getProfile(name) {
|
|
6051
|
-
const profilePath2 = join4(PROFILES_DIR, name, "profile.json");
|
|
6052
|
-
const profile = await readJson(profilePath2);
|
|
6053
|
-
if (!profile) {
|
|
6054
|
-
throw new CLIError(
|
|
6055
|
-
"PROFILE_NOT_FOUND",
|
|
6056
|
-
`Profile "${name}" does not exist. Create it with \`tc init --name ${name}\`.`
|
|
6057
|
-
);
|
|
6058
|
-
}
|
|
6059
|
-
return profile;
|
|
6060
|
-
}
|
|
6061
|
-
/**
|
|
6062
|
-
* Saves a profile config under the profile lock, creating the profile
|
|
6063
|
-
* directory if needed. Use `updateProfile` to change an existing profile.
|
|
6064
|
-
*/
|
|
6065
|
-
static async setProfile(name, data) {
|
|
6066
|
-
await _ProfileManager.withLock(name, async () => {
|
|
6067
|
-
await writeJson(join4(await _ProfileManager.ensureProfileDir(name), "profile.json"), data);
|
|
6068
|
-
});
|
|
6069
|
-
}
|
|
6070
|
-
/** Removes profile.json under the profile lock (rollback of a profile a failed login created). */
|
|
6071
|
-
static async removeProfileConfig(name) {
|
|
6072
|
-
await _ProfileManager.withLock(name, () => rm2(join4(PROFILES_DIR, name, "profile.json"), { force: true }));
|
|
6073
|
-
}
|
|
6074
|
-
/**
|
|
6075
|
-
* Returns true if a profile directory exists.
|
|
6076
|
-
*/
|
|
6077
|
-
static async profileExists(name) {
|
|
6078
|
-
return fileExists(join4(PROFILES_DIR, name, "profile.json"));
|
|
6079
|
-
}
|
|
6080
|
-
/**
|
|
6081
|
-
* Returns an array of profile directory names.
|
|
6082
|
-
*/
|
|
6083
|
-
static async listProfiles() {
|
|
6084
|
-
return listDirs(PROFILES_DIR);
|
|
6085
|
-
}
|
|
6086
|
-
/**
|
|
6087
|
-
* Deletes a profile. Its key, session, settings, stores and cache are
|
|
6088
|
-
* removed while holding the profile lock, so another writer's critical
|
|
6089
|
-
* section never sees them vanish midway: session and key first, settings
|
|
6090
|
-
* last, so a crash midway never leaves a session or key without its
|
|
6091
|
-
* profile. The deletion is then recorded, so a store write that waited for
|
|
6092
|
-
* the lock meanwhile refuses rather than recreating a profile with only a
|
|
6093
|
-
* session in it. `.lock` itself is left to the lock's release; the
|
|
6094
|
-
* then-empty directory is removed afterwards unless another writer took
|
|
6095
|
-
* the lock (or wrote) meanwhile. A profile directory that is a symlink is
|
|
6096
|
-
* unlinked, its target left alone.
|
|
6097
|
-
* Throws if the name is not one path segment or names the default profile.
|
|
6098
|
-
*/
|
|
6099
|
-
static async deleteProfile(name) {
|
|
6100
|
-
let profileDir;
|
|
6101
|
-
try {
|
|
6102
|
-
profileDir = profilePath(name);
|
|
6103
|
-
} catch {
|
|
6104
|
-
throw new CLIError(
|
|
6105
|
-
"INVALID_PROFILE_NAME",
|
|
6106
|
-
`Invalid profile name "${name}": a profile name is one path segment (no "/", "\\", "." or "..").`,
|
|
6107
|
-
ExitCode.USAGE_ERROR
|
|
6108
|
-
);
|
|
6109
|
-
}
|
|
6110
|
-
const config = await _ProfileManager.getConfig();
|
|
6111
|
-
if (config.defaultProfile === name) {
|
|
6112
|
-
throw new CLIError(
|
|
6113
|
-
"PROFILE_DELETE_DEFAULT",
|
|
6114
|
-
`Cannot delete the default profile "${name}". Change the default first with \`tc profile default <other>\`.`
|
|
6115
|
-
);
|
|
6116
|
-
}
|
|
6117
|
-
const kind = await lstat(profileDir).then((stats) => stats.isSymbolicLink() ? "link" : "present", (error) => {
|
|
6118
|
-
if (error.code === "ENOENT") return "missing";
|
|
6119
|
-
throw error;
|
|
6120
|
-
});
|
|
6121
|
-
if (kind === "missing") return;
|
|
6122
|
-
if (kind === "link") {
|
|
6123
|
-
await rm2(profileDir, { force: true });
|
|
6124
|
-
return;
|
|
6125
|
-
}
|
|
6126
|
-
await _ProfileManager.withLock(name, async () => {
|
|
6127
|
-
for (const file of ["session.json", "key.json"]) await rm2(join4(profileDir, file), { force: true });
|
|
6128
|
-
for (const entry of await readdir2(profileDir)) {
|
|
6129
|
-
if (entry !== ".lock" && entry !== "profile.json") await rm2(join4(profileDir, entry), { recursive: true, force: true });
|
|
6130
|
-
}
|
|
6131
|
-
await rm2(join4(profileDir, "profile.json"), { force: true });
|
|
6132
|
-
await recordProfileDeletion(name);
|
|
6133
|
-
});
|
|
6134
|
-
await rmdir(profileDir).catch((error) => {
|
|
6135
|
-
if (error.code !== "ENOENT" && error.code !== "ENOTEMPTY" && error.code !== "EEXIST") throw error;
|
|
6136
|
-
});
|
|
6137
|
-
}
|
|
6138
|
-
// ── Key management ──────────────────────────────────────────────────
|
|
6139
|
-
/**
|
|
6140
|
-
* Returns the parsed JWK for a profile, or null if no key exists.
|
|
6141
|
-
*/
|
|
6142
|
-
static async getKey(name) {
|
|
6143
|
-
return readJson(join4(PROFILES_DIR, name, "key.json"));
|
|
6144
|
-
}
|
|
6145
|
-
/**
|
|
6146
|
-
* Saves a JWK key under the profile lock (0600, in an owner-only profile
|
|
6147
|
-
* directory). Refused (PROFILE_NOT_FOUND) if the profile was deleted while
|
|
6148
|
-
* this waited for the lock, rather than leaving a key-only profile.
|
|
6149
|
-
*/
|
|
6150
|
-
static async setKey(name, jwk) {
|
|
6151
|
-
await _ProfileManager.withLock(name, async () => {
|
|
6152
|
-
await refuseWriteToDeletedProfile2(name);
|
|
6153
|
-
await writeJson(join4(await _ProfileManager.ensureProfileDir(name), "key.json"), jwk);
|
|
6154
|
-
});
|
|
6155
|
-
}
|
|
6156
|
-
/** Removes key.json under the profile lock (rollback of a key a failed login created). */
|
|
6157
|
-
static async removeKey(name) {
|
|
6158
|
-
await _ProfileManager.withLock(name, () => rm2(join4(PROFILES_DIR, name, "key.json"), { force: true }));
|
|
6159
|
-
}
|
|
6160
|
-
// ── Session management ──────────────────────────────────────────────
|
|
6161
|
-
/**
|
|
6162
|
-
* Returns the parsed session for a profile, or null if none exists.
|
|
6163
|
-
*/
|
|
6164
|
-
static async getSession(name) {
|
|
6165
|
-
return readSession(name);
|
|
6166
|
-
}
|
|
6167
|
-
/**
|
|
6168
|
-
* Saves session data for a profile.
|
|
6169
|
-
*/
|
|
6170
|
-
static async setSession(name, session) {
|
|
6171
|
-
await writeSession(name, session);
|
|
6172
|
-
}
|
|
6173
|
-
/**
|
|
6174
|
-
* Removes the session file for a profile.
|
|
6175
|
-
*/
|
|
6176
|
-
static async clearSession(name) {
|
|
6177
|
-
await removeSession(name);
|
|
6178
|
-
}
|
|
6179
|
-
// ── Cache management ────────────────────────────────────────────────
|
|
6180
|
-
/**
|
|
6181
|
-
* Returns the profile's cache directory (share history lives here),
|
|
6182
|
-
* created or tightened to 0700.
|
|
6183
|
-
*/
|
|
6184
|
-
static async getCacheDir(name) {
|
|
6185
|
-
const cacheDir = join4(await _ProfileManager.ensureProfileDir(name), "cache");
|
|
6186
|
-
await ensureDir(cacheDir);
|
|
6187
|
-
await chmod2(cacheDir, PRIVATE_DIR_MODE);
|
|
6188
|
-
return cacheDir;
|
|
6189
|
-
}
|
|
6190
|
-
// ── Resolution helpers ──────────────────────────────────────────────
|
|
6191
|
-
/**
|
|
6192
|
-
* Resolves the full CLI context from flags, env vars, and config.
|
|
6193
|
-
*
|
|
6194
|
-
* Profile resolution: options.profile > TC_PROFILE env > config.defaultProfile > "default"
|
|
6195
|
-
* Host resolution: options.host > TC_HOST env > discovered local node > profile.host > DEFAULT_HOST
|
|
6196
|
-
*
|
|
6197
|
-
* Local-node discovery (TC-106) only runs when no explicit host was given
|
|
6198
|
-
* (`--host` / `TC_HOST`); it probes configured or registered local nodes and,
|
|
6199
|
-
* after DID verification against the profile's pinned identity, prefers one
|
|
6200
|
-
* over the stored/default host. For session-using commands, it verifies the
|
|
6201
|
-
* stored session locally before probing. Loopback requires an explicit
|
|
6202
|
-
* `localNodeUrl`; disable discovery with `autoDiscoverLocalNode: false`.
|
|
6203
|
-
*/
|
|
6204
|
-
static async resolveContext(options, settings = {}) {
|
|
6205
|
-
const config = await _ProfileManager.getConfig();
|
|
6206
|
-
const profile = options.profile ?? process.env.TC_PROFILE ?? config.defaultProfile ?? DEFAULT_PROFILE;
|
|
6207
|
-
let profileHost;
|
|
6208
|
-
try {
|
|
6209
|
-
const profileConfig = await _ProfileManager.getProfile(profile);
|
|
6210
|
-
profileHost = profileConfig.host;
|
|
6211
|
-
} catch {
|
|
6212
|
-
}
|
|
6213
|
-
const explicitHost = options.host ?? process.env.TC_HOST;
|
|
6214
|
-
let host = explicitHost ?? profileHost ?? DEFAULT_HOST;
|
|
6215
|
-
let localDiscovery;
|
|
6216
|
-
if (explicitHost === void 0) {
|
|
6217
|
-
const { discoverLocalNodeHost: discoverLocalNodeHost2 } = await Promise.resolve().then(() => (init_host(), host_exports));
|
|
6218
|
-
const explicitKey = Boolean(options.privateKey || process.env.TC_PRIVATE_KEY);
|
|
6219
|
-
const discovered = await discoverLocalNodeHost2(profile, {
|
|
6220
|
-
awaitStoredSession: settings.storedSession !== "unused" && !explicitKey
|
|
6221
|
-
});
|
|
6222
|
-
if (discovered.host !== null) host = discovered.host;
|
|
6223
|
-
if (discovered.deferred) localDiscovery = { deferredFrom: host };
|
|
6224
|
-
}
|
|
6225
|
-
setActiveProfileName(profile);
|
|
6226
|
-
return {
|
|
6227
|
-
profile,
|
|
6228
|
-
host,
|
|
6229
|
-
verbose: options.verbose ?? false,
|
|
6230
|
-
noCache: options.noCache ?? false,
|
|
6231
|
-
quiet: options.quiet ?? false,
|
|
6232
|
-
...localDiscovery === void 0 ? {} : { localDiscovery }
|
|
6233
|
-
};
|
|
6234
|
-
}
|
|
6235
|
-
};
|
|
6236
|
-
}
|
|
6237
|
-
});
|
|
6238
|
-
|
|
6239
|
-
// src/index.ts
|
|
6240
|
-
init_errors();
|
|
6241
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
6242
|
-
import { Command } from "commander";
|
|
6243
|
-
|
|
6244
|
-
// src/output/banner.ts
|
|
6245
|
-
init_formatter();
|
|
6246
|
-
|
|
6247
|
-
// src/output/taglines.ts
|
|
6248
|
-
var HOLIDAY_TAGLINES = [
|
|
6249
|
-
{ month: 1, day: 1, range: 1, tagline: "New year, new keys, same cloud." },
|
|
6250
|
-
{ month: 2, day: 14, tagline: "We love your data as much as you do." },
|
|
6251
|
-
{ month: 3, day: 14, tagline: "3.14159 reasons to encrypt everything." },
|
|
6252
|
-
{ month: 5, day: 4, tagline: "May the fourth be with your keys." },
|
|
6253
|
-
{ month: 10, day: 31, tagline: "Nothing scarier than plaintext secrets." },
|
|
6254
|
-
{ month: 12, day: 25, range: 2, tagline: "Unwrap your data, not your keys." },
|
|
6255
|
-
{ month: 12, day: 31, tagline: "Encrypt your resolutions." }
|
|
6256
|
-
];
|
|
6257
|
-
var TAGLINES = [
|
|
6258
|
-
// Professional
|
|
6259
|
-
"Your data, your keys, your cloud.",
|
|
6260
|
-
"Self-sovereign storage for the modern web.",
|
|
6261
|
-
"The cloud you actually own.",
|
|
6262
|
-
"Encrypted by default, decentralized by design.",
|
|
6263
|
-
"Where your data answers only to you.",
|
|
6264
|
-
"End-to-end encrypted. No exceptions.",
|
|
6265
|
-
"Like S3 but you hold the keys.",
|
|
6266
|
-
"Privacy isn't a feature. It's the architecture.",
|
|
6267
|
-
"Sovereign storage, zero knowledge.",
|
|
6268
|
-
"Your .env is safe here \u2014 we use real cryptography.",
|
|
6269
|
-
// Playful / nerdy
|
|
6270
|
-
"UCAN do anything.",
|
|
6271
|
-
"Keys generated, delegations granted, data liberated.",
|
|
6272
|
-
"Decentralized storage, centralized vibes.",
|
|
6273
|
-
"Trust nobody, delegate everything.",
|
|
6274
|
-
"sudo make me a sandwich, encrypted.",
|
|
6275
|
-
"Have you tried turning your keys off and on again?",
|
|
6276
|
-
"All your base are belong to you.",
|
|
6277
|
-
"In UCAN we trust.",
|
|
6278
|
-
"0 knowledge, 100% confidence.",
|
|
6279
|
-
"Keeping secrets since 2024."
|
|
6280
|
-
];
|
|
6281
|
-
function getHolidayTagline() {
|
|
6282
|
-
const now = /* @__PURE__ */ new Date();
|
|
6283
|
-
const month = now.getMonth() + 1;
|
|
6284
|
-
const day = now.getDate();
|
|
6285
|
-
for (const h of HOLIDAY_TAGLINES) {
|
|
6286
|
-
const range = h.range ?? 0;
|
|
6287
|
-
if (h.month === month && Math.abs(day - h.day) <= range) {
|
|
6288
|
-
return h.tagline;
|
|
6289
|
-
}
|
|
6290
|
-
}
|
|
6291
|
-
return null;
|
|
6292
|
-
}
|
|
6293
|
-
function pickTagline() {
|
|
6294
|
-
const holiday = getHolidayTagline();
|
|
6295
|
-
if (holiday) return holiday;
|
|
6296
|
-
return TAGLINES[Math.floor(Math.random() * TAGLINES.length)];
|
|
6297
|
-
}
|
|
6298
|
-
|
|
6299
|
-
// src/output/banner.ts
|
|
6300
|
-
init_theme();
|
|
6301
|
-
import { execSync } from "child_process";
|
|
6302
|
-
var bannerEmitted = false;
|
|
6303
|
-
function resolveCommitHash() {
|
|
6304
|
-
try {
|
|
6305
|
-
return execSync("git rev-parse --short HEAD", {
|
|
6306
|
-
encoding: "utf-8",
|
|
6307
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
6308
|
-
}).trim() || null;
|
|
6309
|
-
} catch {
|
|
6310
|
-
return null;
|
|
6311
|
-
}
|
|
6312
|
-
}
|
|
6313
|
-
function formatBannerLine(version2) {
|
|
6314
|
-
const commit = resolveCommitHash();
|
|
6315
|
-
const tagline = pickTagline();
|
|
6316
|
-
const versionPart = `tc v${version2}`;
|
|
6317
|
-
const commitPart = commit ? ` (${commit})` : "";
|
|
6318
|
-
const separator = " \u2014 ";
|
|
6319
|
-
if (!isInteractive()) {
|
|
6320
|
-
return `${versionPart}${commitPart}${separator}${tagline}`;
|
|
6321
|
-
}
|
|
6322
|
-
return [
|
|
6323
|
-
theme.brand("\u2601\uFE0F tc"),
|
|
6324
|
-
" ",
|
|
6325
|
-
theme.muted(`v${version2}`),
|
|
6326
|
-
commit ? theme.dim(` (${commit})`) : "",
|
|
6327
|
-
theme.dim(separator),
|
|
6328
|
-
theme.primary(tagline)
|
|
6329
|
-
].join("");
|
|
6330
|
-
}
|
|
6331
|
-
function emitBanner(version2) {
|
|
6332
|
-
if (bannerEmitted) return;
|
|
6333
|
-
if (shouldOutputJson()) return;
|
|
6334
|
-
if (process.env.TC_HIDE_BANNER === "1") return;
|
|
6335
|
-
bannerEmitted = true;
|
|
6336
|
-
process.stderr.write(formatBannerLine(version2) + "\n\n");
|
|
6337
|
-
}
|
|
6338
|
-
|
|
6339
|
-
// src/index.ts
|
|
6340
|
-
init_theme();
|
|
6341
|
-
init_formatter();
|
|
6342
|
-
init_profiles();
|
|
6343
|
-
|
|
6344
|
-
// ../share-sdk/dist/index.js
|
|
6345
|
-
init_sha2();
|
|
6346
|
-
|
|
6347
|
-
// ../../node_modules/@noble/curves/esm/ed25519.js
|
|
6348
|
-
init_sha2();
|
|
6349
|
-
init_utils();
|
|
6350
|
-
|
|
6351
|
-
// ../../node_modules/@noble/curves/esm/utils.js
|
|
6352
|
-
init_utils();
|
|
6353
|
-
init_utils();
|
|
6354
|
-
var _0n = /* @__PURE__ */ BigInt(0);
|
|
6355
|
-
var _1n = /* @__PURE__ */ BigInt(1);
|
|
6356
|
-
function _abool2(value, title = "") {
|
|
6357
|
-
if (typeof value !== "boolean") {
|
|
6358
|
-
const prefix = title && `"${title}"`;
|
|
6359
|
-
throw new Error(prefix + "expected boolean, got type=" + typeof value);
|
|
6360
|
-
}
|
|
6361
|
-
return value;
|
|
6362
|
-
}
|
|
6363
|
-
function _abytes2(value, length4, title = "") {
|
|
6364
|
-
const bytes = isBytes(value);
|
|
6365
|
-
const len = value?.length;
|
|
6366
|
-
const needsLen = length4 !== void 0;
|
|
6367
|
-
if (!bytes || needsLen && len !== length4) {
|
|
6368
|
-
const prefix = title && `"${title}" `;
|
|
6369
|
-
const ofLen = needsLen ? ` of length ${length4}` : "";
|
|
6370
|
-
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
6371
|
-
throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
6372
|
-
}
|
|
6373
|
-
return value;
|
|
6374
|
-
}
|
|
6375
|
-
function hexToNumber(hex3) {
|
|
6376
|
-
if (typeof hex3 !== "string")
|
|
6377
|
-
throw new Error("hex string expected, got " + typeof hex3);
|
|
6378
|
-
return hex3 === "" ? _0n : BigInt("0x" + hex3);
|
|
6379
|
-
}
|
|
6380
|
-
function bytesToNumberBE(bytes) {
|
|
6381
|
-
return hexToNumber(bytesToHex(bytes));
|
|
6382
|
-
}
|
|
6383
|
-
function bytesToNumberLE(bytes) {
|
|
6384
|
-
abytes(bytes);
|
|
6385
|
-
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
|
|
6386
|
-
}
|
|
6387
|
-
function numberToBytesBE(n, len) {
|
|
6388
|
-
return hexToBytes(n.toString(16).padStart(len * 2, "0"));
|
|
6389
|
-
}
|
|
6390
|
-
function numberToBytesLE(n, len) {
|
|
6391
|
-
return numberToBytesBE(n, len).reverse();
|
|
6392
|
-
}
|
|
6393
|
-
function ensureBytes(title, hex3, expectedLength) {
|
|
6394
|
-
let res;
|
|
6395
|
-
if (typeof hex3 === "string") {
|
|
6396
|
-
try {
|
|
6397
|
-
res = hexToBytes(hex3);
|
|
6398
|
-
} catch (e) {
|
|
6399
|
-
throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
|
|
6400
|
-
}
|
|
6401
|
-
} else if (isBytes(hex3)) {
|
|
6402
|
-
res = Uint8Array.from(hex3);
|
|
6403
|
-
} else {
|
|
6404
|
-
throw new Error(title + " must be hex string or Uint8Array");
|
|
6405
|
-
}
|
|
6406
|
-
const len = res.length;
|
|
6407
|
-
if (typeof expectedLength === "number" && len !== expectedLength)
|
|
6408
|
-
throw new Error(title + " of length " + expectedLength + " expected, got " + len);
|
|
6409
|
-
return res;
|
|
6410
|
-
}
|
|
6411
|
-
function equalBytes(a, b) {
|
|
6412
|
-
if (a.length !== b.length)
|
|
6413
|
-
return false;
|
|
6414
|
-
let diff = 0;
|
|
6415
|
-
for (let i = 0; i < a.length; i++)
|
|
6416
|
-
diff |= a[i] ^ b[i];
|
|
6417
|
-
return diff === 0;
|
|
6418
|
-
}
|
|
6419
|
-
function copyBytes(bytes) {
|
|
6420
|
-
return Uint8Array.from(bytes);
|
|
6421
|
-
}
|
|
6422
|
-
var isPosBig = (n) => typeof n === "bigint" && _0n <= n;
|
|
6423
|
-
function inRange(n, min, max) {
|
|
6424
|
-
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
|
|
6425
|
-
}
|
|
6426
|
-
function aInRange(title, n, min, max) {
|
|
6427
|
-
if (!inRange(n, min, max))
|
|
6428
|
-
throw new Error("expected valid " + title + ": " + min + " <= n < " + max + ", got " + n);
|
|
6429
|
-
}
|
|
6430
|
-
function bitLen(n) {
|
|
6431
|
-
let len;
|
|
6432
|
-
for (len = 0; n > _0n; n >>= _1n, len += 1)
|
|
6433
|
-
;
|
|
6434
|
-
return len;
|
|
6435
|
-
}
|
|
6436
|
-
var bitMask = (n) => (_1n << BigInt(n)) - _1n;
|
|
6437
|
-
function _validateObject(object3, fields, optFields = {}) {
|
|
6438
|
-
if (!object3 || typeof object3 !== "object")
|
|
6439
|
-
throw new Error("expected valid options object");
|
|
6440
|
-
function checkField(fieldName, expectedType, isOpt) {
|
|
6441
|
-
const val = object3[fieldName];
|
|
6442
|
-
if (isOpt && val === void 0)
|
|
6443
|
-
return;
|
|
6444
|
-
const current = typeof val;
|
|
6445
|
-
if (current !== expectedType || val === null)
|
|
6446
|
-
throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
|
|
6447
|
-
}
|
|
6448
|
-
Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
|
|
6449
|
-
Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
|
|
6450
|
-
}
|
|
6451
|
-
var notImplemented = () => {
|
|
6452
|
-
throw new Error("not implemented");
|
|
6453
|
-
};
|
|
6454
|
-
function memoized(fn) {
|
|
6455
|
-
const map = /* @__PURE__ */ new WeakMap();
|
|
6456
|
-
return (arg, ...args) => {
|
|
6457
|
-
const val = map.get(arg);
|
|
6458
|
-
if (val !== void 0)
|
|
6459
|
-
return val;
|
|
6460
|
-
const computed = fn(arg, ...args);
|
|
6461
|
-
map.set(arg, computed);
|
|
6462
|
-
return computed;
|
|
6463
|
-
};
|
|
6464
|
-
}
|
|
6465
|
-
|
|
6466
|
-
// ../../node_modules/@noble/curves/esm/abstract/modular.js
|
|
6467
|
-
var _0n2 = BigInt(0);
|
|
6468
|
-
var _1n2 = BigInt(1);
|
|
6469
|
-
var _2n = /* @__PURE__ */ BigInt(2);
|
|
6470
|
-
var _3n = /* @__PURE__ */ BigInt(3);
|
|
6471
|
-
var _4n = /* @__PURE__ */ BigInt(4);
|
|
6472
|
-
var _5n = /* @__PURE__ */ BigInt(5);
|
|
6473
|
-
var _7n = /* @__PURE__ */ BigInt(7);
|
|
6474
|
-
var _8n = /* @__PURE__ */ BigInt(8);
|
|
6475
|
-
var _9n = /* @__PURE__ */ BigInt(9);
|
|
6476
|
-
var _16n = /* @__PURE__ */ BigInt(16);
|
|
6477
|
-
function mod(a, b) {
|
|
6478
|
-
const result = a % b;
|
|
6479
|
-
return result >= _0n2 ? result : b + result;
|
|
6480
|
-
}
|
|
6481
|
-
function pow2(x, power, modulo) {
|
|
6482
|
-
let res = x;
|
|
6483
|
-
while (power-- > _0n2) {
|
|
6484
|
-
res *= res;
|
|
6485
|
-
res %= modulo;
|
|
6486
|
-
}
|
|
6487
|
-
return res;
|
|
6488
|
-
}
|
|
6489
|
-
function invert(number, modulo) {
|
|
6490
|
-
if (number === _0n2)
|
|
6491
|
-
throw new Error("invert: expected non-zero number");
|
|
6492
|
-
if (modulo <= _0n2)
|
|
6493
|
-
throw new Error("invert: expected positive modulus, got " + modulo);
|
|
6494
|
-
let a = mod(number, modulo);
|
|
6495
|
-
let b = modulo;
|
|
6496
|
-
let x = _0n2, y = _1n2, u = _1n2, v = _0n2;
|
|
6497
|
-
while (a !== _0n2) {
|
|
6498
|
-
const q = b / a;
|
|
6499
|
-
const r = b % a;
|
|
6500
|
-
const m = x - u * q;
|
|
6501
|
-
const n = y - v * q;
|
|
6502
|
-
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
6503
|
-
}
|
|
6504
|
-
const gcd = b;
|
|
6505
|
-
if (gcd !== _1n2)
|
|
6506
|
-
throw new Error("invert: does not exist");
|
|
6507
|
-
return mod(x, modulo);
|
|
6508
|
-
}
|
|
6509
|
-
function assertIsSquare(Fp2, root, n) {
|
|
6510
|
-
if (!Fp2.eql(Fp2.sqr(root), n))
|
|
6511
|
-
throw new Error("Cannot find square root");
|
|
6512
|
-
}
|
|
6513
|
-
function sqrt3mod4(Fp2, n) {
|
|
6514
|
-
const p1div4 = (Fp2.ORDER + _1n2) / _4n;
|
|
6515
|
-
const root = Fp2.pow(n, p1div4);
|
|
6516
|
-
assertIsSquare(Fp2, root, n);
|
|
6517
|
-
return root;
|
|
6518
|
-
}
|
|
6519
|
-
function sqrt5mod8(Fp2, n) {
|
|
6520
|
-
const p5div8 = (Fp2.ORDER - _5n) / _8n;
|
|
6521
|
-
const n2 = Fp2.mul(n, _2n);
|
|
6522
|
-
const v = Fp2.pow(n2, p5div8);
|
|
6523
|
-
const nv = Fp2.mul(n, v);
|
|
6524
|
-
const i = Fp2.mul(Fp2.mul(nv, _2n), v);
|
|
6525
|
-
const root = Fp2.mul(nv, Fp2.sub(i, Fp2.ONE));
|
|
6526
|
-
assertIsSquare(Fp2, root, n);
|
|
6527
|
-
return root;
|
|
6528
|
-
}
|
|
6529
|
-
function sqrt9mod16(P) {
|
|
6530
|
-
const Fp_ = Field(P);
|
|
6531
|
-
const tn = tonelliShanks(P);
|
|
6532
|
-
const c1 = tn(Fp_, Fp_.neg(Fp_.ONE));
|
|
6533
|
-
const c2 = tn(Fp_, c1);
|
|
6534
|
-
const c3 = tn(Fp_, Fp_.neg(c1));
|
|
6535
|
-
const c4 = (P + _7n) / _16n;
|
|
6536
|
-
return (Fp2, n) => {
|
|
6537
|
-
let tv1 = Fp2.pow(n, c4);
|
|
6538
|
-
let tv2 = Fp2.mul(tv1, c1);
|
|
6539
|
-
const tv3 = Fp2.mul(tv1, c2);
|
|
6540
|
-
const tv4 = Fp2.mul(tv1, c3);
|
|
6541
|
-
const e1 = Fp2.eql(Fp2.sqr(tv2), n);
|
|
6542
|
-
const e2 = Fp2.eql(Fp2.sqr(tv3), n);
|
|
6543
|
-
tv1 = Fp2.cmov(tv1, tv2, e1);
|
|
6544
|
-
tv2 = Fp2.cmov(tv4, tv3, e2);
|
|
6545
|
-
const e3 = Fp2.eql(Fp2.sqr(tv2), n);
|
|
6546
|
-
const root = Fp2.cmov(tv1, tv2, e3);
|
|
6547
|
-
assertIsSquare(Fp2, root, n);
|
|
6548
|
-
return root;
|
|
6549
|
-
};
|
|
6550
|
-
}
|
|
6551
|
-
function tonelliShanks(P) {
|
|
6552
|
-
if (P < _3n)
|
|
6553
|
-
throw new Error("sqrt is not defined for small field");
|
|
6554
|
-
let Q = P - _1n2;
|
|
6555
|
-
let S = 0;
|
|
6556
|
-
while (Q % _2n === _0n2) {
|
|
6557
|
-
Q /= _2n;
|
|
6558
|
-
S++;
|
|
6357
|
+
function tonelliShanks(P) {
|
|
6358
|
+
if (P < _3n)
|
|
6359
|
+
throw new Error("sqrt is not defined for small field");
|
|
6360
|
+
let Q = P - _1n2;
|
|
6361
|
+
let S = 0;
|
|
6362
|
+
while (Q % _2n === _0n2) {
|
|
6363
|
+
Q /= _2n;
|
|
6364
|
+
S++;
|
|
6559
6365
|
}
|
|
6560
6366
|
let Z = _2n;
|
|
6561
6367
|
const _Fp = Field(P);
|
|
@@ -6606,26 +6412,6 @@ function FpSqrt(P) {
|
|
|
6606
6412
|
return sqrt9mod16(P);
|
|
6607
6413
|
return tonelliShanks(P);
|
|
6608
6414
|
}
|
|
6609
|
-
var isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n2) === _1n2;
|
|
6610
|
-
var FIELD_FIELDS = [
|
|
6611
|
-
"create",
|
|
6612
|
-
"isValid",
|
|
6613
|
-
"is0",
|
|
6614
|
-
"neg",
|
|
6615
|
-
"inv",
|
|
6616
|
-
"sqrt",
|
|
6617
|
-
"sqr",
|
|
6618
|
-
"eql",
|
|
6619
|
-
"add",
|
|
6620
|
-
"sub",
|
|
6621
|
-
"mul",
|
|
6622
|
-
"pow",
|
|
6623
|
-
"div",
|
|
6624
|
-
"addN",
|
|
6625
|
-
"subN",
|
|
6626
|
-
"mulN",
|
|
6627
|
-
"sqrN"
|
|
6628
|
-
];
|
|
6629
6415
|
function validateField(field) {
|
|
6630
6416
|
const initial = {
|
|
6631
6417
|
ORDER: "bigint",
|
|
@@ -6788,10 +6574,45 @@ function Field(ORDER, bitLenOrOpts, isLE2 = false, opts = {}) {
|
|
|
6788
6574
|
});
|
|
6789
6575
|
return Object.freeze(f);
|
|
6790
6576
|
}
|
|
6577
|
+
var _0n2, _1n2, _2n, _3n, _4n, _5n, _7n, _8n, _9n, _16n, isNegativeLE, FIELD_FIELDS;
|
|
6578
|
+
var init_modular = __esm({
|
|
6579
|
+
"../../node_modules/@noble/curves/esm/abstract/modular.js"() {
|
|
6580
|
+
"use strict";
|
|
6581
|
+
init_utils2();
|
|
6582
|
+
_0n2 = BigInt(0);
|
|
6583
|
+
_1n2 = BigInt(1);
|
|
6584
|
+
_2n = /* @__PURE__ */ BigInt(2);
|
|
6585
|
+
_3n = /* @__PURE__ */ BigInt(3);
|
|
6586
|
+
_4n = /* @__PURE__ */ BigInt(4);
|
|
6587
|
+
_5n = /* @__PURE__ */ BigInt(5);
|
|
6588
|
+
_7n = /* @__PURE__ */ BigInt(7);
|
|
6589
|
+
_8n = /* @__PURE__ */ BigInt(8);
|
|
6590
|
+
_9n = /* @__PURE__ */ BigInt(9);
|
|
6591
|
+
_16n = /* @__PURE__ */ BigInt(16);
|
|
6592
|
+
isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n2) === _1n2;
|
|
6593
|
+
FIELD_FIELDS = [
|
|
6594
|
+
"create",
|
|
6595
|
+
"isValid",
|
|
6596
|
+
"is0",
|
|
6597
|
+
"neg",
|
|
6598
|
+
"inv",
|
|
6599
|
+
"sqrt",
|
|
6600
|
+
"sqr",
|
|
6601
|
+
"eql",
|
|
6602
|
+
"add",
|
|
6603
|
+
"sub",
|
|
6604
|
+
"mul",
|
|
6605
|
+
"pow",
|
|
6606
|
+
"div",
|
|
6607
|
+
"addN",
|
|
6608
|
+
"subN",
|
|
6609
|
+
"mulN",
|
|
6610
|
+
"sqrN"
|
|
6611
|
+
];
|
|
6612
|
+
}
|
|
6613
|
+
});
|
|
6791
6614
|
|
|
6792
6615
|
// ../../node_modules/@noble/curves/esm/abstract/curve.js
|
|
6793
|
-
var _0n3 = BigInt(0);
|
|
6794
|
-
var _1n3 = BigInt(1);
|
|
6795
6616
|
function negateCt(condition, item) {
|
|
6796
6617
|
const neg = item.negate();
|
|
6797
6618
|
return condition ? neg : item;
|
|
@@ -6845,8 +6666,6 @@ function validateMSMScalars(scalars, field) {
|
|
|
6845
6666
|
throw new Error("invalid scalar at index " + i);
|
|
6846
6667
|
});
|
|
6847
6668
|
}
|
|
6848
|
-
var pointPrecomputes = /* @__PURE__ */ new WeakMap();
|
|
6849
|
-
var pointWindowSizes = /* @__PURE__ */ new WeakMap();
|
|
6850
6669
|
function getW(P) {
|
|
6851
6670
|
return pointWindowSizes.get(P) || 1;
|
|
6852
6671
|
}
|
|
@@ -6854,133 +6673,6 @@ function assert0(n) {
|
|
|
6854
6673
|
if (n !== _0n3)
|
|
6855
6674
|
throw new Error("invalid wNAF");
|
|
6856
6675
|
}
|
|
6857
|
-
var wNAF = class {
|
|
6858
|
-
// Parametrized with a given Point class (not individual point)
|
|
6859
|
-
constructor(Point, bits) {
|
|
6860
|
-
this.BASE = Point.BASE;
|
|
6861
|
-
this.ZERO = Point.ZERO;
|
|
6862
|
-
this.Fn = Point.Fn;
|
|
6863
|
-
this.bits = bits;
|
|
6864
|
-
}
|
|
6865
|
-
// non-const time multiplication ladder
|
|
6866
|
-
_unsafeLadder(elm, n, p = this.ZERO) {
|
|
6867
|
-
let d = elm;
|
|
6868
|
-
while (n > _0n3) {
|
|
6869
|
-
if (n & _1n3)
|
|
6870
|
-
p = p.add(d);
|
|
6871
|
-
d = d.double();
|
|
6872
|
-
n >>= _1n3;
|
|
6873
|
-
}
|
|
6874
|
-
return p;
|
|
6875
|
-
}
|
|
6876
|
-
/**
|
|
6877
|
-
* Creates a wNAF precomputation window. Used for caching.
|
|
6878
|
-
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
6879
|
-
* Number of precomputed points depends on the curve size:
|
|
6880
|
-
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
|
6881
|
-
* - 𝑊 is the window size
|
|
6882
|
-
* - 𝑛 is the bitlength of the curve order.
|
|
6883
|
-
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
|
6884
|
-
* @param point Point instance
|
|
6885
|
-
* @param W window size
|
|
6886
|
-
* @returns precomputed point tables flattened to a single array
|
|
6887
|
-
*/
|
|
6888
|
-
precomputeWindow(point, W) {
|
|
6889
|
-
const { windows, windowSize } = calcWOpts(W, this.bits);
|
|
6890
|
-
const points = [];
|
|
6891
|
-
let p = point;
|
|
6892
|
-
let base4 = p;
|
|
6893
|
-
for (let window = 0; window < windows; window++) {
|
|
6894
|
-
base4 = p;
|
|
6895
|
-
points.push(base4);
|
|
6896
|
-
for (let i = 1; i < windowSize; i++) {
|
|
6897
|
-
base4 = base4.add(p);
|
|
6898
|
-
points.push(base4);
|
|
6899
|
-
}
|
|
6900
|
-
p = base4.double();
|
|
6901
|
-
}
|
|
6902
|
-
return points;
|
|
6903
|
-
}
|
|
6904
|
-
/**
|
|
6905
|
-
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
|
6906
|
-
* More compact implementation:
|
|
6907
|
-
* https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
|
|
6908
|
-
* @returns real and fake (for const-time) points
|
|
6909
|
-
*/
|
|
6910
|
-
wNAF(W, precomputes, n) {
|
|
6911
|
-
if (!this.Fn.isValid(n))
|
|
6912
|
-
throw new Error("invalid scalar");
|
|
6913
|
-
let p = this.ZERO;
|
|
6914
|
-
let f = this.BASE;
|
|
6915
|
-
const wo = calcWOpts(W, this.bits);
|
|
6916
|
-
for (let window = 0; window < wo.windows; window++) {
|
|
6917
|
-
const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
|
|
6918
|
-
n = nextN;
|
|
6919
|
-
if (isZero) {
|
|
6920
|
-
f = f.add(negateCt(isNegF, precomputes[offsetF]));
|
|
6921
|
-
} else {
|
|
6922
|
-
p = p.add(negateCt(isNeg, precomputes[offset]));
|
|
6923
|
-
}
|
|
6924
|
-
}
|
|
6925
|
-
assert0(n);
|
|
6926
|
-
return { p, f };
|
|
6927
|
-
}
|
|
6928
|
-
/**
|
|
6929
|
-
* Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
|
|
6930
|
-
* @param acc accumulator point to add result of multiplication
|
|
6931
|
-
* @returns point
|
|
6932
|
-
*/
|
|
6933
|
-
wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
|
|
6934
|
-
const wo = calcWOpts(W, this.bits);
|
|
6935
|
-
for (let window = 0; window < wo.windows; window++) {
|
|
6936
|
-
if (n === _0n3)
|
|
6937
|
-
break;
|
|
6938
|
-
const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
|
|
6939
|
-
n = nextN;
|
|
6940
|
-
if (isZero) {
|
|
6941
|
-
continue;
|
|
6942
|
-
} else {
|
|
6943
|
-
const item = precomputes[offset];
|
|
6944
|
-
acc = acc.add(isNeg ? item.negate() : item);
|
|
6945
|
-
}
|
|
6946
|
-
}
|
|
6947
|
-
assert0(n);
|
|
6948
|
-
return acc;
|
|
6949
|
-
}
|
|
6950
|
-
getPrecomputes(W, point, transform) {
|
|
6951
|
-
let comp = pointPrecomputes.get(point);
|
|
6952
|
-
if (!comp) {
|
|
6953
|
-
comp = this.precomputeWindow(point, W);
|
|
6954
|
-
if (W !== 1) {
|
|
6955
|
-
if (typeof transform === "function")
|
|
6956
|
-
comp = transform(comp);
|
|
6957
|
-
pointPrecomputes.set(point, comp);
|
|
6958
|
-
}
|
|
6959
|
-
}
|
|
6960
|
-
return comp;
|
|
6961
|
-
}
|
|
6962
|
-
cached(point, scalar, transform) {
|
|
6963
|
-
const W = getW(point);
|
|
6964
|
-
return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
|
|
6965
|
-
}
|
|
6966
|
-
unsafe(point, scalar, transform, prev) {
|
|
6967
|
-
const W = getW(point);
|
|
6968
|
-
if (W === 1)
|
|
6969
|
-
return this._unsafeLadder(point, scalar, prev);
|
|
6970
|
-
return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
|
|
6971
|
-
}
|
|
6972
|
-
// We calculate precomputes for elliptic curve point multiplication
|
|
6973
|
-
// using windowed method. This specifies window size and
|
|
6974
|
-
// stores precomputed values. Usually only base point would be precomputed.
|
|
6975
|
-
createCache(P, W) {
|
|
6976
|
-
validateW(W, this.bits);
|
|
6977
|
-
pointWindowSizes.set(P, W);
|
|
6978
|
-
pointPrecomputes.delete(P);
|
|
6979
|
-
}
|
|
6980
|
-
hasCache(elm) {
|
|
6981
|
-
return getW(elm) !== 1;
|
|
6982
|
-
}
|
|
6983
|
-
};
|
|
6984
6676
|
function pippenger(c, fieldN, points, scalars) {
|
|
6985
6677
|
validateMSMPoints(points, c);
|
|
6986
6678
|
validateMSMScalars(scalars, fieldN);
|
|
@@ -7051,12 +6743,147 @@ function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
|
|
|
7051
6743
|
CURVE = Object.freeze(Object.assign({}, CURVE));
|
|
7052
6744
|
return { CURVE, Fp: Fp2, Fn: Fn2 };
|
|
7053
6745
|
}
|
|
6746
|
+
var _0n3, _1n3, pointPrecomputes, pointWindowSizes, wNAF;
|
|
6747
|
+
var init_curve = __esm({
|
|
6748
|
+
"../../node_modules/@noble/curves/esm/abstract/curve.js"() {
|
|
6749
|
+
"use strict";
|
|
6750
|
+
init_utils2();
|
|
6751
|
+
init_modular();
|
|
6752
|
+
_0n3 = BigInt(0);
|
|
6753
|
+
_1n3 = BigInt(1);
|
|
6754
|
+
pointPrecomputes = /* @__PURE__ */ new WeakMap();
|
|
6755
|
+
pointWindowSizes = /* @__PURE__ */ new WeakMap();
|
|
6756
|
+
wNAF = class {
|
|
6757
|
+
// Parametrized with a given Point class (not individual point)
|
|
6758
|
+
constructor(Point, bits) {
|
|
6759
|
+
this.BASE = Point.BASE;
|
|
6760
|
+
this.ZERO = Point.ZERO;
|
|
6761
|
+
this.Fn = Point.Fn;
|
|
6762
|
+
this.bits = bits;
|
|
6763
|
+
}
|
|
6764
|
+
// non-const time multiplication ladder
|
|
6765
|
+
_unsafeLadder(elm, n, p = this.ZERO) {
|
|
6766
|
+
let d = elm;
|
|
6767
|
+
while (n > _0n3) {
|
|
6768
|
+
if (n & _1n3)
|
|
6769
|
+
p = p.add(d);
|
|
6770
|
+
d = d.double();
|
|
6771
|
+
n >>= _1n3;
|
|
6772
|
+
}
|
|
6773
|
+
return p;
|
|
6774
|
+
}
|
|
6775
|
+
/**
|
|
6776
|
+
* Creates a wNAF precomputation window. Used for caching.
|
|
6777
|
+
* Default window size is set by `utils.precompute()` and is equal to 8.
|
|
6778
|
+
* Number of precomputed points depends on the curve size:
|
|
6779
|
+
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
|
|
6780
|
+
* - 𝑊 is the window size
|
|
6781
|
+
* - 𝑛 is the bitlength of the curve order.
|
|
6782
|
+
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
|
6783
|
+
* @param point Point instance
|
|
6784
|
+
* @param W window size
|
|
6785
|
+
* @returns precomputed point tables flattened to a single array
|
|
6786
|
+
*/
|
|
6787
|
+
precomputeWindow(point, W) {
|
|
6788
|
+
const { windows, windowSize } = calcWOpts(W, this.bits);
|
|
6789
|
+
const points = [];
|
|
6790
|
+
let p = point;
|
|
6791
|
+
let base4 = p;
|
|
6792
|
+
for (let window = 0; window < windows; window++) {
|
|
6793
|
+
base4 = p;
|
|
6794
|
+
points.push(base4);
|
|
6795
|
+
for (let i = 1; i < windowSize; i++) {
|
|
6796
|
+
base4 = base4.add(p);
|
|
6797
|
+
points.push(base4);
|
|
6798
|
+
}
|
|
6799
|
+
p = base4.double();
|
|
6800
|
+
}
|
|
6801
|
+
return points;
|
|
6802
|
+
}
|
|
6803
|
+
/**
|
|
6804
|
+
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
|
|
6805
|
+
* More compact implementation:
|
|
6806
|
+
* https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
|
|
6807
|
+
* @returns real and fake (for const-time) points
|
|
6808
|
+
*/
|
|
6809
|
+
wNAF(W, precomputes, n) {
|
|
6810
|
+
if (!this.Fn.isValid(n))
|
|
6811
|
+
throw new Error("invalid scalar");
|
|
6812
|
+
let p = this.ZERO;
|
|
6813
|
+
let f = this.BASE;
|
|
6814
|
+
const wo = calcWOpts(W, this.bits);
|
|
6815
|
+
for (let window = 0; window < wo.windows; window++) {
|
|
6816
|
+
const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
|
|
6817
|
+
n = nextN;
|
|
6818
|
+
if (isZero) {
|
|
6819
|
+
f = f.add(negateCt(isNegF, precomputes[offsetF]));
|
|
6820
|
+
} else {
|
|
6821
|
+
p = p.add(negateCt(isNeg, precomputes[offset]));
|
|
6822
|
+
}
|
|
6823
|
+
}
|
|
6824
|
+
assert0(n);
|
|
6825
|
+
return { p, f };
|
|
6826
|
+
}
|
|
6827
|
+
/**
|
|
6828
|
+
* Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
|
|
6829
|
+
* @param acc accumulator point to add result of multiplication
|
|
6830
|
+
* @returns point
|
|
6831
|
+
*/
|
|
6832
|
+
wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
|
|
6833
|
+
const wo = calcWOpts(W, this.bits);
|
|
6834
|
+
for (let window = 0; window < wo.windows; window++) {
|
|
6835
|
+
if (n === _0n3)
|
|
6836
|
+
break;
|
|
6837
|
+
const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
|
|
6838
|
+
n = nextN;
|
|
6839
|
+
if (isZero) {
|
|
6840
|
+
continue;
|
|
6841
|
+
} else {
|
|
6842
|
+
const item = precomputes[offset];
|
|
6843
|
+
acc = acc.add(isNeg ? item.negate() : item);
|
|
6844
|
+
}
|
|
6845
|
+
}
|
|
6846
|
+
assert0(n);
|
|
6847
|
+
return acc;
|
|
6848
|
+
}
|
|
6849
|
+
getPrecomputes(W, point, transform) {
|
|
6850
|
+
let comp = pointPrecomputes.get(point);
|
|
6851
|
+
if (!comp) {
|
|
6852
|
+
comp = this.precomputeWindow(point, W);
|
|
6853
|
+
if (W !== 1) {
|
|
6854
|
+
if (typeof transform === "function")
|
|
6855
|
+
comp = transform(comp);
|
|
6856
|
+
pointPrecomputes.set(point, comp);
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
return comp;
|
|
6860
|
+
}
|
|
6861
|
+
cached(point, scalar, transform) {
|
|
6862
|
+
const W = getW(point);
|
|
6863
|
+
return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
|
|
6864
|
+
}
|
|
6865
|
+
unsafe(point, scalar, transform, prev) {
|
|
6866
|
+
const W = getW(point);
|
|
6867
|
+
if (W === 1)
|
|
6868
|
+
return this._unsafeLadder(point, scalar, prev);
|
|
6869
|
+
return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
|
|
6870
|
+
}
|
|
6871
|
+
// We calculate precomputes for elliptic curve point multiplication
|
|
6872
|
+
// using windowed method. This specifies window size and
|
|
6873
|
+
// stores precomputed values. Usually only base point would be precomputed.
|
|
6874
|
+
createCache(P, W) {
|
|
6875
|
+
validateW(W, this.bits);
|
|
6876
|
+
pointWindowSizes.set(P, W);
|
|
6877
|
+
pointPrecomputes.delete(P);
|
|
6878
|
+
}
|
|
6879
|
+
hasCache(elm) {
|
|
6880
|
+
return getW(elm) !== 1;
|
|
6881
|
+
}
|
|
6882
|
+
};
|
|
6883
|
+
}
|
|
6884
|
+
});
|
|
7054
6885
|
|
|
7055
6886
|
// ../../node_modules/@noble/curves/esm/abstract/edwards.js
|
|
7056
|
-
var _0n4 = BigInt(0);
|
|
7057
|
-
var _1n4 = BigInt(1);
|
|
7058
|
-
var _2n2 = BigInt(2);
|
|
7059
|
-
var _8n2 = BigInt(8);
|
|
7060
6887
|
function isEdValidXY(Fp2, CURVE, x, y) {
|
|
7061
6888
|
const x2 = Fp2.sqr(x);
|
|
7062
6889
|
const y2 = Fp2.sqr(y);
|
|
@@ -7340,828 +7167,1513 @@ function edwards(params, extraOpts = {}) {
|
|
|
7340
7167
|
Point.BASE.precompute(8);
|
|
7341
7168
|
return Point;
|
|
7342
7169
|
}
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
}
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
}
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7170
|
+
function eddsa(Point, cHash, eddsaOpts = {}) {
|
|
7171
|
+
if (typeof cHash !== "function")
|
|
7172
|
+
throw new Error('"hash" function param is required');
|
|
7173
|
+
_validateObject(eddsaOpts, {}, {
|
|
7174
|
+
adjustScalarBytes: "function",
|
|
7175
|
+
randomBytes: "function",
|
|
7176
|
+
domain: "function",
|
|
7177
|
+
prehash: "function",
|
|
7178
|
+
mapToCurve: "function"
|
|
7179
|
+
});
|
|
7180
|
+
const { prehash } = eddsaOpts;
|
|
7181
|
+
const { BASE, Fp: Fp2, Fn: Fn2 } = Point;
|
|
7182
|
+
const randomBytes3 = eddsaOpts.randomBytes || randomBytes;
|
|
7183
|
+
const adjustScalarBytes2 = eddsaOpts.adjustScalarBytes || ((bytes) => bytes);
|
|
7184
|
+
const domain = eddsaOpts.domain || ((data, ctx, phflag) => {
|
|
7185
|
+
_abool2(phflag, "phflag");
|
|
7186
|
+
if (ctx.length || phflag)
|
|
7187
|
+
throw new Error("Contexts/pre-hash are not supported");
|
|
7188
|
+
return data;
|
|
7189
|
+
});
|
|
7190
|
+
function modN_LE(hash) {
|
|
7191
|
+
return Fn2.create(bytesToNumberLE(hash));
|
|
7192
|
+
}
|
|
7193
|
+
function getPrivateScalar(key) {
|
|
7194
|
+
const len = lengths.secretKey;
|
|
7195
|
+
key = ensureBytes("private key", key, len);
|
|
7196
|
+
const hashed = ensureBytes("hashed private key", cHash(key), 2 * len);
|
|
7197
|
+
const head = adjustScalarBytes2(hashed.slice(0, len));
|
|
7198
|
+
const prefix = hashed.slice(len, 2 * len);
|
|
7199
|
+
const scalar = modN_LE(head);
|
|
7200
|
+
return { head, prefix, scalar };
|
|
7201
|
+
}
|
|
7202
|
+
function getExtendedPublicKey(secretKey) {
|
|
7203
|
+
const { head, prefix, scalar } = getPrivateScalar(secretKey);
|
|
7204
|
+
const point = BASE.multiply(scalar);
|
|
7205
|
+
const pointBytes = point.toBytes();
|
|
7206
|
+
return { head, prefix, scalar, point, pointBytes };
|
|
7207
|
+
}
|
|
7208
|
+
function getPublicKey(secretKey) {
|
|
7209
|
+
return getExtendedPublicKey(secretKey).pointBytes;
|
|
7210
|
+
}
|
|
7211
|
+
function hashDomainToScalar(context = Uint8Array.of(), ...msgs) {
|
|
7212
|
+
const msg = concatBytes(...msgs);
|
|
7213
|
+
return modN_LE(cHash(domain(msg, ensureBytes("context", context), !!prehash)));
|
|
7214
|
+
}
|
|
7215
|
+
function sign(msg, secretKey, options = {}) {
|
|
7216
|
+
msg = ensureBytes("message", msg);
|
|
7217
|
+
if (prehash)
|
|
7218
|
+
msg = prehash(msg);
|
|
7219
|
+
const { prefix, scalar, pointBytes } = getExtendedPublicKey(secretKey);
|
|
7220
|
+
const r = hashDomainToScalar(options.context, prefix, msg);
|
|
7221
|
+
const R = BASE.multiply(r).toBytes();
|
|
7222
|
+
const k = hashDomainToScalar(options.context, R, pointBytes, msg);
|
|
7223
|
+
const s = Fn2.create(r + k * scalar);
|
|
7224
|
+
if (!Fn2.isValid(s))
|
|
7225
|
+
throw new Error("sign failed: invalid s");
|
|
7226
|
+
const rs = concatBytes(R, Fn2.toBytes(s));
|
|
7227
|
+
return _abytes2(rs, lengths.signature, "result");
|
|
7228
|
+
}
|
|
7229
|
+
const verifyOpts = { zip215: true };
|
|
7230
|
+
function verify(sig, msg, publicKey, options = verifyOpts) {
|
|
7231
|
+
const { context, zip215 } = options;
|
|
7232
|
+
const len = lengths.signature;
|
|
7233
|
+
sig = ensureBytes("signature", sig, len);
|
|
7234
|
+
msg = ensureBytes("message", msg);
|
|
7235
|
+
publicKey = ensureBytes("publicKey", publicKey, lengths.publicKey);
|
|
7236
|
+
if (zip215 !== void 0)
|
|
7237
|
+
_abool2(zip215, "zip215");
|
|
7238
|
+
if (prehash)
|
|
7239
|
+
msg = prehash(msg);
|
|
7240
|
+
const mid = len / 2;
|
|
7241
|
+
const r = sig.subarray(0, mid);
|
|
7242
|
+
const s = bytesToNumberLE(sig.subarray(mid, len));
|
|
7243
|
+
let A, R, SB;
|
|
7244
|
+
try {
|
|
7245
|
+
A = Point.fromBytes(publicKey, zip215);
|
|
7246
|
+
R = Point.fromBytes(r, zip215);
|
|
7247
|
+
SB = BASE.multiplyUnsafe(s);
|
|
7248
|
+
} catch (error) {
|
|
7249
|
+
return false;
|
|
7250
|
+
}
|
|
7251
|
+
if (!zip215 && A.isSmallOrder())
|
|
7252
|
+
return false;
|
|
7253
|
+
const k = hashDomainToScalar(context, R.toBytes(), A.toBytes(), msg);
|
|
7254
|
+
const RkA = R.add(A.multiplyUnsafe(k));
|
|
7255
|
+
return RkA.subtract(SB).clearCofactor().is0();
|
|
7256
|
+
}
|
|
7257
|
+
const _size = Fp2.BYTES;
|
|
7258
|
+
const lengths = {
|
|
7259
|
+
secretKey: _size,
|
|
7260
|
+
publicKey: _size,
|
|
7261
|
+
signature: 2 * _size,
|
|
7262
|
+
seed: _size
|
|
7263
|
+
};
|
|
7264
|
+
function randomSecretKey(seed = randomBytes3(lengths.seed)) {
|
|
7265
|
+
return _abytes2(seed, lengths.seed, "seed");
|
|
7266
|
+
}
|
|
7267
|
+
function keygen(seed) {
|
|
7268
|
+
const secretKey = utils.randomSecretKey(seed);
|
|
7269
|
+
return { secretKey, publicKey: getPublicKey(secretKey) };
|
|
7270
|
+
}
|
|
7271
|
+
function isValidSecretKey(key) {
|
|
7272
|
+
return isBytes(key) && key.length === Fn2.BYTES;
|
|
7273
|
+
}
|
|
7274
|
+
function isValidPublicKey(key, zip215) {
|
|
7275
|
+
try {
|
|
7276
|
+
return !!Point.fromBytes(key, zip215);
|
|
7277
|
+
} catch (error) {
|
|
7278
|
+
return false;
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7281
|
+
const utils = {
|
|
7282
|
+
getExtendedPublicKey,
|
|
7283
|
+
randomSecretKey,
|
|
7284
|
+
isValidSecretKey,
|
|
7285
|
+
isValidPublicKey,
|
|
7286
|
+
/**
|
|
7287
|
+
* Converts ed public key to x public key. Uses formula:
|
|
7288
|
+
* - ed25519:
|
|
7289
|
+
* - `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
|
|
7290
|
+
* - `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
|
|
7291
|
+
* - ed448:
|
|
7292
|
+
* - `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
|
|
7293
|
+
* - `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
|
|
7294
|
+
*/
|
|
7295
|
+
toMontgomery(publicKey) {
|
|
7296
|
+
const { y } = Point.fromBytes(publicKey);
|
|
7297
|
+
const size = lengths.publicKey;
|
|
7298
|
+
const is25519 = size === 32;
|
|
7299
|
+
if (!is25519 && size !== 57)
|
|
7300
|
+
throw new Error("only defined for 25519 and 448");
|
|
7301
|
+
const u = is25519 ? Fp2.div(_1n4 + y, _1n4 - y) : Fp2.div(y - _1n4, y + _1n4);
|
|
7302
|
+
return Fp2.toBytes(u);
|
|
7303
|
+
},
|
|
7304
|
+
toMontgomerySecret(secretKey) {
|
|
7305
|
+
const size = lengths.secretKey;
|
|
7306
|
+
_abytes2(secretKey, size);
|
|
7307
|
+
const hashed = cHash(secretKey.subarray(0, size));
|
|
7308
|
+
return adjustScalarBytes2(hashed).subarray(0, size);
|
|
7309
|
+
},
|
|
7310
|
+
/** @deprecated */
|
|
7311
|
+
randomPrivateKey: randomSecretKey,
|
|
7312
|
+
/** @deprecated */
|
|
7313
|
+
precompute(windowSize = 8, point = Point.BASE) {
|
|
7314
|
+
return point.precompute(windowSize, false);
|
|
7315
|
+
}
|
|
7316
|
+
};
|
|
7317
|
+
return Object.freeze({
|
|
7318
|
+
keygen,
|
|
7319
|
+
getPublicKey,
|
|
7320
|
+
sign,
|
|
7321
|
+
verify,
|
|
7322
|
+
utils,
|
|
7323
|
+
Point,
|
|
7324
|
+
lengths
|
|
7325
|
+
});
|
|
7326
|
+
}
|
|
7327
|
+
function _eddsa_legacy_opts_to_new(c) {
|
|
7328
|
+
const CURVE = {
|
|
7329
|
+
a: c.a,
|
|
7330
|
+
d: c.d,
|
|
7331
|
+
p: c.Fp.ORDER,
|
|
7332
|
+
n: c.n,
|
|
7333
|
+
h: c.h,
|
|
7334
|
+
Gx: c.Gx,
|
|
7335
|
+
Gy: c.Gy
|
|
7336
|
+
};
|
|
7337
|
+
const Fp2 = c.Fp;
|
|
7338
|
+
const Fn2 = Field(CURVE.n, c.nBitLength, true);
|
|
7339
|
+
const curveOpts = { Fp: Fp2, Fn: Fn2, uvRatio: c.uvRatio };
|
|
7340
|
+
const eddsaOpts = {
|
|
7341
|
+
randomBytes: c.randomBytes,
|
|
7342
|
+
adjustScalarBytes: c.adjustScalarBytes,
|
|
7343
|
+
domain: c.domain,
|
|
7344
|
+
prehash: c.prehash,
|
|
7345
|
+
mapToCurve: c.mapToCurve
|
|
7346
|
+
};
|
|
7347
|
+
return { CURVE, curveOpts, hash: c.hash, eddsaOpts };
|
|
7348
|
+
}
|
|
7349
|
+
function _eddsa_new_output_to_legacy(c, eddsa2) {
|
|
7350
|
+
const Point = eddsa2.Point;
|
|
7351
|
+
const legacy = Object.assign({}, eddsa2, {
|
|
7352
|
+
ExtendedPoint: Point,
|
|
7353
|
+
CURVE: c,
|
|
7354
|
+
nBitLength: Point.Fn.BITS,
|
|
7355
|
+
nByteLength: Point.Fn.BYTES
|
|
7356
|
+
});
|
|
7357
|
+
return legacy;
|
|
7358
|
+
}
|
|
7359
|
+
function twistedEdwards(c) {
|
|
7360
|
+
const { CURVE, curveOpts, hash, eddsaOpts } = _eddsa_legacy_opts_to_new(c);
|
|
7361
|
+
const Point = edwards(CURVE, curveOpts);
|
|
7362
|
+
const EDDSA = eddsa(Point, hash, eddsaOpts);
|
|
7363
|
+
return _eddsa_new_output_to_legacy(c, EDDSA);
|
|
7364
|
+
}
|
|
7365
|
+
var _0n4, _1n4, _2n2, _8n2, PrimeEdwardsPoint;
|
|
7366
|
+
var init_edwards = __esm({
|
|
7367
|
+
"../../node_modules/@noble/curves/esm/abstract/edwards.js"() {
|
|
7368
|
+
"use strict";
|
|
7369
|
+
init_utils2();
|
|
7370
|
+
init_curve();
|
|
7371
|
+
init_modular();
|
|
7372
|
+
_0n4 = BigInt(0);
|
|
7373
|
+
_1n4 = BigInt(1);
|
|
7374
|
+
_2n2 = BigInt(2);
|
|
7375
|
+
_8n2 = BigInt(8);
|
|
7376
|
+
PrimeEdwardsPoint = class {
|
|
7377
|
+
constructor(ep) {
|
|
7378
|
+
this.ep = ep;
|
|
7379
|
+
}
|
|
7380
|
+
// Static methods that must be implemented by subclasses
|
|
7381
|
+
static fromBytes(_bytes) {
|
|
7382
|
+
notImplemented();
|
|
7383
|
+
}
|
|
7384
|
+
static fromHex(_hex) {
|
|
7385
|
+
notImplemented();
|
|
7386
|
+
}
|
|
7387
|
+
get x() {
|
|
7388
|
+
return this.toAffine().x;
|
|
7389
|
+
}
|
|
7390
|
+
get y() {
|
|
7391
|
+
return this.toAffine().y;
|
|
7392
|
+
}
|
|
7393
|
+
// Common implementations
|
|
7394
|
+
clearCofactor() {
|
|
7395
|
+
return this;
|
|
7396
|
+
}
|
|
7397
|
+
assertValidity() {
|
|
7398
|
+
this.ep.assertValidity();
|
|
7399
|
+
}
|
|
7400
|
+
toAffine(invertedZ) {
|
|
7401
|
+
return this.ep.toAffine(invertedZ);
|
|
7402
|
+
}
|
|
7403
|
+
toHex() {
|
|
7404
|
+
return bytesToHex(this.toBytes());
|
|
7405
|
+
}
|
|
7406
|
+
toString() {
|
|
7407
|
+
return this.toHex();
|
|
7408
|
+
}
|
|
7409
|
+
isTorsionFree() {
|
|
7410
|
+
return true;
|
|
7411
|
+
}
|
|
7412
|
+
isSmallOrder() {
|
|
7413
|
+
return false;
|
|
7414
|
+
}
|
|
7415
|
+
add(other) {
|
|
7416
|
+
this.assertSame(other);
|
|
7417
|
+
return this.init(this.ep.add(other.ep));
|
|
7418
|
+
}
|
|
7419
|
+
subtract(other) {
|
|
7420
|
+
this.assertSame(other);
|
|
7421
|
+
return this.init(this.ep.subtract(other.ep));
|
|
7422
|
+
}
|
|
7423
|
+
multiply(scalar) {
|
|
7424
|
+
return this.init(this.ep.multiply(scalar));
|
|
7425
|
+
}
|
|
7426
|
+
multiplyUnsafe(scalar) {
|
|
7427
|
+
return this.init(this.ep.multiplyUnsafe(scalar));
|
|
7428
|
+
}
|
|
7429
|
+
double() {
|
|
7430
|
+
return this.init(this.ep.double());
|
|
7431
|
+
}
|
|
7432
|
+
negate() {
|
|
7433
|
+
return this.init(this.ep.negate());
|
|
7434
|
+
}
|
|
7435
|
+
precompute(windowSize, isLazy) {
|
|
7436
|
+
return this.init(this.ep.precompute(windowSize, isLazy));
|
|
7437
|
+
}
|
|
7438
|
+
/** @deprecated use `toBytes` */
|
|
7439
|
+
toRawBytes() {
|
|
7440
|
+
return this.toBytes();
|
|
7441
|
+
}
|
|
7442
|
+
};
|
|
7381
7443
|
}
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7444
|
+
});
|
|
7445
|
+
|
|
7446
|
+
// ../../node_modules/@noble/curves/esm/ed25519.js
|
|
7447
|
+
function ed25519_pow_2_252_3(x) {
|
|
7448
|
+
const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80);
|
|
7449
|
+
const P = ed25519_CURVE_p;
|
|
7450
|
+
const x2 = x * x % P;
|
|
7451
|
+
const b2 = x2 * x % P;
|
|
7452
|
+
const b4 = pow2(b2, _2n3, P) * b2 % P;
|
|
7453
|
+
const b5 = pow2(b4, _1n5, P) * x % P;
|
|
7454
|
+
const b10 = pow2(b5, _5n2, P) * b5 % P;
|
|
7455
|
+
const b20 = pow2(b10, _10n, P) * b10 % P;
|
|
7456
|
+
const b40 = pow2(b20, _20n, P) * b20 % P;
|
|
7457
|
+
const b80 = pow2(b40, _40n, P) * b40 % P;
|
|
7458
|
+
const b160 = pow2(b80, _80n, P) * b80 % P;
|
|
7459
|
+
const b240 = pow2(b160, _80n, P) * b80 % P;
|
|
7460
|
+
const b250 = pow2(b240, _10n, P) * b10 % P;
|
|
7461
|
+
const pow_p_5_8 = pow2(b250, _2n3, P) * x % P;
|
|
7462
|
+
return { pow_p_5_8, b2 };
|
|
7463
|
+
}
|
|
7464
|
+
function adjustScalarBytes(bytes) {
|
|
7465
|
+
bytes[0] &= 248;
|
|
7466
|
+
bytes[31] &= 127;
|
|
7467
|
+
bytes[31] |= 64;
|
|
7468
|
+
return bytes;
|
|
7469
|
+
}
|
|
7470
|
+
function uvRatio(u, v) {
|
|
7471
|
+
const P = ed25519_CURVE_p;
|
|
7472
|
+
const v3 = mod(v * v * v, P);
|
|
7473
|
+
const v7 = mod(v3 * v3 * v, P);
|
|
7474
|
+
const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
|
|
7475
|
+
let x = mod(u * v3 * pow, P);
|
|
7476
|
+
const vx2 = mod(v * x * x, P);
|
|
7477
|
+
const root1 = x;
|
|
7478
|
+
const root2 = mod(x * ED25519_SQRT_M1, P);
|
|
7479
|
+
const useRoot1 = vx2 === u;
|
|
7480
|
+
const useRoot2 = vx2 === mod(-u, P);
|
|
7481
|
+
const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P);
|
|
7482
|
+
if (useRoot1)
|
|
7483
|
+
x = root1;
|
|
7484
|
+
if (useRoot2 || noRoot)
|
|
7485
|
+
x = root2;
|
|
7486
|
+
if (isNegativeLE(x, P))
|
|
7487
|
+
x = mod(-x, P);
|
|
7488
|
+
return { isValid: useRoot1 || useRoot2, value: x };
|
|
7489
|
+
}
|
|
7490
|
+
function calcElligatorRistrettoMap(r0) {
|
|
7491
|
+
const { d } = ed25519_CURVE;
|
|
7492
|
+
const P = ed25519_CURVE_p;
|
|
7493
|
+
const mod2 = (n) => Fp.create(n);
|
|
7494
|
+
const r = mod2(SQRT_M1 * r0 * r0);
|
|
7495
|
+
const Ns = mod2((r + _1n5) * ONE_MINUS_D_SQ);
|
|
7496
|
+
let c = BigInt(-1);
|
|
7497
|
+
const D = mod2((c - d * r) * mod2(r + d));
|
|
7498
|
+
let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D);
|
|
7499
|
+
let s_ = mod2(s * r0);
|
|
7500
|
+
if (!isNegativeLE(s_, P))
|
|
7501
|
+
s_ = mod2(-s_);
|
|
7502
|
+
if (!Ns_D_is_sq)
|
|
7503
|
+
s = s_;
|
|
7504
|
+
if (!Ns_D_is_sq)
|
|
7505
|
+
c = r;
|
|
7506
|
+
const Nt = mod2(c * (r - _1n5) * D_MINUS_ONE_SQ - D);
|
|
7507
|
+
const s2 = s * s;
|
|
7508
|
+
const W0 = mod2((s + s) * D);
|
|
7509
|
+
const W1 = mod2(Nt * SQRT_AD_MINUS_ONE);
|
|
7510
|
+
const W2 = mod2(_1n5 - s2);
|
|
7511
|
+
const W3 = mod2(_1n5 + s2);
|
|
7512
|
+
return new ed25519.Point(mod2(W0 * W3), mod2(W2 * W1), mod2(W1 * W3), mod2(W0 * W2));
|
|
7513
|
+
}
|
|
7514
|
+
function ristretto255_map(bytes) {
|
|
7515
|
+
abytes(bytes, 64);
|
|
7516
|
+
const r1 = bytes255ToNumberLE(bytes.subarray(0, 32));
|
|
7517
|
+
const R1 = calcElligatorRistrettoMap(r1);
|
|
7518
|
+
const r2 = bytes255ToNumberLE(bytes.subarray(32, 64));
|
|
7519
|
+
const R2 = calcElligatorRistrettoMap(r2);
|
|
7520
|
+
return new _RistrettoPoint(R1.add(R2));
|
|
7521
|
+
}
|
|
7522
|
+
var _0n5, _1n5, _2n3, _3n2, _5n2, _8n3, ed25519_CURVE_p, ed25519_CURVE, ED25519_SQRT_M1, Fp, Fn, ed25519Defaults, ed25519, SQRT_M1, SQRT_AD_MINUS_ONE, INVSQRT_A_MINUS_D, ONE_MINUS_D_SQ, D_MINUS_ONE_SQ, invertSqrt, MAX_255B, bytes255ToNumberLE, _RistrettoPoint;
|
|
7523
|
+
var init_ed25519 = __esm({
|
|
7524
|
+
"../../node_modules/@noble/curves/esm/ed25519.js"() {
|
|
7525
|
+
"use strict";
|
|
7526
|
+
init_sha2();
|
|
7527
|
+
init_utils();
|
|
7528
|
+
init_curve();
|
|
7529
|
+
init_edwards();
|
|
7530
|
+
init_modular();
|
|
7531
|
+
init_utils2();
|
|
7532
|
+
_0n5 = /* @__PURE__ */ BigInt(0);
|
|
7533
|
+
_1n5 = BigInt(1);
|
|
7534
|
+
_2n3 = BigInt(2);
|
|
7535
|
+
_3n2 = BigInt(3);
|
|
7536
|
+
_5n2 = BigInt(5);
|
|
7537
|
+
_8n3 = BigInt(8);
|
|
7538
|
+
ed25519_CURVE_p = BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed");
|
|
7539
|
+
ed25519_CURVE = /* @__PURE__ */ (() => ({
|
|
7540
|
+
p: ed25519_CURVE_p,
|
|
7541
|
+
n: BigInt("0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"),
|
|
7542
|
+
h: _8n3,
|
|
7543
|
+
a: BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec"),
|
|
7544
|
+
d: BigInt("0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3"),
|
|
7545
|
+
Gx: BigInt("0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a"),
|
|
7546
|
+
Gy: BigInt("0x6666666666666666666666666666666666666666666666666666666666666658")
|
|
7547
|
+
}))();
|
|
7548
|
+
ED25519_SQRT_M1 = /* @__PURE__ */ BigInt("19681161376707505956807079304988542015446066515923890162744021073123829784752");
|
|
7549
|
+
Fp = /* @__PURE__ */ (() => Field(ed25519_CURVE.p, { isLE: true }))();
|
|
7550
|
+
Fn = /* @__PURE__ */ (() => Field(ed25519_CURVE.n, { isLE: true }))();
|
|
7551
|
+
ed25519Defaults = /* @__PURE__ */ (() => ({
|
|
7552
|
+
...ed25519_CURVE,
|
|
7553
|
+
Fp,
|
|
7554
|
+
hash: sha512,
|
|
7555
|
+
adjustScalarBytes,
|
|
7556
|
+
// dom2
|
|
7557
|
+
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
|
|
7558
|
+
// Constant-time, u/√v
|
|
7559
|
+
uvRatio
|
|
7560
|
+
}))();
|
|
7561
|
+
ed25519 = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))();
|
|
7562
|
+
SQRT_M1 = ED25519_SQRT_M1;
|
|
7563
|
+
SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt("25063068953384623474111414158702152701244531502492656460079210482610430750235");
|
|
7564
|
+
INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt("54469307008909316920995813868745141605393597292927456921205312896311721017578");
|
|
7565
|
+
ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt("1159843021668779879193775521855586647937357759715417654439879720876111806838");
|
|
7566
|
+
D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt("40440834346308536858101042469323190826248399146238708352240133220865137265952");
|
|
7567
|
+
invertSqrt = (number) => uvRatio(_1n5, number);
|
|
7568
|
+
MAX_255B = /* @__PURE__ */ BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
7569
|
+
bytes255ToNumberLE = (bytes) => ed25519.Point.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
|
|
7570
|
+
_RistrettoPoint = class __RistrettoPoint extends PrimeEdwardsPoint {
|
|
7571
|
+
constructor(ep) {
|
|
7572
|
+
super(ep);
|
|
7573
|
+
}
|
|
7574
|
+
static fromAffine(ap) {
|
|
7575
|
+
return new __RistrettoPoint(ed25519.Point.fromAffine(ap));
|
|
7576
|
+
}
|
|
7577
|
+
assertSame(other) {
|
|
7578
|
+
if (!(other instanceof __RistrettoPoint))
|
|
7579
|
+
throw new Error("RistrettoPoint expected");
|
|
7580
|
+
}
|
|
7581
|
+
init(ep) {
|
|
7582
|
+
return new __RistrettoPoint(ep);
|
|
7583
|
+
}
|
|
7584
|
+
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
|
7585
|
+
static hashToCurve(hex3) {
|
|
7586
|
+
return ristretto255_map(ensureBytes("ristrettoHash", hex3, 64));
|
|
7587
|
+
}
|
|
7588
|
+
static fromBytes(bytes) {
|
|
7589
|
+
abytes(bytes, 32);
|
|
7590
|
+
const { a, d } = ed25519_CURVE;
|
|
7591
|
+
const P = ed25519_CURVE_p;
|
|
7592
|
+
const mod2 = (n) => Fp.create(n);
|
|
7593
|
+
const s = bytes255ToNumberLE(bytes);
|
|
7594
|
+
if (!equalBytes(Fp.toBytes(s), bytes) || isNegativeLE(s, P))
|
|
7595
|
+
throw new Error("invalid ristretto255 encoding 1");
|
|
7596
|
+
const s2 = mod2(s * s);
|
|
7597
|
+
const u1 = mod2(_1n5 + a * s2);
|
|
7598
|
+
const u2 = mod2(_1n5 - a * s2);
|
|
7599
|
+
const u1_2 = mod2(u1 * u1);
|
|
7600
|
+
const u2_2 = mod2(u2 * u2);
|
|
7601
|
+
const v = mod2(a * d * u1_2 - u2_2);
|
|
7602
|
+
const { isValid: isValid3, value: I } = invertSqrt(mod2(v * u2_2));
|
|
7603
|
+
const Dx = mod2(I * u2);
|
|
7604
|
+
const Dy = mod2(I * Dx * v);
|
|
7605
|
+
let x = mod2((s + s) * Dx);
|
|
7606
|
+
if (isNegativeLE(x, P))
|
|
7607
|
+
x = mod2(-x);
|
|
7608
|
+
const y = mod2(u1 * Dy);
|
|
7609
|
+
const t = mod2(x * y);
|
|
7610
|
+
if (!isValid3 || isNegativeLE(t, P) || y === _0n5)
|
|
7611
|
+
throw new Error("invalid ristretto255 encoding 2");
|
|
7612
|
+
return new __RistrettoPoint(new ed25519.Point(x, y, _1n5, t));
|
|
7613
|
+
}
|
|
7614
|
+
/**
|
|
7615
|
+
* Converts ristretto-encoded string to ristretto point.
|
|
7616
|
+
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-decode).
|
|
7617
|
+
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
|
7618
|
+
*/
|
|
7619
|
+
static fromHex(hex3) {
|
|
7620
|
+
return __RistrettoPoint.fromBytes(ensureBytes("ristrettoHex", hex3, 32));
|
|
7621
|
+
}
|
|
7622
|
+
static msm(points, scalars) {
|
|
7623
|
+
return pippenger(__RistrettoPoint, ed25519.Point.Fn, points, scalars);
|
|
7624
|
+
}
|
|
7625
|
+
/**
|
|
7626
|
+
* Encodes ristretto point to Uint8Array.
|
|
7627
|
+
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-encode).
|
|
7628
|
+
*/
|
|
7629
|
+
toBytes() {
|
|
7630
|
+
let { X, Y, Z, T } = this.ep;
|
|
7631
|
+
const P = ed25519_CURVE_p;
|
|
7632
|
+
const mod2 = (n) => Fp.create(n);
|
|
7633
|
+
const u1 = mod2(mod2(Z + Y) * mod2(Z - Y));
|
|
7634
|
+
const u2 = mod2(X * Y);
|
|
7635
|
+
const u2sq = mod2(u2 * u2);
|
|
7636
|
+
const { value: invsqrt } = invertSqrt(mod2(u1 * u2sq));
|
|
7637
|
+
const D1 = mod2(invsqrt * u1);
|
|
7638
|
+
const D2 = mod2(invsqrt * u2);
|
|
7639
|
+
const zInv = mod2(D1 * D2 * T);
|
|
7640
|
+
let D;
|
|
7641
|
+
if (isNegativeLE(T * zInv, P)) {
|
|
7642
|
+
let _x = mod2(Y * SQRT_M1);
|
|
7643
|
+
let _y = mod2(X * SQRT_M1);
|
|
7644
|
+
X = _x;
|
|
7645
|
+
Y = _y;
|
|
7646
|
+
D = mod2(D1 * INVSQRT_A_MINUS_D);
|
|
7647
|
+
} else {
|
|
7648
|
+
D = D2;
|
|
7649
|
+
}
|
|
7650
|
+
if (isNegativeLE(X * zInv, P))
|
|
7651
|
+
Y = mod2(-Y);
|
|
7652
|
+
let s = mod2((Z - Y) * D);
|
|
7653
|
+
if (isNegativeLE(s, P))
|
|
7654
|
+
s = mod2(-s);
|
|
7655
|
+
return Fp.toBytes(s);
|
|
7656
|
+
}
|
|
7657
|
+
/**
|
|
7658
|
+
* Compares two Ristretto points.
|
|
7659
|
+
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-equals).
|
|
7660
|
+
*/
|
|
7661
|
+
equals(other) {
|
|
7662
|
+
this.assertSame(other);
|
|
7663
|
+
const { X: X1, Y: Y1 } = this.ep;
|
|
7664
|
+
const { X: X2, Y: Y2 } = other.ep;
|
|
7665
|
+
const mod2 = (n) => Fp.create(n);
|
|
7666
|
+
const one = mod2(X1 * Y2) === mod2(Y1 * X2);
|
|
7667
|
+
const two = mod2(Y1 * Y2) === mod2(X1 * X2);
|
|
7668
|
+
return one || two;
|
|
7669
|
+
}
|
|
7670
|
+
is0() {
|
|
7671
|
+
return this.equals(__RistrettoPoint.ZERO);
|
|
7672
|
+
}
|
|
7673
|
+
};
|
|
7674
|
+
_RistrettoPoint.BASE = /* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.BASE))();
|
|
7675
|
+
_RistrettoPoint.ZERO = /* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.ZERO))();
|
|
7676
|
+
_RistrettoPoint.Fp = /* @__PURE__ */ (() => Fp)();
|
|
7677
|
+
_RistrettoPoint.Fn = /* @__PURE__ */ (() => Fn)();
|
|
7385
7678
|
}
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7679
|
+
});
|
|
7680
|
+
|
|
7681
|
+
// ../replica/dist/index.js
|
|
7682
|
+
function assertFolderPrefix(prefix) {
|
|
7683
|
+
const validFolder = typeof prefix === "string" && prefix.length > 0 && !prefix.startsWith("/") && !prefix.includes("//") && prefix.endsWith("/");
|
|
7684
|
+
if (prefix !== "/" && !validFolder) {
|
|
7685
|
+
const folderHint = typeof prefix === "string" ? prefix.replace(/^\/+/, "").replace(/\/+$/, "") : "";
|
|
7686
|
+
const suggestion = folderHint.length > 0 && !folderHint.includes("//") ? ` Use ${JSON.stringify(`${folderHint}/`)}.` : ' Use "/" or a slash-terminated folder path such as "notes/".';
|
|
7687
|
+
throw new TypeError(`Replication prefix must be "/" or a non-empty slash-terminated folder path without empty segments.${suggestion}`);
|
|
7389
7688
|
}
|
|
7390
|
-
|
|
7391
|
-
|
|
7689
|
+
}
|
|
7690
|
+
function assertFolderPrefix2(prefix) {
|
|
7691
|
+
try {
|
|
7692
|
+
assertFolderPrefix(prefix);
|
|
7693
|
+
} catch {
|
|
7694
|
+
const folderHint = typeof prefix === "string" ? prefix.replace(/^\/+/, "").replace(/\/+$/, "") : "";
|
|
7695
|
+
const suggestion = prefix === "" ? 'use "/" for the whole space' : folderHint.length > 0 && !folderHint.includes("//") ? `use ${JSON.stringify(`${folderHint}/`)}` : 'use "/" for the whole space or a folder path such as "notes/"';
|
|
7696
|
+
throw new ReplicaError(
|
|
7697
|
+
ReplicaErrorCode.INVALID_ARGUMENT,
|
|
7698
|
+
`Replication prefix ${JSON.stringify(prefix)} must be "/" or a non-empty folder path ending in / without empty segments; ${suggestion}. Run \`tc replica reset --replica <name> --purge\` and recreate it with the folder prefix.`
|
|
7699
|
+
);
|
|
7392
7700
|
}
|
|
7393
|
-
|
|
7394
|
-
|
|
7701
|
+
}
|
|
7702
|
+
var ReplicaErrorCode, REPLICA_ERROR, ReplicaError, PENDING_REFUSALS, encoder;
|
|
7703
|
+
var init_dist = __esm({
|
|
7704
|
+
"../replica/dist/index.js"() {
|
|
7705
|
+
"use strict";
|
|
7706
|
+
ReplicaErrorCode = {
|
|
7707
|
+
/** Another process holds the sync lease. */
|
|
7708
|
+
BUSY: "REPLICA_BUSY",
|
|
7709
|
+
/** No replica with this name exists. */
|
|
7710
|
+
NOT_FOUND: "REPLICA_NOT_FOUND",
|
|
7711
|
+
/** The replica exists but its stored configuration differs from the request. */
|
|
7712
|
+
CONFIG_MISMATCH: "REPLICA_CONFIG_MISMATCH",
|
|
7713
|
+
/** The runtime has no supported durable store (e.g. Node < 22.13). */
|
|
7714
|
+
RUNTIME_UNSUPPORTED: "RUNTIME_UNSUPPORTED",
|
|
7715
|
+
/** A required open() argument is missing or malformed (e.g. `principal`). */
|
|
7716
|
+
INVALID_ARGUMENT: "REPLICA_INVALID_ARGUMENT",
|
|
7717
|
+
/** The local store failed (I/O, corruption, schema). */
|
|
7718
|
+
STORAGE_ERROR: "STORAGE_ERROR",
|
|
7719
|
+
/** The local disk is full. */
|
|
7720
|
+
STORAGE_FULL: "STORAGE_FULL",
|
|
7721
|
+
/** The key is outside the replica's prefix. */
|
|
7722
|
+
NOT_COVERED: "NOT_COVERED",
|
|
7723
|
+
/** Syncing the secrets space or the vault namespace needs an explicit opt-in. */
|
|
7724
|
+
SECRETS_OPT_IN_REQUIRED: "SECRETS_OPT_IN_REQUIRED",
|
|
7725
|
+
/** No grant is installed, or none covers the requested scope. */
|
|
7726
|
+
GRANT_MISSING: "GRANT_MISSING",
|
|
7727
|
+
/** The grant bytes are not a verifiable UCAN, or its signature is wrong. */
|
|
7728
|
+
GRANT_INVALID: "GRANT_INVALID",
|
|
7729
|
+
/** SIWE/CACAO and other non-UCAN grants cannot be used for a replica. */
|
|
7730
|
+
GRANT_FORMAT_UNSUPPORTED: "GRANT_FORMAT_UNSUPPORTED",
|
|
7731
|
+
/** The grant was issued to a different device. */
|
|
7732
|
+
GRANT_AUDIENCE_MISMATCH: "GRANT_AUDIENCE_MISMATCH",
|
|
7733
|
+
/** The grant lacks `tinycloud.kv/sync` or `tinycloud.kv/get` on the prefix. */
|
|
7734
|
+
GRANT_NOT_COVERING: "GRANT_NOT_COVERING",
|
|
7735
|
+
GRANT_NOT_YET_VALID: "GRANT_NOT_YET_VALID",
|
|
7736
|
+
GRANT_EXPIRED: "GRANT_EXPIRED",
|
|
7737
|
+
/** The configured node does not advertise whole-space KV sync support. */
|
|
7738
|
+
REPLICATION_ROOT_UNSUPPORTED: "REPLICATION_ROOT_UNSUPPORTED",
|
|
7739
|
+
GRANT_REVOKED: "GRANT_REVOKED",
|
|
7740
|
+
/** The node refused the invocation for a reason other than revocation. */
|
|
7741
|
+
GRANT_UNAUTHORIZED: "GRANT_UNAUTHORIZED",
|
|
7742
|
+
/** The node refused the retention grant. */
|
|
7743
|
+
RETENTION_GRANT_REFUSED: "RETENTION_GRANT_REFUSED",
|
|
7744
|
+
/** The node could not be reached. */
|
|
7745
|
+
NETWORK_ERROR: "NETWORK_ERROR",
|
|
7746
|
+
/** The node answered with an unexpected status. */
|
|
7747
|
+
NODE_ERROR: "NODE_ERROR",
|
|
7748
|
+
/** The node's answer violates the wire contract. */
|
|
7749
|
+
PROTOCOL_ERROR: "PROTOCOL_ERROR",
|
|
7750
|
+
/** The node asked for a fresh bootstrap (410). Handled inside sync. */
|
|
7751
|
+
RESET_REQUIRED: "RESET_REQUIRED",
|
|
7752
|
+
/** The feed now comes from a different node than the one pinned. */
|
|
7753
|
+
SOURCE_CHANGED: "SOURCE_CHANGED",
|
|
7754
|
+
/** The feed delivered a key outside the replica's prefix. */
|
|
7755
|
+
SCOPE_VIOLATION: "SCOPE_VIOLATION",
|
|
7756
|
+
/** Fetched bytes do not hash to the ETag the node attested for them. */
|
|
7757
|
+
CONTENT_MISMATCH: "CONTENT_MISMATCH",
|
|
7758
|
+
/** A stored blob no longer hashes to its name. */
|
|
7759
|
+
INTEGRITY_ERROR: "INTEGRITY_ERROR",
|
|
7760
|
+
/** The replica handle was closed; in-flight calls settle with this code. */
|
|
7761
|
+
CLOSED: "REPLICA_CLOSED"
|
|
7762
|
+
};
|
|
7763
|
+
REPLICA_ERROR = /* @__PURE__ */ Symbol.for("tinycloud.replica.error");
|
|
7764
|
+
ReplicaError = class extends Error {
|
|
7765
|
+
[REPLICA_ERROR] = true;
|
|
7766
|
+
code;
|
|
7767
|
+
detail;
|
|
7768
|
+
constructor(code3, message, detail, options) {
|
|
7769
|
+
super(message, options);
|
|
7770
|
+
this.name = "ReplicaError";
|
|
7771
|
+
this.code = code3;
|
|
7772
|
+
if (detail !== void 0) this.detail = detail;
|
|
7773
|
+
}
|
|
7774
|
+
};
|
|
7775
|
+
PENDING_REFUSALS = /* @__PURE__ */ new Set([
|
|
7776
|
+
ReplicaErrorCode.GRANT_UNAUTHORIZED,
|
|
7777
|
+
ReplicaErrorCode.GRANT_EXPIRED,
|
|
7778
|
+
ReplicaErrorCode.GRANT_NOT_YET_VALID
|
|
7779
|
+
]);
|
|
7780
|
+
encoder = new TextEncoder();
|
|
7395
7781
|
}
|
|
7396
|
-
|
|
7397
|
-
|
|
7782
|
+
});
|
|
7783
|
+
|
|
7784
|
+
// src/lib/replication-config.ts
|
|
7785
|
+
import { join as join5 } from "path";
|
|
7786
|
+
import { profilePath, withProfileLock as withProfileLock2 } from "@tinycloud/operations/state";
|
|
7787
|
+
import { sqliteReplicaStorage } from "@tinycloud/node-sdk";
|
|
7788
|
+
function createCliReplicationConfig(profile, settings, output, enabled) {
|
|
7789
|
+
if (!enabled || !settings || settings.prefixes.length === 0) return void 0;
|
|
7790
|
+
for (const prefix of settings.prefixes) {
|
|
7791
|
+
try {
|
|
7792
|
+
assertFolderPrefix2(prefix);
|
|
7793
|
+
} catch (error) {
|
|
7794
|
+
const trimmed = prefix.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
7795
|
+
const replacement = trimmed.length > 0 && !trimmed.includes("//") ? `${trimmed}/` : "/";
|
|
7796
|
+
throw new CLIError(
|
|
7797
|
+
"INVALID_REPLICATION_PREFIX",
|
|
7798
|
+
error instanceof Error ? error.message : String(error),
|
|
7799
|
+
ExitCode.USAGE_ERROR,
|
|
7800
|
+
{ hint: `Replace the saved replication prefix with \`tc auth login --replication-prefix ${replacement}\`; purging a replica alone does not change this profile setting.` }
|
|
7801
|
+
);
|
|
7802
|
+
}
|
|
7398
7803
|
}
|
|
7399
|
-
|
|
7400
|
-
|
|
7804
|
+
const root = profilePath(profile);
|
|
7805
|
+
return {
|
|
7806
|
+
enabled: true,
|
|
7807
|
+
prefixes: settings.prefixes,
|
|
7808
|
+
allowSecrets: settings.allowSecrets === true,
|
|
7809
|
+
mode: "foreground",
|
|
7810
|
+
verify: process.env.TC_REPLICATION_VERIFY === "1",
|
|
7811
|
+
maxStalenessMs: Number(process.env.TC_REPLICATION_MAX_STALENESS_MS ?? 6e4),
|
|
7812
|
+
staleSyncTimeoutMs: Number(process.env.TC_REPLICATION_SYNC_TIMEOUT_MS ?? 1e4),
|
|
7813
|
+
storage: sqliteReplicaStorage({
|
|
7814
|
+
dir: join5(root, "replication"),
|
|
7815
|
+
guard: (section) => withProfileLock2(profile, section, { requireProfile: true, timeoutMs: 35e3 })
|
|
7816
|
+
}),
|
|
7817
|
+
onEvent: createReplicationEventSink(root, output)
|
|
7818
|
+
};
|
|
7819
|
+
}
|
|
7820
|
+
var init_replication_config = __esm({
|
|
7821
|
+
"src/lib/replication-config.ts"() {
|
|
7822
|
+
"use strict";
|
|
7823
|
+
init_replication_log();
|
|
7824
|
+
init_dist();
|
|
7825
|
+
init_errors();
|
|
7826
|
+
init_constants();
|
|
7401
7827
|
}
|
|
7402
|
-
|
|
7403
|
-
|
|
7828
|
+
});
|
|
7829
|
+
|
|
7830
|
+
// src/lib/sdk.ts
|
|
7831
|
+
var sdk_exports = {};
|
|
7832
|
+
__export(sdk_exports, {
|
|
7833
|
+
bootstrapDelegatedSession: () => bootstrapDelegatedSession,
|
|
7834
|
+
closeReplication: () => closeReplication,
|
|
7835
|
+
createSDKInstance: () => createSDKInstance,
|
|
7836
|
+
ensureAuthenticated: () => ensureAuthenticated,
|
|
7837
|
+
jwkHasPrivateParameter: () => jwkHasPrivateParameter,
|
|
7838
|
+
registerReplication: () => registerReplication,
|
|
7839
|
+
registeredReplications: () => registeredReplications,
|
|
7840
|
+
replicationForProfile: () => replicationForProfile,
|
|
7841
|
+
restoreProfileSessionNode: () => restoreProfileSessionNode,
|
|
7842
|
+
selectSignerJwk: () => selectSignerJwk,
|
|
7843
|
+
storedSessionVerifiesLocally: () => storedSessionVerifiesLocally
|
|
7844
|
+
});
|
|
7845
|
+
import { TinyCloudNode, signedCompactUcanExpiry } from "@tinycloud/node-sdk";
|
|
7846
|
+
function jwkHasPrivateParameter(jwk) {
|
|
7847
|
+
if (!jwk || typeof jwk !== "object") return false;
|
|
7848
|
+
const d = jwk.d;
|
|
7849
|
+
return typeof d === "string" && d.length > 0;
|
|
7850
|
+
}
|
|
7851
|
+
function selectSignerJwk(sessionJwk, key) {
|
|
7852
|
+
if (jwkHasPrivateParameter(sessionJwk)) {
|
|
7853
|
+
return sessionJwk;
|
|
7404
7854
|
}
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7855
|
+
return key ?? void 0;
|
|
7856
|
+
}
|
|
7857
|
+
function signerJwkForProfile(profileName, sessionJwk, key) {
|
|
7858
|
+
const jwk = selectSignerJwk(sessionJwk, key);
|
|
7859
|
+
if (jwkHasPrivateParameter(jwk)) {
|
|
7860
|
+
return jwk;
|
|
7408
7861
|
}
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
const
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
return Fn2.create(bytesToNumberLE(hash));
|
|
7862
|
+
throw new CLIError(
|
|
7863
|
+
"AUTH_REQUIRED",
|
|
7864
|
+
`Profile "${profileName}" cannot restore its session because its private key material is missing.`,
|
|
7865
|
+
ExitCode.AUTH_REQUIRED,
|
|
7866
|
+
{
|
|
7867
|
+
hint: `Sign in again with: tc --profile ${profileName} auth login --method openkey`
|
|
7868
|
+
}
|
|
7869
|
+
);
|
|
7870
|
+
}
|
|
7871
|
+
function signedLifetimePassed(delegation) {
|
|
7872
|
+
const authorization = delegation.delegationHeader?.Authorization;
|
|
7873
|
+
const expiry = typeof authorization === "string" ? signedCompactUcanExpiry(authorization) : void 0;
|
|
7874
|
+
return expiry !== void 0 && expiry.getTime() <= Date.now();
|
|
7875
|
+
}
|
|
7876
|
+
async function restoreProfileSession(node, profileName, profile, sessionData) {
|
|
7877
|
+
try {
|
|
7878
|
+
await node.restoreSession(sessionData);
|
|
7879
|
+
} catch (error) {
|
|
7880
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "AUTH_EXPIRED") {
|
|
7881
|
+
throw sessionExpiredError(profileName, profile === null ? void 0 : resolveProfilePosture(profile));
|
|
7882
|
+
}
|
|
7883
|
+
throw error;
|
|
7432
7884
|
}
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7885
|
+
}
|
|
7886
|
+
function persistedSessionData(profileName, profile, session, key) {
|
|
7887
|
+
return {
|
|
7888
|
+
delegationHeader: session.delegationHeader,
|
|
7889
|
+
delegationCid: session.delegationCid,
|
|
7890
|
+
spaceId: session.spaceId,
|
|
7891
|
+
jwk: signerJwkForProfile(profileName, session.jwk, key),
|
|
7892
|
+
verificationMethod: session.verificationMethod ?? profile.sessionDid ?? profile.did,
|
|
7893
|
+
address: session.address,
|
|
7894
|
+
chainId: session.chainId,
|
|
7895
|
+
siwe: session.siwe,
|
|
7896
|
+
signature: session.signature
|
|
7897
|
+
};
|
|
7898
|
+
}
|
|
7899
|
+
async function restoreProfileSessionNode(ctx) {
|
|
7900
|
+
const profile = await ProfileManager.getProfile(ctx.profile);
|
|
7901
|
+
const session = await ProfileManager.getSession(ctx.profile);
|
|
7902
|
+
if (!session) return { unavailable: "session_missing" };
|
|
7903
|
+
if (typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || session.delegationHeader === null || typeof session.delegationHeader !== "object" || !("Authorization" in session.delegationHeader) || typeof session.delegationHeader.Authorization !== "string") {
|
|
7904
|
+
return { unavailable: "session_invalid" };
|
|
7441
7905
|
}
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
const point = BASE.multiply(scalar);
|
|
7445
|
-
const pointBytes = point.toBytes();
|
|
7446
|
-
return { head, prefix, scalar, point, pointBytes };
|
|
7906
|
+
if (typeof session.expiresAt === "string" && Date.parse(session.expiresAt) <= Date.now()) {
|
|
7907
|
+
return { unavailable: "session_expired" };
|
|
7447
7908
|
}
|
|
7448
|
-
|
|
7449
|
-
|
|
7909
|
+
const key = await ProfileManager.getKey(ctx.profile);
|
|
7910
|
+
try {
|
|
7911
|
+
const node = new TinyCloudNode({
|
|
7912
|
+
host: ctx.host,
|
|
7913
|
+
...profile.authMethod === "local" && profile.privateKey ? { privateKey: profile.privateKey } : {}
|
|
7914
|
+
});
|
|
7915
|
+
await restoreProfileSession(node, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
|
|
7916
|
+
return { node };
|
|
7917
|
+
} catch (error) {
|
|
7918
|
+
if (error instanceof CLIError && error.metadata?.reason === "session_expired") {
|
|
7919
|
+
return { unavailable: "session_expired" };
|
|
7920
|
+
}
|
|
7921
|
+
return { unavailable: "session_invalid" };
|
|
7450
7922
|
}
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7923
|
+
}
|
|
7924
|
+
async function storedSessionVerifiesLocally(profileName) {
|
|
7925
|
+
const profile = await ProfileManager.getProfile(profileName).catch(() => null);
|
|
7926
|
+
if (profile === null) return true;
|
|
7927
|
+
const local = profile.authMethod === "local" && typeof profile.privateKey === "string";
|
|
7928
|
+
try {
|
|
7929
|
+
const session = await ProfileManager.getSession(profileName);
|
|
7930
|
+
if (!session || typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || session.delegationHeader === null || typeof session.delegationHeader !== "object" || !("Authorization" in session.delegationHeader) || typeof session.delegationHeader.Authorization !== "string") return true;
|
|
7931
|
+
const key = await ProfileManager.getKey(profileName);
|
|
7932
|
+
const node = new TinyCloudNode({
|
|
7933
|
+
host: profile.host ?? DEFAULT_HOST,
|
|
7934
|
+
...local ? { privateKey: profile.privateKey } : {}
|
|
7935
|
+
});
|
|
7936
|
+
await restoreProfileSession(node, profileName, profile, persistedSessionData(profileName, profile, session, key));
|
|
7937
|
+
return true;
|
|
7938
|
+
} catch {
|
|
7939
|
+
return false;
|
|
7454
7940
|
}
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
return _abytes2(rs, lengths.signature, "result");
|
|
7941
|
+
}
|
|
7942
|
+
async function createSDKInstance(ctx, options) {
|
|
7943
|
+
const profile = options?.privateKey ? await ProfileManager.getProfile(ctx.profile).catch(() => null) : await ProfileManager.getProfile(ctx.profile);
|
|
7944
|
+
const session = await ProfileManager.getSession(ctx.profile);
|
|
7945
|
+
const key = await ProfileManager.getKey(ctx.profile);
|
|
7946
|
+
const effectivePrivateKey = options?.privateKey ?? profile?.privateKey;
|
|
7947
|
+
if (!key && !effectivePrivateKey && !(profile?.authMethod === "openkey" && session !== null)) {
|
|
7948
|
+
throw new CLIError(
|
|
7949
|
+
"AUTH_REQUIRED",
|
|
7950
|
+
`No key found for profile "${ctx.profile}". Run \`tc --profile ${ctx.profile} auth rotate\` to create a new key and sign in.`,
|
|
7951
|
+
ExitCode.AUTH_REQUIRED
|
|
7952
|
+
);
|
|
7468
7953
|
}
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
if (
|
|
7477
|
-
|
|
7478
|
-
if (prehash)
|
|
7479
|
-
msg = prehash(msg);
|
|
7480
|
-
const mid = len / 2;
|
|
7481
|
-
const r = sig.subarray(0, mid);
|
|
7482
|
-
const s = bytesToNumberLE(sig.subarray(mid, len));
|
|
7483
|
-
let A, R, SB;
|
|
7484
|
-
try {
|
|
7485
|
-
A = Point.fromBytes(publicKey, zip215);
|
|
7486
|
-
R = Point.fromBytes(r, zip215);
|
|
7487
|
-
SB = BASE.multiplyUnsafe(s);
|
|
7488
|
-
} catch (error) {
|
|
7489
|
-
return false;
|
|
7954
|
+
if (profile?.authMethod === "local" && effectivePrivateKey) {
|
|
7955
|
+
const replication2 = createCliReplicationConfig(
|
|
7956
|
+
ctx.profile,
|
|
7957
|
+
profile?.replication,
|
|
7958
|
+
{ debug: ctx.replicationDebug, quiet: ctx.quiet },
|
|
7959
|
+
ctx.replication
|
|
7960
|
+
);
|
|
7961
|
+
if (ctx.replication && !replication2) {
|
|
7962
|
+
process.stderr.write("[replication] Enabled, but this profile has no configured prefixes; reads use the network.\n");
|
|
7490
7963
|
}
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7964
|
+
const node2 = new TinyCloudNode({
|
|
7965
|
+
host: ctx.host,
|
|
7966
|
+
privateKey: effectivePrivateKey,
|
|
7967
|
+
...replication2 ? { replication: replication2 } : {}
|
|
7968
|
+
});
|
|
7969
|
+
if (node2.replication) registerReplication(ctx.profile, node2.replication);
|
|
7970
|
+
const restoredOwnSession = Boolean(session && session.delegationHeader && session.delegationCid && session.spaceId);
|
|
7971
|
+
if (restoredOwnSession) {
|
|
7972
|
+
await restoreProfileSession(node2, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
|
|
7973
|
+
} else {
|
|
7974
|
+
await node2.signIn();
|
|
7975
|
+
}
|
|
7976
|
+
if (restoredOwnSession) {
|
|
7977
|
+
recordWarnings(await replayAdditionalDelegations(node2, ctx.profile, {
|
|
7978
|
+
host: ctx.host,
|
|
7979
|
+
ownerSpace: profile.spaceId,
|
|
7980
|
+
migrate: options?.privateKey === void 0
|
|
7981
|
+
}));
|
|
7982
|
+
}
|
|
7983
|
+
return node2;
|
|
7506
7984
|
}
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7985
|
+
const replication = createCliReplicationConfig(
|
|
7986
|
+
ctx.profile,
|
|
7987
|
+
profile?.replication,
|
|
7988
|
+
{ debug: ctx.replicationDebug, quiet: ctx.quiet },
|
|
7989
|
+
ctx.replication
|
|
7990
|
+
);
|
|
7991
|
+
if (ctx.replication && !replication) {
|
|
7992
|
+
process.stderr.write("[replication] Enabled, but this profile has no configured prefixes; reads use the network.\n");
|
|
7510
7993
|
}
|
|
7511
|
-
|
|
7512
|
-
|
|
7994
|
+
const node = new TinyCloudNode({
|
|
7995
|
+
host: ctx.host,
|
|
7996
|
+
privateKey: options?.privateKey,
|
|
7997
|
+
...replication ? { replication } : {}
|
|
7998
|
+
});
|
|
7999
|
+
if (node.replication) registerReplication(ctx.profile, node.replication);
|
|
8000
|
+
if (options?.privateKey) {
|
|
8001
|
+
await node.signIn();
|
|
8002
|
+
} else if (session && session.delegationHeader && session.delegationCid && session.spaceId) {
|
|
8003
|
+
await restoreProfileSession(node, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
|
|
8004
|
+
recordWarnings(await replayAdditionalDelegations(node, ctx.profile, {
|
|
8005
|
+
host: ctx.host,
|
|
8006
|
+
ownerSpace: profile?.spaceId,
|
|
8007
|
+
migrate: true
|
|
8008
|
+
}));
|
|
7513
8009
|
}
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
8010
|
+
return node;
|
|
8011
|
+
}
|
|
8012
|
+
async function bootstrapDelegatedSession(ctx, delegation) {
|
|
8013
|
+
const written = await ProfileManager.withLock(ctx.profile, async () => {
|
|
8014
|
+
const previousProfile = await ProfileManager.getProfile(ctx.profile);
|
|
8015
|
+
if (resolveProfilePosture(previousProfile) !== "delegate-session") {
|
|
8016
|
+
throw new CLIError(
|
|
8017
|
+
"AUTH_REQUIRED",
|
|
8018
|
+
`Profile "${ctx.profile}" is not a delegate-session profile.`,
|
|
8019
|
+
ExitCode.AUTH_REQUIRED
|
|
8020
|
+
);
|
|
7519
8021
|
}
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
}
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
/** @deprecated */
|
|
7551
|
-
randomPrivateKey: randomSecretKey,
|
|
7552
|
-
/** @deprecated */
|
|
7553
|
-
precompute(windowSize = 8, point = Point.BASE) {
|
|
7554
|
-
return point.precompute(windowSize, false);
|
|
8022
|
+
const sessionDid = previousProfile.sessionDid ?? previousProfile.did;
|
|
8023
|
+
if (delegation.delegateDID.split("#", 1)[0] !== sessionDid.split("#", 1)[0]) {
|
|
8024
|
+
throw new CLIError(
|
|
8025
|
+
"DELEGATION_AUDIENCE_MISMATCH",
|
|
8026
|
+
`Delegation targets ${delegation.delegateDID}, but profile "${ctx.profile}" uses ${sessionDid}.`,
|
|
8027
|
+
ExitCode.PERMISSION_DENIED
|
|
8028
|
+
);
|
|
8029
|
+
}
|
|
8030
|
+
if (await ProfileManager.getSession(ctx.profile) !== null) {
|
|
8031
|
+
throw new CLIError(
|
|
8032
|
+
"PROFILE_CHANGED_DURING_IMPORT",
|
|
8033
|
+
`Profile "${ctx.profile}" gained a session (another login or import) after this import checked it. Nothing was saved; run the import again.`,
|
|
8034
|
+
ExitCode.ERROR
|
|
8035
|
+
);
|
|
8036
|
+
}
|
|
8037
|
+
if (signedLifetimePassed(delegation)) throw delegationExpiredError();
|
|
8038
|
+
const jwk = signerJwkForProfile(ctx.profile, void 0, await ProfileManager.getKey(ctx.profile));
|
|
8039
|
+
const session = {
|
|
8040
|
+
delegationHeader: delegation.delegationHeader,
|
|
8041
|
+
delegationCid: delegation.cid,
|
|
8042
|
+
spaceId: delegation.spaceId,
|
|
8043
|
+
jwk,
|
|
8044
|
+
verificationMethod: sessionDid
|
|
8045
|
+
};
|
|
8046
|
+
const profile = { ...previousProfile, sessionDid, spaceId: delegation.spaceId };
|
|
8047
|
+
try {
|
|
8048
|
+
await ProfileManager.setSession(ctx.profile, session);
|
|
8049
|
+
await ProfileManager.setProfile(ctx.profile, profile);
|
|
8050
|
+
} catch (error) {
|
|
8051
|
+
throw annotate(error, await restoreBeforeBootstrap(ctx.profile, previousProfile));
|
|
7555
8052
|
}
|
|
7556
|
-
|
|
7557
|
-
return Object.freeze({
|
|
7558
|
-
keygen,
|
|
7559
|
-
getPublicKey,
|
|
7560
|
-
sign,
|
|
7561
|
-
verify,
|
|
7562
|
-
utils,
|
|
7563
|
-
Point,
|
|
7564
|
-
lengths
|
|
8053
|
+
return { previousProfile, profile, session };
|
|
7565
8054
|
});
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
domain: c.domain,
|
|
7584
|
-
prehash: c.prehash,
|
|
7585
|
-
mapToCurve: c.mapToCurve
|
|
8055
|
+
const abandon = async (cause) => {
|
|
8056
|
+
const reported = cause instanceof CLIError && cause.code === "AUTH_REQUIRED" && signedLifetimePassed(delegation) ? delegationExpiredError() : cause;
|
|
8057
|
+
const note = await ProfileManager.withLock(ctx.profile, async () => {
|
|
8058
|
+
const profile = await ProfileManager.getProfile(ctx.profile).catch((error) => {
|
|
8059
|
+
if (error instanceof CLIError && error.code === "PROFILE_NOT_FOUND") return null;
|
|
8060
|
+
throw error;
|
|
8061
|
+
});
|
|
8062
|
+
const session = await ProfileManager.getSession(ctx.profile);
|
|
8063
|
+
if (profile === null || BOOTSTRAP_PROFILE_FIELDS.some((field) => profile[field] !== written.profile[field]) || JSON.stringify(session) !== JSON.stringify(written.session)) {
|
|
8064
|
+
return `Profile "${ctx.profile}" changed while the import was pending (another login, logout or profile update), so its newer state was kept and the provisional session was not rolled back.`;
|
|
8065
|
+
}
|
|
8066
|
+
return restoreBeforeBootstrap(ctx.profile, written.previousProfile);
|
|
8067
|
+
}, { timeoutMs: PROFILE_COMMIT_LOCK_TIMEOUT_MS }).catch((error) => (
|
|
8068
|
+
// The lock or a read failed: the import's error stays the one reported.
|
|
8069
|
+
`Rolling back the provisional session of profile "${ctx.profile}" could not run (${failureName(error)}); check \`tc --profile ${ctx.profile} context\`.`
|
|
8070
|
+
));
|
|
8071
|
+
throw annotate(reported, note);
|
|
7586
8072
|
};
|
|
7587
|
-
|
|
8073
|
+
let node;
|
|
8074
|
+
try {
|
|
8075
|
+
node = await createSDKInstance(ctx);
|
|
8076
|
+
} catch (error) {
|
|
8077
|
+
return abandon(error);
|
|
8078
|
+
}
|
|
8079
|
+
return { node, abandon };
|
|
7588
8080
|
}
|
|
7589
|
-
function
|
|
7590
|
-
const
|
|
7591
|
-
const
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
8081
|
+
async function restoreBeforeBootstrap(profileName, previousProfile) {
|
|
8082
|
+
const failures = [];
|
|
8083
|
+
for (const write of [
|
|
8084
|
+
() => ProfileManager.clearSession(profileName),
|
|
8085
|
+
() => ProfileManager.updateProfile(profileName, (current) => {
|
|
8086
|
+
const restored = { ...current };
|
|
8087
|
+
for (const field of BOOTSTRAP_PROFILE_FIELDS) {
|
|
8088
|
+
if (previousProfile[field] === void 0) delete restored[field];
|
|
8089
|
+
else restored[field] = previousProfile[field];
|
|
8090
|
+
}
|
|
8091
|
+
return restored;
|
|
8092
|
+
})
|
|
8093
|
+
]) {
|
|
8094
|
+
await write().catch((error) => {
|
|
8095
|
+
failures.push(failureName(error));
|
|
8096
|
+
});
|
|
8097
|
+
}
|
|
8098
|
+
if (failures.length === 0) return void 0;
|
|
8099
|
+
return `Rolling back the provisional session of profile "${profileName}" failed too (${failures.join("; ")}); check \`tc --profile ${profileName} context\`.`;
|
|
7598
8100
|
}
|
|
7599
|
-
function
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
return _eddsa_new_output_to_legacy(c, EDDSA);
|
|
8101
|
+
function failureName(error) {
|
|
8102
|
+
if (error instanceof SyntaxError) return "a profile file is not valid JSON";
|
|
8103
|
+
if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") return error.code;
|
|
8104
|
+
return error instanceof Error ? error.name : "unknown error";
|
|
7604
8105
|
}
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
var _2n3 = BigInt(2);
|
|
7610
|
-
var _3n2 = BigInt(3);
|
|
7611
|
-
var _5n2 = BigInt(5);
|
|
7612
|
-
var _8n3 = BigInt(8);
|
|
7613
|
-
var ed25519_CURVE_p = BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed");
|
|
7614
|
-
var ed25519_CURVE = /* @__PURE__ */ (() => ({
|
|
7615
|
-
p: ed25519_CURVE_p,
|
|
7616
|
-
n: BigInt("0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"),
|
|
7617
|
-
h: _8n3,
|
|
7618
|
-
a: BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec"),
|
|
7619
|
-
d: BigInt("0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3"),
|
|
7620
|
-
Gx: BigInt("0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a"),
|
|
7621
|
-
Gy: BigInt("0x6666666666666666666666666666666666666666666666666666666666666658")
|
|
7622
|
-
}))();
|
|
7623
|
-
function ed25519_pow_2_252_3(x) {
|
|
7624
|
-
const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80);
|
|
7625
|
-
const P = ed25519_CURVE_p;
|
|
7626
|
-
const x2 = x * x % P;
|
|
7627
|
-
const b2 = x2 * x % P;
|
|
7628
|
-
const b4 = pow2(b2, _2n3, P) * b2 % P;
|
|
7629
|
-
const b5 = pow2(b4, _1n5, P) * x % P;
|
|
7630
|
-
const b10 = pow2(b5, _5n2, P) * b5 % P;
|
|
7631
|
-
const b20 = pow2(b10, _10n, P) * b10 % P;
|
|
7632
|
-
const b40 = pow2(b20, _20n, P) * b20 % P;
|
|
7633
|
-
const b80 = pow2(b40, _40n, P) * b40 % P;
|
|
7634
|
-
const b160 = pow2(b80, _80n, P) * b80 % P;
|
|
7635
|
-
const b240 = pow2(b160, _80n, P) * b80 % P;
|
|
7636
|
-
const b250 = pow2(b240, _10n, P) * b10 % P;
|
|
7637
|
-
const pow_p_5_8 = pow2(b250, _2n3, P) * x % P;
|
|
7638
|
-
return { pow_p_5_8, b2 };
|
|
8106
|
+
function annotate(error, note) {
|
|
8107
|
+
if (note === void 0) return error;
|
|
8108
|
+
const cause = wrapError(error);
|
|
8109
|
+
return new CLIError(cause.code, `${cause.message} ${note}`, cause.exitCode, cause.metadata);
|
|
7639
8110
|
}
|
|
7640
|
-
function
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
8111
|
+
async function ensureAuthenticated(ctx, options) {
|
|
8112
|
+
if (options?.privateKey) {
|
|
8113
|
+
return createSDKInstance(ctx, options);
|
|
8114
|
+
}
|
|
8115
|
+
const profile = await ProfileManager.getProfile(ctx.profile).catch(() => null);
|
|
8116
|
+
if (profile?.authMethod === "local" && profile.privateKey) {
|
|
8117
|
+
return createSDKInstance(ctx);
|
|
8118
|
+
}
|
|
8119
|
+
const session = await ProfileManager.getSession(ctx.profile);
|
|
8120
|
+
if (!session) {
|
|
8121
|
+
throw new CLIError(
|
|
8122
|
+
"AUTH_REQUIRED",
|
|
8123
|
+
`Not authenticated. Run \`tc auth login\` or \`tc init\` first.`,
|
|
8124
|
+
ExitCode.AUTH_REQUIRED
|
|
8125
|
+
);
|
|
8126
|
+
}
|
|
8127
|
+
return createSDKInstance(ctx, options);
|
|
7645
8128
|
}
|
|
7646
|
-
var
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
8129
|
+
var BOOTSTRAP_PROFILE_FIELDS;
|
|
8130
|
+
var init_sdk = __esm({
|
|
8131
|
+
"src/lib/sdk.ts"() {
|
|
8132
|
+
"use strict";
|
|
8133
|
+
init_profiles();
|
|
8134
|
+
init_types();
|
|
8135
|
+
init_errors();
|
|
8136
|
+
init_constants();
|
|
8137
|
+
init_permissions();
|
|
8138
|
+
init_session_expired();
|
|
8139
|
+
init_warnings();
|
|
8140
|
+
init_delegation_expiry();
|
|
8141
|
+
init_replication_config();
|
|
8142
|
+
init_replication_registry();
|
|
8143
|
+
init_replication_registry();
|
|
8144
|
+
BOOTSTRAP_PROFILE_FIELDS = ["sessionDid", "spaceId"];
|
|
8145
|
+
}
|
|
8146
|
+
});
|
|
8147
|
+
|
|
8148
|
+
// src/lib/host.ts
|
|
8149
|
+
var host_exports = {};
|
|
8150
|
+
__export(host_exports, {
|
|
8151
|
+
completeDeferredLocalDiscovery: () => completeDeferredLocalDiscovery,
|
|
8152
|
+
discoverLocalNodeHost: () => discoverLocalNodeHost,
|
|
8153
|
+
isRootAuthority: () => isRootAuthority,
|
|
8154
|
+
ownerDidFromSpaceUri: () => ownerDidFromSpaceUri,
|
|
8155
|
+
profileLocalNodeIdentityStore: () => profileLocalNodeIdentityStore,
|
|
8156
|
+
resolveHostSpace: () => resolveHostSpace,
|
|
8157
|
+
spaceNameFromUri: () => spaceNameFromUri,
|
|
8158
|
+
unhostedSpaceError: () => unhostedSpaceError
|
|
8159
|
+
});
|
|
8160
|
+
import {
|
|
8161
|
+
discoverLocalTinyCloudNode
|
|
8162
|
+
} from "@tinycloud/sdk-core";
|
|
8163
|
+
function profileLocalNodeIdentityStore(profileName) {
|
|
8164
|
+
return {
|
|
8165
|
+
get: async (url) => {
|
|
8166
|
+
const profile = await ProfileManager.getProfile(profileName).catch(
|
|
8167
|
+
() => null
|
|
8168
|
+
);
|
|
8169
|
+
return profile?.pinnedLocalNodeDids?.[url];
|
|
8170
|
+
},
|
|
8171
|
+
set: async (url, nodeDid) => {
|
|
8172
|
+
if (!await ProfileManager.profileExists(profileName)) return;
|
|
8173
|
+
await ProfileManager.updateProfile(profileName, (profile) => ({
|
|
8174
|
+
...profile,
|
|
8175
|
+
pinnedLocalNodeDids: {
|
|
8176
|
+
...profile.pinnedLocalNodeDids,
|
|
8177
|
+
[url]: nodeDid
|
|
8178
|
+
}
|
|
8179
|
+
}));
|
|
8180
|
+
}
|
|
8181
|
+
};
|
|
7666
8182
|
}
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
var INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt("54469307008909316920995813868745141605393597292927456921205312896311721017578");
|
|
7683
|
-
var ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt("1159843021668779879193775521855586647937357759715417654439879720876111806838");
|
|
7684
|
-
var D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt("40440834346308536858101042469323190826248399146238708352240133220865137265952");
|
|
7685
|
-
var invertSqrt = (number) => uvRatio(_1n5, number);
|
|
7686
|
-
var MAX_255B = /* @__PURE__ */ BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
7687
|
-
var bytes255ToNumberLE = (bytes) => ed25519.Point.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
|
|
7688
|
-
function calcElligatorRistrettoMap(r0) {
|
|
7689
|
-
const { d } = ed25519_CURVE;
|
|
7690
|
-
const P = ed25519_CURVE_p;
|
|
7691
|
-
const mod2 = (n) => Fp.create(n);
|
|
7692
|
-
const r = mod2(SQRT_M1 * r0 * r0);
|
|
7693
|
-
const Ns = mod2((r + _1n5) * ONE_MINUS_D_SQ);
|
|
7694
|
-
let c = BigInt(-1);
|
|
7695
|
-
const D = mod2((c - d * r) * mod2(r + d));
|
|
7696
|
-
let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D);
|
|
7697
|
-
let s_ = mod2(s * r0);
|
|
7698
|
-
if (!isNegativeLE(s_, P))
|
|
7699
|
-
s_ = mod2(-s_);
|
|
7700
|
-
if (!Ns_D_is_sq)
|
|
7701
|
-
s = s_;
|
|
7702
|
-
if (!Ns_D_is_sq)
|
|
7703
|
-
c = r;
|
|
7704
|
-
const Nt = mod2(c * (r - _1n5) * D_MINUS_ONE_SQ - D);
|
|
7705
|
-
const s2 = s * s;
|
|
7706
|
-
const W0 = mod2((s + s) * D);
|
|
7707
|
-
const W1 = mod2(Nt * SQRT_AD_MINUS_ONE);
|
|
7708
|
-
const W2 = mod2(_1n5 - s2);
|
|
7709
|
-
const W3 = mod2(_1n5 + s2);
|
|
7710
|
-
return new ed25519.Point(mod2(W0 * W3), mod2(W2 * W1), mod2(W1 * W3), mod2(W0 * W2));
|
|
8183
|
+
async function discoverLocalNodeHost(profileName, options) {
|
|
8184
|
+
const profile = await ProfileManager.getProfile(profileName).catch(() => null);
|
|
8185
|
+
if (profile?.autoDiscoverLocalNode === false) return { host: null, deferred: false };
|
|
8186
|
+
if (!profile?.localNodeUrl && !profile?.localLinkName) return { host: null, deferred: false };
|
|
8187
|
+
if (options.awaitStoredSession) {
|
|
8188
|
+
const { storedSessionVerifiesLocally: storedSessionVerifiesLocally2 } = await Promise.resolve().then(() => (init_sdk(), sdk_exports));
|
|
8189
|
+
if (!await storedSessionVerifiesLocally2(profileName)) return { host: null, deferred: true };
|
|
8190
|
+
}
|
|
8191
|
+
const discovered = await discoverLocalTinyCloudNode({
|
|
8192
|
+
localNodeUrl: profile?.localNodeUrl,
|
|
8193
|
+
localLinkName: profile?.localLinkName,
|
|
8194
|
+
expectedNodeDid: profile?.expectedNodeDid,
|
|
8195
|
+
identityStore: profileLocalNodeIdentityStore(profileName)
|
|
8196
|
+
});
|
|
8197
|
+
return { host: discovered?.url ?? null, deferred: false };
|
|
7711
8198
|
}
|
|
7712
|
-
function
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
const
|
|
7718
|
-
|
|
8199
|
+
async function completeDeferredLocalDiscovery(ctx) {
|
|
8200
|
+
const deferred = ctx.localDiscovery;
|
|
8201
|
+
if (deferred === void 0) return;
|
|
8202
|
+
delete ctx.localDiscovery;
|
|
8203
|
+
if (ctx.host !== deferred.deferredFrom) return;
|
|
8204
|
+
const discovered = await discoverLocalNodeHost(ctx.profile, { awaitStoredSession: false });
|
|
8205
|
+
if (discovered.host !== null) ctx.host = discovered.host;
|
|
7719
8206
|
}
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
throw new Error("RistrettoPoint expected");
|
|
7730
|
-
}
|
|
7731
|
-
init(ep) {
|
|
7732
|
-
return new __RistrettoPoint(ep);
|
|
7733
|
-
}
|
|
7734
|
-
/** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
|
|
7735
|
-
static hashToCurve(hex3) {
|
|
7736
|
-
return ristretto255_map(ensureBytes("ristrettoHash", hex3, 64));
|
|
7737
|
-
}
|
|
7738
|
-
static fromBytes(bytes) {
|
|
7739
|
-
abytes(bytes, 32);
|
|
7740
|
-
const { a, d } = ed25519_CURVE;
|
|
7741
|
-
const P = ed25519_CURVE_p;
|
|
7742
|
-
const mod2 = (n) => Fp.create(n);
|
|
7743
|
-
const s = bytes255ToNumberLE(bytes);
|
|
7744
|
-
if (!equalBytes(Fp.toBytes(s), bytes) || isNegativeLE(s, P))
|
|
7745
|
-
throw new Error("invalid ristretto255 encoding 1");
|
|
7746
|
-
const s2 = mod2(s * s);
|
|
7747
|
-
const u1 = mod2(_1n5 + a * s2);
|
|
7748
|
-
const u2 = mod2(_1n5 - a * s2);
|
|
7749
|
-
const u1_2 = mod2(u1 * u1);
|
|
7750
|
-
const u2_2 = mod2(u2 * u2);
|
|
7751
|
-
const v = mod2(a * d * u1_2 - u2_2);
|
|
7752
|
-
const { isValid: isValid3, value: I } = invertSqrt(mod2(v * u2_2));
|
|
7753
|
-
const Dx = mod2(I * u2);
|
|
7754
|
-
const Dy = mod2(I * Dx * v);
|
|
7755
|
-
let x = mod2((s + s) * Dx);
|
|
7756
|
-
if (isNegativeLE(x, P))
|
|
7757
|
-
x = mod2(-x);
|
|
7758
|
-
const y = mod2(u1 * Dy);
|
|
7759
|
-
const t = mod2(x * y);
|
|
7760
|
-
if (!isValid3 || isNegativeLE(t, P) || y === _0n5)
|
|
7761
|
-
throw new Error("invalid ristretto255 encoding 2");
|
|
7762
|
-
return new __RistrettoPoint(new ed25519.Point(x, y, _1n5, t));
|
|
7763
|
-
}
|
|
7764
|
-
/**
|
|
7765
|
-
* Converts ristretto-encoded string to ristretto point.
|
|
7766
|
-
* Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-decode).
|
|
7767
|
-
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
|
7768
|
-
*/
|
|
7769
|
-
static fromHex(hex3) {
|
|
7770
|
-
return __RistrettoPoint.fromBytes(ensureBytes("ristrettoHex", hex3, 32));
|
|
8207
|
+
function canonicalizeAddress2(address) {
|
|
8208
|
+
const trimmed = address.trim();
|
|
8209
|
+
return trimmed.startsWith("0x") ? `0x${trimmed.slice(2).toLowerCase()}` : trimmed.toLowerCase();
|
|
8210
|
+
}
|
|
8211
|
+
async function resolveLocalAddress(profile, profileName) {
|
|
8212
|
+
const session = await ProfileManager.getSession(profileName);
|
|
8213
|
+
const sessAddr = session?.address;
|
|
8214
|
+
if (typeof sessAddr === "string" && sessAddr.length > 0) {
|
|
8215
|
+
return canonicalizeAddress2(sessAddr);
|
|
7771
8216
|
}
|
|
7772
|
-
|
|
7773
|
-
|
|
8217
|
+
if (profile.address) return canonicalizeAddress2(profile.address);
|
|
8218
|
+
if (profile.ownerDid) {
|
|
8219
|
+
const match = profile.ownerDid.match(/^did:pkh:eip155:\d+:(0x[a-fA-F0-9]{40})$/);
|
|
8220
|
+
if (match) return canonicalizeAddress2(match[1]);
|
|
7774
8221
|
}
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
8222
|
+
return null;
|
|
8223
|
+
}
|
|
8224
|
+
function ownerAddressFromSpaceUri(spaceUri) {
|
|
8225
|
+
const match = spaceUri.match(/^tinycloud:pkh:eip155:\d+:(0x[a-fA-F0-9]{40}):/);
|
|
8226
|
+
return match ? canonicalizeAddress2(match[1]) : null;
|
|
8227
|
+
}
|
|
8228
|
+
function ownerDidFromSpaceUri(spaceUri) {
|
|
8229
|
+
const match = spaceUri.match(/^tinycloud:pkh:eip155:(\d+):(0x[a-fA-F0-9]{40}):/);
|
|
8230
|
+
if (!match) return null;
|
|
8231
|
+
return `did:pkh:eip155:${match[1]}:${canonicalizeAddress2(match[2])}`;
|
|
8232
|
+
}
|
|
8233
|
+
async function isRootAuthority(spaceUri, profileName) {
|
|
8234
|
+
const profile = await ProfileManager.getProfile(profileName);
|
|
8235
|
+
if (resolveProfilePosture(profile) === "delegate-session") return false;
|
|
8236
|
+
const ownerAddr = ownerAddressFromSpaceUri(spaceUri);
|
|
8237
|
+
if (!ownerAddr) return false;
|
|
8238
|
+
const selfAddr = await resolveLocalAddress(profile, profileName);
|
|
8239
|
+
return selfAddr !== null && selfAddr === ownerAddr;
|
|
8240
|
+
}
|
|
8241
|
+
function spaceNameFromUri(spaceUri) {
|
|
8242
|
+
return spaceUri.slice(spaceUri.lastIndexOf(":") + 1);
|
|
8243
|
+
}
|
|
8244
|
+
async function unhostedSpaceError(error, spaceUri, profileName) {
|
|
8245
|
+
if (!spaceUri) return null;
|
|
8246
|
+
const status = error.meta?.status;
|
|
8247
|
+
const isUnhosted = status === 404 && /space not found/i.test(error.message);
|
|
8248
|
+
if (!isUnhosted) return null;
|
|
8249
|
+
const spaceName = spaceNameFromUri(spaceUri);
|
|
8250
|
+
const owner = await isRootAuthority(spaceUri, profileName);
|
|
8251
|
+
const hint = owner ? [
|
|
8252
|
+
"You are the owner. Host it once:",
|
|
8253
|
+
` tc space host ${spaceName}`,
|
|
8254
|
+
"Then retry."
|
|
8255
|
+
].join("\n") : [
|
|
8256
|
+
"You are a delegate and CANNOT host this space \u2014 only its owner can.",
|
|
8257
|
+
"Emit a host request:",
|
|
8258
|
+
` tc space host-request ${spaceName} --emit ./host-request.json`,
|
|
8259
|
+
"Send it to the owner; they run `tc space host` and confirm. Then retry."
|
|
8260
|
+
].join("\n");
|
|
8261
|
+
const message = owner ? `Space '${spaceName}' (${spaceUri}) is not hosted.` : `Space '${spaceName}' (owner ${ownerDidFromSpaceUri(spaceUri) ?? spaceUri}) is not hosted.`;
|
|
8262
|
+
return new CLIError("SPACE_NOT_HOSTED", message, ExitCode.ERROR, { hint });
|
|
8263
|
+
}
|
|
8264
|
+
async function resolveHostSpace(name, profileName) {
|
|
8265
|
+
const resolved = await resolveSpaceUri(name, profileName);
|
|
8266
|
+
if (!resolved) {
|
|
8267
|
+
throw new Error(`Could not resolve a space for "${name}".`);
|
|
7806
8268
|
}
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
const two = mod2(Y1 * Y2) === mod2(X1 * X2);
|
|
7818
|
-
return one || two;
|
|
8269
|
+
return resolved;
|
|
8270
|
+
}
|
|
8271
|
+
var init_host = __esm({
|
|
8272
|
+
"src/lib/host.ts"() {
|
|
8273
|
+
"use strict";
|
|
8274
|
+
init_profiles();
|
|
8275
|
+
init_constants();
|
|
8276
|
+
init_types();
|
|
8277
|
+
init_errors();
|
|
8278
|
+
init_space();
|
|
7819
8279
|
}
|
|
7820
|
-
|
|
7821
|
-
|
|
8280
|
+
});
|
|
8281
|
+
|
|
8282
|
+
// src/config/profiles.ts
|
|
8283
|
+
import { chmod as chmod2, lstat, readdir as readdir2, rm as rm2, rmdir } from "fs/promises";
|
|
8284
|
+
import { join as join6 } from "path";
|
|
8285
|
+
import {
|
|
8286
|
+
profilePath as profilePath2,
|
|
8287
|
+
readSession,
|
|
8288
|
+
recordProfileDeletion,
|
|
8289
|
+
refuseWriteToDeletedProfile as refuseWriteToDeletedProfile2,
|
|
8290
|
+
removeSession,
|
|
8291
|
+
withProfileLock as withProfileLock3,
|
|
8292
|
+
writeSession
|
|
8293
|
+
} from "@tinycloud/operations/state";
|
|
8294
|
+
var ProfileManager;
|
|
8295
|
+
var init_profiles = __esm({
|
|
8296
|
+
"src/config/profiles.ts"() {
|
|
8297
|
+
"use strict";
|
|
8298
|
+
init_constants();
|
|
8299
|
+
init_storage2();
|
|
8300
|
+
init_errors();
|
|
8301
|
+
ProfileManager = class _ProfileManager {
|
|
8302
|
+
// ── Initialization ──────────────────────────────────────────────────
|
|
8303
|
+
/**
|
|
8304
|
+
* Runs `action` holding the profile's store lock (shared with operations
|
|
8305
|
+
* and MCP). Reentrant, so the writers below can be called inside it; hold
|
|
8306
|
+
* it around a whole read-modify-write, not just each write.
|
|
8307
|
+
*/
|
|
8308
|
+
static async withLock(name, action, options) {
|
|
8309
|
+
return withProfileLock3(name, action, options);
|
|
8310
|
+
}
|
|
8311
|
+
/**
|
|
8312
|
+
* Read-modify-write of profile.json under the profile lock, so concurrent
|
|
8313
|
+
* updates (another command, a login commit) are never erased.
|
|
8314
|
+
*/
|
|
8315
|
+
static async updateProfile(name, update) {
|
|
8316
|
+
return _ProfileManager.withLock(name, async () => {
|
|
8317
|
+
const next = update(await _ProfileManager.getProfile(name));
|
|
8318
|
+
await _ProfileManager.setProfile(name, next);
|
|
8319
|
+
return next;
|
|
8320
|
+
});
|
|
8321
|
+
}
|
|
8322
|
+
/**
|
|
8323
|
+
* Creates ~/.tinycloud/ and ~/.tinycloud/profiles/ if they don't exist and
|
|
8324
|
+
* (re)sets both to 0700: older releases created them 0775.
|
|
8325
|
+
*/
|
|
8326
|
+
static async ensureConfigDir() {
|
|
8327
|
+
for (const directory of [CONFIG_DIR, PROFILES_DIR]) {
|
|
8328
|
+
await ensureDir(directory);
|
|
8329
|
+
await chmod2(directory, PRIVATE_DIR_MODE);
|
|
8330
|
+
}
|
|
8331
|
+
}
|
|
8332
|
+
/** Owner-only profile directory (0700), created or tightened before any write into it. */
|
|
8333
|
+
static async ensureProfileDir(name) {
|
|
8334
|
+
await _ProfileManager.ensureConfigDir();
|
|
8335
|
+
const profileDir = join6(PROFILES_DIR, name);
|
|
8336
|
+
await ensureDir(profileDir);
|
|
8337
|
+
await chmod2(profileDir, PRIVATE_DIR_MODE);
|
|
8338
|
+
return profileDir;
|
|
8339
|
+
}
|
|
8340
|
+
// ── Global config ───────────────────────────────────────────────────
|
|
8341
|
+
/**
|
|
8342
|
+
* Reads config.json. Returns a default config if the file is missing.
|
|
8343
|
+
*/
|
|
8344
|
+
static async getConfig() {
|
|
8345
|
+
const config = await readJson(CONFIG_FILE);
|
|
8346
|
+
if (!config) {
|
|
8347
|
+
return { defaultProfile: DEFAULT_PROFILE, version: 1 };
|
|
8348
|
+
}
|
|
8349
|
+
return config;
|
|
8350
|
+
}
|
|
8351
|
+
/**
|
|
8352
|
+
* Writes the global config to config.json.
|
|
8353
|
+
*/
|
|
8354
|
+
static async setConfig(config) {
|
|
8355
|
+
await _ProfileManager.ensureConfigDir();
|
|
8356
|
+
await writeJson(CONFIG_FILE, config);
|
|
8357
|
+
}
|
|
8358
|
+
// ── Profile CRUD ────────────────────────────────────────────────────
|
|
8359
|
+
/**
|
|
8360
|
+
* Returns the profile config for the given name.
|
|
8361
|
+
* Throws CLIError if the profile doesn't exist.
|
|
8362
|
+
*/
|
|
8363
|
+
static async getProfile(name) {
|
|
8364
|
+
const profilePath3 = join6(PROFILES_DIR, name, "profile.json");
|
|
8365
|
+
const profile = await readJson(profilePath3);
|
|
8366
|
+
if (!profile) {
|
|
8367
|
+
throw new CLIError(
|
|
8368
|
+
"PROFILE_NOT_FOUND",
|
|
8369
|
+
`Profile "${name}" does not exist. Create it with \`tc init --name ${name}\`.`
|
|
8370
|
+
);
|
|
8371
|
+
}
|
|
8372
|
+
return profile;
|
|
8373
|
+
}
|
|
8374
|
+
/**
|
|
8375
|
+
* Saves a profile config under the profile lock, creating the profile
|
|
8376
|
+
* directory if needed. Use `updateProfile` to change an existing profile.
|
|
8377
|
+
*/
|
|
8378
|
+
static async setProfile(name, data) {
|
|
8379
|
+
await _ProfileManager.withLock(name, async () => {
|
|
8380
|
+
await writeJson(join6(await _ProfileManager.ensureProfileDir(name), "profile.json"), data);
|
|
8381
|
+
});
|
|
8382
|
+
}
|
|
8383
|
+
/** Removes profile.json under the profile lock (rollback of a profile a failed login created). */
|
|
8384
|
+
static async removeProfileConfig(name) {
|
|
8385
|
+
await _ProfileManager.withLock(name, () => rm2(join6(PROFILES_DIR, name, "profile.json"), { force: true }));
|
|
8386
|
+
}
|
|
8387
|
+
/**
|
|
8388
|
+
* Returns true if a profile directory exists.
|
|
8389
|
+
*/
|
|
8390
|
+
static async profileExists(name) {
|
|
8391
|
+
return fileExists(join6(PROFILES_DIR, name, "profile.json"));
|
|
8392
|
+
}
|
|
8393
|
+
/**
|
|
8394
|
+
* Returns an array of profile directory names.
|
|
8395
|
+
*/
|
|
8396
|
+
static async listProfiles() {
|
|
8397
|
+
return listDirs(PROFILES_DIR);
|
|
8398
|
+
}
|
|
8399
|
+
/**
|
|
8400
|
+
* Deletes a profile. Its key, session, settings, stores and cache are
|
|
8401
|
+
* removed while holding the profile lock, so another writer's critical
|
|
8402
|
+
* section never sees them vanish midway: session and key first, settings
|
|
8403
|
+
* last, so a crash midway never leaves a session or key without its
|
|
8404
|
+
* profile. The deletion is then recorded, so a store write that waited for
|
|
8405
|
+
* the lock meanwhile refuses rather than recreating a profile with only a
|
|
8406
|
+
* session in it. `.lock` itself is left to the lock's release; the
|
|
8407
|
+
* then-empty directory is removed afterwards unless another writer took
|
|
8408
|
+
* the lock (or wrote) meanwhile. A profile directory that is a symlink is
|
|
8409
|
+
* unlinked, its target left alone.
|
|
8410
|
+
* Throws if the name is not one path segment or names the default profile.
|
|
8411
|
+
*/
|
|
8412
|
+
static async deleteProfile(name) {
|
|
8413
|
+
let profileDir;
|
|
8414
|
+
try {
|
|
8415
|
+
profileDir = profilePath2(name);
|
|
8416
|
+
} catch {
|
|
8417
|
+
throw new CLIError(
|
|
8418
|
+
"INVALID_PROFILE_NAME",
|
|
8419
|
+
`Invalid profile name "${name}": a profile name is one path segment (no "/", "\\", "." or "..").`,
|
|
8420
|
+
ExitCode.USAGE_ERROR
|
|
8421
|
+
);
|
|
8422
|
+
}
|
|
8423
|
+
const config = await _ProfileManager.getConfig();
|
|
8424
|
+
if (config.defaultProfile === name) {
|
|
8425
|
+
throw new CLIError(
|
|
8426
|
+
"PROFILE_DELETE_DEFAULT",
|
|
8427
|
+
`Cannot delete the default profile "${name}". Change the default first with \`tc profile default <other>\`.`
|
|
8428
|
+
);
|
|
8429
|
+
}
|
|
8430
|
+
const kind = await lstat(profileDir).then((stats) => stats.isSymbolicLink() ? "link" : "present", (error) => {
|
|
8431
|
+
if (error.code === "ENOENT") return "missing";
|
|
8432
|
+
throw error;
|
|
8433
|
+
});
|
|
8434
|
+
if (kind === "missing") return;
|
|
8435
|
+
if (kind === "link") {
|
|
8436
|
+
await rm2(profileDir, { force: true });
|
|
8437
|
+
return;
|
|
8438
|
+
}
|
|
8439
|
+
await _ProfileManager.withLock(name, async () => {
|
|
8440
|
+
for (const file of ["session.json", "key.json"]) await rm2(join6(profileDir, file), { force: true });
|
|
8441
|
+
for (const entry of await readdir2(profileDir)) {
|
|
8442
|
+
if (entry !== ".lock" && entry !== "profile.json") await rm2(join6(profileDir, entry), { recursive: true, force: true });
|
|
8443
|
+
}
|
|
8444
|
+
await rm2(join6(profileDir, "profile.json"), { force: true });
|
|
8445
|
+
await recordProfileDeletion(name);
|
|
8446
|
+
});
|
|
8447
|
+
await rmdir(profileDir).catch((error) => {
|
|
8448
|
+
if (error.code !== "ENOENT" && error.code !== "ENOTEMPTY" && error.code !== "EEXIST") throw error;
|
|
8449
|
+
});
|
|
8450
|
+
}
|
|
8451
|
+
// ── Key management ──────────────────────────────────────────────────
|
|
8452
|
+
/**
|
|
8453
|
+
* Returns the parsed JWK for a profile, or null if no key exists.
|
|
8454
|
+
*/
|
|
8455
|
+
static async getKey(name) {
|
|
8456
|
+
return readJson(join6(PROFILES_DIR, name, "key.json"));
|
|
8457
|
+
}
|
|
8458
|
+
/**
|
|
8459
|
+
* Saves a JWK key under the profile lock (0600, in an owner-only profile
|
|
8460
|
+
* directory). Refused (PROFILE_NOT_FOUND) if the profile was deleted while
|
|
8461
|
+
* this waited for the lock, rather than leaving a key-only profile.
|
|
8462
|
+
*/
|
|
8463
|
+
static async setKey(name, jwk) {
|
|
8464
|
+
await _ProfileManager.withLock(name, async () => {
|
|
8465
|
+
await refuseWriteToDeletedProfile2(name);
|
|
8466
|
+
await writeJson(join6(await _ProfileManager.ensureProfileDir(name), "key.json"), jwk);
|
|
8467
|
+
});
|
|
8468
|
+
}
|
|
8469
|
+
/** Removes key.json under the profile lock (rollback of a key a failed login created). */
|
|
8470
|
+
static async removeKey(name) {
|
|
8471
|
+
await _ProfileManager.withLock(name, () => rm2(join6(PROFILES_DIR, name, "key.json"), { force: true }));
|
|
8472
|
+
}
|
|
8473
|
+
// ── Session management ──────────────────────────────────────────────
|
|
8474
|
+
/**
|
|
8475
|
+
* Returns the parsed session for a profile, or null if none exists.
|
|
8476
|
+
*/
|
|
8477
|
+
static async getSession(name) {
|
|
8478
|
+
return readSession(name);
|
|
8479
|
+
}
|
|
8480
|
+
/**
|
|
8481
|
+
* Saves session data for a profile.
|
|
8482
|
+
*/
|
|
8483
|
+
static async setSession(name, session) {
|
|
8484
|
+
await writeSession(name, session);
|
|
8485
|
+
}
|
|
8486
|
+
/**
|
|
8487
|
+
* Removes the session file for a profile.
|
|
8488
|
+
*/
|
|
8489
|
+
static async clearSession(name) {
|
|
8490
|
+
await removeSession(name);
|
|
8491
|
+
}
|
|
8492
|
+
// ── Cache management ────────────────────────────────────────────────
|
|
8493
|
+
/**
|
|
8494
|
+
* Returns the profile's cache directory (share history lives here),
|
|
8495
|
+
* created or tightened to 0700.
|
|
8496
|
+
*/
|
|
8497
|
+
static async getCacheDir(name) {
|
|
8498
|
+
const cacheDir = join6(await _ProfileManager.ensureProfileDir(name), "cache");
|
|
8499
|
+
await ensureDir(cacheDir);
|
|
8500
|
+
await chmod2(cacheDir, PRIVATE_DIR_MODE);
|
|
8501
|
+
return cacheDir;
|
|
8502
|
+
}
|
|
8503
|
+
// ── Resolution helpers ──────────────────────────────────────────────
|
|
8504
|
+
/**
|
|
8505
|
+
* Resolves the full CLI context from flags, env vars, and config.
|
|
8506
|
+
*
|
|
8507
|
+
* Profile resolution: options.profile > TC_PROFILE env > config.defaultProfile > "default"
|
|
8508
|
+
* Host resolution: options.host > TC_HOST env > discovered local node > profile.host > DEFAULT_HOST
|
|
8509
|
+
*
|
|
8510
|
+
* Local-node discovery (TC-106) only runs when no explicit host was given
|
|
8511
|
+
* (`--host` / `TC_HOST`); it probes configured or registered local nodes and,
|
|
8512
|
+
* after DID verification against the profile's pinned identity, prefers one
|
|
8513
|
+
* over the stored/default host. For session-using commands, it verifies the
|
|
8514
|
+
* stored session locally before probing. Loopback requires an explicit
|
|
8515
|
+
* `localNodeUrl`; disable discovery with `autoDiscoverLocalNode: false`.
|
|
8516
|
+
*/
|
|
8517
|
+
static async resolveContext(options, settings = {}) {
|
|
8518
|
+
const config = await _ProfileManager.getConfig();
|
|
8519
|
+
const profile = options.profile ?? process.env.TC_PROFILE ?? config.defaultProfile ?? DEFAULT_PROFILE;
|
|
8520
|
+
let profileHost;
|
|
8521
|
+
let profileConfig;
|
|
8522
|
+
try {
|
|
8523
|
+
profileConfig = await _ProfileManager.getProfile(profile);
|
|
8524
|
+
profileHost = profileConfig.host;
|
|
8525
|
+
} catch {
|
|
8526
|
+
}
|
|
8527
|
+
const envReplication = process.env.TC_REPLICATION?.toLowerCase();
|
|
8528
|
+
const envEnabled = envReplication === "1" || envReplication === "true" || envReplication === "on";
|
|
8529
|
+
const explicitEnvOff = envReplication === "0" || envReplication === "false" || envReplication === "off";
|
|
8530
|
+
if (envReplication !== void 0 && !envEnabled && !explicitEnvOff) {
|
|
8531
|
+
throw new CLIError("INVALID_ARGUMENT", "TC_REPLICATION must be one of 1, true, on, 0, false or off.", ExitCode.USAGE_ERROR);
|
|
8532
|
+
}
|
|
8533
|
+
const explicitOff = options.noReplication === true || options.replication === false;
|
|
8534
|
+
const replication = options.replication === true ? true : explicitOff ? false : envEnabled;
|
|
8535
|
+
const explicitHost = options.host ?? process.env.TC_HOST;
|
|
8536
|
+
let host = explicitHost ?? profileHost ?? DEFAULT_HOST;
|
|
8537
|
+
let localDiscovery;
|
|
8538
|
+
if (explicitHost === void 0) {
|
|
8539
|
+
const { discoverLocalNodeHost: discoverLocalNodeHost2 } = await Promise.resolve().then(() => (init_host(), host_exports));
|
|
8540
|
+
const explicitKey = Boolean(options.privateKey || process.env.TC_PRIVATE_KEY);
|
|
8541
|
+
const discovered = await discoverLocalNodeHost2(profile, {
|
|
8542
|
+
awaitStoredSession: settings.storedSession !== "unused" && !explicitKey
|
|
8543
|
+
});
|
|
8544
|
+
if (discovered.host !== null) host = discovered.host;
|
|
8545
|
+
if (discovered.deferred) localDiscovery = { deferredFrom: host };
|
|
8546
|
+
}
|
|
8547
|
+
setActiveProfileName(profile);
|
|
8548
|
+
return {
|
|
8549
|
+
profile,
|
|
8550
|
+
host,
|
|
8551
|
+
verbose: options.verbose ?? false,
|
|
8552
|
+
noCache: options.noCache ?? false,
|
|
8553
|
+
quiet: options.quiet ?? false,
|
|
8554
|
+
replication,
|
|
8555
|
+
replicationDebug: options.replicationDebug === true || process.env.TC_REPLICATION_DEBUG === "1",
|
|
8556
|
+
...localDiscovery === void 0 ? {} : { localDiscovery }
|
|
8557
|
+
};
|
|
8558
|
+
}
|
|
8559
|
+
};
|
|
7822
8560
|
}
|
|
7823
|
-
};
|
|
7824
|
-
_RistrettoPoint.BASE = /* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.BASE))();
|
|
7825
|
-
_RistrettoPoint.ZERO = /* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.ZERO))();
|
|
7826
|
-
_RistrettoPoint.Fp = /* @__PURE__ */ (() => Fp)();
|
|
7827
|
-
_RistrettoPoint.Fn = /* @__PURE__ */ (() => Fn)();
|
|
8561
|
+
});
|
|
7828
8562
|
|
|
7829
|
-
//
|
|
7830
|
-
|
|
7831
|
-
init_u64();
|
|
8563
|
+
// src/commands/courier.ts
|
|
8564
|
+
var TC_OPTIONS_BEFORE_COURIER = 'tc courier takes no tc options and does not use tc profiles; Courier keeps its own profile in $COURIER_HOME (default ~/.courier). Put flags after "courier", e.g. tc courier init --host <url>.';
|
|
7832
8565
|
|
|
7833
|
-
//
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
d = rotr(d ^ a, 16);
|
|
7838
|
-
c = c + d | 0;
|
|
7839
|
-
b = rotr(b ^ c, 12);
|
|
7840
|
-
return { a, b, c, d };
|
|
7841
|
-
}
|
|
7842
|
-
function G2s(a, b, c, d, x) {
|
|
7843
|
-
a = a + b + x | 0;
|
|
7844
|
-
d = rotr(d ^ a, 8);
|
|
7845
|
-
c = c + d | 0;
|
|
7846
|
-
b = rotr(b ^ c, 7);
|
|
7847
|
-
return { a, b, c, d };
|
|
7848
|
-
}
|
|
8566
|
+
// src/index.ts
|
|
8567
|
+
init_errors();
|
|
8568
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
8569
|
+
import { Command } from "commander";
|
|
7849
8570
|
|
|
7850
|
-
//
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
this.length += take;
|
|
7896
|
-
pos += take;
|
|
8571
|
+
// src/output/banner.ts
|
|
8572
|
+
init_formatter();
|
|
8573
|
+
|
|
8574
|
+
// src/output/taglines.ts
|
|
8575
|
+
var HOLIDAY_TAGLINES = [
|
|
8576
|
+
{ month: 1, day: 1, range: 1, tagline: "New year, new keys, same cloud." },
|
|
8577
|
+
{ month: 2, day: 14, tagline: "We love your data as much as you do." },
|
|
8578
|
+
{ month: 3, day: 14, tagline: "3.14159 reasons to encrypt everything." },
|
|
8579
|
+
{ month: 5, day: 4, tagline: "May the fourth be with your keys." },
|
|
8580
|
+
{ month: 10, day: 31, tagline: "Nothing scarier than plaintext secrets." },
|
|
8581
|
+
{ month: 12, day: 25, range: 2, tagline: "Unwrap your data, not your keys." },
|
|
8582
|
+
{ month: 12, day: 31, tagline: "Encrypt your resolutions." }
|
|
8583
|
+
];
|
|
8584
|
+
var TAGLINES = [
|
|
8585
|
+
// Professional
|
|
8586
|
+
"Your data, your keys, your cloud.",
|
|
8587
|
+
"Self-sovereign storage for the modern web.",
|
|
8588
|
+
"The cloud you actually own.",
|
|
8589
|
+
"Encrypted by default, decentralized by design.",
|
|
8590
|
+
"Where your data answers only to you.",
|
|
8591
|
+
"End-to-end encrypted. No exceptions.",
|
|
8592
|
+
"Like S3 but you hold the keys.",
|
|
8593
|
+
"Privacy isn't a feature. It's the architecture.",
|
|
8594
|
+
"Sovereign storage, zero knowledge.",
|
|
8595
|
+
"Your .env is safe here \u2014 we use real cryptography.",
|
|
8596
|
+
// Playful / nerdy
|
|
8597
|
+
"UCAN do anything.",
|
|
8598
|
+
"Keys generated, delegations granted, data liberated.",
|
|
8599
|
+
"Decentralized storage, centralized vibes.",
|
|
8600
|
+
"Trust nobody, delegate everything.",
|
|
8601
|
+
"sudo make me a sandwich, encrypted.",
|
|
8602
|
+
"Have you tried turning your keys off and on again?",
|
|
8603
|
+
"All your base are belong to you.",
|
|
8604
|
+
"In UCAN we trust.",
|
|
8605
|
+
"0 knowledge, 100% confidence.",
|
|
8606
|
+
"Keeping secrets since 2024."
|
|
8607
|
+
];
|
|
8608
|
+
function getHolidayTagline() {
|
|
8609
|
+
const now = /* @__PURE__ */ new Date();
|
|
8610
|
+
const month = now.getMonth() + 1;
|
|
8611
|
+
const day = now.getDate();
|
|
8612
|
+
for (const h of HOLIDAY_TAGLINES) {
|
|
8613
|
+
const range = h.range ?? 0;
|
|
8614
|
+
if (h.month === month && Math.abs(day - h.day) <= range) {
|
|
8615
|
+
return h.tagline;
|
|
7897
8616
|
}
|
|
7898
|
-
return this;
|
|
7899
|
-
}
|
|
7900
|
-
digestInto(out) {
|
|
7901
|
-
aexists(this);
|
|
7902
|
-
aoutput(out, this);
|
|
7903
|
-
const { pos, buffer32 } = this;
|
|
7904
|
-
this.finished = true;
|
|
7905
|
-
clean(this.buffer.subarray(pos));
|
|
7906
|
-
swap32IfBE(buffer32);
|
|
7907
|
-
this.compress(buffer32, 0, true);
|
|
7908
|
-
swap32IfBE(buffer32);
|
|
7909
|
-
const out32 = u32(out);
|
|
7910
|
-
this.get().forEach((v, i) => out32[i] = swap8IfBE(v));
|
|
7911
|
-
}
|
|
7912
|
-
digest() {
|
|
7913
|
-
const { buffer, outputLen } = this;
|
|
7914
|
-
this.digestInto(buffer);
|
|
7915
|
-
const res = buffer.slice(0, outputLen);
|
|
7916
|
-
this.destroy();
|
|
7917
|
-
return res;
|
|
7918
|
-
}
|
|
7919
|
-
_cloneInto(to) {
|
|
7920
|
-
const { buffer, length: length4, finished, destroyed, outputLen, pos } = this;
|
|
7921
|
-
to || (to = new this.constructor({ dkLen: outputLen }));
|
|
7922
|
-
to.set(...this.get());
|
|
7923
|
-
to.buffer.set(buffer);
|
|
7924
|
-
to.destroyed = destroyed;
|
|
7925
|
-
to.finished = finished;
|
|
7926
|
-
to.length = length4;
|
|
7927
|
-
to.pos = pos;
|
|
7928
|
-
to.outputLen = outputLen;
|
|
7929
|
-
return to;
|
|
7930
|
-
}
|
|
7931
|
-
clone() {
|
|
7932
|
-
return this._cloneInto();
|
|
7933
|
-
}
|
|
7934
|
-
};
|
|
7935
|
-
function compress(s, offset, msg, rounds, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) {
|
|
7936
|
-
let j = 0;
|
|
7937
|
-
for (let i = 0; i < rounds; i++) {
|
|
7938
|
-
({ a: v0, b: v4, c: v8, d: v12 } = G1s(v0, v4, v8, v12, msg[offset + s[j++]]));
|
|
7939
|
-
({ a: v0, b: v4, c: v8, d: v12 } = G2s(v0, v4, v8, v12, msg[offset + s[j++]]));
|
|
7940
|
-
({ a: v1, b: v5, c: v9, d: v13 } = G1s(v1, v5, v9, v13, msg[offset + s[j++]]));
|
|
7941
|
-
({ a: v1, b: v5, c: v9, d: v13 } = G2s(v1, v5, v9, v13, msg[offset + s[j++]]));
|
|
7942
|
-
({ a: v2, b: v6, c: v10, d: v14 } = G1s(v2, v6, v10, v14, msg[offset + s[j++]]));
|
|
7943
|
-
({ a: v2, b: v6, c: v10, d: v14 } = G2s(v2, v6, v10, v14, msg[offset + s[j++]]));
|
|
7944
|
-
({ a: v3, b: v7, c: v11, d: v15 } = G1s(v3, v7, v11, v15, msg[offset + s[j++]]));
|
|
7945
|
-
({ a: v3, b: v7, c: v11, d: v15 } = G2s(v3, v7, v11, v15, msg[offset + s[j++]]));
|
|
7946
|
-
({ a: v0, b: v5, c: v10, d: v15 } = G1s(v0, v5, v10, v15, msg[offset + s[j++]]));
|
|
7947
|
-
({ a: v0, b: v5, c: v10, d: v15 } = G2s(v0, v5, v10, v15, msg[offset + s[j++]]));
|
|
7948
|
-
({ a: v1, b: v6, c: v11, d: v12 } = G1s(v1, v6, v11, v12, msg[offset + s[j++]]));
|
|
7949
|
-
({ a: v1, b: v6, c: v11, d: v12 } = G2s(v1, v6, v11, v12, msg[offset + s[j++]]));
|
|
7950
|
-
({ a: v2, b: v7, c: v8, d: v13 } = G1s(v2, v7, v8, v13, msg[offset + s[j++]]));
|
|
7951
|
-
({ a: v2, b: v7, c: v8, d: v13 } = G2s(v2, v7, v8, v13, msg[offset + s[j++]]));
|
|
7952
|
-
({ a: v3, b: v4, c: v9, d: v14 } = G1s(v3, v4, v9, v14, msg[offset + s[j++]]));
|
|
7953
|
-
({ a: v3, b: v4, c: v9, d: v14 } = G2s(v3, v4, v9, v14, msg[offset + s[j++]]));
|
|
7954
8617
|
}
|
|
7955
|
-
return
|
|
8618
|
+
return null;
|
|
8619
|
+
}
|
|
8620
|
+
function pickTagline() {
|
|
8621
|
+
const holiday = getHolidayTagline();
|
|
8622
|
+
if (holiday) return holiday;
|
|
8623
|
+
return TAGLINES[Math.floor(Math.random() * TAGLINES.length)];
|
|
7956
8624
|
}
|
|
7957
8625
|
|
|
7958
|
-
//
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
}
|
|
7969
|
-
|
|
7970
|
-
var B3_SIGMA = /* @__PURE__ */ (() => {
|
|
7971
|
-
const Id = Array.from({ length: 16 }, (_, i) => i);
|
|
7972
|
-
const permute = (arr) => [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8].map((i) => arr[i]);
|
|
7973
|
-
const res = [];
|
|
7974
|
-
for (let i = 0, v = Id; i < 7; i++, v = permute(v))
|
|
7975
|
-
res.push(...v);
|
|
7976
|
-
return Uint8Array.from(res);
|
|
7977
|
-
})();
|
|
7978
|
-
var BLAKE3 = class _BLAKE3 extends BLAKE2 {
|
|
7979
|
-
constructor(opts = {}, flags = 0) {
|
|
7980
|
-
super(64, opts.dkLen === void 0 ? 32 : opts.dkLen);
|
|
7981
|
-
this.chunkPos = 0;
|
|
7982
|
-
this.chunksDone = 0;
|
|
7983
|
-
this.flags = 0 | 0;
|
|
7984
|
-
this.stack = [];
|
|
7985
|
-
this.posOut = 0;
|
|
7986
|
-
this.bufferOut32 = new Uint32Array(16);
|
|
7987
|
-
this.chunkOut = 0;
|
|
7988
|
-
this.enableXOF = true;
|
|
7989
|
-
const { key, context } = opts;
|
|
7990
|
-
const hasContext = context !== void 0;
|
|
7991
|
-
if (key !== void 0) {
|
|
7992
|
-
if (hasContext)
|
|
7993
|
-
throw new Error('Only "key" or "context" can be specified at same time');
|
|
7994
|
-
const k = toBytes(key).slice();
|
|
7995
|
-
abytes(k, 32);
|
|
7996
|
-
this.IV = u32(k);
|
|
7997
|
-
swap32IfBE(this.IV);
|
|
7998
|
-
this.flags = flags | B3_Flags.KEYED_HASH;
|
|
7999
|
-
} else if (hasContext) {
|
|
8000
|
-
const ctx = toBytes(context);
|
|
8001
|
-
const contextKey = new _BLAKE3({ dkLen: 32 }, B3_Flags.DERIVE_KEY_CONTEXT).update(ctx).digest();
|
|
8002
|
-
this.IV = u32(contextKey);
|
|
8003
|
-
swap32IfBE(this.IV);
|
|
8004
|
-
this.flags = flags | B3_Flags.DERIVE_KEY_MATERIAL;
|
|
8005
|
-
} else {
|
|
8006
|
-
this.IV = B3_IV.slice();
|
|
8007
|
-
this.flags = flags;
|
|
8008
|
-
}
|
|
8009
|
-
this.state = this.IV.slice();
|
|
8010
|
-
this.bufferOut = u8(this.bufferOut32);
|
|
8011
|
-
}
|
|
8012
|
-
// Unused
|
|
8013
|
-
get() {
|
|
8014
|
-
return [];
|
|
8626
|
+
// src/output/banner.ts
|
|
8627
|
+
init_theme();
|
|
8628
|
+
import { execSync } from "child_process";
|
|
8629
|
+
var bannerEmitted = false;
|
|
8630
|
+
function resolveCommitHash() {
|
|
8631
|
+
try {
|
|
8632
|
+
return execSync("git rev-parse --short HEAD", {
|
|
8633
|
+
encoding: "utf-8",
|
|
8634
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
8635
|
+
}).trim() || null;
|
|
8636
|
+
} catch {
|
|
8637
|
+
return null;
|
|
8015
8638
|
}
|
|
8016
|
-
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
s[3] = v3 ^ v11;
|
|
8026
|
-
s[4] = v4 ^ v12;
|
|
8027
|
-
s[5] = v5 ^ v13;
|
|
8028
|
-
s[6] = v6 ^ v14;
|
|
8029
|
-
s[7] = v7 ^ v15;
|
|
8030
|
-
}
|
|
8031
|
-
compress(buf, bufPos = 0, isLast = false) {
|
|
8032
|
-
let flags = this.flags;
|
|
8033
|
-
if (!this.chunkPos)
|
|
8034
|
-
flags |= B3_Flags.CHUNK_START;
|
|
8035
|
-
if (this.chunkPos === 15 || isLast)
|
|
8036
|
-
flags |= B3_Flags.CHUNK_END;
|
|
8037
|
-
if (!isLast)
|
|
8038
|
-
this.pos = this.blockLen;
|
|
8039
|
-
this.b2Compress(this.chunksDone, flags, buf, bufPos);
|
|
8040
|
-
this.chunkPos += 1;
|
|
8041
|
-
if (this.chunkPos === 16 || isLast) {
|
|
8042
|
-
let chunk = this.state;
|
|
8043
|
-
this.state = this.IV.slice();
|
|
8044
|
-
for (let last, chunks = this.chunksDone + 1; isLast || !(chunks & 1); chunks >>= 1) {
|
|
8045
|
-
if (!(last = this.stack.pop()))
|
|
8046
|
-
break;
|
|
8047
|
-
this.buffer32.set(last, 0);
|
|
8048
|
-
this.buffer32.set(chunk, 8);
|
|
8049
|
-
this.pos = this.blockLen;
|
|
8050
|
-
this.b2Compress(0, this.flags | B3_Flags.PARENT, this.buffer32, 0);
|
|
8051
|
-
chunk = this.state;
|
|
8052
|
-
this.state = this.IV.slice();
|
|
8053
|
-
}
|
|
8054
|
-
this.chunksDone++;
|
|
8055
|
-
this.chunkPos = 0;
|
|
8056
|
-
this.stack.push(chunk);
|
|
8057
|
-
}
|
|
8058
|
-
this.pos = 0;
|
|
8059
|
-
}
|
|
8060
|
-
_cloneInto(to) {
|
|
8061
|
-
to = super._cloneInto(to);
|
|
8062
|
-
const { IV, flags, state, chunkPos, posOut, chunkOut, stack, chunksDone } = this;
|
|
8063
|
-
to.state.set(state.slice());
|
|
8064
|
-
to.stack = stack.map((i) => Uint32Array.from(i));
|
|
8065
|
-
to.IV.set(IV);
|
|
8066
|
-
to.flags = flags;
|
|
8067
|
-
to.chunkPos = chunkPos;
|
|
8068
|
-
to.chunksDone = chunksDone;
|
|
8069
|
-
to.posOut = posOut;
|
|
8070
|
-
to.chunkOut = chunkOut;
|
|
8071
|
-
to.enableXOF = this.enableXOF;
|
|
8072
|
-
to.bufferOut32.set(this.bufferOut32);
|
|
8073
|
-
return to;
|
|
8074
|
-
}
|
|
8075
|
-
destroy() {
|
|
8076
|
-
this.destroyed = true;
|
|
8077
|
-
clean(this.state, this.buffer32, this.IV, this.bufferOut32);
|
|
8078
|
-
clean(...this.stack);
|
|
8079
|
-
}
|
|
8080
|
-
// Same as b2Compress, but doesn't modify state and returns 16 u32 array (instead of 8)
|
|
8081
|
-
b2CompressOut() {
|
|
8082
|
-
const { state: s, pos, flags, buffer32, bufferOut32: out32 } = this;
|
|
8083
|
-
const { h, l } = fromBig(BigInt(this.chunkOut++));
|
|
8084
|
-
swap32IfBE(buffer32);
|
|
8085
|
-
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(B3_SIGMA, 0, buffer32, 7, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], B3_IV[0], B3_IV[1], B3_IV[2], B3_IV[3], l, h, pos, flags);
|
|
8086
|
-
out32[0] = v0 ^ v8;
|
|
8087
|
-
out32[1] = v1 ^ v9;
|
|
8088
|
-
out32[2] = v2 ^ v10;
|
|
8089
|
-
out32[3] = v3 ^ v11;
|
|
8090
|
-
out32[4] = v4 ^ v12;
|
|
8091
|
-
out32[5] = v5 ^ v13;
|
|
8092
|
-
out32[6] = v6 ^ v14;
|
|
8093
|
-
out32[7] = v7 ^ v15;
|
|
8094
|
-
out32[8] = s[0] ^ v8;
|
|
8095
|
-
out32[9] = s[1] ^ v9;
|
|
8096
|
-
out32[10] = s[2] ^ v10;
|
|
8097
|
-
out32[11] = s[3] ^ v11;
|
|
8098
|
-
out32[12] = s[4] ^ v12;
|
|
8099
|
-
out32[13] = s[5] ^ v13;
|
|
8100
|
-
out32[14] = s[6] ^ v14;
|
|
8101
|
-
out32[15] = s[7] ^ v15;
|
|
8102
|
-
swap32IfBE(buffer32);
|
|
8103
|
-
swap32IfBE(out32);
|
|
8104
|
-
this.posOut = 0;
|
|
8105
|
-
}
|
|
8106
|
-
finish() {
|
|
8107
|
-
if (this.finished)
|
|
8108
|
-
return;
|
|
8109
|
-
this.finished = true;
|
|
8110
|
-
clean(this.buffer.subarray(this.pos));
|
|
8111
|
-
let flags = this.flags | B3_Flags.ROOT;
|
|
8112
|
-
if (this.stack.length) {
|
|
8113
|
-
flags |= B3_Flags.PARENT;
|
|
8114
|
-
swap32IfBE(this.buffer32);
|
|
8115
|
-
this.compress(this.buffer32, 0, true);
|
|
8116
|
-
swap32IfBE(this.buffer32);
|
|
8117
|
-
this.chunksDone = 0;
|
|
8118
|
-
this.pos = this.blockLen;
|
|
8119
|
-
} else {
|
|
8120
|
-
flags |= (!this.chunkPos ? B3_Flags.CHUNK_START : 0) | B3_Flags.CHUNK_END;
|
|
8121
|
-
}
|
|
8122
|
-
this.flags = flags;
|
|
8123
|
-
this.b2CompressOut();
|
|
8124
|
-
}
|
|
8125
|
-
writeInto(out) {
|
|
8126
|
-
aexists(this, false);
|
|
8127
|
-
abytes(out);
|
|
8128
|
-
this.finish();
|
|
8129
|
-
const { blockLen, bufferOut } = this;
|
|
8130
|
-
for (let pos = 0, len = out.length; pos < len; ) {
|
|
8131
|
-
if (this.posOut >= blockLen)
|
|
8132
|
-
this.b2CompressOut();
|
|
8133
|
-
const take = Math.min(blockLen - this.posOut, len - pos);
|
|
8134
|
-
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
|
|
8135
|
-
this.posOut += take;
|
|
8136
|
-
pos += take;
|
|
8137
|
-
}
|
|
8138
|
-
return out;
|
|
8139
|
-
}
|
|
8140
|
-
xofInto(out) {
|
|
8141
|
-
if (!this.enableXOF)
|
|
8142
|
-
throw new Error("XOF is not possible after digest call");
|
|
8143
|
-
return this.writeInto(out);
|
|
8144
|
-
}
|
|
8145
|
-
xof(bytes) {
|
|
8146
|
-
anumber(bytes);
|
|
8147
|
-
return this.xofInto(new Uint8Array(bytes));
|
|
8148
|
-
}
|
|
8149
|
-
digestInto(out) {
|
|
8150
|
-
aoutput(out, this);
|
|
8151
|
-
if (this.finished)
|
|
8152
|
-
throw new Error("digest() was already called");
|
|
8153
|
-
this.enableXOF = false;
|
|
8154
|
-
this.writeInto(out);
|
|
8155
|
-
this.destroy();
|
|
8156
|
-
return out;
|
|
8157
|
-
}
|
|
8158
|
-
digest() {
|
|
8159
|
-
return this.digestInto(new Uint8Array(this.outputLen));
|
|
8639
|
+
}
|
|
8640
|
+
function formatBannerLine(version2) {
|
|
8641
|
+
const commit = resolveCommitHash();
|
|
8642
|
+
const tagline = pickTagline();
|
|
8643
|
+
const versionPart = `tc v${version2}`;
|
|
8644
|
+
const commitPart = commit ? ` (${commit})` : "";
|
|
8645
|
+
const separator = " \u2014 ";
|
|
8646
|
+
if (!isInteractive()) {
|
|
8647
|
+
return `${versionPart}${commitPart}${separator}${tagline}`;
|
|
8160
8648
|
}
|
|
8161
|
-
|
|
8162
|
-
|
|
8649
|
+
return [
|
|
8650
|
+
theme.brand("\u2601\uFE0F tc"),
|
|
8651
|
+
" ",
|
|
8652
|
+
theme.muted(`v${version2}`),
|
|
8653
|
+
commit ? theme.dim(` (${commit})`) : "",
|
|
8654
|
+
theme.dim(separator),
|
|
8655
|
+
theme.primary(tagline)
|
|
8656
|
+
].join("");
|
|
8657
|
+
}
|
|
8658
|
+
function emitBanner(version2) {
|
|
8659
|
+
if (bannerEmitted) return;
|
|
8660
|
+
if (shouldOutputJson()) return;
|
|
8661
|
+
if (process.env.TC_HIDE_BANNER === "1") return;
|
|
8662
|
+
bannerEmitted = true;
|
|
8663
|
+
process.stderr.write(formatBannerLine(version2) + "\n\n");
|
|
8664
|
+
}
|
|
8665
|
+
|
|
8666
|
+
// src/index.ts
|
|
8667
|
+
init_replication_registry();
|
|
8668
|
+
init_theme();
|
|
8669
|
+
init_formatter();
|
|
8670
|
+
init_profiles();
|
|
8163
8671
|
|
|
8164
8672
|
// ../share-sdk/dist/index.js
|
|
8673
|
+
init_sha2();
|
|
8674
|
+
init_ed25519();
|
|
8675
|
+
init_blake3();
|
|
8676
|
+
init_ed25519();
|
|
8165
8677
|
init_sha256();
|
|
8166
8678
|
init_sha256();
|
|
8167
8679
|
var __defProp2 = Object.defineProperty;
|
|
@@ -15280,12 +15792,12 @@ async function notifyShare(input) {
|
|
|
15280
15792
|
if (input.signal?.aborted) throw new ShareNotifyError("share delivery was cancelled");
|
|
15281
15793
|
attempts += 1;
|
|
15282
15794
|
try {
|
|
15283
|
-
const
|
|
15795
|
+
const state2 = await input.adapter.deliver({ shareId: input.shareId, recipient, idempotencyKey, ...input.record === void 0 ? {} : { record: input.record }, ...input.signal === void 0 ? {} : { signal: input.signal } });
|
|
15284
15796
|
return {
|
|
15285
15797
|
protocol: "tinycloud-share",
|
|
15286
15798
|
version: 1,
|
|
15287
15799
|
shareId: input.shareId,
|
|
15288
|
-
state:
|
|
15800
|
+
state: state2 === "delivered" && input.record?.deliveredRecipients?.includes(recipient) ? "already-delivered" : state2,
|
|
15289
15801
|
idempotencyKey,
|
|
15290
15802
|
attempts
|
|
15291
15803
|
};
|
|
@@ -16982,7 +17494,7 @@ function receiveJson(result, path) {
|
|
|
16982
17494
|
import { constants } from "fs";
|
|
16983
17495
|
import { lstat as lstat2, mkdir as mkdir2, mkdtemp, open as open2, readFile as readFile3, realpath, stat as stat2, link, rename as rename2, rm as rm3, unlink } from "fs/promises";
|
|
16984
17496
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
16985
|
-
import { basename as basename2, join as
|
|
17497
|
+
import { basename as basename2, join as join7, resolve, sep } from "path";
|
|
16986
17498
|
init_errors();
|
|
16987
17499
|
var MAX_SHARE_STDIN_BYTES = 100 * 1024 * 1024;
|
|
16988
17500
|
var MAX_SHARE_URL_BYTES = 64 * 1024;
|
|
@@ -17036,7 +17548,7 @@ async function assertDirectory(path) {
|
|
|
17036
17548
|
const segments = absolute.split(sep).filter(Boolean);
|
|
17037
17549
|
let current = absolute.startsWith(sep) ? sep : "";
|
|
17038
17550
|
for (const segment of segments) {
|
|
17039
|
-
current = current === sep ?
|
|
17551
|
+
current = current === sep ? join7(current, segment) : join7(current, segment);
|
|
17040
17552
|
try {
|
|
17041
17553
|
const info = await lstat2(current);
|
|
17042
17554
|
if (info.isSymbolicLink()) {
|
|
@@ -17058,17 +17570,17 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
17058
17570
|
const safeName = safeFilename(filename);
|
|
17059
17571
|
const directoryHandle = await open2(outputDirectory, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0) | (constants.O_NOFOLLOW ?? 0));
|
|
17060
17572
|
const stableDirectory = await realpath(outputDirectory);
|
|
17061
|
-
const outputPath =
|
|
17573
|
+
const outputPath = join7(stableDirectory, safeName);
|
|
17062
17574
|
const directoryIdentity = await directoryHandle.stat();
|
|
17063
17575
|
const assertStableDirectory = async () => {
|
|
17064
17576
|
const current = await stat2(stableDirectory);
|
|
17065
17577
|
if (current.dev !== directoryIdentity.dev || current.ino !== directoryIdentity.ino) throw new Error("OUTPUT_EXISTS");
|
|
17066
17578
|
};
|
|
17067
17579
|
await assertStableDirectory();
|
|
17068
|
-
const stagingDirectory = await mkdtemp(
|
|
17580
|
+
const stagingDirectory = await mkdtemp(join7(stableDirectory, ".tinycloud-share-stage-"));
|
|
17069
17581
|
const stagingInfo = await lstat2(stagingDirectory);
|
|
17070
17582
|
if (!stagingInfo.isDirectory() || (stagingInfo.mode & 511) !== 448) throw new Error("OUTPUT_EXISTS");
|
|
17071
|
-
const stagingPath =
|
|
17583
|
+
const stagingPath = join7(stagingDirectory, `.tinycloud-share-${randomBytes2(16).toString("hex")}.tmp`);
|
|
17072
17584
|
let temporaryPath;
|
|
17073
17585
|
let handle;
|
|
17074
17586
|
try {
|
|
@@ -17105,7 +17617,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
17105
17617
|
await rm3(stagingDirectory, { recursive: true, force: true });
|
|
17106
17618
|
await directoryHandle.close();
|
|
17107
17619
|
}
|
|
17108
|
-
return
|
|
17620
|
+
return join7(outputDirectory, safeName);
|
|
17109
17621
|
}
|
|
17110
17622
|
|
|
17111
17623
|
// src/share/errors.ts
|
|
@@ -17391,7 +17903,7 @@ function registerShareCommand(program2) {
|
|
|
17391
17903
|
if (json) writeJson2({ ...redactPublishedShare(result), expiryClamped: result.metadata.expiryClamped === true, ...notification === void 0 ? {} : { notification } });
|
|
17392
17904
|
else publishHuman(result);
|
|
17393
17905
|
} catch (error) {
|
|
17394
|
-
handleError(shareCliError(error));
|
|
17906
|
+
return handleError(shareCliError(error));
|
|
17395
17907
|
}
|
|
17396
17908
|
});
|
|
17397
17909
|
share.command("inspect [url]").description("Verify a share link and print safe metadata").option("--stdin", "Read the complete URL from stdin").option("--json", "Print versioned redacted JSON").option("--viewer-origin <origin>", "Require this canonical Share origin", SHARE_ORIGIN).action(async (url, options, command) => {
|
|
@@ -17401,7 +17913,7 @@ function registerShareCommand(program2) {
|
|
|
17401
17913
|
if (json) writeJson2(result);
|
|
17402
17914
|
else inspectHuman(result);
|
|
17403
17915
|
} catch (error) {
|
|
17404
|
-
handleError(shareCliError(error));
|
|
17916
|
+
return handleError(shareCliError(error));
|
|
17405
17917
|
}
|
|
17406
17918
|
});
|
|
17407
17919
|
share.command("receive [url]").description("Verify and receive a share link").option("--stdin", "Read the complete URL from stdin").option("--output <directory>", "Create the file in this directory").option("--stdout", "Write verified plaintext bytes to stdout").option("--force", "Allow replacing an existing non-symlink output").option("--max-bytes <bytes>", "Bound received content bytes").option("--json", "Print versioned redacted JSON").option("--viewer-origin <origin>", "Require this canonical Share origin", SHARE_ORIGIN).action(async (url, options, command) => {
|
|
@@ -17449,7 +17961,7 @@ function registerShareCommand(program2) {
|
|
|
17449
17961
|
if (json) receiveJson(result, output);
|
|
17450
17962
|
else receiveHuman(output);
|
|
17451
17963
|
} catch (error) {
|
|
17452
|
-
handleError(shareCliError(error));
|
|
17964
|
+
return handleError(shareCliError(error));
|
|
17453
17965
|
}
|
|
17454
17966
|
});
|
|
17455
17967
|
share.command("list").description("List encrypted sender history without complete bearer URLs").option("--json", "Print versioned redacted JSON").action(async (options, command) => {
|
|
@@ -17460,7 +17972,7 @@ function registerShareCommand(program2) {
|
|
|
17460
17972
|
if (json) writeJson2({ protocol: "tinycloud-share", version: 1, shares: result });
|
|
17461
17973
|
else process.stdout.write(result.map((item) => `${item.shareId} ${item.target} ${item.expiresAt}`).join("\n") + (result.length ? "\n" : ""));
|
|
17462
17974
|
} catch (error) {
|
|
17463
|
-
handleError(shareCliError(error));
|
|
17975
|
+
return handleError(shareCliError(error));
|
|
17464
17976
|
}
|
|
17465
17977
|
});
|
|
17466
17978
|
share.command("show <id>").description("Show one redacted sender-history record").option("--reveal-link", "Explicitly include the complete link").option("--json", "Print versioned redacted JSON").action(async (id, options, command) => {
|
|
@@ -17472,7 +17984,7 @@ function registerShareCommand(program2) {
|
|
|
17472
17984
|
if (json) writeJson2({ protocol: "tinycloud-share", version: 1, share: result });
|
|
17473
17985
|
else writeJson2(result);
|
|
17474
17986
|
} catch (error) {
|
|
17475
|
-
handleError(shareCliError(error));
|
|
17987
|
+
return handleError(shareCliError(error));
|
|
17476
17988
|
}
|
|
17477
17989
|
});
|
|
17478
17990
|
share.command("notify <id>").description("Retry idempotent delivery within 5 minutes of publication; after that publish a new share").requiredOption("--to <address>", "Recipient email").option("--json", "Print versioned JSON").action(async (id, options, command) => {
|
|
@@ -17499,7 +18011,7 @@ function registerShareCommand(program2) {
|
|
|
17499
18011
|
if (result.reason === "delivery-window-expired") process.stderr.write(NOTIFY_WINDOW_MESSAGE);
|
|
17500
18012
|
if (result.state === "partial-failure") process.exitCode = 9;
|
|
17501
18013
|
} catch (error) {
|
|
17502
|
-
handleError(shareCliError(error, "notify"));
|
|
18014
|
+
return handleError(shareCliError(error, "notify"));
|
|
17503
18015
|
}
|
|
17504
18016
|
});
|
|
17505
18017
|
share.command("revoke <id>").description("Revoke addressed shares; report bearer retention honestly").option("--ancestor", "Revoke the owner delegation ancestry").option("--json", "Print versioned JSON").action(async (id, options, command) => {
|
|
@@ -17516,7 +18028,7 @@ function registerShareCommand(program2) {
|
|
|
17516
18028
|
else process.stdout.write(`${result.state}
|
|
17517
18029
|
`);
|
|
17518
18030
|
} catch (error) {
|
|
17519
|
-
handleError(shareCliError(error));
|
|
18031
|
+
return handleError(shareCliError(error));
|
|
17520
18032
|
}
|
|
17521
18033
|
});
|
|
17522
18034
|
}
|
|
@@ -17527,7 +18039,7 @@ init_profiles();
|
|
|
17527
18039
|
init_constants();
|
|
17528
18040
|
init_session_expired();
|
|
17529
18041
|
import { readFile as readFile4 } from "fs/promises";
|
|
17530
|
-
import { join as
|
|
18042
|
+
import { join as join8 } from "path";
|
|
17531
18043
|
import { createHash } from "crypto";
|
|
17532
18044
|
import { writeJsonAtomic as writeJsonAtomic2 } from "@tinycloud/operations/state";
|
|
17533
18045
|
import { LocationRecordValidationError, LocationRegistryHttpError, revokePolicyRootV3 } from "@tinycloud/sdk-core";
|
|
@@ -17632,8 +18144,8 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
17632
18144
|
const observedProfiles = /* @__PURE__ */ new Set();
|
|
17633
18145
|
let preparedKeys;
|
|
17634
18146
|
let preparedKey;
|
|
17635
|
-
const path = async (profile) =>
|
|
17636
|
-
const legacyPath = async (profile) =>
|
|
18147
|
+
const path = async (profile) => join8(await ProfileManager.getCacheDir(profile), "share-history-v2.json");
|
|
18148
|
+
const legacyPath = async (profile) => join8(await ProfileManager.getCacheDir(profile), "share-history-v1.bin");
|
|
17637
18149
|
const b64 = (value) => Buffer.from(value).toString("base64url");
|
|
17638
18150
|
const unb64 = (value) => {
|
|
17639
18151
|
if (typeof value !== "string" || !/^[A-Za-z0-9_-]+$/.test(value)) throw new Error("share history is unavailable");
|
|
@@ -18179,6 +18691,12 @@ async function selectedProfileName() {
|
|
|
18179
18691
|
return process.env.TC_PROFILE ?? config.defaultProfile;
|
|
18180
18692
|
}
|
|
18181
18693
|
|
|
18694
|
+
// src/lib/courier-loader.ts
|
|
18695
|
+
async function loadCourierEntry() {
|
|
18696
|
+
const load = new Function("specifier", "return import(specifier)");
|
|
18697
|
+
return load(new URL("./courier-entry.js", import.meta.url).href);
|
|
18698
|
+
}
|
|
18699
|
+
|
|
18182
18700
|
// src/index.ts
|
|
18183
18701
|
var { version } = JSON.parse(
|
|
18184
18702
|
readFileSync2(new URL("../package.json", import.meta.url), "utf-8")
|
|
@@ -18197,7 +18715,7 @@ function selectedShareProfile() {
|
|
|
18197
18715
|
}
|
|
18198
18716
|
return process.env.TC_PROFILE;
|
|
18199
18717
|
}
|
|
18200
|
-
program.name("tc").description("TinyCloud CLI \u2014 self-sovereign storage from the terminal").version(version).option("-p, --profile <name>", "Profile to use").option("-H, --host <url>", "TinyCloud node URL").option("-v, --verbose", "Enable verbose output").option("--no-cache", "Disable caching").option("-q, --quiet", "Suppress non-essential output").option("--json", "Force JSON output");
|
|
18718
|
+
program.name("tc").description("TinyCloud CLI \u2014 self-sovereign storage from the terminal").version(version).option("-p, --profile <name>", "Profile to use").option("-H, --host <url>", "TinyCloud node URL").option("-v, --verbose", "Enable verbose output").option("--no-cache", "Disable caching").option("-q, --quiet", "Suppress non-essential output").option("--json", "Force JSON output").option("--replication", "Enable read-through replication for this invocation").option("--no-replication", "Disable read-through replication for this invocation").option("--replication-debug", "Write replication diagnostics to stderr");
|
|
18201
18719
|
program.hook("preAction", async (thisCommand) => {
|
|
18202
18720
|
const opts = thisCommand.optsWithGlobals();
|
|
18203
18721
|
setJsonOutputRequested(opts.json === true);
|
|
@@ -18238,30 +18756,28 @@ configureShareCommandServices({
|
|
|
18238
18756
|
nativeReader: shareAuthority.nativeReader
|
|
18239
18757
|
});
|
|
18240
18758
|
var argv = process.argv.slice(2);
|
|
18241
|
-
var
|
|
18759
|
+
var globalLongOptionsWithValues = { "--profile": true, "--host": true };
|
|
18760
|
+
var globalShortOptionsWithValues = { p: true, H: true };
|
|
18242
18761
|
function firstCommandToken(values) {
|
|
18243
18762
|
for (let index = 0; index < values.length; index += 1) {
|
|
18244
18763
|
const value = values[index];
|
|
18245
18764
|
if (value === "--") return values[index + 1];
|
|
18246
|
-
if (
|
|
18247
|
-
index += 1;
|
|
18765
|
+
if (value.startsWith("--")) {
|
|
18766
|
+
if (globalLongOptionsWithValues[value]) index += 1;
|
|
18767
|
+
continue;
|
|
18768
|
+
}
|
|
18769
|
+
if (value.length > 1 && value.startsWith("-")) {
|
|
18770
|
+
for (let char = 1; char < value.length; char += 1) {
|
|
18771
|
+
if (!globalShortOptionsWithValues[value[char]]) continue;
|
|
18772
|
+
if (char === value.length - 1) index += 1;
|
|
18773
|
+
break;
|
|
18774
|
+
}
|
|
18248
18775
|
continue;
|
|
18249
18776
|
}
|
|
18250
|
-
if (value.startsWith("--profile=") || value.startsWith("--host=")) continue;
|
|
18251
|
-
if (value === "--verbose" || value === "--no-cache" || value === "-q" || value === "--quiet" || value === "--json") continue;
|
|
18252
|
-
if (value.startsWith("-")) continue;
|
|
18253
18777
|
return value;
|
|
18254
18778
|
}
|
|
18255
18779
|
return void 0;
|
|
18256
18780
|
}
|
|
18257
|
-
var isShareInvocation = firstCommandToken(argv) === "share";
|
|
18258
|
-
if (isShareInvocation) {
|
|
18259
|
-
registerShareCommand(program);
|
|
18260
|
-
} else {
|
|
18261
|
-
const loadLegacy = new Function("specifier", "return import(specifier)");
|
|
18262
|
-
const { registerTinyCloudCommands } = await loadLegacy(new URL("./legacy-entry.js", import.meta.url).href);
|
|
18263
|
-
registerTinyCloudCommands(program);
|
|
18264
|
-
}
|
|
18265
18781
|
program.addHelpText("before", () => `${theme.label("Version:")} ${theme.value(version)}
|
|
18266
18782
|
`);
|
|
18267
18783
|
program.addHelpText("afterAll", () => {
|
|
@@ -18281,10 +18797,37 @@ ${theme.muted("Docs:")} ${theme.accent("https://docs.tinycloud.xyz/cli")}
|
|
|
18281
18797
|
${theme.muted("Repo:")} ${theme.accent("https://github.com/tinycloudlabs/web-sdk")}
|
|
18282
18798
|
`;
|
|
18283
18799
|
});
|
|
18284
|
-
|
|
18285
|
-
|
|
18286
|
-
|
|
18287
|
-
|
|
18800
|
+
var commandToken = firstCommandToken(argv);
|
|
18801
|
+
if (argv[0] === "courier") {
|
|
18802
|
+
const code3 = await (await loadCourierEntry()).runCourier(argv.slice(1));
|
|
18803
|
+
if (code3 !== 0) process.exit(code3);
|
|
18804
|
+
} else if (commandToken === "courier") {
|
|
18805
|
+
process.stderr.write(`${TC_OPTIONS_BEFORE_COURIER}
|
|
18806
|
+
`);
|
|
18807
|
+
process.exit(2);
|
|
18808
|
+
} else {
|
|
18809
|
+
if (commandToken === "share") {
|
|
18810
|
+
registerShareCommand(program);
|
|
18811
|
+
} else {
|
|
18812
|
+
const loadLegacy = new Function("specifier", "return import(specifier)");
|
|
18813
|
+
const { registerTinyCloudCommands } = await loadLegacy(new URL("./legacy-entry.js", import.meta.url).href);
|
|
18814
|
+
registerTinyCloudCommands(program);
|
|
18815
|
+
}
|
|
18816
|
+
try {
|
|
18817
|
+
await program.parseAsync(process.argv);
|
|
18818
|
+
if (await closeReplication()) {
|
|
18819
|
+
process.exitCode = 0;
|
|
18820
|
+
const stdoutFlushed = Promise.withResolvers();
|
|
18821
|
+
process.stdout.write("", () => stdoutFlushed.resolve());
|
|
18822
|
+
await stdoutFlushed.promise;
|
|
18823
|
+
const stderrFlushed = Promise.withResolvers();
|
|
18824
|
+
process.stderr.write("", () => stderrFlushed.resolve());
|
|
18825
|
+
await stderrFlushed.promise;
|
|
18826
|
+
process.exit();
|
|
18827
|
+
}
|
|
18828
|
+
} catch (error) {
|
|
18829
|
+
await handleError(error);
|
|
18830
|
+
}
|
|
18288
18831
|
}
|
|
18289
18832
|
/*! Bundled license information:
|
|
18290
18833
|
|