Documentation
¶
Overview ¶
Package notify folds the Hanzo Notify SEND surface into the unified cloud binary (HIP-0106), mounting /v1/notify/* natively in-process — the native replacement for the standalone notifyd (github.com/hanzoai/notify) Deployment.
SCOPE — the one live contract. notifyd's ONLY production consumer is Hanzo IAM, which POSTs OTP sends to POST /v1/notify/send?sync=true with the wire body
{"to":["…"],"channel":"sms|email","event":"iam.otp_sent",
"template_vars":{"otp":"…","recipient":"…","app":"…"}}
and treats a response status of "sent"/"delivered" as success (see hanzoai/iam object/notify_delivery_http.go). This subsystem serves that exact contract natively. Everything else notifyd carries — the tenants/templates/ providers/preferences/unsubscribe/metering/events/messages collections and the hanzoai/tasks (Temporal) async worker — has NO live consumer (the live tenant's template/provider/event tables are empty and only IAM calls /send), so it is deliberately NOT folded. The Temporal notify-send queue plane is owned elsewhere and is not touched here; async sends (no ?sync=true) return 503, exactly as notifyd does when it runs without a connected worker.
DRY — no reimplementation of provider plumbing. The actual provider implementations and the wire structs are notifyd's OWN public packages, imported directly: github.com/hanzoai/notify/service/{twilio,twilioemail,plivo,mail} and github.com/hanzoai/notify/pkg/types. Only the thin credential→constructor glue (constructProvider) — which lives in notifyd's internal/ and is therefore not importable across the module boundary — is mirrored here, matching internal/tenant/tenant.go verbatim.
SECURITY — the trust boundary moves with the code. notifyd was ClusterIP-internal and trusted a raw X-Org-Id header. Mounted here, /v1/notify/send is reachable via the public gateway (api.hanzo.ai forwards every path to cloud), so — like clients/auto did when it folded the auto engine — this gates on a VALIDATED principal and derives the org from principal.Org (the identity middleware's trusted, gateway-minted X-Org-Id), never from a client-supplied header. An unauthenticated caller gets 401; a signed-in caller can only send scoped to their OWN org.
CREDENTIALS — KMS only, never env, never plaintext, never logged. Provider credentials are read EXCLUSIVELY from cloud's embedded KMS via cloud.Deps.KMS, at the org-scoped, rotatable ref orgs/<org>/notify/<service>/<key> — the SAME /orgs/<org> namespace clients/integrations uses, so a cred is writable and rotatable through POST /v1/kms/orgs/:org/secrets with a validated org token (no operator-injected env Secret, no restart to rotate). The org is the VALIDATED principal's tenant (never a client header). A missing key yields an empty value and constructProvider fails closed; no secret is ever hard-coded, read from the environment, or logged.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
This section is empty.