package recordmutationv1

import (
	"bytes"
	"context"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"testing"
	"time"
)

func TestTypedValuesCanonicalDigestAndOmission(t *testing.T) {
	if SemanticMappingRevision != 7 {
		t.Fatalf("SemanticMappingRevision = %d; update every released mutation mapper before changing this test", SemanticMappingRevision)
	}
	if ProtocolMinor != 2 {
		t.Fatalf("ProtocolMinor = %d; external-identity upsert requires mutation protocol 1.2", ProtocolMinor)
	}
	for name, value := range map[string]interface {
		RecordMutationSemanticMappingRevision() uint32
	}{
		"request": Request{}, "response": Response{}, "status request": StatusRequest{},
		"command shape": CommandShape{}, "status response": StatusResponse{},
	} {
		if got := value.RecordMutationSemanticMappingRevision(); got != SemanticMappingRevision {
			t.Fatalf("%s semantic mapping revision = %d", name, got)
		}
	}
	request := typedRequest()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := ValidateRequest(ctx, request); err != nil {
		t.Fatal(err)
	}
	if len(request.Operations[0].Fields) != 8 {
		t.Fatal("declared-but-absent field unexpectedly materialized")
	}
	digest, err := CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	reordered := request
	reordered.Operations = append([]Operation(nil), request.Operations...)
	reordered.Operations[0].Fields = append([]FieldValue(nil), request.Operations[0].Fields...)
	for left, right := 0, len(reordered.Operations[0].Fields)-1; left < right; left, right = left+1, right-1 {
		reordered.Operations[0].Fields[left], reordered.Operations[0].Fields[right] = reordered.Operations[0].Fields[right], reordered.Operations[0].Fields[left]
	}
	reordered.CommandID = "another-command-id"
	otherDigest, err := CommandDigest(reordered)
	if err != nil || otherDigest != digest {
		t.Fatalf("reordered/renamed digest = %q, %v; want %q", otherDigest, err, digest)
	}
	changed := request
	changed.Operations = append([]Operation(nil), request.Operations...)
	changed.Operations[0].Fields = append([]FieldValue(nil), request.Operations[0].Fields...)
	value := int64(1)
	changed.Operations[0].Fields[2].Integer = &value
	if changedDigest, _ := CommandDigest(changed); changedDigest == digest {
		t.Fatal("semantic change retained command digest")
	}
}

func TestExternalIdentityUpsertIsExplicitCanonicalAndPositionStable(t *testing.T) {
	identity := &ExternalIdentity{FieldID: "ExternalKey", Value: "source:row:1"}
	name := "first"
	request := Request{
		CommandID: "external-upsert", BatchMode: BatchIndependent, UseCase: MutationUseCaseCollection,
		Operations: []Operation{{
			Kind: OperationUpsert, ObjectID: "Entry", ExternalIdentity: identity,
			Fields: []FieldValue{{Name: "Name", Kind: ValueKindString, String: &name}},
		}},
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := ValidateRequest(ctx, request); err != nil {
		t.Fatal(err)
	}
	digest, err := CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	changed := request
	changed.Operations = append([]Operation(nil), request.Operations...)
	changedIdentity := *identity
	changedIdentity.Value = "source:row:2"
	changed.Operations[0].ExternalIdentity = &changedIdentity
	if changedDigest, _ := CommandDigest(changed); changedDigest == digest {
		t.Fatal("external identity change retained command digest")
	}

	for name, mutate := range map[string]func(*Operation){
		"missing identity": func(operation *Operation) { operation.ExternalIdentity = nil },
		"blank value": func(operation *Operation) {
			copy := *operation.ExternalIdentity
			copy.Value = " "
			operation.ExternalIdentity = &copy
		},
		"identity repeated in payload": func(operation *Operation) {
			value := "source:row:1"
			operation.Fields = append(operation.Fields, FieldValue{Name: "externalkey", Kind: ValueKindString, String: &value})
		},
	} {
		t.Run(name, func(t *testing.T) {
			candidate := request
			candidate.Operations = append([]Operation(nil), request.Operations...)
			candidate.Operations[0].Fields = append([]FieldValue(nil), request.Operations[0].Fields...)
			mutate(&candidate.Operations[0])
			if err := ValidateRequest(ctx, candidate); err == nil {
				t.Fatal("invalid upsert accepted")
			}
		})
	}

	for _, created := range []bool{true, false} {
		created := created
		response := Response{
			CommandID: request.CommandID, CommandDigest: digest, Receipts: validReceipts(), OutcomeExpiresAtUTC: "2026-07-20T12:30:00Z",
			Results: []OperationResult{{Index: 0, Kind: OperationUpsert, RecordID: "entry-1", Success: true, Created: &created, Errors: []OperationError{}}},
		}
		if err := ValidateResponse(request, response); err != nil {
			t.Fatalf("created=%v response rejected: %v", created, err)
		}
	}
}

func TestCreateFromSourceGuardIsClosedAndCanonical(t *testing.T) {
	request := Request{CommandID: "source-guard", BatchMode: BatchIndependent, Operations: []Operation{{
		Kind: OperationCreate, ObjectID: "QuoteProduct",
	}}}
	digest, err := CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	response := Response{
		CommandID: request.CommandID, CommandDigest: digest, Receipts: validReceipts(), OutcomeExpiresAtUTC: "2026-07-20T12:30:00Z",
		Results: []OperationResult{{Index: 0, Kind: OperationCreate, Errors: []OperationError{{
			Kind: ErrorInvalidOperation, Fields: []string{}, CreateFromSourceGuard: &CreateFromSourceGuard{
				ObjectID: "QuoteProduct", ActionIDs: []string{"addProduct", "createFromQuote"},
			},
		}}}},
	}
	if err := ValidateResponse(request, response); err != nil {
		t.Fatalf("valid guard = %v", err)
	}

	for name, mutate := range map[string]func(*CreateFromSourceGuard){
		"missing object":      func(value *CreateFromSourceGuard) { value.ObjectID = "" },
		"missing actions":     func(value *CreateFromSourceGuard) { value.ActionIDs = nil },
		"unsorted actions":    func(value *CreateFromSourceGuard) { value.ActionIDs = []string{"zAction", "aAction"} },
		"duplicate actions":   func(value *CreateFromSourceGuard) { value.ActionIDs = []string{"sameAction", "sameAction"} },
		"malformed action id": func(value *CreateFromSourceGuard) { value.ActionIDs = []string{"not/an/action"} },
	} {
		t.Run(name, func(t *testing.T) {
			candidate := response
			candidate.Results = append([]OperationResult(nil), response.Results...)
			candidate.Results[0].Errors = append([]OperationError(nil), response.Results[0].Errors...)
			guard := *response.Results[0].Errors[0].CreateFromSourceGuard
			guard.ActionIDs = append([]string(nil), guard.ActionIDs...)
			candidate.Results[0].Errors[0].CreateFromSourceGuard = &guard
			mutate(&guard)
			if err := ValidateResponse(request, candidate); err == nil {
				t.Fatal("invalid guard accepted")
			}
		})
	}

	wrongKind := response
	wrongKind.Results = append([]OperationResult(nil), response.Results...)
	wrongKind.Results[0].Errors = append([]OperationError(nil), response.Results[0].Errors...)
	wrongKind.Results[0].Errors[0].Kind = ErrorFieldIntegrity
	if err := ValidateResponse(request, wrongKind); err == nil {
		t.Fatal("guard attached to non-invalid-operation error")
	}

	wrongObject := response
	wrongObject.Results = append([]OperationResult(nil), response.Results...)
	wrongObject.Results[0].Errors = append([]OperationError(nil), response.Results[0].Errors...)
	wrongObjectGuard := *response.Results[0].Errors[0].CreateFromSourceGuard
	wrongObjectGuard.ObjectID = "OtherObject"
	wrongObject.Results[0].Errors[0].CreateFromSourceGuard = &wrongObjectGuard
	if err := ValidateResponse(request, wrongObject); err == nil {
		t.Fatal("guard object differs from CREATE operation object")
	}

	updateRequest := Request{CommandID: "source-guard-update", BatchMode: BatchIndependent, Operations: []Operation{{
		Kind: OperationUpdate, ObjectID: "QuoteProduct", RecordID: "record-1",
	}}}
	updateDigest, err := CommandDigest(updateRequest)
	if err != nil {
		t.Fatal(err)
	}
	updateResponse := response
	updateResponse.CommandID = updateRequest.CommandID
	updateResponse.CommandDigest = updateDigest
	updateResponse.Results = append([]OperationResult(nil), response.Results...)
	updateResponse.Results[0].Kind = OperationUpdate
	updateResponse.Results[0].RecordID = "record-1"
	if err := ValidateResponse(updateRequest, updateResponse); err == nil {
		t.Fatal("create-from-source guard attached to UPDATE result")
	}
}

func TestRequestBoundariesCancellationAndRetryPolicy(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	request := typedRequest()
	request.Operations = make([]Operation, MaxOperations)
	for i := range request.Operations {
		request.Operations[i] = Operation{Kind: OperationDelete, RecordID: "record"}
	}
	if err := ValidateRequest(ctx, request); err != nil {
		t.Fatalf("maximum operation count = %v", err)
	}
	request.Operations = append(request.Operations, Operation{Kind: OperationDelete, RecordID: "one-over"})
	var failure *Failure
	if err := ValidateRequest(ctx, request); !errors.As(err, &failure) || failure.LimitKind != LimitOperationCount {
		t.Fatalf("one-over = %#v", err)
	}

	canceled, cancelNow := context.WithCancel(context.Background())
	cancelNow()
	if err := ValidateRequest(canceled, typedRequest()); !errors.As(err, &failure) || failure.Category != FailureCanceled {
		t.Fatalf("canceled = %#v", err)
	}
	if err := ValidateRequest(context.Background(), typedRequest()); !errors.As(err, &failure) || failure.InvalidComponent != InvalidComponentDeadline {
		t.Fatalf("missing deadline = %#v", err)
	}
	for _, category := range []FailureCategory{FailureCanceled, FailureDeadlineExceeded, FailureUnavailable, FailureInternal} {
		if RetryDispositionFor(&Failure{Category: category}) != RetryReconcile {
			t.Fatalf("%s does not require reconciliation", category)
		}
	}
}

func TestSemanticRequestExactAndOneOver(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	request := Request{CommandID: "cmd-envelope", BatchMode: BatchIndependent, Operations: []Operation{{
		Kind: OperationCreate, ObjectID: "WorkItem", Fields: []FieldValue{{Name: "Payload", Kind: ValueKindString}},
	}}}
	empty := ""
	request.Operations[0].Fields[0].String = &empty
	base := SemanticRequestSize(request)
	exact := strings.Repeat("x", MaxSemanticRequestBytes-base)
	request.Operations[0].Fields[0].String = &exact
	if got := SemanticRequestSize(request); got != MaxSemanticRequestBytes {
		t.Fatalf("exact size = %d", got)
	}
	if err := ValidateRequest(ctx, request); err != nil {
		t.Fatalf("exact request = %v", err)
	}
	exact += "x"
	request.Operations[0].Fields[0].String = &exact
	var failure *Failure
	if err := ValidateRequest(ctx, request); !errors.As(err, &failure) || failure.LimitKind != LimitSemanticRequest {
		t.Fatalf("one-over = %#v", err)
	}
}

func TestDecimalStorageEnvelopeRejectsTinyAllocationBombs(t *testing.T) {
	request := typedRequest()
	decimal := request.Operations[0].Fields[1].Decimal
	decimal.Coefficient = strings.Repeat("9", MaxDecimalPrecision)
	decimal.Scale = MaxDecimalScale
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := ValidateRequest(ctx, request); err != nil {
		t.Fatalf("maximum Runtime decimal shape = %v", err)
	}
	decimal.Coefficient += "9"
	if err := ValidateRequest(ctx, request); err == nil {
		t.Fatal("one-over decimal precision accepted")
	}
	decimal.Coefficient = "0"
	decimal.Scale = MaxDecimalScale + 1
	if err := ValidateRequest(ctx, request); err == nil {
		t.Fatal("one-over decimal scale accepted")
	}
	decimal.Scale = ^uint32(0)
	if err := ValidateRequest(ctx, request); err == nil {
		t.Fatal("allocation-bomb decimal scale accepted")
	}
}

func TestRetryResourceExhaustedOnlyRetriesAdmission(t *testing.T) {
	if RetryDispositionFor(&Failure{Category: FailureResourceExhausted, LimitKind: LimitSemanticRequest}) != RetryNever {
		t.Fatal("oversized request was classified as retryable")
	}
	if RetryDispositionFor(&Failure{Category: FailureResourceExhausted, LimitKind: LimitAdmission}) != RetryNever {
		t.Fatal("admission without producer retry advice was classified as retryable")
	}
	if RetryDispositionFor(&Failure{Category: FailureResourceExhausted, LimitKind: LimitAdmission, RetryAfterMillis: 50}) != RetryWithBackoff {
		t.Fatal("admission with producer retry advice was not classified as backoff retryable")
	}
	if ValidMutateTopLevelFailure(FailureMissing) || !ValidStatusTopLevelFailure(FailureMissing) {
		t.Fatal("record missing leaked into Mutate top-level failure grammar")
	}
}

func TestResponseAndStatusInvariants(t *testing.T) {
	request := typedRequest()
	digest, err := CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	created := true
	response := Response{
		CommandID: request.CommandID, CommandDigest: digest,
		Results:  []OperationResult{{Index: 0, Kind: OperationCreate, RecordID: "record-1", Success: true, Created: &created, Errors: []OperationError{}}},
		Receipts: validReceipts(), OutcomeExpiresAtUTC: "2026-07-20T12:30:00Z",
	}
	if err := ValidateResponse(request, response); err != nil {
		t.Fatal(err)
	}
	statusRequest, err := StatusRequestFor(request)
	if err != nil {
		t.Fatal(err)
	}
	shape, err := CommandShapeFor(request)
	if err != nil {
		t.Fatal(err)
	}
	for _, state := range []CommandState{CommandAccepted, CommandExecuting} {
		if err := ValidateStatusResponse(shape, statusRequest, StatusResponse{CommandID: request.CommandID, CommandDigest: digest, State: state}); err != nil {
			t.Fatalf("%s = %v", state, err)
		}
	}
	receipts := validReceipts()
	completed := StatusResponse{
		CommandID: request.CommandID, CommandDigest: digest, State: CommandCompleted, Results: response.Results,
		Receipts: &receipts, OutcomeExpiresAtUTC: response.OutcomeExpiresAtUTC,
	}
	if err := ValidateStatusResponse(shape, statusRequest, completed); err != nil {
		t.Fatal(err)
	}
	completed.Results[0].Index = 1
	if err := ValidateStatusResponse(shape, statusRequest, completed); err == nil {
		t.Fatal("misordered status result accepted")
	}
}

func TestAtomicResponseStateMachine(t *testing.T) {
	request := Request{CommandID: "atomic-state-machine", BatchMode: BatchAtomic, Operations: []Operation{
		{Kind: OperationUpdate, ObjectID: "WorkItem", RecordID: "work-1"},
		{Kind: OperationDelete, RecordID: "work-2"},
	}}
	digest, err := CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	base := Response{
		CommandID: request.CommandID, CommandDigest: digest, Receipts: validReceipts(),
		OutcomeExpiresAtUTC: "2026-07-20T12:30:00Z",
	}
	base.Results = []OperationResult{
		{Index: 0, Kind: OperationUpdate, RecordID: "work-1", Success: false, Errors: []OperationError{{Kind: ErrorAtomicRolledBack, Fields: []string{}}}},
		{Index: 1, Kind: OperationDelete, RecordID: "work-2", Success: false, Errors: []OperationError{{Kind: ErrorCustomValidation, AuthoredMessage: "Cannot delete this record.", Fields: []string{}}}},
	}
	if err := ValidateResponse(request, base); err != nil {
		t.Fatalf("valid rollback outcome = %v", err)
	}

	mixed := base
	mixed.Results = append([]OperationResult(nil), base.Results...)
	mixed.Results[0] = OperationResult{Index: 0, Kind: OperationUpdate, RecordID: "work-1", Success: true, Errors: []OperationError{}}
	if err := ValidateResponse(request, mixed); err == nil {
		t.Fatal("atomic success/failure mixture accepted")
	}

	twoCauses := base
	twoCauses.Results = append([]OperationResult(nil), base.Results...)
	twoCauses.Results[0].Errors = []OperationError{{Kind: ErrorInvalidOperation, Fields: []string{}}}
	if err := ValidateResponse(request, twoCauses); err == nil {
		t.Fatal("atomic outcome with two causal failures accepted")
	}

	independent := request
	independent.BatchMode = BatchIndependent
	independentDigest, err := CommandDigest(independent)
	if err != nil {
		t.Fatal(err)
	}
	independentResponse := base
	independentResponse.CommandDigest = independentDigest
	if err := ValidateResponse(independent, independentResponse); err == nil {
		t.Fatal("independent outcome with atomic rollback marker accepted")
	}
}

func TestMutationResponseBindsUpdateAndDeleteTargetRecords(t *testing.T) {
	request := Request{CommandID: "target-binding", BatchMode: BatchIndependent, Operations: []Operation{
		{Kind: OperationUpdate, ObjectID: "WorkItem", RecordID: "work-1"},
		{Kind: OperationDelete, RecordID: "work-2"},
	}}
	digest, err := CommandDigest(request)
	if err != nil {
		t.Fatal(err)
	}
	response := Response{
		CommandID: request.CommandID, CommandDigest: digest, Receipts: validReceipts(),
		OutcomeExpiresAtUTC: "2026-07-20T12:30:00Z",
		Results: []OperationResult{
			{Index: 0, Kind: OperationUpdate, RecordID: "work-1", Success: true, Errors: []OperationError{}},
			{Index: 1, Kind: OperationDelete, RecordID: "work-2", Success: true, Errors: []OperationError{}},
		},
	}
	if err := ValidateResponse(request, response); err != nil {
		t.Fatal(err)
	}
	for index := range response.Results {
		wrong := response
		wrong.Results = append([]OperationResult(nil), response.Results...)
		wrong.Results[index].RecordID = "different-record"
		if err := ValidateResponse(request, wrong); err == nil {
			t.Fatalf("result %d acknowledged a different target record", index)
		}
	}
}

func TestMutationFieldCountClosesEncodedCommandHeadroom(t *testing.T) {
	fields := make([]FieldValue, MaxFieldsPerOperation+1)
	for i := range fields {
		name := fmt.Sprintf("F%03d", i)
		fields[i] = FieldValue{Name: name, Kind: ValueKindNull, Null: true}
	}
	request := Request{CommandID: "field-count", BatchMode: BatchIndependent, Operations: []Operation{{
		Kind: OperationCreate, ObjectID: "WorkItem", Fields: fields,
	}}}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	err := ValidateRequest(ctx, request)
	var failure *Failure
	if !errors.As(err, &failure) || failure.Category != FailureResourceExhausted ||
		failure.LimitKind != LimitFieldCount || failure.Maximum != MaxFieldsPerOperation {
		t.Fatalf("one-over field count = %#v", err)
	}

	// This is a deliberately conservative proof, not an encoder estimate:
	// 64 bytes covers every protobuf tag/length/nested-message wrapper per
	// field, 512 covers each operation wrapper, and 1024 covers the command.
	// The post-root-release wire follow-up must additionally measure the exact
	// adversarial protobuf vector against its independently owned cap.
	const (
		encodedCommandEvidenceCap = 32 * 1024 * 1024
		structuralUpperBound      = MaxSemanticRequestBytes +
			MaxOperations*MaxFieldsPerOperation*64 +
			MaxOperations*512 + MaxCommandIdentifierBytes + 1024
	)
	if structuralUpperBound > encodedCommandEvidenceCap {
		t.Fatalf("semantic/structural envelope %d exceeds encoded cap %d", structuralUpperBound, encodedCommandEvidenceCap)
	}
}

func TestStatusResponseUsesOriginalCommandBindingAndShape(t *testing.T) {
	request := Request{CommandID: "status-binding", BatchMode: BatchIndependent, Operations: []Operation{
		{Kind: OperationUpdate, ObjectID: "WorkItem", RecordID: "work-1"},
		{Kind: OperationDelete, RecordID: "work-2"},
	}}
	statusRequest, err := StatusRequestFor(request)
	if err != nil {
		t.Fatal(err)
	}
	shape, err := CommandShapeFor(request)
	if err != nil {
		t.Fatal(err)
	}
	receipts := validReceipts()
	response := StatusResponse{
		CommandID: request.CommandID, CommandDigest: statusRequest.CommandDigest, State: CommandCompleted,
		Results: []OperationResult{
			{Index: 0, Kind: OperationUpdate, RecordID: "work-1", Success: true, Errors: []OperationError{}},
			{Index: 1, Kind: OperationDelete, RecordID: "work-2", Success: true, Errors: []OperationError{}},
		},
		Receipts: &receipts, OutcomeExpiresAtUTC: "2026-07-20T12:30:00Z",
	}
	if err := ValidateStatusResponse(shape, statusRequest, response); err != nil {
		t.Fatalf("valid status response = %v", err)
	}

	truncated := response
	truncated.Results = truncated.Results[:1]
	if err := ValidateStatusResponse(shape, statusRequest, truncated); err == nil {
		t.Fatal("truncated terminal status accepted")
	}
	extra := response
	extra.Results = append(append([]OperationResult(nil), response.Results...), OperationResult{Index: 2, Kind: OperationDelete, RecordID: "work-3", Success: true, Errors: []OperationError{}})
	if err := ValidateStatusResponse(shape, statusRequest, extra); err == nil {
		t.Fatal("extra terminal status result accepted")
	}
	wrongBinding := statusRequest
	wrongBinding.CommandDigest = "sha256:" + strings.Repeat("0", 64)
	if err := ValidateStatusResponse(shape, wrongBinding, response); err == nil {
		t.Fatal("status request for different command content accepted")
	}
	changed := request
	changed.Operations = append([]Operation(nil), request.Operations...)
	changed.Operations[1].RecordID = "other-record"
	changedShape, err := CommandShapeFor(changed)
	if err != nil {
		t.Fatal(err)
	}
	if err := ValidateStatusResponse(changedShape, statusRequest, response); err == nil {
		t.Fatal("terminal status accepted against different original command")
	}
}

func TestOperationErrorAllowsOnlyPrintableCatalogAuthoredValidationText(t *testing.T) {
	base := OperationError{Kind: ErrorCustomValidation, AuthoredMessage: "Account name is required.", Fields: []string{"Name"}}
	if !validAuthoredValidationMessage(base) {
		t.Fatal("printable Catalog-authored validation text rejected")
	}
	for name, candidate := range map[string]OperationError{
		"wrong kind":       {Kind: ErrorInternal, AuthoredMessage: base.AuthoredMessage},
		"line injection":   {Kind: ErrorCustomValidation, AuthoredMessage: "safe\ninternal SQL"},
		"format codepoint": {Kind: ErrorCustomValidation, AuthoredMessage: "safe\u200binvisible"},
		"blank":            {Kind: ErrorCustomValidation, AuthoredMessage: "   "},
	} {
		if validAuthoredValidationMessage(candidate) {
			t.Fatalf("%s authored message accepted", name)
		}
	}
}

type vectorSuite struct {
	SchemaVersion string `json:"schema_version"`
	Vectors       []struct {
		Name     string   `json:"name"`
		Covers   []string `json:"covers"`
		Request  Request  `json:"request"`
		Response Response `json:"response"`
	} `json:"vectors"`
}

func TestImmutableConformanceVectors(t *testing.T) {
	data := ConformanceVectorsJSON()
	for _, forbidden := range [][]byte{[]byte("salesforce"), []byte("sfcrm"), []byte("sobject")} {
		if bytes.Contains(bytes.ToLower(data), forbidden) {
			t.Fatalf("product vocabulary %q leaked into neutral vector", forbidden)
		}
	}
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.DisallowUnknownFields()
	var suite vectorSuite
	if err := decoder.Decode(&suite); err != nil {
		t.Fatal(err)
	}
	if suite.SchemaVersion != "nexuscrm.runtime.record-mutation.conformance/v1" {
		t.Fatalf("schema = %q", suite.SchemaVersion)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	covered := map[string]bool{}
	for _, vector := range suite.Vectors {
		for _, item := range vector.Covers {
			covered[item] = true
		}
		if err := ValidateRequest(ctx, vector.Request); err != nil {
			t.Fatalf("%s request = %v", vector.Name, err)
		}
		if err := ValidateResponse(vector.Request, vector.Response); err != nil {
			t.Fatalf("%s response = %v", vector.Name, err)
		}
	}
	for _, required := range []string{"create", "update", "delete", "typed-values", "explicit-null", "absent-field", "missing-rls-mask", "object-crud", "access-denied", "atomic", "partial-result"} {
		if !covered[required] {
			t.Fatalf("coverage %q missing", required)
		}
	}
}

func TestImmutableObjectNotFoundPreflightVector(t *testing.T) {
	data := ObjectNotFoundPreflightVectorJSON()
	for _, forbidden := range [][]byte{[]byte("salesforce"), []byte("sfcrm"), []byte("sobject")} {
		if bytes.Contains(bytes.ToLower(data), forbidden) {
			t.Fatalf("product vocabulary %q leaked into neutral vector", forbidden)
		}
	}
	var vector struct {
		SchemaVersion string   `json:"schema_version"`
		Request       Request  `json:"request"`
		Response      Response `json:"response"`
	}
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(&vector); err != nil {
		t.Fatal(err)
	}
	if vector.SchemaVersion != "nexuscrm.runtime.record-mutation.object-not-found-preflight/v1" {
		t.Fatalf("schema = %q", vector.SchemaVersion)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := ValidateRequest(ctx, vector.Request); err != nil {
		t.Fatal(err)
	}
	digest, err := CommandDigest(vector.Request)
	if err != nil {
		t.Fatal(err)
	}
	if vector.Response.CommandDigest != digest {
		t.Fatalf("vector command digest = %q, want %q", vector.Response.CommandDigest, digest)
	}
	if err := ValidateResponse(vector.Request, vector.Response); err != nil {
		t.Fatalf("valid object-not-found preflight = %v", err)
	}

	for name, mutate := range map[string]func(*Response){
		"sibling success": func(response *Response) {
			created := true
			response.Results[0] = OperationResult{Index: 0, Kind: OperationCreate, RecordID: "created-1", Success: true, Created: &created, Errors: []OperationError{}}
		},
		"two causes": func(response *Response) {
			response.Results[0].Errors = []OperationError{{Kind: ErrorObjectNotFound, Fields: []string{}}}
		},
		"mixed preflight causes": func(response *Response) {
			response.Results[0].Errors = []OperationError{{Kind: ErrorPolicyDenied, AuthoredMessage: "Creation is closed.", Fields: []string{}}}
		},
	} {
		t.Run(name, func(t *testing.T) {
			candidate := vector.Response
			candidate.Results = append([]OperationResult(nil), vector.Response.Results...)
			mutate(&candidate)
			if err := ValidateResponse(vector.Request, candidate); err == nil {
				t.Fatal("invalid command-preflight outcome accepted")
			}
		})
	}
}

func TestExplicitUseCaseCrossLanguageDigestVector(t *testing.T) {
	var vector struct {
		SchemaVersion     string  `json:"schema_version"`
		Request           Request `json:"request"`
		CanonicalBytesHex string  `json:"canonical_bytes_hex"`
		CommandDigest     string  `json:"command_digest"`
	}
	decoder := json.NewDecoder(bytes.NewReader(UseCaseDigestVectorJSON()))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(&vector); err != nil {
		t.Fatal(err)
	}
	if vector.SchemaVersion != "nexuscrm.runtime.record-mutation.use-case-digest/v1" {
		t.Fatalf("schema = %q", vector.SchemaVersion)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := ValidateRequest(ctx, vector.Request); err != nil {
		t.Fatal(err)
	}
	canonical, err := CanonicalCommandBytes(vector.Request)
	if err != nil {
		t.Fatal(err)
	}
	if got := hex.EncodeToString(canonical); got != vector.CanonicalBytesHex {
		t.Fatalf("canonical bytes = %s", got)
	}
	digest, err := CommandDigest(vector.Request)
	if err != nil || digest != vector.CommandDigest {
		t.Fatalf("digest = %s, %v", digest, err)
	}
}

func TestExternalIdentityCrossLanguageDigestVector(t *testing.T) {
	var vector struct {
		SchemaVersion     string  `json:"schema_version"`
		Request           Request `json:"request"`
		CanonicalBytesHex string  `json:"canonical_bytes_hex"`
		CommandDigest     string  `json:"command_digest"`
	}
	decoder := json.NewDecoder(bytes.NewReader(ExternalIdentityDigestVectorJSON()))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(&vector); err != nil {
		t.Fatal(err)
	}
	if vector.SchemaVersion != "nexuscrm.runtime.record-mutation.external-identity-digest/v1" {
		t.Fatalf("schema = %q", vector.SchemaVersion)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := ValidateRequest(ctx, vector.Request); err != nil {
		t.Fatal(err)
	}
	canonical, err := CanonicalCommandBytes(vector.Request)
	if err != nil {
		t.Fatal(err)
	}
	if got := hex.EncodeToString(canonical); got != vector.CanonicalBytesHex {
		t.Fatalf("canonical bytes = %s", got)
	}
	digest, err := CommandDigest(vector.Request)
	if err != nil || digest != vector.CommandDigest {
		t.Fatalf("digest = %s, %v", digest, err)
	}
}

func typedRequest() Request {
	falseValue := false
	zero := int64(0)
	empty := ""
	date := "2026-07-19"
	datetime := "2026-07-19T12:30:00Z"
	reference := "principal-001"
	return Request{CommandID: "cmd-create-001", BatchMode: BatchIndependent, Operations: []Operation{{
		Kind: OperationCreate, ObjectID: "WorkItem", Fields: []FieldValue{
			{Name: "Active", Kind: ValueKindBoolean, Boolean: &falseValue},
			{Name: "Amount", Kind: ValueKindDecimal, Decimal: &Decimal{Coefficient: "0", Scale: 4}},
			{Name: "Count", Kind: ValueKindInteger, Integer: &zero},
			{Name: "DueDate", Kind: ValueKindDate, Date: &date},
			{Name: "EmptyText", Kind: ValueKindString, String: &empty},
			{Name: "OptionalText", Kind: ValueKindNull, Null: true},
			{Name: "OwnerRef", Kind: ValueKindReference, Reference: &reference},
			{Name: "ObservedAt", Kind: ValueKindDateTime, DateTime: &datetime},
		},
	}}}
}

func validReceipts() Receipts {
	return Receipts{ProtocolVersion: "1.0", CatalogRevision: 41, SchemaGeneration: 7, EngineGeneration: 9, SecurityEpoch: 13, CapabilityVersion: CapabilityName}
}
