selftest

package
v1.8.8 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package selftest defines the e2a critical-path self-test: a small battery of scenarios that exercise the real product paths (liveness, authenticated read, the inbound SMTP→webhook round-trip with HMAC verification, and a self-send loopback) against a running instance.

The same battery is consumed three ways (see docs/design/prober-selftest.md):

  • the e2e tests (in-process, against testutil.TestServer);
  • the `e2a selftest` CLI (self-hosters validating an install);
  • cmd/e2a-prober (continuous prod monitor + deploy bake-gate signal).

Scenarios are data (a []Scenario), so adding a check is a list edit. Each scenario carries a SmokeSafe flag: only read-only / round-trip / loopback scenarios that cause no real-world side effect (no external email, no owner notifications, no metering) may run against production. The prober runs only the SmokeSafe subset against live prod; the full set runs in-process.

Index

Constants

This section is empty.

Variables

View Source
var All = []Scenario{
	{Name: "liveness", SmokeSafe: true, Run: scenarioLiveness},
	{Name: "auth_read", SmokeSafe: true, Run: scenarioAuthRead},

	{Name: "delegated_auth", SmokeSafe: true, Run: scenarioDelegatedAuth},
	{Name: "inbound_round_trip", SmokeSafe: true, Run: scenarioInboundRoundTrip},

	{Name: "outbound_send", SmokeSafe: true, Run: scenarioOutboundSend},
	{Name: "self_send_loopback", SmokeSafe: true, Run: scenarioSelfSendLoopback},

	{Name: "websocket_round_trip", SmokeSafe: true, Run: scenarioWebSocketRoundTrip},

	{Name: "agent_lifecycle", SmokeSafe: true, Run: scenarioAgentLifecycle},

	{Name: "mcp_http_round_trip", SmokeSafe: true, Run: scenarioMCPHTTPRoundTrip},
}

All is the critical-path battery. Every scenario here is SmokeSafe: read-only, a loopback (no egress), the inbound round-trip (synthetic mail to the probe agent), or a real outbound send to the AWS mailbox simulator (no real recipient). None meters (the probe runs under a system-class account) and none emails an owner.

Functions

This section is empty.

Types

type Delivery

type Delivery struct {
	Headers http.Header
	Body    []byte
}

Delivery is one webhook callback captured by an HTTPSink.

type HTTPSink

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

HTTPSink is an http.Handler that captures webhook deliveries and lets a scenario await one matching a predicate. The shipped prober mounts it at /sink on its internal server; the in-process tests mount it on an httptest.Server. It is safe for concurrent use.

func NewHTTPSink

func NewHTTPSink() *HTTPSink

NewHTTPSink returns an empty sink.

func (*HTTPSink) Await

func (s *HTTPSink) Await(ctx context.Context, match func(Delivery) bool, timeout time.Duration) (*Delivery, error)

Await returns the first delivery (new or already-buffered) for which match returns true, or an error if ctx/timeout elapses first. It scans the buffer on every new delivery so out-of-order arrivals are handled.

func (*HTTPSink) ServeHTTP

func (s *HTTPSink) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP records the delivery and returns 200. Body read failures are recorded as empty deliveries (the awaiting scenario will simply not match and time out, surfacing the problem) rather than 500s.

type Probe

type Probe struct {
	HTTPBaseURL          string        // e.g. http://e2a:8080 — API + /api/health
	APIKey               string        // probe agent's API key (Bearer)
	AgentEmail           string        // the synthetic probe agent address
	SMTPAddr             string        // host:port of the inbound SMTP listener
	WebhookSecret        string        // signing secret of the probe webhook (HMAC verify)
	MCPBaseURL           string        // deployed streamable-HTTP MCP endpoint, e.g. http://mcp-server:3000/mcp; empty ⇒ mcp scenario skips
	RequireMCP           bool          // when true, an empty MCPBaseURL FAILS the mcp scenario instead of skipping — set on stacks where MCP must be probed (prod)
	DelegatedTokenURL    string        // trusted endpoint that vends one short-lived delegated token; empty ⇒ delegated scenario skips
	DelegatedTokenSecret string        // dedicated Bearer credential for DelegatedTokenURL; never logged
	RequireDelegatedAuth bool          // when true, incomplete delegated config FAILS instead of skipping
	Sink                 *HTTPSink     // receives the webhook callback for the round-trip
	HTTP                 *http.Client  // nil → defaultHTTPClient
	Timeout              time.Duration // round-trip await timeout; 0 → defaultRoundTripTimeout
}

Probe carries everything a scenario needs to talk to a running instance. It is transport-only config plus collaborators; it holds no test scaffolding so both the shipped prober and the in-process tests construct it directly.

func (*Probe) SweepMessages added in v1.7.12

func (p *Probe) SweepMessages() SweepResult

SweepMessages trashes live probe messages and then purges the trash.

The two steps are ordered, not alternatives: "delete forever" only accepts a message that is ALREADY in the trash (the store returns ErrNotInTrash, surfaced as 409 not_in_trash), so a live message has to be trashed first. Trashing is idempotent, so re-trashing a row another pass already moved is harmless.

Best-effort by construction: it runs AFTER every scenario has reported, takes its own context, and returns no error. A failed cleanup is hygiene debt, never a red battery — the same contract trashMessage and the sdk-monitor's _cleanup already follow, and for the same reason: a webhook redelivery or a flaky delete must not be able to turn a healthy stack red.

type Result

type Result struct {
	Name       string `json:"name"`
	Status     Status `json:"status"`
	DurationMS int64  `json:"duration_ms"`
	Detail     string `json:"detail,omitempty"` // human-readable; never contains secrets
}

Result is the outcome of one scenario run.

func Run

func Run(ctx context.Context, p *Probe, scenarios []Scenario, smokeOnly bool) []Result

Run executes the given scenarios in order and returns their results. When smokeOnly is true, scenarios with SmokeSafe=false are skipped (use this when running against production). Run never aborts early — every scenario runs so the caller sees the full picture in one pass.

type Scenario

type Scenario struct {
	Name      string
	SmokeSafe bool
	Run       func(ctx context.Context, p *Probe) Result
}

Scenario is one critical-path check. Run is given the resolved Probe and returns a Result; it must not panic on failure — return StatusFail with a Detail instead.

type Status

type Status string

Status is the tri-state result of a single scenario, mirroring the IETF health-check vocabulary (draft-inadarei-api-health-check).

const (
	StatusPass Status = "pass"
	StatusWarn Status = "warn"
	StatusFail Status = "fail"
)

func Worst

func Worst(results []Result) Status

Worst returns the most severe status across results (fail > warn > pass). An empty slice is treated as fail — "no checks ran" is not healthy.

type SweepResult added in v1.7.12

type SweepResult struct {
	Trashed int `json:"trashed"`
	Purged  int `json:"purged"`
}

SweepResult reports what one hygiene pass actually did.

Jump to

Keyboard shortcuts

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