diff --git a/docs/dev/storage.md b/docs/dev/storage.md index 48bf17f..dcc7d25 100644 --- a/docs/dev/storage.md +++ b/docs/dev/storage.md @@ -195,6 +195,7 @@ pub trait BackendProvider: Send + Sync { fn endpoint_placeholder(&self) -> &'static str; fn sign_in(&self) -> SignIn; fn normalise_endpoint(&self, input: &str) -> Result; + fn upgrade_endpoint(&self, stored: &str) -> Option; // defaulted: None fn account_for(&self, endpoint: &str) -> Result; // defaulted fn connect(&self, conn: &Connection) -> Result, RemoteError>; } @@ -215,6 +216,18 @@ pub enum SignIn { Nextcloud provider upgrades `http://` to `https://` here (`NFR-SEC-3`); the folder provider canonicalises the path, so two spellings of one directory do not become two accounts indexing the same photographs. +- **`upgrade_endpoint` is for accounts already saved,** and is not a second + call to `normalise_endpoint`: the folder provider's needs the path to exist, + so running it on every launch would fail a library on an unplugged disk. + `AccountStore::upgrade_endpoints` runs it at launch; only Nextcloud answers, + rewriting an `http://` account an older build saved to `https://` + (#65). The keyring entry is filed under the endpoint, so the secret is + copied across before the record changes, and a move that would change + `namespace()` is refused rather than performed. Below both, the Nextcloud + client sets `https_only`, so no URL it sends — a typed one, the login flow's + poll endpoint, a redirect — can carry the app password in the clear, and + the login flow keeps the address the user typed rather than the server's + idea of its own URL. - **`connect` is synchronous and cheap.** It validates configuration and builds a client; it does not talk to the remote. Workers call it per task. - **`SignIn` is a shape, not a method.** It would be tidier to expose