@tinycloud/cli 0.7.0-beta.8 → 0.7.0-beta.9
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 +124 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -816,12 +816,19 @@ function buildAuthUrl(did, options = {}) {
|
|
|
816
816
|
if (options.host) {
|
|
817
817
|
params.set("host", options.host);
|
|
818
818
|
}
|
|
819
|
+
const reason = typeof options.reason === "string" ? options.reason.trim() : "";
|
|
819
820
|
if (options.permissions?.length) {
|
|
820
821
|
params.set(
|
|
821
822
|
"permissions",
|
|
822
|
-
Buffer.from(JSON.stringify({
|
|
823
|
+
Buffer.from(JSON.stringify({
|
|
824
|
+
permissions: options.permissions,
|
|
825
|
+
...reason ? { reason } : {}
|
|
826
|
+
})).toString("base64url")
|
|
823
827
|
);
|
|
824
828
|
}
|
|
829
|
+
if (reason) {
|
|
830
|
+
params.set("reason", reason);
|
|
831
|
+
}
|
|
825
832
|
if (options.expiry !== void 0) {
|
|
826
833
|
params.set("expiry", String(options.expiry));
|
|
827
834
|
}
|
|
@@ -11391,6 +11398,10 @@ function registerAuthCommand(program2) {
|
|
|
11391
11398
|
jwk: key,
|
|
11392
11399
|
host: ctx.host,
|
|
11393
11400
|
permissions: group,
|
|
11401
|
+
reason: permissionGrantReason(
|
|
11402
|
+
"Grant requested TinyCloud permissions from `tc auth request --grant`.",
|
|
11403
|
+
group
|
|
11404
|
+
),
|
|
11394
11405
|
openkeyHost,
|
|
11395
11406
|
expiry: expiryOption,
|
|
11396
11407
|
noPopup: options.popup === false
|
|
@@ -11535,6 +11546,7 @@ function registerAuthCommand(program2) {
|
|
|
11535
11546
|
node,
|
|
11536
11547
|
requested: parsed.requested,
|
|
11537
11548
|
expiryOption: parsed.requestedExpiry,
|
|
11549
|
+
reason: "Grant permissions requested by a TinyCloud auth request artifact.",
|
|
11538
11550
|
yes: options.yes === true
|
|
11539
11551
|
});
|
|
11540
11552
|
const grant = await grantAuthRequest(node, parsed);
|
|
@@ -11818,6 +11830,7 @@ async function ensureDelegationAuthority(params) {
|
|
|
11818
11830
|
jwk: key,
|
|
11819
11831
|
host: params.ctx.host,
|
|
11820
11832
|
permissions: group,
|
|
11833
|
+
reason: permissionGrantReason(params.reason, group),
|
|
11821
11834
|
openkeyHost,
|
|
11822
11835
|
expiry: params.expiryOption
|
|
11823
11836
|
});
|
|
@@ -11865,6 +11878,12 @@ async function ensureDelegationAuthority(params) {
|
|
|
11865
11878
|
});
|
|
11866
11879
|
}
|
|
11867
11880
|
}
|
|
11881
|
+
function permissionGrantReason(context, permissions) {
|
|
11882
|
+
const first = permissions[0];
|
|
11883
|
+
const summary = first ? compactPermission(first) : "no permissions";
|
|
11884
|
+
const more = permissions.length > 1 ? ` and ${permissions.length - 1} more permission${permissions.length === 2 ? "" : "s"}` : "";
|
|
11885
|
+
return `${context} Requested: ${summary}${more}.`;
|
|
11886
|
+
}
|
|
11868
11887
|
function execCapturedCommand(command) {
|
|
11869
11888
|
return new Promise((resolve3, reject) => {
|
|
11870
11889
|
const child = spawn(process.execPath, [process.argv[1], ...command.argv], {
|
|
@@ -13541,12 +13560,17 @@ async function runSecretOperation(params) {
|
|
|
13541
13560
|
node: params.node,
|
|
13542
13561
|
requested,
|
|
13543
13562
|
expiryOption: void 0,
|
|
13563
|
+
reason: secretPermissionReason(params.action, params.name),
|
|
13544
13564
|
yes: true,
|
|
13545
13565
|
force: true
|
|
13546
13566
|
})
|
|
13547
13567
|
);
|
|
13548
13568
|
return runSecretOperationAttempt(params.label, params.operation);
|
|
13549
13569
|
}
|
|
13570
|
+
function secretPermissionReason(action, name) {
|
|
13571
|
+
const target = name ? ` secret "${name}"` : " secrets";
|
|
13572
|
+
return `Allow \`tc secrets ${action}${name ? ` ${name}` : ""}\` to access${target} with the required TinyCloud permissions.`;
|
|
13573
|
+
}
|
|
13550
13574
|
async function runSecretOperationAttempt(label, operation) {
|
|
13551
13575
|
try {
|
|
13552
13576
|
return await withSpinner(label, operation);
|
|
@@ -15479,7 +15503,7 @@ import open from "open";
|
|
|
15479
15503
|
import { readFile as readFile10 } from "fs/promises";
|
|
15480
15504
|
var ACCOUNT_BILLING_URL = "https://account.tinycloud.xyz/billing";
|
|
15481
15505
|
function registerAccountCommand(program2) {
|
|
15482
|
-
const account = program2.command("account").description("Account applications, delegations, and billing");
|
|
15506
|
+
const account = program2.command("account").description("Account applications, spaces, delegations, and billing");
|
|
15483
15507
|
account.command("status").description("Show account status").action(async (_options, cmd) => {
|
|
15484
15508
|
try {
|
|
15485
15509
|
const node = await authenticatedNode(cmd);
|
|
@@ -15491,11 +15515,11 @@ function registerAccountCommand(program2) {
|
|
|
15491
15515
|
}
|
|
15492
15516
|
});
|
|
15493
15517
|
const apps = account.command("apps").description("Manage account application registry");
|
|
15494
|
-
apps.command("list").description("List applications registered under account/applications").option("--
|
|
15518
|
+
apps.command("list").description("List applications registered under account/applications").option("--live", "Read canonical account KV records instead of the SQLite index").action(async (_options, cmd) => {
|
|
15495
15519
|
try {
|
|
15496
15520
|
const options = _options;
|
|
15497
15521
|
const node = await authenticatedNode(cmd);
|
|
15498
|
-
const result = options.
|
|
15522
|
+
const result = options.live ? await node.account.applications.list() : await node.account.index.applications.list();
|
|
15499
15523
|
assertOk(result);
|
|
15500
15524
|
const payload = { applications: result.data, count: result.data.length };
|
|
15501
15525
|
if (shouldOutputJson()) {
|
|
@@ -15521,6 +15545,84 @@ function registerAccountCommand(program2) {
|
|
|
15521
15545
|
handleError(error);
|
|
15522
15546
|
}
|
|
15523
15547
|
});
|
|
15548
|
+
const spaces = account.command("spaces").description("Manage account space registry");
|
|
15549
|
+
spaces.command("list").description("List spaces registered under account/spaces").option("--live", "Read canonical account KV records instead of the SQLite index").action(async (options, cmd) => {
|
|
15550
|
+
try {
|
|
15551
|
+
const node = await authenticatedNode(cmd);
|
|
15552
|
+
const result = options.live ? await node.account.spaces.list() : await node.account.index.spaces.list();
|
|
15553
|
+
assertOk(result);
|
|
15554
|
+
const payload = { spaces: result.data.map(formatSpace), count: result.data.length };
|
|
15555
|
+
if (shouldOutputJson()) {
|
|
15556
|
+
outputJson(payload);
|
|
15557
|
+
return;
|
|
15558
|
+
}
|
|
15559
|
+
if (result.data.length === 0) {
|
|
15560
|
+
process.stdout.write(theme.muted("No account spaces registered.") + "\n");
|
|
15561
|
+
return;
|
|
15562
|
+
}
|
|
15563
|
+
process.stdout.write(
|
|
15564
|
+
formatTable(
|
|
15565
|
+
["Space", "Type", "Owner", "Status", "Updated"],
|
|
15566
|
+
result.data.map((space) => [
|
|
15567
|
+
space.name,
|
|
15568
|
+
space.type,
|
|
15569
|
+
space.ownerDid,
|
|
15570
|
+
space.status,
|
|
15571
|
+
space.updatedAt ?? "\u2014"
|
|
15572
|
+
])
|
|
15573
|
+
) + "\n"
|
|
15574
|
+
);
|
|
15575
|
+
} catch (error) {
|
|
15576
|
+
handleError(error);
|
|
15577
|
+
}
|
|
15578
|
+
});
|
|
15579
|
+
spaces.command("info <space-id>").description("Show a registered account space").action(async (spaceId, _options, cmd) => {
|
|
15580
|
+
try {
|
|
15581
|
+
const node = await authenticatedNode(cmd);
|
|
15582
|
+
const result = await node.account.spaces.get(spaceId);
|
|
15583
|
+
assertOk(result);
|
|
15584
|
+
outputJson(formatSpace(result.data));
|
|
15585
|
+
} catch (error) {
|
|
15586
|
+
handleError(error);
|
|
15587
|
+
}
|
|
15588
|
+
});
|
|
15589
|
+
spaces.command("register <space-id>").description("Register a space in account/spaces").requiredOption("--name <name>", "Display name for the space").requiredOption("--owner <did>", "Owner DID for the space").option("--type <type>", "Space type: owned, delegated, or discovered", "discovered").option("--permission <permission...>", "Permission strings for the space").action(async (spaceId, options, cmd) => {
|
|
15590
|
+
try {
|
|
15591
|
+
const node = await authenticatedNode(cmd);
|
|
15592
|
+
const result = await node.account.spaces.register({
|
|
15593
|
+
spaceId,
|
|
15594
|
+
name: options.name,
|
|
15595
|
+
ownerDid: options.owner,
|
|
15596
|
+
type: options.type,
|
|
15597
|
+
permissions: options.permission ?? [],
|
|
15598
|
+
status: "active"
|
|
15599
|
+
});
|
|
15600
|
+
assertOk(result);
|
|
15601
|
+
outputJson({ space: formatSpace(result.data), registered: true });
|
|
15602
|
+
} catch (error) {
|
|
15603
|
+
handleError(error);
|
|
15604
|
+
}
|
|
15605
|
+
});
|
|
15606
|
+
spaces.command("sync").description("Register currently accessible spaces into account/spaces").action(async (_options, cmd) => {
|
|
15607
|
+
try {
|
|
15608
|
+
const node = await authenticatedNode(cmd);
|
|
15609
|
+
const result = await node.account.spaces.syncAccessible();
|
|
15610
|
+
assertOk(result);
|
|
15611
|
+
outputJson({ spaces: result.data.map(formatSpace), count: result.data.length, synced: true });
|
|
15612
|
+
} catch (error) {
|
|
15613
|
+
handleError(error);
|
|
15614
|
+
}
|
|
15615
|
+
});
|
|
15616
|
+
spaces.command("remove <space-id>").alias("delete").description("Remove a space registry entry").action(async (spaceId, _options, cmd) => {
|
|
15617
|
+
try {
|
|
15618
|
+
const node = await authenticatedNode(cmd);
|
|
15619
|
+
const result = await node.account.spaces.remove(spaceId);
|
|
15620
|
+
assertOk(result);
|
|
15621
|
+
outputJson({ spaceId, removed: true });
|
|
15622
|
+
} catch (error) {
|
|
15623
|
+
handleError(error);
|
|
15624
|
+
}
|
|
15625
|
+
});
|
|
15524
15626
|
apps.command("info <app-id>").description("Show a registered account application").action(async (appId, _options, cmd) => {
|
|
15525
15627
|
try {
|
|
15526
15628
|
const node = await authenticatedNode(cmd);
|
|
@@ -15553,14 +15655,14 @@ function registerAccountCommand(program2) {
|
|
|
15553
15655
|
}
|
|
15554
15656
|
});
|
|
15555
15657
|
const delegations = account.command("delegations").description("View and revoke account delegations");
|
|
15556
|
-
delegations.command("list").description("List delegations granted by or to this account").option("--granted", "Show only delegations granted by this account").option("--received", "Show only delegations granted to this account").option("--space <space>", "Filter by space name or ID").option("--
|
|
15658
|
+
delegations.command("list").description("List delegations granted by or to this account").option("--granted", "Show only delegations granted by this account").option("--received", "Show only delegations granted to this account").option("--space <space>", "Filter by space name or ID").option("--live", "Read live delegation services instead of the SQLite index").action(async (options, cmd) => {
|
|
15557
15659
|
try {
|
|
15558
15660
|
if (options.granted && options.received) {
|
|
15559
15661
|
throw new CLIError("USAGE_ERROR", "Use only one of --granted or --received.", ExitCode.USAGE_ERROR);
|
|
15560
15662
|
}
|
|
15561
15663
|
const node = await authenticatedNode(cmd);
|
|
15562
15664
|
const direction = options.granted ? "granted" : options.received ? "received" : "all";
|
|
15563
|
-
const result = options.
|
|
15665
|
+
const result = options.live ? await node.account.delegations.list({ direction, space: options.space }) : await node.account.index.delegations.list({ direction, space: options.space });
|
|
15564
15666
|
assertOk(result);
|
|
15565
15667
|
const payload = { delegations: result.data.map(formatDelegation2), count: result.data.length };
|
|
15566
15668
|
if (shouldOutputJson()) {
|
|
@@ -15599,6 +15701,16 @@ function registerAccountCommand(program2) {
|
|
|
15599
15701
|
}
|
|
15600
15702
|
});
|
|
15601
15703
|
const index = account.command("index").description("Manage the materialized account SQLite index");
|
|
15704
|
+
index.command("status").description("Show account SQLite index sync status").action(async (_options, cmd) => {
|
|
15705
|
+
try {
|
|
15706
|
+
const node = await authenticatedNode(cmd);
|
|
15707
|
+
const result = await node.account.index.status();
|
|
15708
|
+
assertOk(result);
|
|
15709
|
+
outputJson(result.data);
|
|
15710
|
+
} catch (error) {
|
|
15711
|
+
handleError(error);
|
|
15712
|
+
}
|
|
15713
|
+
});
|
|
15602
15714
|
index.command("rebuild").description("Rebuild account SQLite index from canonical account data").action(async (_options, cmd) => {
|
|
15603
15715
|
try {
|
|
15604
15716
|
const node = await authenticatedNode(cmd);
|
|
@@ -15683,6 +15795,12 @@ function formatDelegation2(delegation) {
|
|
|
15683
15795
|
createdAt: delegation.createdAt?.toISOString()
|
|
15684
15796
|
};
|
|
15685
15797
|
}
|
|
15798
|
+
function formatSpace(space) {
|
|
15799
|
+
return {
|
|
15800
|
+
...space,
|
|
15801
|
+
expiresAt: space.expiresAt?.toISOString()
|
|
15802
|
+
};
|
|
15803
|
+
}
|
|
15686
15804
|
|
|
15687
15805
|
// src/index.ts
|
|
15688
15806
|
var { version } = JSON.parse(
|