@tinycloud/cli 1.2.0-beta.5 → 1.2.0-beta.6

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/dist/index.js CHANGED
@@ -5806,1098 +5806,568 @@ var init_replication_log = __esm({
5806
5806
  }
5807
5807
  });
5808
5808
 
5809
- // src/lib/replication-config.ts
5810
- import { join as join5 } from "path";
5811
- import { profilePath, withProfileLock as withProfileLock2 } from "@tinycloud/operations/state";
5812
- import { sqliteReplicaStorage } from "@tinycloud/node-sdk";
5813
- function createCliReplicationConfig(profile, settings, output, enabled) {
5814
- if (!enabled || !settings || settings.prefixes.length === 0) return void 0;
5815
- const root = profilePath(profile);
5816
- return {
5817
- enabled: true,
5818
- prefixes: settings.prefixes,
5819
- allowSecrets: settings.allowSecrets === true,
5820
- mode: "foreground",
5821
- verify: process.env.TC_REPLICATION_VERIFY === "1",
5822
- maxStalenessMs: Number(process.env.TC_REPLICATION_MAX_STALENESS_MS ?? 6e4),
5823
- staleSyncTimeoutMs: Number(process.env.TC_REPLICATION_SYNC_TIMEOUT_MS ?? 1e4),
5824
- storage: sqliteReplicaStorage({
5825
- dir: join5(root, "replication"),
5826
- guard: (section) => withProfileLock2(profile, section, { requireProfile: true, timeoutMs: 35e3 })
5827
- }),
5828
- onEvent: createReplicationEventSink(root, output)
5829
- };
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 };
5830
5816
  }
5831
- var init_replication_config = __esm({
5832
- "src/lib/replication-config.ts"() {
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"() {
5833
5826
  "use strict";
5834
- init_replication_log();
5827
+ init_utils();
5835
5828
  }
5836
5829
  });
5837
5830
 
5838
- // src/lib/sdk.ts
5839
- var sdk_exports = {};
5840
- __export(sdk_exports, {
5841
- bootstrapDelegatedSession: () => bootstrapDelegatedSession,
5842
- closeReplication: () => closeReplication,
5843
- createSDKInstance: () => createSDKInstance,
5844
- ensureAuthenticated: () => ensureAuthenticated,
5845
- jwkHasPrivateParameter: () => jwkHasPrivateParameter,
5846
- registerReplication: () => registerReplication,
5847
- registeredReplications: () => registeredReplications,
5848
- replicationForProfile: () => replicationForProfile,
5849
- restoreProfileSessionNode: () => restoreProfileSessionNode,
5850
- selectSignerJwk: () => selectSignerJwk,
5851
- storedSessionVerifiesLocally: () => storedSessionVerifiesLocally
5852
- });
5853
- import { TinyCloudNode, signedCompactUcanExpiry } from "@tinycloud/node-sdk";
5854
- function jwkHasPrivateParameter(jwk) {
5855
- if (!jwk || typeof jwk !== "object") return false;
5856
- const d = jwk.d;
5857
- return typeof d === "string" && d.length > 0;
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++]]));
5851
+ }
5852
+ return { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 };
5858
5853
  }
5859
- function selectSignerJwk(sessionJwk, key) {
5860
- if (jwkHasPrivateParameter(sessionJwk)) {
5861
- return sessionJwk;
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
+ }
5942
+ };
5862
5943
  }
5863
- return key ?? void 0;
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);
6006
+ }
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));
6158
+ }
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;
5864
6168
  }
5865
- function signerJwkForProfile(profileName, sessionJwk, key) {
5866
- const jwk = selectSignerJwk(sessionJwk, key);
5867
- if (jwkHasPrivateParameter(jwk)) {
5868
- return jwk;
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);
5869
6178
  }
5870
- throw new CLIError(
5871
- "AUTH_REQUIRED",
5872
- `Profile "${profileName}" cannot restore its session because its private key material is missing.`,
5873
- ExitCode.AUTH_REQUIRED,
5874
- {
5875
- hint: `Sign in again with: tc --profile ${profileName} auth login --method openkey`
5876
- }
5877
- );
6179
+ return value;
5878
6180
  }
5879
- function signedLifetimePassed(delegation) {
5880
- const authorization = delegation.delegationHeader?.Authorization;
5881
- const expiry = typeof authorization === "string" ? signedCompactUcanExpiry(authorization) : void 0;
5882
- return expiry !== void 0 && expiry.getTime() <= Date.now();
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);
5883
6185
  }
5884
- async function restoreProfileSession(node, profileName, profile, sessionData) {
5885
- try {
5886
- await node.restoreSession(sessionData);
5887
- } catch (error) {
5888
- if (typeof error === "object" && error !== null && "code" in error && error.code === "AUTH_EXPIRED") {
5889
- throw sessionExpiredError(profileName, profile === null ? void 0 : resolveProfilePosture(profile));
5890
- }
5891
- throw error;
5892
- }
6186
+ function bytesToNumberBE(bytes) {
6187
+ return hexToNumber(bytesToHex(bytes));
5893
6188
  }
5894
- function persistedSessionData(profileName, profile, session, key) {
5895
- return {
5896
- delegationHeader: session.delegationHeader,
5897
- delegationCid: session.delegationCid,
5898
- spaceId: session.spaceId,
5899
- jwk: signerJwkForProfile(profileName, session.jwk, key),
5900
- verificationMethod: session.verificationMethod ?? profile.sessionDid ?? profile.did,
5901
- address: session.address,
5902
- chainId: session.chainId,
5903
- siwe: session.siwe,
5904
- signature: session.signature
5905
- };
6189
+ function bytesToNumberLE(bytes) {
6190
+ abytes(bytes);
6191
+ return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
5906
6192
  }
5907
- async function restoreProfileSessionNode(ctx) {
5908
- const profile = await ProfileManager.getProfile(ctx.profile);
5909
- const session = await ProfileManager.getSession(ctx.profile);
5910
- if (!session) return { unavailable: "session_missing" };
5911
- 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") {
5912
- return { unavailable: "session_invalid" };
5913
- }
5914
- if (typeof session.expiresAt === "string" && Date.parse(session.expiresAt) <= Date.now()) {
5915
- return { unavailable: "session_expired" };
5916
- }
5917
- const key = await ProfileManager.getKey(ctx.profile);
5918
- try {
5919
- const node = new TinyCloudNode({
5920
- host: ctx.host,
5921
- ...profile.authMethod === "local" && profile.privateKey ? { privateKey: profile.privateKey } : {}
5922
- });
5923
- await restoreProfileSession(node, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
5924
- return { node };
5925
- } catch (error) {
5926
- if (error instanceof CLIError && error.metadata?.reason === "session_expired") {
5927
- return { unavailable: "session_expired" };
5928
- }
5929
- return { unavailable: "session_invalid" };
5930
- }
5931
- }
5932
- async function storedSessionVerifiesLocally(profileName) {
5933
- const profile = await ProfileManager.getProfile(profileName).catch(() => null);
5934
- if (profile === null) return true;
5935
- const local = profile.authMethod === "local" && typeof profile.privateKey === "string";
5936
- try {
5937
- const session = await ProfileManager.getSession(profileName);
5938
- 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;
5939
- const key = await ProfileManager.getKey(profileName);
5940
- const node = new TinyCloudNode({
5941
- host: profile.host ?? DEFAULT_HOST,
5942
- ...local ? { privateKey: profile.privateKey } : {}
5943
- });
5944
- await restoreProfileSession(node, profileName, profile, persistedSessionData(profileName, profile, session, key));
5945
- return true;
5946
- } catch {
5947
- return false;
5948
- }
6193
+ function numberToBytesBE(n, len) {
6194
+ return hexToBytes(n.toString(16).padStart(len * 2, "0"));
5949
6195
  }
5950
- async function createSDKInstance(ctx, options) {
5951
- const profile = options?.privateKey ? await ProfileManager.getProfile(ctx.profile).catch(() => null) : await ProfileManager.getProfile(ctx.profile);
5952
- const session = await ProfileManager.getSession(ctx.profile);
5953
- const key = await ProfileManager.getKey(ctx.profile);
5954
- const effectivePrivateKey = options?.privateKey ?? profile?.privateKey;
5955
- if (!key && !effectivePrivateKey && !(profile?.authMethod === "openkey" && session !== null)) {
5956
- throw new CLIError(
5957
- "AUTH_REQUIRED",
5958
- `No key found for profile "${ctx.profile}". Run \`tc --profile ${ctx.profile} auth rotate\` to create a new key and sign in.`,
5959
- ExitCode.AUTH_REQUIRED
5960
- );
5961
- }
5962
- if (profile?.authMethod === "local" && effectivePrivateKey) {
5963
- const replication2 = createCliReplicationConfig(
5964
- ctx.profile,
5965
- profile?.replication,
5966
- { debug: ctx.replicationDebug, quiet: ctx.quiet },
5967
- ctx.replication
5968
- );
5969
- if (ctx.replication && !replication2) {
5970
- process.stderr.write("[replication] Enabled, but this profile has no configured prefixes; reads use the network.\n");
5971
- }
5972
- const node2 = new TinyCloudNode({
5973
- host: ctx.host,
5974
- privateKey: effectivePrivateKey,
5975
- ...replication2 ? { replication: replication2 } : {}
5976
- });
5977
- if (node2.replication) registerReplication(ctx.profile, node2.replication);
5978
- const restoredOwnSession = Boolean(session && session.delegationHeader && session.delegationCid && session.spaceId);
5979
- if (restoredOwnSession) {
5980
- await restoreProfileSession(node2, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
5981
- } else {
5982
- await node2.signIn();
5983
- }
5984
- if (restoredOwnSession) {
5985
- recordWarnings(await replayAdditionalDelegations(node2, ctx.profile, {
5986
- host: ctx.host,
5987
- ownerSpace: profile.spaceId,
5988
- migrate: options?.privateKey === void 0
5989
- }));
5990
- }
5991
- return node2;
5992
- }
5993
- const replication = createCliReplicationConfig(
5994
- ctx.profile,
5995
- profile?.replication,
5996
- { debug: ctx.replicationDebug, quiet: ctx.quiet },
5997
- ctx.replication
5998
- );
5999
- if (ctx.replication && !replication) {
6000
- process.stderr.write("[replication] Enabled, but this profile has no configured prefixes; reads use the network.\n");
6001
- }
6002
- const node = new TinyCloudNode({
6003
- host: ctx.host,
6004
- privateKey: options?.privateKey,
6005
- ...replication ? { replication } : {}
6006
- });
6007
- if (node.replication) registerReplication(ctx.profile, node.replication);
6008
- if (options?.privateKey) {
6009
- await node.signIn();
6010
- } else if (session && session.delegationHeader && session.delegationCid && session.spaceId) {
6011
- await restoreProfileSession(node, ctx.profile, profile, persistedSessionData(ctx.profile, profile, session, key));
6012
- recordWarnings(await replayAdditionalDelegations(node, ctx.profile, {
6013
- host: ctx.host,
6014
- ownerSpace: profile?.spaceId,
6015
- migrate: true
6016
- }));
6017
- }
6018
- return node;
6196
+ function numberToBytesLE(n, len) {
6197
+ return numberToBytesBE(n, len).reverse();
6019
6198
  }
6020
- async function bootstrapDelegatedSession(ctx, delegation) {
6021
- const written = await ProfileManager.withLock(ctx.profile, async () => {
6022
- const previousProfile = await ProfileManager.getProfile(ctx.profile);
6023
- if (resolveProfilePosture(previousProfile) !== "delegate-session") {
6024
- throw new CLIError(
6025
- "AUTH_REQUIRED",
6026
- `Profile "${ctx.profile}" is not a delegate-session profile.`,
6027
- ExitCode.AUTH_REQUIRED
6028
- );
6029
- }
6030
- const sessionDid = previousProfile.sessionDid ?? previousProfile.did;
6031
- if (delegation.delegateDID.split("#", 1)[0] !== sessionDid.split("#", 1)[0]) {
6032
- throw new CLIError(
6033
- "DELEGATION_AUDIENCE_MISMATCH",
6034
- `Delegation targets ${delegation.delegateDID}, but profile "${ctx.profile}" uses ${sessionDid}.`,
6035
- ExitCode.PERMISSION_DENIED
6036
- );
6037
- }
6038
- if (await ProfileManager.getSession(ctx.profile) !== null) {
6039
- throw new CLIError(
6040
- "PROFILE_CHANGED_DURING_IMPORT",
6041
- `Profile "${ctx.profile}" gained a session (another login or import) after this import checked it. Nothing was saved; run the import again.`,
6042
- ExitCode.ERROR
6043
- );
6044
- }
6045
- if (signedLifetimePassed(delegation)) throw delegationExpiredError();
6046
- const jwk = signerJwkForProfile(ctx.profile, void 0, await ProfileManager.getKey(ctx.profile));
6047
- const session = {
6048
- delegationHeader: delegation.delegationHeader,
6049
- delegationCid: delegation.cid,
6050
- spaceId: delegation.spaceId,
6051
- jwk,
6052
- verificationMethod: sessionDid
6053
- };
6054
- const profile = { ...previousProfile, sessionDid, spaceId: delegation.spaceId };
6199
+ function ensureBytes(title, hex3, expectedLength) {
6200
+ let res;
6201
+ if (typeof hex3 === "string") {
6055
6202
  try {
6056
- await ProfileManager.setSession(ctx.profile, session);
6057
- await ProfileManager.setProfile(ctx.profile, profile);
6058
- } catch (error) {
6059
- throw annotate(error, await restoreBeforeBootstrap(ctx.profile, previousProfile));
6203
+ res = hexToBytes(hex3);
6204
+ } catch (e) {
6205
+ throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
6060
6206
  }
6061
- return { previousProfile, profile, session };
6062
- });
6063
- const abandon = async (cause) => {
6064
- const reported = cause instanceof CLIError && cause.code === "AUTH_REQUIRED" && signedLifetimePassed(delegation) ? delegationExpiredError() : cause;
6065
- const note = await ProfileManager.withLock(ctx.profile, async () => {
6066
- const profile = await ProfileManager.getProfile(ctx.profile).catch((error) => {
6067
- if (error instanceof CLIError && error.code === "PROFILE_NOT_FOUND") return null;
6068
- throw error;
6069
- });
6070
- const session = await ProfileManager.getSession(ctx.profile);
6071
- if (profile === null || BOOTSTRAP_PROFILE_FIELDS.some((field) => profile[field] !== written.profile[field]) || JSON.stringify(session) !== JSON.stringify(written.session)) {
6072
- 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.`;
6073
- }
6074
- return restoreBeforeBootstrap(ctx.profile, written.previousProfile);
6075
- }, { timeoutMs: PROFILE_COMMIT_LOCK_TIMEOUT_MS }).catch((error) => (
6076
- // The lock or a read failed: the import's error stays the one reported.
6077
- `Rolling back the provisional session of profile "${ctx.profile}" could not run (${failureName(error)}); check \`tc --profile ${ctx.profile} context\`.`
6078
- ));
6079
- throw annotate(reported, note);
6080
- };
6081
- let node;
6082
- try {
6083
- node = await createSDKInstance(ctx);
6084
- } catch (error) {
6085
- return abandon(error);
6207
+ } else if (isBytes(hex3)) {
6208
+ res = Uint8Array.from(hex3);
6209
+ } else {
6210
+ throw new Error(title + " must be hex string or Uint8Array");
6086
6211
  }
6087
- return { node, abandon };
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;
6088
6216
  }
6089
- async function restoreBeforeBootstrap(profileName, previousProfile) {
6090
- const failures = [];
6091
- for (const write of [
6092
- () => ProfileManager.clearSession(profileName),
6093
- () => ProfileManager.updateProfile(profileName, (current) => {
6094
- const restored = { ...current };
6095
- for (const field of BOOTSTRAP_PROFILE_FIELDS) {
6096
- if (previousProfile[field] === void 0) delete restored[field];
6097
- else restored[field] = previousProfile[field];
6098
- }
6099
- return restored;
6100
- })
6101
- ]) {
6102
- await write().catch((error) => {
6103
- failures.push(failureName(error));
6104
- });
6105
- }
6106
- if (failures.length === 0) return void 0;
6107
- return `Rolling back the provisional session of profile "${profileName}" failed too (${failures.join("; ")}); check \`tc --profile ${profileName} context\`.`;
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;
6108
6224
  }
6109
- function failureName(error) {
6110
- if (error instanceof SyntaxError) return "a profile file is not valid JSON";
6111
- if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") return error.code;
6112
- return error instanceof Error ? error.name : "unknown error";
6225
+ function copyBytes(bytes) {
6226
+ return Uint8Array.from(bytes);
6113
6227
  }
6114
- function annotate(error, note) {
6115
- if (note === void 0) return error;
6116
- const cause = wrapError(error);
6117
- return new CLIError(cause.code, `${cause.message} ${note}`, cause.exitCode, cause.metadata);
6228
+ function inRange(n, min, max) {
6229
+ return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
6118
6230
  }
6119
- async function ensureAuthenticated(ctx, options) {
6120
- if (options?.privateKey) {
6121
- return createSDKInstance(ctx, options);
6122
- }
6123
- const profile = await ProfileManager.getProfile(ctx.profile).catch(() => null);
6124
- if (profile?.authMethod === "local" && profile.privateKey) {
6125
- return createSDKInstance(ctx);
6126
- }
6127
- const session = await ProfileManager.getSession(ctx.profile);
6128
- if (!session) {
6129
- throw new CLIError(
6130
- "AUTH_REQUIRED",
6131
- `Not authenticated. Run \`tc auth login\` or \`tc init\` first.`,
6132
- ExitCode.AUTH_REQUIRED
6133
- );
6134
- }
6135
- return createSDKInstance(ctx, options);
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);
6136
6234
  }
6137
- var BOOTSTRAP_PROFILE_FIELDS;
6138
- var init_sdk = __esm({
6139
- "src/lib/sdk.ts"() {
6140
- "use strict";
6141
- init_profiles();
6142
- init_types();
6143
- init_errors();
6144
- init_constants();
6145
- init_permissions();
6146
- init_session_expired();
6147
- init_warnings();
6148
- init_delegation_expiry();
6149
- init_replication_config();
6150
- init_replication_registry();
6151
- init_replication_registry();
6152
- BOOTSTRAP_PROFILE_FIELDS = ["sessionDid", "spaceId"];
6153
- }
6154
- });
6155
-
6156
- // src/lib/host.ts
6157
- var host_exports = {};
6158
- __export(host_exports, {
6159
- completeDeferredLocalDiscovery: () => completeDeferredLocalDiscovery,
6160
- discoverLocalNodeHost: () => discoverLocalNodeHost,
6161
- isRootAuthority: () => isRootAuthority,
6162
- ownerDidFromSpaceUri: () => ownerDidFromSpaceUri,
6163
- profileLocalNodeIdentityStore: () => profileLocalNodeIdentityStore,
6164
- resolveHostSpace: () => resolveHostSpace,
6165
- spaceNameFromUri: () => spaceNameFromUri,
6166
- unhostedSpaceError: () => unhostedSpaceError
6167
- });
6168
- import {
6169
- discoverLocalTinyCloudNode
6170
- } from "@tinycloud/sdk-core";
6171
- function profileLocalNodeIdentityStore(profileName) {
6172
- return {
6173
- get: async (url) => {
6174
- const profile = await ProfileManager.getProfile(profileName).catch(
6175
- () => null
6176
- );
6177
- return profile?.pinnedLocalNodeDids?.[url];
6178
- },
6179
- set: async (url, nodeDid) => {
6180
- if (!await ProfileManager.profileExists(profileName)) return;
6181
- await ProfileManager.updateProfile(profileName, (profile) => ({
6182
- ...profile,
6183
- pinnedLocalNodeDids: {
6184
- ...profile.pinnedLocalNodeDids,
6185
- [url]: nodeDid
6186
- }
6187
- }));
6188
- }
6189
- };
6235
+ function bitLen(n) {
6236
+ let len;
6237
+ for (len = 0; n > _0n; n >>= _1n, len += 1)
6238
+ ;
6239
+ return len;
6190
6240
  }
6191
- async function discoverLocalNodeHost(profileName, options) {
6192
- const profile = await ProfileManager.getProfile(profileName).catch(() => null);
6193
- if (profile?.autoDiscoverLocalNode === false) return { host: null, deferred: false };
6194
- if (!profile?.localNodeUrl && !profile?.localLinkName) return { host: null, deferred: false };
6195
- if (options.awaitStoredSession) {
6196
- const { storedSessionVerifiesLocally: storedSessionVerifiesLocally2 } = await Promise.resolve().then(() => (init_sdk(), sdk_exports));
6197
- if (!await storedSessionVerifiesLocally2(profileName)) return { host: null, deferred: true };
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}`);
6198
6251
  }
6199
- const discovered = await discoverLocalTinyCloudNode({
6200
- localNodeUrl: profile?.localNodeUrl,
6201
- localLinkName: profile?.localLinkName,
6202
- expectedNodeDid: profile?.expectedNodeDid,
6203
- identityStore: profileLocalNodeIdentityStore(profileName)
6204
- });
6205
- return { host: discovered?.url ?? null, deferred: false };
6206
- }
6207
- async function completeDeferredLocalDiscovery(ctx) {
6208
- const deferred = ctx.localDiscovery;
6209
- if (deferred === void 0) return;
6210
- delete ctx.localDiscovery;
6211
- if (ctx.host !== deferred.deferredFrom) return;
6212
- const discovered = await discoverLocalNodeHost(ctx.profile, { awaitStoredSession: false });
6213
- if (discovered.host !== null) ctx.host = discovered.host;
6252
+ Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
6253
+ Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
6214
6254
  }
6215
- function canonicalizeAddress2(address) {
6216
- const trimmed = address.trim();
6217
- return trimmed.startsWith("0x") ? `0x${trimmed.slice(2).toLowerCase()}` : trimmed.toLowerCase();
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
+ };
6218
6265
  }
6219
- async function resolveLocalAddress(profile, profileName) {
6220
- const session = await ProfileManager.getSession(profileName);
6221
- const sessAddr = session?.address;
6222
- if (typeof sessAddr === "string" && sessAddr.length > 0) {
6223
- return canonicalizeAddress2(sessAddr);
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
+ };
6224
6279
  }
6225
- if (profile.address) return canonicalizeAddress2(profile.address);
6226
- if (profile.ownerDid) {
6227
- const match = profile.ownerDid.match(/^did:pkh:eip155:\d+:(0x[a-fA-F0-9]{40})$/);
6228
- if (match) return canonicalizeAddress2(match[1]);
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;
6286
+ }
6287
+ function pow2(x, power, modulo) {
6288
+ let res = x;
6289
+ while (power-- > _0n2) {
6290
+ res *= res;
6291
+ res %= modulo;
6229
6292
  }
6230
- return null;
6293
+ return res;
6231
6294
  }
6232
- function ownerAddressFromSpaceUri(spaceUri) {
6233
- const match = spaceUri.match(/^tinycloud:pkh:eip155:\d+:(0x[a-fA-F0-9]{40}):/);
6234
- return match ? canonicalizeAddress2(match[1]) : null;
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);
6235
6314
  }
6236
- function ownerDidFromSpaceUri(spaceUri) {
6237
- const match = spaceUri.match(/^tinycloud:pkh:eip155:(\d+):(0x[a-fA-F0-9]{40}):/);
6238
- if (!match) return null;
6239
- return `did:pkh:eip155:${match[1]}:${canonicalizeAddress2(match[2])}`;
6315
+ function assertIsSquare(Fp2, root, n) {
6316
+ if (!Fp2.eql(Fp2.sqr(root), n))
6317
+ throw new Error("Cannot find square root");
6240
6318
  }
6241
- async function isRootAuthority(spaceUri, profileName) {
6242
- const profile = await ProfileManager.getProfile(profileName);
6243
- if (resolveProfilePosture(profile) === "delegate-session") return false;
6244
- const ownerAddr = ownerAddressFromSpaceUri(spaceUri);
6245
- if (!ownerAddr) return false;
6246
- const selfAddr = await resolveLocalAddress(profile, profileName);
6247
- return selfAddr !== null && selfAddr === ownerAddr;
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;
6248
6324
  }
6249
- function spaceNameFromUri(spaceUri) {
6250
- return spaceUri.slice(spaceUri.lastIndexOf(":") + 1);
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;
6251
6334
  }
6252
- async function unhostedSpaceError(error, spaceUri, profileName) {
6253
- if (!spaceUri) return null;
6254
- const status = error.meta?.status;
6255
- const isUnhosted = status === 404 && /space not found/i.test(error.message);
6256
- if (!isUnhosted) return null;
6257
- const spaceName = spaceNameFromUri(spaceUri);
6258
- const owner = await isRootAuthority(spaceUri, profileName);
6259
- const hint = owner ? [
6260
- "You are the owner. Host it once:",
6261
- ` tc space host ${spaceName}`,
6262
- "Then retry."
6263
- ].join("\n") : [
6264
- "You are a delegate and CANNOT host this space \u2014 only its owner can.",
6265
- "Emit a host request:",
6266
- ` tc space host-request ${spaceName} --emit ./host-request.json`,
6267
- "Send it to the owner; they run `tc space host` and confirm. Then retry."
6268
- ].join("\n");
6269
- const message = owner ? `Space '${spaceName}' (${spaceUri}) is not hosted.` : `Space '${spaceName}' (owner ${ownerDidFromSpaceUri(spaceUri) ?? spaceUri}) is not hosted.`;
6270
- return new CLIError("SPACE_NOT_HOSTED", message, ExitCode.ERROR, { hint });
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
+ };
6271
6356
  }
6272
- async function resolveHostSpace(name, profileName) {
6273
- const resolved = await resolveSpaceUri(name, profileName);
6274
- if (!resolved) {
6275
- throw new Error(`Could not resolve a space for "${name}".`);
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++;
6276
6365
  }
6277
- return resolved;
6278
- }
6279
- var init_host = __esm({
6280
- "src/lib/host.ts"() {
6281
- "use strict";
6282
- init_profiles();
6283
- init_constants();
6284
- init_types();
6285
- init_errors();
6286
- init_space();
6287
- }
6288
- });
6289
-
6290
- // src/config/profiles.ts
6291
- import { chmod as chmod2, lstat, readdir as readdir2, rm as rm2, rmdir } from "fs/promises";
6292
- import { join as join6 } from "path";
6293
- import {
6294
- profilePath as profilePath2,
6295
- readSession,
6296
- recordProfileDeletion,
6297
- refuseWriteToDeletedProfile as refuseWriteToDeletedProfile2,
6298
- removeSession,
6299
- withProfileLock as withProfileLock3,
6300
- writeSession
6301
- } from "@tinycloud/operations/state";
6302
- var ProfileManager;
6303
- var init_profiles = __esm({
6304
- "src/config/profiles.ts"() {
6305
- "use strict";
6306
- init_constants();
6307
- init_storage2();
6308
- init_errors();
6309
- ProfileManager = class _ProfileManager {
6310
- // ── Initialization ──────────────────────────────────────────────────
6311
- /**
6312
- * Runs `action` holding the profile's store lock (shared with operations
6313
- * and MCP). Reentrant, so the writers below can be called inside it; hold
6314
- * it around a whole read-modify-write, not just each write.
6315
- */
6316
- static async withLock(name, action, options) {
6317
- return withProfileLock3(name, action, options);
6318
- }
6319
- /**
6320
- * Read-modify-write of profile.json under the profile lock, so concurrent
6321
- * updates (another command, a login commit) are never erased.
6322
- */
6323
- static async updateProfile(name, update) {
6324
- return _ProfileManager.withLock(name, async () => {
6325
- const next = update(await _ProfileManager.getProfile(name));
6326
- await _ProfileManager.setProfile(name, next);
6327
- return next;
6328
- });
6329
- }
6330
- /**
6331
- * Creates ~/.tinycloud/ and ~/.tinycloud/profiles/ if they don't exist and
6332
- * (re)sets both to 0700: older releases created them 0775.
6333
- */
6334
- static async ensureConfigDir() {
6335
- for (const directory of [CONFIG_DIR, PROFILES_DIR]) {
6336
- await ensureDir(directory);
6337
- await chmod2(directory, PRIVATE_DIR_MODE);
6338
- }
6339
- }
6340
- /** Owner-only profile directory (0700), created or tightened before any write into it. */
6341
- static async ensureProfileDir(name) {
6342
- await _ProfileManager.ensureConfigDir();
6343
- const profileDir = join6(PROFILES_DIR, name);
6344
- await ensureDir(profileDir);
6345
- await chmod2(profileDir, PRIVATE_DIR_MODE);
6346
- return profileDir;
6347
- }
6348
- // ── Global config ───────────────────────────────────────────────────
6349
- /**
6350
- * Reads config.json. Returns a default config if the file is missing.
6351
- */
6352
- static async getConfig() {
6353
- const config = await readJson(CONFIG_FILE);
6354
- if (!config) {
6355
- return { defaultProfile: DEFAULT_PROFILE, version: 1 };
6356
- }
6357
- return config;
6358
- }
6359
- /**
6360
- * Writes the global config to config.json.
6361
- */
6362
- static async setConfig(config) {
6363
- await _ProfileManager.ensureConfigDir();
6364
- await writeJson(CONFIG_FILE, config);
6365
- }
6366
- // ── Profile CRUD ────────────────────────────────────────────────────
6367
- /**
6368
- * Returns the profile config for the given name.
6369
- * Throws CLIError if the profile doesn't exist.
6370
- */
6371
- static async getProfile(name) {
6372
- const profilePath3 = join6(PROFILES_DIR, name, "profile.json");
6373
- const profile = await readJson(profilePath3);
6374
- if (!profile) {
6375
- throw new CLIError(
6376
- "PROFILE_NOT_FOUND",
6377
- `Profile "${name}" does not exist. Create it with \`tc init --name ${name}\`.`
6378
- );
6379
- }
6380
- return profile;
6381
- }
6382
- /**
6383
- * Saves a profile config under the profile lock, creating the profile
6384
- * directory if needed. Use `updateProfile` to change an existing profile.
6385
- */
6386
- static async setProfile(name, data) {
6387
- await _ProfileManager.withLock(name, async () => {
6388
- await writeJson(join6(await _ProfileManager.ensureProfileDir(name), "profile.json"), data);
6389
- });
6390
- }
6391
- /** Removes profile.json under the profile lock (rollback of a profile a failed login created). */
6392
- static async removeProfileConfig(name) {
6393
- await _ProfileManager.withLock(name, () => rm2(join6(PROFILES_DIR, name, "profile.json"), { force: true }));
6394
- }
6395
- /**
6396
- * Returns true if a profile directory exists.
6397
- */
6398
- static async profileExists(name) {
6399
- return fileExists(join6(PROFILES_DIR, name, "profile.json"));
6400
- }
6401
- /**
6402
- * Returns an array of profile directory names.
6403
- */
6404
- static async listProfiles() {
6405
- return listDirs(PROFILES_DIR);
6406
- }
6407
- /**
6408
- * Deletes a profile. Its key, session, settings, stores and cache are
6409
- * removed while holding the profile lock, so another writer's critical
6410
- * section never sees them vanish midway: session and key first, settings
6411
- * last, so a crash midway never leaves a session or key without its
6412
- * profile. The deletion is then recorded, so a store write that waited for
6413
- * the lock meanwhile refuses rather than recreating a profile with only a
6414
- * session in it. `.lock` itself is left to the lock's release; the
6415
- * then-empty directory is removed afterwards unless another writer took
6416
- * the lock (or wrote) meanwhile. A profile directory that is a symlink is
6417
- * unlinked, its target left alone.
6418
- * Throws if the name is not one path segment or names the default profile.
6419
- */
6420
- static async deleteProfile(name) {
6421
- let profileDir;
6422
- try {
6423
- profileDir = profilePath2(name);
6424
- } catch {
6425
- throw new CLIError(
6426
- "INVALID_PROFILE_NAME",
6427
- `Invalid profile name "${name}": a profile name is one path segment (no "/", "\\", "." or "..").`,
6428
- ExitCode.USAGE_ERROR
6429
- );
6430
- }
6431
- const config = await _ProfileManager.getConfig();
6432
- if (config.defaultProfile === name) {
6433
- throw new CLIError(
6434
- "PROFILE_DELETE_DEFAULT",
6435
- `Cannot delete the default profile "${name}". Change the default first with \`tc profile default <other>\`.`
6436
- );
6437
- }
6438
- const kind = await lstat(profileDir).then((stats) => stats.isSymbolicLink() ? "link" : "present", (error) => {
6439
- if (error.code === "ENOENT") return "missing";
6440
- throw error;
6441
- });
6442
- if (kind === "missing") return;
6443
- if (kind === "link") {
6444
- await rm2(profileDir, { force: true });
6445
- return;
6446
- }
6447
- await _ProfileManager.withLock(name, async () => {
6448
- for (const file of ["session.json", "key.json"]) await rm2(join6(profileDir, file), { force: true });
6449
- for (const entry of await readdir2(profileDir)) {
6450
- if (entry !== ".lock" && entry !== "profile.json") await rm2(join6(profileDir, entry), { recursive: true, force: true });
6451
- }
6452
- await rm2(join6(profileDir, "profile.json"), { force: true });
6453
- await recordProfileDeletion(name);
6454
- });
6455
- await rmdir(profileDir).catch((error) => {
6456
- if (error.code !== "ENOENT" && error.code !== "ENOTEMPTY" && error.code !== "EEXIST") throw error;
6457
- });
6458
- }
6459
- // ── Key management ──────────────────────────────────────────────────
6460
- /**
6461
- * Returns the parsed JWK for a profile, or null if no key exists.
6462
- */
6463
- static async getKey(name) {
6464
- return readJson(join6(PROFILES_DIR, name, "key.json"));
6465
- }
6466
- /**
6467
- * Saves a JWK key under the profile lock (0600, in an owner-only profile
6468
- * directory). Refused (PROFILE_NOT_FOUND) if the profile was deleted while
6469
- * this waited for the lock, rather than leaving a key-only profile.
6470
- */
6471
- static async setKey(name, jwk) {
6472
- await _ProfileManager.withLock(name, async () => {
6473
- await refuseWriteToDeletedProfile2(name);
6474
- await writeJson(join6(await _ProfileManager.ensureProfileDir(name), "key.json"), jwk);
6475
- });
6476
- }
6477
- /** Removes key.json under the profile lock (rollback of a key a failed login created). */
6478
- static async removeKey(name) {
6479
- await _ProfileManager.withLock(name, () => rm2(join6(PROFILES_DIR, name, "key.json"), { force: true }));
6480
- }
6481
- // ── Session management ──────────────────────────────────────────────
6482
- /**
6483
- * Returns the parsed session for a profile, or null if none exists.
6484
- */
6485
- static async getSession(name) {
6486
- return readSession(name);
6487
- }
6488
- /**
6489
- * Saves session data for a profile.
6490
- */
6491
- static async setSession(name, session) {
6492
- await writeSession(name, session);
6493
- }
6494
- /**
6495
- * Removes the session file for a profile.
6496
- */
6497
- static async clearSession(name) {
6498
- await removeSession(name);
6499
- }
6500
- // ── Cache management ────────────────────────────────────────────────
6501
- /**
6502
- * Returns the profile's cache directory (share history lives here),
6503
- * created or tightened to 0700.
6504
- */
6505
- static async getCacheDir(name) {
6506
- const cacheDir = join6(await _ProfileManager.ensureProfileDir(name), "cache");
6507
- await ensureDir(cacheDir);
6508
- await chmod2(cacheDir, PRIVATE_DIR_MODE);
6509
- return cacheDir;
6510
- }
6511
- // ── Resolution helpers ──────────────────────────────────────────────
6512
- /**
6513
- * Resolves the full CLI context from flags, env vars, and config.
6514
- *
6515
- * Profile resolution: options.profile > TC_PROFILE env > config.defaultProfile > "default"
6516
- * Host resolution: options.host > TC_HOST env > discovered local node > profile.host > DEFAULT_HOST
6517
- *
6518
- * Local-node discovery (TC-106) only runs when no explicit host was given
6519
- * (`--host` / `TC_HOST`); it probes configured or registered local nodes and,
6520
- * after DID verification against the profile's pinned identity, prefers one
6521
- * over the stored/default host. For session-using commands, it verifies the
6522
- * stored session locally before probing. Loopback requires an explicit
6523
- * `localNodeUrl`; disable discovery with `autoDiscoverLocalNode: false`.
6524
- */
6525
- static async resolveContext(options, settings = {}) {
6526
- const config = await _ProfileManager.getConfig();
6527
- const profile = options.profile ?? process.env.TC_PROFILE ?? config.defaultProfile ?? DEFAULT_PROFILE;
6528
- let profileHost;
6529
- let profileConfig;
6530
- try {
6531
- profileConfig = await _ProfileManager.getProfile(profile);
6532
- profileHost = profileConfig.host;
6533
- } catch {
6534
- }
6535
- const envReplication = process.env.TC_REPLICATION?.toLowerCase();
6536
- const envEnabled = envReplication === "1" || envReplication === "true" || envReplication === "on";
6537
- const explicitEnvOff = envReplication === "0" || envReplication === "false" || envReplication === "off";
6538
- if (envReplication !== void 0 && !envEnabled && !explicitEnvOff) {
6539
- throw new CLIError("INVALID_ARGUMENT", "TC_REPLICATION must be one of 1, true, on, 0, false or off.", ExitCode.USAGE_ERROR);
6540
- }
6541
- const explicitOff = options.noReplication === true || options.replication === false;
6542
- const replication = options.replication === true ? true : explicitOff ? false : envEnabled;
6543
- const explicitHost = options.host ?? process.env.TC_HOST;
6544
- let host = explicitHost ?? profileHost ?? DEFAULT_HOST;
6545
- let localDiscovery;
6546
- if (explicitHost === void 0) {
6547
- const { discoverLocalNodeHost: discoverLocalNodeHost2 } = await Promise.resolve().then(() => (init_host(), host_exports));
6548
- const explicitKey = Boolean(options.privateKey || process.env.TC_PRIVATE_KEY);
6549
- const discovered = await discoverLocalNodeHost2(profile, {
6550
- awaitStoredSession: settings.storedSession !== "unused" && !explicitKey
6551
- });
6552
- if (discovered.host !== null) host = discovered.host;
6553
- if (discovered.deferred) localDiscovery = { deferredFrom: host };
6554
- }
6555
- setActiveProfileName(profile);
6556
- return {
6557
- profile,
6558
- host,
6559
- verbose: options.verbose ?? false,
6560
- noCache: options.noCache ?? false,
6561
- quiet: options.quiet ?? false,
6562
- replication,
6563
- replicationDebug: options.replicationDebug === true || process.env.TC_REPLICATION_DEBUG === "1",
6564
- ...localDiscovery === void 0 ? {} : { localDiscovery }
6565
- };
6566
- }
6567
- };
6568
- }
6569
- });
6570
-
6571
- // src/commands/courier.ts
6572
- 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>.';
6573
-
6574
- // src/index.ts
6575
- init_errors();
6576
- import { readFileSync as readFileSync2 } from "fs";
6577
- import { Command } from "commander";
6578
-
6579
- // src/output/banner.ts
6580
- init_formatter();
6581
-
6582
- // src/output/taglines.ts
6583
- var HOLIDAY_TAGLINES = [
6584
- { month: 1, day: 1, range: 1, tagline: "New year, new keys, same cloud." },
6585
- { month: 2, day: 14, tagline: "We love your data as much as you do." },
6586
- { month: 3, day: 14, tagline: "3.14159 reasons to encrypt everything." },
6587
- { month: 5, day: 4, tagline: "May the fourth be with your keys." },
6588
- { month: 10, day: 31, tagline: "Nothing scarier than plaintext secrets." },
6589
- { month: 12, day: 25, range: 2, tagline: "Unwrap your data, not your keys." },
6590
- { month: 12, day: 31, tagline: "Encrypt your resolutions." }
6591
- ];
6592
- var TAGLINES = [
6593
- // Professional
6594
- "Your data, your keys, your cloud.",
6595
- "Self-sovereign storage for the modern web.",
6596
- "The cloud you actually own.",
6597
- "Encrypted by default, decentralized by design.",
6598
- "Where your data answers only to you.",
6599
- "End-to-end encrypted. No exceptions.",
6600
- "Like S3 but you hold the keys.",
6601
- "Privacy isn't a feature. It's the architecture.",
6602
- "Sovereign storage, zero knowledge.",
6603
- "Your .env is safe here \u2014 we use real cryptography.",
6604
- // Playful / nerdy
6605
- "UCAN do anything.",
6606
- "Keys generated, delegations granted, data liberated.",
6607
- "Decentralized storage, centralized vibes.",
6608
- "Trust nobody, delegate everything.",
6609
- "sudo make me a sandwich, encrypted.",
6610
- "Have you tried turning your keys off and on again?",
6611
- "All your base are belong to you.",
6612
- "In UCAN we trust.",
6613
- "0 knowledge, 100% confidence.",
6614
- "Keeping secrets since 2024."
6615
- ];
6616
- function getHolidayTagline() {
6617
- const now = /* @__PURE__ */ new Date();
6618
- const month = now.getMonth() + 1;
6619
- const day = now.getDate();
6620
- for (const h of HOLIDAY_TAGLINES) {
6621
- const range = h.range ?? 0;
6622
- if (h.month === month && Math.abs(day - h.day) <= range) {
6623
- return h.tagline;
6624
- }
6625
- }
6626
- return null;
6627
- }
6628
- function pickTagline() {
6629
- const holiday = getHolidayTagline();
6630
- if (holiday) return holiday;
6631
- return TAGLINES[Math.floor(Math.random() * TAGLINES.length)];
6632
- }
6633
-
6634
- // src/output/banner.ts
6635
- init_theme();
6636
- import { execSync } from "child_process";
6637
- var bannerEmitted = false;
6638
- function resolveCommitHash() {
6639
- try {
6640
- return execSync("git rev-parse --short HEAD", {
6641
- encoding: "utf-8",
6642
- stdio: ["pipe", "pipe", "pipe"]
6643
- }).trim() || null;
6644
- } catch {
6645
- return null;
6646
- }
6647
- }
6648
- function formatBannerLine(version2) {
6649
- const commit = resolveCommitHash();
6650
- const tagline = pickTagline();
6651
- const versionPart = `tc v${version2}`;
6652
- const commitPart = commit ? ` (${commit})` : "";
6653
- const separator = " \u2014 ";
6654
- if (!isInteractive()) {
6655
- return `${versionPart}${commitPart}${separator}${tagline}`;
6656
- }
6657
- return [
6658
- theme.brand("\u2601\uFE0F tc"),
6659
- " ",
6660
- theme.muted(`v${version2}`),
6661
- commit ? theme.dim(` (${commit})`) : "",
6662
- theme.dim(separator),
6663
- theme.primary(tagline)
6664
- ].join("");
6665
- }
6666
- function emitBanner(version2) {
6667
- if (bannerEmitted) return;
6668
- if (shouldOutputJson()) return;
6669
- if (process.env.TC_HIDE_BANNER === "1") return;
6670
- bannerEmitted = true;
6671
- process.stderr.write(formatBannerLine(version2) + "\n\n");
6672
- }
6673
-
6674
- // src/index.ts
6675
- init_replication_registry();
6676
- init_theme();
6677
- init_formatter();
6678
- init_profiles();
6679
-
6680
- // ../share-sdk/dist/index.js
6681
- init_sha2();
6682
-
6683
- // ../../node_modules/@noble/curves/esm/ed25519.js
6684
- init_sha2();
6685
- init_utils();
6686
-
6687
- // ../../node_modules/@noble/curves/esm/utils.js
6688
- init_utils();
6689
- init_utils();
6690
- var _0n = /* @__PURE__ */ BigInt(0);
6691
- var _1n = /* @__PURE__ */ BigInt(1);
6692
- function _abool2(value, title = "") {
6693
- if (typeof value !== "boolean") {
6694
- const prefix = title && `"${title}"`;
6695
- throw new Error(prefix + "expected boolean, got type=" + typeof value);
6696
- }
6697
- return value;
6698
- }
6699
- function _abytes2(value, length4, title = "") {
6700
- const bytes = isBytes(value);
6701
- const len = value?.length;
6702
- const needsLen = length4 !== void 0;
6703
- if (!bytes || needsLen && len !== length4) {
6704
- const prefix = title && `"${title}" `;
6705
- const ofLen = needsLen ? ` of length ${length4}` : "";
6706
- const got = bytes ? `length=${len}` : `type=${typeof value}`;
6707
- throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
6708
- }
6709
- return value;
6710
- }
6711
- function hexToNumber(hex3) {
6712
- if (typeof hex3 !== "string")
6713
- throw new Error("hex string expected, got " + typeof hex3);
6714
- return hex3 === "" ? _0n : BigInt("0x" + hex3);
6715
- }
6716
- function bytesToNumberBE(bytes) {
6717
- return hexToNumber(bytesToHex(bytes));
6718
- }
6719
- function bytesToNumberLE(bytes) {
6720
- abytes(bytes);
6721
- return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
6722
- }
6723
- function numberToBytesBE(n, len) {
6724
- return hexToBytes(n.toString(16).padStart(len * 2, "0"));
6725
- }
6726
- function numberToBytesLE(n, len) {
6727
- return numberToBytesBE(n, len).reverse();
6728
- }
6729
- function ensureBytes(title, hex3, expectedLength) {
6730
- let res;
6731
- if (typeof hex3 === "string") {
6732
- try {
6733
- res = hexToBytes(hex3);
6734
- } catch (e) {
6735
- throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
6736
- }
6737
- } else if (isBytes(hex3)) {
6738
- res = Uint8Array.from(hex3);
6739
- } else {
6740
- throw new Error(title + " must be hex string or Uint8Array");
6741
- }
6742
- const len = res.length;
6743
- if (typeof expectedLength === "number" && len !== expectedLength)
6744
- throw new Error(title + " of length " + expectedLength + " expected, got " + len);
6745
- return res;
6746
- }
6747
- function equalBytes(a, b) {
6748
- if (a.length !== b.length)
6749
- return false;
6750
- let diff = 0;
6751
- for (let i = 0; i < a.length; i++)
6752
- diff |= a[i] ^ b[i];
6753
- return diff === 0;
6754
- }
6755
- function copyBytes(bytes) {
6756
- return Uint8Array.from(bytes);
6757
- }
6758
- var isPosBig = (n) => typeof n === "bigint" && _0n <= n;
6759
- function inRange(n, min, max) {
6760
- return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
6761
- }
6762
- function aInRange(title, n, min, max) {
6763
- if (!inRange(n, min, max))
6764
- throw new Error("expected valid " + title + ": " + min + " <= n < " + max + ", got " + n);
6765
- }
6766
- function bitLen(n) {
6767
- let len;
6768
- for (len = 0; n > _0n; n >>= _1n, len += 1)
6769
- ;
6770
- return len;
6771
- }
6772
- var bitMask = (n) => (_1n << BigInt(n)) - _1n;
6773
- function _validateObject(object3, fields, optFields = {}) {
6774
- if (!object3 || typeof object3 !== "object")
6775
- throw new Error("expected valid options object");
6776
- function checkField(fieldName, expectedType, isOpt) {
6777
- const val = object3[fieldName];
6778
- if (isOpt && val === void 0)
6779
- return;
6780
- const current = typeof val;
6781
- if (current !== expectedType || val === null)
6782
- throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
6783
- }
6784
- Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
6785
- Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
6786
- }
6787
- var notImplemented = () => {
6788
- throw new Error("not implemented");
6789
- };
6790
- function memoized(fn) {
6791
- const map = /* @__PURE__ */ new WeakMap();
6792
- return (arg, ...args) => {
6793
- const val = map.get(arg);
6794
- if (val !== void 0)
6795
- return val;
6796
- const computed = fn(arg, ...args);
6797
- map.set(arg, computed);
6798
- return computed;
6799
- };
6800
- }
6801
-
6802
- // ../../node_modules/@noble/curves/esm/abstract/modular.js
6803
- var _0n2 = BigInt(0);
6804
- var _1n2 = BigInt(1);
6805
- var _2n = /* @__PURE__ */ BigInt(2);
6806
- var _3n = /* @__PURE__ */ BigInt(3);
6807
- var _4n = /* @__PURE__ */ BigInt(4);
6808
- var _5n = /* @__PURE__ */ BigInt(5);
6809
- var _7n = /* @__PURE__ */ BigInt(7);
6810
- var _8n = /* @__PURE__ */ BigInt(8);
6811
- var _9n = /* @__PURE__ */ BigInt(9);
6812
- var _16n = /* @__PURE__ */ BigInt(16);
6813
- function mod(a, b) {
6814
- const result = a % b;
6815
- return result >= _0n2 ? result : b + result;
6816
- }
6817
- function pow2(x, power, modulo) {
6818
- let res = x;
6819
- while (power-- > _0n2) {
6820
- res *= res;
6821
- res %= modulo;
6822
- }
6823
- return res;
6824
- }
6825
- function invert(number, modulo) {
6826
- if (number === _0n2)
6827
- throw new Error("invert: expected non-zero number");
6828
- if (modulo <= _0n2)
6829
- throw new Error("invert: expected positive modulus, got " + modulo);
6830
- let a = mod(number, modulo);
6831
- let b = modulo;
6832
- let x = _0n2, y = _1n2, u = _1n2, v = _0n2;
6833
- while (a !== _0n2) {
6834
- const q = b / a;
6835
- const r = b % a;
6836
- const m = x - u * q;
6837
- const n = y - v * q;
6838
- b = a, a = r, x = u, y = v, u = m, v = n;
6839
- }
6840
- const gcd = b;
6841
- if (gcd !== _1n2)
6842
- throw new Error("invert: does not exist");
6843
- return mod(x, modulo);
6844
- }
6845
- function assertIsSquare(Fp2, root, n) {
6846
- if (!Fp2.eql(Fp2.sqr(root), n))
6847
- throw new Error("Cannot find square root");
6848
- }
6849
- function sqrt3mod4(Fp2, n) {
6850
- const p1div4 = (Fp2.ORDER + _1n2) / _4n;
6851
- const root = Fp2.pow(n, p1div4);
6852
- assertIsSquare(Fp2, root, n);
6853
- return root;
6854
- }
6855
- function sqrt5mod8(Fp2, n) {
6856
- const p5div8 = (Fp2.ORDER - _5n) / _8n;
6857
- const n2 = Fp2.mul(n, _2n);
6858
- const v = Fp2.pow(n2, p5div8);
6859
- const nv = Fp2.mul(n, v);
6860
- const i = Fp2.mul(Fp2.mul(nv, _2n), v);
6861
- const root = Fp2.mul(nv, Fp2.sub(i, Fp2.ONE));
6862
- assertIsSquare(Fp2, root, n);
6863
- return root;
6864
- }
6865
- function sqrt9mod16(P) {
6866
- const Fp_ = Field(P);
6867
- const tn = tonelliShanks(P);
6868
- const c1 = tn(Fp_, Fp_.neg(Fp_.ONE));
6869
- const c2 = tn(Fp_, c1);
6870
- const c3 = tn(Fp_, Fp_.neg(c1));
6871
- const c4 = (P + _7n) / _16n;
6872
- return (Fp2, n) => {
6873
- let tv1 = Fp2.pow(n, c4);
6874
- let tv2 = Fp2.mul(tv1, c1);
6875
- const tv3 = Fp2.mul(tv1, c2);
6876
- const tv4 = Fp2.mul(tv1, c3);
6877
- const e1 = Fp2.eql(Fp2.sqr(tv2), n);
6878
- const e2 = Fp2.eql(Fp2.sqr(tv3), n);
6879
- tv1 = Fp2.cmov(tv1, tv2, e1);
6880
- tv2 = Fp2.cmov(tv4, tv3, e2);
6881
- const e3 = Fp2.eql(Fp2.sqr(tv2), n);
6882
- const root = Fp2.cmov(tv1, tv2, e3);
6883
- assertIsSquare(Fp2, root, n);
6884
- return root;
6885
- };
6886
- }
6887
- function tonelliShanks(P) {
6888
- if (P < _3n)
6889
- throw new Error("sqrt is not defined for small field");
6890
- let Q = P - _1n2;
6891
- let S = 0;
6892
- while (Q % _2n === _0n2) {
6893
- Q /= _2n;
6894
- S++;
6895
- }
6896
- let Z = _2n;
6897
- const _Fp = Field(P);
6898
- while (FpLegendre(_Fp, Z) === 1) {
6899
- if (Z++ > 1e3)
6900
- throw new Error("Cannot find square root: probably non-prime P");
6366
+ let Z = _2n;
6367
+ const _Fp = Field(P);
6368
+ while (FpLegendre(_Fp, Z) === 1) {
6369
+ if (Z++ > 1e3)
6370
+ throw new Error("Cannot find square root: probably non-prime P");
6901
6371
  }
6902
6372
  if (S === 1)
6903
6373
  return sqrt3mod4;
@@ -6942,26 +6412,6 @@ function FpSqrt(P) {
6942
6412
  return sqrt9mod16(P);
6943
6413
  return tonelliShanks(P);
6944
6414
  }
6945
- var isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n2) === _1n2;
6946
- var FIELD_FIELDS = [
6947
- "create",
6948
- "isValid",
6949
- "is0",
6950
- "neg",
6951
- "inv",
6952
- "sqrt",
6953
- "sqr",
6954
- "eql",
6955
- "add",
6956
- "sub",
6957
- "mul",
6958
- "pow",
6959
- "div",
6960
- "addN",
6961
- "subN",
6962
- "mulN",
6963
- "sqrN"
6964
- ];
6965
6415
  function validateField(field) {
6966
6416
  const initial = {
6967
6417
  ORDER: "bigint",
@@ -7124,10 +6574,45 @@ function Field(ORDER, bitLenOrOpts, isLE2 = false, opts = {}) {
7124
6574
  });
7125
6575
  return Object.freeze(f);
7126
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
+ });
7127
6614
 
7128
6615
  // ../../node_modules/@noble/curves/esm/abstract/curve.js
7129
- var _0n3 = BigInt(0);
7130
- var _1n3 = BigInt(1);
7131
6616
  function negateCt(condition, item) {
7132
6617
  const neg = item.negate();
7133
6618
  return condition ? neg : item;
@@ -7166,157 +6651,28 @@ function calcOffsets(n, window, wOpts) {
7166
6651
  return { nextN, offset, isZero, isNeg, isNegF, offsetF };
7167
6652
  }
7168
6653
  function validateMSMPoints(points, c) {
7169
- if (!Array.isArray(points))
7170
- throw new Error("array expected");
7171
- points.forEach((p, i) => {
7172
- if (!(p instanceof c))
7173
- throw new Error("invalid point at index " + i);
7174
- });
7175
- }
7176
- function validateMSMScalars(scalars, field) {
7177
- if (!Array.isArray(scalars))
7178
- throw new Error("array of scalars expected");
7179
- scalars.forEach((s, i) => {
7180
- if (!field.isValid(s))
7181
- throw new Error("invalid scalar at index " + i);
7182
- });
7183
- }
7184
- var pointPrecomputes = /* @__PURE__ */ new WeakMap();
7185
- var pointWindowSizes = /* @__PURE__ */ new WeakMap();
7186
- function getW(P) {
7187
- return pointWindowSizes.get(P) || 1;
7188
- }
7189
- function assert0(n) {
7190
- if (n !== _0n3)
7191
- throw new Error("invalid wNAF");
7192
- }
7193
- var wNAF = class {
7194
- // Parametrized with a given Point class (not individual point)
7195
- constructor(Point, bits) {
7196
- this.BASE = Point.BASE;
7197
- this.ZERO = Point.ZERO;
7198
- this.Fn = Point.Fn;
7199
- this.bits = bits;
7200
- }
7201
- // non-const time multiplication ladder
7202
- _unsafeLadder(elm, n, p = this.ZERO) {
7203
- let d = elm;
7204
- while (n > _0n3) {
7205
- if (n & _1n3)
7206
- p = p.add(d);
7207
- d = d.double();
7208
- n >>= _1n3;
7209
- }
7210
- return p;
7211
- }
7212
- /**
7213
- * Creates a wNAF precomputation window. Used for caching.
7214
- * Default window size is set by `utils.precompute()` and is equal to 8.
7215
- * Number of precomputed points depends on the curve size:
7216
- * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
7217
- * - 𝑊 is the window size
7218
- * - 𝑛 is the bitlength of the curve order.
7219
- * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
7220
- * @param point Point instance
7221
- * @param W window size
7222
- * @returns precomputed point tables flattened to a single array
7223
- */
7224
- precomputeWindow(point, W) {
7225
- const { windows, windowSize } = calcWOpts(W, this.bits);
7226
- const points = [];
7227
- let p = point;
7228
- let base4 = p;
7229
- for (let window = 0; window < windows; window++) {
7230
- base4 = p;
7231
- points.push(base4);
7232
- for (let i = 1; i < windowSize; i++) {
7233
- base4 = base4.add(p);
7234
- points.push(base4);
7235
- }
7236
- p = base4.double();
7237
- }
7238
- return points;
7239
- }
7240
- /**
7241
- * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
7242
- * More compact implementation:
7243
- * https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541
7244
- * @returns real and fake (for const-time) points
7245
- */
7246
- wNAF(W, precomputes, n) {
7247
- if (!this.Fn.isValid(n))
7248
- throw new Error("invalid scalar");
7249
- let p = this.ZERO;
7250
- let f = this.BASE;
7251
- const wo = calcWOpts(W, this.bits);
7252
- for (let window = 0; window < wo.windows; window++) {
7253
- const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo);
7254
- n = nextN;
7255
- if (isZero) {
7256
- f = f.add(negateCt(isNegF, precomputes[offsetF]));
7257
- } else {
7258
- p = p.add(negateCt(isNeg, precomputes[offset]));
7259
- }
7260
- }
7261
- assert0(n);
7262
- return { p, f };
7263
- }
7264
- /**
7265
- * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
7266
- * @param acc accumulator point to add result of multiplication
7267
- * @returns point
7268
- */
7269
- wNAFUnsafe(W, precomputes, n, acc = this.ZERO) {
7270
- const wo = calcWOpts(W, this.bits);
7271
- for (let window = 0; window < wo.windows; window++) {
7272
- if (n === _0n3)
7273
- break;
7274
- const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo);
7275
- n = nextN;
7276
- if (isZero) {
7277
- continue;
7278
- } else {
7279
- const item = precomputes[offset];
7280
- acc = acc.add(isNeg ? item.negate() : item);
7281
- }
7282
- }
7283
- assert0(n);
7284
- return acc;
7285
- }
7286
- getPrecomputes(W, point, transform) {
7287
- let comp = pointPrecomputes.get(point);
7288
- if (!comp) {
7289
- comp = this.precomputeWindow(point, W);
7290
- if (W !== 1) {
7291
- if (typeof transform === "function")
7292
- comp = transform(comp);
7293
- pointPrecomputes.set(point, comp);
7294
- }
7295
- }
7296
- return comp;
7297
- }
7298
- cached(point, scalar, transform) {
7299
- const W = getW(point);
7300
- return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
7301
- }
7302
- unsafe(point, scalar, transform, prev) {
7303
- const W = getW(point);
7304
- if (W === 1)
7305
- return this._unsafeLadder(point, scalar, prev);
7306
- return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
7307
- }
7308
- // We calculate precomputes for elliptic curve point multiplication
7309
- // using windowed method. This specifies window size and
7310
- // stores precomputed values. Usually only base point would be precomputed.
7311
- createCache(P, W) {
7312
- validateW(W, this.bits);
7313
- pointWindowSizes.set(P, W);
7314
- pointPrecomputes.delete(P);
7315
- }
7316
- hasCache(elm) {
7317
- return getW(elm) !== 1;
7318
- }
7319
- };
6654
+ if (!Array.isArray(points))
6655
+ throw new Error("array expected");
6656
+ points.forEach((p, i) => {
6657
+ if (!(p instanceof c))
6658
+ throw new Error("invalid point at index " + i);
6659
+ });
6660
+ }
6661
+ function validateMSMScalars(scalars, field) {
6662
+ if (!Array.isArray(scalars))
6663
+ throw new Error("array of scalars expected");
6664
+ scalars.forEach((s, i) => {
6665
+ if (!field.isValid(s))
6666
+ throw new Error("invalid scalar at index " + i);
6667
+ });
6668
+ }
6669
+ function getW(P) {
6670
+ return pointWindowSizes.get(P) || 1;
6671
+ }
6672
+ function assert0(n) {
6673
+ if (n !== _0n3)
6674
+ throw new Error("invalid wNAF");
6675
+ }
7320
6676
  function pippenger(c, fieldN, points, scalars) {
7321
6677
  validateMSMPoints(points, c);
7322
6678
  validateMSMScalars(scalars, fieldN);
@@ -7387,12 +6743,147 @@ function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
7387
6743
  CURVE = Object.freeze(Object.assign({}, CURVE));
7388
6744
  return { CURVE, Fp: Fp2, Fn: Fn2 };
7389
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
+ });
7390
6885
 
7391
6886
  // ../../node_modules/@noble/curves/esm/abstract/edwards.js
7392
- var _0n4 = BigInt(0);
7393
- var _1n4 = BigInt(1);
7394
- var _2n2 = BigInt(2);
7395
- var _8n2 = BigInt(8);
7396
6887
  function isEdValidXY(Fp2, CURVE, x, y) {
7397
6888
  const x2 = Fp2.sqr(x);
7398
6889
  const y2 = Fp2.sqr(y);
@@ -7676,828 +7167,1513 @@ function edwards(params, extraOpts = {}) {
7676
7167
  Point.BASE.precompute(8);
7677
7168
  return Point;
7678
7169
  }
7679
- var PrimeEdwardsPoint = class {
7680
- constructor(ep) {
7681
- this.ep = ep;
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));
7682
7192
  }
7683
- // Static methods that must be implemented by subclasses
7684
- static fromBytes(_bytes) {
7685
- notImplemented();
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 };
7686
7201
  }
7687
- static fromHex(_hex) {
7688
- notImplemented();
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 };
7689
7207
  }
7690
- get x() {
7691
- return this.toAffine().x;
7208
+ function getPublicKey(secretKey) {
7209
+ return getExtendedPublicKey(secretKey).pointBytes;
7692
7210
  }
7693
- get y() {
7694
- return this.toAffine().y;
7211
+ function hashDomainToScalar(context = Uint8Array.of(), ...msgs) {
7212
+ const msg = concatBytes(...msgs);
7213
+ return modN_LE(cHash(domain(msg, ensureBytes("context", context), !!prehash)));
7695
7214
  }
7696
- // Common implementations
7697
- clearCofactor() {
7698
- return this;
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) };
7699
7270
  }
7700
- assertValidity() {
7701
- this.ep.assertValidity();
7271
+ function isValidSecretKey(key) {
7272
+ return isBytes(key) && key.length === Fn2.BYTES;
7702
7273
  }
7703
- toAffine(invertedZ) {
7704
- return this.ep.toAffine(invertedZ);
7274
+ function isValidPublicKey(key, zip215) {
7275
+ try {
7276
+ return !!Point.fromBytes(key, zip215);
7277
+ } catch (error) {
7278
+ return false;
7279
+ }
7705
7280
  }
7706
- toHex() {
7707
- return bytesToHex(this.toBytes());
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
+ };
7708
7443
  }
7709
- toString() {
7710
- return this.toHex();
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)();
7711
7678
  }
7712
- isTorsionFree() {
7713
- return true;
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}`);
7714
7688
  }
7715
- isSmallOrder() {
7716
- return false;
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
+ );
7717
7700
  }
7718
- add(other) {
7719
- this.assertSame(other);
7720
- return this.init(this.ep.add(other.ep));
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();
7721
7781
  }
7722
- subtract(other) {
7723
- this.assertSame(other);
7724
- return this.init(this.ep.subtract(other.ep));
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
+ }
7725
7803
  }
7726
- multiply(scalar) {
7727
- return this.init(this.ep.multiply(scalar));
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();
7728
7827
  }
7729
- multiplyUnsafe(scalar) {
7730
- return this.init(this.ep.multiplyUnsafe(scalar));
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;
7731
7854
  }
7732
- double() {
7733
- return this.init(this.ep.double());
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;
7734
7861
  }
7735
- negate() {
7736
- return this.init(this.ep.negate());
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;
7737
7884
  }
7738
- precompute(windowSize, isLazy) {
7739
- return this.init(this.ep.precompute(windowSize, isLazy));
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" };
7740
7905
  }
7741
- /** @deprecated use `toBytes` */
7742
- toRawBytes() {
7743
- return this.toBytes();
7906
+ if (typeof session.expiresAt === "string" && Date.parse(session.expiresAt) <= Date.now()) {
7907
+ return { unavailable: "session_expired" };
7744
7908
  }
7745
- };
7746
- function eddsa(Point, cHash, eddsaOpts = {}) {
7747
- if (typeof cHash !== "function")
7748
- throw new Error('"hash" function param is required');
7749
- _validateObject(eddsaOpts, {}, {
7750
- adjustScalarBytes: "function",
7751
- randomBytes: "function",
7752
- domain: "function",
7753
- prehash: "function",
7754
- mapToCurve: "function"
7755
- });
7756
- const { prehash } = eddsaOpts;
7757
- const { BASE, Fp: Fp2, Fn: Fn2 } = Point;
7758
- const randomBytes3 = eddsaOpts.randomBytes || randomBytes;
7759
- const adjustScalarBytes2 = eddsaOpts.adjustScalarBytes || ((bytes) => bytes);
7760
- const domain = eddsaOpts.domain || ((data, ctx, phflag) => {
7761
- _abool2(phflag, "phflag");
7762
- if (ctx.length || phflag)
7763
- throw new Error("Contexts/pre-hash are not supported");
7764
- return data;
7765
- });
7766
- function modN_LE(hash) {
7767
- return Fn2.create(bytesToNumberLE(hash));
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" };
7768
7922
  }
7769
- function getPrivateScalar(key) {
7770
- const len = lengths.secretKey;
7771
- key = ensureBytes("private key", key, len);
7772
- const hashed = ensureBytes("hashed private key", cHash(key), 2 * len);
7773
- const head = adjustScalarBytes2(hashed.slice(0, len));
7774
- const prefix = hashed.slice(len, 2 * len);
7775
- const scalar = modN_LE(head);
7776
- return { head, prefix, scalar };
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;
7777
7940
  }
7778
- function getExtendedPublicKey(secretKey) {
7779
- const { head, prefix, scalar } = getPrivateScalar(secretKey);
7780
- const point = BASE.multiply(scalar);
7781
- const pointBytes = point.toBytes();
7782
- return { head, prefix, scalar, point, pointBytes };
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
+ );
7783
7953
  }
7784
- function getPublicKey(secretKey) {
7785
- return getExtendedPublicKey(secretKey).pointBytes;
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");
7963
+ }
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;
7786
7984
  }
7787
- function hashDomainToScalar(context = Uint8Array.of(), ...msgs) {
7788
- const msg = concatBytes(...msgs);
7789
- return modN_LE(cHash(domain(msg, ensureBytes("context", context), !!prehash)));
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");
7790
7993
  }
7791
- function sign(msg, secretKey, options = {}) {
7792
- msg = ensureBytes("message", msg);
7793
- if (prehash)
7794
- msg = prehash(msg);
7795
- const { prefix, scalar, pointBytes } = getExtendedPublicKey(secretKey);
7796
- const r = hashDomainToScalar(options.context, prefix, msg);
7797
- const R = BASE.multiply(r).toBytes();
7798
- const k = hashDomainToScalar(options.context, R, pointBytes, msg);
7799
- const s = Fn2.create(r + k * scalar);
7800
- if (!Fn2.isValid(s))
7801
- throw new Error("sign failed: invalid s");
7802
- const rs = concatBytes(R, Fn2.toBytes(s));
7803
- return _abytes2(rs, lengths.signature, "result");
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
+ }));
7804
8009
  }
7805
- const verifyOpts = { zip215: true };
7806
- function verify(sig, msg, publicKey, options = verifyOpts) {
7807
- const { context, zip215 } = options;
7808
- const len = lengths.signature;
7809
- sig = ensureBytes("signature", sig, len);
7810
- msg = ensureBytes("message", msg);
7811
- publicKey = ensureBytes("publicKey", publicKey, lengths.publicKey);
7812
- if (zip215 !== void 0)
7813
- _abool2(zip215, "zip215");
7814
- if (prehash)
7815
- msg = prehash(msg);
7816
- const mid = len / 2;
7817
- const r = sig.subarray(0, mid);
7818
- const s = bytesToNumberLE(sig.subarray(mid, len));
7819
- let A, R, SB;
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
+ );
8021
+ }
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 };
7820
8047
  try {
7821
- A = Point.fromBytes(publicKey, zip215);
7822
- R = Point.fromBytes(r, zip215);
7823
- SB = BASE.multiplyUnsafe(s);
8048
+ await ProfileManager.setSession(ctx.profile, session);
8049
+ await ProfileManager.setProfile(ctx.profile, profile);
7824
8050
  } catch (error) {
7825
- return false;
8051
+ throw annotate(error, await restoreBeforeBootstrap(ctx.profile, previousProfile));
7826
8052
  }
7827
- if (!zip215 && A.isSmallOrder())
7828
- return false;
7829
- const k = hashDomainToScalar(context, R.toBytes(), A.toBytes(), msg);
7830
- const RkA = R.add(A.multiplyUnsafe(k));
7831
- return RkA.subtract(SB).clearCofactor().is0();
7832
- }
7833
- const _size = Fp2.BYTES;
7834
- const lengths = {
7835
- secretKey: _size,
7836
- publicKey: _size,
7837
- signature: 2 * _size,
7838
- seed: _size
8053
+ return { previousProfile, profile, session };
8054
+ });
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);
7839
8072
  };
7840
- function randomSecretKey(seed = randomBytes3(lengths.seed)) {
7841
- return _abytes2(seed, lengths.seed, "seed");
8073
+ let node;
8074
+ try {
8075
+ node = await createSDKInstance(ctx);
8076
+ } catch (error) {
8077
+ return abandon(error);
8078
+ }
8079
+ return { node, abandon };
8080
+ }
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\`.`;
8100
+ }
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";
8105
+ }
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);
8110
+ }
8111
+ async function ensureAuthenticated(ctx, options) {
8112
+ if (options?.privateKey) {
8113
+ return createSDKInstance(ctx, options);
7842
8114
  }
7843
- function keygen(seed) {
7844
- const secretKey = utils.randomSecretKey(seed);
7845
- return { secretKey, publicKey: getPublicKey(secretKey) };
8115
+ const profile = await ProfileManager.getProfile(ctx.profile).catch(() => null);
8116
+ if (profile?.authMethod === "local" && profile.privateKey) {
8117
+ return createSDKInstance(ctx);
7846
8118
  }
7847
- function isValidSecretKey(key) {
7848
- return isBytes(key) && key.length === Fn2.BYTES;
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
+ );
7849
8126
  }
7850
- function isValidPublicKey(key, zip215) {
7851
- try {
7852
- return !!Point.fromBytes(key, zip215);
7853
- } catch (error) {
7854
- return false;
7855
- }
8127
+ return createSDKInstance(ctx, options);
8128
+ }
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"];
7856
8145
  }
7857
- const utils = {
7858
- getExtendedPublicKey,
7859
- randomSecretKey,
7860
- isValidSecretKey,
7861
- isValidPublicKey,
7862
- /**
7863
- * Converts ed public key to x public key. Uses formula:
7864
- * - ed25519:
7865
- * - `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
7866
- * - `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
7867
- * - ed448:
7868
- * - `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
7869
- * - `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
7870
- */
7871
- toMontgomery(publicKey) {
7872
- const { y } = Point.fromBytes(publicKey);
7873
- const size = lengths.publicKey;
7874
- const is25519 = size === 32;
7875
- if (!is25519 && size !== 57)
7876
- throw new Error("only defined for 25519 and 448");
7877
- const u = is25519 ? Fp2.div(_1n4 + y, _1n4 - y) : Fp2.div(y - _1n4, y + _1n4);
7878
- return Fp2.toBytes(u);
7879
- },
7880
- toMontgomerySecret(secretKey) {
7881
- const size = lengths.secretKey;
7882
- _abytes2(secretKey, size);
7883
- const hashed = cHash(secretKey.subarray(0, size));
7884
- return adjustScalarBytes2(hashed).subarray(0, size);
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];
7885
8170
  },
7886
- /** @deprecated */
7887
- randomPrivateKey: randomSecretKey,
7888
- /** @deprecated */
7889
- precompute(windowSize = 8, point = Point.BASE) {
7890
- return point.precompute(windowSize, false);
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
+ }));
7891
8180
  }
7892
8181
  };
7893
- return Object.freeze({
7894
- keygen,
7895
- getPublicKey,
7896
- sign,
7897
- verify,
7898
- utils,
7899
- Point,
7900
- lengths
7901
- });
7902
- }
7903
- function _eddsa_legacy_opts_to_new(c) {
7904
- const CURVE = {
7905
- a: c.a,
7906
- d: c.d,
7907
- p: c.Fp.ORDER,
7908
- n: c.n,
7909
- h: c.h,
7910
- Gx: c.Gx,
7911
- Gy: c.Gy
7912
- };
7913
- const Fp2 = c.Fp;
7914
- const Fn2 = Field(CURVE.n, c.nBitLength, true);
7915
- const curveOpts = { Fp: Fp2, Fn: Fn2, uvRatio: c.uvRatio };
7916
- const eddsaOpts = {
7917
- randomBytes: c.randomBytes,
7918
- adjustScalarBytes: c.adjustScalarBytes,
7919
- domain: c.domain,
7920
- prehash: c.prehash,
7921
- mapToCurve: c.mapToCurve
7922
- };
7923
- return { CURVE, curveOpts, hash: c.hash, eddsaOpts };
7924
8182
  }
7925
- function _eddsa_new_output_to_legacy(c, eddsa2) {
7926
- const Point = eddsa2.Point;
7927
- const legacy = Object.assign({}, eddsa2, {
7928
- ExtendedPoint: Point,
7929
- CURVE: c,
7930
- nBitLength: Point.Fn.BITS,
7931
- nByteLength: Point.Fn.BYTES
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)
7932
8196
  });
7933
- return legacy;
7934
- }
7935
- function twistedEdwards(c) {
7936
- const { CURVE, curveOpts, hash, eddsaOpts } = _eddsa_legacy_opts_to_new(c);
7937
- const Point = edwards(CURVE, curveOpts);
7938
- const EDDSA = eddsa(Point, hash, eddsaOpts);
7939
- return _eddsa_new_output_to_legacy(c, EDDSA);
7940
- }
7941
-
7942
- // ../../node_modules/@noble/curves/esm/ed25519.js
7943
- var _0n5 = /* @__PURE__ */ BigInt(0);
7944
- var _1n5 = BigInt(1);
7945
- var _2n3 = BigInt(2);
7946
- var _3n2 = BigInt(3);
7947
- var _5n2 = BigInt(5);
7948
- var _8n3 = BigInt(8);
7949
- var ed25519_CURVE_p = BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed");
7950
- var ed25519_CURVE = /* @__PURE__ */ (() => ({
7951
- p: ed25519_CURVE_p,
7952
- n: BigInt("0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"),
7953
- h: _8n3,
7954
- a: BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec"),
7955
- d: BigInt("0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3"),
7956
- Gx: BigInt("0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a"),
7957
- Gy: BigInt("0x6666666666666666666666666666666666666666666666666666666666666658")
7958
- }))();
7959
- function ed25519_pow_2_252_3(x) {
7960
- const _10n = BigInt(10), _20n = BigInt(20), _40n = BigInt(40), _80n = BigInt(80);
7961
- const P = ed25519_CURVE_p;
7962
- const x2 = x * x % P;
7963
- const b2 = x2 * x % P;
7964
- const b4 = pow2(b2, _2n3, P) * b2 % P;
7965
- const b5 = pow2(b4, _1n5, P) * x % P;
7966
- const b10 = pow2(b5, _5n2, P) * b5 % P;
7967
- const b20 = pow2(b10, _10n, P) * b10 % P;
7968
- const b40 = pow2(b20, _20n, P) * b20 % P;
7969
- const b80 = pow2(b40, _40n, P) * b40 % P;
7970
- const b160 = pow2(b80, _80n, P) * b80 % P;
7971
- const b240 = pow2(b160, _80n, P) * b80 % P;
7972
- const b250 = pow2(b240, _10n, P) * b10 % P;
7973
- const pow_p_5_8 = pow2(b250, _2n3, P) * x % P;
7974
- return { pow_p_5_8, b2 };
7975
- }
7976
- function adjustScalarBytes(bytes) {
7977
- bytes[0] &= 248;
7978
- bytes[31] &= 127;
7979
- bytes[31] |= 64;
7980
- return bytes;
7981
- }
7982
- var ED25519_SQRT_M1 = /* @__PURE__ */ BigInt("19681161376707505956807079304988542015446066515923890162744021073123829784752");
7983
- function uvRatio(u, v) {
7984
- const P = ed25519_CURVE_p;
7985
- const v3 = mod(v * v * v, P);
7986
- const v7 = mod(v3 * v3 * v, P);
7987
- const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
7988
- let x = mod(u * v3 * pow, P);
7989
- const vx2 = mod(v * x * x, P);
7990
- const root1 = x;
7991
- const root2 = mod(x * ED25519_SQRT_M1, P);
7992
- const useRoot1 = vx2 === u;
7993
- const useRoot2 = vx2 === mod(-u, P);
7994
- const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P);
7995
- if (useRoot1)
7996
- x = root1;
7997
- if (useRoot2 || noRoot)
7998
- x = root2;
7999
- if (isNegativeLE(x, P))
8000
- x = mod(-x, P);
8001
- return { isValid: useRoot1 || useRoot2, value: x };
8197
+ return { host: discovered?.url ?? null, deferred: false };
8002
8198
  }
8003
- var Fp = /* @__PURE__ */ (() => Field(ed25519_CURVE.p, { isLE: true }))();
8004
- var Fn = /* @__PURE__ */ (() => Field(ed25519_CURVE.n, { isLE: true }))();
8005
- var ed25519Defaults = /* @__PURE__ */ (() => ({
8006
- ...ed25519_CURVE,
8007
- Fp,
8008
- hash: sha512,
8009
- adjustScalarBytes,
8010
- // dom2
8011
- // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
8012
- // Constant-time, u/√v
8013
- uvRatio
8014
- }))();
8015
- var ed25519 = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))();
8016
- var SQRT_M1 = ED25519_SQRT_M1;
8017
- var SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt("25063068953384623474111414158702152701244531502492656460079210482610430750235");
8018
- var INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt("54469307008909316920995813868745141605393597292927456921205312896311721017578");
8019
- var ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt("1159843021668779879193775521855586647937357759715417654439879720876111806838");
8020
- var D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt("40440834346308536858101042469323190826248399146238708352240133220865137265952");
8021
- var invertSqrt = (number) => uvRatio(_1n5, number);
8022
- var MAX_255B = /* @__PURE__ */ BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
8023
- var bytes255ToNumberLE = (bytes) => ed25519.Point.Fp.create(bytesToNumberLE(bytes) & MAX_255B);
8024
- function calcElligatorRistrettoMap(r0) {
8025
- const { d } = ed25519_CURVE;
8026
- const P = ed25519_CURVE_p;
8027
- const mod2 = (n) => Fp.create(n);
8028
- const r = mod2(SQRT_M1 * r0 * r0);
8029
- const Ns = mod2((r + _1n5) * ONE_MINUS_D_SQ);
8030
- let c = BigInt(-1);
8031
- const D = mod2((c - d * r) * mod2(r + d));
8032
- let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D);
8033
- let s_ = mod2(s * r0);
8034
- if (!isNegativeLE(s_, P))
8035
- s_ = mod2(-s_);
8036
- if (!Ns_D_is_sq)
8037
- s = s_;
8038
- if (!Ns_D_is_sq)
8039
- c = r;
8040
- const Nt = mod2(c * (r - _1n5) * D_MINUS_ONE_SQ - D);
8041
- const s2 = s * s;
8042
- const W0 = mod2((s + s) * D);
8043
- const W1 = mod2(Nt * SQRT_AD_MINUS_ONE);
8044
- const W2 = mod2(_1n5 - s2);
8045
- const W3 = mod2(_1n5 + s2);
8046
- return new ed25519.Point(mod2(W0 * W3), mod2(W2 * W1), mod2(W1 * W3), mod2(W0 * W2));
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;
8047
8206
  }
8048
- function ristretto255_map(bytes) {
8049
- abytes(bytes, 64);
8050
- const r1 = bytes255ToNumberLE(bytes.subarray(0, 32));
8051
- const R1 = calcElligatorRistrettoMap(r1);
8052
- const r2 = bytes255ToNumberLE(bytes.subarray(32, 64));
8053
- const R2 = calcElligatorRistrettoMap(r2);
8054
- return new _RistrettoPoint(R1.add(R2));
8207
+ function canonicalizeAddress2(address) {
8208
+ const trimmed = address.trim();
8209
+ return trimmed.startsWith("0x") ? `0x${trimmed.slice(2).toLowerCase()}` : trimmed.toLowerCase();
8055
8210
  }
8056
- var _RistrettoPoint = class __RistrettoPoint extends PrimeEdwardsPoint {
8057
- constructor(ep) {
8058
- super(ep);
8059
- }
8060
- static fromAffine(ap) {
8061
- return new __RistrettoPoint(ed25519.Point.fromAffine(ap));
8062
- }
8063
- assertSame(other) {
8064
- if (!(other instanceof __RistrettoPoint))
8065
- throw new Error("RistrettoPoint expected");
8066
- }
8067
- init(ep) {
8068
- return new __RistrettoPoint(ep);
8069
- }
8070
- /** @deprecated use `import { ristretto255_hasher } from '@noble/curves/ed25519.js';` */
8071
- static hashToCurve(hex3) {
8072
- return ristretto255_map(ensureBytes("ristrettoHash", hex3, 64));
8073
- }
8074
- static fromBytes(bytes) {
8075
- abytes(bytes, 32);
8076
- const { a, d } = ed25519_CURVE;
8077
- const P = ed25519_CURVE_p;
8078
- const mod2 = (n) => Fp.create(n);
8079
- const s = bytes255ToNumberLE(bytes);
8080
- if (!equalBytes(Fp.toBytes(s), bytes) || isNegativeLE(s, P))
8081
- throw new Error("invalid ristretto255 encoding 1");
8082
- const s2 = mod2(s * s);
8083
- const u1 = mod2(_1n5 + a * s2);
8084
- const u2 = mod2(_1n5 - a * s2);
8085
- const u1_2 = mod2(u1 * u1);
8086
- const u2_2 = mod2(u2 * u2);
8087
- const v = mod2(a * d * u1_2 - u2_2);
8088
- const { isValid: isValid3, value: I } = invertSqrt(mod2(v * u2_2));
8089
- const Dx = mod2(I * u2);
8090
- const Dy = mod2(I * Dx * v);
8091
- let x = mod2((s + s) * Dx);
8092
- if (isNegativeLE(x, P))
8093
- x = mod2(-x);
8094
- const y = mod2(u1 * Dy);
8095
- const t = mod2(x * y);
8096
- if (!isValid3 || isNegativeLE(t, P) || y === _0n5)
8097
- throw new Error("invalid ristretto255 encoding 2");
8098
- return new __RistrettoPoint(new ed25519.Point(x, y, _1n5, t));
8099
- }
8100
- /**
8101
- * Converts ristretto-encoded string to ristretto point.
8102
- * Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-decode).
8103
- * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
8104
- */
8105
- static fromHex(hex3) {
8106
- return __RistrettoPoint.fromBytes(ensureBytes("ristrettoHex", hex3, 32));
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);
8107
8216
  }
8108
- static msm(points, scalars) {
8109
- return pippenger(__RistrettoPoint, ed25519.Point.Fn, points, scalars);
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]);
8110
8221
  }
8111
- /**
8112
- * Encodes ristretto point to Uint8Array.
8113
- * Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-encode).
8114
- */
8115
- toBytes() {
8116
- let { X, Y, Z, T } = this.ep;
8117
- const P = ed25519_CURVE_p;
8118
- const mod2 = (n) => Fp.create(n);
8119
- const u1 = mod2(mod2(Z + Y) * mod2(Z - Y));
8120
- const u2 = mod2(X * Y);
8121
- const u2sq = mod2(u2 * u2);
8122
- const { value: invsqrt } = invertSqrt(mod2(u1 * u2sq));
8123
- const D1 = mod2(invsqrt * u1);
8124
- const D2 = mod2(invsqrt * u2);
8125
- const zInv = mod2(D1 * D2 * T);
8126
- let D;
8127
- if (isNegativeLE(T * zInv, P)) {
8128
- let _x = mod2(Y * SQRT_M1);
8129
- let _y = mod2(X * SQRT_M1);
8130
- X = _x;
8131
- Y = _y;
8132
- D = mod2(D1 * INVSQRT_A_MINUS_D);
8133
- } else {
8134
- D = D2;
8135
- }
8136
- if (isNegativeLE(X * zInv, P))
8137
- Y = mod2(-Y);
8138
- let s = mod2((Z - Y) * D);
8139
- if (isNegativeLE(s, P))
8140
- s = mod2(-s);
8141
- return Fp.toBytes(s);
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}".`);
8142
8268
  }
8143
- /**
8144
- * Compares two Ristretto points.
8145
- * Described in [RFC9496](https://www.rfc-editor.org/rfc/rfc9496#name-equals).
8146
- */
8147
- equals(other) {
8148
- this.assertSame(other);
8149
- const { X: X1, Y: Y1 } = this.ep;
8150
- const { X: X2, Y: Y2 } = other.ep;
8151
- const mod2 = (n) => Fp.create(n);
8152
- const one = mod2(X1 * Y2) === mod2(Y1 * X2);
8153
- const two = mod2(Y1 * Y2) === mod2(X1 * X2);
8154
- 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();
8155
8279
  }
8156
- is0() {
8157
- return this.equals(__RistrettoPoint.ZERO);
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
+ };
8158
8560
  }
8159
- };
8160
- _RistrettoPoint.BASE = /* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.BASE))();
8161
- _RistrettoPoint.ZERO = /* @__PURE__ */ (() => new _RistrettoPoint(ed25519.Point.ZERO))();
8162
- _RistrettoPoint.Fp = /* @__PURE__ */ (() => Fp)();
8163
- _RistrettoPoint.Fn = /* @__PURE__ */ (() => Fn)();
8561
+ });
8164
8562
 
8165
- // ../../node_modules/@noble/hashes/esm/blake3.js
8166
- init_md();
8167
- 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>.';
8168
8565
 
8169
- // ../../node_modules/@noble/hashes/esm/_blake.js
8170
- init_utils();
8171
- function G1s(a, b, c, d, x) {
8172
- a = a + b + x | 0;
8173
- d = rotr(d ^ a, 16);
8174
- c = c + d | 0;
8175
- b = rotr(b ^ c, 12);
8176
- return { a, b, c, d };
8177
- }
8178
- function G2s(a, b, c, d, x) {
8179
- a = a + b + x | 0;
8180
- d = rotr(d ^ a, 8);
8181
- c = c + d | 0;
8182
- b = rotr(b ^ c, 7);
8183
- return { a, b, c, d };
8184
- }
8566
+ // src/index.ts
8567
+ init_errors();
8568
+ import { readFileSync as readFileSync2 } from "fs";
8569
+ import { Command } from "commander";
8185
8570
 
8186
- // ../../node_modules/@noble/hashes/esm/blake2.js
8187
- init_utils();
8188
- var BLAKE2 = class extends Hash {
8189
- constructor(blockLen, outputLen) {
8190
- super();
8191
- this.finished = false;
8192
- this.destroyed = false;
8193
- this.length = 0;
8194
- this.pos = 0;
8195
- anumber(blockLen);
8196
- anumber(outputLen);
8197
- this.blockLen = blockLen;
8198
- this.outputLen = outputLen;
8199
- this.buffer = new Uint8Array(blockLen);
8200
- this.buffer32 = u32(this.buffer);
8201
- }
8202
- update(data) {
8203
- aexists(this);
8204
- data = toBytes(data);
8205
- abytes(data);
8206
- const { blockLen, buffer, buffer32 } = this;
8207
- const len = data.length;
8208
- const offset = data.byteOffset;
8209
- const buf = data.buffer;
8210
- for (let pos = 0; pos < len; ) {
8211
- if (this.pos === blockLen) {
8212
- swap32IfBE(buffer32);
8213
- this.compress(buffer32, 0, false);
8214
- swap32IfBE(buffer32);
8215
- this.pos = 0;
8216
- }
8217
- const take = Math.min(blockLen - this.pos, len - pos);
8218
- const dataOffset = offset + pos;
8219
- if (take === blockLen && !(dataOffset % 4) && pos + take < len) {
8220
- const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4));
8221
- swap32IfBE(data32);
8222
- for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) {
8223
- this.length += blockLen;
8224
- this.compress(data32, pos32, false);
8225
- }
8226
- swap32IfBE(data32);
8227
- continue;
8228
- }
8229
- buffer.set(data.subarray(pos, pos + take), this.pos);
8230
- this.pos += take;
8231
- this.length += take;
8232
- 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;
8233
8616
  }
8234
- return this;
8235
- }
8236
- digestInto(out) {
8237
- aexists(this);
8238
- aoutput(out, this);
8239
- const { pos, buffer32 } = this;
8240
- this.finished = true;
8241
- clean(this.buffer.subarray(pos));
8242
- swap32IfBE(buffer32);
8243
- this.compress(buffer32, 0, true);
8244
- swap32IfBE(buffer32);
8245
- const out32 = u32(out);
8246
- this.get().forEach((v, i) => out32[i] = swap8IfBE(v));
8247
- }
8248
- digest() {
8249
- const { buffer, outputLen } = this;
8250
- this.digestInto(buffer);
8251
- const res = buffer.slice(0, outputLen);
8252
- this.destroy();
8253
- return res;
8254
- }
8255
- _cloneInto(to) {
8256
- const { buffer, length: length4, finished, destroyed, outputLen, pos } = this;
8257
- to || (to = new this.constructor({ dkLen: outputLen }));
8258
- to.set(...this.get());
8259
- to.buffer.set(buffer);
8260
- to.destroyed = destroyed;
8261
- to.finished = finished;
8262
- to.length = length4;
8263
- to.pos = pos;
8264
- to.outputLen = outputLen;
8265
- return to;
8266
- }
8267
- clone() {
8268
- return this._cloneInto();
8269
- }
8270
- };
8271
- function compress(s, offset, msg, rounds, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) {
8272
- let j = 0;
8273
- for (let i = 0; i < rounds; i++) {
8274
- ({ a: v0, b: v4, c: v8, d: v12 } = G1s(v0, v4, v8, v12, msg[offset + s[j++]]));
8275
- ({ a: v0, b: v4, c: v8, d: v12 } = G2s(v0, v4, v8, v12, msg[offset + s[j++]]));
8276
- ({ a: v1, b: v5, c: v9, d: v13 } = G1s(v1, v5, v9, v13, msg[offset + s[j++]]));
8277
- ({ a: v1, b: v5, c: v9, d: v13 } = G2s(v1, v5, v9, v13, msg[offset + s[j++]]));
8278
- ({ a: v2, b: v6, c: v10, d: v14 } = G1s(v2, v6, v10, v14, msg[offset + s[j++]]));
8279
- ({ a: v2, b: v6, c: v10, d: v14 } = G2s(v2, v6, v10, v14, msg[offset + s[j++]]));
8280
- ({ a: v3, b: v7, c: v11, d: v15 } = G1s(v3, v7, v11, v15, msg[offset + s[j++]]));
8281
- ({ a: v3, b: v7, c: v11, d: v15 } = G2s(v3, v7, v11, v15, msg[offset + s[j++]]));
8282
- ({ a: v0, b: v5, c: v10, d: v15 } = G1s(v0, v5, v10, v15, msg[offset + s[j++]]));
8283
- ({ a: v0, b: v5, c: v10, d: v15 } = G2s(v0, v5, v10, v15, msg[offset + s[j++]]));
8284
- ({ a: v1, b: v6, c: v11, d: v12 } = G1s(v1, v6, v11, v12, msg[offset + s[j++]]));
8285
- ({ a: v1, b: v6, c: v11, d: v12 } = G2s(v1, v6, v11, v12, msg[offset + s[j++]]));
8286
- ({ a: v2, b: v7, c: v8, d: v13 } = G1s(v2, v7, v8, v13, msg[offset + s[j++]]));
8287
- ({ a: v2, b: v7, c: v8, d: v13 } = G2s(v2, v7, v8, v13, msg[offset + s[j++]]));
8288
- ({ a: v3, b: v4, c: v9, d: v14 } = G1s(v3, v4, v9, v14, msg[offset + s[j++]]));
8289
- ({ a: v3, b: v4, c: v9, d: v14 } = G2s(v3, v4, v9, v14, msg[offset + s[j++]]));
8290
8617
  }
8291
- return { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 };
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)];
8292
8624
  }
8293
8625
 
8294
- // ../../node_modules/@noble/hashes/esm/blake3.js
8295
- init_utils();
8296
- var B3_Flags = {
8297
- CHUNK_START: 1,
8298
- CHUNK_END: 2,
8299
- PARENT: 4,
8300
- ROOT: 8,
8301
- KEYED_HASH: 16,
8302
- DERIVE_KEY_CONTEXT: 32,
8303
- DERIVE_KEY_MATERIAL: 64
8304
- };
8305
- var B3_IV = SHA256_IV.slice();
8306
- var B3_SIGMA = /* @__PURE__ */ (() => {
8307
- const Id = Array.from({ length: 16 }, (_, i) => i);
8308
- const permute = (arr) => [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8].map((i) => arr[i]);
8309
- const res = [];
8310
- for (let i = 0, v = Id; i < 7; i++, v = permute(v))
8311
- res.push(...v);
8312
- return Uint8Array.from(res);
8313
- })();
8314
- var BLAKE3 = class _BLAKE3 extends BLAKE2 {
8315
- constructor(opts = {}, flags = 0) {
8316
- super(64, opts.dkLen === void 0 ? 32 : opts.dkLen);
8317
- this.chunkPos = 0;
8318
- this.chunksDone = 0;
8319
- this.flags = 0 | 0;
8320
- this.stack = [];
8321
- this.posOut = 0;
8322
- this.bufferOut32 = new Uint32Array(16);
8323
- this.chunkOut = 0;
8324
- this.enableXOF = true;
8325
- const { key, context } = opts;
8326
- const hasContext = context !== void 0;
8327
- if (key !== void 0) {
8328
- if (hasContext)
8329
- throw new Error('Only "key" or "context" can be specified at same time');
8330
- const k = toBytes(key).slice();
8331
- abytes(k, 32);
8332
- this.IV = u32(k);
8333
- swap32IfBE(this.IV);
8334
- this.flags = flags | B3_Flags.KEYED_HASH;
8335
- } else if (hasContext) {
8336
- const ctx = toBytes(context);
8337
- const contextKey = new _BLAKE3({ dkLen: 32 }, B3_Flags.DERIVE_KEY_CONTEXT).update(ctx).digest();
8338
- this.IV = u32(contextKey);
8339
- swap32IfBE(this.IV);
8340
- this.flags = flags | B3_Flags.DERIVE_KEY_MATERIAL;
8341
- } else {
8342
- this.IV = B3_IV.slice();
8343
- this.flags = flags;
8344
- }
8345
- this.state = this.IV.slice();
8346
- this.bufferOut = u8(this.bufferOut32);
8347
- }
8348
- // Unused
8349
- get() {
8350
- 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;
8351
8638
  }
8352
- set() {
8353
- }
8354
- b2Compress(counter, flags, buf, bufPos = 0) {
8355
- const { state: s, pos } = this;
8356
- const { h, l } = fromBig(BigInt(counter), true);
8357
- 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);
8358
- s[0] = v0 ^ v8;
8359
- s[1] = v1 ^ v9;
8360
- s[2] = v2 ^ v10;
8361
- s[3] = v3 ^ v11;
8362
- s[4] = v4 ^ v12;
8363
- s[5] = v5 ^ v13;
8364
- s[6] = v6 ^ v14;
8365
- s[7] = v7 ^ v15;
8366
- }
8367
- compress(buf, bufPos = 0, isLast = false) {
8368
- let flags = this.flags;
8369
- if (!this.chunkPos)
8370
- flags |= B3_Flags.CHUNK_START;
8371
- if (this.chunkPos === 15 || isLast)
8372
- flags |= B3_Flags.CHUNK_END;
8373
- if (!isLast)
8374
- this.pos = this.blockLen;
8375
- this.b2Compress(this.chunksDone, flags, buf, bufPos);
8376
- this.chunkPos += 1;
8377
- if (this.chunkPos === 16 || isLast) {
8378
- let chunk = this.state;
8379
- this.state = this.IV.slice();
8380
- for (let last, chunks = this.chunksDone + 1; isLast || !(chunks & 1); chunks >>= 1) {
8381
- if (!(last = this.stack.pop()))
8382
- break;
8383
- this.buffer32.set(last, 0);
8384
- this.buffer32.set(chunk, 8);
8385
- this.pos = this.blockLen;
8386
- this.b2Compress(0, this.flags | B3_Flags.PARENT, this.buffer32, 0);
8387
- chunk = this.state;
8388
- this.state = this.IV.slice();
8389
- }
8390
- this.chunksDone++;
8391
- this.chunkPos = 0;
8392
- this.stack.push(chunk);
8393
- }
8394
- this.pos = 0;
8395
- }
8396
- _cloneInto(to) {
8397
- to = super._cloneInto(to);
8398
- const { IV, flags, state: state2, chunkPos, posOut, chunkOut, stack, chunksDone } = this;
8399
- to.state.set(state2.slice());
8400
- to.stack = stack.map((i) => Uint32Array.from(i));
8401
- to.IV.set(IV);
8402
- to.flags = flags;
8403
- to.chunkPos = chunkPos;
8404
- to.chunksDone = chunksDone;
8405
- to.posOut = posOut;
8406
- to.chunkOut = chunkOut;
8407
- to.enableXOF = this.enableXOF;
8408
- to.bufferOut32.set(this.bufferOut32);
8409
- return to;
8410
- }
8411
- destroy() {
8412
- this.destroyed = true;
8413
- clean(this.state, this.buffer32, this.IV, this.bufferOut32);
8414
- clean(...this.stack);
8415
- }
8416
- // Same as b2Compress, but doesn't modify state and returns 16 u32 array (instead of 8)
8417
- b2CompressOut() {
8418
- const { state: s, pos, flags, buffer32, bufferOut32: out32 } = this;
8419
- const { h, l } = fromBig(BigInt(this.chunkOut++));
8420
- swap32IfBE(buffer32);
8421
- 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);
8422
- out32[0] = v0 ^ v8;
8423
- out32[1] = v1 ^ v9;
8424
- out32[2] = v2 ^ v10;
8425
- out32[3] = v3 ^ v11;
8426
- out32[4] = v4 ^ v12;
8427
- out32[5] = v5 ^ v13;
8428
- out32[6] = v6 ^ v14;
8429
- out32[7] = v7 ^ v15;
8430
- out32[8] = s[0] ^ v8;
8431
- out32[9] = s[1] ^ v9;
8432
- out32[10] = s[2] ^ v10;
8433
- out32[11] = s[3] ^ v11;
8434
- out32[12] = s[4] ^ v12;
8435
- out32[13] = s[5] ^ v13;
8436
- out32[14] = s[6] ^ v14;
8437
- out32[15] = s[7] ^ v15;
8438
- swap32IfBE(buffer32);
8439
- swap32IfBE(out32);
8440
- this.posOut = 0;
8441
- }
8442
- finish() {
8443
- if (this.finished)
8444
- return;
8445
- this.finished = true;
8446
- clean(this.buffer.subarray(this.pos));
8447
- let flags = this.flags | B3_Flags.ROOT;
8448
- if (this.stack.length) {
8449
- flags |= B3_Flags.PARENT;
8450
- swap32IfBE(this.buffer32);
8451
- this.compress(this.buffer32, 0, true);
8452
- swap32IfBE(this.buffer32);
8453
- this.chunksDone = 0;
8454
- this.pos = this.blockLen;
8455
- } else {
8456
- flags |= (!this.chunkPos ? B3_Flags.CHUNK_START : 0) | B3_Flags.CHUNK_END;
8457
- }
8458
- this.flags = flags;
8459
- this.b2CompressOut();
8460
- }
8461
- writeInto(out) {
8462
- aexists(this, false);
8463
- abytes(out);
8464
- this.finish();
8465
- const { blockLen, bufferOut } = this;
8466
- for (let pos = 0, len = out.length; pos < len; ) {
8467
- if (this.posOut >= blockLen)
8468
- this.b2CompressOut();
8469
- const take = Math.min(blockLen - this.posOut, len - pos);
8470
- out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
8471
- this.posOut += take;
8472
- pos += take;
8473
- }
8474
- return out;
8475
- }
8476
- xofInto(out) {
8477
- if (!this.enableXOF)
8478
- throw new Error("XOF is not possible after digest call");
8479
- return this.writeInto(out);
8480
- }
8481
- xof(bytes) {
8482
- anumber(bytes);
8483
- return this.xofInto(new Uint8Array(bytes));
8484
- }
8485
- digestInto(out) {
8486
- aoutput(out, this);
8487
- if (this.finished)
8488
- throw new Error("digest() was already called");
8489
- this.enableXOF = false;
8490
- this.writeInto(out);
8491
- this.destroy();
8492
- return out;
8493
- }
8494
- digest() {
8495
- 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}`;
8496
8648
  }
8497
- };
8498
- var blake3 = /* @__PURE__ */ createXOFer((opts) => new BLAKE3(opts));
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();
8499
8671
 
8500
8672
  // ../share-sdk/dist/index.js
8673
+ init_sha2();
8674
+ init_ed25519();
8675
+ init_blake3();
8676
+ init_ed25519();
8501
8677
  init_sha256();
8502
8678
  init_sha256();
8503
8679
  var __defProp2 = Object.defineProperty;