@tinycloud/cli 1.3.0-beta.40 → 1.3.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/legacy-entry.js +25 -24
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +1 -1
- package/skills/tc-cli/AUTH.md +1 -1
- package/skills/tc-cli/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -114,7 +114,7 @@ tc delegation create --to did:pkh:eip155:1:0x...
|
|
|
114
114
|
| `tc context` | Show the selected profile, owner, host, space and session state |
|
|
115
115
|
| `tc auth status` | Show authentication status |
|
|
116
116
|
| `tc auth whoami` | Show current identity |
|
|
117
|
-
| `tc auth request --preset apps-agent [--app <id>]... [--write]` | Request read-only access for an agent to the user's installed apps (one app, several, or all);
|
|
117
|
+
| `tc auth request --preset apps-agent [--app <id>]... [--write]` | Request read-only access for an agent to the user's installed apps (one app, several, or all); `--write --app <id>` also lets the agent write the app's `knowledge/` and `prefs/` files and table rows, never its code, manifest or install record |
|
|
118
118
|
| `tc knowledge list` | List the installed apps that have a knowledge bundle |
|
|
119
119
|
| `tc knowledge read <app_id> [concept]` | Read an app's knowledge index, or one concept with its frontmatter parsed |
|
|
120
120
|
| `tc kv get <key>` | Retrieve a value |
|
package/dist/legacy-entry.js
CHANGED
|
@@ -12795,19 +12795,21 @@ var APPS_AGENT_EXPIRY_DAYS = 7;
|
|
|
12795
12795
|
var APPS_AGENT_EXPIRY = `${APPS_AGENT_EXPIRY_DAYS}d`;
|
|
12796
12796
|
var APPS_AGENT_MAX_APPS = 5;
|
|
12797
12797
|
var DAY_MS2 = 864e5;
|
|
12798
|
+
var APPS_AGENT_WRITE_FOLDERS = ["knowledge/", "prefs/"];
|
|
12798
12799
|
var APPS_AGENT_VARIANTS = {
|
|
12799
12800
|
read: {
|
|
12800
12801
|
grants: [
|
|
12801
|
-
{ service: "tinycloud.kv", actions: ["tinycloud.kv/get", "tinycloud.kv/list"] },
|
|
12802
|
-
{ service: "tinycloud.sql", actions: ["tinycloud.sql/read"] }
|
|
12802
|
+
{ service: "tinycloud.kv", actions: ["tinycloud.kv/get", "tinycloud.kv/list"], within: [""] },
|
|
12803
|
+
{ service: "tinycloud.sql", actions: ["tinycloud.sql/read"], within: [""] }
|
|
12803
12804
|
],
|
|
12804
12805
|
perAppOnly: false,
|
|
12805
12806
|
changesStructure: false
|
|
12806
12807
|
},
|
|
12807
12808
|
write: {
|
|
12808
12809
|
grants: [
|
|
12809
|
-
{ service: "tinycloud.kv", actions: ["tinycloud.kv/get", "tinycloud.kv/list", "
|
|
12810
|
-
{ service: "tinycloud.
|
|
12810
|
+
{ service: "tinycloud.kv", actions: ["tinycloud.kv/get", "tinycloud.kv/list"], within: [""] },
|
|
12811
|
+
{ service: "tinycloud.kv", actions: ["tinycloud.kv/put"], within: APPS_AGENT_WRITE_FOLDERS },
|
|
12812
|
+
{ service: "tinycloud.sql", actions: ["tinycloud.sql/read", "tinycloud.sql/write"], within: [""] }
|
|
12811
12813
|
],
|
|
12812
12814
|
perAppOnly: true,
|
|
12813
12815
|
changesStructure: true
|
|
@@ -12842,8 +12844,8 @@ function isAppId(value) {
|
|
|
12842
12844
|
return value.length <= 200 && APP_ID.test(value);
|
|
12843
12845
|
}
|
|
12844
12846
|
function appsAgentPermissions(mode, appIds = []) {
|
|
12845
|
-
const
|
|
12846
|
-
return APPS_AGENT_VARIANTS[mode].grants.flatMap(({ service, actions }) =>
|
|
12847
|
+
const bases = appIds.length === 0 ? [""] : appIds.map((appId) => `${appId}/`);
|
|
12848
|
+
return APPS_AGENT_VARIANTS[mode].grants.flatMap(({ service, actions, within }) => within.flatMap((folder) => bases.map((base4) => ({ service, space: APPS_AGENT_SPACE, path: `${base4}${folder}`, actions: [...actions] }))));
|
|
12847
12849
|
}
|
|
12848
12850
|
function quoteApps(appIds) {
|
|
12849
12851
|
return appIds.map((appId) => `\`${appId}\``).join(", ");
|
|
@@ -12861,14 +12863,17 @@ function revokeSentence(lifetimeMs2) {
|
|
|
12861
12863
|
}
|
|
12862
12864
|
function appsAgentScopeNotice(mode, appIds = []) {
|
|
12863
12865
|
const variant = APPS_AGENT_VARIANTS[mode];
|
|
12864
|
-
const
|
|
12866
|
+
const writes = variant.grants.some(({ actions }) => actions.includes("tinycloud.kv/put"));
|
|
12867
|
+
const writableFolders = appIds.flatMap((appId) => APPS_AGENT_WRITE_FOLDERS.map((folder) => `\`${appId}/${folder}\``)).join(", ");
|
|
12868
|
+
const reads = writes ? `read everything there, write knowledge and data files (${writableFolders}), and add, change and delete table rows` : "list and read its files and read its table rows";
|
|
12865
12869
|
const scope = appIds.length === 0 ? `ALL your installed apps' data in the \`${APPS_AGENT_SPACE}\` space` : `the data of ${quoteApps(appIds)} (everything under ${appIds.map((appId) => `\`${appId}/\``).join(", ")}) in the \`${APPS_AGENT_SPACE}\` space`;
|
|
12866
12870
|
const lines = [
|
|
12867
12871
|
variant.changesStructure ? `This gives the agent access to ${scope}: it can ${reads}.` : `This gives the agent READ-ONLY access to ${scope}: it can ${reads}.`
|
|
12868
12872
|
];
|
|
12869
12873
|
if (variant.changesStructure) {
|
|
12870
12874
|
lines.push(
|
|
12871
|
-
`
|
|
12875
|
+
`It cannot change ${appIds.length === 1 ? "the app's" : "the apps'"} code, manifest or install record: files outside those folders are read-only for it.`,
|
|
12876
|
+
`SQL write is separate from that: it can change ${appIds.length === 1 ? "this app's" : "these apps'"} table rows and, because of how TinyCloud permissions work today (TC-1581), also change or delete ${appIds.length === 1 ? "its" : "their"} tables (structure).`,
|
|
12872
12877
|
"It cannot touch other apps, other spaces or secrets."
|
|
12873
12878
|
);
|
|
12874
12879
|
} else {
|
|
@@ -12932,10 +12937,12 @@ function matchAppsAgentRequest(requested, requestedExpiry, applicationsSpace) {
|
|
|
12932
12937
|
if (requested.some((entry) => entry.expiry !== void 0 || entry.caveats !== void 0)) return void 0;
|
|
12933
12938
|
const kvPaths = requested.filter((entry) => entry.service === "tinycloud.kv").map((entry) => entry.path);
|
|
12934
12939
|
const appIds = [];
|
|
12935
|
-
for (const path of
|
|
12940
|
+
for (const path of kvPaths) {
|
|
12936
12941
|
if (path === "") continue;
|
|
12937
|
-
|
|
12938
|
-
|
|
12942
|
+
const slash = path.indexOf("/");
|
|
12943
|
+
const appId = path.slice(0, slash);
|
|
12944
|
+
if (slash < 1 || !isAppId(appId)) return void 0;
|
|
12945
|
+
if (!appIds.includes(appId)) appIds.push(appId);
|
|
12939
12946
|
}
|
|
12940
12947
|
if (appIds.length > APPS_AGENT_MAX_APPS || appIds.length > 0 && kvPaths.includes("")) return void 0;
|
|
12941
12948
|
for (const mode of ["read", "write"]) {
|
|
@@ -13018,17 +13025,11 @@ function describeEntry(entry, applicationsSpace) {
|
|
|
13018
13025
|
}
|
|
13019
13026
|
function withinPresetSet(entry, applicationsSpace) {
|
|
13020
13027
|
if (!inApplicationsSpace(entry, applicationsSpace) || entry.caveats !== void 0) return false;
|
|
13021
|
-
|
|
13022
|
-
const
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
for (const action of grant.actions) (action.endsWith("/put") || action.endsWith("/write") ? writes : reads).add(action);
|
|
13027
|
-
}
|
|
13028
|
-
}
|
|
13029
|
-
const firstSegment = entry.path.split("/")[0] ?? "";
|
|
13030
|
-
const named = entry.path.includes("/") && isAppId(firstSegment);
|
|
13031
|
-
return entry.actions.length > 0 && entry.actions.every((action) => reads.has(action) || writes.has(action) && named);
|
|
13028
|
+
if (entry.path.split("/").some((segment) => segment === "." || segment === "..")) return false;
|
|
13029
|
+
const slash = entry.path.indexOf("/");
|
|
13030
|
+
const folder = slash > 0 && isAppId(entry.path.slice(0, slash)) ? entry.path.slice(slash + 1) : void 0;
|
|
13031
|
+
const grants = Object.values(APPS_AGENT_VARIANTS).flatMap(({ grants: variantGrants }) => variantGrants.filter((grant) => grant.service === entry.service));
|
|
13032
|
+
return entry.actions.length > 0 && entry.actions.every((action) => grants.some((grant) => grant.actions.includes(action) && (!(action.endsWith("/put") || action.endsWith("/write")) || folder !== void 0 && grant.within.some((within) => folder.startsWith(within)))));
|
|
13032
13033
|
}
|
|
13033
13034
|
function describeGrantScope(requested, requestedExpiry, applicationsSpace) {
|
|
13034
13035
|
const preset = matchAppsAgentRequest(requested, requestedExpiry, applicationsSpace);
|
|
@@ -13818,13 +13819,13 @@ ${signInAgainHint(ctx.profile, posture ?? void 0)}
|
|
|
13818
13819
|
`Lifetime of the granted delegation. ms-format string (e.g. "7d", "30m") or raw milliseconds. Defaults to 7d, capped by the active session's expiry.`
|
|
13819
13820
|
).option("--emit [file]", "Emit the request artifact to stdout, or write it to file when provided").option("--grant", "Grant the requested permissions immediately with this owner profile").option("--yes", "Skip local-key TTY confirmation", false).option("--no-popup", "Print the OpenKey URL without opening a browser when granting with OpenKey").option("--device", "With --grant: approve on another device (e.g. a phone) through OpenKey device authorization (KV-scoped; SQL needs browser login)").option(
|
|
13820
13821
|
"--preset <name>",
|
|
13821
|
-
`Request a named permission set instead of --cap: ${APPS_AGENT_PRESET} is READ-ONLY on the applications space (kv get/list + sql read, ${APPS_AGENT_EXPIRY_DAYS} days)`
|
|
13822
|
+
`Request a named permission set instead of --cap: ${APPS_AGENT_PRESET} is READ-ONLY on the applications space (kv get/list + sql read, ${APPS_AGENT_EXPIRY_DAYS} days); add --write --app <app_id> to also write those apps' knowledge and data files`
|
|
13822
13823
|
).option(
|
|
13823
13824
|
"--app <app_id>",
|
|
13824
13825
|
`With --preset ${APPS_AGENT_PRESET}: limit the grant to this app's <app_id>/ prefix (recommended); repeat for up to ${APPS_AGENT_MAX_APPS} apps`,
|
|
13825
13826
|
(value, previous) => [...previous, value],
|
|
13826
13827
|
[]
|
|
13827
|
-
).option("--write", `
|
|
13828
|
+
).option("--write", `With --preset ${APPS_AGENT_PRESET}: also allow writing the named --app apps' knowledge/ and prefs/ files (kv put) and table rows (sql write); their code, manifest and install record stay read-only. SQL write can also change or drop those apps' tables`).option("--paste", "With --grant on an OpenKey profile: wait up to 5 minutes for a signed code from OpenKey on stdin instead of a browser callback (use when the browser cannot reach this CLI)").action(async (options2, cmd) => {
|
|
13828
13829
|
try {
|
|
13829
13830
|
const globalOpts = cmd.optsWithGlobals();
|
|
13830
13831
|
const ctx = await ProfileManager.resolveContext(globalOpts, options2.grant ? {} : { storedSession: "unused" });
|