Files
ImageApi/CONTEXT.md
T
Cameron Cordes e84ac82f86 ADR-0002: owner defaults live in the DB row; .env keeps deployment config and secrets
Records the config boundary the #127 owner-default columns establish:
.env = boot-time deployment config + secrets (never DB), user_ai_prefs
single row = per-request owner defaults (hot-tunable, no secrets),
resolution request param -> owner default -> hard default, and the
safe-by-default privacy posture for default_backend. Adds the
Configuration glossary section to CONTEXT.md (owner default,
deployment config, hard default).
2026-09-27 22:50:28 -04:00

87 lines
4.2 KiB
Markdown

# ImageApi
A photo/video memory system: it ingests media from one or more libraries, derives metadata
(hashes, dates, faces, insights) that follows the bytes rather than the path, and serves it
to two consumers (the Apollo web UI and the FileViewer mobile app) plus a message store (SMS-API).
## Language
### Dates & time
**True instant**:
The actual moment a photo or video was captured, as Unix seconds. The one clock the whole
system matches against — SMS messages, location track points, and photo dates are all true
instants, so they compare directly with no conversion.
_Avoid_: epoch, real UTC, wall time
**Wall clock**:
The local time the capturing device showed (e.g. "14:30 on the beach"), independent of where
the owner is. A wall clock is not an instant until paired with a zone; it is what the UI's
metadata line and insight prompts show so memories read the way the camera remembered them.
_Avoid_: local time, naive date, camera time, date_taken
**Camera offset**:
The zone offset that converts a photo's wall clock into its true instant, resolved per photo
at ingest from the most specific evidence available (an explicit EXIF offset tag, then GPS
position, then the server's zone as a flagged assumption). Recorded on the row so the
conversion is auditable.
_Avoid_: timezone, tz, server offset
**Display zone**:
The IANA zone name of the owner, used for day-level grouping (memories buckets, timelines,
daily summaries) and for rendering wall clocks when a photo carries no camera offset. Stored
as a zone name, never a fixed minute offset, so DST changes stay correct.
_Avoid_: timezone_offset, tz_offset_minutes, client offset
**Date source**:
Which step of the ingest waterfall filled a photo's date — EXIF tag, external metadata
tool, filename, filesystem time, or a manual edit. Recorded per row so weak entries can be
re-resolved when a better tool arrives and so any row's date can be explained.
_Avoid_: provenance, origin
**Filename date class**:
Filenames whose name itself carries the capture date (screenshots, timestamp-named exports).
For this class the filename is the original date of record and outranks EXIF, even though
EXIF wins everywhere else. Each pattern in the class carries its own convention: some names
encode a wall clock, others encode a true instant.
_Avoid_: regex dates, name parsing
**Manual date**:
A date the operator sets by hand, expressed as a wall clock in the display zone at edit time
and stored as the resulting true instant. The prior value is kept as the original date.
_Avoid_: corrected date, user date
**Re-anchoring (legacy)**:
The pre-instant habit of storing wall clocks as if they were UTC and having every consumer
shift them back by a zone. Survives only in the frozen legacy column and in the consumer
code that migrates off it; new code never re-anchors.
_Avoid_: tz fix, offset correction, naive handling
**Derived day data**:
Insights and pre-computed artifacts grouped by calendar day (daily message summaries,
reel pre-generation). Because it is keyed on the day, re-dating a photo across a day
boundary invalidates the derived data for that day, which regenerates on its normal schedule.
_Avoid_: cache, nightly output
### Configuration
**Owner default**:
A per-request default the owner sets for the whole deployment — the model, backend,
persona, reel span, or segment cap a client gets when it omits the field. Stored in the
single `user_ai_prefs` row, hot-tunable without a redeploy, and global: every client that
omits the field gets it, on every device. Never holds secrets.
_Avoid_: user prefs, user settings, preferences (ambiguous with device-local client state)
**Deployment config**:
Values the server needs before it can start serving — bind address, database path, media
roots, the URLs used to build clients — plus every secret. Lives in `.env` only; changing
it is a redeploy, by design.
_Avoid_: environment config, system config
**Hard default**:
The env/code fallback a request lands on when neither an explicit param nor a stored
owner default supplies the field (e.g. backend `local`, persona `default`, reel span
day). It is the floor under the owner-default layer: env changes keep working whenever a
default column is NULL.
_Avoid_: fallback value, env default