No description
  • Go 96.1%
  • HTML 3.9%
2026-05-17 00:03:59 +02:00
cmd/posta-server chore: fix all golanci-lint warnings 2026-05-17 00:03:59 +02:00
internal chore: fix all golanci-lint warnings 2026-05-17 00:03:59 +02:00
.gitignore initial commit 2026-05-09 02:14:47 +02:00
.golangci.yml chore: fix all golanci-lint warnings 2026-05-17 00:03:59 +02:00
Basefile chore: add basefile for deployment 2026-05-16 21:10:07 +02:00
CLIENT_API.md Polish CLIENT_API.md for AI-readability and add llms.txt 2026-05-13 22:23:06 +02:00
go.mod chore: add basefile for deployment 2026-05-16 21:10:07 +02:00
go.sum chore: add basefile for deployment 2026-05-16 21:10:07 +02:00
llms.txt Polish CLIENT_API.md for AI-readability and add llms.txt 2026-05-13 22:23:06 +02:00
README.md Rename msg → posta and round out the SSE event surface 2026-05-09 11:50:25 +02:00

posta-server

The posta inbox daemon plus the authenticated client API for native apps.

posta-server runs the wire-protocol receiver from SPEC.md and serves a REST + SSE client API at /api/v1/* documented in CLIENT_API.md.

It is the deployment unit: the binary that runs in the arne-posta / marcus-posta containers, replacing posta serve. The wire protocol stays unchanged; existing peers don't notice the swap.

Build

go build ./cmd/posta-server

Static, cgo-free build for the Alpine deployment:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
    go build -trimpath -ldflags="-s -w -X main.version=$(git describe --always --dirty)" \
    -o posta-server ./cmd/posta-server

Run

posta-server serve \
    --url https://arne.posta.no \
    --listen 0.0.0.0:80 \
    --keys /etc/posta/keys.json \
    --db /var/lib/posta/inbox.db \
    --acl open \
    --name Arne

Flags can also live in config.toml (default $XDG_CONFIG_HOME/posta-server/config.toml) or POSTA_SERVER_* env vars. Layering order: flag > env > config > default.

Token management

Clients (iOS, the new TUI) authenticate with bearer tokens. Tokens are minted on the host:

posta-server token create --name "Arne's iPhone"   # prints mst_… once
posta-server token list                              # active + revoked
posta-server token revoke "Arne's iPhone"            # affected devices stop authenticating

Tokens never leave the host as plaintext after the create call — only the SHA-256 hash is persisted. Lost tokens are not recoverable; revoke and re-pair.

Storage layout

Single SQLite database at --db. posta-server applies migrations on startup and keeps the schema as a strict superset of posta's own daemon schema, so an existing inbox.db (with messages, contacts, FTS5) is adopted in place. New tables: identity, auth_tokens, devices, schema_version.

The legacy posta TUI reading the same DB continues to work; the new TUI and iOS apps go through /api/v1/*.

Architecture overview

                ┌────────────────── caddy (TLS) ──────────────────┐
                │                                                 │
       wire     │       /api/v1/*  (Bearer)                       │
       peer ────┼──>  posta-server        ┌─ inbox handler ── DB  │
                │     ┌──────────┐  HTTP  ├─ outbox loop  ──> DB  │
   iOS / TUI ───┼──>  │  router  │ ───────┤                       │
                │     └──────────┘        ├─ api handlers ── DB   │
                │                         └─ SSE hub ── ring buf  │
                └─────────────────────────────────────────────────┘

Wire receiver and client API share the same SQLite store. The SSE hub publishes events from the inbox handler, the outbox loop, and the API handlers themselves (e.g. PATCH /identity triggers identity-changed).

Layout

cmd/posta-server/           cobra CLI (serve, token, version)
internal/api/               REST + SSE handlers for /api/v1/*
internal/auth/              bearer middleware, token mint/hash
internal/config/            TOML / env / flag layering
internal/inbox/             wire-protocol receiver
internal/keys/              read-only loader for keys.json
internal/outbox/            send loop with retry/backoff
internal/sse/               in-memory pub/sub + ring buffer
internal/store/             SQLite schema, migrations, queries

Status

v0.1.0 — first release. APNs is deferred (no /api/v1/devices, no push from the daemon). Foreground iOS via SSE; backgrounded apps see new messages on relaunch.