docs(privacy): document encrypted room chat

This commit is contained in:
Timo
2026-07-26 04:32:06 +02:00
parent 63db02211b
commit 1b97151e69
3 changed files with 64 additions and 6 deletions
+28
View File
@@ -16,6 +16,8 @@ const siteAccessHelpPage = fs.readFileSync(path.join(repoRoot, 'website', 'site-
const websiteBuild = fs.readFileSync(path.join(repoRoot, 'website', 'build.cjs'), 'utf8');
const imprintPage = fs.readFileSync(path.join(repoRoot, 'website', 'imprint.html'), 'utf8');
const germanImprintPage = fs.readFileSync(path.join(repoRoot, 'website', 'impressum-de.html'), 'utf8');
const privacyPage = fs.readFileSync(path.join(repoRoot, 'website', 'privacy.html'), 'utf8');
const germanPrivacyPage = fs.readFileSync(path.join(repoRoot, 'website', 'datenschutz-de.html'), 'utf8');
const alternativesIndex = fs.readFileSync(path.join(repoRoot, 'website', 'alternatives', 'index.html'), 'utf8');
const alternativesCss = fs.readFileSync(path.join(repoRoot, 'website', 'styles', 'alternatives.css'), 'utf8');
const llmsText = fs.readFileSync(path.join(repoRoot, 'website', 'llms.txt'), 'utf8');
@@ -28,6 +30,32 @@ if (mockupStart === -1 || mockupEnd === -1) {
}
const mockup = template.slice(mockupStart, mockupEnd);
const privacyChatContracts = [
[privacyPage, 'English', [
'end-to-end encrypted in the browser extension before transmission',
'256-bit AES-GCM key',
'the relay does not receive the chat secret',
'does not create a server-side chat history',
'maximum of 200 visible message or activity entries',
"browser's notification API"
]],
[germanPrivacyPage, 'German', [
'vor der Übertragung Ende-zu-Ende verschlüsselt',
'256-Bit-Schlüssel für AES-GCM',
'der Relay das Chat-Secret nicht erhält',
'keine serverseitige Chat-Historie',
'höchstens 200 Nachrichten- oder Aktivitätseinträge',
'Benachrichtigungs-API des Browsers'
]]
];
for (const [page, language, statements] of privacyChatContracts) {
for (const statement of statements) {
if (!page.includes(statement)) {
throw new Error(`${language} privacy policy is missing encrypted-chat disclosure: ${statement}`);
}
}
}
const themeSensitiveControls = [
['video selector', /<select[^>]+id="demo-video-select"[^>]+>/],
['sync target', /<div[^>]+class="mock-input"[^>]+title="Choose sync target"[^>]*>/],