Documentation
¶
Overview ¶
Package contractspec defines the runtime descriptor type for one contract endpoint, shared by the layers that bind contracts to wire protocols.
ContractSpec is consumed by:
- kernel/cell.Registrar.Subscribe (event subscription)
- kernel/wrapper.WrapConsumer / WrapSubscriber / HTTPHandler (decorators)
- runtime/auth.Mount (HTTP route binding)
- runtime/eventrouter (subscription routing + tracing)
- runtime/http/router (route attribution + cell label)
Extracted from kernel/wrapper to break the cell→wrapper reverse edge. After the extraction kernel/wrapper sits at the top tier and depends only on outbox + leaves (ctxkeys, contractspec). contractspec imports kernel/cellvocab for the ContractKind type and InternalPathPrefix constant (single source of truth, no lockstep duplication).
Cells MUST NOT construct ContractSpec literals directly. The valid construction sites are:
- generated/contracts/**/spec_gen.go (private `var spec`) — business contracts produced by contractgen codegen; subscription/route mounting goes through the generated NewSubscription / NewHandler adapters.
- runtime/internal/contractbuild.NewFrameworkHTTP — runtime-owned HTTP infrastructure endpoints (health probes, devtools catalog, etc.); the only legitimate construction path for framework ContractSpec values in runtime/ HTTP infra code. Content invariant Hard (frameworkHTTPIDPrefix A-class panic); upstream Hard — the runtime/internal/ placement makes the Go compiler refuse imports from outside the runtime/ subtree, so business code (cells/, examples/, cmd/, adapters/) cannot call it.
- runtime/internal/contractbuild.NewEventDerivation — tracing/observability projection of a validated outbox.Subscription; returns (ContractSpec, error) with sub.Validate() + ContractSpec.Validate() embedded inside the funnel (shape-Hard, NOT provenance-Hard). Upstream caller-set Hard via the runtime/internal/ placement; the typed Subscription parameter forces shape but does NOT type-enforce value provenance (outbox.Subscription has exported fields — a runtime/ caller can fabricate one), so provenance is a runtime data-flow property (eventrouter), Hard-ifiable only by a sealed Subscription constructor (gh #1532). See contractbuild/doc.go grading.
- runtime/internal/contractbuild.NewWebhookDispatch — derivation of the event-kind subscription spec from a validated webhook.DispatchSpec; returns (ContractSpec, error) with spec.Validate() + ContractSpec.Validate() embedded inside the funnel (shape-Hard, NOT provenance-Hard). Upstream caller-set Hard via runtime/internal/ placement (compiler refuses imports from outside runtime/); the typed webhook.DispatchSpec parameter forces shape but does NOT type-enforce value provenance (exported fields), so provenance is a runtime data-flow property (cellgen→RegistrySnapshot), Hard-ifiable only by a sealed DispatchSpec constructor (gh #1532). See contractbuild/doc.go grading.
Three archtest gates enforce this invariant:
- CELLS-NO-CONTRACTSPEC-IMPORT-01
- NO-MANUAL-CONTRACTSPEC-LITERAL-01
- EVENT-SUBSCRIPTION-CONTRACTGEN-COVERAGE-01
ref: k8s.io/apimachinery — lightweight value types shared across layers without runtime parsing dependencies.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ContractSpec ¶
type ContractSpec struct {
// ID is the contract identifier, e.g. "http.auth.login.v1" or
// "event.session.revoked.v1". It MUST match the id field in the
// contract.yaml file identified by Kind + path.
ID string
// Kind is one of ContractHTTP | ContractEvent | ContractCommand |
// ContractProjection | ContractWebhook | ContractGRPC | ContractSaga.
Kind cellvocab.ContractKind
// Transport names the wire protocol the binding uses: "http" for Kind=="http",
// "grpc" for Kind=="grpc", "amqp" / "mqtt" / "internal" for event/command/
// projection. It is the PRIMARY transport — codegen derives it as the first
// element of the contract's `transports:` set (transports[0]); a
// multi-transport contract (e.g. event over [amqp, mqtt]) exposes the full
// sanctioned set via the generated package's `Transports()` accessor (which
// returns a copy so the truth source cannot be aliased), while this field
// carries the primary the production binding routes over. Membership in
// cellvocab.AllTransports() is governed at the declaration layer (FMT-39 +
// schema enum), not at runtime — see Validate.
Transport string
// HTTP-specific fields; required when Kind == "http", rejected otherwise.
Method string // upper-case HTTP verb
Path string // path template, e.g. "/api/v1/auth/login"
// Event-specific fields; required when Kind == "event", rejected
// otherwise. Topic is the broker destination name.
Topic string
// Clients is the allowlist of caller cell IDs for internal HTTP endpoints.
// Required when Kind=="http" and Path has prefix "/internal/v1/"; must be
// empty for non-internal paths. The list is mirrored in contract.yaml
// endpoints.clients and enforced at runtime by auth.RequireCallerCell.
Clients []string
// GRPC carries the grpc transport details; required (non-nil) when
// Kind == "grpc", rejected otherwise.
GRPC *GRPCEndpointSpec
}
ContractSpec is the runtime descriptor for one contract endpoint. It is consumed by:
- runtime/auth.Mount (HTTP route binding)
- runtime/eventbus / kernel/cell.Registrar.Subscribe (event subscription)
- tracing span attributes (gocell.contract.id / kind / transport)
The zero value is invalid — callers must populate ID / Kind / Transport and the kind-specific fields, then rely on auth.Mount / wrapper.HTTPHandler to Validate() before registration.
Construction-site catalog and archtest enforcement gates are documented in this package's doc.go (single source). Composite literal under cells/, examples/*/cells/, and runtime/ is forbidden by archtest NO-MANUAL-CONTRACTSPEC-LITERAL-01.
ref: k8s.io/apimachinery — lightweight value types shared across layers without runtime parsing dependencies.
func (ContractSpec) GRPCInfo ¶
func (s ContractSpec) GRPCInfo() *GRPCEndpointSpec
GRPCInfo returns the grpc transport descriptor for a grpc-kind spec, or nil for any other kind. Callers use it to read service/method without a type switch on Kind.
func (ContractSpec) Validate ¶
func (s ContractSpec) Validate() error
Validate returns an error if the spec is malformed. Validation is separate from construction so test fixtures can assert negative cases without the cost of a full wrapper.HTTPHandler call.
type GRPCEndpointSpec ¶
type GRPCEndpointSpec struct {
Service string // proto FQ service name, e.g. "device.command.v1.DeviceCommandService"
Proto string // contracts-relative .proto path
// ProtoPackage is the proto `package` declaration (e.g. "device.command.v1").
// The contractgen ProtoRegistry resolves it from the .proto starting PR 6;
// runtime ContractSpec population lands PR 8 (first real grpc contract
// registration). Empty until then; must not be relied upon.
ProtoPackage string
}
GRPCEndpointSpec is the grpc-kind transport descriptor carried by ContractSpec.GRPC. It mirrors metadata.GRPCTransportMeta but is the runtime value type (kernel/contractspec is dependency-free of metadata parsing at the registration boundary). A single contract owns a whole proto service (#1655); the .proto file is the single source of truth for the RPC method set. ProtoPackage is the proto file's `package` declaration.