package serving

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
)

var (
	// ErrIngressReceiptDependencyMissing reports that the immutable ingress
	// repository cannot be constructed or called with its required dependency.
	ErrIngressReceiptDependencyMissing = errors.New("connector serving: ingress receipt dependency missing")
	// ErrUnsupportedIngressReceiptProtocol reports an omitted or unknown exact
	// retained protocol used by a V2Receipt, ReceiptComponent, or
	// ReceiptAdmissionKey.
	ErrUnsupportedIngressReceiptProtocol = errors.New("connector serving: unsupported ingress receipt protocol")
	// ErrInvalidIngressReceipt reports caller-authored material outside the
	// closed immutable V2 transport-admission contract.
	ErrInvalidIngressReceipt = errors.New("connector serving: invalid ingress receipt")
	// ErrIngressReceiptIdentityConflict reports that a stable receipt, admission
	// key, or transport identity already names different immutable bytes.
	ErrIngressReceiptIdentityConflict = errors.New("connector serving: ingress receipt identity conflict")
	// ErrStoredIngressReceiptInvalid reports a partial, mixed, or corrupt
	// persisted V2Receipt/ReceiptAdmissionKey graph.
	ErrStoredIngressReceiptInvalid = errors.New("connector serving: stored ingress receipt invalid")
	// ErrIngressReceiptSchemaUnavailable reports that the catalog-owned physical
	// authority shape is absent or has drifted.
	ErrIngressReceiptSchemaUnavailable = errors.New("connector serving: ingress receipt schema unavailable")
	// ErrIngressReceiptAdmissionConflict reports that the exact gate/fence/epoch
	// observation no longer permits a new V2 transport admission.
	ErrIngressReceiptAdmissionConflict = errors.New("connector serving: ingress receipt admission conflict")
)

type ReceiptProtocolVersion string
type ReceiptComponentProtocolVersion string
type ReceiptAdmissionKeyProtocolVersion string
type PayloadCiphertextProtocolVersion string
type PredecessorReferenceProtocolVersion string
type ReceiptAdmissionKind string
type ReceiptAdmissionDisposition string
type IngressChannel string

const (
	ReceiptProtocolV1              ReceiptProtocolVersion              = "nexuscrm.connector-v2-receipt/v1"
	ReceiptComponentProtocolV1     ReceiptComponentProtocolVersion     = "nexuscrm.connector-v2-receipt-component/v1"
	ReceiptAdmissionKeyProtocolV1  ReceiptAdmissionKeyProtocolVersion  = "nexuscrm.connector-v2-receipt-admission-key/v1"
	PayloadCiphertextProtocolV1    PayloadCiphertextProtocolVersion    = "nexuscrm.connector-v2-payload-ciphertext/v1"
	PredecessorReferenceProtocolV1 PredecessorReferenceProtocolVersion = "nexuscrm.connector-v1-acceptance-reference/v1"

	ReceiptAdmissionKindTransport ReceiptAdmissionKind = "transport"

	ReceiptAdmissionDispositionV2Receipt   ReceiptAdmissionDisposition = "v2_receipt"
	ReceiptAdmissionDispositionV1Tombstone ReceiptAdmissionDisposition = "v1_tombstone"

	IngressChannelWebhook IngressChannel = "webhook"

	MaxIngressPayloadBytes           int64 = 1 << 20
	MaxIngressPayloadCiphertextBytes       = 2 << 20
	MaxPredecessorReferenceBytes           = 1 << 20
	// MaxReceiptComponentCount bounds one complete deterministic child set.
	MaxReceiptComponentCount int64 = 4096
	// MaxReceiptComponentSetBytes independently bounds the aggregate plaintext
	// sizes and ciphertext bytes retained by one Receipt component set.
	MaxReceiptComponentSetBytes uint64 = 64 << 20
)

// ReceiptComponentInput authors one detached immutable component value. A
// later publication slice attaches a complete set to TransportAdmission.
type ReceiptComponentInput struct {
	ComponentProtocolVersion         ReceiptComponentProtocolVersion
	PayloadCiphertextProtocolVersion PayloadCiphertextProtocolVersion
	ID                               string
	ReceiptID                        string
	ComponentOrdinal                 int64
	PayloadPlaintext                 []byte
	PayloadCiphertext                []byte
}

type V2TransportAdmissionInput struct {
	ReceiptProtocolVersion           ReceiptProtocolVersion
	AdmissionKeyProtocolVersion      ReceiptAdmissionKeyProtocolVersion
	PayloadCiphertextProtocolVersion PayloadCiphertextProtocolVersion
	ReceiptID                        string
	AdmissionKeyID                   string
	ServingScopeDigest               string
	ConnectorAccountID               string
	AccountServingGateID             string
	AccountServingFenceToken         int64
	ServingEpochID                   string
	ServingEpochDigest               string
	IngressChannel                   IngressChannel
	TransportIdempotencyKey          string
	PayloadPlaintext                 []byte
	PayloadCiphertext                []byte
}

// TransportIdentity is the sole exact transport-idempotency lookup coordinate.
// It deliberately excludes serving scope, current/latest epoch selectors, and
// payload bytes so retained authority survives scope and epoch transitions.
type TransportIdentity struct {
	connectorAccountID      string
	ingressChannel          IngressChannel
	transportIdempotencyKey string
}

func NewTransportIdentity(
	connectorAccountID string,
	ingressChannel IngressChannel,
	transportIdempotencyKey string,
) (TransportIdentity, error) {
	identity := TransportIdentity{
		connectorAccountID:      connectorAccountID,
		ingressChannel:          ingressChannel,
		transportIdempotencyKey: transportIdempotencyKey,
	}
	if err := identity.validate(); err != nil {
		return TransportIdentity{}, err
	}
	return identity, nil
}

func (identity TransportIdentity) ConnectorAccountID() string     { return identity.connectorAccountID }
func (identity TransportIdentity) IngressChannel() IngressChannel { return identity.ingressChannel }
func (identity TransportIdentity) TransportIdempotencyKey() string {
	return identity.transportIdempotencyKey
}

func (identity TransportIdentity) validate() error {
	if !validOpaqueIdentifierWithin(identity.connectorAccountID, connectorDigestProfileV2MaxIdentifierBytes) {
		return invalidIngressReceipt("connector account ID is not canonical")
	}
	if identity.ingressChannel != IngressChannelWebhook {
		return invalidIngressReceipt("ingress channel %q is outside the closed contract", identity.ingressChannel)
	}
	if !validOpaqueIdentifierWithin(string(identity.ingressChannel), 64) {
		return invalidIngressReceipt("ingress channel is not canonical")
	}
	if !validOpaqueIdentifierWithin(identity.transportIdempotencyKey, connectorDigestProfileV2MaxIdentifierBytes) {
		return invalidIngressReceipt("transport idempotency key is not canonical")
	}
	return nil
}

// ReceiptComponent is one immutable deterministic member of a V2Receipt. It
// owns no Event, claim, retry, execution, or provider-I/O state.
type ReceiptComponent struct {
	componentProtocolVersion         ReceiptComponentProtocolVersion
	id                               string
	receiptID                        string
	componentOrdinal                 int64
	payloadCiphertextProtocolVersion PayloadCiphertextProtocolVersion
	payloadCiphertext                []byte
	payloadDigest                    string
	payloadSizeBytes                 int64
}

func NewReceiptComponent(input ReceiptComponentInput) (ReceiptComponent, error) {
	if input.ComponentProtocolVersion != ReceiptComponentProtocolV1 ||
		input.PayloadCiphertextProtocolVersion != PayloadCiphertextProtocolV1 {
		return ReceiptComponent{}, fmt.Errorf(
			"%w: component=%q payload=%q",
			ErrUnsupportedIngressReceiptProtocol,
			input.ComponentProtocolVersion,
			input.PayloadCiphertextProtocolVersion,
		)
	}
	if !validOpaqueIdentifierWithin(input.ID, connectorDigestProfileV2MaxIdentifierBytes) ||
		!validOpaqueIdentifierWithin(input.ReceiptID, connectorDigestProfileV2MaxIdentifierBytes) {
		return ReceiptComponent{}, invalidIngressReceipt("component or receipt ID is not canonical")
	}
	if input.ComponentOrdinal < 0 || input.ComponentOrdinal >= MaxReceiptComponentCount {
		return ReceiptComponent{}, invalidIngressReceipt("component ordinal is outside the closed bound")
	}
	if len(input.PayloadCiphertext) == 0 || len(input.PayloadCiphertext) > MaxIngressPayloadCiphertextBytes {
		return ReceiptComponent{}, invalidIngressReceipt("component payload ciphertext bytes are outside the closed bound")
	}
	if int64(len(input.PayloadPlaintext)) > MaxIngressPayloadBytes {
		return ReceiptComponent{}, invalidIngressReceipt("component plaintext payload exceeds the closed bound")
	}
	component := ReceiptComponent{
		componentProtocolVersion:         input.ComponentProtocolVersion,
		id:                               input.ID,
		receiptID:                        input.ReceiptID,
		componentOrdinal:                 input.ComponentOrdinal,
		payloadCiphertextProtocolVersion: input.PayloadCiphertextProtocolVersion,
		payloadCiphertext:                append([]byte(nil), input.PayloadCiphertext...),
		payloadDigest:                    prefixedIngressDigest(input.PayloadPlaintext),
		payloadSizeBytes:                 int64(len(input.PayloadPlaintext)),
	}
	if err := component.validateStored(); err != nil {
		return ReceiptComponent{}, fmt.Errorf("%w: %v", ErrInvalidIngressReceipt, err)
	}
	return component, nil
}

func (component ReceiptComponent) ComponentProtocolVersion() ReceiptComponentProtocolVersion {
	return component.componentProtocolVersion
}
func (component ReceiptComponent) ID() string              { return component.id }
func (component ReceiptComponent) ReceiptID() string       { return component.receiptID }
func (component ReceiptComponent) ComponentOrdinal() int64 { return component.componentOrdinal }
func (component ReceiptComponent) PayloadDigest() string   { return component.payloadDigest }
func (component ReceiptComponent) PayloadSizeBytes() int64 { return component.payloadSizeBytes }
func (component ReceiptComponent) PayloadCiphertextProtocolVersion() PayloadCiphertextProtocolVersion {
	return component.payloadCiphertextProtocolVersion
}
func (component ReceiptComponent) PayloadCiphertext() []byte {
	return append([]byte(nil), component.payloadCiphertext...)
}

func (component ReceiptComponent) copy() ReceiptComponent {
	component.payloadCiphertext = append([]byte(nil), component.payloadCiphertext...)
	return component
}

func (component ReceiptComponent) equal(other ReceiptComponent) bool {
	return component.componentProtocolVersion == other.componentProtocolVersion &&
		component.id == other.id &&
		component.receiptID == other.receiptID &&
		component.componentOrdinal == other.componentOrdinal &&
		component.payloadCiphertextProtocolVersion == other.payloadCiphertextProtocolVersion &&
		bytes.Equal(component.payloadCiphertext, other.payloadCiphertext) &&
		component.payloadDigest == other.payloadDigest &&
		component.payloadSizeBytes == other.payloadSizeBytes
}

func (component ReceiptComponent) validateStored() error {
	if component.componentProtocolVersion != ReceiptComponentProtocolV1 {
		return storedIngressReceiptInvalid("unsupported receipt component protocol %q", component.componentProtocolVersion)
	}
	if !validOpaqueIdentifierWithin(component.id, connectorDigestProfileV2MaxIdentifierBytes) ||
		!validOpaqueIdentifierWithin(component.receiptID, connectorDigestProfileV2MaxIdentifierBytes) {
		return storedIngressReceiptInvalid("component or receipt ID is not canonical")
	}
	if component.componentOrdinal < 0 || component.componentOrdinal >= MaxReceiptComponentCount {
		return storedIngressReceiptInvalid("component ordinal is outside the closed bound")
	}
	if component.payloadCiphertextProtocolVersion != PayloadCiphertextProtocolV1 {
		return storedIngressReceiptInvalid(
			"unsupported component payload ciphertext protocol %q",
			component.payloadCiphertextProtocolVersion,
		)
	}
	if len(component.payloadCiphertext) == 0 || len(component.payloadCiphertext) > MaxIngressPayloadCiphertextBytes {
		return storedIngressReceiptInvalid("component payload ciphertext bytes are outside the closed bound")
	}
	if !prefixedSHA256Pattern.MatchString(component.payloadDigest) {
		return storedIngressReceiptInvalid("component payload digest is not canonical")
	}
	if component.payloadSizeBytes < 0 || component.payloadSizeBytes > MaxIngressPayloadBytes {
		return storedIngressReceiptInvalid("component payload size is outside the closed bound")
	}
	return nil
}

type V2Receipt struct {
	receiptProtocolVersion           ReceiptProtocolVersion
	id                               string
	servingScopeDigest               string
	connectorAccountID               string
	accountServingGateID             string
	accountServingFenceToken         int64
	servingEpochID                   string
	servingEpochDigest               string
	admissionKind                    ReceiptAdmissionKind
	admissionAuthorityID             string
	payloadCiphertextProtocolVersion PayloadCiphertextProtocolVersion
	payloadCiphertext                []byte
	payloadDigest                    string
	payloadSizeBytes                 int64
	receiptComponentCount            int64
	receiptComponents                []ReceiptComponent
}

func (receipt V2Receipt) ID() string { return receipt.id }
func (receipt V2Receipt) ReceiptProtocolVersion() ReceiptProtocolVersion {
	return receipt.receiptProtocolVersion
}
func (receipt V2Receipt) ServingScopeDigest() string          { return receipt.servingScopeDigest }
func (receipt V2Receipt) ConnectorAccountID() string          { return receipt.connectorAccountID }
func (receipt V2Receipt) AccountServingGateID() string        { return receipt.accountServingGateID }
func (receipt V2Receipt) AccountServingFenceToken() int64     { return receipt.accountServingFenceToken }
func (receipt V2Receipt) ServingEpochID() string              { return receipt.servingEpochID }
func (receipt V2Receipt) ServingEpochDigest() string          { return receipt.servingEpochDigest }
func (receipt V2Receipt) AdmissionKind() ReceiptAdmissionKind { return receipt.admissionKind }
func (receipt V2Receipt) AdmissionAuthorityID() string        { return receipt.admissionAuthorityID }
func (receipt V2Receipt) PayloadCiphertextProtocolVersion() PayloadCiphertextProtocolVersion {
	return receipt.payloadCiphertextProtocolVersion
}
func (receipt V2Receipt) PayloadCiphertext() []byte {
	return append([]byte(nil), receipt.payloadCiphertext...)
}
func (receipt V2Receipt) PayloadDigest() string        { return receipt.payloadDigest }
func (receipt V2Receipt) PayloadSizeBytes() int64      { return receipt.payloadSizeBytes }
func (receipt V2Receipt) ReceiptComponentCount() int64 { return receipt.receiptComponentCount }
func (receipt V2Receipt) ReceiptComponents() []ReceiptComponent {
	components := make([]ReceiptComponent, len(receipt.receiptComponents))
	for index := range receipt.receiptComponents {
		components[index] = receipt.receiptComponents[index].copy()
	}
	return components
}

func (receipt V2Receipt) copy() V2Receipt {
	receipt.payloadCiphertext = append([]byte(nil), receipt.payloadCiphertext...)
	receipt.receiptComponents = receipt.ReceiptComponents()
	return receipt
}

func (receipt V2Receipt) equal(other V2Receipt) bool {
	if receipt.receiptProtocolVersion != other.receiptProtocolVersion ||
		receipt.id != other.id ||
		receipt.servingScopeDigest != other.servingScopeDigest ||
		receipt.connectorAccountID != other.connectorAccountID ||
		receipt.accountServingGateID != other.accountServingGateID ||
		receipt.accountServingFenceToken != other.accountServingFenceToken ||
		receipt.servingEpochID != other.servingEpochID ||
		receipt.servingEpochDigest != other.servingEpochDigest ||
		receipt.admissionKind != other.admissionKind ||
		receipt.admissionAuthorityID != other.admissionAuthorityID ||
		receipt.payloadCiphertextProtocolVersion != other.payloadCiphertextProtocolVersion ||
		!bytes.Equal(receipt.payloadCiphertext, other.payloadCiphertext) ||
		receipt.payloadDigest != other.payloadDigest ||
		receipt.payloadSizeBytes != other.payloadSizeBytes ||
		receipt.receiptComponentCount != other.receiptComponentCount ||
		len(receipt.receiptComponents) != len(other.receiptComponents) {
		return false
	}
	for index := range receipt.receiptComponents {
		if !receipt.receiptComponents[index].equal(other.receiptComponents[index]) {
			return false
		}
	}
	return true
}

func (receipt V2Receipt) validateStored() error {
	if receipt.receiptProtocolVersion != ReceiptProtocolV1 {
		return storedIngressReceiptInvalid("unsupported receipt protocol %q", receipt.receiptProtocolVersion)
	}
	if !validOpaqueIdentifierWithin(receipt.id, connectorDigestProfileV2MaxIdentifierBytes) {
		return storedIngressReceiptInvalid("receipt ID is not canonical")
	}
	if !rawSHA256Pattern.MatchString(receipt.servingScopeDigest) {
		return storedIngressReceiptInvalid("serving scope digest is not canonical")
	}
	for name, value := range map[string]string{
		"connector account ID":    receipt.connectorAccountID,
		"account serving gate ID": receipt.accountServingGateID,
		"serving epoch ID":        receipt.servingEpochID,
		"admission authority ID":  receipt.admissionAuthorityID,
	} {
		if !validOpaqueIdentifierWithin(value, connectorDigestProfileV2MaxIdentifierBytes) {
			return storedIngressReceiptInvalid("%s is not canonical", name)
		}
	}
	if receipt.accountServingFenceToken <= 0 {
		return storedIngressReceiptInvalid("account serving fence token must be positive")
	}
	if !prefixedSHA256Pattern.MatchString(receipt.servingEpochDigest) ||
		!prefixedSHA256Pattern.MatchString(receipt.payloadDigest) {
		return storedIngressReceiptInvalid("epoch or payload digest is not canonical")
	}
	if receipt.admissionKind != ReceiptAdmissionKindTransport {
		return storedIngressReceiptInvalid("admission kind %q is outside this transport repository", receipt.admissionKind)
	}
	if receipt.payloadCiphertextProtocolVersion != PayloadCiphertextProtocolV1 {
		return storedIngressReceiptInvalid("unsupported payload ciphertext protocol %q", receipt.payloadCiphertextProtocolVersion)
	}
	if len(receipt.payloadCiphertext) == 0 || len(receipt.payloadCiphertext) > MaxIngressPayloadCiphertextBytes {
		return storedIngressReceiptInvalid("payload ciphertext bytes are outside the closed bound")
	}
	if receipt.payloadSizeBytes < 0 || receipt.payloadSizeBytes > MaxIngressPayloadBytes {
		return storedIngressReceiptInvalid("payload size is outside the closed bound")
	}
	if receipt.receiptComponentCount < 0 || receipt.receiptComponentCount > MaxReceiptComponentCount {
		return storedIngressReceiptInvalid("receipt component count is outside the closed bound")
	}
	if receipt.receiptComponentCount != int64(len(receipt.receiptComponents)) {
		return storedIngressReceiptInvalid("receipt component count does not match the complete stored set")
	}
	seenIDs := make(map[string]struct{}, len(receipt.receiptComponents))
	var plaintextBytes, ciphertextBytes uint64
	for index, component := range receipt.receiptComponents {
		if err := component.validateStored(); err != nil {
			return err
		}
		if component.receiptID != receipt.id || component.componentOrdinal != int64(index) {
			return storedIngressReceiptInvalid("receipt component parent or contiguous ordinal disagrees at position %d", index)
		}
		if _, duplicate := seenIDs[component.id]; duplicate {
			return storedIngressReceiptInvalid("receipt component ID %q is duplicated", component.id)
		}
		seenIDs[component.id] = struct{}{}
		var ok bool
		plaintextBytes, ok = addReceiptComponentSetBytes(plaintextBytes, uint64(component.payloadSizeBytes))
		if !ok {
			return storedIngressReceiptInvalid("receipt component plaintext set exceeds the closed byte bound")
		}
		ciphertextBytes, ok = addReceiptComponentSetBytes(ciphertextBytes, uint64(len(component.payloadCiphertext)))
		if !ok {
			return storedIngressReceiptInvalid("receipt component ciphertext set exceeds the closed byte bound")
		}
	}
	return nil
}

func addReceiptComponentSetBytes(total, next uint64) (uint64, bool) {
	if total > MaxReceiptComponentSetBytes || next > MaxReceiptComponentSetBytes-total {
		return 0, false
	}
	return total + next, true
}

type receiptAdmissionKey struct {
	id                         string
	protocolVersion            ReceiptAdmissionKeyProtocolVersion
	servingScopeDigest         string
	identity                   TransportIdentity
	accountServingGateID       string
	authorizedPayloadDigest    string
	disposition                ReceiptAdmissionDisposition
	receiptID                  *string
	predecessorProtocolVersion *PredecessorReferenceProtocolVersion
	predecessorRef             []byte
	predecessorRefDigest       *string
}

type V1AcceptanceTombstone struct {
	protocolVersion PredecessorReferenceProtocolVersion
	reference       []byte
	referenceDigest string
}

func (tombstone V1AcceptanceTombstone) ProtocolVersion() PredecessorReferenceProtocolVersion {
	return tombstone.protocolVersion
}
func (tombstone V1AcceptanceTombstone) Reference() []byte {
	return append([]byte(nil), tombstone.reference...)
}
func (tombstone V1AcceptanceTombstone) ReferenceDigest() string { return tombstone.referenceDigest }

// TransportAdmission is the immutable resolution of one transport identity.
// Exactly one of V2Receipt or V1AcceptanceTombstone is present.
type TransportAdmission struct {
	key     receiptAdmissionKey
	receipt *V2Receipt
}

func NewV2TransportAdmission(input V2TransportAdmissionInput) (TransportAdmission, error) {
	if input.ReceiptProtocolVersion != ReceiptProtocolV1 ||
		input.AdmissionKeyProtocolVersion != ReceiptAdmissionKeyProtocolV1 ||
		input.PayloadCiphertextProtocolVersion != PayloadCiphertextProtocolV1 {
		return TransportAdmission{}, fmt.Errorf(
			"%w: receipt=%q admission-key=%q payload=%q",
			ErrUnsupportedIngressReceiptProtocol,
			input.ReceiptProtocolVersion,
			input.AdmissionKeyProtocolVersion,
			input.PayloadCiphertextProtocolVersion,
		)
	}
	// Bound every caller-owned byte carrier before hashing or copying it into
	// immutable authority. In particular, an oversized ciphertext must not be
	// duplicated before the closed storage bound rejects it.
	if len(input.PayloadCiphertext) == 0 || len(input.PayloadCiphertext) > MaxIngressPayloadCiphertextBytes {
		return TransportAdmission{}, invalidIngressReceipt("payload ciphertext bytes are outside the closed bound")
	}
	if int64(len(input.PayloadPlaintext)) > MaxIngressPayloadBytes {
		return TransportAdmission{}, invalidIngressReceipt("plaintext payload exceeds the closed bound")
	}
	identity, err := NewTransportIdentity(
		input.ConnectorAccountID,
		input.IngressChannel,
		input.TransportIdempotencyKey,
	)
	if err != nil {
		return TransportAdmission{}, err
	}
	payloadDigest := prefixedIngressDigest(input.PayloadPlaintext)
	payloadSizeBytes := int64(len(input.PayloadPlaintext))
	receipt := V2Receipt{
		receiptProtocolVersion:           input.ReceiptProtocolVersion,
		id:                               input.ReceiptID,
		servingScopeDigest:               input.ServingScopeDigest,
		connectorAccountID:               input.ConnectorAccountID,
		accountServingGateID:             input.AccountServingGateID,
		accountServingFenceToken:         input.AccountServingFenceToken,
		servingEpochID:                   input.ServingEpochID,
		servingEpochDigest:               input.ServingEpochDigest,
		admissionKind:                    ReceiptAdmissionKindTransport,
		admissionAuthorityID:             input.AdmissionKeyID,
		payloadCiphertextProtocolVersion: input.PayloadCiphertextProtocolVersion,
		payloadCiphertext:                append([]byte(nil), input.PayloadCiphertext...),
		payloadDigest:                    payloadDigest,
		payloadSizeBytes:                 payloadSizeBytes,
		receiptComponentCount:            0,
	}
	receiptID := receipt.id
	admission := TransportAdmission{
		key: receiptAdmissionKey{
			id:                      input.AdmissionKeyID,
			protocolVersion:         input.AdmissionKeyProtocolVersion,
			servingScopeDigest:      input.ServingScopeDigest,
			identity:                identity,
			accountServingGateID:    input.AccountServingGateID,
			authorizedPayloadDigest: payloadDigest,
			disposition:             ReceiptAdmissionDispositionV2Receipt,
			receiptID:               &receiptID,
		},
		receipt: &receipt,
	}
	if err := admission.validateStored(); err != nil {
		return TransportAdmission{}, fmt.Errorf("%w: %v", ErrInvalidIngressReceipt, err)
	}
	return admission.copy(), nil
}

func (admission TransportAdmission) AdmissionKeyID() string { return admission.key.id }
func (admission TransportAdmission) AdmissionKeyProtocolVersion() ReceiptAdmissionKeyProtocolVersion {
	return admission.key.protocolVersion
}
func (admission TransportAdmission) Identity() TransportIdentity { return admission.key.identity }
func (admission TransportAdmission) ServingScopeDigest() string {
	return admission.key.servingScopeDigest
}
func (admission TransportAdmission) AccountServingGateID() string {
	return admission.key.accountServingGateID
}
func (admission TransportAdmission) AuthorizedPayloadDigest() string {
	return admission.key.authorizedPayloadDigest
}
func (admission TransportAdmission) Disposition() ReceiptAdmissionDisposition {
	return admission.key.disposition
}
func (admission TransportAdmission) V2Receipt() (V2Receipt, bool) {
	if admission.receipt == nil {
		return V2Receipt{}, false
	}
	return admission.receipt.copy(), true
}
func (admission TransportAdmission) V1AcceptanceTombstone() (V1AcceptanceTombstone, bool) {
	if admission.key.disposition != ReceiptAdmissionDispositionV1Tombstone ||
		admission.key.predecessorProtocolVersion == nil || admission.key.predecessorRefDigest == nil {
		return V1AcceptanceTombstone{}, false
	}
	return V1AcceptanceTombstone{
		protocolVersion: *admission.key.predecessorProtocolVersion,
		reference:       append([]byte(nil), admission.key.predecessorRef...),
		referenceDigest: *admission.key.predecessorRefDigest,
	}, true
}

func (admission TransportAdmission) copy() TransportAdmission {
	admission.key.predecessorRef = append([]byte(nil), admission.key.predecessorRef...)
	if admission.key.receiptID != nil {
		value := *admission.key.receiptID
		admission.key.receiptID = &value
	}
	if admission.key.predecessorProtocolVersion != nil {
		value := *admission.key.predecessorProtocolVersion
		admission.key.predecessorProtocolVersion = &value
	}
	if admission.key.predecessorRefDigest != nil {
		value := *admission.key.predecessorRefDigest
		admission.key.predecessorRefDigest = &value
	}
	if admission.receipt != nil {
		value := admission.receipt.copy()
		admission.receipt = &value
	}
	return admission
}

func (admission TransportAdmission) equal(other TransportAdmission) bool {
	if admission.key.id != other.key.id ||
		admission.key.protocolVersion != other.key.protocolVersion ||
		admission.key.servingScopeDigest != other.key.servingScopeDigest ||
		admission.key.identity != other.key.identity ||
		admission.key.accountServingGateID != other.key.accountServingGateID ||
		admission.key.authorizedPayloadDigest != other.key.authorizedPayloadDigest ||
		admission.key.disposition != other.key.disposition ||
		!equalOptionalString(admission.key.receiptID, other.key.receiptID) ||
		!equalOptionalPredecessorProtocol(admission.key.predecessorProtocolVersion, other.key.predecessorProtocolVersion) ||
		!bytes.Equal(admission.key.predecessorRef, other.key.predecessorRef) ||
		!equalOptionalString(admission.key.predecessorRefDigest, other.key.predecessorRefDigest) ||
		(admission.receipt == nil) != (other.receipt == nil) {
		return false
	}
	return admission.receipt == nil || admission.receipt.equal(*other.receipt)
}

func (admission TransportAdmission) validateStored() error {
	if admission.key.protocolVersion != ReceiptAdmissionKeyProtocolV1 {
		return storedIngressReceiptInvalid("unsupported admission-key protocol %q", admission.key.protocolVersion)
	}
	if !validOpaqueIdentifierWithin(admission.key.id, connectorDigestProfileV2MaxIdentifierBytes) {
		return storedIngressReceiptInvalid("admission-key ID is not canonical")
	}
	if !rawSHA256Pattern.MatchString(admission.key.servingScopeDigest) {
		return storedIngressReceiptInvalid("admission-key serving scope digest is not canonical")
	}
	if err := admission.key.identity.validate(); err != nil {
		return storedIngressReceiptInvalid("transport identity: %v", err)
	}
	if !validOpaqueIdentifierWithin(admission.key.accountServingGateID, connectorDigestProfileV2MaxIdentifierBytes) {
		return storedIngressReceiptInvalid("account serving gate ID is not canonical")
	}
	if !prefixedSHA256Pattern.MatchString(admission.key.authorizedPayloadDigest) {
		return storedIngressReceiptInvalid("authorized payload digest is not canonical")
	}

	switch admission.key.disposition {
	case ReceiptAdmissionDispositionV2Receipt:
		if admission.key.receiptID == nil || admission.receipt == nil ||
			admission.key.predecessorProtocolVersion != nil || admission.key.predecessorRef != nil ||
			admission.key.predecessorRefDigest != nil {
			return storedIngressReceiptInvalid("v2_receipt disposition has a partial or mixed tuple")
		}
		if err := admission.receipt.validateStored(); err != nil {
			return err
		}
		if *admission.key.receiptID != admission.receipt.id ||
			admission.key.servingScopeDigest != admission.receipt.servingScopeDigest ||
			admission.key.identity.connectorAccountID != admission.receipt.connectorAccountID ||
			admission.key.accountServingGateID != admission.receipt.accountServingGateID ||
			admission.key.authorizedPayloadDigest != admission.receipt.payloadDigest ||
			admission.receipt.admissionKind != ReceiptAdmissionKindTransport ||
			admission.receipt.admissionAuthorityID != admission.key.id {
			return storedIngressReceiptInvalid("receipt and admission-key coordinates disagree")
		}
	case ReceiptAdmissionDispositionV1Tombstone:
		if admission.key.receiptID != nil || admission.receipt != nil ||
			admission.key.predecessorProtocolVersion == nil ||
			len(admission.key.predecessorRef) == 0 ||
			admission.key.predecessorRefDigest == nil {
			return storedIngressReceiptInvalid("v1_tombstone disposition has a partial or mixed tuple")
		}
		if *admission.key.predecessorProtocolVersion != PredecessorReferenceProtocolV1 {
			return storedIngressReceiptInvalid("unsupported predecessor reference protocol %q", *admission.key.predecessorProtocolVersion)
		}
		if len(admission.key.predecessorRef) > MaxPredecessorReferenceBytes ||
			!prefixedSHA256Pattern.MatchString(*admission.key.predecessorRefDigest) ||
			*admission.key.predecessorRefDigest != prefixedIngressDigest(admission.key.predecessorRef) {
			return storedIngressReceiptInvalid("predecessor reference bytes or digest are invalid")
		}
	default:
		return storedIngressReceiptInvalid("disposition %q is outside the closed contract", admission.key.disposition)
	}
	return nil
}

// authorizesTransportRequest reports whether a complete retained admission is
// the authority for a caller's transport retry. Scope, epoch, protocol shape,
// and disposition are retained evidence; they do not mint a second transport
// identity after a serving transition.
func (admission TransportAdmission) authorizesTransportRequest(candidate TransportAdmission) bool {
	if admission.key.identity != candidate.key.identity ||
		admission.key.authorizedPayloadDigest != candidate.key.authorizedPayloadDigest {
		return false
	}
	// A retained V1 tombstone intentionally carries only the authenticated
	// plaintext digest. It prevents V2 from rematerializing accepted V1 work.
	if admission.receipt == nil {
		return true
	}
	if candidate.receipt == nil {
		return false
	}
	// V2 duplicate convergence is byte-exact for the complete accepted payload
	// tuple. The plaintext digest is derived by NewV2TransportAdmission rather
	// than trusted from the caller; ciphertext bytes remain immutable evidence.
	return admission.receipt.payloadCiphertextProtocolVersion == candidate.receipt.payloadCiphertextProtocolVersion &&
		bytes.Equal(admission.receipt.payloadCiphertext, candidate.receipt.payloadCiphertext) &&
		admission.receipt.payloadDigest == candidate.receipt.payloadDigest &&
		admission.receipt.payloadSizeBytes == candidate.receipt.payloadSizeBytes
}

func equalOptionalPredecessorProtocol(
	left, right *PredecessorReferenceProtocolVersion,
) bool {
	if left == nil || right == nil {
		return left == nil && right == nil
	}
	return *left == *right
}

func prefixedIngressDigest(value []byte) string {
	digest := sha256.Sum256(value)
	return "sha256:" + hex.EncodeToString(digest[:])
}

func invalidIngressReceipt(format string, args ...any) error {
	return fmt.Errorf("%w: %s", ErrInvalidIngressReceipt, fmt.Sprintf(format, args...))
}

func storedIngressReceiptInvalid(format string, args ...any) error {
	return fmt.Errorf("%w: %s", ErrStoredIngressReceiptInvalid, fmt.Sprintf(format, args...))
}
