Validation run 2026-09-14¶
Run of 2026-09-14, completing early on 2026-09-15 (UTC). Scenario outcomes, platform coverage and measurement limits for the 1.0.0 server on the Compose route class. The operational account of the run (how it was driven, how the devices and vaults were arranged, what happened on the network path) is held privately by the maintainer and is not part of this record (requirement 11).
Operator¶
The maintainer, with agent assistance for the steps that need no human. Some steps -- a device passcode, an operating-system permission prompt, a host firewall decision -- can only be answered by a person, and a person answered them. The operating account is private.
Route¶
The Compose route (deploy/compose, docs/validation.md V15 and
docs/server.md): the release image by digest, verified before start, behind
the route's own TLS terminator with a private certificate authority, on a
private name, published only on the chosen bind address. No tunnel, no public
DNS record, no public route. The deployment's configuration is private.
The reference route was not exercised in this run.
Devices¶
Platform coverage of this run, by role. Hardware, OS versions and the device arrangement are private.
| Role | Platform | Obsidian | Plugin |
|---|---|---|---|
| desktop, paired first | macOS | 1.13.7 | 0.1.18 from the community directory |
| phone, paired second | iOS | not recorded during the run | 0.1.19 from the community directory |
Server: obsyncd 0.1.19, release commit e47e3d4.
The phone's Obsidian version is not recorded during the run and is left that
way. docs/validation.md requires at least 1.12.4 on each device, and the
phone installed 0.1.19 from the community directory, which root
versions.json offers only to an Obsidian at or above that floor -- but that
is an inference about what the app must have been, not the number the run
observed. Reading it off a device now would record today's version as though
it were the run's. An unrecorded field says so.
Scenarios¶
Every scenario in docs/validation.md, in its own row, as
docs/validation-runs/README.md requires. Silence is not a pass, so a
scenario nobody ran says not attempted and nothing else.
| Scenario | Result | Evidence |
|---|---|---|
| production-path install | pass | both devices installed the listed plugin through Settings -> Community plugins |
| V1 setup on the first desktop, recovery phrase shown | pass | the setup token was accepted, the device enrolled, the 24-word phrase shown once, and the device listed |
| V2 pair a second device from the desktop | pass | a one-time code was entered on the phone, approved by name on the desktop, and the sealed envelope delivered; about one minute end to end. One phone only: the iPad and Windows halves of this scenario had no device in this run |
| V3 edits both ways | pass | a note created on the desktop appeared on the phone, and a line appended on the phone appeared on the desktop, each within a few seconds as observed rather than instrumented, and between the two devices present rather than the four the scenario names |
| V4 rename and move a populated folder | not attempted | unclaimed by this run; the rename defect issue #96 was still open when it ran and shipped in 1.0.4, proven in the 2026-09-21 run |
| V5 offline conflict on two devices | not attempted | |
| V6 a 2 GiB image on macOS | not attempted | |
| V7 a 20 GiB archive, killed mid-upload | not attempted | the retransmission bound is unproven and is named in the changelog's known limits |
| V8 delete and restore from history | not attempted | |
| V9 revoke a device | not attempted | |
| V10 restart the server mid-sync | not attempted | |
| V11 fill the blob volume to the watermark | not attempted | |
| V12 scrub with one blob corrupted by hand | not attempted | unproven on real devices and named in the changelog's known limits |
| V13 off-LAN over a private path | not applicable | this route class has no private route of its own |
| V14 dashboard at 390 px | not attempted | the generated dashboard link drops a non-default port, so the phone never reached the dashboard to measure it (see findings) |
| V15 Compose path from scratch, phone paired over the LAN | pass | this run IS that route: deploy/compose from scratch, the private root exported and trusted on each device, the phone paired over the LAN, and nothing published beyond the chosen bind address -- no provider, no public hostname, no port reachable from the internet |
| V16 native credential persistence across restart | not attempted | |
| native update 0.1.18 -> 0.1.19 | not attempted | the desktop stayed on 0.1.18 for the run |
What was not validated¶
Not attempted: V4 through V12, V14, V16, and the native update on the desktop. Not applicable: V13 for this route class. The reference route, the iPad and Windows had no device in this run, so nothing here speaks for them. Platform coverage: one macOS desktop and one iOS phone; iPad, Windows, Android and Linux had no device in this run.
Privacy evidence¶
- Every sync endpoint refused unsigned requests:
/v1/changes401, the file, device and dashboard API paths 404, a malformed chunk path 400./readyzanswered withCache-Control: no-store,X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Referrer-Policy: no-referrer. Plain HTTP on the TLS port was rejected. - The server log for the whole run shows exactly two device identities making
signed requests, and every unsigned probe with
decision=missing_auth,not_foundorbad_request. - The pairing sequence in the log: claim, repeated
not_approvedwhile the desktop had not yet approved,device_activated ... decision=approved, then one envelope fetch. The vault key crossed the network only inside that device-sealed envelope; the server logs the fetch, never the key.
Findings¶
Both are tracked as issue #68.
- The desktop plugin's "Open dashboard" opens
<host>/login?token=...with neither the scheme nor the configured HTTPS port, so on a non-default port the browser reports the server not found. - The Compose route's TLS terminator redirects HTTP to HTTPS at port 443 rather than the configured HTTPS port: its site address is the bare hostname, so the port the deployment actually publishes is not in the redirect it issues. The server itself never redirects; TLS is outside the process (requirement 7).
Both concern generated URLs on non-default ports; neither affects sync
correctness or privacy. Generic failure classes and fixes for what a device
reports are on docs/troubleshooting.md.
Captures¶
No capture of this run is published. The maintainer holds the run's captures privately; every row above states what was observed, so the row stands on its own.