Concepts
Media
Image upload model, format and quota rules, rights and AI provenance, signed bytes.
Media
Tidenda stores tenant-uploaded images as first-class
documents: one core/image per image, with the
bytes in object storage and the metadata, rights, and provenance
in a collaboratively-edited document. This page describes the
contract integrators meet - what an upload looks like, what
formats are accepted, how rights and AI provenance are modelled,
and the read surface for downstream consumers.
What an image is
An image in Tidenda is one document plus one set of bytes. The document carries the editorial metadata (caption, alt text, copyright, photographer, restrictions, AI provenance, the signing record) and lives in the same workflow machinery as articles and planning items. The bytes live in tenant-scoped object storage and never cross a tenant boundary. The document references the bytes by stable URL.
Re-uploading edited bytes produces a new document. There is no in-place byte replacement and no destructive edit. If you want a cropped or colour-corrected variant, that is a separate image with its own id, its own signature, and its own rights record.
Upload model
Uploads go directly to object storage. The client requests a short-lived signed PUT URL from the platform, uploads the bytes straight to that URL, then confirms the upload by posting the extracted metadata. Bytes never traverse the platform's API servers.
The flow has four steps:
- Allocate. Client posts an intent
(
filename,mimeType,size,contentHash, declared variants) to the upload-request endpoint. The platform enforces format and quota, hands back an image id plus signed PUT URLs for the original and each declared variant. A signed URL expires within minutes - it's not a long-term handle. - Upload. Client PUTs the bytes to the signed URLs. Failed PUTs can be retried by requesting a fresh URL; partial uploads cost nothing on the platform side.
- Finalize. Client posts the extracted metadata (EXIF /
XMP / IPTC fields, dimensions, content hash, optional C2PA
manifest) to the finalize endpoint. The platform creates the
core/imagedocument, indexes the dedup row, and increments the tenant's storage tally. - Sign. The platform signs the original bytes with the
tenant's signing key and writes the signature alongside the
bytes. The signature also lands on the document's
meta.signature. See Signing.
If a finalize arrives without the full set of derived variants
(thumbnail, preview, delivery), a background worker decodes the
original and backfills the missing variants. The document is
marked processingStatus: 'pending' until the worker completes.
Deduplication
Each image carries a SHA-256 hash of the original bytes
(meta.contentHash). Within a single tenant, a hash collision
short-circuits the upload: the allocate response returns the
existing image's id with isDuplicate: true and no PUT URLs.
The caller can link the existing id to additional assignments
without uploading bytes a second time.
Hashes do not cross tenant boundaries. Two tenants holding the same bytes hold two separate documents under two separate storage prefixes.
Supported formats
| Format | MIME | Accepted |
|---|---|---|
| JPEG | image/jpeg |
yes |
| PNG | image/png |
yes |
| WebP | image/webp |
yes |
| AVIF | image/avif |
yes |
| GIF | image/gif |
yes |
| HEIC / HEIF | image/heic, image/heif |
yes |
TIFF, camera RAW (image/x-canon-cr2, ...) |
no |
HEIC support is part of the contract - phone uploads work without an intermediate transcode. TIFF and RAW are intentionally rejected to keep storage and processing predictable; convert upstream and submit the result.
Caps
| Cap | Default |
|---|---|
| Per-image size | 75 MB |
| Per-tenant total storage | 100 GB |
| Files per upload batch | 50 |
The per-tenant cap is administrator-managed. A tenant cannot raise its own cap; contact the platform operator.
Variants
Each image carries up to four variants in object storage. The original is the source of truth; the others are derived for faster reads.
| Variant | Width | Format | Purpose |
|---|---|---|---|
original |
source | source | The bytes the rights record covers. |
thumb |
256w | WebP | List rows, picker tiles. |
preview |
1024w | WebP | Editor figures, modal previews. |
delivery |
source | JPEG | Downstream publishing path. |
The browser-side upload pipeline normally produces thumb,
preview, and delivery during decode; HEIC or any decode
failure falls back to a server-side worker, which fills the
gaps from the original. Until variants land, the document's
meta.variants array is the source of truth for "which
variants exist right now".
Reading bytes
Bytes are reached through a stable URL pattern:
GET /api/images/<id>/<variant>
The platform responds with a 302 redirect to a short-lived
presigned URL on the underlying storage. The redirect target
expires within minutes; clients should follow the redirect
immediately, not cache it. The /api/images/<id>/<variant>
URL itself does not expire.
Anyone authorised against the owning tenant can read any variant. Cross-tenant reads are refused at the auth layer before a presigned URL is issued.
Rights model
Three structured fields capture image rights:
| Field | Maps to | Used for |
|---|---|---|
copyright |
IPTC dc:rights |
Attribution line ("(C) 2026 Jane Doe"). |
instructions |
IPTC photoshop:Instructions |
Provider directives ("Free for editorial use during Q2 2026."). |
usageTerms |
IPTC xmpRights:UsageTerms |
Formal terms ("Editorial use only. No derivatives."). |
Plus a server-computed flag:
| Field | Value |
|---|---|
restrictions |
true when instructions is set, or usageTerms is set, or aiGenerated is true. |
The editor and the media archive surface a warning marker on
any image where restrictions is true; the hover popover
shows the underlying instructions and usageTerms text.
Integrators that surface images downstream should mirror this
treatment - the editorial intent is to make restrictions
visible at the moment of use, not hidden in a sidebar.
Provenance
AI generation
meta.aiGenerated is a tri-state:
| Value | Meaning |
|---|---|
true |
Image is AI-generated. UI surfaces a persistent badge. |
false |
Explicitly disclaimed. |
absent |
Unknown. |
The platform sets aiGenerated: true from incoming metadata or
C2PA assertions; tenants can also flip the flag manually. The
flag propagates into the computed restrictions so a warning
attaches by default even when no rights text accompanies it.
C2PA
The platform preserves C2PA manifests that accompany an
upload but does not issue its own. A preserved manifest is
recorded under meta.c2paManifest with the original issuer and
claim generator (free text - the platform does not maintain a
trust list for C2PA issuers). The raw manifest is stored
alongside the bytes for downstream verifiers that want to
re-validate the chain.
Tidenda signatures
Independent of any C2PA chain, the platform signs the original
bytes with the tenant's signing key. The signature lives on
meta.signature (alg, keyId, sig) and as an
original.sig sidecar in storage. Verification follows the
same recipe as snapshot signatures with one change: the
verified bytes are the original image bytes prefixed with
the domain separator "void-image-v1\0". See the signing
guide.
GDPR and deletion
| Concern | Default |
|---|---|
| GPS in EXIF | Stripped from the delivery variant by default. The original retains it for the rights record. |
| Hard delete | Available to organisation administrators only. |
| Tenant purge | Removes every image's bytes, document, dedup row, and signature on tenant teardown. |
There is no "delete bytes but keep the record" mode. Deleting an image deletes everything attached to it; downstream consumers should treat the snapshot they signed against as the durable historical record.
Document shape
For the wire shape, see core/image in Document formats.
Related pages
- Document formats - the envelope and other types.
- Signing - signature verification for both snapshots and original-byte signatures.
- Webhooks - events for the
core/imagedocument. There are no separate "image upload" events; the document's transitions emit the same shape any other document type does. - Security - tenant isolation, signing-key custody, deletion guarantees.