Files
crushdb/backend/static/index.html
T
jhkaktus 863cd1fd3a feat: first-time setup screen for creating a new passphrase
UX fix from user feedback: previously the app only showed an "Entsperren"
form, leaving first-time users without any passphrase confused. The page
now loads with two distinct pre-screens decided by an initial API call:

- empty DB -> "Willkommen" setup form: new passphrase, typed twice,
  minimum 8 characters, with no-reset warning
- existing ciphertext records -> unlock form as before

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-11 00:30:51 +02:00

114 lines
3.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>crushdb</title>
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<h1>crushdb</h1>
<p class="tagline">Verschlüsselte Datensätze zwischen zwei Personen</p>
<section id="flash" class="flash" aria-live="polite"></section>
<!-- First visit: NO records exist yet → user chooses a new passphrase -->
<section id="setup" hidden>
<form id="setup-form" autocomplete="off">
<h2>Willkommen bei crushdb!</h2>
<p class="intro">
Du benutzt crushdb zum ersten Mal. Wähle jetzt eine Passphrase –
sie ist das Master-Passwort für alle deine Daten. Es gibt keine
Zurücksetzung, speichere sie sicher!
</p>
<label>Neue Passphrase
<input type="password" id="setup-pass1" autocomplete="new-password"
required minlength="8" placeholder="mindestens 8 Zeichen" />
</label>
<label>Passphrase wiederholen
<input type="password" id="setup-pass2" autocomplete="new-password"
required placeholder="gleiche Passphrase nochmal" />
</label>
<button type="submit" id="setup-btn">Konto einrichten →</button>
<p id="setup-progress" class="hint" hidden>Schlüssel wird abgeleitet …</p>
<p class="hint">
Wichtig: Die Passphrase wird <strong>nicht am Server gespeichert</strong>.
Sie bleibt nur in deinem Browser-Arbeitsspeicher. Wer sie vergisst,
verliert Zugriff auf alle Daten (absichtlich so).
</p>
</form>
</section>
<!-- Returning user: records exist but are undecryptable → enter passphrase -->
<section id="unlock">
<form id="unlock-form" autocomplete="off">
<h2>Entsperren</h2>
<p class="intro">
Du hast bereits verschlüsselte Datensätze hinterlegt.
Gib deine Passphrase ein, um sie zu lesen.
</p>
<label>Passphrase
<input type="password" id="passphrase" autocomplete="current-password"
required placeholder="deine Passphrase …" />
</label>
<button type="submit" id="unlock-btn">Entsperren</button>
<p id="unlock-progress" class="hint" hidden>Schlüssel wird abgeleitet …</p>
<p class="hint">
Die Passphrase verlässt niemals deinen Browser. Sie wird per
Argon2id lokal abgeleitet und nur im Arbeitsspeicher gehalten.
</p>
</form>
</section>
<!-- main app, hidden until unlocked -->
<section id="app" hidden>
<div class="toolbar">
<button id="new-btn" type="button">+ Neuer Datensatz</button>
<button id="lock-btn" type="button">Sperren</button>
</div>
<table id="records">
<thead>
<tr>
<th>Person A</th>
<th>Person B</th>
<th>Start</th>
<th>Ende</th>
<th>Aktion</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</section>
<!-- create/edit modal -->
<div id="editor-backdrop" hidden>
<form id="editor" autocomplete="off">
<h2 id="editor-title">Neuer Datensatz</h2>
<label>Person A
<input id="f-persona" type="text" required maxlength="120" />
</label>
<label>Person B
<input id="f-personb" type="text" required maxlength="120" />
</label>
<label>Start (optional)
<input id="f-tsstart" type="datetime-local" />
</label>
<label>Ende (optional)
<input id="f-tsend" type="datetime-local" />
</label>
<label>Aktion
<input id="f-action" type="text" required maxlength="500" />
</label>
<div class="actions">
<button type="submit">Speichern</button>
<button type="button" id="editor-cancel">Abbrechen</button>
</div>
</form>
</div>
<script type="module" src="/static/ui.js"></script>
</body>
</html>