Novu Notifications
Novu 알림 (Novu Notifications)
Section titled “Novu 알림 (Novu Notifications)”FractalOps는 Portal inbox 전달을 위한 OSS 알림 평면으로 Novu를 씁니다. FractalOps는 별도 push 엔진을 발명하지 않습니다 — Temporal/API 코드는 자체 알림을 만드는 대신 Novu 워크플로를 트리거해야 합니다.
flowchart LR trigger["Temporal / API\nNovu workflow trigger"] --> novu["Novu 서버\nnovu.yamon.io/api"] novu --> inbox["Portal bell / inbox\n(fractalops-frontend:portal)"] cfg["GET /v1/portal/notifications/novu-config\n(HMAC subscriber hash)"] -. resolve_env_or_secret .-> openbao["OpenBao\nruntime/novu-client"] inbox -. config 재조회 5분 .-> cfg novu -. push provider (FCM/OneSignal/Pushpad) .-> browser["브라우저 push (옵션)"]
현재 통합 지점
Section titled “현재 통합 지점”- Portal bell / inbox UI는
yamonco/fractalops-frontend:portal에서 마운트. - 백엔드가
GET /v1/portal/notifications/novu-config노출. - 백엔드가
POST /v1/portal/notifications/test노출. - subscriber 신원은 FractalOps
subject_key. - HMAC subscriber hash는 OpenBao에서 on-demand로 해결되며
FRACTALOPS_NOVU_SECRET_KEY에서 파생.
필수 설정 (Required settings)
Section titled “필수 설정 (Required settings)”FRACTALOPS_NOVU_ENABLED=trueFRACTALOPS_NOVU_API_URL=https://novu.yamon.io/apiFRACTALOPS_NOVU_SOCKET_URL=https://novu.yamon.io/wsFRACTALOPS_NOVU_DASHBOARD_URL=https://novu.yamon.ioFRACTALOPS_NOVU_APPLICATION_IDENTIFIER=...FRACTALOPS_NOVU_SECRET_KEY=ref:runtime/novu-client:FRACTALOPS_NOVU_SECRET_KEYFRACTALOPS_NOVU_DEFAULT_WORKFLOW_ID=fractalops-portal-alertFRACTALOPS_PORTAL_WEBPUSH_CONTACT_EMAIL=alerts@yamon.ioOpenBao 경로 (OpenBao paths)
Section titled “OpenBao 경로 (OpenBao paths)”fractalops/default/runtime/novu- 셀프호스트 Novu 서버 시크릿:
JWT_SECRET,STORE_ENCRYPTION_KEY,NOVU_SECRET_KEY,MONGO_INITDB_ROOT_USERNAME,MONGO_INITDB_ROOT_PASSWORD
- 셀프호스트 Novu 서버 시크릿:
fractalops/default/runtime/novu-client- FractalOps 런타임 값:
FRACTALOPS_NOVU_ENABLED,FRACTALOPS_NOVU_API_URL,FRACTALOPS_NOVU_SOCKET_URL,FRACTALOPS_NOVU_DASHBOARD_URL,FRACTALOPS_NOVU_APPLICATION_IDENTIFIER,FRACTALOPS_NOVU_SECRET_KEY,FRACTALOPS_NOVU_DEFAULT_WORKFLOW_ID
- FractalOps 런타임 값:
회전 컨트랙트 (Rotation contract)
Section titled “회전 컨트랙트 (Rotation contract)”runtime/novu-client는 ExternalSecret 전달,reload_strategy=hot_resolve,rotation_strategy=staged_dual_key.- Portal API는 각 config/test 요청마다
resolve_env_or_secret(...)로 Novu 시크릿을 해결하며PortalNotificationService에 캐시하지 않습니다. - Portal UI는 5분마다
cache: no-store로 Novu config를 재조회하므로, subscriber HMAC 변경이 프론트엔드 리빌드 없이 전파됩니다. runtime/novu는 stateful MongoDB/Valkey/서버 키를 담고reload_strategy=staged_restart+rotation_strategy=graceful_dual_credential을 씁니다.refreshInterval은15m; OpenBao Kubernetes auth 토큰 TTL은1h, max TTL은24h로,refreshInterval < token_ttl <= token_max_ttl을 보존합니다.- DB 자격증명은 staged여야 합니다: 새 자격증명 추가 → Novu API/WS/worker 롤 → MongoDB 연결 검증 → 옛 자격증명 폐기. Novu의 Redis-compatible cache는 앱 소유 Secret/PVC가 아니라
cache-planeValkey alias(novu-valkey)를 사용합니다.
검증 (Verify)
Section titled “검증 (Verify)”export FRACTALOPS_API_GATEWAY_URL="${FRACTALOPS_API_GATEWAY_URL:?set from topology/env}"
# Novu config 가 해결되는지 (HMAC subscriber hash 포함)curl -s -H "x-pomerium-claim-email: you@yamon.io" \ "$FRACTALOPS_API_GATEWAY_URL/v1/portal/notifications/novu-config" | head# 테스트 알림 전송curl -s -X POST -H "x-pomerium-claim-email: you@yamon.io" \ "$FRACTALOPS_API_GATEWAY_URL/v1/portal/notifications/test"노트 (Notes)
Section titled “노트 (Notes)”- Portal inbox는 Novu가 설정되고 대상 워크플로가 존재하면 라이브입니다.
- 브라우저 push 전달은 여전히 Novu push provider 통합(FCM/OneSignal/Pushpad)에 의존합니다.
- FractalOps는 별도 push 엔진을 발명하지 않습니다. Temporal/API 코드는 Novu 워크플로를 트리거하세요.
- GitOps 앱 경로:
platform/k8s/apps/novu - Argo application:
platform/k8s/argocd/runtime/resources/novu.application.yaml