added media fixes, search, push updates, pwa, metrics. preparing release 1.0
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
# ADR 0001: Monolith over microservices
|
||||
|
||||
- Status: accepted
|
||||
- Date: 2026-09
|
||||
|
||||
## Context
|
||||
The messenger serves a single family (tens of users) on a home-lab mini PC
|
||||
with ~8 GB RAM. A microservice split would add operational overhead
|
||||
(networking, service discovery, per-service containers) with zero benefit at
|
||||
this scale.
|
||||
|
||||
## Decision
|
||||
Build a single Go process exposing REST, WebSocket, media serving and static
|
||||
files, with PostgreSQL as the only external state. Internal packages
|
||||
(`store`, `auth`, `realtime`, `api`, `media`) are cleanly separated with
|
||||
explicit interfaces, so extraction later is mechanical.
|
||||
|
||||
## Consequences
|
||||
- One container, trivial `docker compose up`.
|
||||
- In-process WebSocket hub gives O(1) presence checks for push decisions.
|
||||
- If the service ever needs horizontal scaling, `realtime` and `store`
|
||||
already hide their implementations behind interfaces.
|
||||
@@ -0,0 +1,21 @@
|
||||
# ADR 0002: In-memory WebSocket hub
|
||||
|
||||
- Status: accepted
|
||||
- Date: 2026-09
|
||||
|
||||
## Context
|
||||
Realtime delivery (messages, typing, presence, read receipts) must reach
|
||||
connected clients immediately. Options: external broker (Redis pub/sub,
|
||||
NATS), Postgres LISTEN/NOTIFY, or an in-process hub.
|
||||
|
||||
## Decision
|
||||
Use an in-process hub: `map[userID] -> connections` plus
|
||||
`map[conversationID] -> subscribers`, guarded by a mutex. Membership and
|
||||
read-state are resolved through a `MembershipProvider` interface implemented
|
||||
by the store.
|
||||
|
||||
## Consequences
|
||||
- Sub-millisecond fan-out, no extra moving parts.
|
||||
- Presence checks (`IsOnline`) are lock-free reads used by the push notifier.
|
||||
- Multi-node scaling would require a broker; the hub's publish methods are
|
||||
the seam where that would plug in.
|
||||
@@ -0,0 +1,20 @@
|
||||
# ADR 0003: Search via ILIKE instead of pg_trgm
|
||||
|
||||
- Status: accepted
|
||||
- Date: 2026-09
|
||||
|
||||
## Context
|
||||
Message search must find substring matches across a user's conversations.
|
||||
pg_trgm + GIN gives indexed trigram search, but the extension is not
|
||||
installed on the target system and cannot be created by a non-superuser role
|
||||
(and adding it to the Docker image is an OS-level dependency).
|
||||
|
||||
## Decision
|
||||
Search with `body ILIKE '%term%'` restricted to the user's conversations,
|
||||
ordered by message id descending with a limit.
|
||||
|
||||
## Consequences
|
||||
- No extension or superuser requirement; works on any PostgreSQL install.
|
||||
- Sequential scan is instant for thousands of messages (family scale).
|
||||
- Scaling path documented: `CREATE EXTENSION pg_trgm` + GIN index with
|
||||
`gin_trgm_ops`, keeping the same SQL semantics.
|
||||
@@ -0,0 +1,22 @@
|
||||
# ADR 0004: Media behind an S3-like interface
|
||||
|
||||
- Status: accepted
|
||||
- Date: 2026-09
|
||||
|
||||
## Context
|
||||
Attachments (images, files, videos) need storage, thumbnails for images, and
|
||||
bounded upload size. Storage must survive container restarts and, ideally, be
|
||||
swappable without touching API code.
|
||||
|
||||
## Decision
|
||||
Define a `Storage` interface (`Save`/`Open`/`Delete` keyed by opaque keys) in
|
||||
`internal/media`. Phase 2 ships `Local` — files on disk with atomic
|
||||
temp-file+rename writes and path-traversal protection. API handlers depend
|
||||
only on the interface.
|
||||
|
||||
## Consequences
|
||||
- Metadata lives in Postgres (`media` table); bytes live in storage.
|
||||
- Replacing disk with MinIO/S3 means a new `Storage` implementation, no
|
||||
handler changes.
|
||||
- Image thumbnails are generated with stdlib decoding + `x/image/draw`,
|
||||
avoiding CGO and external binaries.
|
||||
@@ -0,0 +1,21 @@
|
||||
# ADR 0005: E2EE deferred, libsignal when implemented
|
||||
|
||||
- Status: accepted
|
||||
- Date: 2026-09
|
||||
|
||||
## Context
|
||||
A family messenger should eventually protect message content at rest and in
|
||||
transit, ideally with end-to-end encryption. Rolling a custom crypto protocol
|
||||
is unsafe and a red flag in review.
|
||||
|
||||
## Decision
|
||||
- In transit: TLS everywhere (Caddy on the VPS / reverse proxy; homelab
|
||||
ingress).
|
||||
- At rest: Postgres and media disk live on trusted hardware.
|
||||
- E2EE: deferred to a future major version, implemented with an established
|
||||
library (libsignal) — never hand-written primitives.
|
||||
|
||||
## Consequences
|
||||
- The wire protocol and data model are ready for E2EE (opaque message bodies,
|
||||
device-agnostic session model).
|
||||
- No false-security claims in the README.
|
||||
Reference in New Issue
Block a user