Web-Anwendung: Design-Tokens, Texte, Gesundheitsendpunkt

Design-Tokens aus docs/10-design-system.md als CSS-Variablen: Grundpalette,
die sechs Klassifizierungsfarben, Eckenradius durchgehend 2 px, keine Schatten
ausser dem Fokusring. Der Schwärzungsbalken mit dem einmaligen Durchwischen
respektiert prefers-reduced-motion. Vier Tests halten die Tokens gegen das
Dokument.

IBM Plex selbst gehostet als woff2, latin und latin-ext getrennt über
unicode-range, font-display: swap, immutable-Cache.

Alle Oberflächentexte in lib/i18n/de.ts. Ein Test durchsucht app/ und
components/ nach Umlauten im JSX und schlägt fehl, wenn dort deutscher Text
steht. Er hat beim ersten Lauf gleich einen Verstoss gefunden.

/api/health prüft Datenbank, Discord-Gateway und ClamAV. Die Gesamtbewertung
fällt nur auf "down", wenn die Datenbank weg ist: die anderen Dienste haben
eigene Healthchecks im Stack, und ein ausgefallener Virenscanner soll nicht
den Web-Container als tot markieren.

Strikte CSP mit Nonce, kein unsafe-inline für Skripte. Die erste Route liegt
bei 100 kB JavaScript nach Kompression, Budget sind 120 kB.
This commit is contained in:
Harlekin
2026-09-01 00:01:41 +02:00
parent 8f0644e053
commit ade977538d
38 changed files with 1343 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
import { describe, expect, it } from 'vitest'
import { readFileSync, readdirSync, statSync } from 'node:fs'
import { join } from 'node:path'
import { de } from '@/lib/i18n/de'
describe('Sprachkonvention', () => {
it('kennt alle sechs Freigabestufen', () => {
for (let level = 0; level <= 5; level++) {
expect(de.clearance.names[level]).toBeTypeOf('string')
}
expect(de.clearance.names[3]).toBe('Geheim')
})
it('verzichtet auf Ausrufezeichen und Entschuldigungen', () => {
const flat = JSON.stringify(de)
expect(flat).not.toMatch(/!/)
expect(flat.toLowerCase()).not.toMatch(/erfolgreich|entschuldigung/)
})
it('haelt deutsche Oberflaechentexte aus dem JSX heraus', () => {
// Umlaute und Eszett sind der billigste verlaessliche Marker fuer einen
// deutschen Text. Alles Sichtbare gehoert nach lib/i18n/de.ts, siehe CLAUDE.md.
const offenders: string[] = []
const roots = ['app', 'components']
function walk(dir: string) {
for (const name of readdirSync(dir)) {
const path = join(dir, name)
if (statSync(path).isDirectory()) {
walk(path)
continue
}
if (!name.endsWith('.tsx')) continue
const source = readFileSync(path, 'utf8')
for (const [index, line] of source.split('\n').entries()) {
const withoutComments = line.replace(/\/\/.*$/, '').replace(/\/\*.*?\*\//g, '')
if (/[äöüÄÖÜß]/.test(withoutComments)) {
offenders.push(`${path}:${index + 1}`)
}
}
}
}
for (const root of roots) walk(join(process.cwd(), root))
expect(offenders).toEqual([])
})
})