conformance

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: Apache-2.0 Imports: 39 Imported by: 0

Documentation

Overview

Package conformance is the Harbor Protocol conformance suite — the single binding pass/fail definition of "the Protocol surface works at version 0.1.0" (RFC §5 + master-plan Phase 62 detail block; D-080).

The suite exhaustively exercises every Protocol method (internal/protocol/methods), every Protocol error code (internal/protocol/errors), every documented event-filter shape, the Phase 59 versioning + capability handshake, and the Phase 61 auth pipeline. It runs the same scenario bodies against TWO transports:

  • In-process — direct `protocol.ControlSurface.Dispatch` calls. No HTTP; the transport-agnostic surface Phase 54 shipped.
  • Over-the-wire — the Phase 60 mux mounted on an `httptest.Server`, including the Phase 61 auth middleware. JWT bearers, JSON bodies, HTTP status codes.

A conformance pass means the Protocol surface is consistent across the two consumer profiles a Console (the canonical client) would reach the runtime through: in-process embedding (e.g. `harbor dev`'s own SPA mount) and remote (a third-party Console over the wire).

Consumer pattern

The suite is itself a reusable artifact (D-025): one shared `Stack` serves N concurrent invocations. Consumers wire a `Factory` that builds a fresh `Stack` per top-level subtest (each subtest gets its own in-mem state, its own event bus, its own task registry, its own JWT keypair) and pass it to `RunSuite(t, factory)`:

func TestProtocol_Conformance(t *testing.T) {
    conformance.RunSuite(t, conformance.NewDefaultFactory())
}

The default factory wires real drivers everywhere on the seam — real `tasks.TaskRegistry` (inprocess), real `events.EventBus` (inmem), real `state.StateStore` (inmem), real `protocol.ControlSurface`, real `protocol/auth.Validator` over a real ES256 keypair, real Phase 60 `transports.NewMux` under `httptest.Server`. A future Protocol transport (WebSocket, stdio) consumes the suite via the same Factory seam — no second conformance implementation.

Exhaustiveness

The suite asserts the matrix's exhaustiveness at boot:

  • Every entry in `methods.Methods()` has a happy-path AND a malformed-request scenario.
  • Every entry in `errors` `canonicalCodes` (via the eight constants enumerated in errorCodeMatrix below) has at least one failure scenario surfacing it.
  • Every entry in `types.Capabilities()` is observed in the version handshake test.

A new Protocol method, error code, or capability constant lands in the same PR as its conformance entry; the exhaustiveness check fails loudly otherwise — the failure mode the suite exists to prevent (silent surface drift) is mechanically guarded.

Concurrent reuse (D-025)

`RunSuite` is safe to call concurrently against a single factory: the factory builds a fresh `Stack` per subtest, and every scenario closes over its own request, response, identity, and (for the wire transport) per-request HTTP client. The concurrent-reuse scenario runs N=100 mixed-method invocations against ONE shared `Stack` under `-race` to pin the contract.

Index

Constants

This section is empty.

Variables

View Source
var FixedNow = time.Date(2026, 5, 15, 12, 0, 0, 0, time.UTC)

FixedNow is the deterministic clock the suite's JWT validator + token minter share so exp/nbf behaviour is reproducible across runs. Exported so external consumers (e.g. `test/integration/wave10_test.go`'s own Stack builder) can pin to the same instant — keeping `fixedNow` in one canonical home instead of two `time.Date(2026, 5, 15, 12, 0, 0, 0, time.UTC)` literals (PR #91, Wave 10 audit NIT-3). The concrete value is irrelevant — what matters is that every JWT signer + every validator sees the same instant.

Functions

func RunSuite

func RunSuite(t *testing.T, factory Factory)

RunSuite runs every scenario as a subtest. Consumers wire a Factory that builds a fresh Stack per top-level subtest; the suite itself owns the matrix definition.

The suite asserts the matrix's exhaustiveness at the top of the run:

  • Every entry in methods.Methods() appears as a happy-path scenario name.
  • Every entry in errorCodeMatrix is in lockstep with the canonical errors package's IsValidCode.
  • Every entry in types.Capabilities() is observed by the version handshake test.

A new method / code / capability without a corresponding scenario fails the suite at boot — the silent-surface-drift failure mode the suite exists to prevent is mechanically guarded.

Types

type Factory

type Factory func(t *testing.T) *Stack

Factory builds a fresh Stack per subtest. Implementations MUST wire real drivers everywhere on the seam — a mock at the boundary defeats the conformance suite's purpose (CLAUDE.md §17.3).

func NewDefaultFactory

func NewDefaultFactory(testdataRoot string) Factory

NewDefaultFactory returns the canonical factory used by Harbor's own conformance test. It wires:

  • real `tasks.TaskRegistry` (inprocess driver),
  • real `events.EventBus` (inmem driver),
  • real `state.StateStore` (inmem driver),
  • real `protocol.ControlSurface`,
  • real `protocol/auth.Validator` over a real ES256 keypair (loaded from `internal/protocol/auth/testdata/`),
  • real Phase 60 `transports.NewMux` with the Phase 61 validator threaded via `WithValidator`.

A keypath argument lets a consumer relocate the testdata directory (useful when the suite is invoked from `test/integration/`); an empty string falls back to the package-relative default `../auth/testdata`.

type Stack

type Stack struct {
	// Surface is the in-process Protocol task-control surface (Phase
	// 54). The in-process transport scenarios reach the runtime
	// through `Surface.Dispatch`.
	Surface *protocol.ControlSurface
	// Bus is the real events.EventBus the SSE wire transport
	// subscribes to and the runtime publishes lifecycle events on.
	Bus events.EventBus
	// Steering is the steering.Registry behind Surface — the
	// nine-control methods enqueue events on inboxes opened here.
	// Exposed so scenarios can pre-open an inbox before submitting a
	// control (mirroring the Wave 9 pattern).
	Steering *steering.Registry
	// Tasks is the real tasks.TaskRegistry behind Surface — the
	// `start` method spawns on this; identity-propagation scenarios
	// read spawned tasks back via Get to verify the triple landed.
	Tasks tasks.TaskRegistry
	// Mux is the Phase 60 wire mux mounted on a Phase 61 validator.
	// The over-the-wire scenarios round-trip through `httptest.Server`
	// against this handler.
	Mux http.Handler
	// SignToken mints a valid bearer token for the given identity +
	// scopes against the validator's KeySet. Wire-transport scenarios
	// call SignToken to obtain the Authorization: Bearer header.
	SignToken func(t *testing.T, id identity.Identity, scopes []auth.Scope) string
	// SignHS256Token mints an HS256-signed token using the suite's
	// ES256 public key bytes as the HMAC secret. Exercises the
	// classical algorithm-confusion attack the parser-level allowlist
	// closes (CLAUDE.md §7 rule 1).
	SignHS256Token func(t *testing.T, id identity.Identity) string
	// SignAlgNoneToken mints an `alg: none` token. Exercises RFC 7519
	// §6.1's escape hatch the validator MUST reject (CLAUDE.md §7).
	SignAlgNoneToken func(t *testing.T, id identity.Identity) string
	// SignExpiredToken mints an otherwise-valid token whose `exp` is
	// in the past relative to fixedNow.
	SignExpiredToken func(t *testing.T, id identity.Identity) string
	// Cleanup tears down every driver the factory opened. Called by
	// the suite after every top-level subtest.
	Cleanup func()
}

Stack is the per-subtest seam — the real-driver runtime surface + the wired Protocol transports a conformance scenario exercises. Each top-level subtest gets a fresh Stack (via Factory) so per-test state (the task registry, the event bus, the steering registry) does not bleed across subtests. The Stack itself is a D-025 compiled artifact — its fields are set once at construction and never mutated; the concurrent-reuse scenario runs N≥100 invocations against one shared Stack.

Jump to

Keyboard shortcuts

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