Add hephaestus sync hub to indri (launchagent, PWA, device-code OIDC) (#369)
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
This commit is contained in:
parent
f6c926f1f5
commit
a2f1e06224
10 changed files with 403 additions and 0 deletions
|
|
@ -434,3 +434,82 @@ data:
|
|||
provider: !KeyOf mealie-provider
|
||||
meta_launch_url: https://meals.ops.eblu.me
|
||||
policy_engine_mode: all
|
||||
|
||||
heph.yaml: |
|
||||
version: 1
|
||||
metadata:
|
||||
name: BlumeOps Heph SSO
|
||||
labels:
|
||||
blueprints.goauthentik.io/description: "Hephaestus hub OIDC (device-code) provider, application, and device-code flow"
|
||||
entries:
|
||||
# Device-code flow (RFC 8628). authentik ships no default for this, so we
|
||||
# create one and bind it to the brand below. An empty stage_configuration
|
||||
# flow is sufficient: the already-authenticated user just confirms the code.
|
||||
- model: authentik_flows.flow
|
||||
id: device-code-flow
|
||||
identifiers:
|
||||
slug: default-device-code-flow
|
||||
attrs:
|
||||
name: Device code flow
|
||||
title: Device code flow
|
||||
slug: default-device-code-flow
|
||||
designation: stage_configuration
|
||||
authentication: require_authenticated
|
||||
|
||||
# Enable the device-code grant globally by binding the flow to the default
|
||||
# brand (domain authentik-default). Partial update — only sets this field.
|
||||
- model: authentik_brands.brand
|
||||
identifiers:
|
||||
domain: authentik-default
|
||||
attrs:
|
||||
flow_device_code: !KeyOf device-code-flow
|
||||
|
||||
# OAuth2 provider for heph — PUBLIC client (device-code + PKCE, no secret).
|
||||
# client_id doubles as the token audience the hub verifies (--oidc-audience heph),
|
||||
# and the app slug 'heph' is the issuer path (/application/o/heph/).
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: heph-provider
|
||||
identifiers:
|
||||
name: Heph
|
||||
attrs:
|
||||
name: Heph
|
||||
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
||||
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
||||
client_type: public
|
||||
client_id: heph
|
||||
# Device-code (RFC 8628) + PKCE use no redirect, but the provider
|
||||
# serializer requires the field — an empty list satisfies it.
|
||||
redirect_uris: []
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
||||
property_mappings:
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
|
||||
sub_mode: hashed_user_id
|
||||
include_claims_in_id_token: true
|
||||
|
||||
# Heph application — linked to the OAuth2 provider
|
||||
- model: authentik_core.application
|
||||
id: heph-app
|
||||
identifiers:
|
||||
slug: heph
|
||||
attrs:
|
||||
name: Hephaestus
|
||||
slug: heph
|
||||
provider: !KeyOf heph-provider
|
||||
meta_launch_url: https://heph.ops.eblu.me
|
||||
policy_engine_mode: any
|
||||
|
||||
# Policy binding — restrict heph to admins group (single-owner, sensitive data)
|
||||
- model: authentik_policies.policybinding
|
||||
identifiers:
|
||||
order: 0
|
||||
target: !KeyOf heph-app
|
||||
group: !Find [authentik_core.group, [name, admins]]
|
||||
attrs:
|
||||
target: !KeyOf heph-app
|
||||
group: !Find [authentik_core.group, [name, admins]]
|
||||
order: 0
|
||||
enabled: true
|
||||
negate: false
|
||||
timeout: 30
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue