Changes
The SDK has been worked out with the first app that will use it, round by round. Each round’s decisions are below, newest last, with where to read more. The pages themselves always say how things stand now.
Before the first app (18–19 October 2026)
Decided by Iceblock’s maintainer, on #326:
- An app adopted into the user’s network ends as an app device (Scoped), with its own Collection in scope.
- Adopting an app with its own data is a pulled merge: the user’s device carries it in, and the app never holds the user’s root keys. Never joined at Full and lowered.
- Adoption hands the app’s network over, with the home of any group the app made; such groups show in Devices under Applications.
- An app’s Collections show in Files by default; hiding one is the app’s to ask, and the user’s to change.
- The Rust facade and the Flutter package are built together; Android and Linux first.
The pages, and the first round (20 October)
The SDK’s pages were published, and the first app sent its needs. Decided:
- Its data: immutable records, a file each; one group Collection and one Collection per network; groups only, no plain shares; the app decides what’s urgent and syncs it now.
- No push service. A phone in the background hears at its next background run.
- Presence is off unless an app needs it, and only passive: it comes from use, never from watching the device. Last activity is that same permission.
- Device names are a permission (
devices), and so is knowing of other Collections (collections): without it, an app knows nothing of any Collection outside its scope, not even that it exists. A Collection linked inside the app’s own is in its scope; the app doesn’t know where its own sits in Files. - Group apps ask for what member networks share in the same way (
group-presence,group-devices), each member network deciding. - A cut-down network document for app devices, in stage 2.
- Published on git.tricauda.com, in the organisation’s Cargo and pub registries.
- The user never has to open each app to see what’s new: background sync on Android, on by default, with a handler that notifies.
- Iceblock and apps wake each other on one phone; an app joins Iceblock on the same phone directly, Iceblock checking it by its signing certificate.
- The app’s own invitation URLs, made by the core from a link address that’s an origin only, everything after the
#.
The second round
- Roll-ups: only finished days, written once by the current holder, so no file is ever edited.
- Recall after two days without contact (the app proposed three); a handoff beats a recall.
- Thresholds, to tune once it runs: around is use in the last 15 minutes; recent contact within 30 minutes on Wi-Fi, 90 on mobile data; 5-minute steps.
- Presence additions: use of any app built on Iceblock counts, never saying which; last contact; per device only for the app’s own installs on its own network.
- The app builds its own bridge on
iceblock-sdk, so the platform parts come as a package without Rust (iceblock_platform).
The third round, and validation
- Presence expires after two hours, not one: a phone on mobile data syncs about hourly in the background.
- Roll-ups delete the day’s records to the trash rather than purge them, so the holder needs no Owner’s role.
- The app’s identity rests on the user’s approval at pairing: a second install is shown as another install of an app already granted things.
- The first app validated the agreed design.
After validation
- Recall became “looking for it”: any member network may look once the holder has been out of touch for two days, judged by the home’s last contact, and whoever finds it gets it.
- Coarse presence is a permission of its own (
group-contact:<group>: the group’s home hasn’t heard from a member for two days or more), which an app may require of its group’s members. - Apps have a static id (
app_id, reverse-domain; on Android the package name), recorded by Iceblock on the app’s devices and groups. Claiming another app’s id is stopped where the platform can: on Android the id is pinned to the app’s signing certificate the first time it joins, so a later install with the same certificate inherits its grants and one with another is refused as that app; where nothing can be checked (Linux, over the network), an install never inherits grants silently, and the user decides with what’s at stake in front of them. This amends “identity rests on the user’s approval at pairing”. - The first app’s answers: it requires
group-contact, and a member who declines can’t take part; two days and the 30-minute check suit; looking for it sends no notifications; roll-ups are named by their own id, so two never collide (readers take a day’s records from every roll-up of it).
Stage 2 (21 October)
Decided by Iceblock’s maintainer while building stage 2:
- Stage 2 ships as one release, breaking: an app’s id and manifest go on the wire when it pairs.
- An app’s Collection kept out of Files is kept out of Collections too, shown under the app in a new Applications section under My network, where it opens and where the user puts it back. The command line’s
collectionsstill lists it, marked. - Adoption retires the app network’s key rather than handing it over: the app network signs that the user’s network succeeds it, then destroys its key; everyone who dealt with it checks the succession, whoever shows it. The app’s other installs are pre-approved, and move over once they learn where to go, from a Full-trust device or an install that already moved.
- Applications in a group replace “a group made through an app is that app’s”: a group has apps, each added by any one Owner for everyone in it, with Collections of their own. Each member chooses whether to use each: one that doesn’t has none of the app’s Collections and keeps the group’s others; one that does has at least the role the app’s manifest asks for there.
group-contactis per app. Taking an app out, or moving it to another group, is a proposal with the Owners’ rule; out, its Collections stay the group’s, with a hint for the app to take them up again. - The cut-down network document: thin app devices. Worked through as a split into several documents first, then simpler: an app never holds the network document, but a view the user’s Full-trust or Metadata-only devices make it at each sync, with the members’ keys and trust (names only with
devices), its own Collections, their key records, and its own grants and requests. It learns nothing of other Collections, not even that they exist, nor of other apps. Its requests go to a Full-trust device at its next sync. Encrypting device names isn’t needed.
After stage 2 (21 October)
Asked by the first app while building on library 0.11.2, and built:
- The group’s home, by fingerprint, for every member. A file the home writes in a group’s Collection has no
networkof its own, and only the home could tell it was its own. Every member now has the home’s fingerprint (Group::home), which follows the group when it’s handed on. - Successions, for every member. Adopting an app gives its network a new fingerprint, but its records still name the old one. The group’s home keeps each succession of its own or of a member’s, and gives them with the roster; each member checks the old network’s signature before keeping one.
Group::successionslists them, andGroup::currentfollows a chain of them to the network now, so the adopting network reads as the one it succeeded: it holds what the old one held, and its records go on from the old one’s.
Built
-
Stage 1, released in Iceblock 0.72.0 (library 0.10.0): the Rust facade
iceblock-sdk(Collections and files, watching, syncing, the app on its other devices, groups, its own invitation URLs, conditions, the metered setting); which network wrote each version, as the group’s home checked; a facade without image decoders, FUSE or relaying;iceblock_platform(conditions, background work, waking, finding Iceblock), which Iceblock itself runs on; all of it in the organisation’s registries. -
Stage 2, first part, released in r76 (app 0.76.0, library 0.12.0; breaking): the static
app_idand the manifest, said when an app pairs; the user’s Iceblock pairing it as an app or not at all, showing its manifest, and recording which app each app device is, with its certificate’s digest where the platform checked it (a second install with the same inherits the app’s grants; with another, or unchecked and not vouched for by the user, it’s a separate app holding nothing); permissions generalising Collection requests (asked for within the manifest, approved, denied or offered on any Full-trust device, taken back); the Applications list (iceblock apps, and a section under My network); an app’s Collection kept out of Files and Collections at the app’s ask, shown under the app instead; Iceblock on Android waking the apps grantedwakewhen their Collections change; answers as the app’s events (granted, taken back, denied); thin app devices, which hold a view of the network rather than its document; adoption finished: the app network’s succession, its groups carrying on from the user’s network, and its other installs following it; coarse presence (group-contact), off by default, per app; Applications in a group, each added by an Owner for everyone, used by those who choose to, with Collections of its own, taken out or moved by the Owners’ agreement. The certificate check itself waits for Iceblock and the app meeting on the same phone. -
After stage 2, in r77 (library 0.13.0): a Collection’s new owner tells its recipients directly, with the old owner’s signed consent, and the old owner points to the new share for a year; an app moved to a group with another home, its Collections given there.
-
For the first app, in r78 (library 0.13.1): every member knows its group’s home (
Group::home), and the group’s successions, each checked (Group::successions,Group::current), so what a succeeded network wrote reads as its successor’s. -
For the first app, in r79 (library 0.13.2): when a member last heard from its group’s home (
Group::synced_secs), for looking for what the group shares. -
Found by the first app’s adoption test, fixed in r81: an adopted app holds every Collection its network had, its own included; it reads its groups through the user’s network; and it serves again on the same port, so its old network’s members still reach it and learn where the network went.
-
The user’s devices, in r82 (library 0.13.5):
app.devices(), withdevices. -
Stage 3, presence, in r83 (library 0.14.0): within the user’s network (
app.used(),app.presence()) and in groups (group.share_presence(),group.presence()), from use, with last contact, in memory alone. -
Joining Iceblock on the same phone, in r84, on Android: the platform package’s
joinIceblock, Iceblock checking the app by its signing certificate. -
On Linux, and later requests, in r85:
app.join_on_this_device()andapp.open_requests()through Iceblock’s control socket; on Android,openIceblockRequests. Stage 2 is complete. -
A sample app, Tintbench, in r86: a stand-in photo editor on the facade alone, with a test of scenario 47 against a running Iceblock (see the Rust facade). With it:
app.removed()andEvents::removed, for an app the user removed; and an adopted app now lists the Collection its old network became (merged-…) among its permissions. -
The full Flutter package,
iceblock_flutter, in r87 (#658): the facade for Dart, with the library compiled inside for Android and Linux, and an example app. -
Use said by the platform package, in r88 (#762):
UseReporter(() => app.used())says the app’s in use as it comes to the front and every minute while it stays there, on Android and Linux. -
The change feed, in r89 (#766):
watchasks the Collection’s documents what changed since it last looked, and looks only at those files, so watching a Collection with very many files costs no more than watching a small one. -
Which of your devices you’re using, in r90 (#769):
device-presence, a permission of its own, as Iceblock’s maintainer decided. Each of the app’s installs learns when any app built on Iceblock (Iceblock included) was last used on its machine, never which app (machine_last_used), and the apps on a machine hear within seconds when it’s picked up. Iceblock knows which devices share a machine from an app joining it there. -
An app’s personal Collections, in r91 (#777): its user’s own data, which belongs to the user’s network and stays on it through every migration, only a group’s Collections moving with the group. Once adopted, an app device’s
create_collectionasks the user’s network, which makes it without asking the user, and returns once it has. -
When you’re at your computer, in r95 (library 0.15.0, #772):
device-activity, a permission of its own. Each install learns when the person was last at its computer, from the computer itself (machine_last_active), as Iceblock checks there, or the app where Iceblock isn’t; an app on its own turns it on withreport_activity(true)after asking, and the user’s Iceblock offers to keep it when it adopts the app. Linux for now. Breaking: every device needs r95. -
All of the facade in Dart, in r96 (library 0.16.0), as the first app asked: a whole manifest at start, using the app in a group, successions, who’s out of touch, hiding a Collection from Files,
canGroup, earlier versions, and the rest; cancellingevents()completes. Breaking:acceptGroupInvitationreturns aJoiningInfo. With it, the SDK’s reference (#791), generated from the code: /sdk/llms.txt and /sdk/api.json; and “Keep that here?” when an app’s added on the same phone or computer (#790): passreportsActivitytojoinIceblock. -
Settings, in r102 (#801):
app.settings(), small values under keys that follow the user across the app’s installs, or stay on one device, kept sealed in a hidden store of the app’s own; shown, with a reset, under the app in the user’s Applications. -
The library’s log, for apps, in r100 (#800):
Iceblock::set_logsays where it goes, quiet by default (warnings and errors, marked);recent_logfor a debug report; in Dart,app.log()andrecentLog, and logcat on Android while nothing listens. -
Release builds start, in r105 (library 0.16.9):
iceblock_platformkeeps what WorkManager needs in an app’s release build, which R8 had removed, so the app crashed as it started.
Coming next
In this order:
- Pages for apps that use Iceblock, on the website (#660): what an app in your network can and can’t do, and answering it; a developer’s page. Written with the first app’s testing, as its overall check.
- The presence thresholds, tuned once presence runs in the first app.
- Other platforms, as the core supports them: Android and Linux first.
Still open
- The first app’s own: peeking from the screen’s edge on GNOME, which has no layer-shell.