Advance resource cost evidence contract
This commit is contained in:
parent
d1528944c3
commit
49519a715a
7 changed files with 631 additions and 21 deletions
|
|
@ -227,6 +227,73 @@ class CommitmentCandidate(MonetaryRecord):
|
|||
return money(value, non_negative=True)
|
||||
|
||||
|
||||
class FinancialConstraintSignal(BaseModel):
|
||||
"""Bounded fin-hub authority signal for procurement ranking."""
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
schema_version: Literal["0.1"] = "0.1"
|
||||
record_type: Literal["financial_constraint"] = "financial_constraint"
|
||||
signal_id: str = Field(min_length=1, max_length=256)
|
||||
signal_kind: Literal[
|
||||
"budget_ceiling", "active_commitment", "burn_pressure", "runway_pressure"
|
||||
]
|
||||
classification: Literal[
|
||||
"policy_constraint", "informational_warning", "informational"
|
||||
]
|
||||
domain_slug: str = Field(min_length=1, max_length=64)
|
||||
resource_id: str | None = None
|
||||
service_id: str | None = None
|
||||
environment: str | None = None
|
||||
currency: str
|
||||
period_start: date
|
||||
period_end: date
|
||||
amount: Decimal | None = None
|
||||
metric_value: Decimal | None = None
|
||||
metric_unit: Literal["currency_per_month", "ratio", "months"] | None = None
|
||||
commitment_state: Literal["active"] | None = None
|
||||
source_evidence: list[str] = Field(min_length=1)
|
||||
generated_at: datetime
|
||||
summary: str = Field(min_length=1, max_length=512)
|
||||
|
||||
@field_validator("currency")
|
||||
@classmethod
|
||||
def validate_currency(cls, value: str) -> str:
|
||||
return currency_code(value)
|
||||
|
||||
@field_validator("amount", mode="before")
|
||||
@classmethod
|
||||
def validate_amount(cls, value):
|
||||
return None if value is None else money(value, non_negative=True)
|
||||
|
||||
@field_validator("metric_value", mode="before")
|
||||
@classmethod
|
||||
def validate_metric(cls, value):
|
||||
if value is None:
|
||||
return None
|
||||
normalized = Decimal(str(value))
|
||||
if not normalized.is_finite() or normalized < 0:
|
||||
raise ValueError("metric_value must be a finite non-negative decimal")
|
||||
return normalized
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_signal(self):
|
||||
if self.period_end < self.period_start:
|
||||
raise ValueError("period_end cannot precede period_start")
|
||||
if self.signal_kind in {"budget_ceiling", "active_commitment"}:
|
||||
if self.amount is None:
|
||||
raise ValueError(f"{self.signal_kind} requires amount")
|
||||
if self.classification != "policy_constraint":
|
||||
raise ValueError(f"{self.signal_kind} must be a policy_constraint")
|
||||
if self.signal_kind == "active_commitment" and self.commitment_state != "active":
|
||||
raise ValueError("active_commitment requires commitment_state=active")
|
||||
if self.signal_kind == "burn_pressure" and self.metric_unit != "ratio":
|
||||
raise ValueError("burn_pressure requires a ratio metric")
|
||||
if self.signal_kind == "runway_pressure" and self.metric_unit != "months":
|
||||
raise ValueError("runway_pressure requires a months metric")
|
||||
return self
|
||||
|
||||
|
||||
PlanningEvidence = Annotated[
|
||||
ForecastEvidence
|
||||
| UsageObservation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue