Beta / release candidate. Local replicas are in Replication RC1. Package APIs,
limitations, and release versions may change; do not treat this as a stable contract.
Requirements
-
The TinyCloud node must advertise
kv-sync-v1in its/inforesponse. The production node attee.node.tinycloud.xyzadvertises this feature. -
Install the beta CLI:
- CLI replicas need Node.js 22.13 or newer, or Bun. SQLite rejects older Node versions; Bun supplies its own SQLite runtime.
-
For browser apps, install and pin an explicit replica package version. For
example, use
@tinycloud/[email protected]. The@tinycloud/replica@betadist-tag currently points to an older build, so do not depend on it. -
A device needs a grant that covers its configured KV prefix and includes
getandsync.listandmetadataare optional.
CLI: grant, sync, and read offline
1. Grant the device access to one prefix
Create or select a device profile and make it request access to the narrowest prefix it needs. For example, thedevice profile requests get and sync
access to notes/:
sync is an explicit capability: a grant for ordinary KV reads alone is not
enough. The replica stores only its configured prefix, which must be covered
by the grant; the grant may cover a broader prefix.
2. Sync the prefix
Run the first sync with the desired prefix. The CLI creates a local replica named after that prefix unless you supply--replica:
tc --profile device replica sync again to poll for updates and
deletes. The configured source host, space, and prefix are fixed for that
replica. Use a different --replica name if you need a different scope.
3. Read while offline
get and list read only from local replica storage; they never fall back to
a host KV request. Stop the network or disconnect, then run:
--raw to write the value bytes to standard output, or -o file to save
them to a file. Sync must have completed the initial prefix coverage before
you can rely on reads of keys that have not yet been observed.
4. Inspect or reset local data
status reports the replica’s scope, sync state, authority, counts, and
failures. reset clears entries, content, and the cursor but keeps the
replica configuration and grant, so sync can populate it again. Add
--purge to remove that replica entirely:
Command options
Pass the global
--host <url> when creating a replica if the profile has no
default host; the chosen source is pinned to that replica.
For example, after confirming that storing encrypted secret material locally
is acceptable:
Retaining reads after grant expiry
By default, local reads are allowed only while the device’s sync grant is valid. An owner may separately issue atinycloud.kv/retain grant to authorize
a bounded retention window for already-synced local reads after that sync grant
expires. Supply the retention grant’s CID during a sync:
Error codes and next steps
The CLI prints a machine-readable error code alongside the message. Common replica errors:
Other errors identify configuration, grant, storage, or node failures:
Exit codes:
0 success; 1 busy/runtime/storage error; 2 usage or
NOT_COVERED / SECRETS_OPT_IN_REQUIRED; 3 missing or invalid grant;
4 absent, deleted, missing-content, or incomplete-coverage key; 5 expired,
revoked, or not-yet-valid grant; 6 network; 7 node, protocol, or integrity
error; 10 local storage full.
Browser: open, grant, sync, and read locally
The browser API is exported by@tinycloud/replica/browser; @tinycloud/web-sdk
does not wrap or re-export replica operations. It does expose owner delegation
methods used here: requestPermissions() obtains the explicit KV authority and
delegateTo() issues it to the replica’s device DID. The owner below is an
authenticated TinyCloudWeb instance configured with the app manifest needed
for permission requests.
principal is the signed-in user’s identity DID and partitions data for users
sharing a browser origin; it is not an authorization check. The grant and the
node authorize sync. Browser data is stored in IndexedDB through a dedicated
worker. Browser get and list are explicitly local; call sync() to poll
for updates. Browser sync requires Web Locks (navigator.locks); without it,
sync() rejects with RUNTIME_UNSUPPORTED, but an existing replica can still
be read. If a browser does not support IndexedDB, opening the replica fails
instead of silently switching to non-durable in-memory storage.
Security model
- A replica stores only its configured KV prefix, and the grant must cover that prefix; the grant may be broader. Out-of-scope names and bytes are not fetched into replica storage.
- By default, local reads stop when the node-attested grant window expires. A retention window attested by the node can allow reads after expiry. An offline device cannot discover an online revocation until it reconnects; once the replica learns that its serving grant was revoked, reads are blocked and content purge begins. If physical cleanup is pending, the next open retries it.
- CLI replica files use mode
0600under directories with mode0700. Protect the device account and backups as well; file permissions do not protect against the same operating-system user. - Sync grants do not grant decryption. Replicating the secrets space or a
prefix overlapping the
vaultnamespace (including barevault) requires explicit opt-in:tc replica sync --allow-secretson the CLI, oropenReplica({ allowSecrets: true })in the browser. It copies encrypted secret material to the device. If you separately grant decrypt, note that decrypt authority is network-wide today, not limited to one secret name. Do not use it unless that scope is acceptable. - Since CLI 1.1.0-beta.22:
tc auth logoutdeletes local replicas for that CLI profile by default; pass--keep-replicasto keep them. Logout does not revoke the profile’s grants on the node. To revoke node-side authority, usetc delegation revoke <cid>. Logout refuses to remove replicas if a sync is running or the replicas directory is a symlink.
Known limitations
- Known node limitations being tracked (TC-737): a quiet prefix in a busy space can make each poll scan newer changes outside that prefix, increasing sync work and potentially latency even when the prefix has no updates.
- Known node limitations being tracked (TC-735): on Postgres, blob uploads run inside the per-space write lock, so uploads can slow other writes in that space.
- Remote refresh is polling through
sync(); there is no remote push or watch API. In the browser,onCommittedreports only local commits from other tabs. - Replicas are read-only. Offline writes are not supported.
