Proxy to another Paskia #5

Open
LeoVasanko wants to merge 10 commits from feature/remote-satellite into main
10 Commits
Author SHA1 Message Date
LeoVasanko 2a04d7e0d3 Admin UI remote option; docs match simplified protocol
Domain edit dialog: satellite-mode toggle with remote URL, write-only
sync token, cache TTL and re-sync interval, with auth-host requirement
validated before submit; domain list marks remote domains. AdminApp
sends remote wholesale on PATCH (null clears, absent token keeps the
stored one).
2026-09-21 01:14:00 +00:00
LeoVasanko 33e3185b39 Fix sync client resync condition (ready-tracked, not staging) 2026-09-21 01:07:47 +00:00
LeoVasanko ea780a20e1 Host-keyed dispatch in the satellite module; snapshot-only sync
Callers never see stores: session_ctx/verify/user-info resolve the store
from the request host via satellite.store_for_host; session refresh and
logout eviction are dispatch functions too (satellite.refresh_session /
evict_session). API handlers keep one code path plus forward_request
one-liners; proxy.py folds into satellite.py; Domain.store and the
store parameters are gone; 503 comes from the dispatch point as a plain
HTTPException.

The sync protocol drops replay/generation/seq: snapshots are small, so
every connect starts from a full snapshot and a single ordered WebSocket
cannot gap; a slow subscriber is dropped and resyncs. The satellite
reconnects every refresh_interval to reconcile drift.
2026-09-21 01:04:53 +00:00
LeoVasanko 2b21bfb98a Docs: remote satellite configuration, behavior, and design review 2026-09-20 23:46:53 +00:00
LeoVasanko 44364fdffc Fix replica-path leaks and availability semantics from live testing
- _remote_headers and /check used struct convenience properties that
  read the global database; they now use the SessionContext / the handed
  store (also fixes Remote-Credential carrying a struct repr instead of
  the UUID).
- Replica availability: TTL clock starts at disconnect, not at last
  message or failed reconnect; tight WS keepalive for prompt dead-peer
  detection.
- Proxy preserves repeated Set-Cookie via raw headers; sync endpoint
  does its own accept (wsutil decorator pre-accepts) and bypasses host
  dispatch (server-to-server; satellite may use an out-of-domain
  address).
- Admin-credential bootstrap warning skips remote domains.

Verified live with two instances (remote :4501, satellite :4402):
replica snapshot + events, 204 forward with Remote-* in <1ms, validate
write-behind landing on the remote, proxied logout with instant local
eviction, 503 after cache_ttl of disconnect, resync after remote
restart.
2026-09-20 23:45:01 +00:00
LeoVasanko 9394c38179 Remote domain configuration via admin domains API
ApiDomain carries the remote block (sync token write-only, never
echoed); create/patch accept it, validated with the combined config
(auth host mandatory for remote domains). db.update_domain replaces
remote wholesale like the other domain fields.
2026-09-20 23:26:00 +00:00
LeoVasanko 5ecb10166d Add remote domains: RAM replica + RAM-only sync channel
DomainConfig.remote {url, token, cache_ttl, refresh_interval} marks a
domain as backed by a remote paskia instance (auth host required). The
remote publishes committed changes via struct store()/delete() hooks and
explicit emits in field-mutating operations into syncfeed, an in-RAM
sequenced ring buffer served over a token-gated WebSocket
(/auth/api/sync/ws, tokens from PASKIA_SYNC_TOKENS env). The satellite
keeps a plain DB replica per remote URL, applies snapshots/events,
enforces expiry locally, and writes session refreshes back over the same
channel. /validate refreshes locally with write-behind; /logout,
/set-session, /token-info and /auth/oidc/* are proxied to the remote
with the original Host header; logout also evicts from the replica.
Replicas go fail-closed (503) after cache_ttl of silence.
2026-09-20 23:21:08 +00:00
LeoVasanko 20b145d816 Make session read path store-explicit
DB.session_ctx now reads only its own tables instead of struct
convenience properties that reach the global database, so a DB instance
(a read replica) is self-contained. session_ctx/session_context/
authz.verify/build_user_info take an explicit store parameter defaulting
to the local database; api.py endpoints resolve it from the dispatched
domain (Domain.store).
2026-09-20 23:08:56 +00:00
LeoVasanko b5733657f9 Fastapi-vue-setup 1.7.2 logging fixes. 2026-09-18 19:07:33 +00:00
LeoVasanko 4de164c457 Use fastapi-vue RuntimeConfig passing, simplifying code. 2026-09-18 19:00:13 +00:00