@tinycloud/cli 1.1.0-beta.15 → 1.1.0-beta.16
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/legacy-entry.js +5319 -2995
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +5 -4
- package/skills/tc-cli/REFERENCE.md +31 -1
- package/skills/tc-cli/SKILL.md +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinycloud/cli",
|
|
3
|
-
"version": "1.1.0-beta.
|
|
3
|
+
"version": "1.1.0-beta.16",
|
|
4
4
|
"description": "TinyCloud CLI - manage data, delegations, and nodes from the terminal",
|
|
5
5
|
"author": "TinyCloud, Inc.",
|
|
6
6
|
"license": "EGPL",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@tinycloud/share-sdk": "1.1.0-beta.2",
|
|
33
33
|
"@tinycloud/share-envelope": "1.1.0-beta.0",
|
|
34
|
-
"@tinycloud/node-sdk": "3.1.0-beta.
|
|
34
|
+
"@tinycloud/node-sdk": "3.1.0-beta.10",
|
|
35
35
|
"@tinycloud/node-sdk-wasm": "1.7.7-beta.0",
|
|
36
|
-
"@tinycloud/sdk-core": "3.1.0-beta.
|
|
37
|
-
"@tinycloud/operations": "0.4.0-beta.
|
|
36
|
+
"@tinycloud/sdk-core": "3.1.0-beta.10",
|
|
37
|
+
"@tinycloud/operations": "0.4.0-beta.14",
|
|
38
38
|
"chalk": "^5.3.0",
|
|
39
39
|
"commander": "^14.0.0",
|
|
40
40
|
"open": "^11.0.0",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"siwe": "^3.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
+
"@tinycloud/replica": "0.1.0-beta.0",
|
|
45
46
|
"@types/node": "^20",
|
|
46
47
|
"tsup": "^8.0.0",
|
|
47
48
|
"typescript": "^5.9.3"
|
|
@@ -5,7 +5,7 @@ This release has **Commander coverage tracked, not complete parity**:
|
|
|
5
5
|
|
|
6
6
|
- 1 migrated registration(s).
|
|
7
7
|
- 1 partially migrated registration(s).
|
|
8
|
-
-
|
|
8
|
+
- 122 legacy registration(s) remain Commander-owned.
|
|
9
9
|
|
|
10
10
|
- `auth import [source]` → `tinycloud.auth.import@1` (partial; legacy inputs: v1 delegation artifact, v1 permission artifact without command, bare portable delegation, stored delegation wrapper, cross-user delegation persisted with activated=false).
|
|
11
11
|
- `secrets get <name>` → `tinycloud.secrets.get@1` (migrated).
|
|
@@ -146,6 +146,36 @@ tc --profile agent secrets get OPENAI_API_KEY --raw
|
|
|
146
146
|
|
|
147
147
|
When neither stdin nor stderr is a terminal, `secrets get|list|put|delete` on an OpenKey profile that lacks the grant fails with `PERMISSION_DENIED` (exit 5) and a scoped paste-login hint. Missing or expired sessions instead fail with `AUTH_REQUIRED` (exit 3) before a canonical read invokes the node or starts an unscoped browser refresh. On any profile kind, a stored signed session that has expired or no longer verifies fails with `AUTH_REQUIRED` (exit 3) and a sign-in hint before any node request, never as a retryable `NODE_ERROR`; operations and MCP report a non-retryable `AUTH_REQUIRED`. Any service result coded `AUTH_REQUIRED` or `PERMISSION_DENIED` without an HTTP status now exits 3 or 5 instead of 1 in commands using `cliErrorFromService` (account, delegation, duckdb, kv, secrets list/put/delete, space, sql, vars and vault); for example, `tc secrets list` without a grant returns the NodeSecretsService's status-less `PERMISSION_DENIED` with exit 5. `tc secrets get` and `tc auth import` additionally supply the profile kind's sign-in hint for `AUTH_REQUIRED`. A delegate session bootstrapped by `tc auth import` stores no SIWE or expiry, so its expiry is found only when the node refuses it. At a terminal, the owner approves a missing grant in OpenKey: the request adds `tinycloud.capabilities/read` on the space root and keeps raw decrypt in the `encryption` pseudo-space, and a decrypt-only request is placed in the secrets space. The grant is stored with its signed SIWE proof and bound to exactly its signed capabilities, and `secrets get` (like every operation, including MCP) re-verifies it against the session key and owner, and holds it to that binding, in the same process or a new one; a stored grant that fails (such as one from an earlier release, stored without a proof) is skipped and reported as a `STORED_GRANT_SKIPPED` warning with a fixed reason code and its CID when that CID is the CID of the stored bytes: inside the JSON error's `warnings` (including a failed `-o` write), as one `{"warnings": [...]}` stderr line after a successful read's output, or as one human-readable stderr line. `--json` selects the JSON forms even with stdout on a terminal, and suppresses progress spinners. Expired grants are dropped silently. Operations and MCP results carry the same `warnings` array. A JSON error can carry both `meta` (validated authorization fields) and `warnings`. A canonical `secrets get` that still lacks authority fails with `PERMISSION_DENIED` (exit 5). Redirected stdout alone does not disable an owner's browser approval; its URL appears on stderr and terminal stdin accepts a code. `secrets get -o` validates the destination and existing directory before any read or decrypt, then syncs a fresh 0600 inode and atomically replaces an existing regular file. Directory sync is best-effort after replacement and cannot turn a completed write into a reported failure. It refuses symlinks, directories, devices and absent parent directories (`INVALID_ARGUMENT`); an unreplaceable filesystem target fails with a sanitized error naming the destination, without a non-atomic fallback. A node that refuses decrypt (HTTP 401/403) is reported as missing authority on the invoked network, not as an undecryptable secret.
|
|
148
148
|
|
|
149
|
+
## Local Replicas
|
|
150
|
+
|
|
151
|
+
`tc replica` keeps a durable, read-only copy of one KV prefix on this device. `sync` pulls the node's `tinycloud.kv/sync` change feed (node feature `kv-sync-v1`) and fetches each changed value, accepting bytes only if they hash to the ETag the node attested. `get`, `list`, `status` and `reset` never touch the network, so they work with the host offline. Reads report observed state from one source host, not global finality. Needs Node.js 22.13+ or Bun (built-in SQLite); on older Node every `tc replica` command fails with `RUNTIME_UNSUPPORTED` (exit 1) and other commands are unaffected.
|
|
152
|
+
|
|
153
|
+
A replica needs a device grant carrying `get` and `sync` on the prefix. Neither `*` nor `tinycloud.kv/*` implies `sync`, and the owner's default session does not hold it; `tc auth grant` acquires it for that grant only:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# device
|
|
157
|
+
tc --profile device auth request --cap tinycloud.kv:SPACE:notes/:get,list,metadata,sync --expiry 30d --emit req.json
|
|
158
|
+
# owner
|
|
159
|
+
tc --profile owner auth grant req.json > grant.json
|
|
160
|
+
# device
|
|
161
|
+
tc --profile device auth import grant.json
|
|
162
|
+
tc --profile device replica sync --prefix notes/ # first sync creates the replica "notes"
|
|
163
|
+
tc --profile device replica get notes/todo.md --raw # offline
|
|
164
|
+
tc --profile device replica list notes/ --json
|
|
165
|
+
tc --profile device replica status
|
|
166
|
+
tc --profile device replica sync # catch up: updates and deletes
|
|
167
|
+
tc --profile device replica reset [--purge]
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
- The first `sync` needs `--prefix` (and `--space` when grants cover several spaces); it pins the source host (`--host` or the profile host, never a discovered local node). Later runs use the stored configuration; a different `--prefix`, `--space` or `--host` is `REPLICA_CONFIG_MISMATCH` (exit 2). `--replica <name>` selects or names a replica (default: named after the prefix, or the profile's only replica).
|
|
171
|
+
- The grant must be a compact UCAN issued to this device's key; SIWE/CACAO sessions cannot back a replica. A newer covering grant is installed as pending and takes over after the node accepts a sync under it. If the node refuses it, the current grant keeps serving and `status.device.pendingDelegationError` says why; a revoked replacement is discarded without touching the replica.
|
|
172
|
+
- Reads are allowed only inside the authority window the node attested at the last successful sync (the earliest expiry across the whole delegation chain, which can be before the grant's own `exp`), checked again when each page commits. After expiry, reads fail with `GRANT_EXPIRED` (exit 5) and no new sync starts. An authority bound that is not an RFC 3339 timestamp is `PROTOCOL_ERROR` (exit 7) and changes nothing. A revocation is learned on the next online sync, only from the node's typed revocation answer (never from text such as a key name): the replica purges its entries and content and later reads fail with `GRANT_REVOKED`, including after restart. If a content file cannot be removed, `status.purgePending` is `true` and every later `tc replica` command retries; reads stay blocked meanwhile. A revoked replica stays blocked; remove it with `tc replica reset --purge` and sync again under a new grant.
|
|
173
|
+
- `--retention-grant <cid>` presents an owner-issued `tinycloud.kv/retain` grant on the prefix (never invoked; nothing implies it). Reads then continue after the sync grant expires, marked `authority: "expired"`, until the node-attested `retainUntil`. A revocation of the retain grant a sync presented drops that grant (one set meanwhile with `--retention-grant` is kept): once the sync grant expires, reads fail with `GRANT_REVOKED`. Once the sync grant has expired the device cannot learn that the retain grant was revoked.
|
|
174
|
+
- Syncing the `secrets` space or a prefix in the `vault` namespace needs `--allow-secrets`.
|
|
175
|
+
- `get` statuses: present; `KEY_DELETED`, `KEY_ABSENT` (only once the first sync completed), `CONTENT_MISSING` (known key whose bytes are not local yet; the next sync repairs it) and `COVERAGE_INCOMPLETE` exit 4; `NOT_COVERED` (outside the prefix) exits 2. `-o FILE` writes atomically with mode 0600; stored content is re-hashed on every read unless `--no-verify`.
|
|
176
|
+
- Exit codes: 0 ok; 1 busy, runtime or storage error; 2 usage, `NOT_COVERED`, `SECRETS_OPT_IN_REQUIRED`; 3 grant missing; 4 key absent, deleted, content missing or coverage incomplete; 5 grant expired, revoked or not yet valid; 6 network; 7 node, protocol or integrity error (`SOURCE_CHANGED`, `SCOPE_VIOLATION`, `CONTENT_MISMATCH`); 10 storage full.
|
|
177
|
+
- Store: `profiles/<profile>/replicas/<name>/` (honours `TC_HOME`): `replica.db` (SQLite WAL, `synchronous=FULL`; each feed page and its cursor commit in one transaction) and content-addressed `blobs/`, directories 0700 and files 0600. Only one process syncs a replica at a time (`REPLICA_BUSY`); a process whose sync lease expired or was taken over writes nothing more. `reset --purge` removes the replica only under a live lease on the database it opened, so it never removes a replica another process took over or recreated. A node answer `410 RESET_REQUIRED` resets the replica in place and re-bootstraps from the same source; `status.lastReset` records it. A feed from a different node is `SOURCE_CHANGED` until `tc replica reset` clears the pin. A profile deleted before or while any `tc replica` command runs ends it with `REPLICA_NOT_FOUND`; nothing is written into the profile and it is never recreated.
|
|
178
|
+
|
|
149
179
|
## Node Health
|
|
150
180
|
|
|
151
181
|
```bash
|
package/skills/tc-cli/SKILL.md
CHANGED
|
@@ -44,6 +44,8 @@ tc --profile publisher auth login --device --manifest builtin:share-publishing
|
|
|
44
44
|
|
|
45
45
|
SQL commands need a profile whose session the owner granted through browser login; a device-login session has no SQL authority.
|
|
46
46
|
|
|
47
|
+
To read a KV prefix while the host is unreachable, keep a local replica: `tc replica sync --prefix PREFIX` under a device grant with `sync`, then `tc replica get|list` read only local storage. See [REFERENCE.md](REFERENCE.md#local-replicas) for the grant flow, expiry and exit codes.
|
|
48
|
+
|
|
47
49
|
```bash
|
|
48
50
|
tc --profile PROFILE kv get KEY --space SPACE --json
|
|
49
51
|
tc --profile PROFILE kv get KEY --space SPACE --raw -o ./resource.txt
|