"""Curated V2 overlays for the existing catalog. Does not replace pack rows.

Operational composition (entities, functions, connectors) stays in the DB.
Field flags are applied onto ``entities[].schema.fields[]`` at stamp time.
``entity_contracts`` holds entity-level policy only.

Authoring rules: docs/FEATURE_PACKS_APP_BLOCKS_STARTER.md
"""
from __future__ import annotations

from typing import Any

from src.domain.calculation.mortgage import MORTGAGE_IR
from src.domain.feature_packs.contract import (
    NotificationRoute,
    PackDependencyRef,
    PackEntityContract,
    PackEntityIngestBinding,
    PackEvent,
    PackEventAlias,
    PackEventProducer,
    PackPlannerMeta,
    PackProviderBinding,
    PackSecurity,
    PackWebhookBinding,
    PackWorkflowContract,
    ProvidedCapability,
)

_PRIM = PackDependencyRef
_BIND = PackProviderBinding
_ENT = PackEntityContract
_SEC = PackSecurity
_WF = PackWorkflowContract
_CAP = ProvidedCapability
_WH = PackWebhookBinding
_INGEST = PackEntityIngestBinding

_STRIPE_V1 = (
    "semantic capability = provider-neutral; current implementation = Stripe-only"
)
_PAYMENT_V1 = (
    "semantic capability = provider-neutral; adapters = stripe, paypal; "
    "catalog via payment.catalog.upsert; capture_mode immediate|manual"
)


def _evt(
    event_id: str,
    *,
    producer: PackEventProducer | None = None,
    aliases: list[PackEventAlias] | None = None,
    recipient: NotificationRoute | None = None,
) -> PackEvent:
    return PackEvent(
        id=event_id,
        version=1,
        payload={"record_id": "string", "entity_key": "string"},
        producer=producer,
        aliases=aliases or [],
        recipient=recipient,
    )


def _route_assignment_assignee() -> NotificationRoute:
    return NotificationRoute(strategy="assignment_assignee")


def _route_role_members(role_field: str) -> NotificationRoute:
    return NotificationRoute(strategy="role_members", role_field=role_field)


def _route_field_user_ref(field: str) -> NotificationRoute:
    return NotificationRoute(strategy="field_user_ref", field=field)


def _created(entity: str) -> PackEventProducer:
    return PackEventProducer(kind="record.created", entity=entity)


def _transition(
    entity: str, field: str, *, to: str | None = None
) -> PackEventProducer:
    return PackEventProducer(
        kind="workflow.transition",
        entity=entity,
        field=field,
        to_state=to,
    )


def _field_changed(entity: str, field: str) -> PackEventProducer:
    return PackEventProducer(kind="field.changed", entity=entity, field=field)


def _composition(alias_id: str) -> PackEventAlias:
    return PackEventAlias(id=alias_id, kind="composition")


def _transport(alias_id: str) -> PackEventAlias:
    return PackEventAlias(id=alias_id, kind="transport")


def _plan(*, legacy: bool = False, priority: int = 100) -> PackPlannerMeta:
    if legacy:
        return PackPlannerMeta(
            selectable=False,
            preferred_for_new_projects=False,
            priority=10,
            lifecycle="compatibility",
        )
    return PackPlannerMeta(
        selectable=True,
        preferred_for_new_projects=True,
        priority=priority,
    )


def _sys() -> dict[str, Any]:
    return {
        "system_managed": True,
        "editable": False,
        "public": False,
        "public_create": False,
        "protected": True,
    }


def _pub() -> dict[str, Any]:
    return {"public_create": True, "editable": True, "system_managed": False}


def _prov() -> dict[str, Any]:
    return {
        "system_managed": True,
        "editable": False,
        "public": False,
        "provider": True,
        "protected": True,
    }


CATALOG_OVERLAYS: dict[str, dict[str, Any]] = {
    "contact-capture": {
        "provides": [
            _CAP(id="form.public_submission"),
            _CAP(id="contact.capture"),
        ],
        "optional_requires": [
            _PRIM(
                kind="primitive",
                id="email.send",
                when="notify_email || send_confirmation_email",
            ),
            _PRIM(
                kind="primitive",
                id="crm.contact.upsert",
                when="crm_sync_enabled || crm_status",
            ),
        ],
        "events": [
            _evt(
                "contact.submitted",
                producer=_created("contact_submission"),
                aliases=[
                    _composition("forms.contact.submitted"),
                    _transport("form.submitted"),
                ],
            ),
            _evt("contact.notification_sent"),
            _evt("contact.notification_failed"),
            _evt("contact.crm_synced"),
            _evt("contact.crm_sync_failed"),
        ],
        "entities": [_ENT(entity_key="contact_submission", schema_mode="extensible")],
        "field_policy": {
            "contact_submission": {
                "name": _pub(),
                "email": _pub(),
                "message": _pub(),
                "status": _sys(),
                "notify_error": _sys(),
                "notify_attempts": _sys(),
                "confirmation_sent": _sys(),
                "crm_status": _sys(),
                "crm_sync_error": _sys(),
            }
        },
        "security": _SEC(
            public_actions=["create"],
            ownership_mode="public_create",
            authenticated=False,
        ),
        "provider_bindings": [
            _BIND(
                capability="crm.contact.upsert",
                providers=["hubspot", "salesforce"],
                configuration_required=False,
                missing_configuration_behavior="disabled",
            )
        ],
        "planner": _plan(priority=100),
    },
    "content-ingest": {
        # First consumer of the external.entity_ingest primitive (verified webhook
        # -> bounded payload mapping -> idempotent entity upsert). The primitive
        # itself is provider-agnostic: any future pack (directory listing, jobs
        # board, catalog item, event, knowledge-base article, ...) can declare its
        # own entity_ingest_bindings the same way, independent of this pack.
        "provides": [
            _CAP(id="content.ingest_webhook"),
            _CAP(id="content.item"),
        ],
        "events": [
            _evt("content.ingested", producer=_created("content_item")),
            _evt("content.ingest_rejected"),
        ],
        "entities": [_ENT(entity_key="content_item", schema_mode="extensible")],
        "field_policy": {
            "content_item": {
                "title": _pub(),
                "slug": _pub(),
                "body": _pub(),
                "excerpt": _pub(),
                "cover_image_file_id": _pub(),
                "published_at": _pub(),
                # Identity, provenance, and publication state are stamped by the
                # ingest service itself (source = the webhook's own verified
                # provider; external_id is read for identity matching, not
                # free-written) -- never by the generic bounded-field mapping.
                "external_id": _sys(),
                "source": _sys(),
                "status": _sys(),
                "ingest_error": _sys(),
            }
        },
        "security": _SEC(
            public_actions=["create", "update"],
            ownership_mode="public_create",
            authenticated=False,
        ),
        "webhook_bindings": [
            _WH(
                provider="content_ingest",
                events=[],
                target="pack:content-ingest.ingest",
                forward_path="/api/webhooks/content-ingest",
            ),
        ],
        "entity_ingest_bindings": [
            _INGEST(
                entity_key="content_item",
                webhook_provider="content_ingest",
                identity_fields=["source", "external_id"],
                default_status_field="status",
                default_status_value="draft",
            ),
        ],
        # Selectable but not a default for every new project -- a specific-need
        # addon, not a preferred baseline pack.
        "planner": PackPlannerMeta(
            selectable=True, preferred_for_new_projects=False, priority=80
        ),
    },
    "content-presets": {
        # Pairs with content.collection (and the 8 thin content.* App Blocks
        # built on top of it) so Codegen stops inventing testimonial/FAQ/
        # service/team/location/pricing/gallery/event schemas per project.
        # Public GET (website presentation), staff-authored writes, same
        # posture as product-catalog -- not public_create like contact-capture
        # or content-ingest.
        "provides": [
            _CAP(id="content.preset.testimonial"),
            _CAP(id="content.preset.faq"),
            _CAP(id="content.preset.service"),
            _CAP(id="content.preset.team_member"),
            _CAP(id="content.preset.location"),
            _CAP(id="content.preset.pricing_tier"),
            _CAP(id="content.preset.gallery_item"),
            _CAP(id="content.preset.event"),
        ],
        "entities": [
            _ENT(entity_key="testimonial", schema_mode="extensible"),
            _ENT(entity_key="faq_item", schema_mode="extensible"),
            _ENT(entity_key="service_item", schema_mode="extensible"),
            _ENT(entity_key="team_member", schema_mode="extensible"),
            _ENT(entity_key="business_location", schema_mode="extensible"),
            _ENT(entity_key="pricing_tier", schema_mode="extensible"),
            _ENT(entity_key="gallery_item", schema_mode="extensible"),
            _ENT(entity_key="event_item", schema_mode="extensible"),
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=85),
    },
    "customer-records": {
        "provides": [_CAP(id="crm.customer")],
        "entities": [_ENT(entity_key="customer", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True, ownership_mode="staff_managed", required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=100),
    },
    "organization-records": {
        "provides": [_CAP(id="crm.organization"), _CAP(id="crm.team"), _CAP(id="crm.org_unit")],
        "entities": [
            _ENT(entity_key="organization", schema_mode="extensible"),
            _ENT(entity_key="team", schema_mode="extensible"),
            _ENT(entity_key="org_unit", schema_mode="extensible"),
        ],
        "security": _SEC(
            authenticated=True, ownership_mode="staff_managed", required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=100),
    },
    "quote-lifecycle": {
        "provides": [_CAP(id="crm.quote")],
        "entities": [
            _ENT(entity_key="quote", schema_mode="extensible"),
            _ENT(entity_key="quote_line", schema_mode="extensible"),
        ],
        "security": _SEC(
            authenticated=True, ownership_mode="staff_managed", required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "comment-threads": {
        "provides": [_CAP(id="collaboration.comment")],
        "entities": [_ENT(entity_key="comment", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True, ownership_mode="staff_managed", required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "governance-groups": {
        "provides": [_CAP(id="governance.group")],
        "entities": [_ENT(entity_key="governance_group", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "customer-success-accounts": {
        "provides": [_CAP(id="customer_success.account")],
        "entities": [_ENT(entity_key="customer_success_account", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "contract-management": {
        "provides": [_CAP(id="contract.contract")],
        "entities": [_ENT(entity_key="contract", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "workforce-directory": {
        "provides": [_CAP(id="workforce.worker")],
        "requires": [
            _PRIM(kind="primitive", id="workforce.shift_assign"),
            _PRIM(kind="primitive", id="workforce.shift_release"),
        ],
        "entities": [_ENT(entity_key="worker_record", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "product-catalog": {
        "provides": [_CAP(id="catalog.product")],
        "entities": [
            _ENT(entity_key="catalog_item", schema_mode="extensible"),
            _ENT(entity_key="catalog_variant", schema_mode="extensible"),
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "order-management": {
        "provides": [_CAP(id="orders.order")],
        "entities": [
            _ENT(entity_key="order_record", schema_mode="extensible"),
            _ENT(entity_key="order_line", schema_mode="extensible"),
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "billing-management": {
        "provides": [_CAP(id="billing.invoice")],
        "entities": [
            _ENT(entity_key="invoice_record", schema_mode="extensible"),
            _ENT(entity_key="invoice_line", schema_mode="extensible"),
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "inventory-management": {
        "provides": [_CAP(id="inventory.stock")],
        "requires": [
            _PRIM(kind="primitive", id="inventory.reserve"),
            _PRIM(kind="primitive", id="inventory.release"),
            _PRIM(kind="primitive", id="inventory.commit"),
        ],
        "entities": [_ENT(entity_key="inventory_record", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "membership-management": {
        "provides": [_CAP(id="membership.member")],
        "entities": [_ENT(entity_key="membership_record", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "renewal-operations": {
        "provides": [_CAP(id="record.renewal")],
        "requires": [_PRIM(kind="primitive", id="record.renew")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=85),
        "compatibility": {
            "implementation_notes": (
                "Provider-neutral date renewal for application records. Billing-provider renewal "
                "remains a separate subscription capability."
            )
        },
    },
    "reporting-dashboards": {
        "provides": [_CAP(id="reporting.dashboard")],
        "entities": [_ENT(entity_key="report_definition", schema_mode="extensible")],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin", "super_admin"],
        ),
        "planner": _plan(priority=90),
    },
    "calculator-mortgage": {
        "provides": [_CAP(id="calculator.mortgage")],
        "entities": [],
        "calculators": [MORTGAGE_IR],
        "security": _SEC(public_actions=["calculate"], authenticated=False),
        "planner": _plan(priority=80),
    },
    "lead-lifecycle": {
        "provides": [_CAP(id="crm.lead"), _CAP(id="crm.lead_lifecycle")],
        "requires": [_PRIM(kind="primitive", id="workflow.transition")],
        "events": [
            _evt(
                "lead.created",
                producer=_created("lead"),
                aliases=[_composition("crm.lead.created")],
            ),
            _evt(
                "lead.status_changed",
                producer=_transition("lead", "status"),
                aliases=[_composition("crm.lead.status_changed")],
            ),
            _evt("lead.won", producer=_transition("lead", "status", to="won")),
            _evt("lead.lost", producer=_transition("lead", "status", to="lost")),
        ],
        "entities": [
            _ENT(
                entity_key="lead",
                schema_mode="extensible",
                workflow_configurable=True,
            )
        ],
        "field_policy": {"lead": {"status": _sys()}},
        "workflows": [
            _WF(
                entity_key="lead",
                field="status",
                transitions={
                    "new": ["contacted", "lost"],
                    "contacted": ["qualified", "lost"],
                    "qualified": ["won", "lost"],
                    "won": [],
                    "lost": [],
                },
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin"],
        ),
        "planner": _plan(priority=100),
    },
    "case-lifecycle": {
        "provides": [_CAP(id="case.record"), _CAP(id="case.lifecycle")],
        "requires": [_PRIM(kind="primitive", id="workflow.transition")],
        "events": [
            _evt(
                "case.created",
                producer=_created("case_record"),
                aliases=[_composition("case.management.created")],
            ),
            _evt(
                "case.status_changed",
                producer=_transition("case_record", "status"),
                aliases=[_composition("case.management.status_changed")],
            ),
            _evt(
                "case.resolved",
                producer=_transition("case_record", "status", to="resolved"),
            ),
        ],
        "entities": [
            _ENT(
                entity_key="case_record",
                schema_mode="extensible",
                workflow_configurable=True,
            )
        ],
        "field_policy": {"case_record": {"status": _sys()}},
        "workflows": [
            _WF(
                entity_key="case_record",
                field="status",
                transitions={
                    "open": ["in_review", "closed"],
                    "in_review": ["waiting", "resolved", "closed"],
                    "waiting": ["in_review", "closed"],
                    "resolved": ["closed"],
                    "closed": [],
                },
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin"],
        ),
        "planner": _plan(priority=100),
    },
    "assignment-tracking": {
        # Reusable across verticals by design: the subject is an opaque
        # (subject_entity_key, subject_record_id) pointer, the same pattern Core
        # already uses to reference Cloud records without owning their schema --
        # not a per-pack "assigned_to" field bolted onto lead/case/ticket entities
        # (no cross-pack field-extension mechanism exists to do that safely).
        "provides": [_CAP(id="workflow.assignment"), _CAP(id="assignment.tracking")],
        "requires": [_PRIM(kind="primitive", id="workflow.transition")],
        "events": [
            _evt(
                "assignment.created",
                producer=_created("assignment"),
                aliases=[_composition("workflow.assignment.created")],
                recipient=_route_assignment_assignee(),
            ),
            _evt(
                "assignment.status_changed",
                producer=_transition("assignment", "status"),
                aliases=[_composition("workflow.assignment.status_changed")],
            ),
            _evt(
                "assignment.completed",
                producer=_transition("assignment", "status", to="completed"),
            ),
            _evt(
                "assignment.cancelled",
                producer=_transition("assignment", "status", to="cancelled"),
            ),
        ],
        "entities": [
            _ENT(
                entity_key="assignment",
                schema_mode="extensible",
                workflow_configurable=True,
            )
        ],
        "field_policy": {"assignment": {"status": _sys()}},
        "workflows": [
            _WF(
                entity_key="assignment",
                field="status",
                transitions={
                    "active": ["completed", "cancelled"],
                    "completed": [],
                    "cancelled": [],
                },
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin"],
        ),
        "planner": _plan(priority=100),
    },
    "task-management": {
        # entity_key is "platform_task", deliberately not "task" -- see
        # 137_task_management_pack.py for why reusing the legacy function-
        # library's entity_key would silently leave this pack's access_policy/
        # workflow unapplied on any project where that entity already exists.
        # Assignment composes with assignment-tracking (App Block optional_requires)
        # rather than an assignee field on this entity -- no duplicated behavior.
        "provides": [_CAP(id="task.management"), _CAP(id="task.tracking")],
        "requires": [_PRIM(kind="primitive", id="workflow.transition")],
        "events": [
            _evt(
                "task.created",
                producer=_created("platform_task"),
                aliases=[_composition("task.management.created")],
            ),
            _evt(
                "task.status_changed",
                producer=_transition("platform_task", "status"),
                aliases=[_composition("task.management.status_changed")],
            ),
            _evt(
                "task.completed",
                producer=_transition("platform_task", "status", to="done"),
            ),
        ],
        "entities": [
            _ENT(
                entity_key="platform_task",
                schema_mode="extensible",
                workflow_configurable=True,
            )
        ],
        "field_policy": {"platform_task": {"status": _sys()}},
        "workflows": [
            _WF(
                entity_key="platform_task",
                field="status",
                transitions={
                    "todo": ["in_progress", "done"],
                    "in_progress": ["todo", "done"],
                    "done": ["in_progress"],
                },
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin"],
        ),
        "planner": _plan(priority=100),
    },
    "activity-timeline": {
        # Deliberately: no "events" key (this pack emits nothing -- it is a
        # read model, never a producer), no "workflows" key (append-only log,
        # no status lifecycle), and no primitive requirement beyond the
        # implicit data.entity every pack already has -- the first Phase 11
        # capability that does not need workflow.transition at all.
        "provides": [_CAP(id="activity.timeline"), _CAP(id="activity.tracking")],
        "entities": [
            _ENT(
                entity_key="activity_entry",
                schema_mode="protected",
            )
        ],
        "field_policy": {
            "activity_entry": {
                "event_id": _sys(),
                "canonical_event_id": _sys(),
                "subject_entity_key": _sys(),
                "subject_record_id": _sys(),
                "actor_type": _sys(),
                "actor_id": _sys(),
                "occurred_at": _sys(),
                "category": _sys(),
                "producer_capability": _sys(),
                "payload": _sys(),
            }
        },
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin"],
            public_actions=[],
        ),
        "planner": _plan(priority=100),
    },
    "notifications-in-app": {
        # Same "emits nothing new for the ORIGINATING event, no workflow" shape
        # as activity-timeline (11B3), plus one difference: read_at is
        # deliberately left OUT of field_policy (not _sys()) -- it is the one
        # field the recipient is meant to be able to set, unlike every other
        # field here which is platform-write-only.
        # schema.access_policy is hand-embedded directly on the migration's
        # entity (not derivable from `security` below -- see
        # 140_notifications_in_app_pack.py for why); `security` here still
        # documents intent/ownership_mode for planner/App Block consumers.
        #
        # Phase 11C2 (email channel): optional_requires: email.send, exactly
        # contact-capture's proven pattern -- no provider_bindings entry. Not
        # an oversight: email.send always has a working default delivery path
        # (P2HS-managed, never disclosed to Codegen or the generated app as a
        # specific provider) unless a project configures its own, so there is
        # no per-project "missing connector connection" gate to check for the
        # baseline case -- unlike crm.contact.upsert (hubspot/salesforce),
        # which has no such default and genuinely needs one. Declaring a
        # provider_bindings entry here would invent a connector gate that
        # email.send does not have. Checkout is the pack that lists more than
        # one configuration_required provider; `_missing_prerequisites` ORs
        # providers on one binding (Stripe or PayPal satisfies payment-checkout).
        "provides": [_CAP(id="notifications.in_app"), _CAP(id="notifications.tracking")],
        "optional_requires": [
            _PRIM(kind="primitive", id="email.send", when="email_notifications_enabled"),
        ],
        "events": [
            _evt(
                "notification.email_delivery_attempted",
                producer=_field_changed("platform_notification", "email_status"),
            ),
        ],
        "entities": [
            _ENT(
                entity_key="platform_notification",
                schema_mode="protected",
            )
        ],
        "field_policy": {
            "platform_notification": {
                "recipient_user_id": _sys(),
                "source_event_id": _sys(),
                "canonical_event_id": _sys(),
                "subject_entity_key": _sys(),
                "subject_record_id": _sys(),
                "title": _sys(),
                "message": _sys(),
                "category": _sys(),
                "producer_capability": _sys(),
                "payload": _sys(),
                "email_status": _sys(),
                "email_error": _sys(),
            }
        },
        "security": _SEC(
            authenticated=True,
            ownership_mode="owner_managed",
            public_actions=[],
        ),
        "planner": _plan(priority=100),
    },
    "file-attachments": {
        # Subject-agnostic relation over governed [P] file_id. Platform object
        # storage is a runtime prerequisite, not a Feature Pack primitive and
        # not a provider_binding — generated apps consume files.attachments +
        # generic storage ports, never a vendor bucket/SDK.
        "provides": [_CAP(id="files.attachments"), _CAP(id="file.attachments")],
        "entities": [
            _ENT(
                entity_key="file_attachment",
                schema_mode="protected",
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="mixed",
            required_roles=["admin", "member"],
        ),
        "planner": _plan(priority=100),
    },
    "documents-lifecycle": {
        # Phase 11D5B. No "requires" beyond the implicit data.entity every
        # pack already has -- status is a plain select field, deliberately
        # NOT workflow.transition-governed (see 142_documents_lifecycle_pack.py
        # for why). No "events" key: generic record.created/record.updated
        # (GENERIC_RECORD_EVENT_IDS) already cover the document lifecycle for
        # free -- a branded document.created/etc. PackEvent is deliberately
        # not declared speculatively here; add one only if a real product
        # need for custom-routed document notifications shows up.
        #
        # `security` below is planner/UI-projection metadata ONLY -- it is
        # NEVER translated into schema.access_policy for catalog_v2 packs
        # (confirmed in normalize.py/140's own comments). The actual
        # member-vs-member data isolation boundary is the access_policy
        # hand-embedded directly on the entity in 142's migration, not this
        # block. ownership_mode="owner_managed" here matches that reality
        # (a member owns their own documents; staff can manage all).
        "provides": [_CAP(id="document.record"), _CAP(id="document.lifecycle")],
        "entities": [
            _ENT(
                entity_key="document",
                schema_mode="extensible",
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="owner_managed",
            public_actions=[],
        ),
        "planner": _plan(priority=100),
    },
    "approval-workflow": {
        "provides": [_CAP(id="workflow.approval")],
        "requires": [_PRIM(kind="primitive", id="workflow.transition")],
        "events": [
            _evt(
                "approval.requested",
                producer=_created("approval_request"),
                recipient=_route_role_members("approver_role"),
            ),
            _evt(
                "approval.approved",
                producer=_transition("approval_request", "status", to="approved"),
                recipient=_route_field_user_ref("requested_by"),
            ),
            _evt(
                "approval.rejected",
                producer=_transition("approval_request", "status", to="rejected"),
                recipient=_route_field_user_ref("requested_by"),
            ),
            _evt(
                "approval.escalated",
                producer=_transition("approval_request", "status", to="escalated"),
                recipient=_route_field_user_ref("requested_by"),
            ),
        ],
        "entities": [
            _ENT(
                entity_key="approval_request",
                schema_mode="extensible",
                workflow_configurable=True,
            )
        ],
        "field_policy": {"approval_request": {"status": _sys()}},
        "workflows": [
            _WF(
                entity_key="approval_request",
                field="status",
                transitions={
                    "pending": ["approved", "rejected", "escalated"],
                    "escalated": ["approved", "rejected"],
                    "approved": [],
                    "rejected": [],
                },
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["admin"],
        ),
        "planner": _plan(priority=80),
    },
    "support-inbox": {
        "provides": [_CAP(id="support.ticket"), _CAP(id="support.inbox")],
        "requires": [_PRIM(kind="primitive", id="workflow.transition")],
        "events": [
            _evt("ticket.created", producer=_created("support_ticket")),
            _evt(
                "ticket.assigned",
                producer=_field_changed("support_ticket", "assigned_to"),
            ),
            _evt(
                "ticket.status_changed",
                producer=_transition("support_ticket", "status"),
            ),
            _evt("message.sent", producer=_created("support_message")),
        ],
        "entities": [
            _ENT(
                entity_key="support_ticket",
                schema_mode="extensible",
                workflow_configurable=True,
            ),
            _ENT(entity_key="support_message", schema_mode="extensible"),
        ],
        "field_policy": {"support_ticket": {"status": _sys()}},
        "workflows": [
            _WF(
                entity_key="support_ticket",
                field="status",
                transitions={
                    "open": ["pending", "resolved"],
                    "pending": ["open", "resolved"],
                    "resolved": ["open", "closed"],
                    "closed": [],
                },
            )
        ],
        "security": _SEC(authenticated=True, ownership_mode="mixed"),
        "planner": _plan(priority=80),
    },
    "appointment-booking": {
        "provides": [
            _CAP(id="booking.availability"),
            _CAP(id="booking.appointment"),
            _CAP(id="booking.cancellation"),
        ],
        "requires": [
            _PRIM(kind="primitive", id="booking.reserve"),
            _PRIM(kind="primitive", id="booking.cancel"),
            _PRIM(kind="primitive", id="booking.availability"),
        ],
        "events": [
            _evt("booking.created"),
            _evt("booking.cancelled"),
            _evt("booking.rescheduled"),
        ],
        "provider_bindings": [
            _BIND(
                capability="calendar.sync",
                providers=["google_calendar", "calendly"],
                configuration_required=False,
                missing_configuration_behavior="disabled",
            ),
            _BIND(
                capability="messaging.sms.send",
                providers=["twilio"],
                configuration_required=False,
                missing_configuration_behavior="degraded",
            ),
        ],
        "security": _SEC(authenticated=False, ownership_mode="public_create"),
        "planner": _plan(priority=90),
    },
    "payment-checkout": {
        "provides": [_CAP(id="payments.checkout")],
        "events": [
            _evt("payment.checkout_created"),
            _evt("payment.completed"),
            _evt("payment.failed"),
            _evt("payment.captured"),
            _evt("payment.refunded"),
            _evt("payment.catalog_upserted"),
        ],
        "entities": [
            _ENT(entity_key="product", schema_mode="extensible"),
            _ENT(entity_key="price", schema_mode="protected"),
            _ENT(entity_key="order", schema_mode="protected"),
        ],
        "field_policy": {
            "product": {"stripe_product_id": _prov()},
            "price": {"stripe_price_id": _prov()},
            "order": {
                "source_job_id": _sys(),
                "status": _sys(),
                "kind": _sys(),
                "capture_mode": _sys(),
                "related_order_id": _sys(),
                "provider": _prov(),
                "provider_checkout_id": _prov(),
                "provider_payment_id": _prov(),
                "provider_capture_id": _prov(),
                "provider_customer_id": _prov(),
                "provider_payment_method_id": _prov(),
                "provider_setup_id": _prov(),
                "stripe_checkout_session_id": _prov(),
                "stripe_payment_intent_id": _prov(),
                "amount_total": _sys(),
                "amount_paid": _sys(),
                "amount_refunded": _sys(),
                "paid_at": _sys(),
            },
        },
        "provider_bindings": [
            _BIND(
                capability="payments.checkout",
                providers=["stripe", "paypal"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "webhook_bindings": [
            _WH(
                provider="stripe",
                events=[
                    "checkout.session.completed",
                    "checkout.session.async_payment_succeeded",
                    "checkout.session.async_payment_failed",
                    "checkout.session.expired",
                    "setup_intent.succeeded",
                    "setup_intent.setup_failed",
                    "setup_intent.canceled",
                    "payment_intent.succeeded",
                    "payment_intent.payment_failed",
                    "charge.refunded",
                    "refund.created",
                    "refund.updated",
                ],
                target="pack:payment-checkout.reconcile",
                forward_path="/api/webhooks/checkout-completed",
            ),
            _WH(
                provider="paypal",
                events=[
                    "CHECKOUT.ORDER.APPROVED",
                    "PAYMENT.AUTHORIZATION.CREATED",
                    "PAYMENT.AUTHORIZATION.VOIDED",
                    "PAYMENT.CAPTURE.COMPLETED",
                    "PAYMENT.CAPTURE.DENIED",
                    "PAYMENT.CAPTURE.REFUNDED",
                    "CHECKOUT.ORDER.VOIDED",
                ],
                target="pack:payment-checkout.reconcile",
                forward_path="/api/webhooks/checkout-completed",
            ),
        ],
        "security": _SEC(authenticated=False, ownership_mode="public_create"),
        "planner": _plan(priority=90),
        "compatibility": {"implementation_notes": _PAYMENT_V1},
    },
    "saas-membership": {
        "provides": [
            _CAP(id="payments.subscription"),
            _CAP(id="membership.entitlement"),
        ],
        "events": [
            _evt("subscription.created"),
            _evt("subscription.status_changed"),
            _evt("subscription.canceled"),
        ],
        "entities": [_ENT(entity_key="app_subscription", schema_mode="protected")],
        "field_policy": {
            "app_subscription": {
                "status": _sys(),
                "stripe_customer_id": _prov(),
                "stripe_subscription_id": _prov(),
            }
        },
        "provider_bindings": [
            _BIND(
                capability="payments.subscription",
                providers=["stripe"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="rls",
            rls_required=True,
        ),
        "planner": _plan(priority=90),
        "compatibility": {"implementation_notes": _STRIPE_V1},
    },
    "subscription-operations": {
        "provides": [
            _CAP(id="billing.subscription_operations"),
            _CAP(id="payments.subscription"),
        ],
        "events": [
            _evt("subscription.created"),
            _evt("subscription.status_changed"),
            _evt("subscription.canceled"),
        ],
        "entities": [_ENT(entity_key="subscription_record", schema_mode="protected")],
        "field_policy": {
            "subscription_record": {
                "status": _sys(),
                "provider": _sys(),
                "stripe_customer_id": _prov(),
                "stripe_subscription_id": _prov(),
                "stripe_price_id": _prov(),
                "current_period_start": _prov(),
                "current_period_end": _prov(),
                "cancel_at_period_end": _prov(),
            }
        },
        "provider_bindings": [
            _BIND(
                capability="payments.subscription",
                providers=["stripe"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "webhook_bindings": [
            _WH(
                provider="stripe",
                events=[
                    "customer.subscription.created",
                    "customer.subscription.updated",
                    "customer.subscription.deleted",
                ],
                target="pack:subscription-operations.reconcile",
                forward_path="/api/webhooks/subscriptions",
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="rls",
            rls_required=True,
        ),
        "planner": _plan(priority=90),
        "compatibility": {
            "implementation_notes": (
                "Generated-app subscription records are project-scoped and use "
                "Cloud connector actions; Core workspace billing remains separate."
            )
        },
    },
    "education-learning": {
        "provides": [
            _CAP(id="education.course_delivery"),
            _CAP(id="education.progress"),
            _CAP(id="education.assessment"),
            _CAP(id="education.certificate"),
            _CAP(id="education.attendance"),
        ],
        "provider_bindings": [
            _BIND(
                capability="education.certificate",
                providers=["accredible"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "events": [
            _evt("education.enrollment_created"),
            _evt("education.progress_changed"),
            _evt("education.assessment_submitted"),
            _evt(
                "education.certificate_issued",
                producer=_field_changed("certificate_record", "status"),
            ),
        ],
        "entities": [
            _ENT(entity_key="course", schema_mode="extensible"),
            _ENT(entity_key="lesson", schema_mode="extensible"),
            _ENT(entity_key="enrollment", schema_mode="protected"),
            _ENT(entity_key="lesson_progress", schema_mode="protected"),
            _ENT(entity_key="assessment", schema_mode="extensible"),
            _ENT(entity_key="assessment_attempt", schema_mode="protected"),
            _ENT(entity_key="certificate_record", schema_mode="protected"),
            _ENT(entity_key="attendance_session", schema_mode="protected"),
            _ENT(entity_key="attendance_record", schema_mode="protected"),
        ],
        "field_policy": {
            "enrollment": {"status": _sys()},
            "lesson_progress": {"status": _sys(), "completed_at": _sys()},
            "assessment_attempt": {"status": _sys(), "score": _sys()},
            "certificate_record": {"status": _sys(), "issued_at": _sys()},
            "attendance_session": {"status": _sys()},
            "attendance_record": {"status": _sys(), "recorded_at": _sys()},
        },
        "security": _SEC(
            authenticated=True,
            ownership_mode="rls",
            rls_required=True,
        ),
        "planner": _plan(priority=70),
        "compatibility": {
            "implementation_notes": (
                "Course delivery is record-backed; an issued certificate emits "
                "education.certificate_issued for an installed Accredible event "
                "function. External proctoring remains out of scope."
            )
        },
    },
    "billing-portal": {
        "provides": [_CAP(id="billing.portal")],
        "provider_bindings": [
            _BIND(
                capability="billing.portal",
                providers=["stripe"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "security": _SEC(authenticated=True, ownership_mode="owner_managed"),
        "planner": _plan(priority=80),
        "compatibility": {
            "implementation_notes": (
                "Cloud creates the provider-hosted portal session; generated apps "
                "do not receive payment credentials."
            )
        },
    },
    "tax-calculation": {
        "provides": [_CAP(id="billing.tax_calculation")],
        "provider_bindings": [
            _BIND(
                capability="billing.tax_calculation",
                providers=["stripe"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "security": _SEC(authenticated=True, ownership_mode="staff_managed"),
        "planner": _plan(priority=80),
        "compatibility": {
            "implementation_notes": (
                "Stripe Tax calculates jurisdiction rules; Core/Cloud do not claim "
                "tax registration, filing, or legal authority."
            )
        },
    },
    "crm-pipeline": {
        "provides": [
            _CAP(id="crm.contact"),
            _CAP(id="crm.deal"),
            _CAP(id="crm.pipeline"),
        ],
        "legacy_aggregate": True,
        "events": [
            _evt("crm.contact_created"),
            _evt("crm.deal_created"),
            _evt("crm.deal_stage_changed"),
        ],
        "entities": [
            _ENT(entity_key="crm_contact", schema_mode="extensible"),
            _ENT(entity_key="crm_deal", schema_mode="extensible"),
        ],
        "field_policy": {"crm_deal": {"stage": _sys()}},
        "provider_bindings": [
            _BIND(
                capability="crm.external_sync",
                providers=["hubspot", "salesforce"],
                configuration_required=False,
                missing_configuration_behavior="disabled",
            )
        ],
        "security": _SEC(authenticated=True, ownership_mode="staff_managed"),
        "planner": _plan(legacy=True),
        "compatibility": {"legacy_aggregate": True},
    },
    "client-portal": {
        "provides": [
            _CAP(id="client.account"),
            _CAP(id="client.updates"),
            _CAP(id="billing.customer"),
        ],
        "legacy_aggregate": True,
        "events": [
            _evt("client.account_created"),
            _evt("client.update_published"),
        ],
        "entities": [
            _ENT(entity_key="client_account", schema_mode="extensible"),
            _ENT(entity_key="project_update", schema_mode="extensible"),
        ],
        "field_policy": {"client_account": {"stripe_customer_id": _prov()}},
        "provider_bindings": [
            _BIND(
                capability="payments.provider",
                providers=["stripe"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="rls",
            rls_required=True,
        ),
        "planner": _plan(legacy=True),
        "compatibility": {
            "legacy_aggregate": True,
            "implementation_notes": _STRIPE_V1,
        },
    },
    "ai-knowledge-assistant": {
        "provides": [_CAP(id="ai.assistant"), _CAP(id="ai.chat")],
        "requires": [_PRIM(kind="primitive", id="data.entity")],
        "events": [_evt("assistant.message_created")],
        "provider_bindings": [
            _BIND(
                capability="ai.chat",
                providers=["openai"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "security": _SEC(authenticated=True, ownership_mode="owner_managed"),
        "planner": _plan(priority=70),
    },
    "staff-admin-console": {
        "provides": [_CAP(id="staff.invitation"), _CAP(id="admin.staff_management")],
        "events": [
            _evt("staff.invited"),
            _evt("staff.accepted"),
            _evt("staff.revoked"),
        ],
        "entities": [_ENT(entity_key="staff_invite", schema_mode="extensible")],
        "field_policy": {"staff_invite": {"status": _sys()}},
        "security": _SEC(
            authenticated=True,
            ownership_mode="staff_managed",
            required_roles=["super_admin"],
        ),
        "planner": _plan(priority=60),
    },
    "business-directory": {
        "provides": [_CAP(id="directory.business"), _CAP(id="directory.profile")],
        "events": [_evt("directory.profile_updated")],
        "entities": [_ENT(entity_key="business_profile", schema_mode="extensible")],
        "security": _SEC(authenticated=True, ownership_mode="owner_managed"),
        "planner": _plan(priority=70),
    },
    "connections-networking": {
        "provides": [_CAP(id="directory.connection")],
        "requires": [_PRIM(kind="feature_pack", id="business-directory")],
        "events": [
            _evt("connection.requested"),
            _evt("connection.accepted"),
            _evt("connection.declined"),
        ],
        "security": _SEC(authenticated=True, ownership_mode="owner_managed"),
        "planner": _plan(priority=50),
    },
    "social-feed": {
        "provides": [
            _CAP(id="social.post"),
            _CAP(id="social.reaction"),
            _CAP(id="social.comment"),
        ],
        "requires": [_PRIM(kind="feature_pack", id="business-directory")],
        "events": [
            _evt("post.created"),
            _evt("reaction.created"),
            _evt("comment.created"),
        ],
        "security": _SEC(authenticated=True, ownership_mode="owner_managed"),
        "planner": _plan(priority=50),
    },
    "messaging": {
        "provides": [_CAP(id="communication.messaging")],
        "events": [
            _evt("conversation.created"),
            _evt("message.sent", producer=_created("message")),
            _evt("message.read"),
        ],
        "entities": [
            _ENT(entity_key="conversation_membership", schema_mode="protected"),
            _ENT(entity_key="message", schema_mode="extensible"),
        ],
        "security": _SEC(
            authenticated=True,
            ownership_mode="rls",
            rls_required=True,
        ),
        "planner": _plan(priority=70),
    },
    "classifieds": {
        "provides": [_CAP(id="marketplace.classifieds")],
        "events": [_evt("listing.created"), _evt("listing.updated")],
        "security": _SEC(authenticated=True, ownership_mode="owner_managed"),
        "planner": _plan(priority=50),
    },
    "salesforce-order-sync": {
        "provides": [_CAP(id="crm.external_order_sync")],
        "events": [_evt("order.synced")],
        "provider_bindings": [
            _BIND(
                capability="crm.external_sync",
                providers=["salesforce"],
                configuration_required=True,
                missing_configuration_behavior="degraded",
            )
        ],
        "security": _SEC(authenticated=True, ownership_mode="staff_managed"),
        "planner": _plan(priority=40),
    },
}


def overlay_for(slug: str) -> dict[str, Any]:
    return dict(CATALOG_OVERLAYS.get(slug) or {})
