Trust layer — invariants
Properties that must hold after every change to lib/trust.php.
Run this before and after touching the calibration constants.
45 passed
policy 2026.09.1
Replay
9/9| ok | cus_fresh rebuilds identically from its ledger | |
| ok | cus_introduced rebuilds identically from its ledger | |
| ok | cus_verified rebuilds identically from its ledger | |
| ok | cus_established rebuilds identically from its ledger | |
| ok | cus_trusted rebuilds identically from its ledger | |
| ok | cus_preferred rebuilds identically from its ledger | |
| ok | cus_risky rebuilds identically from its ledger | |
| ok | a new event immediately changes the derived profile | completed 5 → 6 |
| ok | removing the event restores the original profile |
Monotonicity
5/5| ok | cus_preferred meets no more friction than cus_trusted | INSTANT vs INSTANT |
| ok | cus_trusted meets no more friction than cus_established | INSTANT vs CONFIRM_THEN_PAY |
| ok | cus_established meets no more friction than cus_verified | CONFIRM_THEN_PAY vs DEPOSIT |
| ok | cus_verified meets no more friction than cus_fresh | DEPOSIT vs DEPOSIT |
| ok | the whole ladder is ordered | cus_preferred: INSTANT · cus_trusted: INSTANT · cus_established: CONFIRM_THEN_PAY · cus_verified: DEPOSIT · cus_fresh: DEPOSIT |
Critical events
4/4| ok | the risky customer meets more friction than the trusted one | CONFIRM_THEN_PAY vs INSTANT |
| ok | a no-show five months ago is still flagged | |
| ok | a critical event blocks ESTABLISHED and above | level is VERIFIED on 7 completed |
| ok | a critical event never fully decays, even after 20 years | decay floored at 0.25 |
Explainability
5/5| ok | the decision names its policy version | |
| ok | the decision names the rule that fired | gate.identity-required-for-value |
| ok | the decision carries at least five reasons | 12 reasons |
| ok | the reasons include the matched rule | |
| ok | the reasons include both risk directions |
Provider floor
2/2| ok | a provider can raise the rung | INSTANT → PREPAY |
| ok | a provider cannot lower it below policy | asked for INSTANT, still PREPAY |
Vocabulary
3/3| ok | an unknown event type is rejected, never silently dropped | |
| ok | a known event type is accepted | |
| ok | a rated event without a rating is rejected |
External signals
2/2| ok | a live signal counts toward X | |
| ok | an expired signal does not count |
Scoring
5/5| ok | one perfect booking does not produce a perfect score | score 60 from a single event |
| ok | more evidence moves the score further from the prior | 60 → 91.7 across 40 events |
| ok | identity is capped at 100 | |
| ok | repeating one identity event does not raise the score | |
| ok | a critical failure outweighs a completed booking | 40 vs 10 |
Exposure
3/3| ok | a booking close to the service date is more exposed | 0.799 vs 0.699 |
| ok | perishable capacity is not made cheap by a long lead time | 0.699 → 0.779 when a seat is held |
| ok | a larger transaction is more exposed | 0.286 vs 0.64 |
Gates
7/7| ok | a high-value booking without ID verification is gated | identity 50 → PREPAY |
| ok | a recent critical failure sends a large booking to a human | gate.critical-recent |
| ok | an unknown provider really does score HIGH counter-risk | counter-risk 0.535 (HIGH) |
| ok | the customer is never asked to prepay a high-risk provider | €3,000 to an unvetted provider → MANUAL |
| ok | conflicting protections resolve to manual review, not to either side losing | gate.conflicting-protections |
| ok | a proven provider removes the conflict — no human needed | same basket, proven provider → PREPAY |
| ok | and the unverified customer still pays up front there | gate.identity-required-for-value |
What these protect
- Replay — the score is derived from events, never stored. Recalibration re-reads history rather than rewriting it.
- Monotonicity — behaving well can never cost you. If this breaks, the incentive the whole platform rests on is inverted.
- Explainability — support can answer "why was I asked for a deposit?" years later, from the stored reasons.
- Provider floor — a provider sets its own commercial minimum; trust may raise friction but never sells the provider's risk.
- Gates — customer protection and identity checks fire before the arithmetic, so no score can buy past them.