The ntfy fan-out (publish each push to every active push node so a
round-robin-DNS-pinned subscriber receives it) was coded but INERT: the
gateway's cfg.NtfyBaseURL was never populated, so the fan-out resolver was
never built and pushes went single-host (the ~87% loss the bug describes).
The orchestrator already derives https://push.<dnsZone> for the ntfy server +
Caddy reverse-proxy but never put it in node.yaml's http_gateway. Same
regression class as the v0.122.42 secrets_encryption_key fix (consumer
landed; template + parse field + node->gateway mapping were missed).
Plumb it through all four layers: render it under http_gateway (derived as
push.<dnsZone>, matching the ntfy host), parse it in HTTPGatewayConfig, map
it onto gateway.Config. Rolling-upgrade safe: Phase 4 regen runs under the
new binary (post-swap), so an old binary never reads a node.yaml with the new
field. DecodeStrict regression guard added (mirrors secrets_encryption_key).
The 5-10s RPCs that broke calling were not cold-start — they were
per-RPC sequential rqlite reads, each forwarded to a raft leader that
geography-blind election had placed on a 256ms-distant node.
Lever A (serverless): cache function metadata + env vars in-process
(5s TTL, invalidated on deploy/enable/disable/delete) and stop the hot
invoke path re-fetching the function for the authorization check —
removes ~820ms of leader-routed pre-flight reads from every op.
Lever B (namespace): a locality-aware leadership reconciler hands raft
leadership off a geographically-isolated namespace leader to the nearest
co-located voter, via rqlite's transfer-leadership API. All nodes stay
voters — membership, quorum and fault tolerance are unchanged. Cuts the
per-hop cost from ~274ms to ~20ms when a distant node had become leader.
- add `secrets_encryption_key` to gateway config for serverless secrets
- implement durable TURN secret persistence to prevent config regen outages
- add regression test for gateway config loading and field mapping
- Add `raw_http_response` configuration to functions to allow verbatim HTTP responses
- Implement cluster-wide secrets encryption key generation and distribution for serverless functions
- Update documentation with UnifiedPush support for ntfy on Android/GrapheneOS
- Add `namespace_push_config` table for per-namespace provider settings
- Introduce `cluster_secret_path` to enable deterministic JWT signing and
AES-256-GCM encryption for push credentials
- Update gateway config to support per-namespace overrides of push
notification providers (ntfy/Expo)
- Bump version to 0.122.3