BareGit
# Overseer

A self-hosted family information system. One binary, one SQLite file,
one YAML config, one systemd unit. Server-rendered HTML with htmx for
the interactive bits — no SPA, no JS build step.

Overseer is structured as a set of independent modules. v1 ships a
single module:

- **Inventory** — track where things live at home. A tree of
  *storages* (rooms, shelves, drawers…) holding *stuffs* (items). Each
  stuff can have a photo, a description, and a rolling 10-entry move
  history. Full-text search over names and descriptions. Inline name
  editing and one-click move via htmx.

A *Doc* module is sketched in the design but not built yet.

## Features

- OIDC login (any provider with discovery — Keycloak, Authentik,
  Dex, …). Tokens stay server-side; the browser holds an opaque
  session cookie.
- Photo upload, scaled to 1024 px long-side and transcoded to AVIF.
  Identical photos are stored once and shared by SHA-256.
- SQLite + FTS5 search, WAL journaling, foreign keys with
  `ON DELETE RESTRICT`, versioned migrations with automatic pre-migration
  backup.
- CSRF protection (double-submit token + same-origin check) on all
  mutating routes.
- Structured logging via `spdlog`, with a journald sink when run
  under systemd.
- Unix-socket or TCP bind. The socket mode is configurable so a
  reverse proxy can connect without any group/user juggling.

## Build

Requires a C++23 compiler (GCC 14+ / Clang 18+), CMake ≥ 3.24, and:

- SQLite ≥ 3.38 (FTS5)
- libcurl
- ImageMagick (Magick++)
- libsystemd
- pkg-config

Other dependencies (`libmw`, `inja`, `nlohmann_json`, `spdlog`,
`yaml-cpp`, `cxxopts`, and optionally `googletest`) are fetched
through CMake's `FetchContent`.

```
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
```

For development / running tests:

```
cmake -B build -S . -DOVERSEER_BUILD_TEST=ON
cmake --build build -j
ctest --test-dir build
```

## Configuration

Copy `overseer.example.yaml` to `/etc/overseer.yaml` and edit it. The
config file must not be world-readable (the daemon refuses to start
otherwise) since it carries the OIDC client secret.

Minimum keys:

```yaml
bind_address: "unix:/run/overseer/overseer.sock"   # or "127.0.0.1"
port: 8080                                         # only used for TCP binds
socket_permission: "0666"                          # only used for unix binds
log_level: "info"
db_path: "/var/lib/overseer/overseer.db"

oidc:
    issuer_url:    "https://keycloak.example.com/realms/family"
    client_id:     "overseer"
    client_secret: "REPLACE_ME"
    redirect_uri:  "https://overseer.example.com/oidc/callback"
```

The redirect URI must be registered with the OIDC provider as an
allowed callback for the client.

## Running

```
overseer --config /etc/overseer.yaml
```

Other flags (run `overseer --help` for the full list):

- `--template-dir DIR` — override the template root (defaults to the
  source tree in a dev build, `/usr/share/overseer/modules` in the
  Arch package).
- `--static-dir DIR` — override the static-files root.
- `--dev` — verbose logging and template hot reload.

### Arch Linux

A `-git` PKGBUILD lives in `packages/arch/`:

```
cd packages/arch
makepkg -si
```

The package installs the binary to `/usr/bin/overseer`, templates to
`/usr/share/overseer/`, a sample config to `/etc/overseer.yaml`,
and registers a system user `overseer`, a tmpfiles entry for
`/var/lib/overseer/`, and an `overseer.service` unit. After editing
the config:

```
systemctl enable --now overseer.service
```

The unit binds to `/run/overseer/overseer.sock` by default. Point your
reverse proxy at that socket.

## Development

The source tree mirrors the module layout:

```
src/
    inventory/           # liboverseer_inventory — pure repo/domain code
    db/                  # migrations + backup
    overseer/            # the binary: web server, OIDC, render, session
        modules/
            inventory/   # routes, views, templates for the inventory module
    static/              # CSS, JS (htmx)
tests/                   # GoogleTest unit + HTTP integration tests
designs/                 # design docs
packages/arch/           # PKGBUILD and systemd assets
```

The `inventory` library has no web dependency, so a future
agent-facing surface (MCP, REST) can reuse it directly.

For the full architectural rationale see
[designs/design-0-architecture.md](designs/design-0-architecture.md).