Import into the library, which is on the server

There was a local destination, defaulting to ~/Pictures, and an "upload" switch
that could be turned off. That was wrong twice over. DarkRoom's library *is* a
folder on a Nextcloud server (FR-NC-6) — there is no local library — so a
user-chosen local destination built a second pile of photographs that no view
in the application ever lists, and made "where did my import go" a question
with two answers.

An import now has exactly one destination and the page asks nothing about it.
With no account there is nowhere to go at all, so Import is refused rather than
quietly filling a folder.

What lands on the device is a staging copy in a directory the app owns, the
same shape `export` uses for its outbox and for the reason its module docs
give: staging first is the only path, not a fallback for being offline. The
bytes have to reach disk before the network — streaming a card straight to the
server would let a move-import erase a card against an in-flight upload, and
would make importing impossible with no connection (FR-NC-10). A staged file is
removed once the server confirms it; one that is not confirmed stays queued, and
the next import drains it.

And the rule that was stated but never enforced: `retirable` was reported and
`dr_ingest::retire` was never called by anything, so a move-import silently
behaved as a copy. The card is now emptied by the worker, of exactly those
photographs the *server* has confirmed — not those merely written here, because
the staging copy is removed moments later and anything unconfirmed would then
exist nowhere at all.

FR-NC-7b said "copied locally first ... then queued for upload", which is a
staging area; it has been rewritten to say so in terms that do not also permit
what was built.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-22 21:09:26 +02:00
co-authored by Claude Opus 5
parent ce666c768e
commit d04087af83
8 changed files with 336 additions and 104 deletions
+23 -6
View File
@@ -654,14 +654,31 @@ Two consequences the mechanics do not give for free:
Sidecars follow their image, not the template: they are named from `oc:fileid` (FR-NC-8) and live
beside the file they describe.
**FR-NC-7b — Ingest to remote.** Import (FR-CAT-10) and upload (FR-NC-7) shall compose: a card
import may target a Nextcloud library, in which case files are copied locally first, verified by
checksum, and only then queued for upload. The local copy is not deleted on a move-import until
the upload is confirmed — a card erased against an in-flight upload is unrecoverable, which is the
one failure in this app with no undo.
**FR-NC-7b — Ingest to remote.** Import (FR-CAT-10) and upload (FR-NC-7) compose, and the library
an import targets is **always** the remote one. There is no local library for a card to land in:
FR-NC-6 puts the library on the server, so an import has exactly one destination and the interface
shall not offer a choice of another.
What lands on the device is a **staging copy**, in a location the app owns, and it is not a
library: no view lists it, and it is removed once the server confirms the file. A staged file the
server did not take remains queued, and a later import drains the queue. An import with no
reachable server therefore succeeds and defers, rather than failing (FR-NC-10); an import with no
*account* has nowhere to go at all and shall be refused.
The bytes shall reach the device before they reach the network. Streaming a card straight to the
server would make a move-import erase a card against an in-flight upload, and would make importing
impossible offline.
**On erasing the card.** A move-import shall delete from the card only those photographs the
**server has confirmed** — not those merely written to the staging copy, since that copy is removed
as soon as the upload succeeds and would otherwise be the only remaining copy. Anything that does
not upload keeps its card copy. A card erased against an unfinished upload is unrecoverable, which
is the one failure in this app with no undo.
Duplicate detection (FR-CAT-11) runs against the catalog before upload, so re-inserting a card
that was already imported transfers nothing.
that was already imported transfers nothing. Where the catalog cannot answer — a file already in
the destination folder, locally or on the server — the folder's own listing shall answer instead,
so a re-import neither duplicates nor renames what is already held.
**FR-NC-8 — Edit metadata sync.** Edit graphs sync bidirectionally as sidecars, one per image,
named deterministically from `oc:fileid`. Each sidecar carries a monotonic revision counter, a