FORBIDDEN={'full_address','internal_note','raw_carrier_payload','full_phone','full_email'}

def decide(c):
    fields=set(c.get('fields',[]))
    if fields & FORBIDDEN: return 'BLOCKED'
    if not c.get('recipient_matches',False) or not c.get('destination_masked',False): return 'BLOCKED'
    if not c.get('purpose') or not c.get('basis_ref') or not c.get('redaction_version') or not c.get('template_version') or not c.get('retention'): return 'HOLD'
    if c.get('delivery_event'): return 'DELIVERED'
    if c.get('failure')=='TRANSIENT_PROVIDER':
        if c.get('idempotency_key') and c.get('retry_count',99)<c.get('retry_max',0): return 'RETRY_ALLOWED'
        return 'FAILED'
    if c.get('failure') not in (None,'','NONE'): return 'FAILED'
    if c.get('provider_accepted'): return 'PROVIDER_ACCEPTED'
    return 'QUEUED'

def invariants(c):
    got=decide(c); fields=set(c.get('fields',[]))
    return [
      not (got=='DELIVERED' and not c.get('delivery_event')),
      not (got in ('QUEUED','PROVIDER_ACCEPTED','DELIVERED','RETRY_ALLOWED') and bool(fields & FORBIDDEN)),
      not (got in ('QUEUED','PROVIDER_ACCEPTED','DELIVERED','RETRY_ALLOWED') and (not c.get('destination_masked') or not c.get('recipient_matches'))),
      not (got in ('QUEUED','PROVIDER_ACCEPTED','DELIVERED','RETRY_ALLOWED') and (not c.get('basis_ref') or not c.get('template_version') or not c.get('redaction_version') or not c.get('retention'))),
      not (c.get('channel') and c.get('baseline_channel') and c.get('channel')!=c.get('baseline_channel') and not c.get('channel_evidence_recomputed',False))
    ]

def check_case(c):
    got=decide(c); return got, got==c['expected']
