Makes indri the canonical **heph** hub for the hub-and-spoke task/context system, deployed as a self-updating LaunchAgent managed by Ansible. Other devices (gilbert) attach as offline-capable spokes.
## What's here
- **`ansible/roles/heph`** (tag `heph`) — bootstrap `cargo install hephd` (only if absent; `--self-update` keeps it current after), version-pinned `heph-pwa` checkout served via `--web-root`, launchagent `mcquack.eblume.heph`:
```
hephd --mode server --http-addr 0.0.0.0:8787 --db … --web-root …
--oidc-issuer …/o/heph/ --oidc-audience heph
--self-update --self-update-interval-secs 600
```
`~/.cargo/bin` is on the agent `PATH` so self-update's `cargo install` works.
- **Caddy** — `heph.ops.eblu.me → localhost:8787` (TLS for the PWA secure context).
- **Authentik** — new `heph` **public device-code** OIDC app + `default-device-code-flow` bound to the default brand's `flow_device_code` (verified live: brand `authentik-default`, field currently unset → additive).
- **Docs** — `services/hephaestus.md` (Path-A seeding runbook + spoke caveat), `indri.md`, changelog fragment.
## Three features requested
- **Autoupdate** — 10-min interval (`--self-update-interval-secs 600`).
- **PWA** — `--web-root` (confirmed shipped in v1.2.0).
- **Spoke** — gilbert reconfig documented (post-merge step).
## Deploy plan (not done yet — awaiting review)
1. Seed from gilbert (Path A): `heph daemon stop` → copy `heph.db` → `DELETE FROM meta WHERE key='origin'`.
2. Sync Authentik `apps`/blueprint; verify blueprint status via API (not just logs).
3. `provision-indri --tags heph,caddy` from this branch.
4. Point gilbert at the hub + `heph auth login`.
## Known follow-ups (heph-side, tracked in the Hephaestus project)
- `heph daemon` can't bake hub/spoke config or pass `--self-update-interval-secs` → worked around by the ansible plist.
- Path-A seeding lacks a clean `hephd --owner-id`/seed command → manual `meta.origin` reset for now.
- Self-update moves hephd ahead of the ansible-pinned PWA shell over time (drift; tolerated by the SW cache, revisit on next release).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: #369
50 lines
1.7 KiB
Django/Jinja
50 lines
1.7 KiB
Django/Jinja
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- {{ ansible_managed }} -->
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>Label</key>
|
|
<string>mcquack.eblume.heph</string>
|
|
<key>ProgramArguments</key>
|
|
<array>
|
|
<string>{{ heph_binary }}</string>
|
|
<string>--mode</string>
|
|
<string>server</string>
|
|
<string>--http-addr</string>
|
|
<string>{{ heph_http_addr }}</string>
|
|
<string>--db</string>
|
|
<string>{{ heph_db }}</string>
|
|
<string>--socket</string>
|
|
<string>{{ heph_socket }}</string>
|
|
<string>--web-root</string>
|
|
<string>{{ heph_web_root }}</string>
|
|
<string>--oidc-issuer</string>
|
|
<string>{{ heph_oidc_issuer }}</string>
|
|
<string>--oidc-audience</string>
|
|
<string>{{ heph_oidc_audience }}</string>
|
|
<string>--self-update</string>
|
|
<string>--self-update-interval-secs</string>
|
|
<string>{{ heph_self_update_interval_secs }}</string>
|
|
</array>
|
|
<key>RunAtLoad</key>
|
|
<true/>
|
|
<key>KeepAlive</key>
|
|
<true/>
|
|
<key>EnvironmentVariables</key>
|
|
<dict>
|
|
<!-- cargo + toolchain on PATH so --self-update can run `cargo install`. -->
|
|
<key>PATH</key>
|
|
<string>{{ heph_bin_dir }}:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
<key>HOME</key>
|
|
<string>/Users/erichblume</string>
|
|
<!-- Pin the rustup channel: the launchagent runs without mise, so a bare
|
|
cargo shim would otherwise use rustup's (stale) default toolchain. -->
|
|
<key>RUSTUP_TOOLCHAIN</key>
|
|
<string>{{ heph_rust_toolchain }}</string>
|
|
</dict>
|
|
<key>StandardOutPath</key>
|
|
<string>{{ heph_log_dir }}/mcquack.heph.out.log</string>
|
|
<key>StandardErrorPath</key>
|
|
<string>{{ heph_log_dir }}/mcquack.heph.err.log</string>
|
|
</dict>
|
|
</plist>
|