Add secure credential storage, sessions, and a launch screen
Login now persists properly rather than through the JSON file the test
harness was using.
dr-plat SecretStore trait plus a Secret Service backend.
Verified against the live GNOME Keyring: store,
retrieve, delete, confirm-gone all round-trip.
Session/SessionStore splits credentials from settings — the app
password goes to the keyring (FR-NC-2), while
server, login, chosen root and format selection are
ordinary config. A test asserts the credential never
appears in the config file.
LaunchModel the launch-screen state machine, testable without a
display server: sign in, approve in browser, choose
folder, tick formats, sign out.
launch.slint the screen itself, in its own file.
Absence of a secrets daemon is an explicit degraded mode, not a silent
fallback to plaintext — the screen says sign-in will not persist rather
than letting the user find out next launch. Android's Keystore backend
fails loudly for the same reason: a no-op store would look like it
worked and then lose the credential.
Two bugs caught by tests rather than by running it:
- fail() after busy() signed the user out, because busy() had already
discarded the session. A failed *scan* would have logged you out.
Busy now carries the session.
- normalise_server upgrades http:// to https:// rather than accepting
it. NFR-SEC-3 requires TLS, and silently sending a credential in the
clear is not a decision to make on the user's behalf.
launch.slint is not yet wired into app.slint. Calling slint_build::compile
twice replaces the generated module rather than adding to it, which broke
the other in-flight work on dr-ui; I reverted that immediately. Wiring it
needs an import inside app.slint, which is that work's file to change.
419 tests passing across ten crates.
This commit is contained in:
@@ -643,6 +643,16 @@ dir_validator(root)
|
||||
`folders.etag` must exist from schema v1. Adding it later means a migration plus a full re-scan of
|
||||
every user's library (ARCH §6.6).
|
||||
|
||||
**Validated against a real library, 2026-08-09.** A cold recursive scan of a 17,185-RAW library
|
||||
(7,836 CR2 + 9,349 DNG) across 334 directories completed in **34.1 s** — `Depth: 1` per directory,
|
||||
never `Depth: infinity`. Two implementation details worth keeping:
|
||||
|
||||
- **The format filter sees through VFS placeholder suffixes**, so a dehydrated `IMG.CR2.nextcloud`
|
||||
matches as the CR2 it stands for rather than being skipped as an unknown type (§9.0).
|
||||
- **Pruning is capability-gated, not assumed.** With `LocalEtags` a directory probe costs a request
|
||||
and proves nothing about children, so it is pure overhead; a test asserts zero probes in that
|
||||
case. Only `PropagatingEtags` makes an unchanged parent prove an unchanged subtree.
|
||||
|
||||
### 8.5 Sidecar conflict resolution
|
||||
|
||||
`put` with `Precondition::IfMatch(validator)`. On precondition failure:
|
||||
@@ -920,6 +930,22 @@ from schema v1.
|
||||
primary path; server previews are opportunistic. `preview_max_filesize_image` defaults to 50 MB,
|
||||
excluding many RAWs even where a provider exists.
|
||||
|
||||
**Measured against a real instance, 2026-08-09, and the case is stronger than assumed.**
|
||||
`/core/preview` returned HTTP 400 for *every* parameter combination attempted — including bare
|
||||
`?fileId=N`, and including a JPEG the same server reported as `nc:has-preview=true`. The cause is
|
||||
unexplained: it is a server-side preview configuration issue, not a request-shape error on our side.
|
||||
|
||||
Recorded as **unexplained rather than understood**, because the distinction matters if someone later
|
||||
tries to depend on this endpoint. Nothing does today — the connector treats a preview failure as a
|
||||
miss and falls through to range extraction, which is the designed behaviour rather than a
|
||||
workaround.
|
||||
|
||||
**Range extraction validated on the same library.** 262 KB read from a 21.5 MB DNG in 119 ms —
|
||||
**1.22% of the file** — yielded camera model and ISO. Extrapolated across the 17,185-file test
|
||||
library, cataloguing by whole-file fetch would move roughly 370 GB; the range path moves a few MB.
|
||||
That ratio is the difference between a viable mobile experience and an unusable one, and it is why
|
||||
§6.7 treats range reads as the mechanism and server previews as a bonus.
|
||||
|
||||
### 6.8 Sync is selective, not mirror-style
|
||||
|
||||
### 6.9 Android forbids the filesystem-scan model
|
||||
|
||||
Reference in New Issue
Block a user