Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 43 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ lib/
audit-engine.ts Règles, scoring et exports JSON/SARIF
audit-history.ts Agrégation confidentielle et comparaison des audits
finding-exceptions.ts Registre local et exports des risques acceptés
trustmap-governance.ts Signature des politiques et bundles d’exceptions chiffrés
collector.ts Découverte, redaction et probe MCP passif
lockfiles.ts Graphes package-lock, pnpm, Yarn, uv et Poetry
kubernetes-admission.ts Génération sûre des politiques d’admission
Expand Down Expand Up @@ -611,6 +612,7 @@ tests/
pdf-report.test.ts Tests du document PDF et de sa pagination
provenance.test.ts Tests ECDSA, digest SLSA et politique Sigstore
supply-chain.test.ts Tests npm, PyPI, OCI, PURL et CycloneDX
trustmap-governance.test.ts Tests des signatures et échanges chiffrés
workspaces.test.ts Tests de découverte et d’isolation des monorepos
rendered-html.test.mjs Tests du rendu de production
public/
Expand Down Expand Up @@ -720,6 +722,38 @@ ordonnés chronologiquement et incluent les variations de score, les écarts
introduits/résolus ainsi que les compteurs agrégés par règle. Aucun nom de
serveur, chemin de configuration, extrait ou secret n’est exporté.

### Signer les politiques CI

Dans **TrustMap CI → Chaîne de confiance**, une équipe peut créer une identité
ECDSA P-256, protégée par une phrase secrète et exportée dans un fichier JSON
chiffré. La clé privée n’est jamais écrite en clair ni envoyée à un service.
Cette identité signe ensuite l’ensemble des profils CI et produit un fichier
`.signed.json`.

Avant de charger les profils, le destinataire doit :

1. obtenir l’empreinte `sha256:…` du signataire par un canal séparé ;
2. charger le fichier de politique ;
3. saisir cette empreinte comme identité approuvée ;
4. laisser MCP TrustMap vérifier la clé, la signature ECDSA et le schéma.

Une signature cryptographiquement valide sans empreinte approuvée reste
explicitement **non fiable** et ne modifie pas les profils actifs. Une politique
altérée, un profil mal formé ou une clé substituée est refusé.

### Échanger les exceptions de manière chiffrée

Dans **TrustMap Enterprise → Échange confidentiel**, le registre d’exceptions
peut être exporté dans un bundle AES-256-GCM. La clé est dérivée localement
d’une phrase secrète avec PBKDF2-HMAC-SHA-256 et un sel aléatoire. Le fichier
chiffré peut être transmis par le canal documentaire habituel, tandis que la
phrase secrète doit être communiquée séparément.

À l’import, l’authenticité du bundle et son schéma sont vérifiés avant la
fusion. Les décisions sont rapprochées par identifiant et une révocation gagne
toujours sur une version active, ce qui évite de réactiver un risque déjà
refusé. Aucune phrase secrète n’est persistée par l’application.

## Limites actuelles

- la découverte doit être lancée explicitement sur chaque poste à inventorier ;
Expand All @@ -745,14 +779,19 @@ serveur, chemin de configuration, extrait ou secret n’est exporté.
OAuth ou système de fichiers ;
- l’historique est limité à 60 synthèses agrégées et ne permet pas de rouvrir
l’inventaire complet d’un audit précédent ;
- le registre d’exceptions est local au navigateur et n’est pas synchronisé
entre les utilisateurs ou les appareils ;
- le registre d’exceptions reste local au navigateur ; sa synchronisation
s’effectue volontairement par échange de bundles chiffrés et n’est pas encore
automatique ;
- l’empreinte d’une identité de signature doit être validée par un canal
distinct ; un fichier auto-signé ne constitue pas à lui seul une identité de
confiance ;
- le catalogue de règles devra évoluer avec les spécifications et pratiques MCP.

## Prochaines étapes possibles

- signature et vérification des fichiers de politique CI exportés ;
- synchronisation chiffrée des exceptions entre membres d’un même espace.
- synchronisation automatique des exceptions avec SSO, journal d’accès et
révocation centralisée ;
- clés de signature matérielles ou gérées par un KMS d’entreprise.

## Contribution

Expand Down
159 changes: 158 additions & 1 deletion app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,143 @@ button.table-row:hover {
margin: -4px 3px 0;
}

.policy-signature-card,
.exception-sync-card {
padding: 25px;
}

.crypto-badge {
background: var(--green-soft);
border: 1px solid #c6e5d6;
border-radius: 999px;
color: var(--green-dark);
flex: 0 0 auto;
font-family: var(--font-geist-mono), monospace;
font-size: 8px;
font-weight: 760;
padding: 6px 9px;
}

.crypto-intro {
color: var(--muted);
font-size: 10px;
line-height: 1.6;
margin: -7px 0 19px;
max-width: 770px;
}

.policy-trust-grid,
.exception-sync-grid {
display: grid;
gap: 14px;
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.policy-trust-grid > section {
background: var(--ivory);
border: 1px solid var(--line);
border-radius: 12px;
display: flex;
flex-direction: column;
gap: 13px;
padding: 18px;
}

.policy-trust-grid label,
.exception-sync-grid > label {
color: var(--muted);
display: flex;
flex-direction: column;
font-size: 9px;
font-weight: 650;
gap: 7px;
}

.policy-trust-grid input:not([type="file"]),
.exception-sync-grid input:not([type="file"]) {
background: var(--paper);
border: 1px solid var(--line-strong);
border-radius: 9px;
font-size: 10px;
min-height: 40px;
padding: 0 11px;
}

.file-field {
background: var(--paper);
border: 1px dashed var(--line-strong);
border-radius: 9px;
cursor: pointer;
padding: 11px;
}

.file-field input {
font-size: 8px;
max-width: 100%;
}

.file-field > span {
color: var(--subtle);
font-size: 8px;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.crypto-actions {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: 9px;
margin-top: auto;
}

.fingerprint {
align-items: center;
background: #eff3ff;
border: 1px solid #d4ddf7;
border-radius: 10px;
display: grid;
gap: 10px;
grid-template-columns: auto minmax(0, 1fr) auto;
margin-top: 14px;
padding: 11px 13px;
}

.fingerprint span {
color: #49619d;
font-size: 8px;
font-weight: 700;
}

.fingerprint code {
color: #1d3f9f;
font-family: var(--font-geist-mono), monospace;
font-size: 8px;
overflow-wrap: anywhere;
}

.crypto-message {
background: var(--green-soft);
border-radius: 8px;
color: var(--green-dark);
font-size: 9px;
line-height: 1.5;
margin: 14px 0 0;
padding: 10px 12px;
}

.exception-sync-grid {
align-items: end;
grid-template-columns: minmax(180px, 0.8fr) minmax(220px, 1fr) auto;
}

.exception-sync-grid .crypto-actions {
flex-wrap: nowrap;
margin: 0;
}

.view-intro {
align-items: flex-end;
display: flex;
Expand Down Expand Up @@ -3561,10 +3698,20 @@ button.table-row:hover {

.module-grid,
.ci-layout,
.enterprise-layout {
.enterprise-layout,
.policy-trust-grid {
grid-template-columns: 1fr;
}

.exception-sync-grid {
align-items: stretch;
grid-template-columns: 1fr;
}

.exception-sync-grid .crypto-actions {
flex-wrap: wrap;
}

.gate-preview {
flex-basis: auto;
width: 100%;
Expand Down Expand Up @@ -3750,6 +3897,16 @@ button.table-row:hover {
grid-template-columns: 1fr;
}

.fingerprint {
align-items: flex-start;
grid-template-columns: 1fr auto;
}

.fingerprint code {
grid-column: 1 / -1;
grid-row: 2;
}

.module-kpis article {
min-height: 94px;
}
Expand Down
1 change: 1 addition & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,7 @@ export default function Home() {
servers={servers}
exceptions={riskExceptions}
onNotify={notify}
onExceptionsImported={setRiskExceptions}
/>
)}
</main>
Expand Down
Loading