tenant

package
v1.6.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package tenant resolves per-tenant Notifier instances on demand.

On every Send, the routes layer asks the resolver for a Notifier configured for (tenant, channel). The resolver looks up the active Provider row, fetches credentials from KMS, and constructs the matching provider impl from the library. No cache — credentials may rotate, and provider rows may change at runtime; the cost of one extra KMS Get per send is the price of correctness.

Phase 1: plivo (SMS/WhatsApp/Voice) + mail (SMTP). Other providers land as small functions that follow the same shape — the library already exposes 33 implementations; this package wraps them.

Index

Constants

View Source
const DefaultBrand = "hanzo"

DefaultBrand is the brand slug whose KMS credentials are used when the caller's brand has not configured an override. Lives in KMS at `brand/hanzo/plivo/*`.

View Source
const PlivoBrandKMSPathPrefix = "brand"

PlivoBrandKMSPathPrefix is the KMS path under which per-brand Plivo credentials live. Combined with brand slug:

brand/<slug>/plivo/auth-id
brand/<slug>/plivo/auth-token
brand/<slug>/plivo/sender-id
brand/<slug>/plivo/from-email

Variables

This section is empty.

Functions

func Channel

func Channel(s string) types.Channel

Channel narrows a string to a known types.Channel or returns "". Used by the routes layer when reading the body's channel field.

Types

type Credentials

type Credentials map[string]string

Credentials is the flat key/value bag the library providers consume. The KMS values land here as plain strings; envelope decoding happens inside kmsclient.

type PlivoConfig added in v1.6.6

type PlivoConfig struct {
	// Brand is the slug whose credentials produced this config. When a
	// brand override exists, Brand == the requested brand. When the
	// resolver fell back to the Hanzo default, Brand == "hanzo".
	// Callers use this to log which Plivo account actually sent.
	Brand string

	// AuthID is the Plivo Auth ID (account-level credential).
	AuthID string

	// AuthToken is the Plivo Auth Token (account-level credential).
	AuthToken string

	// SenderID is the source number / shortcode / alphanumeric ID that
	// will appear as the From on the SMS.
	SenderID string

	// FromEmail is the email address the brand sends from when notify
	// channel=email is wired to the same per-brand config. Optional.
	FromEmail string

	// Override is true when this config came from the requested brand's
	// own KMS entries (not the Hanzo default). Used by the platform
	// UI's "current effective provider" indicator.
	Override bool
}

PlivoConfig is the resolved per-brand Plivo configuration. The SenderID doubles as the Plivo "Source" — either an E.164 number or a Powerpack UUID.

type PlivoResolver added in v1.6.6

type PlivoResolver struct {
	// contains filtered or unexported fields
}

PlivoResolver resolves per-brand Plivo configuration via KMS. One instance per process is enough — the underlying KMSClient already memoizes secrets for 1m TTL.

func NewPlivoResolver added in v1.6.6

func NewPlivoResolver(kms *platform.KMSClient) (*PlivoResolver, error)

NewPlivoResolver returns a PlivoResolver bound to the given KMS client. A nil KMS client is rejected at boot — fail-closed.

func (*PlivoResolver) ResolvePlivoConfig added in v1.6.6

func (r *PlivoResolver) ResolvePlivoConfig(ctx context.Context, brand string) (*PlivoConfig, error)

ResolvePlivoConfig returns the Plivo credentials that should be used when sending for brand. The lookup order is:

  1. brand/<requested>/plivo/* — the brand's own override.
  2. brand/hanzo/plivo/* — the Hanzo default.

On step 1 the resolver does NOT short-circuit on any non-EOF error: a KMS access error against the requested brand falls through to the default ONLY when the error indicates "secret not found". Any other error (auth fail, transport, 5xx) is surfaced — silently degrading to the Hanzo creds for someone else's transient KMS outage would risk sending the wrong brand's SMS during the outage window.

On step 2 the resolver fail-closes: a missing or unreachable Hanzo default returns an error. notify callers surface 503.

The empty string for `brand` is rejected as a programming error — the platform plugin always injects X-Org-Id before this fires.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver is the entry point routes call. It owns the base app (to look up provider rows) and the platform-side KMS facade (to fetch credentials).

func New

func New(app core.App, kms *platform.KMSClient) *Resolver

New returns a Resolver bound to the given app + KMS client. A nil KMS client is allowed; in that mode the resolver falls back to env var credentials, which is the local-dev / scratch-image path.

func (*Resolver) Resolve

func (r *Resolver) Resolve(ctx context.Context, tenant, channel, service string, to []string) (notify.Notifier, string, error)

Resolve returns a notifier wired with credentials for (tenant, channel). service may be empty to take the tenant's default provider for the channel. The returned notifier targets `to` so caller can call Send directly — providers in the library are constructed with a fixed recipient list per the casdoor/nikoksr design.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL