feat(capability): Master Capability Registry v0 (Phase 2C, Compliance Execution domain)
Third instance of the identity-machine pattern (after Master Controls and Master Obligations). New compliance/capability/ package: MasterCapability with stable MCAP ids, CapabilityCandidate minting, seven typed relation types, a VERSIONED derivation policy, and identity lifecycle (merge/split/deprecate/redirect with provenance). Stored: identities, sources, relationship types, policy versions, lifecycle events, provenance. Derived (never stored): confidence/status via evaluate_relation under a policy version. Hard rule (structurally guarded): a certification alone can never yield CONFIRMED — only CONFIRMS + concrete artifact (or expert) does. Built from the Reasoning session per user directive but this IS the Compliance Execution model (Execution owns Capability) — handed off via the board. Metadata-first: CapabilityRelation is registry metadata, NOT a new meta-model class (freeze v1.0 untouched). No Company-Gap, no real ISO/cert mappings, no UI/RAG, no generic canonicalization engine. 11 tests; mypy --strict clean; LOC ok. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
"""Master Capability Registry v0 — Compliance Execution domain (Phase 2C).
|
||||
|
||||
Built from the Reasoning session per user directive, but this IS the Compliance
|
||||
Execution model (Execution owns Capability). Third real instance of the
|
||||
identity-machine pattern (after Master Controls and Master Obligations):
|
||||
|
||||
Candidate -> Normalization -> Dedup -> Stable Identity (MCAP) -> Typed Relations
|
||||
|
||||
KEY SENTENCE (stored vs derived):
|
||||
STORED : identities, sources, relationship types, policy versions, lifecycle
|
||||
events, provenance.
|
||||
DERIVED : confidence, coverage and gap statements — computed on demand, NEVER
|
||||
stored (see policy.py / engine.evaluate_relation).
|
||||
|
||||
These are APPLICATION/registry types, NOT compliance-meta-model classes. In
|
||||
particular `CapabilityRelation` is relation METADATA inside the registry — it does
|
||||
NOT introduce a new meta-model class. Whether a reified relation must enter the
|
||||
frozen meta-model is a Meta-Model-Owner decision (architecture freeze v1.0),
|
||||
deferred until a demonstrable failure case exists.
|
||||
|
||||
Self-contained (no Reasoning import — Reasoning consumes Capability, not the other
|
||||
way round). Python 3.9 compatible (no `|` unions).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class Confidence(str, Enum):
|
||||
HIGH = "high"
|
||||
MEDIUM = "medium"
|
||||
LOW = "low"
|
||||
|
||||
|
||||
class AssertionStatus(str, Enum):
|
||||
"""How well-established a capability claim is. A numeric score is presentation;
|
||||
THIS type is the truth (derived from relationship type + evidence + policy)."""
|
||||
|
||||
DECLARED = "declared"
|
||||
INFERRED = "inferred"
|
||||
CONFIRMED = "confirmed"
|
||||
UNKNOWN = "unknown"
|
||||
|
||||
|
||||
class RelationType(str, Enum):
|
||||
EQUIVALENT = "equivalent"
|
||||
SUPPORTS = "supports"
|
||||
REQUIRES = "requires"
|
||||
CONFIRMS = "confirms"
|
||||
BROADER_THAN = "broader_than"
|
||||
NARROWER_THAN = "narrower_than"
|
||||
RELATED_TO = "related_to"
|
||||
|
||||
|
||||
class EvidenceKind(str, Enum):
|
||||
CERTIFICATION = "certification" # a held certificate — a CLAIM, never proof
|
||||
ARTIFACT = "artifact" # concrete doc/config/test/log
|
||||
EXPERT = "expert" # human expert assertion
|
||||
NONE = "none"
|
||||
|
||||
|
||||
class LifecycleState(str, Enum):
|
||||
ACTIVE = "active"
|
||||
DEPRECATED = "deprecated"
|
||||
|
||||
|
||||
class LifecycleEventType(str, Enum):
|
||||
MERGE = "merge"
|
||||
SPLIT = "split"
|
||||
DEPRECATE = "deprecate"
|
||||
REDIRECT = "redirect"
|
||||
|
||||
|
||||
class Provenance(BaseModel):
|
||||
"""Every CURATED atom carries its own provenance (who / when / on what basis)."""
|
||||
|
||||
author: str = ""
|
||||
asserted_at: Optional[str] = None # ISO timestamp passed in; never generated here
|
||||
basis: str = ""
|
||||
|
||||
|
||||
# ── stored: identity ──────────────────────────────────────────────────────
|
||||
class MasterCapability(BaseModel):
|
||||
capability_id: str # stable MCAP-xxxxx
|
||||
name: str = ""
|
||||
definition: str = ""
|
||||
category: str = ""
|
||||
domains: List[str] = Field(default_factory=list)
|
||||
typical_evidence: List[str] = Field(default_factory=list)
|
||||
version: int = 1
|
||||
state: LifecycleState = LifecycleState.ACTIVE
|
||||
redirect_to: Optional[str] = None # set on merge/deprecate
|
||||
provenance: Provenance = Field(default_factory=Provenance)
|
||||
|
||||
|
||||
class CapabilityCandidate(BaseModel):
|
||||
raw_term: str # e.g. "Patch Management"
|
||||
source: str = "" # e.g. "CRA:Annex I (2)(d)"
|
||||
normalized: str = ""
|
||||
|
||||
|
||||
# ── stored: typed relation metadata (NOT a meta-model class) ──────────────
|
||||
class CapabilityRelation(BaseModel):
|
||||
relation_id: str
|
||||
source: str # external term/obligation/certification id, e.g. "certification:ISO27001"
|
||||
target_capability_id: str # MCAP-...
|
||||
relationship_type: RelationType
|
||||
evidence_kind: EvidenceKind = EvidenceKind.NONE
|
||||
provenance: Provenance = Field(default_factory=Provenance)
|
||||
|
||||
|
||||
# ── stored: versioned derivation policy ───────────────────────────────────
|
||||
class PolicyRule(BaseModel):
|
||||
relationship_type: RelationType
|
||||
evidence_kind: EvidenceKind
|
||||
status: AssertionStatus
|
||||
confidence: Confidence
|
||||
|
||||
|
||||
class PolicyVersion(BaseModel):
|
||||
"""A versioned derivation policy. `policy_version` is recorded with every
|
||||
assessment so "why did you say X last year" is answerable with the policy
|
||||
as-of-then. Without this, `derived` and `auditable/reproducible` contradict."""
|
||||
|
||||
policy_version: str
|
||||
description: str = ""
|
||||
rules: List[PolicyRule] = Field(default_factory=list)
|
||||
|
||||
|
||||
# ── stored: identity lifecycle ────────────────────────────────────────────
|
||||
class IdentityLifecycleEvent(BaseModel):
|
||||
event_id: str
|
||||
event_type: LifecycleEventType
|
||||
from_ids: List[str] = Field(default_factory=list)
|
||||
to_ids: List[str] = Field(default_factory=list)
|
||||
at: Optional[str] = None
|
||||
provenance: Provenance = Field(default_factory=Provenance)
|
||||
|
||||
|
||||
# ── DERIVED — never stored ────────────────────────────────────────────────
|
||||
class DerivedAssessment(BaseModel):
|
||||
target_capability_id: str
|
||||
status: AssertionStatus
|
||||
confidence: Confidence
|
||||
policy_version: str
|
||||
explanation: str = ""
|
||||
Reference in New Issue
Block a user