"""Consumption contract for the Certification -> Capability mapping.

OWNERSHIP BOUNDARY (hard): the Capability Registry, CapabilityDefinition and the
Certification->Capability / Feature->Capability mapping RULES live in the Compliance
Execution domain. This Reasoning layer defines ONLY the shape it consumes and never
ships mapping DATA in product code — tests inject mocks, so the real table can only
ever live in Execution.

Execution will eventually provide CapabilityRegistry / CapabilityMapping /
CapabilityDefinition; Reasoning consumes exactly `OperationalCapabilityCandidate`
{capability_id, source, confidence, verification_status} (see schemas.py) and the
minimal mapping SHAPE below — nothing more.

Python 3.9 compatible (no `|` unions).
"""

from __future__ import annotations

from typing import Dict, List

from pydantic import BaseModel, Field

from compliance.reasoning.enums import Confidence


class CapabilityMappingEntry(BaseModel):
    """One mapping rule SHAPE: a certification implies candidate capabilities.

    Contract type only. The actual table (which capabilities ISO27001 implies) is
    Execution's DATA and MUST NOT be hard-coded here or anywhere in product code.
    """

    capability_ids: List[str] = Field(default_factory=list)
    confidence: Confidence = Confidence.MEDIUM


# certification_id -> entry. Injected at call time; product code holds NO entries.
CertificationCapabilityMap = Dict[str, CapabilityMappingEntry]

# Intentionally empty: without an injected mapping there are zero inferred
# candidates. This is the architectural guarantee that the registry lives only in
# the Compliance Execution domain.
EMPTY_MAPPING: CertificationCapabilityMap = {}
