Say where an uploaded original lands
FR-NC-7 specifies how bytes travel and deliberately has no opinion about
where they go, and nothing else said either — so the one thing a photograph
needs on arrival, a folder, was unwritten.
FR-NC-7a gives it `{yyyy}/{yyyy}-{mm}-{dd}`, and two consequences the
transport mechanics do not supply on their own: expansion is a pure function
of capture metadata, so two devices computing a destination for the same
frame agree; and the template governs placement on upload only, because the
remote library is reachable by other clients and restructuring it under them
is not ours to do.
FR-NC-7b joins import to upload. A move-import must not erase the card until
the upload is confirmed — a card erased against an in-flight transfer is the
one failure in this application with no undo.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -634,6 +634,35 @@ resume or `DELETE` stranded uploads on startup.
|
|||||||
Small files (sidecars) use **bulk upload** via `POST /remote.php/dav/bulk` with a
|
Small files (sidecars) use **bulk upload** via `POST /remote.php/dav/bulk` with a
|
||||||
`multipart/related` body, allowing hundreds of edit-graph sidecars in a single request.
|
`multipart/related` body, allowing hundreds of edit-graph sidecars in a single request.
|
||||||
|
|
||||||
|
**FR-NC-7a — Remote layout.** FR-NC-7 says how bytes travel; this says where they land. An
|
||||||
|
uploaded original shall be placed under the account's library root in a directory expanded from a
|
||||||
|
date template, defaulting to `{yyyy}/{yyyy}-{mm}-{dd}` — one directory per year, one per capture
|
||||||
|
day beneath it. The template is configurable per account and uses the same token vocabulary as
|
||||||
|
export naming (FR-EXP-6), so `{date}` means the image's **capture** date and never today's; an
|
||||||
|
image with no readable capture time falls back to file mtime, and the fallback is visible in the
|
||||||
|
import report rather than silent.
|
||||||
|
|
||||||
|
Two consequences the mechanics do not give for free:
|
||||||
|
|
||||||
|
- **The path is derived, not remembered.** The same image uploaded twice from two devices must
|
||||||
|
compute the same destination, so expansion is a pure function of capture metadata and the
|
||||||
|
template — never of local library layout, which differs per device.
|
||||||
|
- **Existing trees are not restructured.** An image already present remotely stays where it is.
|
||||||
|
The template governs placement on upload only; DarkRoom shall not move server-side files to
|
||||||
|
conform, because the remote library is also reachable by other clients (§1.3).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Duplicate detection (FR-CAT-11) runs against the catalog before upload, so re-inserting a card
|
||||||
|
that was already imported transfers nothing.
|
||||||
|
|
||||||
**FR-NC-8 — Edit metadata sync.** Edit graphs sync bidirectionally as sidecars, one per image,
|
**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
|
named deterministically from `oc:fileid`. Each sidecar carries a monotonic revision counter, a
|
||||||
per-device UUID, and a last-edit timestamp.
|
per-device UUID, and a last-edit timestamp.
|
||||||
|
|||||||
Reference in New Issue
Block a user