Trust lifecycle
Trust is a composition, not a new model. The TrustEngine folds three operational assessments into one weighted, explainable score.
Trust lifecycle
The TrustEngine produces one TrustAssessment per operation by aggregating the three commercial assessments, Compliance, Risk and Quality. It never duplicates their logic: it either consumes assessments the caller supplies, or derives them from an EvidenceEnvelope by delegating to the existing engines. No model calls, no network.
flowchart TD
E["EvidenceEnvelope (dict)"] --> TE["TrustEngine.assess(envelope)"]
TE --> C{"compliance supplied?"}
C -->|no| CA["ComplianceEngine.assess(env, pack_id)"]
C -->|yes| CU["use supplied"]
TE --> R{"risk supplied?"}
R -->|no| RA["RiskEngine.assess(env)"]
R -->|yes| RU["use supplied"]
TE --> Q{"quality supplied?"}
Q -->|no| QA["QualityEngine.assess(env)"]
Q -->|yes| QU["use supplied"]
CA --> S["scoring.build_signals / build_findings / aggregate"]
CU --> S
RA --> S
RU --> S
QA --> S
QU --> S
S --> O["TrustAssessment
trust_score 0-100 · trust_level · summaries · signals · findings"]
Trust lifecycle, aggregate compliance + risk + quality; derive missing parts from the envelope. Source: trust/engine.py.Scoring model
The trust score is a weighted sum over the three components, out of 100. The exact weights come from trust/scoring.aggregate:
| Component | Weight | Basis |
|---|---|---|
| Compliance coverage | 30 | control coverage ratio from the compliance pack |
| Risk (inverse) | 35 | lower operational risk → higher contribution |
| Quality level | 35 | operational quality band |
The score maps to an ordered trust_level: trusted ≥ 80, acceptable ≥ 60, caution ≥ 40, else untrusted. When risk or quality cannot be determined, the level is unknown rather than a fabricated number, a first-class "we don't know" state.
Determinism & linkage
The sub-engines mint fresh ids internally, but the embedded compliance_summary / risk_summary / quality_summary deliberately omit those sub-ids and timestamps. That keeps the trust output deterministic for a given envelope even though the components are not. Linkage ids (evidence_id, receipt_id, provenance_id) are picked from whichever source carries them.
The assessment also reports a confidence of full (all three components present) or partial, plus a per-component breakdown. See the trust object schema.
disclaimer field is part of the model: this is an automated, aggregated signal derived from operational evidence, not a guarantee, certification, or advice. The disclaimer travels with every serialized assessment.What consumes trust
The TrustAssessment feeds the identity layer (latest trust posture), the passport, and via the trust profile the reputation. The POST /api/v1/trust/assess endpoint is a thin transport that calls _trust_engine.assess(envelope=body.evidence) and returns the full export.