Case file - evidence, counterfactual and decision
flair-case-file/ · 7 files
componentskill: emil-design-eng + design-taste-frontendpublic-recordscomplianceevidenceformsdense
Brief
The prompt that produced this. Re-run it to generate more in the same taste.
- Aesthetic
- institutional utility - DSFR-sober, ruled, evidence-led, dense, trust-first, unornamented
- Reference
- FLAIR case dialog, fiche cas
- Intent
- give an agent everything needed to accept or reject a scored dossier, and make recording that judgement the only way out of the screen
- Guardrails
- always show the evidence and its confidence before the score is justified, state what would lower the score alongside what raised it, require a matricule before a decision can be logged, require a reason for anything other than retainingnever let a decision be recorded anonymously, present an estimated amount as a determined one, hide the existing decision history for the dossier, imply the tool decided
Install
pnpm dlx shadcn@latest add http://localhost:3040/r/flair-case-file.json
Source
Meta block and library type import stripped - this is what pastes cleanly elsewhere.
'use client'
import { useState } from 'react'
import { CaseFile } from './case-file'
import type { ActionControle, Decision, FlairCase } from './lib'
const cas: FlairCase = {
id: 'FLR-2026-00418',
type: 'particulier',
score: 92,
rang: 1,
montant_estime: 148_300,
typologies: ['REVENUS_OCCULTES', 'COMPTE_ETRANGER_NON_DECLARE'],
identite: {
nom: 'Valcour',
prenom: 'Noémie',
departement: '35',
commune: 'Rennes',
categorie: 'Foyer fiscal — salariés',
},
preuves: [
{
typologie: 'REVENUS_OCCULTES',
source: 'DSN',
description:
"Le salaire net social remonté par l'employeur dépasse de 62 400 € les salaires portés sur la déclaration 2042 pour la même année.",
ecart: 62_400,
fiabilite: 0.93,
},
{
typologie: 'COMPTE_ETRANGER_NON_DECLARE',
source: 'CRS',
description:
"Un compte détenu à l'étranger est signalé par échange automatique d'informations, sans déclaration 3916 ni revenus de capitaux correspondants.",
ecart: 41_900,
fiabilite: 0.71,
},
{
typologie: 'REVENUS_OCCULTES',
source: 'FLUX BANCAIRES',
description:
'Encaissements récurrents sans contrepartie déclarée identifiée, concentrés sur le dernier trimestre.',
ecart: 0,
fiabilite: 0.54,
},
],
contrefactuels: [
'Une déclaration 3916 régularisant le compte étranger ferait passer le sous-score « compte étranger » sous le seuil de remontée.',
'Un écart DSN inférieur à 15 % des salaires déclarés ramènerait le score global sous 50.',
],
declare_vs_detecte: [
{ indicateur: 'Salaires annuels', declare: 34_200, detecte: 96_600, source: 'DSN' },
{ indicateur: 'Revenus de capitaux', declare: 0, detecte: 41_900, source: 'CRS' },
{ indicateur: 'Opérations créditrices', declare: 12, detecte: 38, source: 'Flux bancaires' },
],
chronologie: [
{ annee: 2022, evenement: 'Première DSN employeur au-dessus des salaires déclarés.' },
{ annee: 2023, evenement: 'Signalement CRS reçu pour un compte ouvert en 2021.' },
{ annee: 2024, evenement: 'Écart DSN confirmé, dossier remonté au ciblage.' },
],
}
export default function FlairCaseFile() {
const [matricule, setMatricule] = useState('')
const [decisions, setDecisions] = useState<Decision[]>([])
const enregistrer = (entree: { action: ActionControle; motif: string; matricule: string }) => {
setDecisions((prev) => [
// Newest first, matching how the dossier's history reads.
{ uid: `d-${prev.length + 1}`, dateIso: new Date().toISOString(), ...entree },
...prev,
])
}
return (
<main className="min-h-[100dvh] bg-[#F6F6F6] p-4 text-[#161616] sm:p-8">
<CaseFile
cas={cas}
decisionsCas={decisions}
matricule={matricule}
onMatriculeChange={setMatricule}
onDecision={enregistrer}
/>
</main>
)
}