SIMA GUARDRAILS
Source: docs/architecture/SIMA_GUARDRAILS.md
# SIMA Guardrails
This document defines the contractual guarantees and expansion guardrails for the SIMA (Special Import Measures Act) risk assessment system.
## SIMA Invariants Checklist
These invariants must NEVER be violated, regardless of internal refactors or rule expansions.
| ID | Invariant | Description |
|----|-----------|-------------|
| **INV-01** | Country Gating | If `status = AT_RISK`, then `country ∈ measure.origins` |
| **INV-02** | HS Eligibility | SKU enters SIMA eval only if `hs ∈ measure.codes ∪ measure.prefixes` |
| **INV-03** | Material Confirmation | If `AT_RISK`, material must satisfy measure's definition |
| **INV-04** | NEEDS_REVIEW Is Monitored | SHOULD be < 10% of total exposures; sustained >10% is a data-quality alert (e.g., HS confidence gating) |
| **INV-05** | No Hidden Attributes | SIMA logic branches only on HS, country, material |
| **INV-06** | Evasion Is Explicit | Any evasion record has original_hs, corrected_hs, measure_code, notes |
| **INV-07** | Version Determinism | Every record has `sima_config_version` populated |
| **INV-08** | Replay Safety | Same SKU + attrs + config → same result (deterministic) |
| **INV-09** | Fail Fast | Invalid config crashes startup, never silently degrades |
| **INV-10** | Status Totals | `AT_RISK + CLEARED + FALSE_POSITIVE + NEEDS_REVIEW = total` |
| **INV-11** | Zero Surprise Rule | No AT_RISK without HS + country + material rationale in notes |
**Note:** INV-04 is a soft guardrail, not a hard invariant. If HS-confidence gating is enabled, temporary spikes in NEEDS_REVIEW are expected and should trigger review, not a hard failure.
## Why These New Files Don't Change SIMA
The `sku_attributes` table and attribute strategy documentation were added for:
1. **Future use cases** (landed cost, safety compliance) - not SIMA
2. **Raw attribute preservation** for audit trail
3. **Source-agnostic attribute storage**
**SIMA decisions continue to use only:**
- HS code (from catalog feed + validated/corrected)
- Country of origin (normalized ISO code)
- Material type (normalized category)
The `sku_attributes` table is a **storage layer**, not a decision layer.
## INV-05 Enforcement: No Hidden Attributes
INV-05 ("No Hidden Attributes") ensures SIMA logic only branches on the three permitted attributes.
### Enforcement Mechanisms
1. **Boundary comments** in `packages/modules/trade/src/sima.ts`:
- Entry point: `validateSIMAExposure()`
- Decision point: `validateAttributesClearance()`
Both marked with "DO NOT EXPAND" warnings.
2. **Function signature constraints**:
- `validateSIMAExposure()` accepts only: sku, name, hsCode, correctedHsCode, country, material, monthlyVolume
- `validateAttributesClearance()` accepts only: sku, hsCode, correctedHsCode, country, material, measureCode, measureName, monthlyVolume
3. **CI grep check** (recommended addition):
```bash
# Fail if weight, dimensions, certifications appear in SIMA decision paths
grep -r "weight\|dimension\|certification" packages/modules/trade/src/*.ts | grep -v "test\|comment"
```
## What NOT To Do (Expansion Guardrails)
| Action | Status | Reason |
|--------|--------|--------|
| Add weight/dimensions into SIMA logic | FORBIDDEN | Not required by any CBSA measure |
| Generalize SIMA into a "risk engine" | FORBIDDEN | SIMA is specific regulatory program |
| Normalize all attributes up front | FORBIDDEN | Over-engineering; violates separation |
| Auto-learn SIMA rules | FORBIDDEN | Rules are legal definitions, not ML |
| Use sku_attributes data in SIMA decisions | FORBIDDEN | Violates INV-05 |
## Version Determinism Policy
### New Records
- MUST have `sima_config_version` populated
- Service fails hard at startup if config version is undefined
### Legacy Records
- Nullable `sima_config_version` for existing data
- Never reprocessed without version assignment
### Config Version Requirements
- Config file must have `_meta.version` (semver format)
- Service crashes on startup if missing
- Every decision traceable to specific config version
## Decision Audit Requirements
Every `sima_outcomes` record must include:
1. **HS code** - Current and corrected (if applicable)
2. **Country of origin** - ISO 2-letter code
3. **Material type** - Normalized category
4. **Status** - AT_RISK, CLEARED, FALSE_POSITIVE, NEEDS_REVIEW
5. **Evidence** - Human-readable rationale (JSONB); `reason_code` stores the structured enum
6. **Config version** - Which rules produced this decision
For the measure-covered subset, every `sima_exposures` record must also include:
1. **Measure code** - Which SIMA measure applies
2. **Risk values** - Original and validated risk
3. **Notes** - Human-readable rationale
## Ingestion Replay Tracking
Every request is recorded in `app.sku_ingestions` with:
- `payload_hash` for exact-repeat detection
- `inputs_hash` for outcome-input repeats
- Outcome snapshot + config version
This supports INV-08 (Replay Safety) and enables QBR-level duplicate analysis.
## Contract Tests Location
Invariant tests live under `packages/modules/trade/src/__tests__/`:
- `sima-outcome.test.ts`
- `sima-invariants.test.ts`
## References
- CBSA SIMA Measures: https://www.cbsa-asfc.gc.ca/sima-lmsi/mif-mev/menu-eng.html
- Config file: `packages/modules/trade/src/config/sima-measures.ts`
- Attribute strategy: `docs/architecture/attribute-strategy.md`