Documentation
¶
Overview ¶
Package integrations is the use-case module for a Workspace's sending-provider Integrations: config validation, credential sealing, the default-per-channel rule and the redacted read view. /site and /api are thin adapters over it, so the two surfaces cannot diverge on how a credential is stored or what is refused.
Handlers hand in a *ent.Scoped and domain-typed input (not their DTOs) and get back the row or a domain error: validation.Error (a 422), ErrDefaultConflict (a 409), or ent's not-found for an unknown id.
Index ¶
- Constants
- Variables
- func IsConflict(err error) bool
- func ParamsOf[M ~map[string]jx.Raw](raw M) (map[string]any, error)
- func RawOf(values map[string]any) map[string]jx.Raw
- type ConfigInput
- type CreateInput
- type InboxConfig
- type Limit
- type Module
- func (m *Module) All(ctx context.Context, s *ent.Scoped, archived bool) ([]*ent.Integration, error)
- func (m *Module) Archive(ctx context.Context, s *ent.Scoped, id int64) error
- func (m *Module) ConfirmSubscription(ctx context.Context, url string) error
- func (m *Module) Create(ctx context.Context, s *ent.Scoped, in CreateInput) (*ent.Integration, error)
- func (m *Module) Get(ctx context.Context, s *ent.Scoped, id int64) (*ent.Integration, error)
- func (m *Module) HookURL(row *ent.Integration) string
- func (m *Module) List(ctx context.Context, s *ent.Scoped, p pagination.Params, archived bool) (pagination.Page[*ent.Integration], error)
- func (m *Module) Params(row *ent.Integration) (preset.Params, error)
- func (m *Module) Presets() *preset.Registry
- func (m *Module) Redact(row *ent.Integration) (RedactedConfig, error)
- func (m *Module) RegenerateKey(ctx context.Context, s *ent.Scoped, id int64) (*ent.Integration, error)
- func (m *Module) Unarchive(ctx context.Context, s *ent.Scoped, id int64) error
- func (m *Module) Update(ctx context.Context, s *ent.Scoped, id int64, in UpdateInput) (*ent.Integration, error)
- func (m *Module) View(row *ent.Integration) (ParamsView, error)
- type Option
- type ParamsView
- type PresetChange
- type QuotaEnqueuer
- type RedactedConfig
- type RedactedInbox
- type RedactedSES
- type RedactedSMTP
- type SESConfig
- type SMTPConfig
- type UpdateInput
Constants ¶
const SecretMask = "********"
SecretMask is what a read shows in place of a secret param. Sending it back, or a blank, or nothing, leaves the stored secret as it is.
Variables ¶
var ErrDefaultConflict = validation.Refuse("a default provider already exists for this channel", "errors.integration_default_conflict")
ErrDefaultConflict means another default Integration already exists for the channel.
var ErrNotFound = validation.Refuse("integrations: integration not found", "errors.integration_not_found")
ErrNotFound means there is no such Integration in this Workspace.
var ErrOneInbox = validation.Refuse("a workspace has at most one Test inbox", "errors.integration_one_inbox")
ErrOneInbox means the Workspace already keeps a Test inbox: it has at most one (ADR 0058).
Functions ¶
func IsConflict ¶
IsConflict reports whether err is one of the refusals a handler answers with 409.
Types ¶
type ConfigInput ¶
type ConfigInput struct {
SMTP *SMTPConfig
SES *SESConfig
Inbox *InboxConfig
}
ConfigInput carries exactly one provider's settings.
type CreateInput ¶
type CreateInput struct {
Name string
Enabled *bool
IsDefault bool
MaxPerSecond Limit
MaxPerDay Limit
Config ConfigInput
// Preset and Params are the inbound side (ADR 0037); Params without a Preset is refused.
Preset *string
Params map[string]any
}
CreateInput is a new Integration. Enabled defaults to true when nil.
type Limit ¶
Limit is a Send rate limit in a request: unset keeps the stored value (update) or means no limit (create); Value nil with Set true clears it.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module holds the shared collaborators; it is stateless otherwise.
func New ¶
func New(bus *events.Bus, cipher *secrets.Cipher, catalog *messaging.Catalog, quota QuotaEnqueuer, presets *preset.Registry, appURL string, opts ...Option) *Module
New builds the module. presets is the Instance's Preset registry and appURL the public origin the hook URLs are built from.
func (*Module) All ¶
All returns every kept Integration of the Workspace, or with archived every archived one, ascending by id.
func (*Module) Archive ¶
Archive discards an Integration (ADR 0049), unless live work uses it: then it returns an *inuse.Error naming that work. A scheduled or sending Broadcast uses the Integration it names, and the default one when it names none; an active Automation that sends email uses the one it names, and the default one when it names none. A sent or failed Broadcast is history and does not block. An archived Integration gives up the default: its channel has none until another is picked. Archiving an archived Integration changes nothing. An unknown id is ErrNotFound.
func (*Module) ConfirmSubscription ¶
ConfirmSubscription performs a Preset's confirm action: it fetches the URL the provider asked to be fetched, through the SSRF-guarded client. The engine has already refused a URL the provider's own rules do not allow (SNS: an https SNS host only).
func (*Module) Create ¶
func (m *Module) Create(ctx context.Context, s *ent.Scoped, in CreateInput) (*ent.Integration, error)
Create validates and stores an Integration, sealing its credentials.
func (*Module) HookURL ¶
func (m *Module) HookURL(row *ent.Integration) string
HookURL is where the provider posts this Integration's callbacks.
func (*Module) List ¶
func (m *Module) List(ctx context.Context, s *ent.Scoped, p pagination.Params, archived bool) (pagination.Page[*ent.Integration], error)
List returns one page of the Workspace's Integrations, ascending by id: the kept ones, or with archived the archived ones.
func (*Module) Params ¶
Params opens the stored params for the engine: a rotating secret is a list, the current value first.
func (*Module) Redact ¶
func (m *Module) Redact(row *ent.Integration) (RedactedConfig, error)
Redact opens the stored config and returns it without secrets.
func (*Module) RegenerateKey ¶
func (m *Module) RegenerateKey(ctx context.Context, s *ent.Scoped, id int64) (*ent.Integration, error)
RegenerateKey gives the Integration a new hook key: the old hook URL stops working at once. The write is audited like any other edit of the Integration; the key itself never reaches the entry.
func (*Module) Unarchive ¶
Unarchive brings an archived Integration back to the lists. It does not become the default again. Restoring an Integration that is not archived changes nothing. An unknown id is ErrNotFound.
func (*Module) Update ¶
func (m *Module) Update(ctx context.Context, s *ent.Scoped, id int64, in UpdateInput) (*ent.Integration, error)
Update applies a partial edit. An unknown id is ErrNotFound.
func (*Module) View ¶
func (m *Module) View(row *ent.Integration) (ParamsView, error)
View opens the stored params and returns them without a secret.
type ParamsView ¶
ParamsView is the read side of an Integration's params: the values as saved with each secret masked, and the secrets that are rotating.
type PresetChange ¶
PresetChange is the Preset of a write: unset keeps the stored one, Name nil removes it.
type QuotaEnqueuer ¶
type QuotaEnqueuer interface {
EnqueueIntegrationQuotaRefresh(ctx context.Context, integrationID int64) error
}
QuotaEnqueuer schedules a read of one Integration's provider send quota (ADR 0023).
type RedactedConfig ¶
type RedactedConfig struct {
SMTP *RedactedSMTP
SES *RedactedSES
Inbox *RedactedInbox
}
RedactedConfig is the read-side provider config: no password, no secret key.
type RedactedInbox ¶
type RedactedInbox struct{}
RedactedInbox is the Test inbox's config: it has no field.
type RedactedSES ¶
type RedactedSMTP ¶
type SESConfig ¶
type SESConfig struct {
Region string
AccessKeyID string
SecretAccessKey string
From string
FromName string
Endpoint string
}
SMTPConfig and SESConfig are the write-side provider settings, secrets included.
type SMTPConfig ¶
type SMTPConfig struct {
Host string
Port int
Username string
Password string
From string
FromName string
}
SMTPConfig and SESConfig are the write-side provider settings, secrets included.
type UpdateInput ¶
type UpdateInput struct {
Name *string
Enabled *bool
IsDefault *bool
MaxPerSecond Limit
MaxPerDay Limit
Config *ConfigInput
// Preset, Params and RetireSecrets edit the inbound side; see sealInbound.
Preset PresetChange
Params map[string]any
RetireSecrets bool
}
UpdateInput is a partial edit; nil fields keep the stored value. A nil Config keeps the credentials; inside a supplied Config, blank secrets keep the stored secret.