Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
858 commits
Select commit Hold shift + click to select a range
2105086
data-browser: fix ? and \ hotkeys broken by react-hotkeys-hook v5
joepio Jul 8, 2026
4e331ec
Outbox fix: count debounced + cold-drain saves as pending (no silent …
Polleps Jul 8, 2026
c8cb9a2
desktop: Android Tauri app boots and syncs — TLS verifier init, gradl…
joepio Jul 8, 2026
ebbffe8
data-browser: shortcuts overlay - real filter input, scroll inside panel
joepio Jul 8, 2026
b42f69d
planning: device-pairing.md — one-scan server↔phone pairing UX + enve…
joepio Jul 8, 2026
120a0c2
data-browser: one floating-surface style for menus and popovers
joepio Jul 8, 2026
7971be2
data-browser: dropdown menu behaves like the popovers
joepio Jul 8, 2026
9bd9e24
data-browser: presence for canvas + tables on the drive presence channel
joepio Jul 8, 2026
335c4bf
planning: device-pairing — SaaS device directory for zero-scan pairing
joepio Jul 8, 2026
d043233
data-browser: client-side demo workspace + Meetings (follow + chat), …
joepio Jul 8, 2026
8590a6d
Fix three e2e flakes: sync offline-reconnect, table views, table cell…
joepio Jul 8, 2026
648717d
Device pairing: stop logging the agent secret; device-directory client
joepio Jul 8, 2026
2dd47ba
lib: atomic://pair envelope encode/decode (device pairing P1)
joepio Jul 8, 2026
a41933d
data-browser: QR pairing dialog + atomic://pair paste support
joepio Jul 8, 2026
f86d61f
planning: device-pairing — record P0/P1 render-side progress
joepio Jul 8, 2026
867a597
Demo polish: fix canvas draw crash, enrich team table, reactive say-h…
joepio Jul 9, 2026
01ae700
Demo: drop welcome-doc todo list; RTE: copy resource mentions as thei…
joepio Jul 9, 2026
6e67dd6
Device pairing: atomic:// deep link + import flow (phone-side receiver)
joepio Jul 9, 2026
5f260ca
Comments/chat: tighter, aligned message rows with compact timestamps
joepio Jul 9, 2026
44b6d01
Chat: avatars beside messages; compact, aligned follow-event lines
joepio Jul 9, 2026
1f0c47e
Navbar panel toggles show open state; meeting survives refresh
joepio Jul 9, 2026
ef541d3
Avatars: shared follow menu + online dot everywhere (incl. chat)
joepio Jul 9, 2026
51b7448
Device pairing: make atomic:// deep links actually work on Android
joepio Jul 9, 2026
b63c938
Kanban: custom vertical card ordering with a live drag preview
joepio Jul 9, 2026
07db293
Demo on Tauri: ClientDb becomes a platform default, not a hard block
joepio Jul 9, 2026
51042e3
Chat: rounded hover chip clear of the avatar; meeting trail dedups pe…
joepio Jul 9, 2026
737f055
Navbar: collapse actions to icons based on real overflow, not a fixed…
joepio Jul 9, 2026
72eb83e
Meeting: toast new chat messages when the meeting panel is closed
joepio Jul 9, 2026
81e3eb9
Android UX: swipe to open/close the sidebar; keyboard resizes the app
joepio Jul 9, 2026
40c51e9
Right panel: sidebar-style slide animation + overlay-on-small-screens
joepio Jul 9, 2026
6da5038
Fix ClientDb never starting on Android: stale SharedWorker guard
joepio Jul 9, 2026
043b49e
i18n: regenerate translation catalog (single-writer clean)
joepio Jul 9, 2026
f7c1cf9
Sync page: full device-to-device pairing (QR + copyable code + paste,…
joepio Jul 9, 2026
cc4e9c3
Sync UI: target the local server origin, not a bare path (fixes deskt…
joepio Jul 9, 2026
0eafe66
data-browser: live "typing…" presence for chat & comment composers
joepio Jul 9, 2026
7999fd5
Welcome screen: scrollable on phones (was clipped; buttons unreachable)
joepio Jul 9, 2026
9df9800
Drive UX redesign: user page owns drives, caret switcher, drop dead s…
joepio Jul 9, 2026
d43f9b9
Redesign the Sync page around unified connection cards
joepio Jul 9, 2026
b783b9a
Fix host-to-drive binding: /setup becomes /bind-drive and actually wr…
joepio Jul 9, 2026
cd2fb9b
Planning: tours/replayable meetings + DID-branch deployment strategy
joepio Jul 9, 2026
05befe2
Fix cargo test -p atomic_lib for every feature combination
joepio Jul 9, 2026
227acce
Sync page: honest local-only state + 'Sync this workspace' promote
joepio Jul 9, 2026
9998a0d
locales: extract Sync page redesign + promote strings
joepio Jul 9, 2026
218dc72
Fix 'Exit demo' getting stuck on 'Leaving…' forever
joepio Jul 9, 2026
8ce3c03
Demo v3 + presence: meeting narration, live nudges, de-duplicated fol…
joepio Jul 9, 2026
6cdab0e
Never store the agent's private key in plaintext
joepio Jul 9, 2026
f80b3f7
Scan pairing QRs with the device camera
joepio Jul 9, 2026
fd5fbdc
Introduce Android devices by name, not "localhost"
joepio Jul 9, 2026
48aed6c
Point a freshly signed-in device at the data it's missing
joepio Jul 9, 2026
ca18338
Meet a data-less sign-in with a way to reach the data
joepio Jul 10, 2026
dc3d6fb
Stop telling people their workspace isn't there while it's arriving
joepio Jul 10, 2026
5a68f10
Write one node identity, not two
joepio Jul 10, 2026
3f528c6
A pairing code can no longer hand over an account
joepio Jul 10, 2026
3ef88f7
Make room for the on-screen keyboard on the onboarding screens
joepio Jul 10, 2026
02a4575
Shrink the layout for the keyboard instead of scrolling the top bar away
joepio Jul 10, 2026
98ad6a3
Show pairing as steps in a dialog, not a status line and a toast
joepio Jul 10, 2026
30034f8
Land pairing on success or on a reason, and rebuild the Sync page's p…
joepio Jul 10, 2026
26c499b
Refuse peer sync from a different account, instead of syncing nothing
joepio Jul 10, 2026
ec90714
Make a device's node act as the signed-in user, not as its own server
joepio Jul 10, 2026
721b780
Ask whether the drive is here, not whether it exists somewhere
joepio Jul 10, 2026
c7bf3b2
Tell the local clients about changes no commit produced
joepio Jul 10, 2026
7feb467
Remember the drive a device syncs, so it reconnects on its own
joepio Jul 10, 2026
2e04f02
Sync the agent resource between a user's own devices
joepio Jul 10, 2026
a6f4930
Record the resolution: the node relays and serves, never signs as a p…
joepio Jul 10, 2026
b175448
Plan node-as-granted-replica: how autonomous private-drive replicatio…
joepio Jul 10, 2026
0a4901c
P2: classify a commit's authorization impact
joepio Jul 10, 2026
2e3c538
Add Resource::genesis_signer(): the forge-resistant creator from the …
joepio Jul 10, 2026
3c7bb9e
Golden cross-language vectors for the v1 genesis certificate
joepio Jul 10, 2026
dcd22b6
Bind the browser GenesisCert to the shared golden fixture
joepio Jul 10, 2026
9e93e33
Add signBytes to the crypto providers + Agent
joepio Jul 10, 2026
f11541f
Mint cert-based DIDs at creation in newResource; drop _new: from that…
joepio Jul 10, 2026
d31702b
Send the cert-DID subject in the genesis commit body
joepio Jul 10, 2026
232aca8
Cert-mint file uploads; move AI ids off the _new: scheme
joepio Jul 10, 2026
34caaba
Zero-scan: auto-connect the account's devices on sign-in
joepio Jul 10, 2026
68f5ffe
Add "Back up to Cloud Sync" for a locally-started drive
joepio Jul 11, 2026
482dde7
Sign in to Cloud Sync in-app instead of a dead-end toast
joepio Jul 12, 2026
0fa1f6b
Fix the Tauri dev server serving a stale bundle under nushell
joepio Jul 12, 2026
116fbe8
Simplify the welcome screen to a title and three buttons
joepio Jul 12, 2026
9e8935b
Make skipping the recovery backup a deliberate, warned choice
joepio Jul 12, 2026
1a7ef82
Tell an over-quota drive apart from an unenrolled one
joepio Jul 12, 2026
d90c6df
docs: state the no-phone-home guarantee for self-hosters
joepio Jul 12, 2026
8ec3e72
Send the backup CTA to a sign-in form, not the sales page
joepio Jul 13, 2026
a0aa17a
Let a server push one of its drives to another server
joepio Jul 13, 2026
08278cf
Let a user ask their server to replicate a drive elsewhere
joepio Jul 13, 2026
ad1ccfc
Demo improvements, and planning for importer
joepio Jul 13, 2026
12491b5
fix: restore DID-aware website templates
joepio Jul 14, 2026
d6b20cc
feat: classify Atomic DID subject kinds
joepio Jul 14, 2026
5ffa7d1
fix: read creation metadata from genesis certificates
joepio Jul 14, 2026
3c84a9a
fix: make scoped search resilient to index lag
joepio Jul 14, 2026
c6f1d88
fix: stabilize collaborative browser flows
joepio Jul 14, 2026
b0bf559
refactor: remove unused WebSocket frame encoders
joepio Jul 14, 2026
f98d706
docs: document template drive configuration
joepio Jul 14, 2026
a89e857
docs: expand importer and browser assistant plans
joepio Jul 14, 2026
f19ee5e
style: apply Rust formatting
joepio Jul 14, 2026
c61e110
fix: derive `drive` from `parent` so moving a resource revokes inheri…
joepio Jul 14, 2026
e750a35
feat: drafts and suggestions as a fork of a resource
joepio Jul 14, 2026
5782b01
feat: Edit as draft / Merge draft / Open original in the actions regi…
joepio Jul 14, 2026
a34e2b0
fix: a fork must not inherit the original's ACL; show drafts in their…
joepio Jul 14, 2026
453fbb7
style: make the draft bar a bar, not a card
joepio Jul 14, 2026
55d73c9
fix: three-way merge so a draft can't revert a concurrent edit to the…
joepio Jul 14, 2026
5442f93
test: draft flow e2e; fix DraftBar change count frozen by React Compiler
joepio Jul 15, 2026
66bd09f
docs: record that Loro-container classes aren't draftable yet
joepio Jul 15, 2026
49c9f5e
feat: surface pending drafts on the original, so a reviewer finds the…
joepio Jul 15, 2026
14fc694
feat: CRDT body merge for document drafts
joepio Jul 15, 2026
ed176c9
feat: meeting agenda/minutes feature (integrated from codex/meeting-a…
joepio Jul 15, 2026
6844828
refactor: split Fork (edit an existing resource) from Draft (new unpu…
joepio Jul 15, 2026
faf503e
docs: update the drafts/forks design doc for the Fork/Draft terminolo…
joepio Jul 15, 2026
f5be356
test: fix e2e typecheck drift so `pnpm typecheck` passes in the e2e p…
joepio Jul 15, 2026
a072fc7
fix: bootstrap the meeting and forks ontologies into the client store
joepio Jul 15, 2026
eddaeba
feat: record meeting join/leave in the chat, like start/end
joepio Jul 15, 2026
551a555
feat: meeting panel polish — Notes link, subtle Leave, title-to-edito…
joepio Jul 15, 2026
d9ee37a
fix: resolve the personal drive via getResource, not a raw server fetch
joepio Jul 15, 2026
be0b1b4
Dashboard view planning #1234
joepio Jul 15, 2026
ebd3e48
docs: update auth, genesis, and websocket docs to match shipped v2 be…
joepio Jul 15, 2026
eb253ef
docs: add the dashboards proposal (user- and LLM-composable views)
joepio Jul 15, 2026
bceef2b
test: offline agent persistence — save then resolve an agent with no …
joepio Jul 15, 2026
e85a7c8
feat(desktop): read-only NFS virtual drive — mount your Atomic drives
joepio Jul 15, 2026
323d099
feat(desktop): start/stop the virtual drive from Settings
joepio Jul 15, 2026
a14d2c5
feat(desktop): mount the virtual drive from the app, no terminal
joepio Jul 15, 2026
4d692b3
feat(desktop): virtual drive write path — edit files, changes sync back
joepio Jul 15, 2026
081c977
feat(desktop): persist the virtual-drive fileid map (stable ids acros…
joepio Jul 15, 2026
f248c77
feat(desktop): cache directory listings so readdir paging isn't O(N²)
joepio Jul 15, 2026
ab0bb3d
perf(desktop): skip the virtual-drive commit when a file's bytes are …
joepio Jul 15, 2026
4ffe853
feat(desktop): content-defined chunking for large virtual-drive files
joepio Jul 16, 2026
cddff43
perf(desktop): make virtual-drive listings fast on large stores
joepio Jul 16, 2026
028c21c
feat(desktop): surface all resources in the virtual drive, scoped to …
joepio Jul 16, 2026
b3dbc68
perf(desktop): reconstruct-once read cache + VFS benchmarks
joepio Jul 16, 2026
0f1782a
feat(server): implement GET /drive-usage (per-drive storage) + test
joepio Jul 16, 2026
0d25836
refactor(data-browser): unify server connect/switch inline on the Syn…
joepio Jul 16, 2026
ae8dc07
feat(data-browser): working server switch, remove-server, and Node ID…
joepio Jul 16, 2026
a28a238
feat(data-browser): accept bare host in connect box + restore explainer
joepio Jul 16, 2026
61158b8
fix(lib): don't error-toast benign redundant-genesis commit drops
joepio Jul 16, 2026
11d58ff
test(server): fresh client reads a replicated resource after source i…
joepio Jul 16, 2026
3018cf9
fix(lib): scope connection status to the active server + Sync card re…
joepio Jul 16, 2026
7cd7c62
chore(data-browser): extract new Sync page strings
joepio Jul 16, 2026
d243495
refactor(data-browser): one stable server list, active one marked not…
joepio Jul 16, 2026
4503338
chore(data-browser): re-extract Sync strings after the stable-list re…
joepio Jul 16, 2026
4e660fe
perf(lib): make per_drive_usage O(drive) instead of O(store)
joepio Jul 16, 2026
44aa33f
chore: fix lint + format drift already on the branch
joepio Jul 17, 2026
f6a2801
chore(build): drop dependency debuginfo from the dev profile
joepio Jul 17, 2026
5c203ef
refactor(lib): Endpoint handlers are closures, built with a builder
joepio Jul 17, 2026
9808028
feat(server): a node describes itself as an Atomic Server resource
joepio Jul 17, 2026
5844897
refactor(lib): endpoints declare the params they need, and share one …
joepio Jul 17, 2026
59c2907
fix(server): version links point at a path that exists
joepio Jul 17, 2026
cea4c39
fix(lib): a version id names the state its change produced
joepio Jul 17, 2026
ad14f07
feat(server): versioning reads Loro history, not the commit log
joepio Jul 17, 2026
f2d0317
feat(flutter): server settings in the shared views
joepio Jul 17, 2026
c7a1bef
feat(data-browser): show a pairing code for the server your drives li…
joepio Jul 17, 2026
2886b9b
feat(flutter): read the pairing codes the other Atomic apps show
joepio Jul 17, 2026
6d68c6e
fix: a LAN address is a dev server, not a public one
joepio Jul 17, 2026
21837f1
fix(flutter): let debug builds talk to a dev server
joepio Jul 17, 2026
04b345a
fix(data-browser): offer the code, not a server URL, when your data i…
joepio Jul 17, 2026
0a1c576
fix(data-browser): stop offering a pairing code that can never authen…
joepio Jul 17, 2026
61fc7cf
chore: refresh lockfile and strings after the pairing-code revert
joepio Jul 17, 2026
e9aacc2
feat(flutter): offer this device's workspace to a server
joepio Jul 17, 2026
f75d2bb
fix(flutter): make the generated bridge compile as generated
joepio Jul 17, 2026
cc24567
fix(flutter): stop asking where to sync an identity that has nothing yet
joepio Jul 17, 2026
8c15ebf
docs: a sync & onboarding guideline, and make the clients point at it
joepio Jul 17, 2026
6b782d2
fix(sync): rights decide who may sync, not whether they are you
joepio Jul 17, 2026
6926e29
feat: a server is a device you can scan, and we call it one
joepio Jul 17, 2026
f1497af
docs: correct the guideline where it taught my mistake
joepio Jul 17, 2026
9b6971e
refactor(data-browser): say it once
joepio Jul 17, 2026
5b68c14
fix(data-browser): show the code on the screen that needs it most
joepio Jul 17, 2026
d7ae65d
fix(sync): a push is not a failure, and neither is being in sync
joepio Jul 17, 2026
0388a28
docs: record how the fixture hid the flow
joepio Jul 17, 2026
f80d148
fix(flutter): say what the sync did, not how much it imported
joepio Jul 17, 2026
5ac5e33
feat(server): /server says which devices it syncs with
joepio Jul 17, 2026
a346b17
fix(data-browser): signing in cannot end in somebody else's workspace
joepio Jul 17, 2026
3cd86c2
fix: a pairing code names its drive, and the scanner adopts it
joepio Jul 17, 2026
d0e80d4
fix(data-browser): sign out instantly, and stop treating the server r…
joepio Jul 17, 2026
69fc5a7
fix(sync): always hand a peer your own agent resource on connect
joepio Jul 17, 2026
dda8c45
fix(flutter): settings speaks the browser's language
joepio Jul 17, 2026
aa218e9
fix(data-browser): find the workspace once a paired device pushes it
joepio Jul 17, 2026
a9c3d1c
fix(flutter): one Devices panel, in the browser's order
joepio Jul 17, 2026
4ae3db2
feat: sign-in secret field — hidden, paste-and-go, with a Paste button
joepio Jul 17, 2026
bda4e2b
perf(flutter): sign in without waiting on Iroh discovery
joepio Jul 17, 2026
4d5063b
fix(flutter): one Devices list, and delete the peer UI it replaced
joepio Jul 17, 2026
1e876fd
feat(data-browser): show the server's paired devices in the Devices list
joepio Jul 17, 2026
ead0db2
test(server): merge integration tests into one binary
joepio Jul 17, 2026
683a25d
fix(lib): authorize relayed sync by owned drive, not peer identity
joepio Jul 17, 2026
f80025d
feat(server): add signed POST /forget-peer to disconnect a paired device
joepio Jul 17, 2026
91c01da
feat(data-browser): disconnect a paired device from the Sync page
joepio Jul 17, 2026
8a015e1
feat(flutter): fold QR pairing into one Devices list with richer cards
joepio Jul 17, 2026
397dcfb
feat(flutter): make the gallery-root title a drive switcher
joepio Jul 17, 2026
435b1d9
fix(lib): persist device identity and paired peers durably
joepio Jul 17, 2026
c061e8a
fix(flutter): invalidate canvas edit cache on remote strokes to stop …
joepio Jul 17, 2026
313d7f9
fix(flutter): merge store state before a stroke so concurrent edits d…
joepio Jul 17, 2026
abd9300
fix(lib): enable mDNS local discovery so same-LAN devices dial directly
joepio Jul 17, 2026
16e5d87
feat(flutter): persistent, copyable error toasts
joepio Jul 17, 2026
ded7f2d
build(flutter): 16 KB-align the Rust native library for Android
joepio Jul 17, 2026
0f74190
fix(flutter): white screen on canvas after a remote stroke
joepio Jul 18, 2026
f4af102
fix(flutter): store the agent secret in secure storage, not plaintext…
joepio Jul 18, 2026
f797905
fix(data-browser): declutter the mobile topbar and unify navbar buttons
joepio Jul 18, 2026
382dfa7
fix(sync): stop RBSR dropping subjects at a range's low end
joepio Jul 20, 2026
2d10b0d
test(sync): cover device sync across real process boundaries
joepio Jul 20, 2026
799eb1c
fix(flutter): keep a peer's stroke through a whole-list rewrite, and …
joepio Jul 20, 2026
f104f11
test(browser): cover the pairing helpers and the sync page
joepio Jul 20, 2026
c12c713
fix(browser): stop shipping a developer's portal override
joepio Jul 20, 2026
fc78080
style: cargo fmt
joepio Jul 20, 2026
ff6f6f4
docs: map test coverage, and the blind spots
joepio Jul 20, 2026
7122dfb
test(server): cover forgetting a paired device
joepio Jul 20, 2026
7fbd938
test(sync): reproduce the concurrent commit vs peer apply data loss
joepio Jul 20, 2026
0585cf2
fix(sync): stop a local edit and a peer update clobbering each other
joepio Jul 20, 2026
3b447c3
test(browser): cover pasting a pairing code
joepio Jul 20, 2026
c431e53
test(browser): cover paired-device cards and forgetServerPeer
joepio Jul 20, 2026
761b896
Content localization and translations i18n #1069
joepio Jul 21, 2026
0472714
Website template locale routing + DID import fix for i18n content loc…
joepio Jul 22, 2026
882e7b0
fix(demo): stop the guest identity flashing "Error loading resource"
joepio Jul 22, 2026
e295505
fix(browser): give the meeting side panel title its own transition tag
joepio Jul 22, 2026
fc0c464
fix(onboarding): don't send self-hosted users to a dev portal URL
joepio Jul 22, 2026
a438d35
rename(managed): call the hosted product AtomicServer.eu, not AtomicC…
joepio Jul 22, 2026
a576fd9
feat(browser): add @tomic/edit-mode, guest-editable local-first page …
joepio Jul 22, 2026
7ceaffc
feat(browser): add marketing site seed/apply scripts and a demo recorder
joepio Jul 22, 2026
fffbdbc
Bump to v0.41.0-beta.1, update changelog
joepio Jul 22, 2026
55c5607
Merge develop into did, pulling in 4 security hotfixes
joepio Jul 22, 2026
fbc2654
fix(ci): unpin Flutter Dagger image from a version 20+ releases behind
joepio Jul 22, 2026
01fa296
Revert the internalId server-managed-property check — breaks local-fi…
joepio Jul 22, 2026
4010427
test(flutter): mock the secure-storage channel for AtomicSession.save()
joepio Jul 22, 2026
478ea20
fix(ci): satisfy oxlint padding-line-between-statements in record-dem…
joepio Jul 22, 2026
5ce8529
fix(ci): mount two repo-root fixture files the Dagger JS container wa…
joepio Jul 22, 2026
7245532
fix(cli): handle LocalizedText in the interactive `new` prompt's data…
joepio Jul 22, 2026
728ae22
Hide genesis
joepio Jul 23, 2026
ea8b5fc
fix(data-browser): DOM prop leaks, missing keys, and New Table Enter-…
joepio Jul 23, 2026
276c33b
feat(browser): per-agent encrypted OPFS databases for the ClientDb
joepio Jul 23, 2026
8bb6b3c
feat(browser): add /app/new-drive route for the managed portal's "+ N…
joepio Jul 23, 2026
49a4435
fix(client-db): give lock-steal recovery a realistic settle budget
joepio Jul 23, 2026
2b96f30
fix(data-browser): restore the New Meeting quick-create button
joepio Jul 23, 2026
4c80d2b
fix(data-browser): move editor-render-phase state updates into effects
joepio Jul 23, 2026
971cec2
fix(lib): release the subject lock before after-commit handlers run
joepio Jul 23, 2026
4a44fca
fix(server): repopulate base models, not just JSON ontologies, on ATO…
joepio Jul 23, 2026
39b9a27
chore(deps): bump wasmtime, quinn-proto, crossbeam-epoch, plist to pa…
joepio Jul 23, 2026
59e86b7
fix(browser): patch 45 real npm vulnerabilities via scoped pnpm overr…
joepio Jul 23, 2026
8a4b473
fix(data-browser): Kanban view polish — icons, header pill, add-card …
joepio Jul 23, 2026
b4fd025
feat(data-browser): colorful mode — tint the app chrome with the main…
joepio Jul 23, 2026
f241952
feat(data-browser): unify the sidebar drive header
joepio Jul 23, 2026
9144050
feat(data-browser): dark mode for the static loading screen
joepio Jul 23, 2026
4f6fe05
feat(data-browser): p2p video & audio calls in the meeting panel
joepio Jul 23, 2026
8bcc0ba
fix(data-browser): merge kanban column header into one rounded card
joepio Jul 23, 2026
5e9add3
feat(data-browser): meetings start from their page, not the top bar o…
joepio Jul 23, 2026
e5e83ce
Create android-data-reuse.md
joepio Jul 23, 2026
f5c3027
Create emoji-cover-images.md
joepio Jul 23, 2026
d2a43d8
feat(data-browser): dark-aware theme-color metas for OS/browser chrome
joepio Jul 24, 2026
d12607a
fix(data-browser): only list origins that answer /server as known ser…
joepio Jul 24, 2026
e5edc3e
Emoji v1 #1235
joepio Jul 24, 2026
1665992
fix(server): qualify propvals filter clauses so `/search?filters=` ac…
joepio Jul 24, 2026
4f88ae2
fix(data-browser): guard slash-menu suggestion handlers against an un…
joepio Jul 24, 2026
bde6ff7
fix(lib): stop `_new:` placeholder resources from looping stuck-commi…
joepio Jul 24, 2026
f235561
Optional vector search
joepio Jul 24, 2026
3578d08
perf(lib): rework query execution and indexes — shallow rows, typed s…
joepio Jul 24, 2026
2ae326f
docs(perf): correct index-rework numbers with verified paired measure…
joepio Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
docs: a sync & onboarding guideline, and make the clients point at it
Three clients grew their own vocabulary for one concept — server, sync hub,
connection, node — and their own idea of what can reach what. That second
part is not a matter of taste: I shipped a pairing code for a server because
I assumed a server could be paired with, and it took a round trip through a
real phone to find out it cannot.

So write down what is true, once: the rules of reach (a server signs in as
its own agent and is never a pairing target; a browser tab is not a node and
holds nothing; connecting fetches but never offers), the words we use for
each thing, every account/device path someone can get into and whether it
works today, which file in each client twins which, and what is actually
tested versus verified by hand.

Both codebases' agent docs now open with a pointer to it, because the failure
mode is an agent changing one client's sync screen without knowing the other
exists.

Claude-Session: https://claude.ai/code/session_01VddwtxveM8Zqsf765aQSHY
  • Loading branch information
joepio committed Jul 17, 2026
commit 8c15ebfc8b31e75a844d36cfcfb6e0aa7a7c1c80
12 changes: 12 additions & 0 deletions browser/data-browser/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## Sync & onboarding — read first

The Flutter canvas app (`flutter/lib/atomic/`) is a client of the same system,
used by the same person. Before changing anything about signing in, servers,
pairing or sync, read
[`../../planning/sync-onboarding-ux.md`](../../planning/sync-onboarding-ux.md):
it holds the shared vocabulary, the rules of what can actually reach what (a
server is **not** a device you can pair with), every account/device path, and
the map of which file here twins which file in the Flutter app.

Change a sync screen here → change its twin there, and update that doc.

## Editing UI

When working on the data-browser, determine if you need to change or add UI, if so, read `./UI_COMPONENTS.md` for a list of existing reusable components.
Expand Down
12 changes: 12 additions & 0 deletions flutter/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Atomic Canvas Flutter — Agent Context

## Sync & onboarding — read first

The Dart in `lib/atomic/` is a client of the same system the data-browser
talks to, and the same person uses both. Before changing anything about
signing in, servers, pairing or sync, read
[`../planning/sync-onboarding-ux.md`](../planning/sync-onboarding-ux.md): it
holds the shared vocabulary, the rules of what can actually reach what (a
server is **not** a device you can pair with), every account/device path, and
the map of which file here twins which file in `browser/data-browser`.

Change a sync screen here → change its twin there, and update that doc.

## What This Is

A cross-platform infinite drawing canvas app, migrated from a Kotlin/Android + Jetpack Compose app at `../atomiccanvas`. The Flutter version targets Android, iOS, and Web from a single codebase.
Expand Down
3 changes: 3 additions & 0 deletions planning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@ scratch document. When a plan becomes obsolete, delete it.
| [`structural-problems-index.md`](./structural-problems-index.md) | 2026-05-28 audit: ranked open structural issues with per-item plan files. Covers React Compiler / Resource proxy mismatch, subscription unification, save-state signals, Loro-as-authority, subject typing, and remaining actor-message Arc-wrap. |
| [`nextgraph-interop.md`](./nextgraph-interop.md) | **Proposal:** read/edit `did:ng:` (NextGraph) resources via a pluggable, scheme-routed Store backend; use Atomic components chrome-free in NextGraph apps. Builds on the elfa-tables proof. |
| [`drive-reconciliation.md`](./drive-reconciliation.md) | **Proposal (2026-07-08):** replace the flat whole-drive VV hash with range-based set reconciliation (RBSR) so sync cost tracks the delta, not the drive; optional signed drive state root (reusing genesis `stateHash`) closes F1 + enables offline verification. Records the RBSR-over-hierarchy-Merkle and VV-leaves-first decisions before any build. |
| [`sync-onboarding-ux.md`](./sync-onboarding-ux.md) | **Guideline:** the language, the rules of what can reach what, every account/device path, where each client's logic lives, and what is tested. Read before changing a sync or onboarding screen in any client. |
| [`device-pairing.md`](./device-pairing.md) | **Proposal (2026-07-08):** one-scan pairing between a server and a phone/tablet — `atomic://pair` QR/deep-link envelope (`onboard` with secret now, channel-provisioned secret later), mDNS/pkarr as routing-only discovery, and a SaaS per-account device directory for zero-scan "sign in and it syncs". Resolves serverless-p2p OQ3, narrows OQ1/OQ4. |
| [`importers.md`](./importers.md) | **Analysis (2026-07-14):** importers for existing data — the LLM writes only a pure, sandboxed mapping function; the host owns acquire/parse/validate/preview/commit; schema validation is the feedback-loop oracle. Ontola-authored trusted importer skills (hash-pinned transform + verifiable fixtures, Notion export first) precede client publishing; promotion path to server-side connectors. |
| [`habits-app.md`](./habits-app.md) | **Proposal (2026-07-13):** habit tracker built strictly as an external app (`@tomic/lib`, plugin iframe view, code-first schema, assistant skill, Wear OS Flutter watch client) — append-only Completion event log for conflict-free counter taps; doubles as a dogfooding exercise whose gaps feed the SDK, plugin, and query plans. |
| [`atomic-assistant-browser-extension.md`](./atomic-assistant-browser-extension.md) | **Proposal (2026-07-14):** local-first Chromium extension using Atomic WASM/OPFS to read approved webpage context, preview and fill forms from scoped personal data, and persist existing `AiChat` resources; Free local pairing first, Vault/Server optional. |
| [`p2p-presence.md`](./p2p-presence.md) | **Proposal (2026-07-10):** carry ephemeral presence (cursors, viewing/following/typing) device-to-device over the Iroh live channel via the reserved `EPHEMERAL 0x40` frame and a server-side WS⇄peer bridge — never persisted. Same-agent (own devices) only; multi-user P2P presence deferred to `authorization-sync.md`. |
| [`meetings.md`](./meetings.md) | **Built (2026-07-14):** one Meeting-only resource with rich-text Agenda/Notes/Minutes, child chat, persisted lifecycle, a dedicated page, and an explicit prepare-then-start flow. Clean cutover; no backwards compatibility. |
| [`dashboards.md`](./dashboards.md) | **Proposal (2026-07-15):** user- and LLM-composable dashboards — `Dashboard` resource + standalone `Block` resources (embedded View, stat, constrained-Vega-Lite chart, text) with JSON grid layout; `create_dashboard` tool mirroring `create_table`; blocks reusable later as DocumentV2 embeds. |
| [`social-apps.md`](./social-apps.md) | **Requirements (2026-07-17):** platform gaps for social-network-shaped apps (recipes app as driver): generic `atomic_flutter` SDK extraction, mobile blobs, push notifications, feed primitives (client fan-out now, hub feed endpoint later), invite-link onboarding, web share views, groups, moderation-by-display-filtering. Companion to `zones.md`. |
| [`zones.md`](./zones.md) | **Proposal (2026-07-17):** any ACL-bearing resource is a "zone" — the single unit of access, sync, quota, keys, and (opt-in) announce; rights live only on zone roots, `subject → zone` is a derived index (drive stamp leaves signed state), authority is evaluated at commit time via `AuthImpact` replay, discovery is one pkarr record per agent. "Share a doc" = promote it to a zone. |
| [`drafts-and-suggestions.md`](./drafts-and-suggestions.md) | **Active (2026-07-15):** two generic capabilities, no Website-specific path. A **Fork** (`Fork` class + `originalSubject`) proposes a change to an existing resource and merges onto it; a **Draft** is unpublished new content defined by location (a resource in a private Drafts folder) and publishes by moving. Visibility is location; needs no deny rule. Milestone 11 (headless CMS): #467, mechanism half of #1000. |

Protocol reference lives in the public docs: [`docs/src/websockets.md`](../docs/src/websockets.md).
Expand Down
128 changes: 128 additions & 0 deletions planning/sync-onboarding-ux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Sync & Onboarding UX

How we talk about sync, what can actually reach what, and which paths exist.
Read this before changing any sync/onboarding screen in **any** client — the
same person meets several of them, and should not have to learn each one.

Applies to: the data-browser (browser tab), the data-browser in Tauri
(desktop/mobile), the Flutter canvas app, and atomic-server.

---

## 1. What can reach what

Most UX mistakes here come from getting this wrong. It is not symmetric.

| From → to | How | Hard constraint |
| --- | --- | --- |
| your device ↔ your other device | Iroh peer sync, started by scanning a pairing code | **Same account only.** `is_same_agent_as_ours` (`lib/src/sync/peer.rs`) fails closed and says so |
| your device → an always-on machine | push (replication) | needs write rights there, signed as *your* agent |
| an always-on machine → your device | WS subscribe + fetch | the device must know its address |
| browser tab ↔ anything | only through an always-on machine | a browser tab **is not a node**: it cannot pair, and holds nothing |

Three consequences that keep being forgotten:

- **An always-on machine is not one of your devices.** It signs in as its own
agent. It can never be a pairing target — a code for it is refused by every
device that scans it. (Learned by shipping one. Don't.)
- **A secret restores who you are, not what you have.** Signing in on a new
device gets you an identity and an empty workspace. Something still has to
carry the data.
- **Connecting is not pushing.** Connecting to a machine fetches a workspace
you lack; it never offers the one you have. A workspace made before you
connected anywhere exists in exactly one place until someone pushes it.

## 2. Language

The same concept has been called a server, a sync hub, a connection and a node
— in three clients. Pick one word and keep it.

| Say | Not | Why |
| --- | --- | --- |
| workspace | drive, store | "drive" is our schema's word, not a person's |
| your devices | peers, nodes | a node is an implementation detail |
| always-on machine, or its address (`atomicserver.eu`) | server, hub, sync hub | name the thing, not the category — "server" makes it plumbing to learn |
| pairing code | envelope, node DID, `atomic://pair` URI | it is a code you scan |
| sync | replicate, reconcile, promote | one verb, whatever the transport |

Rules of thumb:

- **Name what the person wants, not the mechanism.** "Where your data is",
not "Sync hub URL". The address is the answer, not the concept.
- **Ask for plumbing only when there is plumbing to do.** Nothing that has no
data yet should be asked where to sync it.
- **A dead end is not a question.** Do not offer a box to type into if no
answer exists — the workspace made on a phone has never been on a machine,
so "connect the machine it lives on" cannot be answered.
- **Say where things are, plainly.** "This code reaches `localhost:9883`, not
this browser." Mechanism belongs in a footnote, never in the headline.
- **A state is not an error.** No machine connected, unreachable, data
elsewhere — these are normal, and read as normal.

## 3. The paths

Every combination someone can actually get into. "Crosses by" is the only step
that moves data.

| Start | Then | Crosses by | Works today |
| --- | --- | --- | --- |
| new account in browser | mobile / desktop later | device connects the same address, fetches | ✅ |
| new account on Tauri desktop | browser later | desktop pushes workspace up, browser reads it | ✅ `promoteLocalDrive` |
| new account on Tauri desktop | Tauri mobile later | pairing code, either direction | ✅ |
| new account on Flutter mobile | Tauri desktop later | pairing code | ⚠️ untested across the two apps |
| new account on Flutter mobile | another Flutter mobile | pairing code | ✅ |
| new account on Flutter mobile | browser later | mobile pushes workspace up, browser reads it | ✅ `syncDriveToServer` |
| new account anywhere | atomicserver.eu later | device pushes up, then everything reads from there | ⚠️ untested |
| new account in browser A | browser B, no machine in common | **nothing crosses** | ❌ by design — say so |

The last row is the one to get right in copy: two browser tabs with no machine
between them cannot reach each other, ever. Neither is a node.

## 4. Where the logic lives

Keep these in step. A change to one is usually a change to its twin.

| Concern | Browser | Flutter |
| --- | --- | --- |
| sync screen | `data-browser/src/routes/SyncRoute.tsx` | `flutter/lib/atomic/widgets/server_settings_section.dart` |
| settings shell | (same route) | `flutter/lib/atomic/widgets/agent_settings_dialog.dart` |
| onboarding, data elsewhere | `data-browser/src/views/getting-started/ConnectDeviceStep.tsx` | `flutter/lib/screens/login_screen.dart` |
| pairing code, show / scan | `components/PairingCode.tsx`, `ConnectToDeviceForm.tsx` | `flutter/lib/screens/pair_screen.dart` |
| pairing code, format | `browser/lib/src/pairing.ts` | `pair_screen.dart` (`_parsePairingUri`) |
| URL rules (scheme, local address) | `data-browser/src/helpers/serverUrl.ts` | `flutter/lib/atomic/server_url.dart` |
| what a machine says about itself | `data-browser/src/helpers/managedServer.ts` | `flutter/lib/atomic/server_info.dart` |
| push a workspace up | `browser/lib/src/store.ts` (`promoteLocalDrive`) | `AtomicClient.syncDriveToServer` |

Shared, and authoritative over all of the above:

- `lib/src/sync/peer.rs` — pairing, AUTH, the same-account rule
- `lib/src/sync/replicate.rs` — `replicate_drive_to_remote`, the push
- `server/src/plugins/server_info.rs` — `/server`, what a machine says it is
- [`device-pairing.md`](./device-pairing.md) — the code's wire format
- [`unified-sync.md`](./unified-sync.md) — where the transports are heading

## 5. What is tested

| Level | Covers | Where |
| --- | --- | --- |
| Rust unit | pairing AUTH, same-account refusal | `lib/src/sync/` |
| Rust integration | replication, a fresh client reading a replicated workspace | `server/tests/replicate.rs` |
| Rust integration | `/server`, `/drive-usage` | `server/src/tests.rs` |
| Dart unit | URL rules, pairing code parsing, signing parity with Rust | `flutter/test/atomic/` |
| Browser e2e | two servers, sync between them | `browser/e2e/` |

Gaps worth knowing, rather than rediscovering:

- **No test crosses two clients.** Every path in §3 is verified by hand. The
Flutter↔Tauri pairing row has never been run at all.
- **Dart signing is checked against Rust by golden vectors**
(`lib/src/genesis_test_vectors.json`), not by a live handshake. That caught a
real bug (base64 alphabet); it would not catch a header the server ignores.
- **The push path has no Dart-side test.** `syncDriveToServer` is covered by
Rust replication tests underneath, and nothing above.

---

*If you change vocabulary or a flow here, change it in both clients and update
this table. A person moving from the phone to the laptop should not notice
they moved.*