{
  "schema": "nexuscrm.app-authority-contract.a1b/v1",
  "status": "normative-on-merge",
  "evidence_revision": "483e285b70bd85270103b073cd875128e648fb45",
  "normative_document": "docs/design/app-authority-contract.md",
  "first_slice": {
    "route": "POST /services/data/:version/ui-api/record-access",
    "publisher_id": "io.nexuscrm",
    "app_id": "io.nexuscrm.sfcrm",
    "l1_capability_id": "io.nexuscrm.sfcrm.ui.record-access.v1",
    "handler_ref": "io.nexuscrm.sfcrm.handler.ui.record-access.v1",
    "runtime_capability_id": "runtime.records.evaluate-access.v1",
    "accepted_non_empty_runtime_rpc_count": 1,
    "accepted_empty_runtime_rpc_count": 0,
    "rejected_runtime_rpc_count": 0
  },
  "identity": {
    "named_identifier_pattern": "^[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?)+$",
    "app_id_minimum_segments": 3,
    "maximum_bytes": 128,
    "normalization": "reject_noncanonical",
    "app_installation_id_format": "lowercase_uuidv7",
    "app_id_immutable": true,
    "publisher_transfer_requires_current_publisher_and_operator": true,
    "forbidden_app_id_sources": [
      "_System_App",
      "PackManifest.name",
      "FrontendAppId",
      "PackInstallId",
      "repository_url",
      "git_sha"
    ]
  },
  "release_contract": {
    "semantic_version_profile": "semver-2.0.0-no-leading-v-no-build-metadata",
    "canonical_json_profile": "RFC8785",
    "digest_algorithm": "sha256",
    "digest_text_pattern": "^sha256:[0-9a-f]{64}$",
    "component_id_domain": "nexuscrm.app-component-id.v1\u0000",
    "component_digest_domain": "nexuscrm.app-component.v1\u0000",
    "metadata_bundle_digest_domain": "nexuscrm.metadata-bundle.v1\u0000",
    "app_release_digest_domain": "nexuscrm.app-release.v1\u0000",
    "app_release_identity": "AppID+AppReleaseDigest",
    "app_release_digest_in_manifest": false,
    "package_digest_is_app_release_digest": true,
    "manifest_schema_version": "nexuscrm.app-manifest/v1",
    "metadata_bundle_schema_version": "nexuscrm.metadata-bundle/v1",
    "registered_component_kinds": [
      {
        "component_kind": "io.nexuscrm.layout-bundle-slot.v1",
        "component_format_version": 1,
        "behavior_schema_version": "nexuscrm.layout-bundle-slot/v1",
        "behavior_canonical_profile": "RFC8785",
        "behavior_required_fields": ["schema_version", "local_component_key", "target_component_id"],
        "behavior_optional_fields": ["previous_target_component_id"],
        "business_key_grammar": "key256:<64 lowercase hex>",
        "registered_kind_validation_required": true,
        "local_key_unique_across_app_namespaces": true,
        "external_component_refs_must_be_empty": true,
        "override_policy": "replace",
        "removal_policy": "block-if-referenced-or-overridden",
        "local_dependencies_rule": "exact singleton target_component_id",
        "target_rule": "non-slot component in the same MetadataBundle",
        "predecessor_rule": "version 1 omits previous_target_component_id; version N above 1 requires it to equal version N-1 target_component_id",
        "revision_digest_domain": "nexuscrm.layout-bundle-slot-revision.v1\u0000",
        "revision_digest_input": "RFC8785 JCS of app_id plus exact canonical component descriptor",
        "reservation_key": ["AppID", "LocalComponentKey"],
        "version_key": ["AppID", "LocalComponentKey", "DefinitionVersion"],
        "head_compare_and_swap_fields": ["HeadDefinitionVersion", "HeadRevisionDigest"],
        "exact_historical_reuse": true,
        "append_requires_head_plus_one": true,
        "append_requires_target_change": true,
        "omission_mutates_lineage": false
      }
    ],
    "manifest_behavior_fields": [
      "schema_version",
      "app_id",
      "publisher_id",
      "semantic_version",
      "metadata_bundle_digest",
      "dependencies",
      "owned_namespaces",
      "required_protocols",
      "required_engine_capabilities",
      "provided_capabilities",
      "frontend_compatibility"
    ],
    "manifest_forbidden_fields": [
      "app_release_digest",
      "service_release_digest",
      "frontend_release_digest",
      "endpoint_url",
      "app_installation_id",
      "catalog_revision",
      "l2_revision",
      "extensions"
    ],
    "metadata_bundle_owned_fields": [
      "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"
    ],
    "metadata_bundle_forbidden_fields": [
      "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"
    ],
    "dependency_entry_fields": [
      "alias",
      "app_id",
      "minimum_version_inclusive",
      "maximum_version_exclusive",
      "required_capabilities"
    ],
    "required_protocol_entry_fields": ["protocol_id", "major", "minimum_minor"],
    "provided_capability_entry_fields": [
      "capability_id",
      "kind",
      "handler_ref",
      "required_runtime_capabilities"
    ],
    "provided_capability_kinds": ["metadata", "service-handler"],
    "frontend_compatibility_modes": ["none", "required"],
    "component_entry_fields": [
      "component_id",
      "component_kind",
      "component_format_version",
      "namespace_id",
      "business_key",
      "definition_version",
      "local_dependencies",
      "external_component_refs",
      "override_policy",
      "removal_policy",
      "content_digest"
    ],
    "external_component_ref_entry_fields": [
      "dependency_alias",
      "namespace_id",
      "component_kind",
      "business_key"
    ],
    "override_policy_values": ["replace", "preserve-authorized-overrides"],
    "removal_policy_values": ["remove-if-unreferenced", "block-if-referenced-or-overridden"],
    "canonical_set_sort_keys": {
      "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"
    },
    "detached_informational_metadata_only": true,
    "behavioral_extensions_allowed": false
  },
  "fact_owners": [
    {
      "id": "app-identity",
      "author": "L1 publisher",
      "authority": "Catalog App identity registry",
      "representation": "canonical AppID reservation and ownership epoch",
      "forbidden_authorities": ["_System_App", "PackManifest.name", "FrontendAppId", "PackInstallId"]
    },
    {
      "id": "publisher-trust",
      "author": "operator trust authority",
      "authority": "Catalog publisher trust registry",
      "representation": "PublisherID to accepted signing identities and validity windows",
      "forbidden_authorities": ["repository URL", "Git SHA", "self-asserted AppManifest"]
    },
    {
      "id": "app-manifest-contract",
      "author": "L1 publisher",
      "authority": "canonical AppManifest in immutable AppPackage",
      "representation": "digest-covered closed v1 manifest",
      "forbidden_authorities": ["MetadataBundle", "legacy PackManifest after conversion", "deployment BOM"]
    },
    {
      "id": "app-release",
      "author": "derived from canonical AppPackage",
      "authority": "Catalog AppRelease registry",
      "representation": "AppID plus SHA-256 AppReleaseDigest, immutable semver mapping, and exact AppRelease-to-registered-slot-version bindings",
      "forbidden_authorities": ["PackVersion", "source revision", "Git SHA", "ServiceRelease", "FrontendRelease"]
    },
    {
      "id": "app-dependencies-namespaces-compatibility",
      "author": "L1 publisher",
      "authority": "AppManifest",
      "representation": "dependencies, owned namespaces, protocol/engine/frontend compatibility, provided capabilities",
      "forbidden_authorities": ["MetadataBundle", "PackManifest compatibility after conversion", "Runtime projection"]
    },
    {
      "id": "metadata-components",
      "author": "L1 publisher",
      "authority": "MetadataBundle",
      "representation": "component identity, component dependency graph, policies, content digests, and canonical registered component-kind behavior including io.nexuscrm.layout-bundle-slot.v1",
      "forbidden_authorities": ["AppManifest component list", "RuntimeMetadataView", "legacy source after conversion"]
    },
    {
      "id": "app-layout-bundle-slot-lineage",
      "author": "derived from verified signed declaration and the prior registered head",
      "authority": "Catalog App layout-bundle slot registry",
      "representation": "immutable AppID and LocalComponentKey reservation, version-indexed declaration revision ledger, AppRelease version binding, and fenced head compare-and-swap",
      "forbidden_authorities": ["AppRelease registration order", "semantic version order", "AppInstallation activation order", "deployment lockfile", "Runtime"]
    },
    {
      "id": "publication-provenance",
      "author": "owning release CI and publisher",
      "authority": "artifact registry bytes plus detached publisher attestation",
      "representation": "AppReleaseDigest-addressed artifact and detached provenance",
      "forbidden_authorities": ["Catalog informational annotations", "deployment lockfile"]
    },
    {
      "id": "app-installation",
      "author": "operator request validated by Catalog",
      "authority": "Catalog AppInstallation registry and journal",
      "representation": "OrgID plus AppInstallationID binding, lifecycle, exact releases, workloads, grants, namespaces, Catalog activation and ownership epochs, expected prior SecurityEpoch, and returned Runtime security binding",
      "forbidden_authorities": ["Runtime security projection", "signed delegation", "deployment lockfile", "_System_InstalledPack"]
    },
    {
      "id": "runtime-security-projection",
      "author": "Runtime Identity/Security from authoritative non-App inputs and fenced Catalog desired-App-grant commands",
      "authority": "Runtime Identity/Security SecurityEpoch allocator, complete security projection and immutable attestation writer, and serving reader",
      "representation": "complete per-org Profile eligibility, user membership, permission and sharing/group facts, workload/AppInstallation/capability bindings, plus immutable OrgID and SecurityEpoch to projection-digest attestation",
      "forbidden_authorities": ["Catalog-written Runtime security projection", "Catalog-allocated SecurityEpoch", "Runtime-created AppInstallation", "delegation claims", "process configuration"]
    },
    {
      "id": "handler-declaration",
      "author": "L1 publisher",
      "authority": "AppManifest ProvidedCapabilities",
      "representation": "L1 CapabilityID, HandlerRef, and required neutral capabilities",
      "forbidden_authorities": ["endpoint URL", "ProductHooks as durable authority", "Gateway route table"]
    },
    {
      "id": "handler-binding",
      "author": "operator binding validated by Catalog",
      "authority": "Catalog HandlerBinding registry",
      "representation": "installation/release/capability/handler/workload/service digest/ownership epoch binding",
      "forbidden_authorities": ["AppManifest endpoint", "deployment-discovered handler", "Runtime"]
    },
    {
      "id": "service-release",
      "author": "owning service release CI",
      "authority": "artifact registry",
      "representation": "immutable executable image bytes addressed by digest",
      "forbidden_authorities": ["AppReleaseDigest", "AppManifest", "MetadataBundle"]
    },
    {
      "id": "frontend-release",
      "author": "owning frontend release CI",
      "authority": "artifact registry",
      "representation": "immutable frontend asset bytes addressed by digest",
      "forbidden_authorities": ["AppReleaseDigest", "FrontendManifestRef in AppManifest", "_System_App"]
    },
    {
      "id": "frontend-binding",
      "author": "operator binding validated by Catalog",
      "authority": "Catalog frontend binding registry",
      "representation": "AppInstallation and AppRelease to exact compatible FrontendReleaseDigest",
      "forbidden_authorities": ["AppManifest exact asset reference", "_System_App", "deployment BOM"]
    },
    {
      "id": "online-configuration",
      "author": "org administrator through the configuration domain",
      "authority": "configuration domain authority independent of Catalog publication",
      "representation": "domain-owned committed configuration and concurrency or definition version",
      "forbidden_authorities": ["Catalog revision lineage", "Catalog activation pointer", "AppReleaseDigest", "deployment BOM", "Runtime cache"]
    },
    {
      "id": "navigation-configuration",
      "author": "org administrator and L1 defaults",
      "authority": "_System_App metadata read/write path",
      "representation": "mutable UI/navigation configuration",
      "forbidden_authorities": ["product AppID", "AppInstallationID", "AppRelease"]
    },
    {
      "id": "generic-pack-lifecycle",
      "author": "pack author and controlplane lifecycle",
      "authority": "PackManifest and _System_InstalledPack for non-App categories",
      "representation": "generic pack source, install, verify, and convergence facts",
      "forbidden_authorities": ["product App identity", "CRM AppRelease after conversion"]
    }
  ],
  "release_planes": [
    {
      "id": "app-release",
      "identity": "AppID+AppReleaseDigest",
      "content": "immutable L1 App contract and metadata",
      "active_binding": "Catalog AppInstallation"
    },
    {
      "id": "service-release",
      "identity": "immutable image digest",
      "content": "L0 or L1 executable image",
      "active_binding": "Catalog HandlerBinding or deployment service binding"
    },
    {
      "id": "frontend-release",
      "identity": "immutable asset digest",
      "content": "frontend assets",
      "active_binding": "Catalog frontend binding"
    },
    {
      "id": "catalog-publication",
      "identity": "CatalogRevision plus content checksum",
      "content": "release serving selection and derived publication artifacts; not online configuration authority",
      "active_binding": "Catalog activation pointer"
    }
  ],
  "handler_binding": {
    "id_format": "lowercase_uuidv7",
    "natural_key": "OrgID+AppInstallationID+CapabilityID+OwnershipEpoch",
    "states": ["STAGED", "ACTIVE", "DRAINING", "RETIRED", "FAILED"],
    "maximum_active_per_installation_capability": 1,
    "contains_endpoint_url": false,
    "endpoint_owner": "deployment authority",
    "activation_is_fenced_compare_and_swap": true
  },
  "app_installation": {
    "authority": "Catalog",
    "states": ["PREPARING", "ACTIVE", "UPGRADING", "ROLLING_BACK", "REMOVING", "FAILED", "REMOVED"],
    "app_id_immutable_after_creation": true,
    "maximum_live_per_org_app_id": 1,
    "live_states": ["PREPARING", "ACTIVE", "UPGRADING", "ROLLING_BACK", "REMOVING", "FAILED"],
    "removing_completion_releases_live_reservation": true,
    "multiple_live_rows_fail_closed": true,
    "runtime_projection_is_authoritative": false,
    "deployment_lockfile_is_authoritative": false,
    "security_epoch_and_catalog_revision_are_independent": true,
    "publication_sequence": [
      "commit non-active candidate authority, expected projection digest, expected prior SecurityEpoch, and stable command identity without allocating the next epoch",
      "build and verify immutable projections without changing serving pointers",
      "send the stable fenced command; Runtime Identity/Security validates the prior epoch, allocates a strictly newer SecurityEpoch, atomically writes the complete projection and immutable attestation, returns the binding, and Catalog journals the acknowledgement",
      "compare-and-swap CatalogRevision and active AppInstallation only after all acknowledgements and the returned Runtime binding match",
      "ServingAdmission independently validates the active tuple before repository access"
    ]
  },
  "pack_transition": {
    "scope": "crm-app-pack-only",
    "mode": "one-time-direct-conversion",
    "target_app_id": "io.nexuscrm.sfcrm",
    "excluded_categories": ["platform", "tenant", "connector", "integration", "non-app"],
    "issue_tracker_excluded": true,
    "legacy_serving_adapter_permanent": false,
    "dual_read_for_same_capability_allowed": false,
    "legacy_upgrade_writes_after_conversion_allowed": false,
    "inputs": [
      "exact legacy installed-pack row and PackInstallId as incarnation evidence",
      "source kind URI revision manifest and component bytes",
      "desired and applied hashes host requirement digest and runtime declarations",
      "canonical AppPackage AppReleaseDigest publisher attestation and provenance",
      "explicit legacy source to AppID mapping",
      "authorized workloads capability grants and binding inputs"
    ],
    "equivalence_proofs": [
      "legacy source deep verify and desired/applied hash convergence",
      "complete one-to-one component conversion with canonical content digests",
      "materialized metadata and runtime declaration parity",
      "single target owner for dependencies namespaces compatibility and capabilities",
      "publisher trust and AppID reservation",
      "zero identity ownership namespace dependency installation or binding conflicts",
      "Catalog and Runtime projection checksum parity"
    ],
    "deletion_gates": [
      "R1b immutable artifact publication and verification",
      "A1c migration recovery conflict rollback and projection tests",
      "P7b full snapshot parity and P7c/S1 per-closure fallback deletion",
      "finite disposition for every CRM legacy consumer",
      "zero reachable CRM source-checkout installed projection or legacy metadata readers for migrated facts",
      "rollback handler and work retention complete",
      "repository zero-reader guard and passing generic non-App pack tests"
    ]
  },
  "handoffs": [
    {
      "phase": "A1c",
      "inputs": ["A1b ADR and manifest", "canonical fixture packages", "P6 projection API", "A1a legacy facts", "explicit CRM mapping"],
      "outputs": ["non-serving Catalog App authority", "single Catalog AppInstallation writer and lifecycle journal", "Runtime Identity/Security sole SecurityEpoch projection and attestation writer with idempotent Catalog advance-command acknowledgement", "idempotent migration and deletion guards"],
      "forbidden": ["production consumer switch", "second install registry", "Runtime-authored App state", "permanent adapter"]
    },
    {
      "phase": "P7b",
      "inputs": ["canonical AppRelease and MetadataBundle fixtures", "AppInstallation effective facts", "P7a closure"],
      "outputs": ["immutable RuntimeMetadataView", "checksums and complete parity oracle", "non-serving selection guard"],
      "forbidden": ["App semantic reinterpretation", "PackManifest fallback", "serving current pointer", "repository fallback"]
    },
    {
      "phase": "R1b",
      "inputs": ["A1b canonical formats and IDs", "R1a delivery inventory", "L1 CRM source bytes"],
      "outputs": ["digest-addressed AppPackage", "detached attestation and provenance", "reproducible publication evidence", "L2 BOM digest reference"],
      "forbidden": ["Catalog authority", "App semantic reinterpretation", "service or frontend digest in AppRelease", "BOM serving authority"]
    },
    {
      "phase": "P7c/S1",
      "inputs": ["A1c authority and projections", "P7b exact view", "R1b artifact evidence", "P6 TrustedCall", "compatible service and frontend bindings"],
      "outputs": ["one bound AppInstallation and RuntimeMetadataView", "compatible serving receipts", "switched consumers and deleted fallbacks"],
      "forbidden": ["selection before all inputs agree", "mixed revisions", "missing scope fallback", "dual selectable read paths"]
    }
  ],
  "invariants": [
    "one App identity owner and one Catalog write path",
    "AppManifest alone owns App version dependencies namespaces compatibility and capabilities",
    "MetadataBundle alone owns component identity graph policies and content hashes",
    "AppRelease digest transitively covers all behavior-affecting App and L1 metadata bytes",
    "io.nexuscrm.layout-bundle-slot.v1 is the signed App slot declaration; Catalog reserves AppID plus LocalComponentKey, permits only exact historical revision reuse or a head-plus-one prior-head compare-and-swap append, and treats AppRelease omission as no lineage mutation",
    "informational metadata cannot affect behavior",
    "Catalog alone owns AppInstallation and HandlerBinding authority",
    "Runtime Identity/Security alone allocates SecurityEpoch and writes the complete security projection and immutable attestation; Catalog authors desired App grants and records only the returned binding",
    "Catalog permits at most one live AppInstallation per OrgID plus AppID; only REMOVED releases the live reservation and multiple live rows fail closed",
    "AppRelease ServiceRelease FrontendRelease and Catalog publication remain independent; online configuration versions belong to their domains",
    "record-access uses distinct L1 and neutral L0 capabilities",
    "accepted non-empty record-access performs exactly one Runtime data RPC while the empty no-op remains local",
    "generic non-App PackManifest categories do not migrate",
    "the CRM transition has no permanent adapter and no dual read for one capability",
    "P7c/S1 waits for A1c P7b and R1b"
  ],
  "source_anchors": [
    {
      "path": "docs/refactor/serviceification/c0-first-real-crm-consumer.md",
      "anchor": "POST /services/data/:version/ui-api/record-access"
    },
    {
      "path": "docs/refactor/serviceification/app-fact-consumer-inventory.md",
      "anchor": "No current `HandlerBinding` implementation exists."
    },
    {
      "path": "docs/refactor/serviceification/runtime-metadata-closure-p7a.md",
      "anchor": "C0's selected record-access path reads an object schema"
    },
    {
      "path": "nexuscrm-kernel/pkg/schemacatalog/system_tables.json",
      "anchor": "\"tableName\": \"_System_InstalledPack\""
    },
    {
      "path": "nexuscrm-kernel/pkg/schemacatalog/system_tables.json",
      "anchor": "\"tableName\": \"_System_App\""
    },
    {
      "path": "nexuscrm-persistence/runtime_security_repository.go",
      "anchor": "type RuntimeSecurityBinding = securityprojectionv1.Binding"
    },
    {
      "path": "backend/distributions/appsource/source.go",
      "anchor": "SalesforceCRMStandardPackName = \"salesforce-crm-standard\""
    }
  ]
}
