Documentation
¶
Overview ¶
Package preset is the Preset engine (ADR 0037): a Preset describes one provider's inbound callbacks, how a request is verified and how its payload becomes Delivery notices. The engine does no I/O: it takes a Preset, the raw request and the Integration's params and returns the validated Delivery notices, an optional action for the caller to perform, or a typed error.
Index ¶
- Constants
- Variables
- func TestSNSCertificates(context.Context, string) (*x509.Certificate, error)
- type Action
- type ActionKind
- type CaseResult
- type CertFetcher
- type DeliveryNotice
- type Kind
- type Option
- type Params
- type Preset
- func (p *Preset) Description() string
- func (p *Preset) Handle(ctx context.Context, req Request, params Params, now time.Time) (Result, error)
- func (p *Preset) Name() string
- func (p *Preset) ParamsSchema() map[string]any
- func (p *Preset) RunTests(ctx context.Context) []CaseResult
- func (p *Preset) SecretParams() []string
- func (p *Preset) Test(ctx context.Context) error
- func (p *Preset) ValidateParams(values Params) error
- type Registry
- type Request
- type Result
Constants ¶
const ( // MaxBodyBytes is the largest request body the engine parses. MaxBodyBytes = 1 << 20 // MaxProgramBytes is the largest transform program. MaxProgramBytes = 16 << 10 // MaxNotices is the most Delivery notices one request may yield. // contract-copy: provider preset cap on Delivery notices per request; not in the contract MaxNotices = 100 // TransformTimeout bounds one run of a transform. TransformTimeout = 100 * time.Millisecond )
Limits on what one request may make the engine do.
const MaxReasonChars = 500
MaxReasonChars caps a notice's provider reason, in characters. contract-copy: cap of the reason an email delivery Event keeps; not in the contract
Variables ¶
var ( // ErrUnauthentic: the request did not come from the provider for this Integration. ErrUnauthentic = errors.New("preset: request is not authentic") // ErrMalformed: the body is not JSON, or is over the limit. ErrMalformed = errors.New("preset: request is malformed") // ErrTransformFailed: the transform failed, timed out or returned something that is // not a list of valid Delivery notices. ErrTransformFailed = errors.New("preset: transform failed") // failed (the signing certificate could not be fetched). It says nothing about the // request, so a caller answers 5xx and the provider retries. ErrUnavailable = errors.New("preset: verification is unavailable") )
The ways a request is refused. A caller answers 4xx for the first three: the request is the provider's to fix, a retry would not change it. ErrUnavailable is ours: 5xx.
var Schema []byte
Schema is the JSON Schema of the Preset file (draft 2020-12), published for editors (`# yaml-language-server: $schema=...`) and the validator the loader uses.
Functions ¶
func TestSNSCertificates ¶
TestSNSCertificates serves the test certificate for any URL. A Preset runs its `tests` with it, never in production.
Types ¶
type Action ¶
type Action struct {
Kind ActionKind
URL string
}
Action is a side effect the engine asks of its caller, which performs it through the SSRF-guarded client.
type ActionKind ¶
type ActionKind string
ActionKind is something the caller performs for the engine.
const ActionConfirm ActionKind = "confirm"
ActionConfirm means fetch URL to confirm a subscription (SNS).
type CaseResult ¶
CaseResult is the outcome of one of the Preset's own tests: Err is nil when the case passed, and says how it disagreed otherwise.
type CertFetcher ¶
CertFetcher returns the signing certificate at an already host-checked URL.
type DeliveryNotice ¶
type DeliveryNotice struct {
// ID is the provider's event id; with Destination it dedupes a redelivery.
ID string `json:"id"`
// Destination is the normalized (trimmed, lower-cased) address.
Destination string `json:"destination"`
Kind Kind `json:"kind"`
// Permanent is meaningful for a bounce only.
Permanent bool `json:"permanent"`
// SendingDomain is the lower-cased domain the message was sent from, "" when unknown.
SendingDomain string `json:"sending_domain,omitempty"`
// MessageID is the provider's id of the message the notice is about, "" when the
// provider returns none: it links the notice to its Outbound message.
MessageID string `json:"message_id,omitempty"`
// Reason is the provider's short explanation of a bounce, delay or drop, capped at
// MaxReasonChars characters.
Reason string `json:"reason,omitempty"`
}
DeliveryNotice is the one normalized shape every Preset produces. Only a permanent bounce or a complaint enters Suppression; a transient bounce still counts in the deliverability rates.
type Option ¶
type Option func(*options)
Option configures how Presets are built.
func WithSNSCertificates ¶
func WithSNSCertificates(f CertFetcher) Option
WithSNSCertificates replaces how an `sns` Preset fetches the signing certificate, which is an HTTPS request through the SSRF-guarded client by default.
type Params ¶
Params are the values the Owner entered on the Integration, validated against the Preset's params schema. A secret is a string, or a list of strings (the current one first, then the one being retired) while it rotates.
type Preset ¶
type Preset struct {
// contains filtered or unexported fields
}
Preset is a parsed, validated and compiled Preset file.
func Parse ¶
Parse reads one Preset file: it must be YAML, valid against the published Preset JSON Schema, carry a params schema that compiles, a verify block that is coherent and a transform that compiles. An error names the file and the line.
func (*Preset) Description ¶
Description is the Preset's one-line description, possibly empty.
func (*Preset) Handle ¶
func (p *Preset) Handle(ctx context.Context, req Request, params Params, now time.Time) (Result, error)
Handle verifies the request and turns its payload into Delivery notices. Nothing reaches the transform unverified: a header scheme checks the raw bytes before any parsing, a body scheme parses under the body limit, verifies, and only then transforms. now is the clock, for timestamp tolerance.
func (*Preset) ParamsSchema ¶
ParamsSchema is the JSON Schema of the params, as the Preset file wrote it.
func (*Preset) RunTests ¶
func (p *Preset) RunTests(ctx context.Context) []CaseResult
RunTests runs each case the Preset carries: it posts the case's request with its params and clock and expects the Delivery notices, or the refusal, it names.
func (*Preset) SecretParams ¶
SecretParams names the params the schema marks `writeOnly`: secrets, which are stored encrypted, never returned by a read and rotated rather than replaced.
func (*Preset) Test ¶
Test runs the cases the Preset carries; the error lists every case that disagreed.
func (*Preset) ValidateParams ¶
ValidateParams checks the Integration's values against the params schema.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds every Preset of an Instance: the built-in ones and the Self-hoster's.
func Load ¶
Load parses the built-in Presets and, when custom is not nil, every *.yaml and *.yml file at its root. It is the one entry the server uses at start: a file that fails to parse, to validate or to compile, or a name that collides with a built-in (or with another custom file), is an error naming the file.
type Request ¶
type Request struct {
Header http.Header
// Body is the raw body, exactly as received.
Body []byte
}
Request is what arrived at the hook.
type Result ¶
type Result struct {
Notices []DeliveryNotice
Action *Action
}
Result of a verified request.