Help us shape the future of Go! Take the 2026 Go Developer Survey

contract

package
v0.113.1 Latest Latest
Warning

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

Go to latest
Published: Oct 21, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package contract holds the parts of the serverless endpoint contract that are not protobuf messages: header names, the upgrade signature payload, wire constants and the protojson encoding every message travels in. The messages themselves are generated from api-contracts/v1/serverless.proto into internal/services/shared/proto/v1, which is also the source of the endpoint SDK's TypeScript types.

Package contract holds the constants shared between the serverless operator core and the API server: the data ids for secrets encrypted at rest. Both sides must agree on these for ciphertext written by one to be readable by the other.

Index

Constants

View Source
const (
	SignatureHeader  = "X-Hatchet-Signature"
	EndpointIdHeader = "X-Hatchet-Endpoint-Id"
	// TimestampHeader carries the time the request was built as decimal Unix seconds (not
	// milliseconds or nanoseconds), the same value as the body's timestamp_unix_seconds. An
	// endpoint rejects a value more than RequestMaxAge (5 minutes) from its own clock in
	// either direction.
	TimestampHeader = "X-Hatchet-Timestamp"
)

Headers carried by every request the operator sends to an endpoint. Endpoints verify SignatureHeader by recomputing the HMAC-SHA256 hex digest of the raw body with their signing secret (Verify). The signed body of every POST (v1.ServerlessHealthcheckRequest, v1.ServerlessTriggerRequest) carries the operator's timestamp in Unix seconds; an endpoint rejects a body whose timestamp lies more than RequestMaxAge from its own clock in either direction, so a captured request cannot be replayed later. Within that window a delivery may be repeated: endpoints key side effects on (endpoint id, task run external id, retry count).

View Source
const (
	NonceHeader      = "X-Hatchet-Nonce"
	TaskIdHeader     = "X-Hatchet-Task-Id"
	InvocationHeader = "X-Hatchet-Invocation"
)

Headers carried only by the durable websocket upgrade, which has no body to sign. The endpoint verifies SignatureHeader against UpgradeSigningPayload with its signing secret, rejects a TimestampHeader more than UpgradeMaxAge from its clock in either direction, consumes NonceHeader from a nonce set after the signature verified so a captured upgrade cannot be replayed within the window (every accepted nonce is kept until its window has passed; an endpoint whose nonce storage cannot admit another refuses the upgrade rather than forget a live nonce), and checks that the first frame's task id and invocation are the ones the headers were signed for.

View Source
const (
	// ErrorCodeNonDeterminism reports a replay that diverged from the log.
	ErrorCodeNonDeterminism = "nondeterminism"
	// ErrorCodeUnspecified is every other engine-side error.
	ErrorCodeUnspecified = "unspecified"
)

Codes of v1.ServerlessErrorFrame.

View Source
const DoneStatusEvicted = "evicted"

DoneStatusEvicted is the v1.ServerlessDoneFrame status of an invocation that evicted itself.

View Source
const RequestMaxAge = 5 * time.Minute

RequestMaxAge is how far a signed timestamp may lie from the endpoint's clock, in either direction, before the endpoint rejects the request. It applies to the timestamp inside every signed POST body and to the upgrade's TimestampHeader.

View Source
const SigningSecretEncryptionDataID = "v1_serverless_endpoint_signing_secret" //nolint:gosec // associated-data label for envelope encryption, not a credential

SigningSecretEncryptionDataID is the associated data used when encrypting a serverless endpoint's signing secret with pkg/encryption. It binds the ciphertext in v1_serverless_endpoint.signing_secret_enc to that column so it cannot be replayed as any other secret.

View Source
const TriggerEnvelopeVersion = 1

TriggerEnvelopeVersion is the version field of v1.ServerlessTriggerRequest.

View Source
const UpgradeMaxAge = RequestMaxAge

UpgradeMaxAge is RequestMaxAge as it applies to the durable upgrade.

Variables

This section is empty.

Functions

func Marshal

func Marshal(m proto.Message) ([]byte, error)

Marshal encodes a contract message as protojson.

func MarshalFrame

func MarshalFrame(frame *v1.ServerlessDurableFrame) ([]byte, error)

MarshalFrame encodes one durable websocket frame.

func Sign

func Sign(data string, secret string) (string, error)

Sign returns the hex-encoded HMAC-SHA256 of data under secret, the value carried in SignatureHeader. The key is checked against the FIPS minimum length first, so a short secret is an error instead of a panic.

func Unmarshal

func Unmarshal(raw []byte, m proto.Message) error

Unmarshal decodes protojson into m, ignoring unknown fields.

func UnmarshalFrame

func UnmarshalFrame(raw []byte) (*v1.ServerlessDurableFrame, error)

UnmarshalFrame decodes one durable websocket frame.

func UpgradeSigningPayload

func UpgradeSigningPayload(endpointId, timestamp, nonce, taskId, invocation string) string

UpgradeSigningPayload is the string the durable upgrade signature covers: endpoint_id "." timestamp "." nonce "." task_id "." invocation, each as it appears in its header. The endpoint id is part of it so a signature made for one endpoint cannot be presented to another that shares the signing secret: the endpoint verifies the id it serves against the signed one, not against an unsigned header alone.

func Verify

func Verify(data string, secret string, signature string) bool

Verify reports whether signature is the HMAC-SHA256 hex signature of data under secret. The comparison is constant-time.

Types

This section is empty.

Jump to

Keyboard shortcuts

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