package boundary_test

import (
	"bytes"
	"encoding/json"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"testing"
)

const appAuthorityManifestPath = "docs/design/app-authority-contract.json"

type appAuthorityManifest struct {
	Schema            string                      `json:"schema"`
	Status            string                      `json:"status"`
	EvidenceRevision  string                      `json:"evidence_revision"`
	NormativeDocument string                      `json:"normative_document"`
	FirstSlice        appAuthorityFirstSlice      `json:"first_slice"`
	Identity          appAuthorityIdentity        `json:"identity"`
	ReleaseContract   appAuthorityReleaseContract `json:"release_contract"`
	FactOwners        []appAuthorityFactOwner     `json:"fact_owners"`
	ReleasePlanes     []appAuthorityReleasePlane  `json:"release_planes"`
	HandlerBinding    appAuthorityHandlerBinding  `json:"handler_binding"`
	AppInstallation   appAuthorityInstallation    `json:"app_installation"`
	PackTransition    appAuthorityPackTransition  `json:"pack_transition"`
	Handoffs          []appAuthorityHandoff       `json:"handoffs"`
	Invariants        []string                    `json:"invariants"`
	SourceAnchors     []appAuthoritySourceAnchor  `json:"source_anchors"`
}

type appAuthorityFirstSlice struct {
	Route                           string `json:"route"`
	PublisherID                     string `json:"publisher_id"`
	AppID                           string `json:"app_id"`
	L1CapabilityID                  string `json:"l1_capability_id"`
	HandlerRef                      string `json:"handler_ref"`
	RuntimeCapabilityID             string `json:"runtime_capability_id"`
	AcceptedNonEmptyRuntimeRPCCount int    `json:"accepted_non_empty_runtime_rpc_count"`
	AcceptedEmptyRuntimeRPCCount    int    `json:"accepted_empty_runtime_rpc_count"`
	RejectedRuntimeRPCCount         int    `json:"rejected_runtime_rpc_count"`
}

type appAuthorityIdentity struct {
	NamedIdentifierPattern                      string   `json:"named_identifier_pattern"`
	AppIDMinimumSegments                        int      `json:"app_id_minimum_segments"`
	MaximumBytes                                int      `json:"maximum_bytes"`
	Normalization                               string   `json:"normalization"`
	AppInstallationIDFormat                     string   `json:"app_installation_id_format"`
	AppIDImmutable                              bool     `json:"app_id_immutable"`
	PublisherTransferRequiresCurrentAndOperator bool     `json:"publisher_transfer_requires_current_publisher_and_operator"`
	ForbiddenAppIDSources                       []string `json:"forbidden_app_id_sources"`
}

type appAuthorityReleaseContract struct {
	SemanticVersionProfile          string                                `json:"semantic_version_profile"`
	CanonicalJSONProfile            string                                `json:"canonical_json_profile"`
	DigestAlgorithm                 string                                `json:"digest_algorithm"`
	DigestTextPattern               string                                `json:"digest_text_pattern"`
	ComponentIDDomain               string                                `json:"component_id_domain"`
	ComponentDigestDomain           string                                `json:"component_digest_domain"`
	MetadataBundleDigestDomain      string                                `json:"metadata_bundle_digest_domain"`
	AppReleaseDigestDomain          string                                `json:"app_release_digest_domain"`
	AppReleaseIdentity              string                                `json:"app_release_identity"`
	AppReleaseDigestInManifest      bool                                  `json:"app_release_digest_in_manifest"`
	PackageDigestIsAppReleaseDigest bool                                  `json:"package_digest_is_app_release_digest"`
	ManifestSchemaVersion           string                                `json:"manifest_schema_version"`
	MetadataBundleSchemaVersion     string                                `json:"metadata_bundle_schema_version"`
	RegisteredComponentKinds        []appAuthorityRegisteredComponentKind `json:"registered_component_kinds"`
	ManifestBehaviorFields          []string                              `json:"manifest_behavior_fields"`
	ManifestForbiddenFields         []string                              `json:"manifest_forbidden_fields"`
	MetadataBundleOwnedFields       []string                              `json:"metadata_bundle_owned_fields"`
	MetadataBundleForbiddenFields   []string                              `json:"metadata_bundle_forbidden_fields"`
	DependencyEntryFields           []string                              `json:"dependency_entry_fields"`
	RequiredProtocolEntryFields     []string                              `json:"required_protocol_entry_fields"`
	ProvidedCapabilityEntryFields   []string                              `json:"provided_capability_entry_fields"`
	ProvidedCapabilityKinds         []string                              `json:"provided_capability_kinds"`
	FrontendCompatibilityModes      []string                              `json:"frontend_compatibility_modes"`
	ComponentEntryFields            []string                              `json:"component_entry_fields"`
	ExternalComponentRefEntryFields []string                              `json:"external_component_ref_entry_fields"`
	OverridePolicyValues            []string                              `json:"override_policy_values"`
	RemovalPolicyValues             []string                              `json:"removal_policy_values"`
	CanonicalSetSortKeys            map[string]string                     `json:"canonical_set_sort_keys"`
	DetachedInformationalOnly       bool                                  `json:"detached_informational_metadata_only"`
	BehavioralExtensionsAllowed     bool                                  `json:"behavioral_extensions_allowed"`
}

type appAuthorityRegisteredComponentKind struct {
	ComponentKind                     string   `json:"component_kind"`
	ComponentFormatVersion            uint32   `json:"component_format_version"`
	BehaviorSchemaVersion             string   `json:"behavior_schema_version"`
	BehaviorCanonicalProfile          string   `json:"behavior_canonical_profile"`
	BehaviorRequiredFields            []string `json:"behavior_required_fields"`
	BehaviorOptionalFields            []string `json:"behavior_optional_fields"`
	BusinessKeyGrammar                string   `json:"business_key_grammar"`
	RegisteredKindValidationRequired  bool     `json:"registered_kind_validation_required"`
	LocalKeyUniqueAcrossAppNamespaces bool     `json:"local_key_unique_across_app_namespaces"`
	ExternalComponentRefsMustBeEmpty  bool     `json:"external_component_refs_must_be_empty"`
	OverridePolicy                    string   `json:"override_policy"`
	RemovalPolicy                     string   `json:"removal_policy"`
	LocalDependenciesRule             string   `json:"local_dependencies_rule"`
	TargetRule                        string   `json:"target_rule"`
	PredecessorRule                   string   `json:"predecessor_rule"`
	RevisionDigestDomain              string   `json:"revision_digest_domain"`
	RevisionDigestInput               string   `json:"revision_digest_input"`
	ReservationKey                    []string `json:"reservation_key"`
	VersionKey                        []string `json:"version_key"`
	HeadCompareAndSwapFields          []string `json:"head_compare_and_swap_fields"`
	ExactHistoricalReuse              bool     `json:"exact_historical_reuse"`
	AppendRequiresHeadPlusOne         bool     `json:"append_requires_head_plus_one"`
	AppendRequiresTargetChange        bool     `json:"append_requires_target_change"`
	OmissionMutatesLineage            bool     `json:"omission_mutates_lineage"`
}

type appAuthorityFactOwner struct {
	ID                   string   `json:"id"`
	Author               string   `json:"author"`
	Authority            string   `json:"authority"`
	Representation       string   `json:"representation"`
	ForbiddenAuthorities []string `json:"forbidden_authorities"`
}

type appAuthorityReleasePlane struct {
	ID            string `json:"id"`
	Identity      string `json:"identity"`
	Content       string `json:"content"`
	ActiveBinding string `json:"active_binding"`
}

type appAuthorityHandlerBinding struct {
	IDFormat                               string   `json:"id_format"`
	NaturalKey                             string   `json:"natural_key"`
	States                                 []string `json:"states"`
	MaximumActivePerInstallationCapability int      `json:"maximum_active_per_installation_capability"`
	ContainsEndpointURL                    bool     `json:"contains_endpoint_url"`
	EndpointOwner                          string   `json:"endpoint_owner"`
	ActivationIsFencedCompareAndSwap       bool     `json:"activation_is_fenced_compare_and_swap"`
}

type appAuthorityInstallation struct {
	Authority                                  string   `json:"authority"`
	States                                     []string `json:"states"`
	AppIDImmutableAfterCreation                bool     `json:"app_id_immutable_after_creation"`
	MaximumLivePerOrgAppID                     int      `json:"maximum_live_per_org_app_id"`
	LiveStates                                 []string `json:"live_states"`
	RemovingCompletionReleasesLiveReservation  bool     `json:"removing_completion_releases_live_reservation"`
	MultipleLiveRowsFailClosed                 bool     `json:"multiple_live_rows_fail_closed"`
	RuntimeProjectionIsAuthoritative           bool     `json:"runtime_projection_is_authoritative"`
	DeploymentLockfileIsAuthoritative          bool     `json:"deployment_lockfile_is_authoritative"`
	SecurityEpochAndCatalogRevisionIndependent bool     `json:"security_epoch_and_catalog_revision_are_independent"`
	PublicationSequence                        []string `json:"publication_sequence"`
}

type appAuthorityPackTransition struct {
	Scope                                     string   `json:"scope"`
	Mode                                      string   `json:"mode"`
	TargetAppID                               string   `json:"target_app_id"`
	ExcludedCategories                        []string `json:"excluded_categories"`
	IssueTrackerExcluded                      bool     `json:"issue_tracker_excluded"`
	LegacyServingAdapterPermanent             bool     `json:"legacy_serving_adapter_permanent"`
	DualReadForSameCapabilityAllowed          bool     `json:"dual_read_for_same_capability_allowed"`
	LegacyUpgradeWritesAfterConversionAllowed bool     `json:"legacy_upgrade_writes_after_conversion_allowed"`
	Inputs                                    []string `json:"inputs"`
	EquivalenceProofs                         []string `json:"equivalence_proofs"`
	DeletionGates                             []string `json:"deletion_gates"`
}

type appAuthorityHandoff struct {
	Phase     string   `json:"phase"`
	Inputs    []string `json:"inputs"`
	Outputs   []string `json:"outputs"`
	Forbidden []string `json:"forbidden"`
}

type appAuthoritySourceAnchor struct {
	Path   string `json:"path"`
	Anchor string `json:"anchor"`
}

func TestAppAuthorityContractHasOneOwnerPerFact(t *testing.T) {
	manifest := loadAppAuthorityManifest(t)

	if manifest.Schema != "nexuscrm.app-authority-contract.a1b/v1" || manifest.Status != "normative-on-merge" {
		t.Fatalf("unexpected App authority identity: schema=%q status=%q", manifest.Schema, manifest.Status)
	}
	if !validCommitSHA(manifest.EvidenceRevision) {
		t.Fatalf("evidence revision = %q, want a full commit SHA", manifest.EvidenceRevision)
	}
	if manifest.NormativeDocument != "docs/design/app-authority-contract.md" {
		t.Fatalf("normative document = %q", manifest.NormativeDocument)
	}

	requiredOwners := map[string]string{
		"app-identity":          "Catalog App identity registry",
		"publisher-trust":       "Catalog publisher trust registry",
		"app-manifest-contract": "canonical AppManifest in immutable AppPackage",
		"app-release":           "Catalog AppRelease registry",
		"app-dependencies-namespaces-compatibility": "AppManifest",
		"metadata-components":                       "MetadataBundle",
		"app-layout-bundle-slot-lineage":            "Catalog App layout-bundle slot registry",
		"publication-provenance":                    "artifact registry bytes plus detached publisher attestation",
		"app-installation":                          "Catalog AppInstallation registry and journal",
		"runtime-security-projection":               "Runtime Identity/Security SecurityEpoch allocator, complete security projection and immutable attestation writer, and serving reader",
		"handler-declaration":                       "AppManifest ProvidedCapabilities",
		"handler-binding":                           "Catalog HandlerBinding registry",
		"service-release":                           "artifact registry",
		"frontend-release":                          "artifact registry",
		"frontend-binding":                          "Catalog frontend binding registry",
		"online-configuration":                      "configuration domain authority independent of Catalog publication",
		"navigation-configuration":                  "_System_App metadata read/write path",
		"generic-pack-lifecycle":                    "PackManifest and _System_InstalledPack for non-App categories",
	}
	seen := make(map[string]bool, len(manifest.FactOwners))
	for _, fact := range manifest.FactOwners {
		if strings.TrimSpace(fact.ID) == "" || seen[fact.ID] {
			t.Fatalf("blank or duplicate fact owner id %q", fact.ID)
		}
		seen[fact.ID] = true
		if fact.Author == "" || fact.Authority == "" || fact.Representation == "" || len(fact.ForbiddenAuthorities) == 0 {
			t.Fatalf("incomplete owner declaration for %q: %#v", fact.ID, fact)
		}
		if want, required := requiredOwners[fact.ID]; required && fact.Authority != want {
			t.Fatalf("fact %q authority = %q, want %q", fact.ID, fact.Authority, want)
		}
		if fact.ID == "online-configuration" {
			for _, forbidden := range []string{"Catalog revision lineage", "Catalog activation pointer", "AppReleaseDigest", "deployment BOM", "Runtime cache"} {
				if !containsString(fact.ForbiddenAuthorities, forbidden) {
					t.Fatalf("online configuration must forbid %q as its authority", forbidden)
				}
			}
		}
		if fact.ID == "runtime-security-projection" {
			if fact.Author != "Runtime Identity/Security from authoritative non-App inputs and fenced Catalog desired-App-grant commands" {
				t.Fatalf("Runtime security author = %q", fact.Author)
			}
			for _, required := range []string{"Profile eligibility", "user membership", "SecurityEpoch to projection-digest attestation"} {
				if !strings.Contains(fact.Representation, required) {
					t.Fatalf("Runtime security representation must bind %q", required)
				}
			}
			for _, forbidden := range []string{"Catalog-written Runtime security projection", "Catalog-allocated SecurityEpoch"} {
				if !containsString(fact.ForbiddenAuthorities, forbidden) {
					t.Fatalf("Runtime security projection must forbid %q", forbidden)
				}
			}
		}
		for _, forbidden := range fact.ForbiddenAuthorities {
			if strings.TrimSpace(forbidden) == "" || forbidden == fact.Authority {
				t.Fatalf("fact %q has invalid forbidden authority %q", fact.ID, forbidden)
			}
		}
	}
	if len(seen) != len(requiredOwners) {
		t.Fatalf("fact owner count = %d, want exactly %d", len(seen), len(requiredOwners))
	}
	for id := range requiredOwners {
		if !seen[id] {
			t.Fatalf("required fact owner %q is missing", id)
		}
	}
}

func TestAppAuthorityIdentityAndReleasePlanesAreClosed(t *testing.T) {
	manifest := loadAppAuthorityManifest(t)
	first := manifest.FirstSlice
	identity := manifest.Identity

	if first.Route != "POST /services/data/:version/ui-api/record-access" ||
		first.PublisherID != "io.nexuscrm" || first.AppID != "io.nexuscrm.sfcrm" ||
		first.L1CapabilityID != "io.nexuscrm.sfcrm.ui.record-access.v1" ||
		first.HandlerRef != "io.nexuscrm.sfcrm.handler.ui.record-access.v1" ||
		first.RuntimeCapabilityID != "runtime.records.evaluate-access.v1" {
		t.Fatalf("first slice changed without an A1b revision: %#v", first)
	}
	if first.AcceptedNonEmptyRuntimeRPCCount != 1 || first.AcceptedEmptyRuntimeRPCCount != 0 || first.RejectedRuntimeRPCCount != 0 {
		t.Fatalf("first-slice RPC counts changed: %#v", first)
	}
	if identity.MaximumBytes != 128 || identity.AppIDMinimumSegments != 3 || identity.Normalization != "reject_noncanonical" ||
		identity.AppInstallationIDFormat != "lowercase_uuidv7" || !identity.AppIDImmutable || !identity.PublisherTransferRequiresCurrentAndOperator {
		t.Fatalf("identifier contract changed: %#v", identity)
	}
	pattern, err := regexp.Compile(identity.NamedIdentifierPattern)
	if err != nil {
		t.Fatalf("compile named identifier pattern: %v", err)
	}
	for label, value := range map[string]string{
		"publisher": first.PublisherID, "app": first.AppID,
		"L1 capability": first.L1CapabilityID, "handler": first.HandlerRef,
		"Runtime capability": first.RuntimeCapabilityID,
	} {
		if len(value) > identity.MaximumBytes || !pattern.MatchString(value) {
			t.Fatalf("%s identifier %q violates the A1b grammar", label, value)
		}
	}
	for _, invalid := range []string{"A.b.c", "a..b.c", "a-.b.c", "a.b.c-", " a.b.c", "a.b.c "} {
		if pattern.MatchString(invalid) {
			t.Fatalf("named identifier pattern accepts noncanonical value %q", invalid)
		}
	}
	if len(strings.Split(first.AppID, ".")) < identity.AppIDMinimumSegments {
		t.Fatalf("AppID %q has too few segments", first.AppID)
	}
	for _, value := range []string{first.L1CapabilityID, first.HandlerRef, first.RuntimeCapabilityID} {
		if !regexp.MustCompile(`\.v[1-9][0-9]*$`).MatchString(value) {
			t.Fatalf("versioned identifier %q has no terminal major", value)
		}
	}
	assertStringSet(t, "forbidden_app_id_sources", identity.ForbiddenAppIDSources, []string{
		"_System_App", "PackManifest.name", "FrontendAppId", "PackInstallId", "repository_url", "git_sha",
	})

	release := manifest.ReleaseContract
	if release.SemanticVersionProfile != "semver-2.0.0-no-leading-v-no-build-metadata" ||
		release.CanonicalJSONProfile != "RFC8785" || release.DigestAlgorithm != "sha256" ||
		release.DigestTextPattern != "^sha256:[0-9a-f]{64}$" ||
		release.ComponentIDDomain != "nexuscrm.app-component-id.v1\x00" ||
		release.ComponentDigestDomain != "nexuscrm.app-component.v1\x00" ||
		release.MetadataBundleDigestDomain != "nexuscrm.metadata-bundle.v1\x00" ||
		release.AppReleaseDigestDomain != "nexuscrm.app-release.v1\x00" ||
		release.AppReleaseIdentity != "AppID+AppReleaseDigest" || release.AppReleaseDigestInManifest ||
		!release.PackageDigestIsAppReleaseDigest || release.ManifestSchemaVersion != "nexuscrm.app-manifest/v1" ||
		release.MetadataBundleSchemaVersion != "nexuscrm.metadata-bundle/v1" ||
		!release.DetachedInformationalOnly || release.BehavioralExtensionsAllowed {
		t.Fatalf("release contract is no longer closed: %#v", release)
	}
	for _, required := range []string{"schema_version", "app_id", "publisher_id", "semantic_version", "metadata_bundle_digest", "dependencies", "owned_namespaces", "required_protocols", "required_engine_capabilities", "provided_capabilities", "frontend_compatibility"} {
		if !containsString(release.ManifestBehaviorFields, required) {
			t.Fatalf("manifest behavior fields missing %q", required)
		}
	}
	assertStringSet(t, "manifest forbidden fields", release.ManifestForbiddenFields, []string{
		"app_release_digest", "service_release_digest", "frontend_release_digest", "endpoint_url",
		"app_installation_id", "catalog_revision", "l2_revision", "extensions",
	})
	for _, forbidden := range []string{"app_id", "publisher_id", "semantic_version", "dependencies", "owned_namespaces", "required_protocols", "required_engine_capabilities", "provided_capabilities", "owner_app_id", "metadata_bundle_digest", "app_release_digest", "extensions"} {
		if !containsString(release.MetadataBundleForbiddenFields, forbidden) {
			t.Fatalf("MetadataBundle forbidden fields missing %q", forbidden)
		}
	}
	for _, owned := range []string{"schema_version", "components", "component_id", "component_kind", "component_format_version", "namespace_id", "business_key", "definition_version", "local_dependencies", "external_component_refs", "override_policy", "removal_policy", "content_digest"} {
		if !containsString(release.MetadataBundleOwnedFields, owned) {
			t.Fatalf("MetadataBundle owned fields missing %q", owned)
		}
	}
	assertStringSet(t, "dependency entry fields", release.DependencyEntryFields, []string{"alias", "app_id", "minimum_version_inclusive", "maximum_version_exclusive", "required_capabilities"})
	assertStringSet(t, "required protocol entry fields", release.RequiredProtocolEntryFields, []string{"protocol_id", "major", "minimum_minor"})
	assertStringSet(t, "provided capability entry fields", release.ProvidedCapabilityEntryFields, []string{"capability_id", "kind", "handler_ref", "required_runtime_capabilities"})
	assertStringSet(t, "provided capability kinds", release.ProvidedCapabilityKinds, []string{"metadata", "service-handler"})
	assertStringSet(t, "frontend compatibility modes", release.FrontendCompatibilityModes, []string{"none", "required"})
	assertStringSet(t, "component entry fields", release.ComponentEntryFields, []string{
		"component_id", "component_kind", "component_format_version", "namespace_id", "business_key", "definition_version",
		"local_dependencies", "external_component_refs", "override_policy", "removal_policy", "content_digest",
	})
	assertStringSet(t, "external component ref fields", release.ExternalComponentRefEntryFields, []string{"dependency_alias", "namespace_id", "component_kind", "business_key"})
	assertStringSet(t, "override policies", release.OverridePolicyValues, []string{"replace", "preserve-authorized-overrides"})
	assertStringSet(t, "removal policies", release.RemovalPolicyValues, []string{"remove-if-unreferenced", "block-if-referenced-or-overridden"})
	wantSortKeys := map[string]string{
		"dependencies": "alias", "dependency_required_capabilities": "value", "owned_namespaces": "value",
		"required_protocols": "protocol_id", "required_engine_capabilities": "value", "provided_capabilities": "capability_id",
		"provided_required_runtime_capabilities": "value", "components": "component_id", "local_dependencies": "value",
		"external_component_refs": "dependency_alias+namespace_id+component_kind+business_key",
	}
	if len(release.CanonicalSetSortKeys) != len(wantSortKeys) {
		t.Fatalf("canonical sort keys = %v, want %v", release.CanonicalSetSortKeys, wantSortKeys)
	}
	for collection, want := range wantSortKeys {
		if got := release.CanonicalSetSortKeys[collection]; got != want {
			t.Fatalf("canonical sort key for %q = %q, want %q", collection, got, want)
		}
	}
	if len(release.RegisteredComponentKinds) != 1 {
		t.Fatalf("registered component kinds = %d, want one", len(release.RegisteredComponentKinds))
	}
	slot := release.RegisteredComponentKinds[0]
	if slot.ComponentKind != "io.nexuscrm.layout-bundle-slot.v1" || slot.ComponentFormatVersion != 1 ||
		slot.BehaviorSchemaVersion != "nexuscrm.layout-bundle-slot/v1" || slot.BehaviorCanonicalProfile != "RFC8785" ||
		slot.BusinessKeyGrammar != "key256:<64 lowercase hex>" || !slot.RegisteredKindValidationRequired ||
		!slot.LocalKeyUniqueAcrossAppNamespaces || !slot.ExternalComponentRefsMustBeEmpty ||
		slot.OverridePolicy != "replace" || slot.RemovalPolicy != "block-if-referenced-or-overridden" ||
		slot.LocalDependenciesRule != "exact singleton target_component_id" ||
		slot.TargetRule != "non-slot component in the same MetadataBundle" ||
		slot.PredecessorRule != "version 1 omits previous_target_component_id; version N above 1 requires it to equal version N-1 target_component_id" ||
		slot.RevisionDigestDomain != "nexuscrm.layout-bundle-slot-revision.v1\x00" ||
		slot.RevisionDigestInput != "RFC8785 JCS of app_id plus exact canonical component descriptor" ||
		!slot.ExactHistoricalReuse || !slot.AppendRequiresHeadPlusOne || !slot.AppendRequiresTargetChange || slot.OmissionMutatesLineage {
		t.Fatalf("layout-bundle slot registered-kind contract drifted: %#v", slot)
	}
	assertStringSet(t, "layout-bundle slot required behavior fields", slot.BehaviorRequiredFields, []string{"schema_version", "local_component_key", "target_component_id"})
	assertStringSet(t, "layout-bundle slot optional behavior fields", slot.BehaviorOptionalFields, []string{"previous_target_component_id"})
	assertStringSet(t, "layout-bundle slot reservation key", slot.ReservationKey, []string{"AppID", "LocalComponentKey"})
	assertStringSet(t, "layout-bundle slot version key", slot.VersionKey, []string{"AppID", "LocalComponentKey", "DefinitionVersion"})
	assertStringSet(t, "layout-bundle slot head CAS", slot.HeadCompareAndSwapFields, []string{"HeadDefinitionVersion", "HeadRevisionDigest"})

	requiredPlanes := map[string]string{
		"app-release": "AppID+AppReleaseDigest", "service-release": "immutable image digest",
		"frontend-release": "immutable asset digest", "catalog-publication": "CatalogRevision plus content checksum",
	}
	seenPlane := make(map[string]bool, len(manifest.ReleasePlanes))
	seenIdentity := make(map[string]bool, len(manifest.ReleasePlanes))
	for _, plane := range manifest.ReleasePlanes {
		if seenPlane[plane.ID] || seenIdentity[plane.Identity] || plane.Content == "" || plane.ActiveBinding == "" {
			t.Fatalf("release planes are not independent: %#v", plane)
		}
		seenPlane[plane.ID], seenIdentity[plane.Identity] = true, true
		if want := requiredPlanes[plane.ID]; want == "" || plane.Identity != want {
			t.Fatalf("release plane %q identity = %q, want %q", plane.ID, plane.Identity, want)
		}
	}
	if len(seenPlane) != len(requiredPlanes) {
		t.Fatalf("release plane count = %d, want %d", len(seenPlane), len(requiredPlanes))
	}
}

func TestAppAuthorityTransitionAndHandoffsStayFinite(t *testing.T) {
	manifest := loadAppAuthorityManifest(t)
	transition := manifest.PackTransition
	if transition.Scope != "crm-app-pack-only" || transition.Mode != "one-time-direct-conversion" ||
		transition.TargetAppID != manifest.FirstSlice.AppID || !transition.IssueTrackerExcluded ||
		transition.LegacyServingAdapterPermanent || transition.DualReadForSameCapabilityAllowed ||
		transition.LegacyUpgradeWritesAfterConversionAllowed {
		t.Fatalf("CRM transition widened or gained a legacy path: %#v", transition)
	}
	assertStringSet(t, "excluded_categories", transition.ExcludedCategories, []string{"platform", "tenant", "connector", "integration", "non-app"})
	for name, values := range map[string][]string{
		"transition inputs": transition.Inputs, "equivalence proofs": transition.EquivalenceProofs,
		"deletion gates": transition.DeletionGates, "invariants": manifest.Invariants,
	} {
		assertFiniteStrings(t, name, values)
	}
	if len(transition.EquivalenceProofs) < 7 || len(transition.DeletionGates) < 7 {
		t.Fatalf("CRM transition proof was weakened: proofs=%d deletion_gates=%d", len(transition.EquivalenceProofs), len(transition.DeletionGates))
	}

	if manifest.AppInstallation.Authority != "Catalog" || !manifest.AppInstallation.AppIDImmutableAfterCreation ||
		manifest.AppInstallation.RuntimeProjectionIsAuthoritative || manifest.AppInstallation.DeploymentLockfileIsAuthoritative ||
		!manifest.AppInstallation.SecurityEpochAndCatalogRevisionIndependent {
		t.Fatalf("AppInstallation authority changed: %#v", manifest.AppInstallation)
	}
	assertStringSet(t, "AppInstallation states", manifest.AppInstallation.States, []string{
		"PREPARING", "ACTIVE", "UPGRADING", "ROLLING_BACK", "REMOVING", "FAILED", "REMOVED",
	})
	if manifest.AppInstallation.MaximumLivePerOrgAppID != 1 ||
		!manifest.AppInstallation.RemovingCompletionReleasesLiveReservation ||
		!manifest.AppInstallation.MultipleLiveRowsFailClosed {
		t.Fatalf("AppInstallation live reservation contract drifted: %#v", manifest.AppInstallation)
	}
	assertStringSet(t, "AppInstallation live states", manifest.AppInstallation.LiveStates, []string{
		"PREPARING", "ACTIVE", "UPGRADING", "ROLLING_BACK", "REMOVING", "FAILED",
	})
	assertFiniteStrings(t, "AppInstallation publication sequence", manifest.AppInstallation.PublicationSequence)
	if len(manifest.AppInstallation.PublicationSequence) != 5 {
		t.Fatalf("AppInstallation publication sequence has %d steps, want five", len(manifest.AppInstallation.PublicationSequence))
	}
	if manifest.HandlerBinding.IDFormat != "lowercase_uuidv7" ||
		manifest.HandlerBinding.NaturalKey != "OrgID+AppInstallationID+CapabilityID+OwnershipEpoch" ||
		manifest.HandlerBinding.MaximumActivePerInstallationCapability != 1 || manifest.HandlerBinding.ContainsEndpointURL ||
		manifest.HandlerBinding.EndpointOwner != "deployment authority" || !manifest.HandlerBinding.ActivationIsFencedCompareAndSwap {
		t.Fatalf("HandlerBinding authority changed: %#v", manifest.HandlerBinding)
	}
	assertStringSet(t, "HandlerBinding states", manifest.HandlerBinding.States, []string{"STAGED", "ACTIVE", "DRAINING", "RETIRED", "FAILED"})

	requiredHandoffs := map[string]bool{"A1c": false, "P7b": false, "R1b": false, "P7c/S1": false}
	for _, handoff := range manifest.Handoffs {
		if _, ok := requiredHandoffs[handoff.Phase]; !ok || requiredHandoffs[handoff.Phase] {
			t.Fatalf("unknown or duplicate handoff %q", handoff.Phase)
		}
		requiredHandoffs[handoff.Phase] = true
		assertFiniteStrings(t, handoff.Phase+" inputs", handoff.Inputs)
		assertFiniteStrings(t, handoff.Phase+" outputs", handoff.Outputs)
		assertFiniteStrings(t, handoff.Phase+" forbidden", handoff.Forbidden)
	}
	for phase, present := range requiredHandoffs {
		if !present {
			t.Fatalf("handoff %q is missing", phase)
		}
	}
}

func TestAppAuthoritySourcesAndNormativeDocsStayAligned(t *testing.T) {
	root := repoRoot(t)
	manifest := loadAppAuthorityManifest(t)
	if len(manifest.SourceAnchors) < 7 {
		t.Fatalf("source anchors = %d, want at least seven independent anchors", len(manifest.SourceAnchors))
	}
	seen := make(map[string]bool, len(manifest.SourceAnchors))
	for _, source := range manifest.SourceAnchors {
		if filepath.IsAbs(source.Path) || strings.Contains(source.Path, "..") || source.Anchor == "" {
			t.Fatalf("invalid source anchor %#v", source)
		}
		key := source.Path + "\x00" + source.Anchor
		if seen[key] {
			t.Fatalf("duplicate source anchor %#v", source)
		}
		seen[key] = true
		body, err := os.ReadFile(filepath.Join(root, filepath.FromSlash(source.Path)))
		if err != nil {
			t.Fatalf("read source anchor %s: %v", source.Path, err)
		}
		if !bytes.Contains(body, []byte(source.Anchor)) {
			t.Fatalf("source anchor %q is absent from %s", source.Anchor, source.Path)
		}
	}

	adr := readFile(t, filepath.Join(root, filepath.FromSlash(manifest.NormativeDocument)))
	for _, required := range []string{
		"AppReleaseDigest is not present inside AppManifest",
		"The release/deployment planes are independent of each other and of online configuration",
		"configuration-and-execution-lifecycle.md",
		"runtime.records.evaluate-access.v1",
		"A1c, P7b, and R1b may implement in parallel from this contract",
		"blocked until all three complete",
	} {
		if !strings.Contains(adr, required) {
			t.Fatalf("App authority ADR lost invariant marker %q", required)
		}
	}
	for _, removed := range []string{"TenantCustomizable", "tenant_customizable", "upgrade_policy", "replace-l1", "authorized-l2"} {
		if strings.Contains(adr, removed) {
			t.Fatalf("normative App authority document retains removed contract token %q", removed)
		}
	}

	target := readFile(t, filepath.Join(root, "docs", "design", "nexuscrm-serviceification-target-architecture.md"))
	if !strings.Contains(target, "[App authority contract](app-authority-contract.md)") {
		t.Fatal("target architecture must delegate App-domain details to the App authority contract")
	}
	if !strings.Contains(target, "configuration-and-execution-lifecycle.md") {
		t.Fatal("target architecture must route editable configuration lifecycle to its domain boundary")
	}
	// Reject the competing authority claims found in review, including claims
	// buried below a top-level supersession note. This is a regression guard,
	// not a substitute for reviewing new ownership prose.
	for _, stale := range []string{
		"the sole authority for metadata, ownership,",
		"- the metadata catalog;",
		"Catalog is the sole authority for desired and published revisions",
		"Each org has one canonical CatalogRevision",
		"- org-global metadata: `OrgID + CatalogRevision`",
		"L2 CatalogRevision",
		"- authoring cannot succeed before snapshot publication;",
		"Authoring may be unavailable.",
		"AppRelease (immutable digest + semantic version)",
		"FrontendManifestRef",
		"HandlerBinding{HandlerRef, HandlerVersion, AppRelease}",
		"TenantCustomizable",
		"UpgradePolicy",
	} {
		if strings.Contains(target, stale) {
			t.Fatalf("target architecture retains competing App authority marker %q", stale)
		}
	}
}

func loadAppAuthorityManifest(t *testing.T) appAuthorityManifest {
	t.Helper()
	root := repoRoot(t)
	body, err := os.ReadFile(filepath.Join(root, filepath.FromSlash(appAuthorityManifestPath)))
	if err != nil {
		t.Fatalf("read App authority manifest: %v", err)
	}
	var manifest appAuthorityManifest
	decoder := json.NewDecoder(bytes.NewReader(body))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(&manifest); err != nil {
		t.Fatalf("decode App authority manifest: %v", err)
	}
	if err := decoder.Decode(&struct{}{}); err != io.EOF {
		t.Fatalf("App authority manifest has trailing content: %v", err)
	}
	return manifest
}

func assertStringSet(t *testing.T, name string, actual, expected []string) {
	t.Helper()
	actual = append([]string(nil), actual...)
	expected = append([]string(nil), expected...)
	sort.Strings(actual)
	sort.Strings(expected)
	if strings.Join(actual, "\x00") != strings.Join(expected, "\x00") {
		t.Fatalf("%s = %v, want %v", name, actual, expected)
	}
}

func assertFiniteStrings(t *testing.T, name string, values []string) {
	t.Helper()
	if len(values) == 0 {
		t.Fatalf("%s must be non-empty", name)
	}
	seen := make(map[string]bool, len(values))
	for _, value := range values {
		if strings.TrimSpace(value) == "" || seen[value] {
			t.Fatalf("%s has blank or duplicate value %q", name, value)
		}
		seen[value] = true
	}
}

func containsString(values []string, want string) bool {
	for _, value := range values {
		if value == want {
			return true
		}
	}
	return false
}
