@tinycloud/cli 1.2.2-beta.1 → 1.2.2-beta.3
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 +6 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +100 -69
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +2 -2
package/dist/legacy-entry.js
CHANGED
|
@@ -16288,7 +16288,7 @@ function eddsa(Point, cHash, eddsaOpts = {}) {
|
|
|
16288
16288
|
});
|
|
16289
16289
|
const { prehash } = eddsaOpts;
|
|
16290
16290
|
const { BASE, Fp: Fp2, Fn: Fn2 } = Point;
|
|
16291
|
-
const
|
|
16291
|
+
const randomBytes9 = eddsaOpts.randomBytes || randomBytes;
|
|
16292
16292
|
const adjustScalarBytes2 = eddsaOpts.adjustScalarBytes || ((bytes) => bytes);
|
|
16293
16293
|
const domain = eddsaOpts.domain || ((data, ctx, phflag) => {
|
|
16294
16294
|
_abool2(phflag, "phflag");
|
|
@@ -16370,7 +16370,7 @@ function eddsa(Point, cHash, eddsaOpts = {}) {
|
|
|
16370
16370
|
signature: 2 * _size,
|
|
16371
16371
|
seed: _size
|
|
16372
16372
|
};
|
|
16373
|
-
function randomSecretKey(seed =
|
|
16373
|
+
function randomSecretKey(seed = randomBytes9(lengths.seed)) {
|
|
16374
16374
|
return _abytes2(seed, lengths.seed, "seed");
|
|
16375
16375
|
}
|
|
16376
16376
|
function keygen(seed) {
|
|
@@ -17797,6 +17797,7 @@ __export(sdk_exports, {
|
|
|
17797
17797
|
storedSessionVerifiesLocally: () => storedSessionVerifiesLocally
|
|
17798
17798
|
});
|
|
17799
17799
|
import { TinyCloudNode, signedCompactUcanExpiry } from "@tinycloud/node-sdk";
|
|
17800
|
+
import { ownerSessionLacksProof } from "@tinycloud/operations/profile";
|
|
17800
17801
|
function jwkHasPrivateParameter(jwk) {
|
|
17801
17802
|
if (!jwk || typeof jwk !== "object") return false;
|
|
17802
17803
|
const d = jwk.d;
|
|
@@ -17828,11 +17829,15 @@ function signedLifetimePassed(delegation) {
|
|
|
17828
17829
|
return expiry !== void 0 && expiry.getTime() <= Date.now();
|
|
17829
17830
|
}
|
|
17830
17831
|
async function restoreProfileSession(node, profileName2, profile, sessionData) {
|
|
17832
|
+
const posture = profile === null ? void 0 : resolveProfilePosture(profile);
|
|
17833
|
+
if (ownerSessionLacksProof(sessionData, profile)) {
|
|
17834
|
+
throw sessionExpiredError(profileName2, posture);
|
|
17835
|
+
}
|
|
17831
17836
|
try {
|
|
17832
17837
|
await node.restoreSession(sessionData);
|
|
17833
17838
|
} catch (error) {
|
|
17834
17839
|
if (typeof error === "object" && error !== null && "code" in error && error.code === "AUTH_EXPIRED") {
|
|
17835
|
-
throw sessionExpiredError(profileName2,
|
|
17840
|
+
throw sessionExpiredError(profileName2, posture);
|
|
17836
17841
|
}
|
|
17837
17842
|
throw error;
|
|
17838
17843
|
}
|
|
@@ -20277,6 +20282,7 @@ init_types();
|
|
|
20277
20282
|
init_constants();
|
|
20278
20283
|
init_errors();
|
|
20279
20284
|
import { createServer } from "http";
|
|
20285
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
20280
20286
|
import { createInterface } from "readline";
|
|
20281
20287
|
var PRIVATE_JWK_FIELDS = /* @__PURE__ */ new Set([
|
|
20282
20288
|
"d",
|
|
@@ -20288,6 +20294,7 @@ var PRIVATE_JWK_FIELDS = /* @__PURE__ */ new Set([
|
|
|
20288
20294
|
"oth",
|
|
20289
20295
|
"k"
|
|
20290
20296
|
]);
|
|
20297
|
+
var MAX_CALLBACK_BODY_BYTES = 1024 * 1024;
|
|
20291
20298
|
function publicJwkForDelegation(jwk) {
|
|
20292
20299
|
const publicJwk = {};
|
|
20293
20300
|
for (const [key, value] of Object.entries(jwk)) {
|
|
@@ -20438,6 +20445,7 @@ async function callbackFlow(did, options = {}) {
|
|
|
20438
20445
|
settled = true;
|
|
20439
20446
|
clearTimeout(timeout);
|
|
20440
20447
|
server.close();
|
|
20448
|
+
server.closeAllConnections();
|
|
20441
20449
|
if (rl) {
|
|
20442
20450
|
rl.close();
|
|
20443
20451
|
}
|
|
@@ -20447,37 +20455,50 @@ async function callbackFlow(did, options = {}) {
|
|
|
20447
20455
|
reject(result.error);
|
|
20448
20456
|
}
|
|
20449
20457
|
}
|
|
20450
|
-
const
|
|
20451
|
-
|
|
20452
|
-
|
|
20458
|
+
const callbackPath = `/callback/${randomBytes3(16).toString("base64url")}`;
|
|
20459
|
+
const openKeyOrigin = new URL(options.openkeyHost ?? DEFAULT_OPENKEY_HOST).origin;
|
|
20460
|
+
const cors = { "Access-Control-Allow-Origin": openKeyOrigin, "Vary": "Origin" };
|
|
20461
|
+
const server = createServer({ connectionsCheckingInterval: 1e3 }, (req, res) => {
|
|
20462
|
+
if (req.headers.origin !== openKeyOrigin) {
|
|
20463
|
+
res.writeHead(403);
|
|
20464
|
+
res.end();
|
|
20465
|
+
return;
|
|
20466
|
+
}
|
|
20467
|
+
if (req.method === "POST" && req.url === callbackPath) {
|
|
20468
|
+
const chunks = [];
|
|
20469
|
+
let size = 0;
|
|
20453
20470
|
req.on("data", (chunk) => {
|
|
20454
|
-
|
|
20471
|
+
size += chunk.length;
|
|
20472
|
+
if (size > MAX_CALLBACK_BODY_BYTES) {
|
|
20473
|
+
res.writeHead(413, cors);
|
|
20474
|
+
res.end();
|
|
20475
|
+
req.destroy();
|
|
20476
|
+
return;
|
|
20477
|
+
}
|
|
20478
|
+
chunks.push(chunk);
|
|
20455
20479
|
});
|
|
20456
20480
|
req.on("end", () => {
|
|
20481
|
+
let data;
|
|
20457
20482
|
try {
|
|
20458
|
-
|
|
20459
|
-
|
|
20460
|
-
|
|
20461
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
20462
|
-
res.end(JSON.stringify({ error: invalid2 }));
|
|
20463
|
-
settle({ error: new Error(`Invalid delegation payload: ${invalid2}`) });
|
|
20464
|
-
return;
|
|
20465
|
-
}
|
|
20466
|
-
res.writeHead(200, {
|
|
20467
|
-
"Content-Type": "application/json",
|
|
20468
|
-
"Access-Control-Allow-Origin": "*"
|
|
20469
|
-
});
|
|
20470
|
-
res.end(JSON.stringify({ success: true }));
|
|
20471
|
-
settle({ data });
|
|
20472
|
-
} catch (err2) {
|
|
20473
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
20483
|
+
data = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
20484
|
+
} catch {
|
|
20485
|
+
res.writeHead(400, { ...cors, "Content-Type": "application/json" });
|
|
20474
20486
|
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
20475
|
-
|
|
20487
|
+
return;
|
|
20476
20488
|
}
|
|
20489
|
+
const invalid2 = validateDelegationCallbackPayload(data);
|
|
20490
|
+
if (invalid2) {
|
|
20491
|
+
res.writeHead(400, { ...cors, "Content-Type": "application/json" });
|
|
20492
|
+
res.end(JSON.stringify({ error: invalid2 }));
|
|
20493
|
+
return;
|
|
20494
|
+
}
|
|
20495
|
+
res.writeHead(200, { ...cors, "Content-Type": "application/json" });
|
|
20496
|
+
res.end(JSON.stringify({ success: true }));
|
|
20497
|
+
settle({ data });
|
|
20477
20498
|
});
|
|
20478
|
-
} else if (req.method === "OPTIONS") {
|
|
20499
|
+
} else if (req.method === "OPTIONS" && req.url === callbackPath) {
|
|
20479
20500
|
res.writeHead(204, {
|
|
20480
|
-
|
|
20501
|
+
...cors,
|
|
20481
20502
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
20482
20503
|
"Access-Control-Allow-Headers": "Content-Type"
|
|
20483
20504
|
});
|
|
@@ -20487,6 +20508,8 @@ async function callbackFlow(did, options = {}) {
|
|
|
20487
20508
|
res.end();
|
|
20488
20509
|
}
|
|
20489
20510
|
});
|
|
20511
|
+
server.headersTimeout = 1e4;
|
|
20512
|
+
server.requestTimeout = 1e4;
|
|
20490
20513
|
server.listen(0, "127.0.0.1", async () => {
|
|
20491
20514
|
const addr = server.address();
|
|
20492
20515
|
if (!addr || typeof addr === "string") {
|
|
@@ -20494,7 +20517,7 @@ async function callbackFlow(did, options = {}) {
|
|
|
20494
20517
|
return;
|
|
20495
20518
|
}
|
|
20496
20519
|
const port = addr.port;
|
|
20497
|
-
const callbackUrl = `http://127.0.0.1:${port}
|
|
20520
|
+
const callbackUrl = `http://127.0.0.1:${port}${callbackPath}`;
|
|
20498
20521
|
const authUrl = buildAuthUrl(did, { ...options, callback: callbackUrl });
|
|
20499
20522
|
const openBrowser = shouldOpenBrowser(options);
|
|
20500
20523
|
const hasTerminal = Boolean(process.stdin.isTTY || process.stderr.isTTY);
|
|
@@ -20584,14 +20607,14 @@ import {
|
|
|
20584
20607
|
createECDH,
|
|
20585
20608
|
createHash,
|
|
20586
20609
|
createHmac,
|
|
20587
|
-
randomBytes as
|
|
20610
|
+
randomBytes as randomBytes5
|
|
20588
20611
|
} from "crypto";
|
|
20589
20612
|
|
|
20590
20613
|
// src/auth/local-key.ts
|
|
20591
20614
|
init_replication_config();
|
|
20592
20615
|
import { TCWSessionManager, importKey, initPanicHook } from "@tinycloud/node-sdk-wasm";
|
|
20593
20616
|
import { PrivateKeySigner } from "@tinycloud/node-sdk";
|
|
20594
|
-
import { randomBytes as
|
|
20617
|
+
import { randomBytes as randomBytes4 } from "crypto";
|
|
20595
20618
|
var wasmInitialized = false;
|
|
20596
20619
|
function ensureWasm() {
|
|
20597
20620
|
if (!wasmInitialized) {
|
|
@@ -20616,7 +20639,7 @@ function keyToDID(jwk) {
|
|
|
20616
20639
|
return mgr.getDID(keyId);
|
|
20617
20640
|
}
|
|
20618
20641
|
function generateEthereumPrivateKey() {
|
|
20619
|
-
const keyBytes =
|
|
20642
|
+
const keyBytes = randomBytes4(32);
|
|
20620
20643
|
return "0x" + keyBytes.toString("hex");
|
|
20621
20644
|
}
|
|
20622
20645
|
async function deriveAddress(privateKey) {
|
|
@@ -20670,7 +20693,7 @@ async function localKeySignIn(options) {
|
|
|
20670
20693
|
init_errors();
|
|
20671
20694
|
init_constants();
|
|
20672
20695
|
import { NodeWasmBindings, signedCompactUcanExpiry as signedCompactUcanExpiry2 } from "@tinycloud/node-sdk";
|
|
20673
|
-
import { isLocalOwnerProfile as isLocalOwnerProfile2 } from "@tinycloud/operations/profile";
|
|
20696
|
+
import { isLocalOwnerProfile as isLocalOwnerProfile2, ownerSessionLacksProof as ownerSessionLacksProof2 } from "@tinycloud/operations/profile";
|
|
20674
20697
|
|
|
20675
20698
|
// src/lib/duration.ts
|
|
20676
20699
|
function parseDuration(input) {
|
|
@@ -20772,8 +20795,9 @@ function sessionExpiresAt(session) {
|
|
|
20772
20795
|
if (typeof value === "string") return new Date(value).toISOString();
|
|
20773
20796
|
return null;
|
|
20774
20797
|
}
|
|
20775
|
-
function storedSessionState(session) {
|
|
20798
|
+
function storedSessionState(session, profile) {
|
|
20776
20799
|
if (session === null) return { state: "missing", expiresAt: null };
|
|
20800
|
+
if (ownerSessionLacksProof2(session, profile)) return { state: "unverified", expiresAt: null };
|
|
20777
20801
|
const siweExpiry = typeof session.siwe === "string" ? session.siwe.match(/^Expiration Time:\s*(.+)$/m)?.[1] : void 0;
|
|
20778
20802
|
const expiresAt = siweExpiry !== void 0 && Number.isFinite(Date.parse(siweExpiry)) ? new Date(siweExpiry).toISOString() : sessionExpiresAt(session);
|
|
20779
20803
|
if (expiresAt === null) return { state: "unknown-expiry", expiresAt };
|
|
@@ -21134,6 +21158,11 @@ function warnIfNotPrimaryKey(ownerDid, primary) {
|
|
|
21134
21158
|
if (primary !== false || ownerDid === void 0) return;
|
|
21135
21159
|
process.stderr.write(nonPrimaryKeyWarning(ownerDid));
|
|
21136
21160
|
}
|
|
21161
|
+
function announceFirstOwner(profileName2, expectedOwner, ownerDid) {
|
|
21162
|
+
if (expectedOwner !== void 0 || ownerDid === void 0) return;
|
|
21163
|
+
process.stderr.write(`Profile "${profileName2}" now belongs to ${ownerDid}. If that isn't your OpenKey account, stop using this profile and create a new one with tc init.
|
|
21164
|
+
`);
|
|
21165
|
+
}
|
|
21137
21166
|
function ownerLoginPermissions(owner) {
|
|
21138
21167
|
const space = ownerSpaceId("default", owner);
|
|
21139
21168
|
return [
|
|
@@ -21379,8 +21408,8 @@ async function acquireDeviceDelegation(input) {
|
|
|
21379
21408
|
const nodeOrigin = canonicalOrigin(input.nodeOrigin, "TinyCloud node origin");
|
|
21380
21409
|
const shareOrigin = canonicalOrigin(input.shareOrigin, "Share origin");
|
|
21381
21410
|
const fetchFn = input.fetchFn ?? globalThis.fetch;
|
|
21382
|
-
const deviceSecret =
|
|
21383
|
-
const codeVerifier =
|
|
21411
|
+
const deviceSecret = randomBytes5(32).toString("base64url");
|
|
21412
|
+
const codeVerifier = randomBytes5(32).toString("base64url");
|
|
21384
21413
|
const relayKey = createECDH("prime256v1");
|
|
21385
21414
|
relayKey.generateKeys();
|
|
21386
21415
|
const relayPublicJwk = relayPublicJwkOf(relayKey);
|
|
@@ -21495,15 +21524,6 @@ async function acquireDeviceDelegation(input) {
|
|
|
21495
21524
|
}
|
|
21496
21525
|
throw new CLIError("DEVICE_AUTH_EXPIRED", "OpenKey device authorization expired before approval. Run the command again.", ExitCode.AUTH_REQUIRED);
|
|
21497
21526
|
}
|
|
21498
|
-
function mergePrivateJwkIntoSession(session, key) {
|
|
21499
|
-
const sessionJwk = session.jwk;
|
|
21500
|
-
if (!sessionJwk || typeof sessionJwk !== "object") return session;
|
|
21501
|
-
const sessionJwkRecord = sessionJwk;
|
|
21502
|
-
if (typeof sessionJwkRecord.d === "string" && sessionJwkRecord.d.length > 0) return session;
|
|
21503
|
-
const privateParameter = key.d;
|
|
21504
|
-
if (typeof privateParameter !== "string" || privateParameter.length === 0) return session;
|
|
21505
|
-
return { ...session, jwk: { ...sessionJwkRecord, d: privateParameter } };
|
|
21506
|
-
}
|
|
21507
21527
|
async function loginWithDeviceAuthorization(input) {
|
|
21508
21528
|
const snapshot = await readProfileSnapshot(input.profileName);
|
|
21509
21529
|
const existing = snapshot.profile;
|
|
@@ -21548,6 +21568,7 @@ async function loginWithDeviceAuthorization(input) {
|
|
|
21548
21568
|
approved: { scope: result.session.permissions, ownerDid: result.ownerDid, replaceSession: input.replaceSession === true }
|
|
21549
21569
|
});
|
|
21550
21570
|
warnIfNotPrimaryKey(result.ownerDid, result.primary);
|
|
21571
|
+
announceFirstOwner(input.profileName, expectedOwner, result.ownerDid);
|
|
21551
21572
|
return { profile, result };
|
|
21552
21573
|
}
|
|
21553
21574
|
|
|
@@ -22254,7 +22275,7 @@ function registerAuthCommand(program, options) {
|
|
|
22254
22275
|
}
|
|
22255
22276
|
const posture = profile ? resolveProfilePosture(profile) : null;
|
|
22256
22277
|
const operatorType = profile ? resolveProfileOperatorType(profile) : null;
|
|
22257
|
-
const { state: sessionState, expiresAt } = storedSessionState(session);
|
|
22278
|
+
const { state: sessionState, expiresAt } = storedSessionState(session, profile);
|
|
22258
22279
|
const authenticated = sessionStateIsUsable(sessionState);
|
|
22259
22280
|
if (shouldOutputJson()) {
|
|
22260
22281
|
outputJson({
|
|
@@ -22289,7 +22310,7 @@ function registerAuthCommand(program, options) {
|
|
|
22289
22310
|
process.stdout.write(formatField("Address", profile?.address ?? null) + "\n");
|
|
22290
22311
|
process.stdout.write(formatField("Space ID", profile?.spaceId ?? null) + "\n");
|
|
22291
22312
|
process.stdout.write(formatField("Has Key", hasKey !== null) + "\n");
|
|
22292
|
-
if (sessionState === "expired") {
|
|
22313
|
+
if (sessionState === "expired" || sessionState === "unverified") {
|
|
22293
22314
|
process.stdout.write(`
|
|
22294
22315
|
${signInAgainHint(ctx.profile, posture ?? void 0)}
|
|
22295
22316
|
`);
|
|
@@ -22741,9 +22762,9 @@ ${signInAgainHint(ctx.profile, posture ?? void 0)}
|
|
|
22741
22762
|
const ctx = await ProfileManager.resolveContext(globalOpts, { storedSession: "unused" });
|
|
22742
22763
|
const profile = await ProfileManager.getProfile(ctx.profile);
|
|
22743
22764
|
const session = await ProfileManager.getSession(ctx.profile);
|
|
22744
|
-
const { state: sessionState, expiresAt } = storedSessionState(session);
|
|
22745
|
-
const authenticated = sessionStateIsUsable(sessionState);
|
|
22746
22765
|
const posture = resolveProfilePosture(profile);
|
|
22766
|
+
const { state: sessionState, expiresAt } = storedSessionState(session, profile);
|
|
22767
|
+
const authenticated = sessionStateIsUsable(sessionState);
|
|
22747
22768
|
const operatorType = resolveProfileOperatorType(profile);
|
|
22748
22769
|
if (shouldOutputJson()) {
|
|
22749
22770
|
outputJson({
|
|
@@ -22790,6 +22811,8 @@ function describeSession(state2, expiresAt) {
|
|
|
22790
22811
|
return `active until ${expiresAt}`;
|
|
22791
22812
|
case "unknown-expiry":
|
|
22792
22813
|
return "active (no recorded expiry)";
|
|
22814
|
+
case "unverified":
|
|
22815
|
+
return "not usable (no signed OpenKey proof)";
|
|
22793
22816
|
}
|
|
22794
22817
|
}
|
|
22795
22818
|
async function emitPermissionRequestArtifact(artifact, emitOption) {
|
|
@@ -23437,10 +23460,10 @@ async function handleOpenKeyAuth(profileName2, host, options = {}) {
|
|
|
23437
23460
|
profile: profileName2,
|
|
23438
23461
|
did: profile.did,
|
|
23439
23462
|
spaceId: delegationData.spaceId,
|
|
23463
|
+
ownerDid: profile.ownerDid ?? null,
|
|
23440
23464
|
authMethod: "openkey",
|
|
23441
23465
|
...options.permissions ? {
|
|
23442
23466
|
scoped: true,
|
|
23443
|
-
ownerDid: profile.ownerDid,
|
|
23444
23467
|
host,
|
|
23445
23468
|
permissions: delegationData.permissions,
|
|
23446
23469
|
declined,
|
|
@@ -23534,15 +23557,13 @@ async function refreshOpenKeySession(profileName2, host, options = {}) {
|
|
|
23534
23557
|
verifiedOwner = sanitizedSession.ownerDid;
|
|
23535
23558
|
declined = declinedPermissions(permissions, sanitizedSession.permissions, verifiedOwner);
|
|
23536
23559
|
} else {
|
|
23537
|
-
const
|
|
23538
|
-
const
|
|
23539
|
-
if (
|
|
23540
|
-
|
|
23541
|
-
verifiedOwner = signed.ownerDid;
|
|
23542
|
-
sanitizedSession = withVerifiedAuthority(merged, signed);
|
|
23543
|
-
} else {
|
|
23544
|
-
sanitizedSession = Object.fromEntries(Object.entries(withoutTrustFields(merged)).filter(([name]) => name !== "siwe" && name !== "signature"));
|
|
23560
|
+
const signed = verifySignedSession(delegationData, key, sessionDid, { expectedOwner, expiry });
|
|
23561
|
+
const spaceId = String(delegationData.spaceId);
|
|
23562
|
+
if (normalizePkhIdentifier(ownerSpaceId(spaceId.split(":").at(-1) ?? "", signed.ownerDid)) !== normalizePkhIdentifier(spaceId)) {
|
|
23563
|
+
throw new CLIError("OPENKEY_SCOPE_MISMATCH", "The approved session is for a space the signing account doesn't own. No session was saved.", ExitCode.PERMISSION_DENIED);
|
|
23545
23564
|
}
|
|
23565
|
+
verifiedOwner = signed.ownerDid;
|
|
23566
|
+
sanitizedSession = withVerifiedAuthority({ ...delegationData, jwk: key }, signed);
|
|
23546
23567
|
}
|
|
23547
23568
|
const ownerKeyPrimary = verifiedOwner === void 0 ? void 0 : openKeyPrimaryFlag(delegationData);
|
|
23548
23569
|
const updatedProfile = withOwnerKeyPrimary({
|
|
@@ -23562,6 +23583,7 @@ async function refreshOpenKeySession(profileName2, host, options = {}) {
|
|
|
23562
23583
|
...permissions && verifiedOwner ? { approved: { scope: sanitizedSession.permissions, ownerDid: verifiedOwner, replaceSession: options.replaceSession === true } } : {}
|
|
23563
23584
|
});
|
|
23564
23585
|
warnIfNotPrimaryKey(verifiedOwner, ownerKeyPrimary);
|
|
23586
|
+
announceFirstOwner(profileName2, expectedOwner, verifiedOwner);
|
|
23565
23587
|
return { profile: updatedProfile, delegationData: sanitizedSession, declined, legacyNested };
|
|
23566
23588
|
}
|
|
23567
23589
|
|
|
@@ -23731,7 +23753,7 @@ function registerContextCommand(program) {
|
|
|
23731
23753
|
host: ctx.host,
|
|
23732
23754
|
spaceId,
|
|
23733
23755
|
session: {
|
|
23734
|
-
...storedSessionState(session),
|
|
23756
|
+
...storedSessionState(session, profile),
|
|
23735
23757
|
evidence: "local-metadata"
|
|
23736
23758
|
},
|
|
23737
23759
|
access: "not-tested"
|
|
@@ -23861,6 +23883,8 @@ init_constants();
|
|
|
23861
23883
|
init_formatter();
|
|
23862
23884
|
init_theme();
|
|
23863
23885
|
init_errors();
|
|
23886
|
+
init_session_expired();
|
|
23887
|
+
init_types();
|
|
23864
23888
|
function registerDoctorCommand(program) {
|
|
23865
23889
|
program.command("doctor").description("Run diagnostic checks").action(async (_options, cmd) => {
|
|
23866
23890
|
try {
|
|
@@ -23906,8 +23930,14 @@ function registerDoctorCommand(program) {
|
|
|
23906
23930
|
if (profileOk && profileName2) {
|
|
23907
23931
|
try {
|
|
23908
23932
|
const session = await ProfileManager.getSession(profileName2);
|
|
23909
|
-
|
|
23910
|
-
|
|
23933
|
+
const { state: state2, expiresAt } = storedSessionState(session);
|
|
23934
|
+
sessionOk = sessionStateIsUsable(state2);
|
|
23935
|
+
if (state2 === "expired") {
|
|
23936
|
+
const posture = resolveProfilePosture(await ProfileManager.getProfile(profileName2));
|
|
23937
|
+
sessionDetail = `expired ${expiresAt} \u2014 ${signInAgainHint(profileName2, posture)}`;
|
|
23938
|
+
} else {
|
|
23939
|
+
sessionDetail = sessionOk ? "active" : "no session \u2014 run tc auth login";
|
|
23940
|
+
}
|
|
23911
23941
|
} catch {
|
|
23912
23942
|
sessionDetail = "error reading session";
|
|
23913
23943
|
}
|
|
@@ -23920,7 +23950,7 @@ function registerDoctorCommand(program) {
|
|
|
23920
23950
|
try {
|
|
23921
23951
|
const host = profileOk && profileName2 ? (await ProfileManager.getProfile(profileName2)).host : globalOpts.host || DEFAULT_HOST;
|
|
23922
23952
|
const start = Date.now();
|
|
23923
|
-
const response = await fetch(`${host}/
|
|
23953
|
+
const response = await fetch(`${host}/healthz`);
|
|
23924
23954
|
const latency = Date.now() - start;
|
|
23925
23955
|
nodeReachable = response.ok;
|
|
23926
23956
|
nodeDetail = nodeReachable ? `${host} (${latency}ms)` : `${host} returned ${response.status}`;
|
|
@@ -23939,7 +23969,7 @@ function registerDoctorCommand(program) {
|
|
|
23939
23969
|
spaceDetail = "error checking space";
|
|
23940
23970
|
}
|
|
23941
23971
|
} else {
|
|
23942
|
-
spaceDetail = "skipped (no session)";
|
|
23972
|
+
spaceDetail = "skipped (no active session)";
|
|
23943
23973
|
}
|
|
23944
23974
|
checks.push({ name: "Space", ok: spaceOk, detail: spaceDetail });
|
|
23945
23975
|
const result = {
|
|
@@ -24925,7 +24955,7 @@ function parseOperatorType(raw) {
|
|
|
24925
24955
|
// src/commands/replica.ts
|
|
24926
24956
|
init_sdk();
|
|
24927
24957
|
init_replication_registry();
|
|
24928
|
-
import { randomBytes as
|
|
24958
|
+
import { randomBytes as randomBytes6 } from "crypto";
|
|
24929
24959
|
import { constants as fsConstants2 } from "fs";
|
|
24930
24960
|
import { open as open4, readdir as readdir5, rename as rename3, stat as stat3, unlink as unlink2, readFile as readFile9, lstat as lstat4 } from "fs/promises";
|
|
24931
24961
|
import { basename as basename3, dirname as dirname5, join as join10, resolve as resolve2 } from "path";
|
|
@@ -25272,7 +25302,7 @@ function describeStatus(status) {
|
|
|
25272
25302
|
}
|
|
25273
25303
|
async function writeFileAtomic(path, bytes) {
|
|
25274
25304
|
const target = resolve2(path);
|
|
25275
|
-
const temp = join10(dirname5(target), `.${basename3(target)}.${
|
|
25305
|
+
const temp = join10(dirname5(target), `.${basename3(target)}.${randomBytes6(6).toString("hex")}.tmp`);
|
|
25276
25306
|
const handle = await open4(temp, fsConstants2.O_CREAT | fsConstants2.O_EXCL | fsConstants2.O_WRONLY, 384);
|
|
25277
25307
|
try {
|
|
25278
25308
|
await handle.writeFile(bytes);
|
|
@@ -25459,7 +25489,7 @@ or coverage incomplete; 5 grant expired, revoked or not yet valid; 6 network;
|
|
|
25459
25489
|
chooseGrant(grants, deviceDid, space, prefix);
|
|
25460
25490
|
store = await createReplica(profile, {
|
|
25461
25491
|
name,
|
|
25462
|
-
replicaId:
|
|
25492
|
+
replicaId: randomBytes6(16).toString("hex"),
|
|
25463
25493
|
host,
|
|
25464
25494
|
space,
|
|
25465
25495
|
prefix,
|
|
@@ -35549,7 +35579,7 @@ function receiveJson(result, path) {
|
|
|
35549
35579
|
// src/share/io.ts
|
|
35550
35580
|
import { constants } from "fs";
|
|
35551
35581
|
import { lstat as lstat5, mkdir as mkdir4, mkdtemp, open as open7, readFile as readFile11, realpath as realpath2, stat as stat4, link as link2, rename as rename4, rm as rm6, unlink as unlink3 } from "fs/promises";
|
|
35552
|
-
import { randomBytes as
|
|
35582
|
+
import { randomBytes as randomBytes7 } from "crypto";
|
|
35553
35583
|
import { basename as basename4, join as join12, resolve as resolve3, sep as sep2 } from "path";
|
|
35554
35584
|
init_errors();
|
|
35555
35585
|
var MAX_SHARE_STDIN_BYTES = 100 * 1024 * 1024;
|
|
@@ -35636,7 +35666,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
35636
35666
|
const stagingDirectory = await mkdtemp(join12(stableDirectory, ".tinycloud-share-stage-"));
|
|
35637
35667
|
const stagingInfo = await lstat5(stagingDirectory);
|
|
35638
35668
|
if (!stagingInfo.isDirectory() || (stagingInfo.mode & 511) !== 448) throw new Error("OUTPUT_EXISTS");
|
|
35639
|
-
const stagingPath = join12(stagingDirectory, `.tinycloud-share-${
|
|
35669
|
+
const stagingPath = join12(stagingDirectory, `.tinycloud-share-${randomBytes7(16).toString("hex")}.tmp`);
|
|
35640
35670
|
let temporaryPath;
|
|
35641
35671
|
let handle;
|
|
35642
35672
|
try {
|
|
@@ -36094,7 +36124,7 @@ init_constants();
|
|
|
36094
36124
|
init_sdk();
|
|
36095
36125
|
init_host();
|
|
36096
36126
|
init_theme();
|
|
36097
|
-
import { randomBytes as
|
|
36127
|
+
import { randomBytes as randomBytes8 } from "crypto";
|
|
36098
36128
|
import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
|
|
36099
36129
|
import { dirname as dirname6 } from "path";
|
|
36100
36130
|
function didWithoutFragment2(did) {
|
|
@@ -36175,7 +36205,7 @@ it directly with \`tc space host <name>\` (no request needed).
|
|
|
36175
36205
|
const artifact = {
|
|
36176
36206
|
kind: "tinycloud.host.request",
|
|
36177
36207
|
version: 1,
|
|
36178
|
-
requestId: `hostreq_${Date.now().toString(36)}_${
|
|
36208
|
+
requestId: `hostreq_${Date.now().toString(36)}_${randomBytes8(4).toString("hex")}`,
|
|
36179
36209
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
36180
36210
|
spaceName,
|
|
36181
36211
|
spaceId,
|
|
@@ -36517,6 +36547,7 @@ init_permissions();
|
|
|
36517
36547
|
import {
|
|
36518
36548
|
NodeWasmBindings as NodeWasmBindings2
|
|
36519
36549
|
} from "@tinycloud/node-sdk";
|
|
36550
|
+
import { ownerSessionLacksProof as ownerSessionLacksProof3 } from "@tinycloud/operations/profile";
|
|
36520
36551
|
var wasmBindings = null;
|
|
36521
36552
|
function registerStatusCommand(program) {
|
|
36522
36553
|
program.command("status").description("Show local TinyCloud profile, session, delegation, and permission state").action(async (_options, cmd) => {
|
|
@@ -36583,7 +36614,7 @@ async function inspectProfile(params) {
|
|
|
36583
36614
|
]);
|
|
36584
36615
|
const hasPrivateKey = typeof profile?.privateKey === "string" && profile.privateKey.length > 0;
|
|
36585
36616
|
const localKeyAuthenticated = profile?.authMethod === "local" && hasPrivateKey;
|
|
36586
|
-
const sessionAuthenticated = session !== null && sessionExpired !== true;
|
|
36617
|
+
const sessionAuthenticated = session !== null && sessionExpired !== true && !ownerSessionLacksProof3(session, profile);
|
|
36587
36618
|
const authenticated = localKeyAuthenticated || sessionAuthenticated;
|
|
36588
36619
|
const status = resolveStatus({
|
|
36589
36620
|
exists: profile !== null,
|