Stand 16:29: vollständig (Teil 1 bis 7) · 26.10. Bewertung Runde 2: automatische Übersetzung der Anzeigen (en/tr) als Teil von 2a (1.18, H143, H144, Paket 2a.11a) · 26.10. ergänzt: Einhängepunkt Vorab-Fragen im Bewerben-Fenster (B1), Quelle je Bewerbung (B4), Mehrfach-Beschäftigungsart und Befristung im Stellenformular (B5, B2), Mail-Dienst aus 1a · 26.10. Sicherheit: zweiter Faktor auch als E-Mail-Code (1.2, 1.9 Nr. 4, H137, H138, Mail A12), Mail bei Anmeldung von neuem Gerät mit „Das war ich nicht“ (1.2, H139, Mail A13), Kennwort-Regeln mit Maß und wachsende Wartezeit statt Kontosperre (1.1 Nr. 3, H55, H140), erneute Kennworteingabe vor heiklen Aktionen (H141), Sicherheitsprotokollanmeldungen(Teil 3); Prüfliste in_· 26.10. Nomad: Firmen legen Mitarbeiter-Konten selbst an (1.14 Nr. 2, Rollen Admin und Recruiter) · 22.10. nachgeprüft: B-Fundstellen am Entwurf, Usability 3.x/A–D und Änderungsliste eingearbeitet, Mails gegen T 6.2–6.4planung/ sicherheit. md
Stand 22.10.2026, Nomad. Grundlage: PLAN-BACKEND Fassung 5 (Zeitplan 2a, Bewerber: Erste Bewerbung, Ein Konto je Person, Status, Bewerberbereich, Benachrichtigungen; Arbeitgeber; Menüs; Listen; Auswählen; Zustände; Laden und Rückmeldung; Lebensläufe; Sicherheit und Datenschutz), USABILITY-KONZEPT (3.1 bis 3.12, A bis D), TEXTE-UND-MAILS 1.1, 1.4, 1.6, 1.7, 1.8, 2, 3.1 bis 3.3, 4.1 bis 4.4, 5.1 bis 5.5, 6.0 bis 6.4, 7.1, 7.2, 7.4, FUNKTIONEN-CHECK, AENDERUNGSLISTE-GESAMTKONZEPT, Entwurf B (anmelden.html, mein-bereich.html, firmen-bereich.html, stelle.html, assets/style.css, assets/app.js), Karten 1a und 1b.
Umfang 2a laut Zeitplan: Anmelden und Konten mit zweitem Faktor, Einwilligungen, Mindestbewerbung mit Datei (Bewerben-Fenster über der Stelle), Bewerberbereich (Bewerbungen, Reiter Lebenslauf schlank: Persönliches und Datei, Postfach, Merkliste und Job-Alarme aus dem Konto), Benachrichtigungen, Einladung mit Kalender-Datei · Firmen-Registrierung, Firmenprofil bearbeiten (Logo, Text, Ansprechperson), Stellen (Formular mit Vorschau, Entwurf, bearbeiten, kopieren, beenden, verlängern), Bewerbungen mit Notizen, Postfach der Firma, Team mit Einladung und Rollen, Live-Aktualisierung (Abfrage alle 60 s, 1.16; Server-Sent Events erst 2b.9) · automatische Übersetzung der Stellenanzeigen nach Englisch und Türkisch im Hintergrund (1.18; Kundenliste „Zum Livegang“, Plan Sprachen). Nicht in 2a (nur als Abgrenzung): Lebenslauf-Baukasten mit Stationen, Deckblatt, Anschreiben-Vorlage, Bewerbungsmappe als PDF, KI-Texte, Übersetzung von Inhalten und Firmenprofilen (Plan Sprachen: Profile bleiben zum Start deutsch), Verwaltung (Prüfen, Anfragen, Firmen und Nutzer, Werbung, Inhalte, Einstellungen = Abschnitt 3), Premium-Anfrage und Top-Stellen (Abschnitt 3, Haken ist hier vorbereitet), Meldungen (3), COPLA-Schnittstelle (2b/3), Bewerberansprache und Bezahlen.
Was 1a/1b schon bauen und hier nur benutzt wird (nicht doppelt geplant): Seitenrahmen, Kopf mit Konto-Knopf-Platz, Toasts, Sprachwahl (1a 1.1, 2.1), Stellenkarte mit Varianten (1a), Leerzustand, Platzhalter, Sonderseiten, Seitenkopf, Band, Sortierung, Kontaktformular, Honigfeld und Bremse (1b 2.1), Mail-Dienst mit Warteschlange, Rahmen und Kopfzeilen (1a 2.2 dienste/mail, Fundament; Vorlagen b15 bis b17 und v04 aus 1b), Gerätespeicher mit Merkliste und inseratEntwurf (1a/1b), Tabellen firmen, stellen, stellen_adressen, stellen_uebersetzungen, fachbereiche, plz, job_alarme, mail_warteschlange, einstellungen, protokoll (1a/1b Teil 3), Hintergrund-Startpunkt pg-boss (1a), Merkliste- und Job-Alarm-Seiten (1b 1.9, 1.10; hier nur der Konto-Zweig), Firmenprofil öffentlich (1b 1.3), Ausprobieren-Entwurf (1b W5).
Fundstellen: B:anmelden. = Datei und Zeile in entwurf-b/; css:919 = assets/style.css; js:1236 = assets/app.js; T bewerben. = Textschlüssel aus TEXTE-UND-MAILS; U 3. = Usability-Bildschirm; P Arbeitgeber = Abschnitt im Plan; FC 7 = Befund im FUNKTIONEN-CHECK.
Seiten
Alle Seiten für Anmelden, Bewerben, den Bewerberbereich und den Firmenbereich, jeweils mit Inhalt und Bedienung.
Diese Tabelle ist die Adressliste aller Bereichsseiten: Bewerberbereich unter / (Gruppe (konto)), Konto-Einstellungen, Papierkorb und Zielseiten unter /, Firmenbereich unter / (Gruppe (firma)); der Plan („Aufbau im Repo“) und Karte 1a A3 verweisen hierher. Adressen in Mails, weiter=-Regeln und Tests nehmen diese Schreibweise.
Adressen unter /. Öffentliche Zugänge liegen in app/, die angemeldeten Bereiche in app/ (Bewerber, Layout mit Reitern aus B mein-bereich.html:113–118) und app/ (Firma, Layout aus B firmen-bereich.html:117–122). Beide Bereichs-Layouts prüfen die Sitzung auf dem Server (ohne Sitzung → /anmelden?weiter=…), setzen noindex und zeigen oben den Bereichskopf von B (bereich-kopf: Begrüßung h1, rechts ein Knopf; B mein-bereich.html:97–101, firmen-bereich.html:98–102) sowie die Reiterleiste (reiter mit role=tablist, B mein-bereich.html:112, firmen-bereich.html:116; js reiter() js:356–383). Die Reiter sind echte Links auf eigene Adressen in <nav aria-label> mit aria-current="page" (kein JS-Tabpanel wie in B; die CSS-Regel . wird auf . umgeschrieben, Optik bleibt; aktiver Reiter wird beim Laden in den sichtbaren Bereich gescrollt; Zahl-Kreis mit Vorlesetext „Postfach, 2 ungelesen“; U A.1). D-5 (entschieden 26.10.): Am Handy wird der letzte Reiter am rechten Rand angeschnitten gezeigt, damit man sieht, dass es weitere gibt: Die Reiterleiste hat rechts keinen Innenabstand und kein Abschluss-Element, der Überlauf bleibt sichtbar, die Scrollleiste bleibt wie in B ausgeblendet (css:626); Breite der Reiter unverändert. Test reiter.test.ts: bei 390 px Breite ragt der fünfte Reiter über den Rand. Die Übersicht ist die Startseite des Bereichs und kein Reiter: Jede Unterseite trägt über der h1 die Zeile „‹ Übersicht“, „Mein Bereich“ steht im Konto-Menü (U 4, U 7 Punkt 8). Seitentitel nach Muster „Bewerbungen · Firmenbereich · bululu“, nach jedem Wechsel bekommt die h1 den Fokus (U A.1). Der Konto-Knopf oben rechts (P Menüs, „neu gegenüber B, im Stil von B“) liegt im Seitenrahmen 1a (Platz vorgesehen) und wird hier gefüllt (Teil 2).
| Nr | Seite | Adresse | B-Datei | Daten | ||
|---|---|---|---|---|---|---|
| 1 | Anmelden | /anmelden?modus=anmelden | registrieren | firma&weiter= | anmelden.html | konten, sitzungen |
| 2 | Kennwort vergessen / neu, zweiter Faktor (App oder E-Mail-Code), Konto sichern, Zielseiten Konto | /anmelden/kennwort · /anmelden/kennwort-neu?t= · /anmelden/faktor · /konto/sichern?t= · /konto/bestaetigt?t= | anmelden.html:144–153 (vergessen-Box) | konten, konto_tokens, faktor, faktor_mail_codes, anmeldungen | ||
| 3 | Bewerben-Fenster | /stelle/[adresse]#bewerben (Dialog über 1a-Stelle) | stelle.html:103–156 | bewerbungen, bewerbungs_entwuerfe, dateien | ||
| 4 | Bewerberbereich: Übersicht | /mein-bereich | mein-bereich.html:124–134 | bewerbungen, einladungen, merkliste_konto | ||
| 5 | Bewerbungen und Bewerbung | /mein-bereich/bewerbungen · /mein-bereich/bewerbungen/[id] | mein-bereich.html:136–139 + Konzept U 3.5/3.6 | bewerbungen, nachrichten, einladungen | ||
| 6 | Postfach (Bewerber) | /mein-bereich/postfach · /mein-bereich/postfach/[bewerbungId] | firmen-bereich.html:196–209 (Chat-Optik) | nachrichten | ||
| 7 | Lebenslauf (schlank) | /mein-bereich/lebenslauf | mein-bereich.html:160–180 (B-Reiter mit Stationen und Mappe, erst 2b), Felder aus Einstellungen :184–189 | konten, dateien | ||
| 8 | Merkliste, Job-Alarme (Konto-Zweig) | /merkliste · /mein-bereich/job-alarme | mein-bereich.html:141–158 | merkliste_konto, job_alarme | ||
| 9 | Einstellungen (Konto-Menü, alle Rollen) | /konto/einstellungen | mein-bereich.html:182–193 | konten, faktor, geraete, einwilligungen | ||
| 10 | Firmenbereich: Übersicht | /firma | firmen-bereich.html:128–138 | stellen, bewerbungen | ||
| 11 | Stellen, geöffnete Stelle, Stelle neu/bearbeiten | /firma/stellen · /firma/stellen/[id] (Firmen-Sicht) · /firma/stellen/neu · /firma/stellen/[id]/bearbeiten | firmen-bereich.html:140–149, 156–194 | stellen, bewerbungen | ||
| 12 | Bewerbungen der Firma, Bewerbung | /firma/bewerbungen · /firma/bewerbungen/[id] | firmen-bereich.html:151–154 | bewerbungen, notizen, nachrichten, einladungen | ||
| 13 | Postfach (Firma) | /firma/postfach · /firma/postfach/[bewerbungId] | firmen-bereich.html:196–209 | nachrichten | ||
| 14 | Firmenprofil bearbeiten | /firma/profil | firmen-bereich.html:212–227 | firmen, dateien (Logo) | ||
| 15 | Team | /firma/team · /einladung?t= (Zielseite) | neu (B hat „Nutzer verwalten“ nur als Menüpunkt firmen-bereich.html:107 im „…“-Menü :103–113) | firmen_nutzer, firmen_einladungen | ||
| 16 | Live-Aktualisierung (ohne Seite) | /api/live?seit= (Abfrage alle 60 s; SSE erst 2b.9) | neu | Fachtabellen | ||
| 17 | Papierkorb (Bewerber, Firma) | /konto/papierkorb · /firma/papierkorb | neu (Zeilen-Optik firmen-bereich.html:140–149) | stellen, bewerbungs_notizen, job_alarme, bewerbungs_entwuerfe (je geloescht_am; dateien nicht, 1.17 Nr. 2) |
1.1 Anmelden, Registrieren, Firma registrieren
Datei (oeffentlich)/ · Teile in anmelden/. Drei Modi über ?modus= (B hat den Umschalter Anmelden/Registrieren :106–109 und die Rollen-Wahl :111–123; U 3.1/3.2 trennen Bewerber und Firma). Handy = Desktop (Layout anmelde-layout mit Karte anmelde-karte, css:600).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Kopf | h1 (T oeffentlich.anmelden.titel; registrieren: oeffentlich.registrieren.titel; firma: oeffentlich.firmaReg.titel), Satz (T …einleitung) | anmelden.html:95–102 (h1 :96) | B-Titel „Willkommen zurück“ wird durch T ersetzt. |
| 2 | Umschalter | umschalter (css:601–603) zwei button[data-modus][aria-pressed] Anmelden · Registrieren | :106–109 | wird zu zwei Links auf ?modus=; Modus „firma“ hat keinen Umschalter, sondern den Link oeffentlich.anmelden.neuFirma unter dem Formular. Rollen-Radios (fieldset. :111–123) entfallen (Konto ist rollenlos, P Ein Konto je Person). |
| 3 | Anmelden | form.: E-Mail (:127), Kennwort mit „Zeigen“ (:133, js data-zeigen in anmelden() js:917, Klick :942), „Kennwort vergessen?“ (:131 → /anmelden/kennwort), Haken „Angemeldet bleiben“ (T …angemeldetBleiben, vorgewählt; neu gegenüber B, check wie :136), Knopf (:138) | :110–143 | Server-Aktion anmelden() (Better Auth, Teil 2). Anmelden ohne Kennwort, für alle Konten gleich: unter dem E-Mail-Feld der Rand-Knopf T oeffentlich.anmelden.codeSenden „Ohne Kennwort anmelden: Code per E-Mail“; ein Klick zeigt darunter Satz T .codeHinweis („Wenn es ein Konto mit {mail} gibt, haben wir einen Code geschickt.“), Code-Feld .codeFeld, Textlink „Code erneut senden“ und Knopf .codeAnmelden (A12 Fassung anmelden, faktorMail., 3 je 15 Minuten); gibt es kein Konto, geht keine Mail, die Seite antwortet gleich (_ Nr. 15); das Kennwort bleibt der Hauptweg der Seite. Richtiger Code meldet an; hat das Konto einen Faktor, folgt bei Art app der App-Code, bei Art mail das Kennwort. Falscher Code: fehler.faktor.falschMail. Mit zweitem Faktor → /anmelden/faktor (Nr. 1.2). weiter= nur auf eigene Adressen (Test). Unbestätigte Adresse: Anmelden geht, Bereich zeigt Zeile „Bitte E-Mail bestätigen“ (P Ein Konto je Person). Links unten: oeffentlich.anmelden.neuBewerber, .neuFirma. Fehler: fehler.anmelden.falsch (ein Satz für E-Mail und Kennwort, T 7.6). Fehlversuche (26.10., _ Nr. 11): jede Anmeldung schreibt anmeldungen (Teil 3; IP, Gerät grob, Zeit, Ergebnis); ab dem 3. Fehlversuch je Konto in 15 Minuten steht T fehler.anmelden.vergessenHinweis „Kennwort vergessen? Neues Kennwort anfordern“ hervorgehoben unter dem Feld (Link /anmelden/kennwort); ab dem 5. Fehlversuch in 15 Minuten je Konto wartet die Anmeldung 1 Minute, mit jedem weiteren Fehlversuch doppelt so lang, höchstens 15 Minuten (fehler.versuche.anmelden mit {minuten}, T 4.4); je IP greift dieselbe Staffel erst ab 50 Fehlversuchen in 15 Minuten (einstellungen.sicherheit.bremse_ip_fehlversuche, Karte 3 1.11 Nr. 6) mit dem eigenen Satz fehler.versuche.netz „Aus Ihrem Netz kamen gerade viele Anmeldeversuche. Bitte versuchen Sie es in {minuten} Minuten noch einmal.“; keine dauerhafte Kontosperre. Sperrliste (Karte 3 1.15): wirkt nicht auf das Anmelden, weder IP noch Mail oder Domain; gesperrte Konten → fehler.gesperrt.konto. Erfolg: Token-Wechsel der Sitzung, Zeile ergebnis erfolg; unbekannte Gerätekennung → zusätzlich Mail A13 (1.2 „Konto sichern“, H139), nicht bei Anmeldung per E-Mail-Code. |
| 4 | Registrieren (Bewerber) | Felder bewerben.vorname, .nachname, .mail, .kennwortNeu (+ .kennwortRegel), Haken bewerben.zustimmung mit Links, Knopf oeffentlich.registrieren.anlegen | :124–137 (data-nur="registrieren") | B hat ein Feld „Name“ (:125); T trennt Vor- und Nachname → zwei Felder in zwei. Aktion kontoAnlegen() → B01-Bestätigungsmail (T 6.2), Zielseite T 3.3 „Konto angelegt, bitte bestätigen“. Honigfeld + Bremse (1b). Vergeben: fehler.feld.mailVergeben. |
| 5 | Firma registrieren | zwei Blöcke fieldset: „Ihr Betrieb“ (firmenname, strasse, plz, ort, telefon) · „Ihr Zugang“ (ihrName, mail, kennwort, zustimmung mit agbLink) · Knopf oeffentlich.firmaReg.knopf | neu, Felder im Stil :125–137 | Aktion firmaRegistrieren(): Konto (oder vorhandenes Konto nach Anmeldung) + firmen (zustand registriert) + firmen_nutzer (admin). Mail F01 „Registrierung bestätigen“ (T 6.4), Zielseite T 3.3 „Firma registriert“. weiter=stelle-neu (1b W5): nach Bestätigung → /firma/stellen/neu mit inseratEntwurf aus dem Gerätespeicher. Ort über plz-Tabelle prüfen (fehler.feld.ortUnbekannt). |
| 6 | Kein Faktor-Hinweis | unter dem Firmen-Formular steht kein Hinweis auf den zweiten Faktor; die B-info-box (anmelden.html:139–142) entfällt | Die Empfehlung kommt als Zeile firma.heute.faktor mit Knopf „Einrichten“ in „Heute zu tun“ (1.10 Nr. 2), sobald die erste Stelle online ist, also sobald Bewerberdaten kommen können. |
1.2 Kennwort, zweiter Faktor, Zielseiten Konto
Dateien anmelden/, anmelden/, anmelden/, (oeffentlich)/. Aufbau wie B vergessen-Box (anmelden.html:144–153: h2 tabindex -1, Satz, ein Feld, Knopf, Bestätigung bestaetigung[role=status]).
| Fall | Adresse | Inhalt | Hinweis |
|---|---|---|---|
| Kennwort vergessen | /anmelden/kennwort | oeffentlich.kennwort.titel, .text, Feld E-Mail, .anfordern, .zurueck; nach Senden Satz wie B :151 (T 3.2) | immer dieselbe Antwort, ob Konto existiert oder nicht (B-Satz). Mail A01 „Kennwort zurücksetzen“ (T 6.3) mit Token 60 Minuten. Dieselbe Aktion kennwortLinkAnfordern({mail, weiter}) ruft das Bewerben-Fenster (1.3 Nr. 2, N-1); weiter wandert in den Token (konto_tokens.weiter) und in den Link. |
| Neues Kennwort | /anmelden/kennwort-neu?t= | oeffentlich.kennwortNeu.titel, .feld (+ bewerben.kennwortRegel), .knopf | gültig → Kennwort gesetzt, alle anderen Sitzungen beendet, Mail A02 „Kennwort geändert“ (T 6.3), danach angemeldet → Bereich, oder zurück auf weiter (N-1: Stelle mit #bewerben, Fenster öffnet in Schritt 2). Ungültig: fehler.link.falsch/.abgelaufen (1b Fehlerseite) + „Link neu anfordern“. |
| Zweiter Faktor (Anmeldung) | /anmelden/faktor | Art app: oeffentlich.faktor.titel, .text, .feld (6 Ziffern, inputmode=numeric, autocomplete one-time-code), .knopf, Link .keinZugriff → Feld .codeFeld. Art mail (26.10.): .mailTitel „Code aus Ihrer E-Mail“, .mailText „Wir haben einen 6-stelligen Code an {mailTeil} geschickt. Er gilt 10 Minuten.“, dasselbe Feld und derselbe Knopf, Textlink .mailErneut „Code erneut senden“ (frühestens nach 60 Sekunden, Satz .mailErneutWarten; höchstens 3 Codes je 15 Minuten, danach .mailZuOft), statt .keinZugriff der Satz .keinZugriffMail „Kein Zugriff auf Ihr Postfach? Rufen Sie uns an: 0203/73997996.“ (kein Code-Feld, F3) | TOTP (App, ±1 Schritt, Wiederverwendung gesperrt) oder E-Mail-Code (fachlich/: 6 Ziffern aus sicherem Zufall, Hash in faktor_mail_codes, 10 Minuten, einmalig; Mail A12 geht sofort, ohne Warteschlangen-Verzögerung über die Vorrang-Spur der Warteschlange); Wiederherstellungscodes 10 Stück einmalig nur bei Art app. Fehler fehler.faktor.falsch bei Art app, fehler.faktor.falschMail bei Art mail, 5 Fehlversuche je Code → App: fehler.versuche.code (15 Minuten, T 4.4); Mail: Code verfällt, fehler.faktor.abgelaufen + „Code erneut senden“. Welche Art gilt, steht in faktor.art (Teil 3). Sicherheit: _ Nr. 13. |
| Faktor Pflicht (Firma) | /anmelden/faktor?einrichten=1 | oeffentlich.faktor.pflichtTitel „{firma} verlangt einen Code bei jeder Anmeldung“, .pflichtText, .einrichten „Schutz einrichten“ → Einrichtung wie Einstellungen (1.9 Nr. 4, Wahl App oder E-Mail-Code) | wenn firmen. und der Nutzer keinen Faktor hat: Sitzung ist „halb“ (nur diese Seite erreichbar). Beide Arten erfüllen die Pflicht (Satz T firma.team.faktorPflichtSatz in 1.14 Nr. 3); nur die Verwaltung verlangt die App (Karte 3 1.12). |
| Konto sichern (neues Gerät, 26.10.) | /konto/sichern?t= | Schritt 1 (GET, nur Anzeige): konto.sichern.titel „Konto sichern“, .frage „Wir melden alle Geräte ab, danach legen Sie ein neues Kennwort fest.“ + Knopf .bestaetigen „Ja, alle Geräte abmelden“ (POST); Schritt 2: .text, Feld wie Neues Kennwort, .knopf, danach .fertig + Knopf „Anmelden“ | Ziel des Knopfs „Das war ich nicht“ in Mail A13 (Token konto_tokens zweck sichern, 24 Stunden, einmalig). Der Link selbst ändert nichts (_ Nr. 29: Firmen-Postfächer rufen Links vorab auf); erst der Knopf ruft kontoSichern(token) per POST: beendet alle Sitzungen des Kontos (auch die, die gerade die Seite geöffnet hat), dann Formular neues Kennwort → kennwortNeu (A02, Protokoll kennwort_geaendert mit Grund „Konto sichern“); abgelaufen → fehler.link.abgelaufen ohne „neu anfordern“ (stattdessen Weg über Kennwort vergessen, Satz T konto.sichern.abgelaufen). A13 geht bei jeder erfolgreichen Anmeldung, deren Gerätekennung (Browser + Betriebssystem aus der Browser-Kennung, dienste/) in den letzten 12 Monaten keine erfolgreiche Anmeldung dieses Kontos hatte, nicht bei der allerersten Anmeldung nach der Registrierung und nicht bei einer Anmeldung per E-Mail-Code, auch nicht im Bewerben-Fenster. |
| E-Mail bestätigt | /konto/bestaetigt?t= | GET zeigt T 3.3 „Fast geschafft: noch ein Tipp“ mit genau einem Knopf oeffentlich.bestaetigt.knopf „Ja, {mail} ist meine Adresse“; danach T 3.3 „E-Mail bestätigt“ + Knopf in den Bereich (Bewerber: „Stellen suchen“ bzw. „Meine Bewerbungen“, Firma: „Zum Firmenbereich“) | der POST setzt konten.bestaetigt_am (Bewerbungen warten seit dem Code-Schritt im Bewerben-Fenster nicht mehr auf diese Bestätigung, 1.3 Nr. 2, C36); Firma: zustand registriert bleibt, bis erste Stelle veröffentlicht. Link älter 7 Tage: fehler.link.abgelaufen + „E-Mail erneut senden“ (nur angemeldet). |
| Faktor zurückgesetzt (Verwaltung, Abschnitt 3) | /konto/faktor-reset?t= · /konto/faktor-reset/abbrechen?t= | nur Adresse reserviert; Seiten kommen mit Abschnitt 3 (FC 9: Mails A04/A08), beide als Anzeige mit einem Knopf, erst der POST wirkt (_ Nr. 29) | hier nicht gebaut. |
1.3 Bewerben-Fenster
Datei (oeffentlich)/ (ergänzt 1a Stelle): BewerbenDialog. (Client, <dialog> wie B stelle.html:103–156, js kurzbewerbung() js:756–834), Schritte als eigene Teile. Öffnet über „Jetzt bewerben“ (1a, B :100), Adresse #bewerben, bei bewerbungsweg karriereseite nicht vorhanden (1a). Drei Schritte (T bewerben.schritt1–3, U 3.4; B hat zwei + Erfolg, Fortschrittsbalken :111 bekommt drei Segmente).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Kopf | dialog_: h2 (T bewerben.kopf mit {stelle}, {firma}), Schließen (icon-btn data-dialog-zu) | :104–110 | Natives <dialog> mit showModal(): beim Öffnen und bei jedem Schritt-Wechsel Fokus auf die Schritt-Überschrift „Schritt 1 von 3: Ihre E-Mail“ (B setzt ihn ins erste Feld, js:770; U A.2), Fortschritt als drei Striche aria-hidden, Text „Schritt 2 von 3“. Esc und ✕ schließen; Klick auf den Hintergrund schließt nur, solange nichts eingegeben wurde (B js:781; U A.1); am Handy bildschirmfüllend. Schließen mit angefangenem Entwurf: Entwurf bleibt 7 Tage (bewerbungs_entwuerfe), Toast T 3.2 „Entwurf gespeichert“; an der Stelle erscheint beim nächsten Besuch „Sie haben eine Bewerbung angefangen“ als Text am Platz des Knopfes (P Lebensläufe, T 7.4, U A.2). Dort und in den Bewerbungen (1.5 Nr. 1, Marke „Nicht fertig“) lässt sich der Entwurf mit „Verwerfen“ in den Papierkorb legen (1.17; bewerbungs_entwuerfe.geloescht_am, Rückgängig T 3.1 konto.rg.entwurfVerwerfen); der stille Verfall nach 7 Tagen löscht endgültig ohne Papierkorb. |
| 2 | Schritt 1 E-Mail | nur das Feld bewerben.mail (autocomplete=email, inputmode=email), Knopf T bewerben.weiter1 „Mit dieser E-Mail weiter“; nach Weiter prüft kontoStatus(mail), das neue Feld wird höflich angesagt und bekommt den Fokus (U 3.4, A.2): Konto vorhanden, für jedes vorhandene Konto gleich, mit oder ohne Kennwort → Ansage T bewerben.kontoGefundenAnsage „Konto gefunden. Code an {mail} senden oder mit Kennwort anmelden.“, Satz .kontoVorhanden, Hauptknopf .codeSenden „Code an {mail} senden“ (A12 Fassung anmelden) mit Code-Schritt wie unten, darunter Textlink .kontoMitKennwort „Mit Kennwort anmelden“, der das Kennwortfeld aufklappt (.kennwort, .kennwortVergessen: Textlink unter dem Feld; N-1, entschieden 26.10., Annahme C34: ein Klick sendet sofort Mail A01 an die in Schritt 1 eingetippte Adresse (Server-Aktion kennwortLinkAnfordern({mail, weiter}), dieselbe Bremse und dieselbe neutrale Antwort wie /anmelden/kennwort), das Fenster bleibt offen und zeigt an Stelle des Links den Satz T bewerben.kennwortLinkUnterwegs; der Link in der Mail führt auf /anmelden/kennwort-neu?t=…&weiter=/stelle/[adresse]#bewerben, nach dem neuen Kennwort ist die Person angemeldet und landet in der Stelle mit geöffnetem Fenster in Schritt 2, der Entwurf ist vorbelegt; weiter nur auf eigene Adressen); bei Faktor folgt nach Code oder Kennwort im selben Schritt der zweite Schritt (bewerben.faktor = oeffentlich.faktor.*; FC 7): Art app → App-Code; Art mail → nach Kennwort der E-Mail-Code, nach E-Mail-Code das Kennwort; kein Konto → die Schritt-Überschrift wechselt sichtbar und mit Fokus auf T bewerben.schritt1Konto „Schritt 1 von 3: Ihr Konto“, darunter .neuHinweis „Mit dieser E-Mail gibt es noch kein Konto. Ihr Name, dann ein Code aus Ihrer E-Mail, und es geht weiter.“ + vorname, nachname, Haken .zustimmung (Haken, so in den Nutzungsbedingungen beschrieben; Dokument „Offene Fragen“ R8); Knopf T bewerben.codeSenden „Code an {mail} senden“. Kein Kennwort in Schritt 1: nach dem Knopf wechselt die Schritt-Überschrift auf T bewerben.schritt1Code „Schritt 1 von 3: Code aus Ihrer E-Mail“, Name und Haken schrumpfen zur Zeile T bewerben.nameZeile „{vorname} {nachname} · ändern“ (Textlink klappt die Felder wieder auf), und das Code-Feld aus faktor/ (6 Ziffern, inputmode=numeric, autocomplete=one-time-code) bekommt den Fokus; darüber Satz .codeHinweis „Wir haben einen Code an {mail} geschickt. Er gilt 10 Minuten.“ mit der vollen, eben getippten Adresse und daneben Textlink .mailAendern „E-Mail ändern“, Textlink .codeErneut „Code erneut senden“ (frühestens nach 60 s, höchstens 3 je 15 Minuten, dieselbe Bremse wie der E-Mail-Faktor, faktorMail. mit Zweck bewerben, Mail A12 Fassung bewerben), nach 60 s unter dem Code-Feld der Satz bewerben.spam, Knopf .codePruefen „Weiter zum Lebenslauf“; richtiger Code → kontoAnlegenMitCode(): konten-Zeile mit bestaetigt_am = jetzt, kennwort_hash leer, Sitzung sofort, Protokoll konto_angelegt_code; die Adresse ist damit bestätigt, es gibt keinen Zustand „wartet auf Bestätigung“ und keine Mails B02 bis B04 mehr. Falscher Code: fehler.faktor.falschMail; 5 falsche Codes → Code verfällt, .codeAbgelaufen + „Code erneut senden“. Ein Kennwort kann die Person später in Einstellungen › Kennwort setzen (1.9 Nr. 3); bis dahin meldet sie sich mit Code an (1.1 Nr. 3) | :115–124 (data-form-kontakt: Vorname, Nachname, E-Mail, Telefon freiwillig, Link „Anmelden“ :123; vier Felder → E-Mail allein, Link „Schon registriert? Anmelden“ entfällt, U 3.4) | Angemeldet: Schritt 1 ist übersprungen, Kopf zeigt „als {name}“. Konto-Anlage in Schritt 1 erst mit richtigem Code (Sitzung sofort, konten.bestaetigt_am gesetzt, kein Kennwort); wird das Fenster vor dem Code geschlossen, entsteht kein Konto, danach bleibt nur der Entwurf (kein B01 aus dem Fenster; B01 gehört allein zur Seite Registrieren, 1.1 Nr. 4). kontoStatus(mail) liefert nur „neu“ oder „vorhanden“, nie ob ein zweiter Faktor besteht (_ Nr. 15: Bremse 10 je IP und Stunde, hinter dem Honigfeld); hat das vorhandene Konto einen Faktor, folgt der zweite Schritt erst nach richtigem Code oder Kennwort; der Aufbau (Code-Knopf vorn, Kennwort aufklappbar) ist für Konten mit und ohne Kennwort gleich. Bremse und Honigfeld. |
| 3 | Schritt 2 Lebenslauf | Telefon (.telefon, Pflicht, Beschriftung mit Grund „damit der Betrieb Sie anrufen kann“, vorbelegt aus konten.telefon), Ablagefläche ablage „Lebenslauf wählen oder Foto machen“ (echtes input type=file accept="application/, das Wort „Foto“ steht auf dem Knopf; .ablageFormate: PDF, JPG, PNG, HEIC bis 10 MB; N-2, entschieden 26.10., Annahme C35: Fotos verkleinert und kodiert der Browser vor dem Hochladen in ablage/ (createImageBitmap + Canvas → JPG, längste Kante 2.000 px, Qualität 0,85; Metadaten und Ortsangaben fallen dabei weg; HEIC nur, wo der Browser es dekodiert, sonst geht die Datei unverändert an den Server-Rückfall); hochgeladen wird die kleine Datei, die 10-MB-Grenze gilt für das Ergebnis; Word nicht zum Livegang, bei Word-Datei erklärt das Fenster, wie man als PDF speichert, G58; Handy: Kamera über capture; Hochladen als <progress> mit Namen), nach Wahl .ablageGewaehlt + .ablageAndere + .ablageWeiteresFoto (mehrere Fotos = mehrere Dateien einer Bewerbung, höchstens 10); hat das Konto Unterlagen (1.7 Nr. 3, „Meine Unterlagen“): alle als Liste mit Haken schon angehakt und mitgeschickt, je Zeile abwählbar, darunter .ablageAndere für weitere Dateien; neue Dateien aus dem Fenster kommen mit Haken T bewerben.auchSpeichern „Auch für künftige Bewerbungen speichern“ (angehakt) in „Meine Unterlagen“; Knöpfe .zurueck (Rand) + „Weiter zum Absenden“; keine freiwilligen Felder in diesem Schritt; nach der Ablage der Einhängepunkt FragenBlock. „Fragen des Betriebs“: wird nur gerendert, wenn die Stelle Zeilen in stellen_ (1a Teil 3) hat und einstellungen. an ist; zum Livegang trifft beides nicht zu, der Baustein ist eine leere Hülle mit Test (rendert nichts, Schritt-Zähler bleibt „2 von 3“). Antworten gingen später nach bewerbungs_ (Teil 3); das Stellenformular bekommt den Fragen-Teil erst mit der Freischaltung, nach dem Livegang | :126–143 (data-form-unterlagen, Ablage :127–131, B-Formate PDF, Word oder Foto) | „Mit meinem Bululu-Lebenslauf“ (B profil-wahl :133–136, T .mitProfil) erst 2b (Profil mit Station); Block ist hier nicht gebaut (Funktion lebenslaufBaukasten aus). Upload sofort beim Wählen über Server-Aktion dateiHochladen() → dateien (zustand hochgeladen → geprueft), Fortschritt in der Ablage; Fehler fehler.datei.* (T 4.2); der Server prüft Typ, Größe, Pixelmaße und Viren, verkleinert aber nichts (C35). |
| 4 | Schritt 3 Absenden | zusammenfassung als <dl> in drei Zeilen (T .zusammenfassung, .zfStelle, .zfLebenslauf, .zfKontakt), eingeklappt als <details> .nachricht „Nachricht an den Betrieb (freiwillig)“ (Textfeld, 2.000 Zeichen; Vorlagentext erst mit der Anschreiben-Vorlage 2b), Pflicht-Haken .einwilligung mit Datenschutz-Link, Knöpfe .zurueck + „Bewerbung senden“ (orange, voll breit; beim Senden aria-disabled mit „Wird gesendet“, nicht disabled, U A.2) | neu als Schritt (U 3.4 Schritt 3); Nachricht-Feld und Einwilligungs-Haken stehen in B in Schritt 2 (:137–138) und wandern hierher, Knöpfe wie :139–142 | Aktion bewerbungSenden(): bewerbungen (zustand neu; die Adresse ist seit Schritt 1 bestätigt, C36), einwilligungen (weitergabe, Textfassung), Dateien werden der Bewerbung zugeordnet, Entwurf gelöscht; Mails: Bewerber B05 „Bewerbung angekommen“ (T 6.2); Firma (an alle Firmennutzer je ihrer Einstellung) F03 „Neue Bewerbung“ sofort oder F04 täglich gesammelt. Ein Konto von der Seite Registrieren mit noch unbestätigter Adresse (1.1 Nr. 4) durchläuft im Fenster denselben Code-Schritt, bevor es senden kann (setzt bestaetigt_am). Erneute Bewerbung auf dieselbe Stelle, solange eine Bewerbung läuft oder nach einer Absage: fehler.bewerben.schonBeworben (T 4.3) mit Link „Meine Bewerbungen“; nach Verfall oder Rückzug ist eine neue Bewerbung möglich (G60). Zählung (U C.1): zaehleImBrowser sendet bewerben_geoeffnet (weg) beim Öffnen und bewerben_schritt (schritt 1 mit konto neu/bestand, schritt 2 mit art datei/foto) nach jedem erfolgreichen Weiter; ohne Cookies, nur Tagessummen. |
| 5 | Erfolg | erfolg (role status, Fokus auf die Überschrift): eine Fassung (U 3.4 Schritt 4): Haken-SVG, „Ihre Bewerbung ist bei {firma} angekommen.“ + Satz, was jetzt passiert (T 3.3), Knopf .meineBewerbungen → /mein-bereich/bewerbungen, Textlink .weitereStellen schließt | :145–154 | B-Text „Ihre Bewerbung ist unterwegs“ (:147) und B-Kasten „Konto anlegen“ (:149–152) entfallen (Konto besteht). Die frühere zweite Fassung „Fast geschafft: Bitte E-Mail bestätigen“ mit „E-Mail erneut senden“ und „Adresse ändern“ entfällt, weil der Code in Schritt 1 die Adresse bestätigt (C36). |
Ohne JS: das Fenster ist eine Seite /stelle/[adresse]/bewerben mit denselben drei Schritten als normale POST-Formulare (Annahme C1). Bewerben ist erlaubt, solange fachlich/ istOeffentlichSichtbar() ja sagt (Zustand aktiv oder pruefung, Firma nicht gesperrt; eine Stelle in Prüfung ist auf Bululu sichtbar, P, 1a W5, C20). Sonst zeigt 1a kein „Bewerben“; ein offener Entwurf dazu wird beim Öffnen mit fehler.bewerben.stelleWeg (T 4.3) verworfen, und bewerbungSenden() lehnt mit demselben Schlüssel ab.
1.4 Bewerberbereich: Übersicht
Datei (konto)/ · Teile in mein-bereich/. Layout (konto)/: Bereichskopf (h1 T konto.hallo {vorname}, nur Vorname; rechts kein Knopf, B-Knopf „Stellen suchen“ :101, Satz „Ihr Bereich als Bewerber“ :98 und „…“-Menü :102–109 entfallen, U 3.5), Reiter T konto.reiter.bewerbungen (+ Zahl bei Statusänderung seit dem letzten Besuch) · .lebenslauf · .postfach (+ .neuZahl ungelesen) · .merkliste · .jobAlarme (P Menüs; B :113–118 hat Übersicht/Einstellungen als Reiter, beide fallen: Übersicht = /mein-bereich selbst, Einstellungen ins Konto-Menü).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Zeile „Bitte E-Mail bestätigen“ | info-box mit Knopf „Erneut senden“ (T 7.1 Zeile Bestätigung) | css info-box (1b 617–619) | nur bei konten.bestaetigt_am leer; Erneut senden 60 s Sperre. |
| 2 | Jetzt wichtig | box jetzt-wichtig: h2 T konto.uebersicht.wichtig, höchstens 5 Zeilen je ein Satz mit einem Knopf (nur der erste farbig), Reihenfolge fest nach T 7.1 und U 4 (Blockierendes → mit Frist → wartend auf mich → Hinweis ohne Frist: E-Mail bestätigen, Einladung „Zusagen“, ungelesene Nachricht „Lesen“, Bewerbung geöffnet als reine Information ohne Knopf (verschwindet nach dem Ansehen), gemerkte Stelle läuft ab „Bewerben“, Telefon fehlt „Ergänzen“); die sechste Zeile wird „und {n} weitere“ mit Link in den Reiter | neu (P Menüs „Jetzt wichtig“; Optik kachel-Box B :125–129 als Liste) | Baustein jetztwichtig/ (Teil 2), auch Firma (7.2). Leer: ruhiger Kasten „Alles erledigt. Sobald sich ein Betrieb meldet, steht es hier, und Sie bekommen eine E-Mail.“ + „Stellen suchen“ (U 3.5). Desktop: „Jetzt wichtig“ links breit, Nr. 3 und 4 rechts schmal. |
| 3 | Ihre Bewerbungen | h2 konto.uebersicht.ihreBewerbungen, die letzten drei Zeilen wie 1.5 Nr. 1, Link .alleBewerbungen „Alle {n} ansehen“; ohne Bewerbung fehlt der Block (dann trägt „Jetzt wichtig“ den Satz und „Stellen suchen“) | neu; ersetzt die drei Zahlen-Kacheln B :125–129 (U 3.5: eine Zahl beantwortet keine Frage) | Daten aus bewerbungenBewerber(kontoId, {limit: 3}); js-Zähler data-kachel-* (js:1065–1066) entfallen. |
| 4 | Gemerkt | h2 .gemerkt, die letzten drei gemerkten Stellen (Stellenkarte „zeile“ 1a) je mit „Bewerben“; leer fehlt der Block | neu | Die grüne Box „Lebenslauf aktuell?“ (B :130–133) entfällt; sie erscheint nur als Zeile „Telefonnummer fehlt im Lebenslauf. → Ergänzen“ in „Jetzt wichtig“ (U 3.5). Keine Werbung im Login-Bereich. |
1.5 Bewerbungen und Bewerbung (mit Postfach-Verlauf)
Dateien mein-bereich/ (Liste) und bewerbungen/ (eine Bewerbung); Teile in _ und _. B zeigt nur eine Liste (:136–139, js meinBereich() js:1059–1064); U 3.5/3.6 liefern Liste und Detail.
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Liste | panel-kopf h2 konto.bewerbungen.titel mit Anzahl im Satz („7 Bewerbungen“, ohne B-Erklärsatz :137); gruppiert statt gefiltert: Gruppe „Offen“, darunter eingeklappt .gruppeAbgeschlossen „Abgeschlossen ({n})“ (Absage, Zurückgezogen, Stelle nicht mehr offen); Filter-Pillen .alle · .offen · .abgeschlossen (Optik data-stellen-filter B firmen-bereich.html:143–146) erst ab 20 Bewerbungen (U 3.6); ul. je Zeile (ganze Zeile klickbar auf die geöffnete Bewerbung, ein Tab-Halt): Firma (Monogramm/Logo 1a), Stellentitel, Firma, Ort, „Beworben vor {n} Tagen“ (.beworbenVor), Status-Marke rechts (T 5.1 Bewerbersicht: E-Mail bestätigen · Angekommen · Vom Betrieb geöffnet · Einladung zum Gespräch · Gespräch am {datum} · Anderer Termin erbeten · Termin abgesagt · Zusage · Absage · Zurückgezogen · Stelle nicht mehr offen · Nicht fertig · Nicht abgeschickt), Punkt .ungelesen bei neuer Nachricht (mit verstecktem Wort) | :136–139, js meinBereich() js:1054–1066 (füllt data-bewerbungen; B verlinkt nur auf die Stelle) | Sortierung: neueste zuerst (U 3.6), abgeschlossene in ihrer Gruppe darunter. Keine Bedienelemente in der Zeile (P). Leer: T 2 „Noch keine Bewerbungen“ + Knopf → /jobs. Live: neue Nachricht/Status kommt über SSE (1.16). |
| 2 | Bewerbung: Kopf | „‹ Übersicht“-Zeile (konto.bewerbung.zurueck → Liste), h1 Stelle bei Firma, Link .stelleAnsehen (1a-Stelle; beendet → Marke statt Link), Status-Chip; Hauptknopf je Zustand: (entfällt, C36) „E-Mail erneut senden“, Einladung „Zusagen“, neue Nachricht „Antworten“, sonst keiner | neu (U 3.6) | |
| 3 | Zeitstrahl | ol. (T 5.2: Gesendet → Angekommen → Vom Betrieb geöffnet → Einladung/Zusage/Absage), aktueller Schritt markiert, „Jetzt ist der Betrieb dran“ nur bei offenem Stand und Firma aktiv | neu | Firma gesperrt: Satz fehler.postfach.firmaGesperrt statt Zeitstrahl-Hinweis (P Gesperrte Firma, FC 6). |
| 4 | Einladung | box einladung (nur Zustand eingeladen): Datum, Uhrzeit, Ort oder Online-Link (.onlineLink), Ansprechperson; Knöpfe .zusagen (farbig), .andererTermin (Rand, Fenster mit .andererTerminTitel/-Feld/-Senden), .absagen (Text, Fenster .absagenTitel/.absagenGrund freiwillig/.absagenSenden); nach Zusage Link .kalender „In Kalender speichern“ (ICS) und der Satz „Wir erinnern Sie am Vortag“ (T 5.1 status.eingeladenZugesagt) | neu (U 3.6) | Antwort schreibt einladungen.antwort + Nachricht in den Verlauf + Mail F05 an die Ansprechperson der Einladung (T 6.4); Zusage/Absage des Bewerbers ändert den Bewerbungsstatus nicht (nur die Firma setzt Zusage/Absage; P Arbeitgeber). ICS über /api/kalender/[einladungId].ics (nur eigene; Datei: Titel „Vorstellungsgespräch {firma}“, Ort/Link, 1 h Dauer; Erinnerung am Vortag = Mail B09, nur bei zugesagtem Termin, T 6.2). |
| 5 | Nachrichten | chat (B firmen-bereich.html:198–209: chat_ :200 mit chat_ und chat_, Blasen blase/blase ich css:703, chat_ Feld + Senden :203–207), Anhang-Knopf .anhang (nur Bewerber, bis 10 MB) | firmen-bereich.html:196–209, css chat | Baustein postfach/ (Teil 2); schreibgeschützt mit Satz fehler.postfach.* nach Absage, Rückzug, Stelle beendet, Kontolöschung, Sperre (P Postfach, G39); der Satz ersetzt Eingabe und Knopf ganz (kein ausgegrautes Feld, U A.2). Eingehende Nachrichten erscheinen über Live ohne Neuladen, aber ohne Live-Ansage (kein Echtzeit-Chat, U A.2). Senden → nachrichten + B12/F07 „Neue Nachricht“ (T 6.2/6.4, je Benachrichtigungs-Einstellung). |
| 6 | Unterlagen | box .unterlagen: Datei(en) der Bewerbung mit Download (nur eigene, über /api/datei/[id]), .unterlagenStand „Stand beim Absenden“ | neu | Mappe/PDF (.mappe, .mappeAnsehen) erst 2b. |
| 7 | Zurückziehen | Textlink .zurueckziehen ganz unten → Fenster T 3.3 „Bewerbung zurückziehen“ (Kennwort nicht nötig), danach Status Zurückgezogen, Postfach gesperrt; Rückgängig-Muster (U A.6): ein Knopf „Rückgängig“ ersetzt den gedrückten Knopf und bekommt den Fokus, Toast zusätzlich, Frist nach Einstellung des Kontos (Standard 10 s, T 3.1) | neu | Rückgängig innerhalb der Frist stellt Zustand wieder her (keine F-Mail in der Frist; Mail F06 „Bewerbung zurückgezogen“ an die Firmennutzer mit Benachrichtigung „Neue Bewerbung“ erst nach Ablauf, T 6.4). Einwilligung weitergabe → widerrufen (P Lebensläufe Einwilligung). |
| 8 | Absage geöffnet | Überschrift „Absage von {firma}“, darunter der Text der Firma, kein Rot, kein großes Symbol; direkt darunter „Diese drei Stellen passen zu Ihrer Suche“ mit drei ähnlichen Stellen (Abfrage „ähnliche Stellen“ aus 1a) je mit „Bewerben“ | neu (U 3.6, 5.3) | Nichts, was Hoffnung oder Angst erzeugt: keine Notizen, keine Bewertung, keine Lesebestätigung. |
1.6 Postfach (Bewerber)
Dateien mein-bereich/ und postfach/ (U 3.12). Jeder Verlauf gehört zu genau einer Bewerbung; es ist derselbe Verlauf wie in der geöffneten Bewerbung (1.5 Nr. 5), nur ein zweiter Zugang. Kopf: h1 „Postfach“, Satz „{n} ungelesen“, Umschalter-Pille „Nur ungelesene“; Suchfeld erst ab 10 Verläufen. Liste (B chat_ :199), neueste Nachricht zuerst, ungelesene fett mit Punkt und dem versteckten Wort „ungelesen“: Logo · Firma · Stelle · letzte Zeile · Zeit. Handy: Tippen öffnet den Verlauf als eigenen Bildschirm (Kopf mit Firma, Link „Zur Bewerbung“, Zurück-Pfeil; Blasen B blase, eigene rechts mit verstecktem Vorsatz „Sie:“; Eingabe unten fest, Anhang-Knopf). Desktop: zweispaltig wie B chat (Liste links ein Drittel, Verlauf rechts, erster ungelesener vorausgewählt, offener Verlauf mit aria-current, Auswahl setzt den Fokus auf die Überschrift des Verlaufs). Nach dem Senden bleibt der Fokus in der Eingabe, Meldung „Gesendet“. Schreibgeschützt: der Satz „Diese Bewerbung ist abgeschlossen. Nachrichten sind nicht mehr möglich.“ ersetzt Eingabe und Knopf ganz. Mehrfachauswahl (Baustein auswahl/) mit Sammelaktion „Als gelesen markieren“ (G82). Keine Online-Anzeige, kein „tippt gerade“, keine Lesebestätigung mit Uhrzeit. Leer: „Hier erscheinen Nachrichten von Betrieben, bei denen Sie sich beworben haben.“ (T 2). Firma genauso (1.12 Nr. 8).
1.7 Lebenslauf (schlank zum Livegang)
Datei mein-bereich/ · Teile in _. P Bewerberbereich: „Persönliches (Name, Telefon, Wohnort) und ‚Ihre Datei: lebenslauf.jpg · Andere Datei‘; in 2b wächst er zum Baukasten“ (FC 5).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Kopf | h2 konto.lebenslauf.titel, Satz .fortschritt nur mit Baukasten (2b) → hier stattdessen .telefonErgaenzen als Hinweis, wenn Telefon fehlt | mein-bereich.html:160–163 | Fortschrittsbalken (B) erst 2b. |
| 2 | Persönliches | form. .persoenliches: .name (Vor- und Nachname, zwei Felder), .telefon, .wohnort (Ort mit Vorschlägen 1a data-wo); speichert je Feld sofort (P Zwischenspeichern), Zeile „Gespeichert {uhrzeit}“ (T 3.2) | mein-bereich.html:185–189 (Felder Name :186 und Wohnort :189 aus „Einstellungen“ von B; Telefon hat B nicht) | E-Mail-Feld (B :187) hier nicht; die Adresse steht lesend mit dem Weg „rufen Sie uns an“ in Einstellungen › Kennwort und E-Mail (1.9 Nr. 3, Karte 3 1.4a). Sprache-Hinweis .aufDeutsch. |
| 3 | Meine Unterlagen (T konto.lebenslauf.unterlagen) | box mit Liste: Lebenslauf (zweck lebenslauf, höchstens einer) und bis zu 9 weitere Dateien (zweck anhang mit Art T .artZeugnis · .artZertifikat · .artFuehrerschein · .artSonstiges), je Zeile Name, Art, Datum, „Ansehen“ (Download eigene), „Ersetzen“, „Entfernen“; darunter Ablage wie im Bewerben-Fenster mit Art-Auswahl; .keineDatei (Leerzustand mit Ablage) | neu (Ablage stelle.html:127–131) | Alle Unterlagen sind bei der nächsten Bewerbung angehakt und gehen automatisch mit. Entfernen wirkt wie Ersetzen (Rückgängig, kein Papierkorb). Ersetzen ist kein Löschen: die alte Datei bekommt nur den Rückgängig-Hinweis (T 3.1 konto.rg.dateiErsetzt, Frist nach Einstellung) und keinen Papierkorb-Eintrag (Einfachheit B6, 26.10.: sonst taucht „Papierkorb (1)“ auf, ohne dass die Person etwas gelöscht hat); nach der Frist setzt dateien.loeschen_ab, gesendete Bewerbungen zeigen weiter auf sie (W8), die Datei selbst bleibt deshalb bis zur Frist der letzten Bewerbung. |
| 4 | Abgrenzung 2b | Erfahrung, Ausbildung, Nachweise, Sprachen, Kenntnisse, Anlagen, Deckblatt, Mappe-PDF (B :163–178, konto.lebenslauf.erfahrung … .mappe) | Schlüssel bleiben in T 1.7, Bausteine kommen 2b; Reiter zeigt keinen Hinweis auf das Kommende (P Menüs: nichts, was es nicht gibt). |
1.8 Merkliste und Job-Alarme (Konto-Zweig)
Dieselben Seiten wie 1b 1.9/1.10 (P Menüs). Angemeldet: merkliste/ liest merkliste_ (Server, Reiter-Zahl konto.reiter), beim ersten Anmelden Zusammenführung Gerät → Konto mit Toast oeffentlich.ok.merklisteUebernommen (1b 1.9). Erinnerung „gemerkte Stelle läuft in 5 Tagen ab“ = Mail B13 (T 6.2) je Einstellung, einmal je gemerkter Stelle (merkliste_konto.erinnert_am). job-alarme/ (neu, Adresse /mein-bereich/job-alarme, Reiter): Liste der Alarme des Kontos (Was, Wo, Umkreis, Takt, Zustand T 5.5; Zeilen-Knöpfe „Ändern“, „Abbestellen“ (Zustand abbestellt, Rückgängig) und im „…“ „Löschen“ (legt den Alarm in den Papierkorb 1.17, job_alarme.geloescht_am, Rückgängig T 3.1 konto.rg.jobAlarmLoeschen); B mein-bereich.html:146–158 Formular data-alarm-neu als „Neuen Job-Alarm anlegen“ unten, Felder wie 1b mit zusätzlicher Takt-Option „keine E-Mail, nur speichern“ = gespeicherte Suche mit Knopf „Treffer ansehen“, P Benachrichtigungen). Beim Anmelden werden Alarme mit derselben Mail dem Konto zugeordnet (1b Teil 3 konto_id). Ändern über Formular 1b 1.11 ohne Token (Sitzung).
1.9 Einstellungen (Konto-Menü, alle Rollen)
Datei (konto)/ · Teile in _; Zugang über Konto-Knopf oben rechts (Teil 2 kontomenue/). Reihenfolge P Menüs: Benachrichtigungen, Bedienung, Kennwort und E-Mail; darunter die Zwischenüberschrift T konto.einst.gruppeSicherheit „Sicherheit und Daten“ mit Anmeldung zusätzlich schützen (zweiter Faktor), Geräte, Einwilligungen, Daten herunterladen, Konto löschen; alle als zugeklappte Karten (details wie 1b FAQ, css 930–936), nur die erste offen. B hat ein einziges Formular (mein-bereich.html:184–193, Haken „Zweiten Faktor … nutzen“ :191); „Meine Daten herunterladen“ und „Konto löschen“ stehen in B ohne Funktion im „…“-Menü (:105–106).
| Nr | Karte | Inhalt | Hinweis |
|---|---|---|---|
| 1 | Benachrichtigungen | Haken je Art (T 1.7 konto.einst.benachr*: Bewerber: neue Nachricht (bnNachricht), Statusänderung (bnStand), gemerkte Stelle läuft ab (bnMerkliste); Firmennutzer zusätzlich: neue Bewerbung sofort/täglich (fnBewerbung/fnTaeglich), Stelle läuft ab und abgelaufen als ein Schalter (fnAblauf: F08 und F09), Premium (fnPremium)), speichert sofort; der Job-Alarm-Takt liegt am Alarm selbst (1.8), kein Haken hier | immer: Konto, Kennwort, Sicherheit (nicht abschaltbar, Satz). Tabelle benachrichtigungen (Teil 3). |
| 2 | Bedienung (T konto.einst.bedienung) | keine Sprachwahl mehr in der Karte: die Sprachwahl im Kopf (1a) schreibt angemeldet konten.sprache mit, Mails folgen ihr; sonst nur die Haken aus Nr. 1; kein Haken „Weniger Bewegung“ (die Betriebssystem-Einstellung prefers-reduced-motion wird beachtet, U D) und keine Auswahl der Rückgängig-Zeit: sie ist fest 10 Sekunden | Die verzögerte Ausführung (dienste/) nimmt einstellungen.fristen.rueckgaengig_sekunden. Mails gehen erst nach dieser Frist. Die Karte „Bedienung“ entfällt, wenn sie leer wäre (Bewerber ohne Firmen-Haken). |
| 3 | Kennwort und E-Mail (T konto.einst.kennwort) | oben die aktuelle Adresse lesend T konto.einst.mailAktuell „Ihre E-Mail-Adresse: {mail}“ mit dem Satz T konto.einst.mailAendernHinweis „Adresse ändern: rufen Sie uns an, 0203/73997996, oder schreiben Sie uns“; darunter aktuelles Kennwort, neues (+ Regel „mindestens 10 Zeichen“), Knopf; danach A02 und andere Sitzungen beendet. Konto ohne Kennwort (C36): statt „aktuelles Kennwort“ der Satz T konto.einst.keinKennwort „Sie melden sich mit einem Code per E-Mail an. Mit einem Kennwort geht es schneller.“ und nur das neue Kennwort (kennwortSetzen.ts, A02) | fehler.feld.kennwortAltFalsch, .kennwortKurz, .kennwortGleich, neu .kennwortHaeufig (26.10.: dienste/ prüft gegen eine lokale Liste der 100.000 häufigsten Kennwörter im Projekt und gegen E-Mail-Adresse, Vorname, Nachname der Person; keine Zwangs-Sonderzeichen, kein Ablauf; _ Nr. 10). Gilt überall, wo ein Kennwort gesetzt wird (Registrieren, Firma registrieren, Bewerben-Fenster, Kennwort neu, Einladung, Konto sichern). |
| 4 | Anmeldung zusätzlich schützen (T konto.einst.faktor, Satz T .faktorSatz „Beim Anmelden kommt zusätzlich ein Code.“) | aus: Wahl T konto.einst.faktorArt „So bekommen Sie den Code“ als zwei Pillen .faktorArtApp „Authenticator-App (empfohlen)“ (Satz .faktorArtAppSatz) · .faktorArtMail „Code per E-Mail“ (Satz .faktorArtMailSatz mit der Konto-Adresse); Konto ohne Kennwort: statt der Pille .faktorArtMail der Satz T .faktorErstKennwort „Code per E-Mail: Legen Sie zuerst ein Kennwort fest.“ mit Link auf Karte 3; App: Knopf „Einrichten“ → Fenster: QR-Code + Geheimnis als Text, Code-Feld, danach im selben Fenster die 10 Wiederherstellungscodes mit Rand-Knopf .faktorCodesSpeichern „Codes als Datei speichern“ und Knopf „Fertig“ (kein eigener Pflichtschritt, die Codes bleiben in der Karte abrufbar; T 1.7 konto.einst.faktor*); E-Mail: Knopf .faktorMailEinrichten „Code an {mail} senden“ → Fenster mit Code-Feld (A12), danach fertig, keine Wiederherstellungscodes; an: .faktorAnApp „Eingerichtet am …, Authenticator-App“ bzw. .faktorAnMail „…, Code per E-Mail“, „Codes neu erzeugen“ nur bei Art app, bei Art mail zusätzlich .faktorUmstellen „Auf App umstellen“ (Einrichtung wie App; danach faktor.art app, alte Codes bleiben), „Abschalten“ (gesperrt, wenn Firma Pflicht hat: Satz). Abschalten, Umstellen und Codes neu erzeugen verlangen die erneute Bestätigung. Knöpfe und Meldungen sagen „Schutz einrichten“, „Schutz abschalten“, nie „zweiter Faktor“. | B :191 Haken wird Karte. Mail A03 mail. „Anmeldung zusätzlich geschützt“ mit {faktorArt} (App oder E-Mail-Code), beim Abschalten A09 mail. „Zusätzlicher Schutz abgeschaltet“ an die Person selbst (T 6.3). Verwaltungskonten: nur App (Karte 3 1.12, D34). 26.10., H138. |
| 5 | Geräte | Liste der Sitzungen (Gerät/Browser und Betriebssystem aus der Browser-Kennung, letzte Nutzung, „Dieses Gerät“, dazu nur bei Firmen- und Verwaltungskonten T konto.einst.geraetIp „zuletzt von {ip}“ mit der gekürzten IP-Adresse der Anmeldung dieser Sitzung, z. B. „91.12.…“, aus anmeldungen über sitzungen.anmeldung_id; fehlt die Zeile (älter als 30 Tage), fehlt der Zusatz; Bewerber sehen keine IP), „Abmelden“ je Zeile, „Überall abmelden“ | P Sicherheit Sitzungen; IP nur im Sicherheitsprotokoll anmeldungen 30 Tage (Annahme C2, 26.10. geändert; Karte 3 D36). |
| 6 | Einwilligungen | Bewerber: je Bewerbung „Weitergabe an {firma}, erteilt am {datum}“ lesend + Link „Bewerbung zurückziehen“ (P Bewerberbereich, FC 17); Textfassung aufklappbar | B :190 Haken „Betriebe dürfen mich … ansprechen“ wird mit; keine eigene Einwilligung. Keine freiwillige Einwilligung zum Livegang → Karte zeigt nur die Liste; ohne Bewerbung fehlt die Karte. |
| 7 | Daten herunterladen | Knopf → ZIP (JSON je Tabelle + Dateien) im Hintergrund, Mail A05 mit Link auf diese Karte (T 6.3); der Download selbst nur angemeldet als Kontoinhaber über / (zweck export, 24 Stunden), nie über einen Token im Link (_ Nr. 29) | Hintergrund-Aufgabe datenexport. |
| 8 | Konto löschen | Fenster T 3.3 „Konto löschen“ nach der Bestätigung über kennwortbestaetigung/; Folgen-Satz (Bewerbungen bleiben beim Betrieb bis zur Frist als Nachweis, P) ; Mail A06 „Konto gelöscht“ | letzter Admin einer Firma: fehler.team.letzterAdmin → erst Firma löschen oder Admin ernennen. Löschung: Konto anonymisiert; Dateien ohne Bewerbungsverweis sofort gelöscht, Dateien gesendeter Bewerbungen bleiben bis zur letzten Bewerbungsfrist (Nachweis, loeschen_ab); Bewerbungen gelten mit konten.geloescht_am als gesperrt. |
1.10 Firmenbereich: Übersicht
Datei (firma)/; Layout (firma)/: Bereichskopf h1 Firmenname (B firmen-bereich.html:98, ohne Satz „Ihr Firmenbereich.“ :99), rechts Knopf firma.kopf.neueStelle „Neue Stelle“ als Rand-Knopf btn-rand (B :102 ist btn-primary; der einzige farbige Knopf der Übersicht ist der Knopf der ersten „Heute zu tun“-Zeile) → /firma/stellen/neu, am Handy in der Leiste unten (Klebeleiste wie B stelle.html:98; U 3.8), Reiter firma.reiter.stellen · .bewerbungen (+ Zahl neu, :119) · .postfach · .firmenprofil (nur Admin) · .team (nur Admin) (P Menüs; B-Reiter :117–122 heißen Übersicht, Meine Stellen, Bewerbereingang, Neue Stelle, Nachrichten, Firmenprofil; Reiter Übersicht :117, Neue Stelle :120 und das „…“-Menü :103–113 entfallen). Firma gesperrt → Erklärseite fehler.gesperrt.firma (T 4.4) statt Bereich. Mehrere Firmen: Wechsel im Konto-Menü (Sitzung trägt firma_).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Bestätigungs-Zeile | wie 1.4 Nr. 1; zusätzlich Hinweis „Veröffentlichen geht nach der Bestätigung“ | ||
| 1a | Erste Anmeldung ohne Stelle | statt „Heute zu tun“ ein Block mit drei Schritten als Haken-Liste „Konto angelegt ✓ · Erste Stelle anlegen ○ · Bewerbungen empfangen ○“ und großem Knopf „Erste Stelle anlegen“ (farbig) | neu (U 3.8) | nur solange die Firma keine Stelle hat (auch keinen Entwurf). |
| 2 | Heute zu tun | Baustein jetztwichtig, höchstens 5 Zeilen nach T 7.2 und U 3.8: „{n} neue Bewerbungen, davon {m} für {stelle}“ → „Ansehen“ (Bewerbungen, Filter Neu) · „{name} wartet seit {n} Tagen auf eine Antwort“ → „Antworten“ (öffnet die Bewerbung) · „Stelle „{titel}“ läuft in {n} Tagen ab“ → „Verlängern“ (sofort, Toast, kein Formular) · „Stelle „{titel}“ ist pausiert seit {datum}“ → „Verlängern“ + Textlink T firma.stellen.besetztBeenden „Besetzt? Beenden“ · „„{titel}“ ist seit fast 6 Monaten pausiert, in {n} Tagen schließen wir {m} offene Bewerbungen ab“ → „Verlängern“ (14 Tage vor dem automatischen Abschluss, 1.11 Nr. 4, T 7.8 firma.heute.pausiertAbschluss) · „{n} ungelesene Nachrichten“ → „Postfach“ · Stelle nachbessern (Abschnitt 3 setzt den Zustand) · „Schützen Sie Ihr Konto mit einem zweiten Code“ → „Einrichten“ · „Ihr Firmenprofil hat noch kein Logo“ → „Logo hochladen“ · „Stelle „{titel}“ wartet auf Prüfung durch Bululu, in der Regel bis morgen. Bewerber sehen sie schon.“ (Information ohne Knopf) | neu | Den Hinweis „Frau Lenz hat das vor 5 Minuten geöffnet“ gibt es erst mit 2b.9. Leer: Satz mit der nächsten Frist „Nichts zu tun. Ihre {n} Stellen laufen, die nächste bis {datum}.“ ohne Knopf. |
| 3 | Ihre Stellen | kompakt je Stelle eine Zeile: Titel · „noch {n} Tage“ · „{n} Bewerbungen ({m} neu)“, klickbar auf die geöffnete Stelle (1.11 Nr. 1b); höchstens 5, dann „Alle Stellen“ | ersetzt die drei Zahlen-Kacheln B :129–133 (U 3.8: Zahl steht am Ding) | Desktop: „Heute zu tun“ links breit, „Ihre Stellen“ rechts. |
| 4 | Premium-Hinweis | B :134–138 „Mehr Sichtbarkeit mit Premium“ mit „Pakete ansehen“ (grün, Mitte) entfällt | U 3.8 sieht stattdessen einen ruhigen Kasten ganz unten vor („Mehr Sichtbarkeit: Top-Stellen stehen oben in der Liste.“ + „Premium anfragen“ als Rand-Knopf, einmal wegklickbar, nie bei aktivem Premium); er kommt mit der Premium-Anfrage in Abschnitt 3, bis dahin fehlt er. Keine Pakete (P). |
1.11 Stellen, Stelle neu und bearbeiten
Dateien firma/ (Liste), stellen/ (geöffnete Stelle, Firmen-Sicht), stellen/, stellen/ (Bearbeiten = dasselbe Formular), Teile _, _, _. B: Liste :140–149 mit Filter-Pillen und js firmenBereich() → stellenZeichnen() js:1144–1162 (füllt data-meine-stellen); Formular mit Live-Vorschau :156–194 (data-editor, data-inserat, data-vorschau, js inseratEditor() js:835–900 wie 1b Ausprobieren).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Liste | panel-kopf h2 firma.stellen.titel (ohne Satz „Jede Anzeige läuft 30 Tage“ :141, die Restlaufzeit steht an jeder Zeile); Gruppen statt Pillen (U 3.9), leere Gruppen fehlen: „Braucht Aufmerksamkeit“ (Nachbessern, läuft ab ≤ 5 Tage, pausiert seit höchstens 14 Tagen, Entwurf, wartet auf Prüfung, gesperrt) · „Aktiv“ · „Pausiert“ (abgelaufene Stellen, jederzeit verlängerbar; T 7.8 firma.stellen.gruppePausiert) · „Beendet“ (eingeklappt, mit Anzahl); Pillen firma.stellen.pilleAlle · .pilleAktiv · .pilleLaeuftAb · .pillePausiert · .pilleBeendet (B :143–146) und ein Suchfeld nach Titel erst ab 8 Stellen; Zeile: Titel (Link → geöffnete Stelle, Firmen-Sicht; B :1148 verlinkt auf stelle.html), Ort, Art, Status-Chip, „noch {n} Tage“ bei laufenden Stellen, „{n} Bewerbungen ({m} neu)“ als Text, rechts genau ein Rand-Knopf je Zustand: läuft ab/pausiert „Verlängern“ mit dem Textlink T firma.stellen.besetztBeenden „Besetzt? Beenden“ daneben · Entwurf „Weiter bearbeiten“ · wartet auf Prüfung keiner (Chip „Prüfung, bis morgen“) · Nachbessern „Bearbeiten“ (Chip „Bitte ergänzen: {grund}“) · gesperrt keiner · aktiv „Bewerbungen ({m} neu)“ als Knopf · beendet „Erneut schalten“; alles andere im „…“ der Zeile: Bearbeiten, Kopieren, Beenden, Löschen (nur Admin, nur Entwurf/pausiert/beendet ohne offene Bewerbungen; legt die Stelle in den Papierkorb, 1.17) | :140–149, js:1144–1162 (B-Zeile hat immer „Verlängern“ bzw. „Wieder online“ als Knopf) | Sortierung innerhalb der Gruppen: neueste Änderung zuerst. Auswahl-Leiste (P Auswählen: Strg/Umschalt-Klick, Strg+A, Esc) für Beenden und Verlängern mehrerer Stellen, Baustein auswahl/ (Teil 2). Rückgängig bei Beenden und Löschen nach dem Muster U A.6 (Knopf „Rückgängig“ an der Stelle des gedrückten Knopfes, Frist nach Einstellung, T 3.1). Marke „Als Top-Stelle“ nur mit Premium (Abschnitt 3; Haken im Formular hier vorbereitet, versteckt). Unter der Liste Textlink „Papierkorb ({n})“ (nur bei n > 0) → /firma/papierkorb (1.17). |
| 1b | Geöffnete Stelle (Firmen-Sicht) | Kopf wie die öffentliche Stelle (1a), darunter Reihe Zustand · Restlaufzeit · Aufrufe (Zahl ohne Kurve, aus dienste/) · Bewerbungen; Knöpfe „Bearbeiten“ (Rand) · „Verlängern“ (läuft ab oder pausiert, Rand) · „…“ (Kopieren, Beenden, Löschen nur Admin; Premium anfragen und „Als Top-Stelle“ mit Abschnitt 3); darunter die Bewerbungen dieser Stelle als Liste wie 1.12 Nr. 1 | neu (U 3.9; in B nicht vorhanden) | „Alles, was mit einer Stelle zu tun hat, erreicht man von der Stelle aus“ (P). Nach „Veröffentlichen“ landet die Firma hier mit Toast „Online. Läuft bis {datum}.“, bei der ersten Stelle einer neuen Firma „Online für Bewerber. Bululu prüft sie bis morgen, dann erscheint sie auch bei Google und im Job-Alarm.“ (U 3.11). |
| 2 | Formular | Überschrift „Neue Stelle“, rechts klein „Entwurf gespeichert {uhrzeit}“ (sobald das erste Feld gefüllt ist, nur sichtbar, keine Ansage); formular box am Desktop links mit Live-Vorschau rechts (inserat-vorschau B :166–193, css:585), am Handy eine Spalte; Felder nach 1a Teil 3 stellen in drei Blöcken mit h2 (U 3.11): Block 1 „Die Stelle“: Titel mit (m/w/d) (Beispiel als Platzhalter, Prüfung), Fachbereich (Auswahl aus Tabelle), Beschäftigungsart (4 Pillen mit Mehrfachwahl, Vollzeit vorgewählt, mindestens eine bleibt gewählt; 1a W3 B, 26.10.), Arbeitsort + PLZ (Standard Firmensitz, Vorschläge 1a), Erforderliche Deutschkenntnisse (enum deutschstufe aus 1a: keine, grund, gut, sehr_gut, also 4 Pillen, Standard „Grundkenntnisse“); Block 2 „Der Text“: Aufgaben · Das brauchen Sie · Gut, aber nicht nötig (freiwillig, eingeklappt) · Das bieten wir (freiwillig, vorbelegt aus firmen.bieten (Firmenprofil 1.13 Nr. 3), sonst aus der letzten Stelle) (je Listenfeld ein Punkt je Zeile, Hinweis in der Beschriftung, Baustein listenfeld/); Block 3 „Bedingungen und Bewerbung“ mit drei sichtbaren Dingen und einem eingeklappten Rest: Gehalt von/bis mit Einheit als Pillen, „pro Monat“ vorgewählt (freiwillig, Pflicht wenn einstellungen.gehalt_pflicht), Start (freiwillig, Datum oder sofort), Ansprechperson (siehe unten); darunter <details> T firma.neu.weitereAngaben „Weitere Angaben (freiwillig)“, zugeklappt, mit den vier Angaben, die ein Betrieb für die meisten Stellen nie ändert (Vorgaben bleiben; beim Bearbeiten einer Stelle offen, sobald eine davon vom Standard abweicht): Befristung (freiwillig, erste Zeile im eingeklappten Teil: zwei Pillen „Unbefristet“ · „Befristet“, keine vorgewählt; bei „Befristet“ erscheint das Datumsfeld „bis“, freiwillig; schreibt 1a stellen./befristet_; T firma.neu.befristung, .befristungUnbefristet, .befristungBefristet, .befristetBis, T 7.9; Anzeige nur in den Eckdaten der Stelle, F2 A), Haken „Sozialversicherungspflichtig“ direkt nach der Befristung, Homeoffice (Ja/Nein, Standard Nein), Bewerbungsweg (Standard „über Bululu“, „eigene Karriereseite“ blendet das https-Adressfeld erst auf Wahl ein); die Ansprechperson steht sichtbar im Block (Auswahl aus dem Team, Standard: ich; ob ihr Telefon in Anzeigen steht, legt die Person einmal unter Team fest, 1.14, firmen_); Pillen-Gruppen als fieldset mit legend; das Pflichtfeld-Zählen und die Live-Vorschau lesen auch die eingeklappten Felder; unten Fortschrittssatz „Noch {n} Pflichtangaben: {liste}“ + firma.neu.veroeffentlichen (farbig, B :181; am Handy unten fest); am Handy daneben Rand-Knopf „Vorschau“ (bildschirmfüllend, so wie Bewerber sie sehen) | :167–194 | Kein Knopf „Zwischenspeichern“ (B :182 entfällt, das System speichert selbst; U 3.11). Live-Vorschau am Desktop inert mit aria-label „Vorschau, so sehen Bewerber die Anzeige“ (U A.2). B hat ein freies Textfeld „Anzeigentext“ (:176) + KI-Knopf (:175): ersetzt durch die Feldstruktur (Gesamtkonzept 5.3, 1a Teil 3); KI-Knopf entfällt (2b). Import-Zeile „Vorhandene Anzeige übernehmen“ (data-import :158–165) entfällt (Idee, nicht beauftragt). Entwurf speichert jedes Feld sofort (P Zwischenspeichern), „Veröffentlichen“ prüft Pflichtfelder (fehler.feld., fehler.stelle.; Fehler am Feld in einem Satz, erstes fehlendes Feld bekommt den Fokus, dazu dringende Meldung „{n} Angaben fehlen“, U 3.11/A.2), setzt veroeffentlicht_am und laeuft_bis und den Zustand: aktiv, oder pruefung, wenn fachlich/ ja sagt (firmen.geprueft false UND Schalter einstellungen.pruefung.neue_firmen an UND firmen.pruefstufe normal UND kein aktives Premium; D25). Bei pruefung ruft stelleVeroeffentlichen() in derselben Transaktion pruefungAnlegen() (Karte 3: Zeile in pruefungen, frist_am = nächster Werktag 9:00, V01 in die Warteschlange) und legt F21 mail. „Stelle wartet auf Prüfung“ an die Person, die veröffentlicht hat, in die Warteschlange (T 6.4); F10 mail. kommt aus Karte 3. Steht die Firma noch auf zustand registriert, wird sie dabei aktiv (auch bei pruefung). Unbestätigte Mail → Fehlertext am Knopf (P), es entsteht keine Prüfung. Vorbelegung aus inseratEntwurf (1b W5) beim ersten Aufruf von /firma/stellen/neu, danach Gerätespeicher leeren. Kopieren = neuer Entwurf mit Feldern und Titel „{titel} (Kopie)“. Änderung von Titel oder Firmenname in den ersten 30 Tagen nach der Freigabe der Firma (firmen.geprueft_am) erzeugt eine Zeile in der Gruppe „nachprüfen“ der Verwaltung. Nachbessern-Zustand (Abschnitt 3: nach „Ablehnen“ in der Prüfung oder „Offline nehmen“ nach einer Meldung) nutzt dasselbe Formular mit Grund-Zeile oben; „Veröffentlichen“ aus nachbessern geht immer in pruefung mit erneut_ und neuer Prüfzeile (pruefung_art nachbesserung), unabhängig von noetig., damit die beanstandete Stelle einen zweiten Blick bekommt (Annahme C22). |
| 3 | Vorschau rechts | vorschau-karte (css:586–589) mit Stellenkarte „zeile“ (1a) live aus den Feldern | :185–192, js:841–889 | |
| 4 | Ablauf-Aktionen | Verlängern: laeuft_bis = heute + einstellungen.laufzeit_tage (Standard 30), beliebig oft, solange die Stelle aktiv, läuft ab oder pausiert (abgelaufen) ist, ohne zeitliche Grenze; Toast „30 Tage verlängert“, kein Fenster. Pausiert: eine abgelaufene Stelle ist nicht öffentlich (1a Sichtbarkeit, 410), für die Firma sichtbar mit Chip „Pausiert seit {datum}“ (T 5.4, überall dieselbe Formulierung: Zeile, „Heute zu tun“, Mail F09) und bleibt so, bis die Firma sie verlängert, beendet oder löscht; der Nachtlauf fasst die Stelle selbst nicht an. Beenden: zustand beendet, offene Bewerbungen → „Stelle beendet“ (B14 neutral, T 6.2), Rückgängig nach Einstellung (davor keine Mails); erreichbar über „…“, den Textlink „Besetzt? Beenden“ in Stellenzeile und „Heute zu tun“ und den Textlink in Mail F09 (führt nach Anmeldung in die Firmensicht der Stelle mit geöffnetem Fenster „Stelle beenden? {n} offenen Bewerbern sagen wir ab.“; erst der Knopf beendet, der Link selbst ändert nichts, _ Nr. 29; danach Toast „Beendet. {n} Bewerbern sagen wir ab.“ und Rückgängig; H203); Erneut schalten: nur beendet, Kopie als Entwurf (Annahme C3); Löschen: nur Admin, Fenster T 3.3, legt die Stelle in den Papierkorb (1.17; stellen.geloescht_am), Rückgängig | neu (P Lebensläufe Stelle) | Hintergrund (stellen-ablauf.ts): täglich laeuft_ab-Mail F08 (5 Tage vorher) an Ansprechperson und Admins, abgelaufen F09 (sagt: pausiert, jederzeit verlängerbar). Datenschutz: offene Bewerbungen (neu, gesichtet, eingeladen) auf einer Stelle, die seit einstellungen.fristen.pausiert_abschluss_monate (6) abgelaufen ist, werden automatisch abgeschlossen (zustand stelle_beendet, abgeschlossen_am, B14 neutral an den Bewerber; ab da läuft die 6-Monats-Löschfrist der Bewerbung); 14 Tage davor steht eine Zeile in „Heute zu tun“ (1.10 Nr. 2), Verlängern stoppt den Abschluss, die Frist zählt dann ab dem nächsten Ablauf neu; die Stelle selbst bleibt pausiert. Schnittstellen-Stellen: ohne Laufzeit-Mails (FC 12, Abschnitt 3). |
1.12 Bewerbungen der Firma, eine Bewerbung, Postfach der Firma
Dateien firma/, bewerbungen/, firma/; Teile _, _. B: Bewerbereingang :151–154 mit js firmenBereich() js:1164–1195 (füllt data-eingang; Status-Auswahl status-wahl und Notiz-Feld notiz je Zeile) und Chat :196–209 (Liste chat_ :199 + Verlauf; js:1199 ff.).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Liste | h2 firma.bewerbungen.titel + Satz „{n} Bewerbungen, {m} neu“ (B-Erklärsatz :152 entfällt); Filter in einer Zeile: Auswahl „Stelle: Alle ▾“ und Pillen „Neu · Offen · Alle“ (Standard „Offen“ = Neu + Gesichtet + Eingeladen; U 3.10); fest neueste zuerst, am Desktop über die Spaltenköpfe umsortierbar, kein Sortier-Knopf; Zeile (ganze Zeile klickbar, ein Tab-Halt auf dem Namen): Initialen-Kreis, Name, Stelle, „heute“/„vor {n} Tagen“, Status-Chip (T 5.1 Firmensicht), Punkt bei ungelesener Nachricht (mit verstecktem Wort), leise Marke „seit {n} Tagen ohne Antwort“ (Zustand Neu oder Gesichtet ab Tag 3, T 5.1), „Konto gelöscht“ wenn zutreffend; keine Bedienelemente in der Zeile (P) | :151–154, js:1164–1195 (Status-Select und Notiz in der Zeile entfallen: Aktionen im Detail) | Auswahl-Leiste für „Absagen“ mehrerer (P Auswählen; Fenster mit einer Vorlage für alle). Leer: T 2. |
| 2 | Bewerbung: Kopf | ‹ Zurück, h1 Name, Stelle (Link auf die geöffnete Stelle), „beworben vor {n} Tagen“, Status-Chip; kein Kollegen-Hinweis zum Livegang (2b.9: Satz „Frau Lenz hat das vor 5 Minuten geöffnet“, wenn eine Kollegin kurz vorher hier war (aus ereignisse); Kontaktzeile: Telefon (antippen ruft an) und E-Mail aktuell aus dem Konto des Bewerbers, weicht die Nummer vom Stand beim Absenden ab, steht „aktuelle Nummer“ daneben (P Mappe); „Gesichtet“ wird beim ersten Öffnen durch einen Firmennutzer ohne Mail gesetzt (geoeffnet_am, geoeffnet_von), nie durch die Verwaltung (FC 14) | neu (U 3.10) | |
| 3 | Handlungsleiste je Zustand | im Quelltext direkt nach dem Kopf, am Handy unten fest, am Desktop oben rechts: neu/gesichtet: firma.bewerbung.einladen (orange) + .absagen (Rand), „Zusage“ hinter „…“; eingeladen: .zusage (orange), .neuerTermin (Rand), .absagen (Text); Zusage/Absage/zurückgezogen/beendet: keine Leiste, nur Chip mit Datum (U 3.10, U 7) | neu | Jeder Knopf öffnet ein Fenster mit Vorlage aus T 6.1 (vorlage.firma.einladung, .zusage, .absage, .neuerTermin) zum Bearbeiten; erst „Senden“ setzt den Status, schreibt die Nachricht in den Verlauf und schickt B07 Einladung / B08 Neuer Termin / B10 Zusage / B11 Absage (T 6.2). Einladen-Fenster: Datum, Uhrzeit, Ort oder Online-Link, Ansprechperson (select Team, vorbelegt Ansprechperson der Stelle) → einladungen + ICS im Mail-Anhang; „Neuer Termin“ = neue Einladung, alte als ersetzt. Rückgängig bei Einladung und Absage nach dem Muster U A.6 (Frist nach Einstellung; B07/B11 erst danach, T 6.2). Ein Zustand entsteht nur durch eine Handlung, nie durch ein Auswahlfeld (B status-wahl js:1182 und die sofortige Mail-Meldung js:1187 entfallen). |
| 4 | Verlauf (Firmensicht) | ol. T 5.3 (Eingegangen, Gesichtet von {name}, Eingeladen, Antwort des Bewerbers, Zusage/Absage) | neu | |
| 5 | Unterlagen | Dateien der Bewerbung: Bilder als Ansicht, PDF als Download (P Dateien), Zugriff nur Firmennutzer (Rechte-Prüfung je Datei), Nachricht des Bewerbers | neu | Mappe-Ansicht 2b. Öffnen durch Verwaltung mit Grund → Protokoll (Abschnitt 3). |
| 6 | Notizen | box notizen unten (nach der Entscheidung): ein Textfeld „Notiz (nur für Ihr Team)“, speichert sofort, darunter „zuletzt geändert von {name}, {zeit}“; kein Speichern-Knopf; Textlink „Notiz löschen“ unter dem Feld (nur wenn Text da ist; legt die Notiz in den Papierkorb 1.17, Rückgängig T 3.1 firma.rg.notizLoeschen); nur Firmennutzer, nie Bewerber (U 3.10) | js:1183 (Notiz-Feld notiz, B speichert im Gerät) | Tabelle bewerbungs_notizen (eine Notiz je Bewerbung; geloescht_am gesetzt = im Papierkorb, das Feld ist dann leer). Wiederherstellen setzt den Text zurück; steht inzwischen eine neue Notiz da, kommt der alte Text mit Datumszeile darunter. |
| 7 | Nachrichten | Verlauf-Baustein wie 1.5 Nr. 5 (ohne Anhang, P: Anhänge nur vom Bewerber), in der Eingabezeile Textknopf „Vorlage einfügen“; ungelesen zählt für die Firma gemeinsam (Admin und Recruiter) | firmen-bereich.html:198–209 | Mail B12 „Neue Nachricht“ an den Bewerber je Einstellung. |
| 7a | Vorherige / Nächste | Knöpfe „Vorherige Bewerbung“ / „Nächste Bewerbung: {name}“ am Ende und Pfeiltasten ← → (nur wenn der Fokus nicht in einem Textfeld steht), innerhalb des aktuellen Filters | neu (U 3.10, A.2) | |
| 8 | Postfach (Firma) | wie 1.6 (Liste, eigener Verlauf-Bildschirm am Handy, zweispaltig am Desktop, „Nur ungelesene“, Mehrfachauswahl „Als gelesen markieren“); Zeile: Initialen · Name · Stelle · letzte Zeile · Zeit; im Verlauf Textknopf „Vorlage“; Leer: „Hier erscheinen Nachrichten Ihrer Bewerber. Schreiben Sie ihnen aus der Bewerbung heraus.“ + „Bewerbungen“ (Rand) | :196–210 (Optik der Liste: chat_ :199; Reiter heißt „Postfach“ statt „Nachrichten“ :121) | U 3.12 |
1.13 Firmenprofil bearbeiten
Datei firma/ (nur Admin; Recruiter sieht im Reiter-Platz nur den Link firma.profil.ansehen → /firmen/[adresse], P Rechte). B :212–227 (data-firmenprofil, Felder Firmenname, Ort, Webseite, Telefon, Über uns, Knopf „Speichern“).
| Nr | Bereich | Bausteine | B-Fundstelle | Hinweis |
|---|---|---|---|---|
| 1 | Logo | logo-feld: Vorschau (Monogramm 1a, wenn leer), Ablage „Logo wählen“ (PNG, JPG, WebP bis 2 MB; kein SVG, P Dateien), „Entfernen“ | B :215 (firmenkasten_: Monogramm + Knopf „Logo hochladen“ ohne Funktion); Ablage wie Bewerben | der Browser verkleinert das Logo vor dem Hochladen auf Anzeigegröße (längste Kante 800 px, PNG bleibt PNG wegen Transparenz, JPG/WebP → WebP; ablage/, N-2, C35), der Server prüft Typ, Größe (2 MB), Maße (höchstens 1.000 px) und Viren und speichert ohne Neukodierung; firmen.; das Logo ist öffentlich, sobald die Virenprüfung es freigibt (dateien.zustand geprueft), ohne Freigabe durch die Verwaltung. Unter dem Logo-Feld steht T firma.profil.logoOeffentlich „Öffentlich seit {datumKurz}“ (dateien.geprueft_am), während der Virenprüfung T gemeinsam.datei.hochladen „Wird hochgeladen“; ohne Logo kein Satz. |
| 2 | Stammdaten | Firmenname, Straße, PLZ, Ort (Vorschläge), Telefon + Haken „Telefon öffentlich zeigen“ (firmen.telefon_frei, 1b), Webseite (https, fehler.feld.webseite) | :216–223 (B: Firmenname, Ort, Webseite, Telefon) | Jede Änderung speichert sofort, Zeile „Gespeichert {uhrzeit}“ (P Zwischenspeichern); B-Knopf „Speichern“ (:225) entfällt. Firmenname oder Ort geändert → neue firmen.adresse über 1a firmenAdresseBilden(), alte Adresse in firmen_adressen (301). Firmenname geändert innerhalb von 30 Tagen nach der ersten Freigabe → Zeile in pruefungen mit art aenderung und zustand offen in der Gruppe „Automatisch freigegeben, nachprüfen“ (Karte 3 1.2, D27, C10); die Änderung ist sofort sichtbar. Inline-Styles :214, :225 → Klassen. |
| 3 | Über uns | Textfeld (Absätze, 2.000 Zeichen) → firmen.beschreibung (1b 1.3 zeigt es); darunter Listenfeld firma.profil.bieten „Das bieten wir“ (ein Punkt je Zeile) → firmen.bieten, Vorlage für neue Stellen (1.11 Nr. 2), öffentlich nicht gezeigt | :224 | Hinweis „Bitte auf Deutsch“ (P Sprachen). |
| 4 | Ansprechperson des Betriebs | select aus Team (Name, Telefon aus konten) → firmen.ansprechperson_id; wird Vorbelegung für neue Stellen | neu (P 2a „Firmenprofil … Ansprechperson“) | Öffentlich zeigt das Profil keine Person (1b 1.3 hat keine Zeile; nur Stellen zeigen ihre Ansprechperson). Annahme C5. |
| 5 | Link öffentlich | Textlink firma.profil.ansehen → /firmen/[adresse] | neu | Adresse aus firmen.adresse (1a). Solange die Firma registriert (noch keine Stelle veröffentlicht) ist, liefert 1b das Profil nur für angemeldete Nutzer dieser Firma (Besucher 404); der Link funktioniert also ab dem ersten Tag. |
| 6 | Firma löschen | ganz unten, nur Admin: Textlink firma.profil.firmaLoeschen → Fenster nach Muster „Konto löschen“ mit Kennwort (P Firma löschen): Stellen beendet, offene Bewerbungen „Stelle beendet“ (B14 neutral), Nutzer-Mitgliedschaft endet, Mail F18 an alle Firmennutzer; der Export-ZIP der Firma liegt 30 Tage in den Einstellungen der bisherigen Admins (Karte „Daten herunterladen“, Abschnitt „Exporte“), Download nur angemeldet, kein Link mit Token in F18 (_ Nr. 29) | neu (FC 6) | Zustand geloescht; Firma verschwindet aus 1b-Listen. |
1.14 Team
Datei firma/ (nur Admin) · Teile _; Zielseite (oeffentlich)/. Kein B-Bildschirm (nur Menüpunkt „Nutzer verwalten“ firmen-bereich.html:107, „Bald verfügbar“); Optik: Liste wie Stellen-Zeilen, Formular wie formular box.
| Nr | Bereich | Bausteine | Hinweis |
|---|---|---|---|
| 1 | Liste | Zeile je Nutzer: Name, E-Mail, Rolle-Chip (Admin · Recruiter), Faktor-Marke „2. Faktor aktiv“, letzte Anmeldung, Haken „Telefon in Anzeigen zeigen“ (firmen_, je Person und Firma einmal; U 3.11; 1a Arbeitgeber-Kasten liest ihn); „…“: Rolle ändern, Entfernen (nicht beim letzten Admin: Knopf fehlt + Satz fehler.team.letzterAdmin); angelegte Konten ohne Kennwort stehen in derselben Liste mit dem Zustand T firma.team.eingeladen „wartet auf Kennwort, E-Mail vom {datumKurz}“ statt Rolle-Chip-Zusatz und mit „…“: „E-Mail erneut senden“, „Zurückziehen“ | Entfernen: firmen_nutzer.zustand entfernt, der entfernende Admin wird Ansprechperson aller Stellen und offenen Einladungen der Person (P Arbeitgeber), Toast mit Rückgängig (Frist nach Einstellung) nennt das (T 3.1). Nach Ablauf der Frist Mail F19 mail. „Aus dem Team entfernt“ an die entfernte Person (T 6.4). |
| 2 | Mitarbeiter anlegen | Formular: Vorname, Nachname, E-Mail, Rolle (Admin · Recruiter), Überschrift firma.team.anlegen „Mitarbeiter anlegen“, Knopf firma.team.anlegenKnopf „Konto anlegen“ → firmen_einladungen (Token 7 Tage), Mail F02 „Ihr Konto im Team“ (T 6.4); danach Toast T firma.team.anlegenOk „{name} bekommt jetzt eine E-Mail und legt das Kennwort selbst fest, gültig bis {datumKurz}.“ und die Zeile „wartet auf Kennwort“ in der Liste | Nomad 26.10.: Jede Firma legt Mitarbeiter-Konten selbst an. Zielseite /einladung?t=: ohne Konto → nur noch Kennwort festlegen (Name und Mail stehen schon da; hat die Verwaltung nur die Mail eingetragen, Karte 3 H126/H127, fragt die Seite den Namen mit ab; die Mail gilt mit dem Klick als bestätigt), bei Faktor-Pflicht der Firma gleich danach Faktor einrichten, dann Beitritt; Adresse hat schon ein Konto → Anmelden und „Einladung annehmen“ (ein Konto je Person, nie ohne Zustimmung angehängt); danach Toast T 3.2 und Firmenbereich. Kennwörter vergibt nie der Admin. Abgelaufen: fehler.link.abgelaufen. Mail-Adresse bereits Mitglied: fehler.team.schonImTeam. |
| 3 | Schalter Faktor-Pflicht | check „Zweiter Faktor für alle Nutzer dieser Firma Pflicht“ (firmen.faktor_pflicht), Satz T firma.team.faktorPflichtSatz „App oder Code per E-Mail, beides zählt.“ (T 7.10), Satz, wer ihn noch nicht hat (Zahl) | P Arbeitgeber; wirkt bei der nächsten Anmeldung (1.2); beide Faktor-Arten erfüllen die Pflicht (26.10.). Beim Einschalten Mail F20 mail. „{firma} verlangt ab jetzt einen Code bei jeder Anmeldung“ an alle Nutzer der Firma ohne zweiten Faktor (T 6.4). |
1.15 Konto-Menü oben rechts (ohne eigene Seite)
Baustein kontomenue/ (Teil 2) im Seitenrahmen 1a: Knopf mit Monogramm des Namens (Optik sprache_-Stil B anmelden.html:60, Ausklapp ausklapp; Name „Konto von {vorname} {nachname}“, aria-expanded, darin normale Links, kein ARIA-„menu“, Esc schließt und gibt den Fokus zurück; U A.1), Einträge P Menüs: Mein Bereich (Bewerber: /mein-bereich; Firma: /firma) · Wechsel zu Bewerber / {Firma} (nur bei Mitgliedschaften; setzt Sitzungs-Firma) · Einstellungen · Papierkorb ({n}) (nur, wenn der Papierkorb des gewählten Bereichs etwas enthält; Bewerber → /konto/papierkorb, Firma → /firma/papierkorb; 1.17) · Hilfe und Kontakt (öffnet den passenden Hilfe-Artikel: Firmen-Sitzung → /ratgeber/hilfe-betriebe, sonst /ratgeber/hilfe-bewerber; Karte 1b 1.6, B21; von dort führt der Schluss-Block auf /kontakt) · Abmelden. Ohne Sitzung zeigt der Kopf wie B „Anmelden“ (orange) und „Stelle inserieren“ (grün, :61–62); angemeldet ersetzt das Konto-Menü den Anmelden-Knopf, „Stelle inserieren“ führt für Firmennutzer auf /firma/stellen/neu.
1.16 Live-Aktualisierung (ohne Seite)
Zum Livegang ohne Dauerverbindung: Reiter-Zahlen (ungelesen, neue Bewerbungen) kommen mit jeder Seite vom Server; der Client-Baustein live/ fragt in offenen Listen und Verläufen alle 60 Sekunden GET / ab (Rechte-Prüfung wie die Liste; liefert Zähler und neue Zeilen seit dem Zeitpunkt aus den Fachtabellen, keine eigene Tabelle) und fügt neue Zeilen nicht selbst ein: über der Liste erscheint die ruhige Zeile T gemeinsam.live.neu „{n} neue … · anzeigen“ (aria-live polite, z. B. „2 neue Bewerbungen · anzeigen“); erst der Klick lädt sie oben in die Liste, Auswahl und Scrollstand bleiben; dieselbe Abfrage frischt die Reiter-Zahlen, die Zahlen von „Heute zu tun“ und in der Verwaltung die Zahl-Kreise auf; den offenen Verlauf lädt er ohne Ansage nach (kein Echtzeit-Chat, U A.2). Server-Sent Events mit Tabelle ereignisse und LISTEN/NOTIFY (W6) kommen nach dem Livegang (Baureihenfolge 2b.9); keine Browser-Push-Benachrichtigungen (nicht beauftragt).
1.17 Papierkorb (Firma und Bewerber)
Dateien (firma)/ und (konto)/; Baustein papierkorb/ (Teil 2.1), Aktionen fachlich/ (Teil 2.2, 3.2). Nomad 26.10.: ein Papierkorb für beide Seiten, für vieles, was man anlegen und löschen kann. Bisher hatte nur die Verwaltung einen (Inhalte, Karte 3 1.10); die Regeln sind dieselben: Löschen setzt geloescht_ (Lesen filtert überall), der Rückgängig-Hinweis (T 3.1, Frist C6) bleibt, nach einstellungen.fristen.papierkorb_tage (30, Karte 3) löscht der Nachtlauf (fristen.ts) endgültig. Optik aus vorhandenen Bausteinen, nichts Neues gestaltet: panel-kopf h2 gemeinsam.papierkorb.titel + Satz gemeinsam.papierkorb.satz, Zeilen wie die Stellenliste (1.11 Nr. 1), Leerzustand wie T 2, Fenster (Teil 2 fenster/) nur für „Papierkorb leeren“.
| Nr | Bereich | Bausteine | Hinweis |
|---|---|---|---|
| 1 | Was hineingeht (Firma) | Stellen in jedem löschbaren Zustand (Entwurf, pausiert, beendet; nur Admin, ohne offene Bewerbungen, 1.11 Nr. 1) · Notizen zu Bewerbungen (1.12 Nr. 6) | Nicht: Team-Mitglieder und Einladungen (Zustand mit Rückgängig und Übernahme der Stellen, unnötig), Logo (eine Datei, neu wählen ist ein Klick), Firma löschen (eigener Ablauf mit Export und Fristen, 1.13 Nr. 6), eigene Vorlagen (gibt es in 2a nicht: Vorlagen kommen aus T 6.1, „Das bieten wir“ ist ein Profilfeld). |
| 2 | Was hineingeht (Bewerber) | Job-Alarme (1.8 „Löschen“) · verworfene Bewerbungsentwürfe (1.3, 1.5), also nur bewusst Gelöschtes | Nicht: ersetzte Lebenslauf-Dateien, Merkliste (Rückgängig genügt, 1b W1), Bewerbung zurückziehen (Zustand, 1.5 Nr. 7), Konto löschen (eigener Ablauf, 1.9 Nr. 8), Nachrichten und Einwilligungen (werden nicht gelöscht), Geräte (Sitzungen). Eine versendete Bewerbung behält ihren Verweis auf die Datei (W8). |
| 3 | Zugang | Textlink gemeinsam.papierkorb.link „Papierkorb ({n})“ (btn-text, klein) unter der jeweiligen Liste: Stellen (Firma); Job-Alarme und Bewerbungen (Bewerber); dazu Eintrag im Konto-Menü (1.15); beides nur bei n > 0 | Baustein PapierkorbLink., Zahl kommt vom Server mit der Seite. Kein Reiter, kein Menüpunkt bei leerem Papierkorb (P Menüs: nichts, was es nicht gibt). |
| 4 | Liste | ul Zeilen (Optik Stellenzeile): Art als Chip (gemeinsam.papierkorb.art*: Stelle · Entwurf · Notiz zu {name} · Job-Alarm · Bewerbungsentwurf), Name (Stellentitel, Alarm „{was} in {wo}“, Stelle des Entwurfs), gemeinsam.papierkorb.geloeschtVon „von {name}“ (nur Firma), gemeinsam.papierkorb.geloeschtVor „gelöscht {datumKurz} · noch {m} Tage“, rechts Rand-Knopf gemeinsam.papierkorb.wiederherstellen und Textknopf .endgueltig; neueste zuerst; Gruppen nach Art erst ab 8 Einträgen | Keine Mehrfachauswahl im Papierkorb. Kopf rechts Rand-Knopf gemeinsam.papierkorb.leeren → Fenster .leerenFrage mit Knopf „Endgültig löschen“ (einzige Nachfrage, weil nicht umkehrbar; P Bedienregeln). |
| 5 | Wiederherstellen | geloescht_am leeren. Stelle: geloescht_am leeren genügt, der Fachzustand (Entwurf, pausiert, beendet) war nie verändert, sie steht wieder in ihrer Gruppe; Notiz: Text zurück ins Feld, steht inzwischen eine neue Notiz da, kommt der alte Text mit Datumszeile darunter; Job-Alarm: Zustand wie vorher (abbestellt bleibt abbestellt); Bewerbungsentwurf: wieder am Platz des Knopfes an der Stelle, sofern die Stelle noch bewerbbar ist (sonst fehler.bewerben.stelleWeg, der Eintrag bleibt) | Toast gemeinsam.papierkorb.wiederhergestellt, kein Rückgängig (der Weg zurück ist „Löschen“). |
| 6 | Endgültig löschen, leeren | Zeile löschen. Stelle mit abgeschlossenen Bewerbungen (offene verhindern das Löschen schon vorher): Zeile bleibt als zustand geloescht ohne Firmen-Sicht hinter ihren Bewerbungen, bis deren 6-Monats-Frist abgelaufen ist, dann weg (Bewerber sieht bis dahin den Titel ohne Link); Notiz, Alarm, Entwurf: sofort weg (ersetzte Lebenslauf-Dateien laufen ohne Papierkorb über dateien.loeschen_ab, 1.7 Nr. 3) | Toast gemeinsam.papierkorb.endgueltigOk ohne Rückgängig. Der Nachtlauf macht dasselbe nach papierkorb_tage (fristen.ts, H134). |
| 7 | Rechte und Datenschutz | Wer löschen darf, darf wiederherstellen und endgültig löschen (fachlich/rechte.ts); Recruiter sieht nur Notizen (Stellen löscht nur der Admin), Admin alles der Firma; Bewerber nur eigene Einträge (RLS wie die Ursprungstabellen) | Inhalte im Papierkorb zählen beim Datenexport (A05, F18) und bei den Löschfristen mit (eine Bewerbung läuft nicht länger, weil ihr Entwurf im Papierkorb liegt); Konto löschen (1.9 Nr. 8) und Firma löschen (1.13 Nr. 6) leeren den Papierkorb sofort. Protokoll (1a) schreibt papierkorb_wiederhergestellt und papierkorb_endgueltig mit Art und Kennung. |
1.18 Übersetzung der Stellenanzeigen (ohne eigene Seite; Hintergrund)
Zugesagt zum Livegang (Kundenliste: „Stellenanzeigen werden automatisch übersetzt“; Plan Sprachen: „beim Veröffentlichen und nach jeder Änderung im Hintergrund“; Karte 0 Teil 2: Azure, Europa-Rechenzentrum, Monatsgrenze). Tabelle stellen_ liegt seit 1a (Platzhalter), die Anzeige mit Hinweis und Umschalter seit 1a 1.3 (A7). Hier kommt der Dienst, die Hintergrundaufgabe und die Anzeige der echten Übersetzung dazu. Paket 2a.11a (), Annahme C33.
| Nr | Bereich | Was passiert | Hinweis | |
|---|---|---|---|---|
| 1 | Auslöser | Zeilen mit stand geprueft (gelieferte Fassung, z. B. COPLA-Englisch, Karte 3 1.13) werden nie auf wartet gesetzt; der COPLA-Abgleich schreibt en mit zustand fertig, stand geprueft. fachlich/: veroeffentlichen() und jede Änderung eines Textfeldes (titel, einleitung, aufgaben, brauchen, gut_nicht_noetig, bieten) einer Stelle im Zustand aktiv, pruefung oder nachbessern legt je freigegebener Sprache aus einstellungen. (ohne de) eine Zeile in stellen_ an oder setzt sie auf zustand wartet und quelle_; danach hintergrund. (pg-boss, Warteschlange uebersetzung, Parallelität 1, Verzögerung 2 Minuten, damit mehrere Änderungen kurz nacheinander nur einen Lauf auslösen). Kopieren, verlängern, erneut schalten lösen nichts aus (Text unverändert). | Nur, wenn einstellungen. und einstellungen. an sind (Karte 3 1.11 Nr. 1 und 3); sonst bleibt die Zeile bei nochNichtUebersetzt. | |
| 2 | Dienst | dienste/: `uebersetzen(texte: string[], von: 'de', nach: 'en' \ | 'tr') gegen Azure AI Translator (Text API 3.AZURE_REGION, Schlüssel AZURE_UEBERSETZER_SCHLUESSEL, Karte 0 Teil 4), HTML-Modus für die Listenfelder (textType=html, Absätze und <li> bleiben), Zeitlimit 20 s, Wiederholung bei 429/index.ts wählt den Dienst: azure, in Tests stummel (Übersetzung = „[en] “ + Text).zaehler_tag` („uebersetzung_zeichen“) für die Zustandsanzeige. | Keine Personendaten: nur die sechs Textfelder gehen hinaus (Ansprechperson, Adresse, Firma nicht); Offene Fragen R7. |
| 3 | Aufgabe | hintergrund/: liest alle Zeilen der Stelle mit zustand wartet, übersetzt die sechs Felder in einem Aufruf je Sprache, schreibt titel, einleitung, aufgaben, brauchen, gut_nicht_noetig, bieten, stand maschinell, uebersetzt_, zustand fertig, versuche. Fehler: zustand fehler, fehler_ (gekürzt, ohne Schlüssel), versuche + 1; nach dem dritten Fehler bleibt die Zeile auf fehler, Protokoll-Eintrag (dienste/protokoll, Art uebersetzung_), und einstellungen. zählt hoch. Erfolg setzt einstellungen.. | Ist der deutsche Text seit dem Start der Übersetzung erneut geändert (quelle_ neuer als beim Lesen), wird das Ergebnis verworfen und die Zeile bleibt wartet (nächster Lauf). | |
| 4 | Anzeige | 1a 1.3 zeigt in /en/ und /tr/ die Zeile mit zustand fertig: übersetzter Titel groß, deutscher Titel klein mit lang="de", Hinweis T gemeinsam.sprache.maschinell „Mit KI übersetzt. Verbindlich ist die deutsche Fassung.“ (1b 1.12, KI-Kennzeichnung), Umschalter T .deutschZeigen / .uebersetzungZeigen an Ort und Stelle (Gerätespeicher merkt die Wahl je Sitzung, H144); fehlt die Zeile oder ist sie wartet/fehler, deutscher Text mit T .nochNichtUebersetzt (unverändert seit 1a). Google: JSON-LD bleibt deutsch (inLanguage de), hreflang je Sprache (1a 1.3). Suche und Job-Alarm suchen weiter im deutschen Text (Plan: Begriffslisten der Fachbereiche). | stand geprueft (von Hand gegengelesen, Verwaltung) kommt mit 2b.5; bis dahin zeigt jede Übersetzung den Hinweis. | |
| 5 | Verwaltung | Karte 3 1.11 Nr. 3: Schalter „Anzeigen automatisch übersetzen“ (einstellungen.), Zustand „Letzte Übersetzung {zeit} · {n} Fehler · {zeichen} Zeichen diesen Monat“, Knopf „Übersetzung erneut starten“ (setzt alle Zeilen fehler auf wartet, reiht die Aufgabe je Stelle ein, fehler_); „Heute zu tun“ beim Super Admin: T verwaltung.heute.uebersetzung „Übersetzung von {anzahl} Anzeigen fehlgeschlagen.“ → Erneut starten (Karte 3 1.1 Nr. 1, T 7.3). Zählt in H119. | Schalter aus: laufende Aufgaben enden leer, vorhandene Übersetzungen bleiben sichtbar (Rückgängig-Toast mit Folgen-Satz wie Karte 3 1.11). | |
| 6 | Test | pruefung/ mit Stummel: Veröffentlichen legt zwei Zeilen wartet an; Lauf schreibt fertig mit Stummel-Text; Fehler im Stummel → fehler, versuche 1, Protokoll; Änderung während des Laufs → bleibt wartet; Schalter aus → keine Zeile. pruefung/ (1a) ergänzt: /tr/ zeigt übersetzten Titel, Hinweis und Umschalter; ohne Zeile den deutschen Text. Kein Aufruf des echten Dienstes im Test. | Prüfart Nachtlauf: Zustand (nach Fristen-Lauf; die Testadresse hat den Azure-Schlüssel aus Karte 0 Teil 2). |
Bausteinkatalog-Ergänzung (nur Neues gegenüber 1a/1b)
Wiederverwendbare Teile wie Konto-Menü, Postfach, Datei-Ablage, Papierkorb und Anmeldeschutz, die für diese Bereiche neu gebaut werden.
Dieser Abschnitt beschreibt nur die technische Umsetzung. Mit dem Schalter „Technische Angaben“ blenden Sie ihn ein.
Regel wie 1a/1b. CSS von B bleibt in stile/; Neues nur beim Baustein mit vorhandenen Werten. Die angemeldeten Bereiche nutzen dieselben Bausteine wie die öffentlichen Seiten (kein zweites Design).
2.1 Neue gemeinsame Bausteine
| Baustein (Ordner) | Dateien | Aus B: HTML | Aus B: CSS-Klassen | Aus B: app.js | Benutzt von |
|---|---|---|---|---|---|
| kontomenue/ | KontoMenue.tsx (Client: Knopf + Ausklapp, Wechsel Firma/Bewerber über Server-Aktion) | anmelden.html:60 (Ausklapp-Muster), firmen-bereich.html:103–113 („…“-Menü) | sprache__knopf (css:129), ausklapp (css:132), mehr-menue (css:634–635) | data-ausklapp-Logik js:259–300 (1a Sprachwahl) | Seitenrahmen 1a (angemeldet) |
| bereich/ | BereichKopf.tsx (h1 + höchstens ein Rand-Knopf, nur Firma „Neue Stelle“; U 4), UebersichtZeile.tsx („‹ Übersicht“ über der h1 jeder Unterseite), Reiter.tsx (Links mit aria-current, Zahl-Marke zahl-klein), BestaetigenZeile.tsx | mein-bereich.html:93–121, firmen-bereich.html:94–125 | bereich-kopf (css:622–625), reiter (626–629), zahl-klein (631), panel-kopf (661–662); die Kacheln uebersicht-raster/kachel (css:636–640) entfallen (U 3.5, 3.8) | reiter() mit data-zu-reiter js:356–383 entfällt (echte Adressen) | (konto)/layout, (firma)/layout |
| jetztwichtig/ | JetztWichtig.tsx (bis 5 Zeilen, je ein Satz und ein Knopf oder reine Information, nur der erste Knopf farbig, sechste Zeile „und {n} weitere“, Leer-Satz), zeilen.ts (Regeln Bewerber T 7.1, Firma T 7.2; Reihenfolge U 4) | neu, Optik box | box, btn-klein | Übersicht Bewerber, Übersicht Firma; ab 3 Verwaltung (T 7.3) | |
| ablage/ | Ablage.tsx (Client: Datei wählen, Kamera, Fortschritt, Fehler je Datei), verkleinern.ts (Client, N-2/C35: Bilder je Zweck verkleinern und neu kodieren, createImageBitmap + Canvas, Zielmaße lebenslauf 2.000 px JPG · logo 800 px · werbemotiv unverändert kodiert · ratgeberbild 1.600 px WebP; HEIC nur, wenn der Browser es dekodiert; schlägt die Verkleinerung fehl, geht die Originaldatei hoch und der Server entscheidet), pruefen.ts (Typ am Inhalt, Größe, Anzahl, Pixelmaße; Server und Client) | stelle.html:127–131 | ablage (css:549–552); Hinweis- und Dateizeile neu mit vorhandenen Werten | dateiGewaehlt() in kurzbewerbung() js:798 | Bewerben-Fenster, Lebenslauf (Datei), Firmenprofil (Logo), Postfach-Anhang |
| statuschip/ | StatusChip.tsx (Bewerbung Bewerber-/Firmensicht, Stelle Firmensicht, Einladung, Alarm; Wörter aus T 5.1, 5.4, 5.5) | Status-Marken in den B-Zeilen (js:1063, 1152, 1181) | status, status--neu, --gesichtet, --eingeladen, --absage, --aktiv, --laeuft, --archiv (css:648–656); fehlende Zustände neu mit vorhandenen Farben | STATUS-Tabelle in app.js (Wörter werden durch T ersetzt) | Listen und Details beider Bereiche |
| postfach/ | Verlauf.tsx (Client: Blasen, Eingabe, Anhang-Knopf nur Bewerber, Schreibschutz-Satz), nachricht.ts (Prüfung 4.000 Zeichen) | firmen-bereich.html:196–209 | chat (css:692), chat__liste (693), chat__verlauf (699), chat__kopf (700), chat__nachrichten (702), blase (703), chat__eingabe (706) | Chat-Demo in firmenBereich() js:1199 ff. | Bewerbung (Bewerber), Bewerbung (Firma), Postfach beider Seiten (Liste.tsx + Verlauf) |
| fenster/ | Fenster.tsx (natives <dialog> mit showModal(), Fokus beim Öffnen auf die Überschrift, beim Schließen zurück auf den Auslöser, aria-labelledby/aria-describedby, Hintergrund-Klick schließt nur ohne Eingabe; Kopf, Inhalt, Knopfzeile; Varianten bestätigen · mit Kennwort · mit Vorlage; U A.1) | stelle.html:103–112 (Dialog-Rahmen) | dialog__kopf (css:539), dialog__inhalt (542), fortschritt (543) | data-dialog-zu | Bewerben, Zurückziehen, Einladen/Absagen/Zusage, Konto löschen, Firma löschen, Stelle löschen, Faktor einrichten |
| auswahl/ | Auswahl.tsx (Client: Mehrfachauswahl mit Maus und Tastatur: Klick, Umschalt/Strg-Klick, Strg+A, Esc; Leiste unten mit Aktionen und „{n} ausgewählt“) | neu (P Auswählen) | neu: auswahl-leiste, ist-gewaehlt (gibt es in B nicht; nur vorhandene Farbwerte) | Stellen (Firma), Bewerbungen (Firma), Postfach beider Seiten („Als gelesen markieren“, G82); Merkliste erst, wenn gewünscht (1b W1) | |
| listenfeld/ | ListenFeld.tsx (Textfeld „ein Punkt je Zeile“ → text[]; Vorschau als ul) | firmen-bereich.html:176 (Textarea) | feld, feld-zeile (css:613) | Stellenformular (Aufgaben, Brauchen, Gut nicht nötig, Bieten) | |
| live/ | LiveClient.tsx (Abfrage alle 60 s über GET /; SSE erst 2b.9), typen.ts | neu | beide Bereiche (Layout), Reiter-Zahlen | ||
| zeitstrahl/ | Zeitstrahl.tsx (Bewerber T 5.2), Verlauf.tsx (Firma T 5.3) | neu | schritte (1b css:368–375 als Vorlage) | Bewerbung beide Sichten | |
| faktor/ | FaktorEinrichten.tsx (Client: Wahl App oder E-Mail-Code; App: QR + Geheimnis, Code, danach Wiederherstellungscodes mit „Codes als Datei speichern“; E-Mail: Code senden, Code, fertig ohne Wiederherstellungscodes, F3), CodeFeld.tsx (6 Ziffern, one-time-code), CodeErneut.tsx (Textlink mit 60-Sekunden-Sperre, nur Art mail) | neu, Felder wie anmelden.html:127–133 | formular, feld, passwort (css:614–616) | Anmelden/faktor, Einstellungen, Bewerben-Fenster (Code im Schritt 1), Verwaltung faktor-einrichten (nur App, Karte 3) | |
| kennwortbestaetigung/ | KennwortBestaetigen.tsx (Client: kleines Fenster T gemeinsam.kennwortBestaetigen.titel „Zur Sicherheit: Ihr Kennwort“, .text, Feld, .knopf „Weiter“; Server-Aktion kennwortBestaetigen(kennwort) setzt sitzungen.kennwort_bestaetigt_am; Konto ohne Kennwort (C36): dasselbe Fenster mit T .titelCode „Zur Sicherheit: Code an {mail} senden“, .textCode, Knopf .codeSenden, dann Code-Feld aus faktor/CodeFeld (A12 Fassung bestaetigen, faktorMail. Zweck bestaetigen) und codeBestaetigen(code), das dieselbe Spalte setzt; gilt 5 Minuten, danach fragt die nächste heikle Aktion erneut), mitKennwort(aktion) (Hülle, die eine Server-Aktion ablehnt, wenn kennwort_bestaetigt_am älter als 5 Minuten ist: fehler.kennwortBestaetigen.noetig) | neu (26.10., _ Nr. 9; Fenster-Rahmen aus fenster/) | dialog, formular, feld, passwort | Faktor abschalten, umstellen, Codes neu erzeugen (1.9 Nr. 4), Konto löschen (1.9 Nr. 8, ersetzt das Kennwortfeld im Fenster), Firma löschen (1.13), Verwaltung: Firma löschen, Bewerberkonto löschen, E-Mail-Adresse ändern (Karte 3 1.4) · H141 | |
| papierkorb/ | PapierkorbListe.tsx (Client: Zeilen mit Art-Chip, Name, „gelöscht {datum} · noch {m} Tage“, Knöpfe „Wiederherstellen“ und „Endgültig löschen“ je Zeile, keine Mehrfachauswahl (1.17, C18); Kopf-Knopf „Papierkorb leeren“ mit Fenster), PapierkorbLink.tsx (Textlink „Papierkorb ({n})“ unter einer Liste, nur bei n > 0) | firmen-bereich.html:140–149 (Zeilen-Optik), stelle.html:103–112 (Fenster) | zeile, status (Chip), btn-rand, btn-text, auswahl-leiste (aus auswahl/), Leerzustand 1a | /firma/papierkorb, /konto/papierkorb (1.17); Link unter Stellen (Firma), Job-Alarme, Bewerbungen (Bewerber); Konto-Menü |
Erweiterungen vorhandener Bausteine: seitenrahmen/ (1a) bekommt den Konto-Zustand (Anmelden-Knopf ↔ KontoMenue; „Stelle inserieren“ zielt für Firmennutzer auf /firma/stellen/neu); Stellenkarte. Variante „vorschau“ (Formular rechts) und „firma“ (Zeile in der Stellenliste mit Status-Chip); Fehlerseite. Fälle „gesperrt (Firma, Konto)“, „Rechte“; kontaktformular/ unverändert; stelle/ (1a) bindet _ ein und zeigt am Platz des Bewerben-Knopfes als Text „Beworben am {datum} · Stand ansehen“ bzw. „Sie haben hier eine Bewerbung angefangen. Weiter“ (U A.2) sowie die Firmen-Vorschau (?vorschau=, nur Firmennutzer der Firma und Verwaltungsrollen nomad/verwaltung, Karte 3 1.4 Nr. 3).
2.2 Fachlich und Dienste (neu)
| Ordner | Dateien | Inhalt |
|---|---|---|
| dienste/auth/ | better-auth.ts (Konfiguration: E-Mail + Kennwort, TOTP-Plugin, Sitzungen 30/14 Tage, „angemeldet bleiben“), sitzung.ts (sitzung() auf dem Server → {konto, firma?, rolle}, erforderlich(rolle)), kennwort.ts (Argon2id über Better Auth; Regel 10 bis 128 Zeichen, keine Zwangs-Sonderzeichen; Prüfung gegen dienste/ (100.000 Einträge, im Projekt, kein Dienst eines Dritten; Datei im Bau in ein Set geladen) und gegen E-Mail, Vorname, Nachname), geraete.ts (Sitzungen auflisten/beenden; Gerätekennung aus der Browser-Kennung; neuesGeraet(kontoId, kennung) prüft gegen konto_ der letzten 12 Monate und trägt die Kennung nach jeder erfolgreichen Anmeldung dort ein), anmeldungen.ts (anmeldungSchreiben({kontoId?, mail?, ip, geraet, ergebnis}), wartezeit(kontoId, ip) → Sekunden aus den Fehlversuchen der letzten 15 Minuten: ab 5 Fehlversuchen 60 s, je weiterem verdoppelt, höchstens 900 s), ip.ts (echte IP aus X-Forwarded-For, nur wenn die Anfrage von einem Host aus VERTRAUTE_ kommt, sonst die Verbindungs-IP; Karte 0 Teil 4), faktorMail.ts (Code erzeugen, senden über A12, prüfen, 3 je 15 Minuten) | Better Auth mit Drizzle-Adapter; Tabellen in Teil 3. Verwaltungs-Rollen erst Abschnitt 3 (Faktor-Pflicht dort erzwungen, nur App). Sicherheits-Prüfliste _ Nr. 9 bis 13. |
| fachlich/konto/ | anlegen.ts (kontoAnlegen von der Seite Registrieren mit Kennwort und B01; kontoAnlegenMitCode aus dem Bewerben-Fenster ohne Kennwort, bestaetigt_am sofort, C36; bestätigen per POST der Zielseite, erneut senden), felder.ts, loeschen.ts, export.ts (ZIP), einstellungen.ts (Benachrichtigungen, Sprache), faktor.ts (einrichten, prüfen, Codes, abschalten), kennwortSetzen.ts (erstes Kennwort für Konten ohne Kennwort, 1.9 Nr. 3), token.ts (Hash, Zwecke: bestaetigen, kennwort, einladung, export, sichern) | |
| fachlich/bewerbung/ | anlegen.ts (bewerbungSenden; Entwurf → Bewerbung; Zustände; Einwilligung), entwurf.ts (bewerbungsEntwurfSpeichern/lesen; verwerfen legt in den Papierkorb 1.17; stiller Verfall 7 Tage), status.ts (gesichtet beim Öffnen durch Firmennutzer; einladen, zusage, absage mit Nachricht; zurueckziehen mit Rückgängig-Frist = verzögerte Ausführung; erste Einladung, Zusage, Absage oder Nachricht der Firma setzt erste_antwort_am), liste.ts (bewerbungenBewerber, bewerbungenFirma mit Filtern), notizen.ts, felder.ts (Typ, Status je Sicht) | Verzögerte Aktionen (Rückgängig) laufen über dienste/ (pg-boss-Job mit fester Frist einstellungen.fristen.rueckgaengig_sekunden, Standard 10, Karte 3 D23; abbrechbar; der Auftrag trägt Konto, Firma und Rolle des Auslösers und prüft darf() beim Ausführen erneut, bricht still ab, wenn die Bewerbung inzwischen zurückgezogen, die Firma gesperrt oder die Person entfernt ist; End-Check Befund 9) statt im Browser (so wirkt Rückgängig auch nach Tab-Wechsel, Annahme C6). |
| fachlich/einladung/ | anlegen.ts (Termin, Ort/Link, Ansprechperson; ICS erzeugen), antworten.ts (zusagen, andererTermin, absagen → Nachricht + F05), ics.ts (RFC 5545, Europe/Berlin), erinnerung.ts (Vortag, Hintergrund) | |
| fachlich/nachricht/ | senden.ts (Bewerber ↔ Firma, Schreibschutz-Regeln), lesen.ts (gelesen_am je Sicht, ungelesen-Zähler Firma gemeinsam), liste.ts (Postfach beide) | |
| fachlich/stelle/ | ergänzt: schreiben.ts (entwurfSpeichern je Feld, veroeffentlichen mit Prüfung, kopieren, beenden mit Rückgängig, verlaengern, erneutSchalten, loeschen), rechte.ts (Rolle × Handlung, P Rechte), vorschau.ts (Stelle für die Firma vor Veröffentlichung), ablauf.ts (Hintergrund: laeuft_ab-Mail, abgelaufen = pausiert ohne Frist, offene Bewerbungen pausierter Stellen nach 6 Monaten abschließen; die Stelle selbst bleibt) | 1a abfragen.ts bleibt. |
| fachlich/papierkorb/ | liste.ts (Einträge je Bereich: Firma aus stellen und bewerbungs_notizen, Bewerber aus job_alarme und bewerbungs_entwuerfe, je geloescht_am gesetzt; ersetzte Lebenslauf-Dateien nie, 1.7 Nr. 3), loeschen.ts (in den Papierkorb legen: geloescht_am, geloescht_von; verzögert über dienste/verzoegert.ts für Rückgängig), wiederherstellen.ts (geloescht_am leeren, Folgen je Art nach 1.17 Nr. 5), endgueltig.ts (Zeile löschen; Stelle mit Bewerbungen bleibt als zustand geloescht hinter ihren Bewerbungen bis zu deren Frist; Datei erst, wenn keine Bewerbung mehr auf sie zeigt), leeren.ts (alle Einträge des Bereichs endgültig) | Rechte: wer löschen darf, darf wiederherstellen und endgültig löschen (fachlich/rechte.ts); fristen.ts ruft endgueltig.ts nach papierkorb_tage. |
| fachlich/firma/ | ergänzt: registrieren.ts, profil-schreiben.ts (Feld sofort), logo.ts, team.ts (einladen, annehmen, rolle, entfernen mit Übernahme der Stellen, faktorPflicht), loeschen.ts (Firma löschen: Stellen, Bewerbungen, Nutzer, F18), rechte.ts (gemeinsam mit stelle/rechte.ts: eine Tabelle rolle × handlung) | |
| fachlich/datei/ | hochladen.ts (Stream auf verschlüsselten Datenträger, Typ am Inhalt, Größe und Pixelmaße je Zweck prüfen, bei JPG die Metadaten-Segmente ohne Neukodierung entfernen; kein Verkleinern auf dem Server (N-2, C35); einziger Rückfall: HEIC → JPG mit Verkleinerung, nur für Zweck lebenslauf, nur wenn der Browser es nicht konnte, höchstens 3 je Konto und Tag), pruefen.ts (ClamAV-Anbindung, Zustand geprueft/gesperrt), ausliefern.ts (Rechte: Eigentümer, Firma der Bewerbung, Verwaltung mit Grund; dazu der Fall „öffentlich“ ohne Sitzung, nur für geprüfte Dateien dieser Zwecke: logo (geprüft genügt), werbemotiv einer Kampagne im Zustand geplant oder laeuft, ratgeberbild eines veröffentlichten Inhalts (Zwecke aus Karte 3); alles andere nie öffentlich), loeschen.ts | Virenprüfung gestört → Datei bleibt gesperrt (P Dateien). |
| fachlich/zaehler/ | ungelesen.ts (Zähler aus den Fachtabellen: neue Bewerbungen, ungelesene Nachrichten; gelesen beim Seitenwechsel und alle 60 Sekunden, kein Dauer-Strom, Live-Strom erst 2b.9) | |
| fachlich/rechte.ts | darf(sitzung, handlung, ding): jede Aktion und jede Seite prüft selbst (P Sicherheit, doppelt mit RLS) | Tabelle Rolle × Handlung in Teil 4. |
| dienste/db/rls.ts | Rollen und Rechte nach Karte 0 Teil 7 (einzige Quelle: bululu_, _, _, _, _); hier nur SET LOCAL app. in der Transaktion der Anfrage auf dem Pool der Rolle (dienste/, ein Pool je Rolle); Policies je Tabelle (Teil 3) | eigene Datei db/; Test rls.test.ts: zwei Anfragen nacheinander auf demselben Pool erben nichts voneinander |
| dienste/mail/vorlagen/ | b01, b05, b07–b14 (Bewerber; B02 bis B04 entfallen, C36; B06 ist bewusst keine Mail; B15–B17 Job-Alarm aus 1b, B18/B19 mit Abschnitt 3), a01–a03, a05–a07, a09 (Konto; A04/A08 mit Abschnitt 3), f01–f09, f18–f21 (Firma; F10–F17 kommen mit Abschnitt 3) als React-E-Mail mit Text-Fassung, ICS-Anhang bei Einladung; versand-regel.ts (Benachrichtigungs-Einstellung je Konto, „immer“-Arten) | Nummern nach T 6.2–6.4; Sammelmail „neue Bewerbungen täglich“ als Hintergrund-Aufgabe |
| dienste/verzoegert.ts | verzögerte Jobs (Rückgängig); dienste/sse.ts erst 2b.9 | |
| hintergrund/aufgaben/ | konto-unbestaetigt.ts (unbestätigte Konten von der Seite Registrieren ohne Bewerbung nach 30 Tagen löschen; keine B01 aus dem Bewerben-Fenster mehr, C36), stellen-ablauf.ts (F08 5 Tage vorher, F09 abgelaufen = pausiert; offene Bewerbungen auf Stellen, die seit einstellungen.fristen.pausiert_abschluss_monate (6) abgelaufen sind, abschließen mit B14, 14 Tage davor Zeile in „Heute zu tun“; die Stelle selbst bleibt pausiert), bewerbungen-sammel.ts (F04 täglich um einstellungen.job_alarm_versandzeit (07:00, 1b) gesammelt für Nutzer mit Einstellung „täglich“), einladung-erinnerung.ts (B09 am Vortag eines zugesagten Gesprächs), merkliste-ablauf.ts (B13 genau am Tag „laeuft_bis minus einstellungen.fristen.ablauf_mail_tage“ (5, wie F08), nur wenn keine Bewerbung des Kontos auf die Stelle besteht; einmal je Eintrag über merkliste_konto.erinnert_am, mehrere Stellen desselben Kontos am selben Tag in einer Mail), fristen.ts (Bewerbungen 6 Monate nach Abschluss, Konten 24 Monate ohne Anmeldung: A07 + 3 Monate, Papierkorb-Einträge von Firma und Bewerber nach einstellungen.fristen.papierkorb_tage (30, Karte 3) endgültig über fachlich/papierkorb/endgueltig.ts), datenexport.ts (A05) | pg-boss wie 1a |
| dienste/uebersetzung/ | azure.ts (Azure AI Translator, HTML-Modus, Zeitlimit, Zeichenzählung), stummel.ts (Tests), index.ts (wählt nach Umgebung) | 1.18 Nr. 2; Schlüssel aus Karte 0 Teil 4; nur die sechs Textfelder der Stelle, keine Personendaten |
| hintergrund/aufgaben/stellen-uebersetzen.ts | Warteschlange uebersetzung, Parallelität 1, Verzögerung 2 Minuten, 3 Versuche mit Rückzug; schreibt stellen_uebersetzungen, einstellungen.uebersetzung.letzte_am / .fehler_anzahl; Protokoll bei Fehler | 1.18 Nr. 3; Auslöser in fachlich/stelle/schreiben.ts |
| sprachen/{de,en,tr}/ | anmelden.json, bewerben.json, konto.json, firma.json, status.json, mail-*.json | Schlüssel aus T 1.4, 1.6, 1.7, 1.8, 2, 3, 4, 5, 6, 7.1, 7.2 |
2.3 Nur in 2a (seitenspezifisch)
| Ort | Dateien |
|---|---|
| (oeffentlich)/anmelden/page.tsx · _formular/Anmelden.tsx · Registrieren.tsx · FirmaRegistrieren.tsx (alle Client) · kennwort/page.tsx · kennwort-neu/page.tsx · faktor/page.tsx | |
| (oeffentlich)/konto/bestaetigt/page.tsx · (oeffentlich)/einladung/page.tsx | Zielseiten aus Mails |
| (oeffentlich)/stelle/[adresse]/_bewerben/BewerbenDialog.tsx · Schritt1.tsx · Schritt2.tsx · Schritt3.tsx · Erfolg.tsx · EntwurfZeile.tsx · (oeffentlich)/stelle/[adresse]/bewerben/page.tsx (ohne JS) | |
| (konto)/layout.tsx · mein-bereich/page.tsx · _uebersicht/IhreBewerbungen.tsx · Gemerkt.tsx · bewerbungen/page.tsx · _liste/BewerbungenListe.tsx · Filter.tsx · bewerbungen/[id]/page.tsx · _bewerbung/Kopf.tsx · Einladung.tsx (Client) · Unterlagen.tsx · Zurueckziehen.tsx (Client) · AbsageAehnliche.tsx · postfach/page.tsx · postfach/[bewerbungId]/page.tsx · lebenslauf/page.tsx · _lebenslauf/Persoenliches.tsx (Client) · Datei.tsx (Client) · job-alarme/page.tsx · _alarme/AlarmListe.tsx · AlarmNeu.tsx | |
| (konto)/konto/einstellungen/page.tsx · _einstellungen/Benachrichtigungen.tsx · Bedienung.tsx · Kennwort.tsx · Faktor.tsx · Geraete.tsx · Einwilligungen.tsx · Export.tsx · Loeschen.tsx (Client je Karte) | |
| (firma)/layout.tsx · firma/page.tsx · _uebersicht/IhreStellen.tsx · ErsteSchritte.tsx · stellen/page.tsx · _liste/StellenListe.tsx (Client, Auswahl, Gruppen) · ZeilenMenue.tsx · stellen/[id]/page.tsx · _stelle/Kopfreihe.tsx · stellen/neu/page.tsx · stellen/[id]/bearbeiten/page.tsx · _formular/StellenFormular.tsx (Client) · Vorschau.tsx · Ansprechperson.tsx · bewerbungen/page.tsx · _liste/BewerbungenFirma.tsx (Client, Auswahl) · bewerbungen/[id]/page.tsx · _bewerbung/Kopf.tsx · Knoepfe.tsx (Client, Fenster mit Vorlage) · Verlauf.tsx · Unterlagen.tsx · Notizen.tsx (Client) · VorherigeNaechste.tsx · postfach/page.tsx · postfach/[bewerbungId]/page.tsx · profil/page.tsx · _profil/Logo.tsx · Stammdaten.tsx · UeberUns.tsx · Ansprechperson.tsx · FirmaLoeschen.tsx · team/page.tsx · _team/Liste.tsx · Einladen.tsx · FaktorPflicht.tsx | |
| app/api/live/route.ts · app/api/datei/[id]/route.ts · app/api/kalender/[id].ics/route.ts · app/api/auth/[...all]/route.ts (Better Auth) | |
| db/migrationen/0003_konten.sql + rueckweg · 0003_rechte.sql (RLS) · musterdaten/konten.ts · bewerbungen.ts · firmen-nutzer.ts · nachrichten.ts |
Nicht übernommen aus B (bewusst): Reiter „Übersicht“, „Neue Stelle“, „Einstellungen“ als Reiter (P Menüs); „…“-Menü mit Rechnungen, Statistiken, Pakete (gibt es nicht); Premium-Band mit „Pakete ansehen“ (firmen-bereich.html:134–137); Import-Zeile „Link übernehmen“ (:158–163); KI-Knopf (:175, 2b); Rollen-Radios auf Anmelden (:112–120); Deckblatt-Wahl, Mappe-PDF, Stationen (mein-bereich.html:165–180, 2b); Haken „Betriebe dürfen mich ansprechen“ (:190, kommt als Schalter mit; Status-Select in der Bewerber-Zeile (Aktionen im Detail, P); Inline-Styles (Klassen).
Datenmodell-Ergänzung
Was Bululu zu Konten, Bewerbungen, Nachrichten, Einladungen, Dateien und Teams speichert und wer was sehen darf.
Dieser Abschnitt beschreibt nur die technische Umsetzung. Mit dem Schalter „Technische Angaben“ blenden Sie ihn ein.
Migration db/ (+ Rückweg) und 0003_ (RLS-Policies). Regeln wie 1a/1b (UUID v7, angelegt_am/geaendert_am, echte Felder). Better Auth bringt eigene Tabellen (user, session, account, verification, twoFactor); sie werden über den Drizzle-Adapter auf die hier genannten Namen abgebildet (konten, sitzungen, konto_zugang, konto_tokens, faktor); abweichende Pflichtspalten von Better Auth bleiben zusätzlich (Annahme C7). konto_zugang: id, konto_id FK (cascade), anbieter text (zum Livegang nur „credential“), anbieter_konto_id text, kennwort_hash text leer (leer bei Konten ohne Kennwort, C36), angelegt_am, geaendert_am; eindeutig (anbieter, anbieter_konto_id). Das Probe-Paket 1a.2a bestätigt die Abbildung, bevor 2a.1 sie anlegt.
konten
| Feld | Typ | Hinweis |
|---|---|---|
| id | uuid PK | |
| citext, eindeutig | ||
| bestaetigt_am | timestamptz, leer | leer = unbestätigt |
| anrede | enum anrede: herr, frau, ohne; Standard ohne | für die Ansprechperson einer Stelle bei der Bundesagentur (Salutation); im Konto freiwillig |
| vorname, nachname | text, je ≤ 30 | Name für Begrüßung, Bewerbung, Team; Nachname ist bei der Bundesagentur Pflicht |
| telefon | text, leer | Bewerbung liest hier (P Mappe) |
| wohnort, plz_id | text, FK plz, leer | Lebenslauf Persönliches |
| sprache | text (de/en/tr) | Mails und Bereich |
| kennwort_hash | text, leer erlaubt | Argon2id (Better Auth); leer bei Konten aus dem Bewerben-Fenster (C36): Anmelden dann per Code an die E-Mail (A12, Zweck anmelden), bis die Person in den Einstellungen ein Kennwort setzt |
| faktor_aktiv | boolean, Standard false | zweiter Faktor eingerichtet, Art in faktor. (app oder mail, 1.9 Nr. 4); Geheimnis und Codes in faktor |
| lebenslauf_datei_id | uuid FK dateien, leer | Lebenslauf in „Meine Unterlagen“; weitere Unterlagen sind dateien mit konto_id, zweck anhang, unterlage_art (zeugnis, zertifikat, fuehrerschein, sonstiges) und ohne bewerbung_id |
| sichtbar_fuer_betriebe | boolean, Standard true | Profil für Betriebe und Ansprache; ohne Wirkung und ohne Oberfläche, bis 3BS mit Paket A4 funktionen. einschaltet |
| zustand | enum konto_zustand: aktiv, gesperrt, geloescht | „unbestätigt“ ist kein Zustand, sondern bestaetigt_am leer; Entsperren setzt aktiv, bestaetigt_am bleibt, wie es war; gesperrt/entsperrt durch Verwaltung (3) mit sperr_grund |
| sperr_grund | text, leer | |
| letzte_anmeldung_am | timestamptz, leer | Frist 24 Monate |
| geloescht_am | timestamptz, leer | anonymisiert: mail → „geloescht-{id}“, Name leer |
| Index | (mail); (zustand, letzte_anmeldung_am) |
konto_geraete: konto_id FK, kennung text (Browser-Name · Betriebssystem-Name, ohne Fassung, ohne IP), zuletzt_am timestamptz; Schlüssel (konto_id, kennung); geschrieben bei jeder erfolgreichen Anmeldung, gelesen von neuesGeraet() für Mail A13; Nachtlauf löscht Zeilen älter als einstellungen.fristen.geraete_monate (12); RLS wie konten; Konto löschen räumt sie mit.
sitzungen: id, konto_id FK, token_hash eindeutig, firma_id FK firmen leer (gewählte Firma), geraet text (Browser-Kennung, keine IP), anmeldung_id FK anmeldungen leer (die Anmeldung, aus der die Sitzung entstand; liefert der Geräte-Liste die gekürzte IP; bleibt leer, wenn die Zeile nach 30 Tagen gelöscht ist), kennwort_bestaetigt_am timestamptz leer (erneute Kennworteingabe, 5 Minuten, H141), laeuft_ab_am (30 Tage Bewerber-Sicht, 14 Tage sobald firma_id gesetzt), zuletzt_genutzt_am, faktor_bestaetigt boolean. Index (konto_id), (laeuft_ab_am).
faktor: konto_id PK, art enum faktor_art (app, mail; 26.10.), geheimnis_verschluesselt text leer (nur app), eingerichtet_am, codes_hash text[] (10 Wiederherstellungscodes, je Hash, verbraucht = entfernt), letzter_code_zeitpunkt (Wiederverwendung sperren, nur app).
faktor_mail_codes: id, zweck enum code_zweck, mail text (kleingeschrieben, Pflicht), konto_id FK leer (leer bei zweck bewerben, solange es noch kein Konto gibt), entwurf jsonb leer (nur bei bewerben: Vorname, Nachname, Zustimmung mit Textfassung und Zeit aus Schritt 1; wird beim richtigen Code zum Konto und zur Einwilligung, dann geleert), code_hash text, laeuft_ab_am (+10 Minuten), genutzt_am leer, fehlversuche smallint Standard 0 (5 → Code ungültig), angelegt_am; Index (mail, angelegt_am). Höchstens 3 Zeilen je Adresse und 15 Minuten (Bremse je Adresse, nicht je Konto; Prüfung im Code). Zeilen älter als 1 Stunde löscht fristen.ts, mit ihnen den Entwurf.
anmeldungen: id, konto_id FK leer (unbekannte Adresse: leer), mail_hash text leer (nur bei unbekannter Adresse, für die Bremse je Adresse), ip inet, geraet text (Browser und Betriebssystem grob, aus der Browser-Kennung), ergebnis enum anmelde_ergebnis (erfolg, kennwort_falsch, faktor_falsch, gebremst, gesperrt, neues_geraet), zeitpunkt timestamptz. Index (konto_id, zeitpunkt), (ip, zeitpunkt). 30 Tage (einstellungen.fristen.anmeldungen_tage, Karte 3 1.14), kein Export in „Meine Daten“ außer den eigenen Zeilen (Konto-Bezug). Lesen: die Person über die Geräte-Liste (gekürzte IP), die Verwaltung je Firma und Konto (Karte 3 1.16), der Alarm-Lauf, die Bremse, der Haken „auch IP-Adressen sperren“. RLS: die Konto-Rolle liest nur eigene Zeilen, schreibt nie direkt; dienste/ schreibt beim Anmelden über die Datenbank-Funktion anmeldung_ mit der Rolle bululu_ (Karte 0 Teil 7 „Schreiben ohne Anmeldung“).
konto_tokens: id, konto_id FK, zweck enum token_zweck (bestaetigen, kennwort, export, adresse_neu, sichern), token_hash eindeutig, wert text leer (neue Adresse), laeuft_ab_am, genutzt_am. Bestätigen 7 Tage, Kennwort 60 Minuten, Export 24 Stunden, Sichern 24 Stunden (A13).
einwilligungen: id, konto_id FK, art enum einwilligung_art (nutzung, weitergabe; die Sichtbarkeit für Betriebe ist ein Schalter, keine Einwilligung,, bezug_id uuid leer (Bewerbung bei weitergabe), textfassung_id uuid FK inhalte_fassungen_historie leer (Rechtstext-Fassung, Tabelle aus Karte 3; leer, solange der Text aus dem Einspielskript 1b stammt), textfassung text (Schlüssel des Rechtstexts + Stand-Datum, immer gefüllt), erteilt_am, widerrufen_am leer. Index (konto_id, art).
benachrichtigungen: konto_id FK, art enum benachr_art (nachricht = bnNachricht/fnNachricht, status = bnStand, merkliste_ablauf = bnMerkliste, bewerbung_neu = fnBewerbung mit takt, ablauf = fnAblauf für F08 und F09, premium = fnPremium; genau die Schalter aus T 1.7/6.4), an boolean, takt enum (sofort, taeglich) nur bei bewerbung_neu; PK (konto_id, art). Fehlende Zeile = an. Der Job-Alarm-Takt liegt in job_alarme.takt (1b), nicht hier.
firmen (ergänzt): ansprechperson_id uuid FK konten leer, recruiter_darf_ansprechen boolean Standard true, bieten text[] leer („Das bieten wir“ als Vorlage für neue Stellen, 1.13 Nr. 3), faktor_pflicht boolean Standard false, logo_datei_id bekommt den FK dateien (1a Platzhalter), bestaetigt_am (Mail-Bestätigung des ersten Admins; Kopie aus konten für Abfragen), geloescht_am.
firmen_nutzer: id, firma_id FK, konto_id FK, rolle enum firma_rolle (admin, recruiter), zustand enum (aktiv, entfernt), telefon_in_anzeigen boolean Standard false (Haken „Telefon in Anzeigen zeigen“, 1.14; 1a Arbeitgeber-Kasten liest ihn für die Ansprechperson der Stelle), eingeladen_von FK konten leer, beigetreten_am, entfernt_am. UNIQUE (firma_id, konto_id). Letzter Admin: Prüfung im Code + Trigger.
firmen_einladungen: id, firma_id FK, vorname, nachname (je ≤ 30, vom Admin eingetragen, werden beim Anlegen des Kontos übernommen), mail citext, rolle, token_hash eindeutig, eingeladen_von FK, laeuft_ab_am (7 Tage), angenommen_am leer, zurueckgezogen_am leer. Index (firma_id, mail).
stellen (ergänzt): ansprechperson_id bekommt den FK konten (Annahme C8), erstellt_von FK konten, geaendert_von, beendet_am, verlaengert_am, geloescht_am timestamptz leer (im Papierkorb, Lesen filtert; 1.17), geloescht_von FK konten leer, kopie_von FK stellen leer; die Rückfall-Felder ansprech_anrede/-vorname/-nachname/-telefon (1a Teil 3) bleiben für Stellen ohne Konto-Ansprechperson (Schnittstelle, Import); Stellen aus dem Formular füllen nur ansprechperson_id, Telefon kommt aus konten.telefon und erscheint nur mit firmen_nutzer.telefon_in_anzeigen (1a A21).
stellen_uebersetzungen (ergänzt, 1.18; Tabelle aus 1a Teil 3 mit titel, einleitung, aufgaben, brauchen, gut_nicht_noetig, bieten, stand, quelle_geaendert_am): zustand enum uebersetzung_zustand (wartet, fertig, fehler; Standard wartet), versuche smallint Standard 0, fehler_text text leer, uebersetzt_am timestamptz leer; Index (zustand) für den Lauf. Lesen in 1a abfragen. liefert nur zustand fertig. Löschfrist: Zeilen fallen mit der Stelle (FK on delete cascade, Karte 3 Fristen unverändert).
bewerbungs_entwuerfe: id, konto_id FK, stelle_id FK, telefon, nachricht, datei_ids uuid[], schritt smallint, angelegt_am, geaendert_am, geloescht_am leer (Papierkorb nach „Verwerfen“, 1.17); UNIQUE (konto_id, stelle_id); stiller Verfall nach 7 Tagen ohne Änderung löscht endgültig (Hintergrund), Einträge im Papierkorb erst nach papierkorb_tage.
bewerbungen
| Feld | Typ | Hinweis |
|---|---|---|
| id | uuid PK | |
| konto_id | FK konten | bleibt nach Kontolöschung (anonymisiertes Konto) |
| stelle_id, firma_id | FK | firma_id Kopie für RLS und Listen |
| zustand | enum bewerbung_zustand: neu, gesichtet, eingeladen, zusage, absage, zurueckgezogen, stelle_beendet, geloescht | T 5.1 übersetzt je Sicht; einen Zustand „wartet auf Bestätigung“ oder „verfallen“ gibt es nicht, weil der Code im Bewerben-Fenster die Adresse vor dem Senden bestätigt (C36) |
| name_stand, mail_stand, telefon_stand | text | Momentaufnahme beim Absenden (P Mappe: Kontaktzeile zeigt „aktuelle Nummer“, wenn konten.telefon abweicht) |
| nachricht | text, leer | an den Betrieb |
| quelle | enum quelle (1a Teil 3): direkt, google, job_alarm, merkliste, folgen, geteilt, unbekannt | Herkunft der Bewerbung für die Arbeitgeber-Statistik nach dem Livegang: aus dem Adress-Parameter von der Stellenseite, den das Bewerben-Fenster beim Öffnen liest (ohne JS als verstecktes Feld der Seite /bewerben); ohne Parameter direkt. Kein Cookie, keine IP, kein Referrer |
| gesendet_am | timestamptz | |
| bestaetigt_am | timestamptz, leer | Mail-Bestätigung → zustand neu, B05 an den Bewerber, F03/F04 an die Firma |
| geoeffnet_am, geoeffnet_von | timestamptz, FK konten, leer | erstes Öffnen durch Firmennutzer (nie Verwaltung) |
| erste_antwort_am | timestamptz, leer | erste Einladung, Zusage, Absage oder Nachricht der Firma; für „wartet seit {n} Tagen“ und die Antwortzeit (U C.2, U D) |
| entschieden_am | timestamptz, leer | Zusage/Absage/Rückzug/beendet |
| abgeschlossen_am | timestamptz, leer | Start der 6-Monats-Frist |
| ungelesen_firma, ungelesen_bewerber | smallint | Zähler aus nachrichten (gepflegt per Trigger) |
| letzte_aenderung_am | timestamptz | Sortierung |
| Indizes | (firma_id, zustand, letzte_aenderung_am desc); (konto_id, letzte_aenderung_am desc); (stelle_id, zustand); UNIQUE (konto_id, stelle_id) wo zustand not in (zurueckgezogen) (G60) |
bewerbung_dateien: bewerbung_id FK, datei_id FK, reihenfolge; PK (bewerbung_id, datei_id).
bewerbungs_antworten: bewerbung_id FK, frage_id FK stellen_fragen, antwort_ja boolean leer, antwort_text text leer (≤ 500); PK (bewerbung_id, frage_id). Zum Livegang schreibt niemand hinein; RLS wie bewerbungen; Export und Löschfrist hängen an der Bewerbung.
bewerbungs_notizen: id, bewerbung_id FK UNIQUE (eine Notiz je Bewerbung, U 3.10), firma_id (Kopie), geaendert_von FK konten, text (2.000), angelegt_am, geaendert_am, geloescht_am leer (Papierkorb, 1.17), geloescht_von FK konten leer.
nachrichten: id, bewerbung_id FK, firma_id (Kopie), von enum (bewerber, firma), von_konto_id FK, text (4.000), datei_id FK leer (nur bewerber), gesendet_am, gelesen_am leer (Gegenseite; Firma gemeinsam), art enum (nachricht, system) (system = Statuswechsel-Zeilen im Verlauf). Index (bewerbung_id, gesendet_am).
einladungen: id, bewerbung_id FK, firma_id, termin_am timestamptz, dauer_min smallint Standard 60, ort text leer, online_link text leer, ansprechperson_id FK konten, nachricht_id FK nachrichten, zustand enum einladung_zustand (gesendet, zugesagt, abgesagt, neuer_termin, ersetzt), antwort_text leer, beantwortet_am leer, erinnert_am leer. Index (bewerbung_id), (termin_am) für Erinnerung.
dateien: id, konto_id FK leer (Eigentümer; Pflicht bei lebenslauf, bewerbung, anhang, logo; leer bei Dateien ohne Konto aus Karte 3: werbemotiv eines Werbekunden, zertifikat, ratgeberbild der Verwaltung), firma_id FK leer (Logo), zweck enum datei_zweck (lebenslauf, bewerbung, anhang, logo; Karte 3 ergänzt werbemotiv, zertifikat, ratgeberbild), unterlage_art enum leer (zeugnis, zertifikat, fuehrerschein, sonstiges; nur bei zweck anhang in „Meine Unterlagen“,, name_original, typ (erkannt), groesse_bytes, pfad text (verschlüsselter Datenträger, kein Pfad unter /public; Auslieferung nur über /api/datei/[id] und ausliefern.ts, öffentlich allein im dort beschriebenen Fall „öffentlich“), zustand enum datei_zustand (hochgeladen, geprueft, gesperrt, geloescht), geprueft_am, loeschen_ab date leer (ersetzte Lebenslauf-Datei nach der Rückgängig-Frist, 1.7 Nr. 3; Datei ohne Bewerbungsverweis: Ende der Frist, sonst Ende der letzten Bewerbungsfrist); kein geloescht_am: Dateien liegen nie im Papierkorb. Regel für die drei Lösch-Kennzeichen: zustand geloescht setzt nur der Fristen-Lauf beim physischen Löschen, loeschen_ab plant es, geloescht_am gibt es hier nicht. Index (konto_id, zweck), (zustand).
ereignisse (Live, erst 2b.9, nicht in 0003): id bigserial, zeitpunkt, konto_id leer, firma_id leer, art enum (bewerbung, nachricht, einladung, stelle), ding_id, daten jsonb (nur Anzeige-Felder: Titel, Name, Zustand; nie gefiltert, nur für den Strom). 24 Stunden, danach gelöscht. Index (konto_id, id), (firma_id, id).
merkliste_konto (1b angekündigt): konto_id FK, stelle_id FK, gemerkt_am, erinnert_am timestamptz leer (B13 gesendet); PK (konto_id, stelle_id).
job_alarme (1b): konto_id wird beim Anmelden gefüllt (Mail gleich), takt „keine“ nur mit konto_id (bereits 1b). Ergänzt: geloescht_am leer (Papierkorb nach „Löschen“ im Konto, 1.17); Versand (B15) und Listen lesen nur Zeilen ohne geloescht_am.
protokoll (1a): ab 2a geschrieben für: Faktor ein/aus/umgestellt (Art), Kennwort geändert (auch über „Konto sichern“), Konto gesichert (A13-Link genutzt), Konto gelöscht, Firma gelöscht, Nutzer entfernt, Stelle veröffentlicht/beendet/gelöscht (Papierkorb), Papierkorb wiederhergestellt/endgültig/geleert (Art und Kennung), Datei geöffnet (nur Verwaltung mit Grund, Abschnitt 3), Einwilligung erteilt/widerrufen.
einstellungen (ergänzt): fristen {bewerbung_monate: 6, konto_inaktiv_monate: 24, konto_inaktiv_nachfrist_monate: 3, entwurf_tage: 7, konto_unbestaetigt_tage: 30, einladung_team_tage: 7, pausiert_abschluss_monate: 6 (offene Bewerbungen auf einer pausierten Stelle abschließen, 1.11 Nr. 4); bewerbung_ohne_antwort_monate: 6; papierkorb_tage: 30 kommt aus Karte 3 und gilt auch für Firma und Bewerber}, sitzung {bewerber_tage: 30, firma_tage: 14; Karte 3 ergänzt verwaltung_stunden: 8}, funktionen (1a) um lebenslaufBaukasten: false, mappePdf: false, kiTexte: false, uebersetzung: true (zugesagt zum Livegang, 1.18; ohne AZURE_ bleiben die Zeilen auf wartet und die Seite zeigt den deutschen Text); uebersetzung {anzeigen_automatisch: true, letzte_am: null, fehler_anzahl: 0} (Karte 3 1.11 Nr. 3 zeigt und schaltet sie).
RLS (0003_rechte.sql): Rollen nach Karte 0 Teil 7 (einzige Quelle); hier die Policies der Konto-Rolle bululu_: je Anfrage SET LOCAL app. und app. (gewählte Firma, nur wenn firmen_nutzer aktiv), im Support-Modus zusätzlich app. (Karte 3 1.5). Policies: konten (eigene Zeile), sitzungen/faktor/konto_tokens/einwilligungen/benachrichtigungen (eigene), bewerbungen/nachrichten/einladungen/bewerbung_dateien (konto_id = eigene ODER firma_id = app.firma_id), bewerbungs_notizen (nur firma_id UND app.support_id leer), dateien (Eigentümer ODER über bewerbung_dateien die Firma; Logo: Firma), stellen, firmen (öffentlich lesen aktiv ODER eigene Bewerbung auf eine Stelle der Firma, auch bei gesperrter Firma lesend; schreiben nur eigene mit Rolle admin, Prüfung im Code), firmen_nutzer/firmen_einladungen (eigene Firma), merkliste_konto/job_alarme (eigene). Schreiben ohne Sitzung (Registrieren, Code anfordern, Zähler, Sicherheitsprotokoll) läuft nie über diese Rolle, sondern über die Funktionen der Rolle bululu_ (Karte 0 Teil 7). Ein Test je Tabelle mit fremder Firma (Teil 4), dazu je Tabelle ein Test „nicht zu wenig“: Bewerber liest Titel und Firmenname einer beendeten Stelle und einer gesperrten Firma seiner Bewerbung.
3.2 Abfragen und Aktionen 2a (Signaturen)
- Konto:
kontoAnlegen({vorname, nachname, mail, kennwort, sprache, zustimmung}) → {kontoId}(Seite Registrieren, B01 sofort; gesperrte Adresse oder IP (Karte 3gesperrt()in dienste/sperrliste.ts) → fehler.gesperrt.neutral, nichts schreiben),bewerbenCodeAnfordern({mail, vorname, nachname, zustimmung}) → ok(A12 Zweck bewerben, Bremse 3 je 15 Minuten, Honigfeld, Sperrliste wie kontoAnlegen) undkontoAnlegenMitCode({mail, code}) → {kontoId}(richtiger Code → konten mit bestaetigt_am, ohne Kennwort, Sitzung; C36),kontoStatus(mail) → 'neu'|'vorhanden'(gebremst 10 je IP und Stunde, nur im Bewerben-Fenster nach Honigfeld; verrät weder Faktor noch Kennwort, sicherheit.md Nr. 15),mailBestaetigen(token),bestaetigungErneut(kontoId)(60 s),adresseAendern(kontoId, neueMail)(nur unbestätigt),anmelden({mail, kennwort, bleiben})(prüft die Sperrliste nicht, Karte 3 D44; prüft gesperrtes Konto, Wartezeit aus anmeldungen, schreibt anmeldungen, A13 bei neuem Gerät),faktorPruefen(code|wiederherstellungscode)(app und mail),faktorMailCodeSenden()(3 je 15 Minuten, A12),kennwortVergessen(mail)(immer gleiche Antwort),kennwortNeu(token, kennwort),kennwortAendern(alt, neu),kontoSichern(token)(alle Sitzungen beenden, dann kennwortNeu),faktorEinrichten(art) → {geheimnis, qr} | {gesendetAn},faktorBestaetigen(code) → {codes[]},faktorUmstellen()(mail → app, mit Kennwortbestätigung),faktorAbschalten()(mit Kennwortbestätigung),kennwortBestaetigen(kennwort)(5 Minuten),geraete(),geraetAbmelden(id),ueberallAbmelden(),einstellungSetzen(art, an, takt?),datenExport(),kontoLoeschen(kennwort). - Bewerbung:
bewerbungsEntwurf(stelleId) → Entwurf|null,entwurfSpeichern(stelleId, felder),entwurfVerwerfen(stelleId)(verzögert, Papierkorb),dateiHochladen(zweck, datei) → {dateiId, zustand},bewerbungSenden({stelleId, telefon, dateiIds, nachricht, einwilligung, quelle}) → {bewerbungId, zustand},bewerbungenBewerber(filter),bewerbung(id)(Sicht nach Rolle),bewerbungZurueckziehen(id)(verzögert 10 s,rueckgaengig(jobId)),einladungAntworten(id, antwort, text?),nachrichtSenden(bewerbungId, text, dateiId?),gelesenSetzen(bewerbungId). - Firma:
firmaRegistrieren({betrieb…, zugang…}) → {firmaId}(firmen.adresse über 1afirmenAdresseBilden(name, ort); gesperrte Adresse wie kontoAnlegen),profilFeldSpeichern(feld, wert)(name oder ort → neue adresse, alte in firmen_adressen),logoSetzen(dateiId),teamEinladen(mail, rolle),einladungAnnehmen(token),rolleAendern(nutzerId, rolle),nutzerEntfernen(nutzerId)(verzögert nach Rückgängig-Frist; Übernahme der Stellen),faktorPflichtSetzen(an),firmaLoeschen(kennwort). - Stellen:
stellenFirma(filter, sort),stelleEntwurfAnlegen(vorbelegung?) → {stelleId},stelleFeldSpeichern(stelleId, feld, wert),stelleVeroeffentlichen(stelleId) → {zustand: 'aktiv'|'pruefung'} | {fehler[]}(eine Transaktion: Pflichtprüfung, Zustand nachnoetig.bzw. immer pruefung aus nachbessern (C22), firmen.zustand registriert → aktiv, bei pruefungts pruefungAnlegen()aus Karte 3 + F21, Protokoll),stelleKopieren,stelleBeenden(verzögert, B14),stelleVerlaengern(laeuft_bis = heute + laufzeit_tage; aktiv, läuft ab oder pausiert, ohne zeitliche Grenze),stelleErneutSchalten(nur beendet),stelleLoeschen(Admin; verzögert, in den Papierkorb). - Bewerbungen Firma:
bewerbungenFirma({stelleId?, zustand?, seite}),bewerbungOeffnen(id)(setzt gesichtet, nur Firmennutzer),einladen(id, {termin, ort|link, ansprechpersonId, text}),zusage(id, text),absage(id, text)undeinladen(verzögert nach Rückgängig-Frist),neuerTermin(id, …),notizSpeichern(bewerbungId, text)(sofort),notizLoeschen(bewerbungId)(verzögert, Papierkorb),absageMehrere(ids, text). - Papierkorb (1.17):
papierkorb(bereich: 'firma'|'konto') → {eintraege[]},papierkorbWiederherstellen(ids),papierkorbEndgueltig(ids),papierkorbLeeren(bereich); hinein legen die bestehenden AktionenstelleLoeschen,notizLoeschen,jobAlarmLoeschen(id)(1b, ergänzt um geloescht_am),entwurfVerwerfen,; alle verzögert nach Rückgängig-Frist (C6). - Live:
GET /(Abfrage alle 60 s; SSE mitapi/ live?seit={zeitpunkt} Last-Event-IDerst 2b.9). - Zählung (1a zaehle):
bewerbung_,gesendet {fachbereich, mitKonto} konto_,angelegt {quelle} firma_,registriert stelle_,veroeffentlicht einladung,absage,zusage; keine IP, keine Konto-Kennung in den Zählern.
Handlungen je Rolle in 2a
Jeder Knopf für Bewerber, Admins und Recruiter mit Wirkung, Rechten und dem Test, der ihn absichert.
Aus der Aktionen-Matrix (FUNKTIONEN-CHECK, Bewerber und Firma) und P Rechte. Nummern laufen nach 1b weiter (H55 ff.). Tests wie 1a/1b ohne Browser (PGlite mit RLS-Policies, Testing Library im jsdom); Mails aus der Warteschlange gelesen; je Endpunkt ein Test mit der Sitzung einer fremden Firma (P Sicherheit) in pruefung/.
Rolle × Handlung (Firma) (P Rechte, FC 15): Admin alles; Recruiter: Stellen anlegen, bearbeiten, veröffentlichen, kopieren, verlängern, beenden, erneut schalten, Top-Haken (3), Bewerbungen öffnen, einladen, zusagen, absagen, Notizen, Postfach; nicht: Stelle löschen, Firmenprofil (nur Link „So sehen Bewerber Ihren Betrieb“), Team, Premium anfragen (3), Firma löschen. Verstoß → fehler.rechte.recruiter (T 4.4), Server lehnt ab (nicht nur ausgeblendet). Papierkorb (1.17): wer etwas löschen darf, darf es wiederherstellen und endgültig löschen; der Recruiter sieht im Firmen-Papierkorb nur Notizen (Stellen und Entwürfe löscht nur der Admin), der Admin alles.
| Nr | Rolle · Bildschirm | Knopf/Link (Wortlaut T) | Wirkung | Test (Datei · prüft) |
|---|---|---|---|---|
| H55 | Besucher · Anmelden | „Anmelden“ | Sitzung (30 Tage, „Angemeldet bleiben“), Weiterleitung weiter= nur eigene Adressen; Faktor → /anmelden/faktor; Zeile in anmeldungen; die Sperrliste prüft das Anmelden nicht (Karte 3 1.15 Nr. 3, D44); gesperrtes Konto → fehler.gesperrt.konto; wachsende Wartezeit je Konto, je IP erst ab 50 Fehlversuchen mit eigenem Satz (H140) | pruefung/seiten/anmelden.test.ts · falsches Kennwort fehler.anmelden.falsch, 5 Fehlversuche in 15 Minuten → fehler.versuche.anmelden mit 1 Minute, danach 2, 4 … bis 15 Minuten, nach 15 Minuten ohne Versuch wieder frei; IP auf der Sperrliste → Anmeldung geht trotzdem; fremde Adresse in weiter → /mein-bereich |
| H56 | Besucher · Anmelden | „Konto anlegen“ | konten (zustand aktiv, bestaetigt_am leer), B01 in Warteschlange, Zielseite „Konto angelegt“; vergeben → fehler.feld.mailVergeben (kein Hinweis, ob Konto existiert, nur im Registrieren-Modus) | anmelden.test.ts + pruefung/fachlich/konto/anlegen.test.ts · Kennwort < 10 Zeichen, Zustimmung Pflicht, Honigfeld still |
| H57 | Besucher · Firma registrieren | „Firma registrieren“ | konten + firmen (registriert) + firmen_nutzer (admin), F01, Zielseite; mit weiter=stelle-neu Merker in Sitzung | pruefung/seiten/firma-registrieren.test.ts · Ort unbekannt, zweites Registrieren derselben Mail → Anmelden-Hinweis, inseratEntwurf wird nach Bestätigung zur Entwurfs-Stelle |
| H58 | Alle · Mail B01/F01 | Link → Zielseite (nur Anzeige, „Fast geschafft: noch ein Tipp“) → Knopf „Ja, {mail} ist meine Adresse“ | GET ändert nichts; POST setzt bestaetigt_am; Zielseite mit Knopf in den Bereich; Token 7 Tage (sicherheit.md Nr. 29) | pruefung/seiten/konto-bestaetigt.test.ts · zweiter Klick harmlos, abgelaufen → fehler.link.abgelaufen |
| H59 | Alle · Kennwort | „Link anfordern“ · Mail A01 „Neues Kennwort“ · „Kennwort speichern“ | gleiche Antwort ob Konto oder nicht; Token 60 min; neues Kennwort beendet andere Sitzungen, A02 | pruefung/fachlich/konto/kennwort.test.ts · unbekannte Mail sendet nichts, Token einmalig |
| H60 | Alle · Faktor (App) | „Bestätigen“ (Code) · „Wiederherstellungscode nutzen“ | Sitzung faktor_bestaetigt, Token-Wechsel; Code verbraucht; 5 Fehlversuche → 15 Minuten | pruefung/fachlich/konto/faktor.test.ts · TOTP-Fenster ±1 Schritt, Wiederverwendung desselben Codes abgelehnt, Code-Liste schrumpft |
| H61 | Besucher/Bewerber · Stelle | „Jetzt bewerben“ → Fenster Schritt 1 „Mit dieser E-Mail weiter“ · „Code an {mail} senden“ · „Mit Kennwort anmelden“ · „E-Mail ändern“ · „Code erneut senden“ · „Kennwort vergessen?“ im Fenster (N-1) | kontoStatus (nur neu/vorhanden); neu: Name + Zustimmung → A12 (Zweck bewerben) → richtiger Code → Konto ohne Kennwort, bestaetigt_am gesetzt, Sitzung (C36); vorhanden (gleich, ob mit oder ohne Kennwort, damit niemand erfährt, welcher Fall vorliegt): Hauptknopf „Code an {mail} senden“ (A12, Zweck anmelden) und Textlink „Mit Kennwort anmelden“, der Kennwortfeld und „Kennwort vergessen?“ aufklappt, danach ggf. zweiter Schritt; Code-Schritt mit voller Adresse und „E-Mail ändern“; angemeldet: Schritt übersprungen; Kennwort vergessen: A01 mit weiter=/stelle/[adresse]#bewerben, Fenster bleibt offen, Satz „Link unterwegs“ | pruefung/seiten/bewerben.test.ts · vier Wege, vorhandenes Konto mit und ohne Kennwort zeigt denselben Aufbau (Code-Knopf vorn), „E-Mail ändern“ führt zurück und behält den Namen, Zustimmung Pflicht bei neu, falscher Code 5× → verfallen, 3 Codes je 15 Minuten, Konto entsteht erst nach richtigem Code, kontoStatus verrät keinen Faktor, Faktor-Konto verlangt Code; pruefung/fachlich/konto/kennwort-link.test.ts · A01 in der Warteschlange mit weiter-Adresse, fremde weiter-Adresse verworfen, Link öffnet Stelle mit Fenster Schritt 2 |
| H62 | Bewerber · Fenster Schritt 2 | Ablage, „Andere Datei wählen“, „Weitere Seite fotografieren“, „Weiter zum Absenden“ | Browser verkleinert Fotos vor dem Hochladen (N-2); dateien (hochgeladen → geprueft), Entwurf gespeichert; Telefon Pflicht; alle Unterlagen aus „Meine Unterlagen“ angehakt, abwählbar; neue Datei mit „Auch für künftige Bewerbungen speichern“ landet im Konto | bewerben.test.ts + pruefung/bausteine/ablage/verkleinern.test.ts (Testbild 4.000 px → längste Kante 2.000 px, JPG, ohne EXIF; Fehler → Originaldatei) + pruefung/fachlich/datei/hochladen.test.ts · Typ am Inhalt (PDF mit .jpg-Namen), 11 MB abgelehnt fehler.datei.zuGross, 5.000 px abgelehnt fehler.datei.bildZuGross, JPG-Metadaten entfernt, HEIC → JPG nur im Rückfall, Server verkleinert sonst nichts |
| H63 | Bewerber · Fenster Schritt 3 | „Bewerbung senden“ | bewerbungen neu, einwilligungen weitergabe, B05, F03/F04 je Einstellung sofort/täglich an alle Firmennutzer mit dieser Einstellung; Erfolg mit Fokus; Entwurf gelöscht | pruefung/fachlich/bewerbung/anlegen.test.ts · zweite Bewerbung auf dieselbe Stelle fehler.bewerben.schonBeworben, Stelle nicht öffentlich sichtbar (istOeffentlichSichtbar() false: weder aktiv noch pruefung, oder Firma gesperrt) → fehler.bewerben.stelleWeg, Stelle in pruefung → Bewerbung geht durch, Einwilligung mit Textfassung gespeichert, unbestätigt → keine F03 |
| H64 | Bewerber · Fenster Schritt 1 (Code) | Code-Feld → „Weiter zum Lebenslauf“ · „Code erneut senden“ | A12 Zweck bewerben in der Warteschlange (Vorrang); richtiger Code legt das Konto an (bestaetigt_am, kein Kennwort) und öffnet Schritt 2; falscher Code fehler.faktor.falschMail, 5× verfallen; erneut frühestens nach 60 s (C36) | pruefung/fachlich/konto/code.test.ts · Code 10 Minuten, einmalig, Bremse 3 je 15 Minuten, Mail A12 in der Fassung des Zwecks |
| H65 | Bewerber · Fenster schließen | Schließen-Knopf, Esc | Entwurf bleibt 7 Tage; Toast; vor dem Code geschlossen: kein Konto; nach dem Code geschlossen: Konto besteht bestätigt, keine Mail (C36) | bewerben.test.ts · Entwurf nach Wiederöffnen vorbelegt; kein Konto ohne Code |
| H66 | Bewerber · Übersicht | „Jetzt wichtig“-Knöpfe, „Ihre Bewerbungen“, „Gemerkt“ (je „Bewerben“), „Stellen suchen“ (nur im Leer-Satz), „Erneut senden“ | Ziele; Reihenfolge nach T 7.1; 60 s Sperre | pruefung/seiten/mein-bereich.test.ts · 5 Zeilen Maximum, Reihenfolge Einladung vor Nachricht |
| H67 | Bewerber · Bewerbungen | Gruppe „Abgeschlossen“ aufklappen · Filter Alle/Offen/Abgeschlossen (ab 20) · Zeile öffnen | Liste neueste zuerst, abgeschlossene eingeklappt unten; Status-Wörter Bewerbersicht | pruefung/seiten/bewerbungen.test.ts · „gesichtet“ wird „Vom Betrieb geöffnet“, (entfällt, C36)-Zeile mit Hinweis |
| H68 | Bewerber · Bewerbung | „Zusagen“ · „Anderer Termin“ · „Absagen“ (Einladung) · Kalender-Datei | einladungen.zustand, Nachricht (system + Text) im Verlauf, F05 an Firma; ICS nur für eigene Einladung | pruefung/fachlich/einladung/antworten.test.ts + ics.test.ts · ICS Zeitzone Europe/Berlin, fremde Einladung 404 |
| H69 | Bewerber · Bewerbung | Nachricht „Senden“ (+ Anhang) | nachrichten, ungelesen_firma +1, B12/F07 je Einstellung; Schreibschutz nach Absage/Rückzug/beendet/Sperre | pruefung/fachlich/nachricht/senden.test.ts · Schreibschutz-Fälle je Zustand, Anhang nur Bewerber, 4.001 Zeichen → fehler.feld.zuLang |
| H70 | Bewerber · Bewerbung | „Bewerbung zurückziehen“ → Fenster → Knopf „Rückgängig“ | verzögert um die feste Rückgängig-Zeit (10 s, einstellungen.fristen.rueckgaengig_sekunden); danach zurueckgezogen, Einwilligung widerrufen, F06; Rückgängig bricht ab | pruefung/fachlich/bewerbung/zurueckziehen.test.ts + pruefung/dienste/verzoegert.test.ts |
| H71 | Bewerber · Lebenslauf | Felder Name/Telefon/Wohnort (sofort) · Meine Unterlagen: „Hochladen“ mit Art · „Ersetzen“ · „Entfernen“ · „Ansehen“ | konten.*, lebenslauf_datei_id; alte Datei nur mit Rückgängig (kein Papierkorb, B6), danach dateien.loeschen_ab; gesendete Bewerbungen verweisen weiter auf sie (W8) | pruefung/seiten/lebenslauf.test.ts · Telefon leer → Zeile in „Jetzt wichtig“ |
| H72 | Bewerber · Job-Alarme | „Ändern“ · „Abbestellen“ (Rückgängig) · „Anlegen“ mit Takt „keine“ · „Treffer ansehen“ | job_alarme mit konto_id, takt keine erlaubt; Alarme gleicher Mail beim Anmelden übernommen | pruefung/seiten/job-alarme.test.ts · Übernahme beim ersten Anmelden, „keine“ ohne Konto abgelehnt (1b) |
| H73 | Bewerber · Merkliste (Konto) | Herz, „Entfernen“, Übernahme vom Gerät | merkliste_konto; Toast oeffentlich.ok.merklisteUebernommen | pruefung/seiten/merkliste-konto.test.ts · Dubletten beim Zusammenführen einmal |
| H74 | Alle · Einstellungen | Benachrichtigungen (Haken) · Bedienung · Kennwort ändern · Faktor einrichten/abschalten · Geräte abmelden · Einwilligungen lesen · Daten herunterladen · Konto löschen | benachrichtigungen; konten.sprache; A02; faktor + Codes + A03 (Abschalten: A09); sitzungen gelöscht; Export-Job + A05; Löschung (anonymisiert, Dateien ohne Bewerbungsverweis weg, übrige bis zur Bewerbungsfrist, Papierkorb sofort geleert, Bewerbungen über geloescht_am gesperrt) + A06; letzter Admin → fehler.team.letzterAdmin | pruefung/seiten/einstellungen.test.ts + pruefung/fachlich/konto/loeschen.test.ts, export.test.ts · Export enthält alle eigenen Tabellen, keine fremden Notizen |
| H75 | Alle · Konto-Menü | „Mein Bereich“ · „Wechsel zu {Firma}/Bewerber“ · „Einstellungen“ · „Hilfe und Kontakt“ · „Abmelden“ | Sitzung firma_id setzen (laeuft_ab auf 14 Tage), Abmelden löscht Sitzung | pruefung/bausteine/kontomenue.test.ts · Wechsel nur zu aktiven Mitgliedschaften |
| H76 | Firma · Übersicht | „Heute zu tun“, „Ihre Stellen“, „Erste Stelle anlegen“, „Neue Stelle“ (Rand) | Ziele; Zeilen nach T 7.2; „Verlängern“ aus der Zeile sofort | pruefung/seiten/firma-uebersicht.test.ts |
| H77 | Firma · Stellen | Gruppen (Pillen und Suche ab 8) · Zeilen-Knopf je Zustand · „…“: Bearbeiten, Kopieren, Beenden, Löschen · geöffnete Stelle · Auswahl-Leiste „Beenden“/„Verlängern“ · Link „Papierkorb ({n})“ | Zustände P Lebensläufe; Beenden verzögert nach Frist + B14 an offene Bewerbungen (stelle_beendet); Löschen nur Admin und ohne offene Bewerbungen, legt in den Papierkorb (H131) | pruefung/seiten/stellen.test.ts + pruefung/fachlich/stelle/schreiben.test.ts · Recruiter: Löschen fehlt und Server lehnt ab; Verlängern setzt laeuft_bis = heute + laufzeit_tage, auch bei einer seit 400 Tagen pausierten Stelle; Beenden-Rückgängig stellt aktiv wieder her, keine B14 |
| H78 | Firma · Stelle neu/bearbeiten | Felder (sofort gespeichert, Zeile „Entwurf gespeichert {uhrzeit}“) · „Veröffentlichen“ · „Vorschau“ (Handy) | Entwurf; veröffentlichen prüft Pflichtfelder, (m/w/d), https bei Karriereseite, Ansprechperson aus Team; Stelle einer ungeprüften Firma → pruefung + pruefungAnlegen() + F21, nur wenn Prüfung nötig (Karte 3 noetig., D25: geprueft false, Schalter an, Stufe normal, kein Premium), sonst sofort aktiv ohne F21; aus nachbessern immer pruefung mit erneut_eingereicht (C22); Firma registriert → aktiv; unbestätigte Mail → Fehler am Knopf; inseratEntwurf übernommen | pruefung/fachlich/stelle/veroeffentlichen.test.ts · alle Pflichtfeld-Fehler als Liste, pruefung-Stelle nicht in sitemap (1b), aber in suchen() (1a), aktiv erscheint in suchen() (1a), pruefungen-Zeile und V01 entstehen in derselben Transaktion, firmen.zustand wird aktiv, Vorschau nur eigene Firma und Verwaltung |
| H203 | Firma (Admin/Recruiter) · Stellenzeile, „Heute zu tun“, Mail F09 | Textlink „Besetzt? Beenden“ (Mail: „Stelle ist besetzt: beenden und Bewerbern absagen“) | dieselbe Aktion wie „Beenden“ im „…“: zustand beendet, Rückgängig 10 s, danach B14 an offene Bewerber; aus der Mail nach Anmeldung die Firmensicht mit Fenster „Stelle beenden?“, erst der Knopf wirkt (sicherheit.md Nr. 29); Toast „Beendet. {n} Bewerbern sagen wir ab.“ | pruefung/fachlich/stelle/ablauf.test.ts · Beenden aus Zeile, Übersicht und Mail-Weg gleich; GET der Mail-Adresse ändert nichts |
| H79 | Firma · Bewerbungen | Filter Stelle/Status · Zeile öffnen · Auswahl „Absagen“ | bewerbungOeffnen setzt gesichtet + geoeffnet_von (nur beim ersten Mal, nur Firmennutzer); Mehrfach-Absage verzögert | pruefung/seiten/firma-bewerbungen.test.ts · zweites Öffnen ändert geoeffnet_am nicht; Bewerbung fremder Firma 404 (RLS) |
| H80 | Firma · Bewerbung | „Einladen“ · „Zusage“ · „Neuer Termin“ · „Absagen“ (Fenster mit Vorlage, „Senden“) | Status erst beim Senden; Nachricht in Verlauf; einladungen + ICS-Anhang; B07/B08/B10/B11 (T 6.2); Absage verzögert 10 s mit Rückgängig | pruefung/fachlich/bewerbung/status.test.ts · Knöpfe je Zustand, Vorlage mit Platzhaltern gefüllt, Mail enthält ICS, Absage-Rückgängig ohne Mail |
| H81 | Firma · Bewerbung, Postfach | Notiz (sofort gespeichert) · Nachricht senden (+ „Vorlage einfügen“) · Unterlagen öffnen · Vorherige/Nächste · „Als gelesen markieren“ (Auswahl-Leiste im Postfach, auch Bewerber-Postfach 1.6) | bewerbungs_notizen (nur Firma, nicht im Support-Modus); nachrichten + B12; Datei nur mit Rechte-Prüfung; gelesenSetzen() für mehrere Verläufe, Zähler ungelesen_firma/ungelesen_bewerber | pruefung/fachlich/bewerbung/notizen.test.ts, pruefung/api/datei.test.ts, pruefung/fachlich/nachricht/lesen.test.ts · Bewerber sieht keine Notiz (RLS + Sicht), fremde Firma 404, Sammel-Gelesen setzt nur eigene Verläufe |
| H82 | Firma (Admin) · Firmenprofil | Logo wählen/entfernen · Felder sofort · Ansprechperson · „So sehen Bewerber Ihren Betrieb“ · „Firma löschen“ | firmen.*; Logo verkleinert; Firmenname innerhalb 30 Tagen nach der ersten Freigabe geändert → pruefungen-Zeile art aenderung; Löschen: Stellen beendet, Bewerbungen stelle_beendet + B14, Mitgliedschaften entfernt, Papierkorb der Firma sofort geleert, F18 | pruefung/seiten/firmenprofil-bearbeiten.test.ts (Firmenname 10 Tage nach Freigabe geändert → eine Zeile „nachprüfen“, nach 31 Tagen keine) + pruefung/fachlich/firma/loeschen.test.ts · Recruiter: Seite 403 fehler.rechte.recruiter; SVG-Logo abgelehnt; Löschung lässt Bewerbungen bis Frist |
| H83 | Firma (Admin) · Team | „Konto anlegen“ (Mitarbeiter anlegen) · „Erneut senden“ · „Zurückziehen“ · Rolle ändern · „Entfernen“ (Rückgängig) · Faktor-Pflicht-Schalter | firmen_einladungen + F02; Entfernen verzögert, Übernahme der Stellen/Einladungen durch den Admin, F19 an die entfernte Person; letzter Admin nicht entfernbar; faktor_pflicht → F20 an Nutzer ohne Faktor, nächste Anmeldung halbe Sitzung | pruefung/fachlich/firma/team.test.ts · letzter Admin, Übernahme der ansprechperson_id, Pflicht erzwingt /anmelden/faktor?einrichten=1 |
| H84 | Besucher/Konto · Mail F02 | „Kennwort festlegen“ · „Einladung annehmen“ | ohne Konto Kennwort festlegen (Name vorbelegt) + Beitritt; mit Konto Anmelden + Beitritt; abgelaufen; schon Mitglied | pruefung/seiten/einladung.test.ts |
| H85 | Alle · Live | (ohne Knopf) | Abfrage GET / liefert nur eigene Zähler und Zeilen; fremde Firma nie (SSE erst 2b.9) | pruefung/api/live.test.ts · Zeile fremder Firma fehlt, seit liefert nur Neueres, Antwort ohne Sitzung 401 |
| H86 | Hintergrund | Fristen und Mails | 30 Tage unbestätigte Konten ohne Bewerbung; F08 (5 Tage), F09; offene Bewerbungen auf seit 6 Monaten pausierten Stellen → stelle_beendet + B14, Zeile „Heute zu tun“ 14 Tage davor, die Stelle bleibt pausiert; F04 täglich; B09 Vortag; B13 Merkliste-Ablauf; Bewerbungen 6 Monate nach Abschluss gelöscht (Dateien mit); Konten 24 Monate (A07) + 3 | pruefung/hintergrund/*.test.ts je Aufgabe · Stichtage, keine Mail an abgeschaltete Arten, „immer“-Arten trotz Abschaltung |
| H87 | Alle · fremde Firma | jede Aktion und Adresse aus Teil 3.2 mit Sitzung einer anderen Firma | 403/404, keine Zeile sichtbar, kein Schreiben | pruefung/rechte/fremde-firma.test.ts · Liste aller Aktionen aus fachlich/ wird per Wächter mit diesem Test abgeglichen (fehlender Fall = Testfehler) |
| H131 | Firma (Admin, Recruiter) · Stellen, Bewerbung | „Löschen“ (Stelle, Entwurf; nur Admin) · „Notiz löschen“ · Link „Papierkorb ({n})“ | legt in den Papierkorb (geloescht_am, geloescht_von) nach der Rückgängig-Frist, Toast T 3.1 (firma.rg.loeschenOhneBewerbung/.loeschenMitBewerbung/.entwurfLoeschen/.notizLoeschen); Listen und Suche zeigen die Zeile nicht mehr; Link nur bei n > 0 | pruefung/fachlich/papierkorb/loeschen.test.ts · Rückgängig in der Frist lässt geloescht_am leer; Stelle mit offener Bewerbung lehnt ab; Recruiter: Stelle löschen 403, Notiz löschen geht; Zähler im Link stimmt |
| H132 | Firma (Admin, Recruiter) · Papierkorb | „Wiederherstellen“ · „Endgültig löschen“ · „Papierkorb leeren“ (Fenster) | 1.17 Nr. 5 und 6; Recruiter sieht nur Notizen; Protokoll | pruefung/seiten/papierkorb.test.ts + pruefung/fachlich/papierkorb/wiederherstellen.test.ts · Stelle kommt im alten Zustand zurück; Notiz-Text zurück bzw. unter die neue Notiz; Stelle mit abgeschlossenen Bewerbungen bleibt als geloescht hinter den Bewerbungen; Recruiter sieht keine Stellen-Einträge; fremde Firma 404 |
| H133 | Bewerber · Job-Alarme, Bewerben-Fenster und Bewerbungen, Papierkorb | „Löschen“ (Alarm) · „Verwerfen“ (Entwurf) · im Papierkorb „Wiederherstellen“ · „Endgültig löschen“ · „Papierkorb leeren“ | geloescht_am an job_alarme, bewerbungs_entwuerfe; Toasts T 3.1 (konto.rg.jobAlarmLoeschen, .entwurfVerwerfen); Wiederherstellen nach 1.17 Nr. 5; ersetzte Lebenslauf-Datei: nur Rückgängig (H71), nie im Papierkorb (B6) | pruefung/seiten/papierkorb.test.ts (Konto-Teil) + pruefung/fachlich/papierkorb/endgueltig.test.ts · ersetzte Datei liegt nicht im Papierkorb, gesendete Bewerbung öffnet sie weiter; Entwurf einer nicht mehr bewerbbaren Stelle lässt sich nicht wiederherstellen; Alarm im Papierkorb bekommt keine B15; fremdes Konto sieht nichts |
| H134 | Hintergrund · Papierkorb, pausierte Stellen | Fristen | fristen.ts: Einträge älter als papierkorb_tage (30) endgültig wie 1.17 Nr. 6; stellen-ablauf.ts: offene Bewerbungen auf seit pausiert_abschluss_monate (6) abgelaufenen Stellen → stelle_beendet + abgeschlossen_am + B14, 14 Tage davor Zeile firma.heute.pausiertAbschluss; Konto- und Firmenlöschung leeren den Papierkorb sofort | pruefung/hintergrund/papierkorb.test.ts, stellen-ablauf.test.ts · Stichtage; Verlängern am Tag 13 der Vorwarnung stoppt den Abschluss; Stelle bleibt pausiert; eine seit 400 Tagen pausierte Stelle wird nicht gelöscht; nach Kontolöschung ist der Papierkorb leer |
| H137 | Alle · Faktor (E-Mail-Code), Anmelden und Bewerben-Fenster Schritt 1 | „Bestätigen“ (Code aus Mail A12) · „Code erneut senden“ · „Wiederherstellungscode nutzen“ | faktor_mail_codes: Code gehasht, 10 Minuten, einmalig; A12 sofort in der Fassung des Zwecks; falscher Code fehler.faktor.falschMail; nach einer Anmeldung per E-Mail-Code ist der zweite Schritt bei Art mail das Kennwort, nie ein zweiter E-Mail-Code; erneut frühestens nach 60 s, höchstens 3 je 15 Minuten; 5 Fehlversuche → Code verfällt; Erfolg → Sitzung faktor_bestaetigt, Token-Wechsel | pruefung/fachlich/konto/faktor-mail.test.ts · abgelaufener Code abgelehnt, zweite Nutzung abgelehnt, vierter Code in 15 Minuten → fehler.faktor.mailZuOft, Verwaltungskonto mit Art mail kommt nicht nach /verwaltung (Karte 3 D34); Code-Anmeldung eines Kontos mit Art mail verlangt danach das Kennwort, keinen zweiten Code |
| H138 | Alle · Einstellungen › Anmeldung zusätzlich schützen | Pillen „Authenticator-App (empfohlen)“ / „Code per E-Mail“ · „Code an {mail} senden“ · „Code prüfen“ · „Auf App umstellen“ | faktor.art app oder mail; Einrichtung per App endet mit 10 Wiederherstellungscodes, per E-Mail ohne Codes (F3); A03 mit {faktorArt}; Umstellen mail → app nach Kennwortbestätigung (H141), Protokoll faktor_umgestellt | pruefung/seiten/einstellungen.test.ts · App-Weg endet mit Codes, E-Mail-Weg ohne; Konto ohne Kennwort sieht keine Pille „Code per E-Mail“; Umstellen ohne Kennwortbestätigung → fehler.kennwortBestaetigen.noetig; Firma mit Faktor-Pflicht nimmt beide Arten (halbe Sitzung endet) |
| H139 | System · Anmelden von neuem Gerät, Mail A13 | A13 „Neue Anmeldung bei Ihrem Konto“ mit Knopf „Das war ich nicht“ → /konto/sichern?t= (nur Anzeige) → „Ja, alle Geräte abmelden“ (POST) → „Neues Kennwort speichern“ | A13 bei erfolgreicher Anmeldung mit unbekannter Gerätekennung (12 Monate, konto_), nicht bei der ersten Anmeldung nach Registrierung und nicht bei Anmeldung per E-Mail-Code; Link 24 h einmalig (konto_tokens sichern); der Abruf des Links ändert nichts, erst der Knopf beendet alle Sitzungen, dann Kennwort-neu-Formular, A02, Protokoll konto_gesichert | pruefung/fachlich/konto/neues-geraet.test.ts · bekanntes Gerät: keine Mail; unbekanntes: eine Mail; unbekanntes Gerät mit Anmeldung per Code: keine A13; Link beendet Sitzungen, bevor das Formular erscheint; abgelaufener Link → Satz mit Weg „Kennwort vergessen“; Verwaltungskonto → zusätzlich Betriebsmail (Karte 3 1.16) |
| H140 | Alle · Anmelden, jedes Kennwort-Feld | Hinweis „Kennwort vergessen? Neues Kennwort anfordern“ · Kennwort-Prüfung | ab 3 Fehlversuchen je Konto in 15 Minuten Link hervorgehoben; Kennwort mindestens 10, höchstens 128 Zeichen, nicht in der Liste häufiger Kennwörter, nicht E-Mail/Vorname/Nachname → fehler.feld.kennwortKurz/.kennwortHaeufig | pruefung/fachlich/konto/kennwort.test.ts, anmelden-bremse.test.ts · „passwort123“ abgelehnt, „Max Mustermann“ für Max Mustermann abgelehnt, 10 Zeichen ohne Sonderzeichen angenommen; Hinweis erscheint beim 3. Fehlversuch, nicht beim 2. |
| H141 | Alle · heikle Aktionen | Fenster „Zur Sicherheit: Ihr Kennwort“ → „Weiter“; Konto ohne Kennwort: „Zur Sicherheit: Code an {mail} senden“ → Code → „Weiter“ | sitzungen.kennwort_bestaetigt_am (auch nach richtigem Code, A12 Fassung bestaetigen); gilt 5 Minuten; nötig für: Faktor abschalten, umstellen, Codes neu erzeugen, Konto löschen, Firma löschen, Verwaltung: Firma löschen, Bewerberkonto löschen, E-Mail-Adresse ändern (Karte 3 1.4) | pruefung/bausteine/kennwortbestaetigung.test.ts · Aktion ohne Bestätigung → fehler.kennwortBestaetigen.noetig; nach 6 Minuten erneut nötig; falsches Kennwort zählt als Fehlversuch in anmeldungen; Konto ohne Kennwort kann sein Konto per Code löschen |
| H143 | Automatik · Übersetzung der Anzeigen | Veröffentlichen oder Textänderung einer Stelle (H78) | Zeilen wartet in stellen_uebersetzungen je Sprache aus sprachen_frei; Aufgabe stellen-uebersetzen (1.18 Nr. 1 bis 3) schreibt fertig mit Text und uebersetzt_am, bei Fehler fehler + versuche + Protokoll, nach 3 Versuchen fehler_anzahl in einstellungen.uebersetzung; nur mit Schalter an | pruefung/hintergrund/stellen-uebersetzen.test.ts · Stummel: wartet → fertig, Fehler → fehler/versuche/Protokoll, Änderung während des Laufs bleibt wartet, Schalter aus → keine Zeile |
| H144 | Besucher · Stelle (/en/, /tr/) | Umschalter „Deutsch zeigen“ / „Übersetzung zeigen“ am Hinweis „Mit KI übersetzt“ | zeigt die deutsche bzw. übersetzte Fassung an Ort und Stelle (Client, ohne Neuladen; ohne JS Link mit ?fassung=de), Wahl im Gerätespeicher je Sitzung; Hinweis bleibt sichtbar | pruefung/seiten/stelle.test.ts · /tr/ mit Zeile fertig: übersetzter Titel, deutscher Titel lang="de", Hinweis, Umschalter; ohne Zeile: deutscher Text mit nochNichtUebersetzt, kein Umschalter |
Nicht-Handlungen, die ein Test sichert: kein „Gesichtet“ durch Verwaltung (H79, vorbereitet für 3); Bewerber sieht nie Notizen, nie den Firmensicht-Status („Neu“), nie geoeffnet_von; Verwaltung tritt in 2a nicht auf (Rolle existiert nur in RLS-Vorbereitung); die Übersetzung schickt nie Ansprechperson, Adresse oder Firmenname an den Dienst (H143); Mails an Firmennutzer gehen nie an entfernte; noindex auf allen (konto)/(firma)-Seiten; kein Zählpixel; Dateien nie unter /public; Bausteinliste je Seite (waechter/bausteinliste.ts +16 Seiten); Wortliste: kein „Paket“, „Abo“, „Rechnung“ im Firmenbereich.
Zustände je Seite
Was jede Seite zeigt, wenn sie leer ist, lädt, ein Fehler auftritt oder Rechte fehlen.
| Seite | leer | lädt | Fehler | nicht gefunden / Rechte | nicht mehr verfügbar |
|---|---|---|---|---|---|
| Anmelden | entfällt | Knopf „Wird gesendet …“ aria-disabled (1b-Muster) | fehler.anmelden.falsch (ein Satz für Mail und Kennwort, T 7.6), fehler.versuche.anmelden (Bremse), fehler.netz.* | Konto gesperrt → fehler.gesperrt.konto (Erklärseite); Firma gesperrt → Anmelden geht, Firmenbereich zeigt fehler.gesperrt.firma | Konto gelöscht = unbekannt (gleiche Meldung) |
| Registrieren / Firma registrieren | entfällt | wie oben | Feldfehler (fehler.feld.mail, .mailVergeben, .kennwortKurz, .zustimmung, .ortUnbekannt, .plz), Honigfeld still | ||
| Kennwort / Faktor / Zielseiten | entfällt | Server-Seite | Token falsch/abgelaufen (fehler.link.*) + „Link neu anfordern“; Code falsch: App fehler.faktor.falsch, E-Mail-Code fehler.faktor.falschMail; 5 × → App fehler.versuche.code, E-Mail-Code verfällt | ||
| Bewerben-Fenster | entfällt | Schritt-Wechsel sofort; Verkleinern im Browser als „Foto wird vorbereitet“ (T gemeinsam.datei.vorbereiten, 7.12), dann Upload mit Fortschritt je Datei; Senden „Wird gesendet …“ | Feldfehler je Schritt; Datei fehler.datei.* (Typ, Größe, Anzahl; Virenprüfung läuft noch = fehler.datei.pruefungLaeuft, man kann weiterarbeiten; Virenprüfung gestört = fehler.datei.pruefungGestoert); Netz: Eingaben bleiben (Entwurf) | Stelle beim Senden nicht mehr öffentlich sichtbar (weder aktiv noch pruefung, oder Firma gesperrt) → fehler.bewerben.stelleWeg + „Ähnliche Stellen“ (1a) | schon beworben → fehler.bewerben.schonBeworben + „Meine Bewerbungen“ |
| Übersicht Bewerber | keine Bewerbungen: „Ihre Bewerbungen“ fehlt, „Jetzt wichtig“ trägt den Satz und „Stellen suchen“; nichts zu tun: Kasten „Alles erledigt …“ + „Stellen suchen“; nichts gemerkt: „Gemerkt“ fehlt (U 3.5) | Server-Seite | error.tsx | ||
| Bewerbungen | 0: T 2 „Noch keine Bewerbungen“ + „Stellen ansehen“; Filter ohne Treffer: T 2 je Filter | Platzhalter-Zeilen nur beim Nachladen über Live | Ladefehler fehler.netz.allgemein | Bewerbung fremd/unbekannt → 404 | abgeschlossene Gruppe unten; Stelle beendet: Titel ohne Link |
| Bewerbung | keine Nachrichten: Verlauf zeigt nur System-Zeilen + Eingabe | Senden „Wird gesendet …“ | Netz: Text bleibt im Feld; Schreibschutz-Satz: fehler.postfach.abgeschlossen (ein Satz für Absage, Rückzug, Stelle beendet), fehler.postfach.firmaGesperrt, beim gesperrten eigenen Konto konto.postfach.kontoGesperrt (T 7.7); Firmensicht: fehler.postfach.bewerberGesperrt, fehler.postfach.kontoGeloescht | 404 | Einladung ersetzt: alte eingeklappt |
| Postfach | 0: T 2 „Noch keine Nachrichten“ | Server-Seite | error.tsx | ||
| Lebenslauf | keine Datei: .keineDatei mit Ablage; Telefon leer: Hinweis | Feld „Gespeichert …“ je Feld, Upload-Fortschritt | fehler.feld.telefon, fehler.datei.*; Netz: „Nicht gespeichert, erneut versuchen“ (fehler.netz.gespeichertNicht) | ||
| Job-Alarme / Merkliste (Konto) | wie 1b, zusätzlich T 2 „Noch kein Job-Alarm“ | wie 1b | wie 1b | ||
| Einstellungen | keine Bewerbung: Karte Einwilligungen fehlt; kein Faktor: Karte zeigt „Einrichten“ | je Karte eigener Knopfzustand | Kennwort falsch fehler.feld.kennwortAltFalsch; Faktor-Code falsch: App fehler.faktor.falsch, E-Mail-Code fehler.faktor.falschMail; Export läuft schon: Satz | letzter Admin beim Löschen: fehler.team.letzterAdmin | |
| Übersicht Firma | keine Stellen: Block „Erste Schritte“ mit „Erste Stelle anlegen“ (U 3.8); nichts zu tun: Satz mit der nächsten Frist | Server-Seite | error.tsx | Firma gesperrt → Erklärseite statt Bereich; registriert ohne Bestätigung → Zeile oben | |
| Stellen | 0: T 2 „Noch keine Stellen“ + „Neue Stelle“; Filter leer: Satz je Filter | Platzhalter beim Nachladen | Netz | fremde Stelle 404 | Nachbessern/gesperrt (3): Chip + Satz, Zeilen-Menü eingeschränkt |
| Stelle neu/bearbeiten | Team ohne zweite Person: Ansprechperson vorbelegt (einzige) | „Gespeichert 12:03“ je Feld; Veröffentlichen „Wird geprüft …“ | Fehler am Feld in einem Satz, erstes fehlendes Feld bekommt den Fokus, dringende Meldung „{n} Angaben fehlen“ (U 3.11, A.2); unbestätigte Mail: Satz am Knopf; Entwurf-Konflikt (zwei Tabs): letzter gewinnt, Hinweis (Annahme C9) | 404 fremd | aktiv und bearbeitet: Änderungen sofort live (keine erneute Prüfung, Annahme C10) |
| Bewerbungen Firma | 0: T 2 „Noch keine Bewerbungen“ (je Stelle) | Platzhalter beim Nachladen | Netz | 404 fremd | zurückgezogen/beendet: ohne Knöpfe |
| Bewerbung Firma | keine Notizen: Feld allein; keine Datei (nur Nachricht): Satz | Fenster „Wird gesendet …“ | Vorlage leer → fehler.feld.nachrichtLeer; Termin in der Vergangenheit fehler.feld.datumVergangen | 404 | Bewerber-Konto gelöscht: Kontaktzeile „Konto gelöscht“, Postfach gesperrt (fehler.postfach.kontoGeloescht), Unterlagen bleiben bis Frist |
| Firmenprofil | kein Logo: Monogramm; keine Beschreibung: leeres Feld mit Platzhalter (B :224) | „Gespeichert …“ je Feld, Logo-Fortschritt | fehler.datei.logo* (SVG, 2 MB, bildZuGross), fehler.feld.webseite (T 7.6) | Recruiter 403 fehler.rechte.recruiter | |
| Team | nur ich: Liste mit einer Zeile, Formular „Mitarbeiter anlegen“ offen | Konto anlegen | fehler.team.schonImTeam, .schonEingeladen, fehler.feld.mail | Recruiter 403 | Einladung abgelaufen: Zeile grau mit „Erneut senden“ |
| Papierkorb (Firma, Bewerber) | 0: gemeinsam.papierkorb.leer, „‹ Übersicht“-Zeile; der Link „Papierkorb ({n})“ und der Konto-Menü-Eintrag fehlen dann | Server-Seite; Knöpfe „Wird ausgeführt …“ aria-disabled | Netz; Eintrag inzwischen endgültig gelöscht (anderer Tab, Nachtlauf) → Zeile verschwindet mit Satz fehler.papierkorb.weg | Recruiter sieht nur Notizen; fremde Firma 404 | Stelle mit Bewerbungen nach „Endgültig löschen“: aus dem Papierkorb weg, Bewerbungen bleiben bis zu ihrer Frist (Titel ohne Link) |
| Live | Verbindungsaufbau still; Rückfall nach 5 s ohne Strom | Verbindungsabbruch: Wiederaufnahme mit Last-Event-ID, nach 3 Fehlschlägen Abfrage 30 s; nie Toast |
Rückmeldung nach Klick (P Laden und Rückmeldung, U A.6): sofort speichernde Felder zeigen „Gespeichert {uhrzeit}“ neben dem Feld-Block; Fenster-Knöpfe „Wird gesendet …“ aria-disabled; Rückgängig nach U A.6: Knopf „Rückgängig“ ersetzt den gedrückten Knopf und bekommt den Fokus, Toast zusätzlich, Frist nach Einstellung (Standard 10 s) (Zurückziehen, Einladen, Absagen, Beenden, Löschen, Entfernen, Alarm abbestellen oder löschen, Entwurf verwerfen, Notiz löschen, Lebenslauf-Datei ersetzen; was dabei in den Papierkorb geht, steht in 1.17); Toast hält, solange Maus oder Fokus darin sind, Info-Toasts ohne Rückgängig stehen 6 s; Ladebalken ab 0,3 s, Platzhalter in Form des Inhalts, bei Netzfehler bleiben Eingaben erhalten (G80); Sitzung abgelaufen: Eingaben bleiben, nach dem Anmelden zurück an dieselbe Stelle (U A.6); Live-Einträge in Listen mit aria-live polite („1 neue Bewerbung“), nie aria-live assertive, eingehende Nachrichten im Verlauf ohne Ansage; Reiter-Zahlen ändern sich ohne Ansage.
Dateien mit geschätzter Größe und Wegweiser-Zeilen
Liste der Programmdateien mit geschätztem Umfang und Bau-Reihenfolge, als Wegweiser für die Programmierung.
Dieser Abschnitt beschreibt nur die technische Umsetzung. Mit dem Schalter „Technische Angaben“ blenden Sie ihn ein.
Richtwert 600 Zeilen, Notbremse 1.500; Schätzungen in Zeilen; nur Neues und Geändertes gegenüber 1a/1b.
6.1 Dateiliste
| Datei | Z. | Inhalt |
|---|---|---|
| (oeffentlich)/anmelden/page.tsx · _formular/Anmelden.tsx · Registrieren.tsx · FirmaRegistrieren.tsx · kennwort/page.tsx · kennwort-neu/page.tsx · faktor/page.tsx | 60 · 140 · 120 · 180 · 60 · 70 · 110 | Client-Formulare, ohne JS als POST |
| (oeffentlich)/konto/bestaetigt/page.tsx · (oeffentlich)/einladung/page.tsx | 60 · 120 | Zielseiten |
| (oeffentlich)/stelle/[adresse]/_bewerben/BewerbenDialog.tsx · Schritt1.tsx · Schritt2.tsx · FragenBlock.tsx · Schritt3.tsx · Erfolg.tsx · EntwurfZeile.tsx · bewerben/page.tsx | 160 · 160 · 150 · 30 · 120 · 60 · 30 · 90 | Dialog aus B stelle.html:103–156; FragenBlock leere Hülle (B1) |
| (konto)/layout.tsx · mein-bereich/page.tsx · _uebersicht/ (2) · bewerbungen/page.tsx · _liste/ (2) · bewerbungen/[id]/page.tsx · _bewerbung/ (4) · postfach/page.tsx · lebenslauf/page.tsx · _lebenslauf/ (2) · job-alarme/page.tsx · _alarme/* (2) | 80 · 60 · 60+40 · 70 · 140+50 · 90 · 60+160+60+90 · 70 · 50 · 120+110 · 60 · 120+120 | |
| (konto)/konto/einstellungen/page.tsx · _einstellungen/* (8 Karten) | 70 · je 60–150 | Faktor.tsx 150, Loeschen.tsx 90 |
| (firma)/layout.tsx · firma/page.tsx · _uebersicht/IhreStellen.tsx · ErsteSchritte.tsx · stellen/page.tsx · _liste/StellenListe.tsx · ZeilenMenue.tsx · stellen/[id]/page.tsx · _stelle/Kopfreihe.tsx · stellen/neu/page.tsx · stellen/[id]/bearbeiten/page.tsx · _formular/StellenFormular.tsx · Vorschau.tsx · Ansprechperson.tsx | 90 · 60 · 60 · 40 · 70 · 220 · 90 · 90 · 60 · 50 · 60 · 320 · 60 · 50 | StellenFormular größte Client-Datei (unter 600) |
| (firma)/firma/bewerbungen/page.tsx · _liste/BewerbungenFirma.tsx · bewerbungen/[id]/page.tsx · _bewerbung/Kopf.tsx · Knoepfe.tsx · Verlauf.tsx · Unterlagen.tsx · Notizen.tsx · postfach/page.tsx | 70 · 180 · 100 · 70 · 220 · 60 · 80 · 110 · 70 | |
| (firma)/firma/profil/page.tsx · _profil/Logo.tsx · Stammdaten.tsx · UeberUns.tsx · Ansprechperson.tsx · FirmaLoeschen.tsx · team/page.tsx · _team/Liste.tsx · Einladen.tsx · FaktorPflicht.tsx | 60 · 120 · 130 · 50 · 50 · 90 · 60 · 140 · 80 · 50 | |
| (konto)/konto/papierkorb/page.tsx · (firma)/firma/papierkorb/page.tsx · bausteine/papierkorb/PapierkorbListe.tsx · PapierkorbLink.tsx · fachlich/papierkorb/liste.ts · loeschen.ts · wiederherstellen.ts · endgueltig.ts · leeren.ts · pruefung/seiten/papierkorb.test.ts · pruefung/fachlich/papierkorb/*.test.ts (3) · pruefung/hintergrund/papierkorb.test.ts | 60 · 60 · 180 · 30 · 90 · 70 · 90 · 110 · 40 · 200 · je 80–150 · 80 | Papierkorb (1.17, H131–H134); 0003_konten.sql ergänzt geloescht_am an stellen, bewerbungs_notizen, bewerbungs_entwuerfe, job_alarme |
| bausteine/kontomenue/KontoMenue.tsx · bereich/BereichKopf.tsx · Reiter.tsx · BestaetigenZeile.tsx · jetztwichtig/JetztWichtig.tsx · zeilen.ts · ablage/Ablage.tsx · pruefen.ts · statuschip/StatusChip.tsx · postfach/Verlauf.tsx · nachricht.ts · fenster/Fenster.tsx · auswahl/Auswahl.tsx · listenfeld/ListenFeld.tsx · live/LiveClient.tsx · NeuZeile.tsx · zeitstrahl/Zeitstrahl.tsx · Verlauf.tsx · faktor/FaktorEinrichten.tsx · CodeFeld.tsx | 110 · 40 · 60 · 40 · 80 · 120 · 220 · 90 · 70 · 200 · 30 · 120 · 180 · 70 · 140 · 40 · 60 · 60 · 160 · 50 | |
| bausteine/seitenrahmen/Kopf.tsx (+40) · stellenkarte/Stellenkarte.tsx (+50) · sonderseiten/Fehlerseite.tsx (+30) · (oeffentlich)/stelle/[adresse]/page.tsx (+40) | Änderungen | |
| dienste/auth/better-auth.ts · sitzung.ts · kennwort.ts · haeufige-kennwoerter.txt · geraete.ts · anmeldungen.ts · ip.ts · faktorMail.ts · dienste/db/rls.ts · dienste/verzoegert.ts | 120 · 90 · 90 · (Daten) · 100 · 120 · 40 · 110 · 110 · 90 | Sicherheit 26.10.: Kennwort-Liste, anmeldungen, IP aus vertrauten Weiterleitern, E-Mail-Code |
| (oeffentlich)/konto/sichern/page.tsx · bausteine/kennwortbestaetigung/* · faktor/CodeErneut.tsx · dienste/mail/vorlagen/a12.tsx · a13.tsx · pruefung/fachlich/konto/faktor-mail.test.ts · neues-geraet.test.ts · anmelden-bremse.test.ts · pruefung/bausteine/kennwortbestaetigung.test.ts | 70 · 120 · 40 · 40 · 50 · 140 · 120 · 120 · 80 | H137 bis H141 (26.10.) |
| fachlich/konto/anlegen.ts · felder.ts · loeschen.ts · export.ts · einstellungen.ts · faktor.ts · token.ts | 140 · 60 · 120 · 110 · 70 · 140 · 60 | |
| fachlich/bewerbung/anlegen.ts · entwurf.ts · status.ts · liste.ts · notizen.ts · felder.ts · fachlich/einladung/anlegen.ts · antworten.ts · ics.ts · erinnerung.ts · fachlich/nachricht/senden.ts · lesen.ts · liste.ts | 160 · 80 · 200 · 140 · 60 · 70 · 110 · 90 · 90 · 50 · 110 · 60 · 80 | |
| fachlich/stelle/schreiben.ts · rechte.ts · vorschau.ts · ablauf.ts · fachlich/firma/registrieren.ts · profil-schreiben.ts · logo.ts · team.ts · loeschen.ts · fachlich/datei/hochladen.ts · pruefen.ts · ausliefern.ts · loeschen.ts · fachlich/zaehler/ungelesen.ts · fachlich/rechte.ts | 220 · 80 · 50 · 120 · 130 · 90 · 90 · 180 · 130 · 180 · 90 · 90 · 50 · 50 · 90 · 120 | rechte.ts enthält die Tabelle Rolle × Handlung als Daten |
| dienste/mail/vorlagen/b01, b05, b07–b14 · a01–a03, a05–a07, a09, a12, a13 · f01–f09, f18–f21 · versand-regel.ts | je 40–90 · 80 | 32 Vorlagen; Sammel-F04 100 |
| hintergrund/aufgaben/konto-unbestaetigt.ts · stellen-ablauf.ts · bewerbungen-sammel.ts · einladung-erinnerung.ts · merkliste-ablauf.ts · fristen.ts · datenexport.ts · bewerbung-ohne-antwort.ts | 60 · 120 · 90 · 60 · 60 · 140 · 120 · 70 | bewerbung-ohne-antwort.ts: End-Check Befund 15 (offene Bewerbung ohne Handlung der Firma seit einstellungen.fristen.bewerbung_ohne_antwort_monate (6) → stelle_beendet-ähnlicher Abschluss ohne_, B14 neutral; 14 Tage vorher Zeile firma.heute.bewerbungAbschluss) |
| app/api/live/route.ts · api/datei/[id]/route.ts · api/kalender/[id].ics/route.ts · api/auth/[...all]/route.ts | 110 · 80 · 50 · 20 | |
| dienste/db/schema/konten.ts · sitzungen.ts · faktor.ts · konto_tokens.ts · einwilligungen.ts · benachrichtigungen.ts · firmen_nutzer.ts · firmen_einladungen.ts · bewerbungs_entwuerfe.ts · bewerbungen.ts · bewerbung_dateien.ts · bewerbungs_antworten.ts · bewerbungs_notizen.ts · nachrichten.ts · einladungen.ts · dateien.ts · merkliste_konto.ts · konto_zugang.ts; firmen.ts (+5), stellen.ts (+7), einstellungen.ts (Typen) | 60 · 40 · 30 · 40 · 40 · 30 · 40 · 40 · 40 · 90 · 20 · 30 · 50 · 60 · 60 · 40 · 20 | |
| db/migrationen/0003_konten.sql · 0003_rueckweg.sql · 0003_rechte.sql · musterdaten/konten.ts · bewerbungen.ts · firmen-nutzer.ts · nachrichten.ts | 320 · 80 · 220 · 80 · 120 · 40 · 60 | Musterdaten: 3 Bewerber (einer mit Faktor), 2 Firmen mit Admin + Recruiter, 6 Bewerbungen in allen Zuständen, Einladung, Notizen |
| sprachen/{de,en,tr}/anmelden.json · bewerben.json · konto.json · firma.json · status.json · mail-bewerber.json · mail-konto.json · mail-firma.json | je 40–200 | aus T 1.4, 1.6, 1.7 (ohne 2b-Schlüssel), 1.8, 2, 3, 4, 5, 6, 7.1, 7.2 |
| pruefung/seiten/anmelden · firma-registrieren · konto-bestaetigt · bewerben · mein-bereich · bewerbungen · lebenslauf · job-alarme · merkliste-konto · einstellungen · firma-uebersicht · stellen · firma-bewerbungen · firmenprofil-bearbeiten · einladung (.test.ts) | je 80–260 | |
| pruefung/fachlich/konto/ (6) · bewerbung/ (5) · einladung/ (2) · nachricht/ (1) · stelle/ (2) · firma/ (3) · datei/ (2) · pruefung/api/live · datei · pruefung/dienste/verzoegert · pruefung/rechte/fremde-firma · pruefung/hintergrund/ (8) · pruefung/mails/* (Stichproben b03, f03, b05 mit ICS, f18) · pruefung/bausteine/kontomenue · ablage · auswahl | je 50–220 | fremde-firma.test.ts ~300 (alle Aktionen) |
| dienste/uebersetzung/azure.ts · stummel.ts · index.ts · hintergrund/aufgaben/stellen-uebersetzen.ts · bausteine/stellenkarte/UebersetzungUmschalter.tsx (Client, 1a-Seite Stelle) · pruefung/hintergrund/stellen-uebersetzen.test.ts · pruefung/dienste/uebersetzung.test.ts | 120 · 30 · 30 · 110 · 60 · 140 · 60 | 1.18, H143, H144; Schema-Ergänzung stellen_uebersetzungen in 0003_konten.sql |
| pruefung/waechter/bausteinliste.ts (+16 Seiten), links.test.ts (+2a-Adressen), aktionen-liste.ts (neu: jede exportierte Aktion braucht einen Rechte-Test) | +120 |
Summe grob: ~210 neue Dateien, ~14.000 Zeilen inkl. Mails, Tests und Migrationen; keine Datei über 320 außer 0003_konten.sql. Bauzeit nach Zeitplan 2a (P): in Paketen von 30–45 Minuten, Reihenfolge: Konten und Anmelden → Bewerben-Fenster → Bewerberbereich → Firma registrieren und Stellen → Bewerbungen und Postfach → Team und Profil → Live → Hintergrund und Fristen.
6.2 Zeilen für ARCHITEKTUR.md
Seite → Dateien:
- Anmelden =
(oeffentlich)/+anmelden/ page. tsx _,formular/ kennwort/,kennwort-neu/,faktor/,(oeffentlich)/· Bausteine fenster, faktor, honigfeld · dienste/auth (auch anmeldungen, ip, faktorMail), dienste/sperrliste (Karte 3) · fachlich/konto · dienste/mail (B01, F01, A01, A02, A12, A13) · sprachen anmelden.json, bewerben.json (Felder) · Tests anmelden.test.ts, firma-registrieren.test.ts, pruefung/fachlich/konto/konto/ sichern/ - Zielseiten Konto =
(oeffentlich)/,konto/ bestaetigt/ page. tsx (oeffentlich)/· fachlich/konto/anlegen, fachlich/firma/team · Tests konto-bestaetigt, einladungeinladung/ page. tsx - Bewerben-Fenster =
(oeffentlich)/,stelle/ [adresse]/ _ bewerben/ bewerben/· Bausteine fenster, ablage, faktor, honigfeld · fachlich/bewerbung, fachlich/datei, fachlich/konto · dienste/mail (B01 bei Abbruch, B05, F03, F04), bremse · sprachen bewerben.json, fehler.json · Tests bewerben.test.ts, pruefung/fachlich/bewerbung/, datei/*page. tsx - Bewerberbereich =
(konto)/,layout. tsx mein-bereich/· Bausteine bereich, jetztwichtig, statuschip, postfach, zeitstrahl, fenster, ablage, live, stellenkarte · fachlich/bewerbung, einladung, nachricht, konto, jobalarm (1b) · sprachen konto.json, status.json · Tests mein-bereich, bewerbungen, lebenslauf, job-alarme, merkliste-konto** - Einstellungen =
(konto)/· Bausteine faktor, fenster, kennwortbestaetigung · fachlich/konto/* · dienste/auth/geraete, faktorMail · dienste/mail (A02, A03, A05, A06, A09, A12) · Tests einstellungen, konto/loeschen, konto/exportkonto/ einstellungen/ ** - Firmenbereich =
(firma)/,layout. tsx firma/· Bausteine bereich, jetztwichtig, statuschip, postfach, fenster, auswahl, listenfeld, ablage, live, stellenkarte (vorschau, firma), kontomenue · fachlich/stelle (schreiben, rechte, vorschau), bewerbung (status, liste, notizen), einladung, nachricht, firma (profil-schreiben, logo, team, loeschen), datei · dienste/mail (B07–B14, F02–F09, F18–F21) · sprachen firma.json, status.json · Tests firma-uebersicht, stellen, firma-bewerbungen, firmenprofil-bearbeiten, team, fremde-firma** - Live =
app/(Abfrage aus den Fachtabellen, 1.16) · bausteine/live · Test pruefung/api/live; SSE undapi/ live/ route. ts ereignisseerst 2b.9 - Übersetzung der Anzeigen = hintergrund/aufgaben/stellen-uebersetzen.ts · dienste/uebersetzung/* · Auslöser fachlich/stelle/schreiben.ts · Anzeige (oeffentlich)/stelle (1a) mit bausteine/stellenkarte/UebersetzungUmschalter · Tabelle stellen_uebersetzungen · Tests pruefung/hintergrund/stellen-uebersetzen, pruefung/dienste/uebersetzung
- Dateien =
app/· fachlich/datei/ · Test pruefung/api/datei, fachlich/datei/api/ datei/ [id]/ route. ts - Kalender =
app/· fachlich/einladung/ics · Test einladung/icsapi/ kalender/ [id]. ics/ route. ts - Hintergrund 2a = hintergrund/aufgaben/{bewerbung-wartet-mail, konto-unbestaetigt, stellen-ablauf, bewerbungen-sammel, einladung-erinnerung, merkliste-ablauf, fristen, datenexport} · Tests pruefung/hintergrund/*
- Rechte = fachlich/rechte.ts (Rolle × Handlung), fachlich/stelle/rechte.ts, fachlich/firma/rechte.ts, dienste/db/rls.ts, db/migrationen/0003_rechte.sql · Test pruefung/rechte/fremde-firma.test.ts, waechter/aktionen-liste.ts
- Papierkorb =
(konto)/,konto/ papierkorb/ page. tsx (firma)/· Bausteine papierkorb, auswahl, fenster · fachlich/papierkorb/ · dienste/verzoegert · Tests papierkorb.test.ts, pruefung/fachlich/papierkorb/, pruefung/hintergrund/papierkorbfirma/ papierkorb/ page. tsx
Baustein → wo benutzt (Ergänzung zu 1a/1b):
- kontomenue → Seitenrahmen (angemeldet, alle Seiten)
- bereich (BereichKopf, Reiter, BestaetigenZeile) → (konto)/layout, (firma)/layout; die Verwaltung nutzt ihn nicht (Karte 3 D43: Menüleiste links, h1 der Seite)
- jetztwichtig → Übersicht Bewerber, Übersicht Firma; ab 3 Verwaltung
- ablage → Bewerben-Fenster, Lebenslauf, Firmenprofil (Logo), Postfach-Anhang; ab 2b Anlagen
- statuschip → alle Listen und Details beider Bereiche; ab 3 Verwaltung
- postfach/Verlauf → Bewerbung (Bewerber), Bewerbung (Firma)
- fenster → Bewerben, Zurückziehen, Einladen/Zusage/Absage/Neuer Termin, Konto löschen, Firma löschen, Stelle löschen, Faktor; ab 3 Verwaltungs-Fenster
- auswahl → Stellen (Firma), Bewerbungen (Firma), Papierkorb beider Bereiche; ab 3 Verwaltungslisten; Merkliste nur bei Bedarf (1b W1)
- papierkorb → /firma/papierkorb, /konto/papierkorb; PapierkorbLink unter Stellen (Firma), Job-Alarme, Bewerbungen (Bewerber); Konto-Menü
- listenfeld → Stellenformular
- live → beide Bereiche; ab 3 Verwaltung („Heute zu tun“)
- zeitstrahl → Bewerbung beide Sichten
- faktor → Anmelden/faktor, Einstellungen, Bewerben-Fenster Schritt 1
- honigfeld + bremse (1b) → zusätzlich Registrieren, Firma registrieren, Bewerben, Anmelden (Bremse), kontoStatus
- dienste/mail (1a) → alle Konto-, Bewerber- und Firmen-Mails; ICS-Anhang neu
- stellenkarte (1a) → zusätzlich Vorschau im Stellenformular, Stellenliste der Firma
Offene Punkte (Weichen), Annahmen, Textschlüssel
Getroffene Entscheidungen und Annahmen, etwa Bewerben ohne Kennwort, Rückgängig, Papierkorb und Übersetzung, sowie Ideen für später.
7.1 Weichen (A = mein Vorschlag)
| Nr | Weiche | A | B |
|---|---|---|---|
| W1 | Bewerben-Fenster ohne JS: B und U kennen nur den Dialog. Ohne JS gibt es entweder eine eigene Seite mit denselben drei Schritten (mehr Dateien, aber vollständig bedienbar) oder nur einen Hinweis „Bitte JavaScript einschalten“. | eigene Seite /stelle/[adresse]/bewerben als POST-Formulare (dieselben Server-Aktionen, Bausteine geteilt) | nur Hinweis; Fenster braucht JS |
| W2 | Rückgängig 10 s (Zurückziehen, Absagen, Beenden, Entfernen): im Browser verzögert (einfach; bricht bei Tab-Wechsel/Netzabbruch ab und sendet dann nie) oder auf dem Server verzögert (pg-boss-Job, abbrechbar; wirkt immer). | Server (dienste/): Aktion sofort als „ausstehend“ sichtbar, Job führt nach der festen Frist aus (10 s, einstellungen.fristen.rueckgaengig_sekunden, Karte 3 D23), Rückgängig löscht den Job; Mails erst bei Ausführung | Browser-Timer |
| W3 | Ansprechperson der Stelle: FK auf konten (Konto ist rollenlos; 1a sah firmen_ vor) oder FK auf firmen_ (Mitgliedschaft; sauberer bei mehreren Firmen je Konto, aber beim Entfernen hängt die Zeile an einer entfernten Mitgliedschaft). | FK konten + Prüfung „ist aktives Mitglied dieser Firma“ im Code; beim Entfernen Übernahme durch den Admin (P) | FK firmen_nutzer |
| W4 | Zustand „Bewerbung wartet auf Mail-Bestätigung“: eigener Zustand (entfällt, C36) in bewerbungen (klar in Listen, Firma sieht sie nie) oder Zustand neu mit Prüfung über konten.bestaetigt_am (weniger Zustände, aber jede Firmen-Abfrage muss den Join prüfen). | eigener Zustand (entfällt, C36); Übergang zu neu beim Bestätigen (eine Stelle, ein Test) | neu + Join |
| W5 | „Gesichtet“ beim Öffnen: beim Laden der Detailseite (jedes Öffnen durch einen Firmennutzer, auch versehentlich aus der Live-Vorschau) oder erst beim Öffnen der Unterlagen. P sagt „Öffnen setzt Gesichtet“. | Laden der Detailseite durch einen Firmennutzer (P wörtlich); Rolle Verwaltung ausgenommen | erst Unterlagen |
| W6 | Live-Aktualisierung technisch: Server-Sent Events mit Tabelle ereignisse (einfach, Abfrage je Sekunde pro offener Verbindung gebündelt über LISTEN/NOTIFY) oder reine Abfrage alle 30 s (kein Strom, weniger Verbindungen, aber bis 30 s Verzögerung). P nennt SSE mit Rückfall. | SSE über PostgreSQL LISTEN/NOTIFY (eine Verbindung je Tab, Rückfall Abfrage 30 s); Ereignisse 24 h in ereignisse für Wiederaufnahme | nur Abfrage 30 s |
| W7 | Better Auth oder eigener Auth-Code: P Technik nennt Better Auth (Tabellen, Sitzungen, TOTP). Eigener Code wäre kleiner, aber Sicherheit selbst gebaut. | Better Auth mit Drizzle-Adapter und TOTP-Plugin; eigene Tabellennamen über das Mapping; zusätzliche Felder (faktor_pflicht, geraet) in eigenen Spalten | eigener Code |
| W8 | Kennung der Konto-Datei bei neuer Bewerbung: Datei wird je Bewerbung kopiert (Momentaufnahme, mehr Speicher) oder die Bewerbung zeigt auf dieselbe Datei und „Ersetzen“ im Lebenslauf legt eine neue Datei an, die alte bleibt für gesendete Bewerbungen (kein Kopieren, Löschung erst, wenn keine Bewerbung mehr darauf zeigt). | Verweis ohne Kopie; Löschen der alten Datei erst, wenn keine Bewerbung sie nutzt (loeschen_ab) | Kopie je Bewerbung |
Entschieden am 22.10. als Annahme (jederzeit korrigierbar): W1 bis W8 je Spalte A.
7.2 Annahmen
| Nr | Annahme |
|---|---|
| C1 | Bewerben ohne JS über eigene Seite (W1 A). |
| C2 | Geräte-Liste zeigt Browser und Betriebssystem aus der Browser-Kennung, die letzte Nutzung und die gekürzte IP-Adresse der Anmeldung (aus anmeldungen, 30 Tage); kein Ort. Die Zählung bleibt ohne IP (1a); IP-Adressen liegen nur im Sicherheitsprotokoll und in der Sperrliste. |
| C3 | „Erneut schalten“ (nur beendet) legt eine Kopie als Entwurf an (neue Adresse, neue 30 Tage); die alte Stelle bleibt mit ihren Bewerbungen. Pausierte Stellen werden verlängert, nicht erneut geschaltet (C24). |
| C4 | Logos sind öffentlich, sobald die Virenprüfung bestanden ist (dateien.zustand geprueft); eine Freigabe durch die Verwaltung gibt es nicht, das Feld logo_ wird nicht angelegt (1a Teil 3). Missbrauch decken Melden und Sperren ab. Öffentliche Auslieferung über fachlich/ Fall „öffentlich“. |
| C5 | Ansprechperson des Betriebs (Firmenprofil) ist nur Vorbelegung für neue Stellen; das öffentliche Profil zeigt keine Person (1b 1.3 hat keine Zeile). |
| C6 | Rückgängig auf dem Server verzögert (W2 A), Frist fest aus einstellungen.fristen.rueckgaengig_sekunden; der Fokus landet auf dem Rückgängig-Knopf an der Stelle des gedrückten Knopfes (U A.6). |
| C7 | Better Auth (W7 A); seine Pflichtspalten bleiben neben den hier genannten. |
| C8 | stellen.ansprechperson_id zeigt auf konten (W3 A); die 1a-Felder ansprech_anrede/-vorname/-nachname/-telefon bleiben als Rückfall für Stellen ohne Konto-Ansprechperson (Schnittstelle, Import, Musterdaten; 1a A21). Stellen aus dem Formular haben immer ansprechperson_id. |
| C21 | Telefon-Freigabe der Ansprechperson liegt je Person und Firma in firmen_nutzer.telefon_in_anzeigen (Team), nicht je Stelle; es gibt kein stellen.ansprech_telefon_frei. |
| C22 | Eine Stelle im Zustand nachbessern (nach Ablehnen in der Prüfung oder Offline nehmen nach Meldung) geht bei „Veröffentlichen“ immer in pruefung mit erneut_eingereicht und neuer Prüfzeile, auch bei geprüfter Firma; Bearbeiten einer aktiven Stelle bleibt ohne Prüfung (C10). |
| C23 | Bewerben ist erlaubt, solange istOeffentlichSichtbar() ja sagt (aktiv oder pruefung, Firma nicht gesperrt); eine Stelle in Prüfung ist für Bewerber sichtbar und bewerbbar (P, 1a W5). |
| C9 | Zwei Tabs bearbeiten denselben Entwurf: letzter Schreibzugriff gewinnt, beim Speichern im anderen Tab prüft der Server den Stand (geaendert_am) und zeigt den Hinweis „Inzwischen geändert, bitte neu laden“, statt still zu überschreiben. |
| C10 | Bearbeiten einer aktiven Stelle geht sofort live, ohne neue Prüfung (Prüfung nur bei der ersten Stelle einer neuen Firma, P). Ausnahme ohne Sperre: Ändert eine Firma in den ersten 30 Tagen nach der Freigabe Stellentitel oder Firmennamen, entsteht eine Prüfzeile art aenderung in der Gruppe „nachprüfen“ (Karte 3 D27); die Stelle bleibt online. |
| C11 | Mail-Nummern nach T 6.2 bis 6.4 (am 22.10. abgeglichen): B01 Konto bestätigen, B02 bis B04 entfallen (C36), B05 Bewerbung angekommen, B06 keine Mail, B07 Einladung, B08 Neuer Termin, B09 Erinnerung Vortag, B10 Zusage, B11 Absage, B12 Neue Nachricht, B13 Merkliste läuft ab, B14 Stelle beendet, B15–B17 Job-Alarm (1b), B18/B19 Sperre (3); A01 Kennwort, A02 Kennwort geändert, A03 Faktor eingerichtet, A04/A08 Faktor-Rücksetzung (3), A05 Export, A06 Konto gelöscht, A07 lange nicht genutzt, A09 Faktor abgeschaltet; F01 Registrierung, F02 Team-Einladung, F03 neue Bewerbung, F04 täglich gesammelt, F05 Antwort auf Einladung, F06 zurückgezogen, F07 Nachricht, F08/F09 Ablauf, F10–F17 Verwaltung/Premium (3), F18 Firma gelöscht, F19 aus dem Team entfernt, F20 Faktor jetzt Pflicht, F21 Stelle wartet auf Prüfung. Codes mail., mail., mail. wie T; Vorlagen heißen nach der Nummer. |
| C12 | Benachrichtigungs-Arten je Konto in einer Tabelle (fehlende Zeile = an); „immer“-Arten (Konto, Kennwort, Sicherheit) haben keine Zeile. |
| C13 | Firmen-Sitzung 14 Tage sobald eine Firma gewählt ist; Wechsel zurück zu „Bewerber“ setzt nicht auf 30 Tage zurück (kürzere Dauer bleibt). |
| C14 | Reiter sind Links mit eigener Adresse (kein JS-Tabpanel wie B), Optik unverändert; Konto-Menü ersetzt B-„…“-Menü. |
| C15 | Firma registrieren mit bestehendem Konto: angemeldet → nur Block „Ihr Betrieb“, Zugang entfällt; nicht angemeldet mit vergebener Mail → Hinweis „Bitte zuerst anmelden“ mit weiter=firma-registrieren. |
| C16 | Dateien liegen auf einem verschlüsselten Datenträger des Servers (P), Pfad in dateien., Auslieferung nur über /api/datei/[id] mit Rechte-Prüfung; Virenprüfung über ClamAV-Dienst, Konfiguration Abschnitt 4 (Betrieb); in der Testumgebung Stummel, der „geprueft“ setzt. Lesen und Schreiben von Dateien läuft nur über fachlich/ mit einem Ablage-Dienst; kein anderer Teil kennt den Pfad, damit ein späterer Wechsel auf einen Objektspeicher nur diesen Dienst betrifft. |
| C17 | Live zum Livegang als Abfrage alle 60 s; LISTEN/NOTIFY mit SSE (W6 A) erst 2b.9. |
| C18 | Die Auswahl-Leiste (P Auswählen) wird hier für Stellen und Firmen-Bewerbungen gebaut; Merkliste bleibt wie 1b W1. |
| C19 | Einwilligung „nutzung“ (Datenschutz + Nutzungsbedingungen beim Konto) und „weitergabe“ (je Bewerbung) werden mit Textfassung gespeichert; die Sichtbarkeit für Betriebe ist keine Einwilligung, sondern ein Schalter. |
| C20 | Öffentlicher Stellen-Zustand pruefung (1a: sichtbar) bleibt; die Firma sieht Chip „Wartet auf Prüfung“ (T 5.4) und kann bearbeiten. |
| C24 | Eine abgelaufene Stelle ist pausiert: nicht öffentlich, für die Firma sichtbar, jederzeit ohne zeitliche Grenze verlängerbar, bis die Firma sie beendet oder löscht; der Nachtlauf fasst die Stelle nicht an (1a Enum stelle_zustand ohne archiviert). Datenschutz: offene Bewerbungen darauf werden 6 Monate nach dem Ablauf automatisch abgeschlossen (stelle_beendet, B14; Hinweis 14 Tage vorher in „Heute zu tun“), die Stelle bleibt pausiert. |
| C25 | Papierkorb für Firma und Bewerber: Löschen legt in den Papierkorb (geloescht_am), 30 Tage (einstellungen.fristen.papierkorb_tage, Karte 3), danach endgültig; Seiten /firma/papierkorb und /konto/papierkorb (1.17). Drin: Stellen und Entwürfe, Notizen (Firma); Job-Alarme, verworfene Bewerbungsentwürfe. Nicht drin: Merkliste (Rückgängig genügt, 1b W1), Konto und Firma löschen (eigene Abläufe mit Export und Fristen), Bewerbung zurückziehen (Zustand), Team-Mitglied entfernen und Einladung zurückziehen (Zustand mit Rückgängig und Übernahme der Stellen), Logo entfernen (eine Datei, neu wählen ist ein Klick), Nachrichten und Einwilligungen (werden nicht gelöscht), Geräte abmelden (Sitzung). Inhalte im Papierkorb zählen bei Export und Löschfristen mit; Konto- oder Firmenlöschung leert den Papierkorb sofort. |
| C26 | Quelle je Bewerbung (B4, 26.10.): nur aus dem Adress-Parameter von (Werte wie 1a stellen_aufrufe_tag), den das Bewerben-Fenster beim Öffnen übernimmt; kein Cookie, kein Referrer; fehlt er, „direkt“. Die Statistik dazu kommt nach dem Livegang (Kundenliste). |
| C27 | Vorab-Fragen des Betriebs (B1, 26.10.): FragenBlock. in Schritt 2 und Tabelle bewerbungs_ sind zum Livegang leer; Stellenformular, Bewerbungsansicht und die AGG-Prüfung der erlaubten Fragen kommen erst mit der Freischaltung fragen nach dem Livegang. |
| C28 | Stellenformular (B5, B2, 26.10.): Beschäftigungsart als Pillen mit Mehrfachwahl (Vollzeit vorgewählt, mindestens eine), Befristung freiwillig als zwei Pillen plus Datumsfeld nach „Start“; beides ohne neues Element (Pillen und Datumsfeld gibt es im Formular schon). |
| C29 | Zweiter Faktor per E-Mail-Code: Bewerber und Firmennutzer wählen in den Einstellungen App oder E-Mail-Code; Code 6 Ziffern, 10 Minuten, einmalig, gehasht; höchstens 3 Codes je 15 Minuten; Wiederherstellungscodes nur bei der App; Firmen-Pflicht nimmt beide; die Verwaltung bleibt bei der App (Karte 3 D34). A12 geht über die Vorrang-Spur der Mail-Warteschlange (sofort, vor Massenmails). |
| C30 | Fehlversuche: keine dauerhafte Kontosperre; wachsende Wartezeit je Konto (ab 5 in 15 Minuten: 1, 2, 4, 8, 15 Minuten) und je IP erst ab 50 in 15 Minuten mit eigenem Satz, Hinweis „Kennwort vergessen?“ ab dem 3. Fehlversuch. Kennwort: 10 bis 128 Zeichen, lokale Liste häufiger Kennwörter, keine Sonderzeichen-Pflicht, kein Ablauf. |
| C31 | „Neues Gerät“ = Gerätekennung aus der Browser-Kennung: Browser-Name und Betriebssystem-Name, beide ohne Fassungsnummer (z. B. „Chrome · Android“; 26.10., Bewertung), ohne erfolgreiche Anmeldung dieses Kontos in den letzten 12 Monaten; keine Cookie-Marke, keine IP im Vergleich (Mobilfunk wechselt sie ständig). Ein Browser-Update löst darum keine A13 aus; ein anderer Browser auf demselben Gerät schon, das ist hinnehmbar, die Mail ist kurz und hat einen klaren Weg. |
| C32 | Erneute Kennworteingabe vor heiklen Aktionen gilt 5 Minuten je Sitzung (sitzungen.kennwort_bestaetigt_am) und ersetzt die bisherigen Kennwortfelder in den Fenstern „Konto löschen“ und „Firma löschen“ durch den einen Baustein kennwortbestaetigung/. |
| C34 | „Kennwort vergessen?“ im Bewerben-Fenster: sendet A01 sofort an die eingetippte Adresse, ohne eigene Seite; die neutrale Antwort und die Bremse (höchstens 3 Links je Adresse und Stunde) sind dieselben wie auf /anmelden/kennwort; der Token trägt weiter (konto_tokens.weiter, nur eigene Adressen), nach dem neuen Kennwort landet die Person angemeldet in der Stelle mit offenem Fenster in Schritt 2. Neue Schlüssel bewerben.kennwortLinkUnterwegs (T 7.9). Ohne JS (C1): der Link führt auf /anmelden/kennwort?weiter=…, die Seite übernimmt weiter genauso. |
| C35 | Bilder verkleinert der Browser, nicht der Server: bausteine/ (createImageBitmap + Canvas, Zielmaße je Zweck: Lebenslauf-Foto 2.000 px JPG 0,85, Logo 800 px (PNG bleibt PNG), Werbemotiv in Originalmaßen neu kodiert (GIF unverändert, Animation), Ratgeber-Bild 1.600 px WebP), Metadaten fallen beim Kodieren weg. Der Server verlässt sich nicht darauf (_ Nr. 16): Typ am Inhalt, Größe, Pixelmaße je Zweck (Lebenslauf höchstens 4.000 px, Logo 1.000 px, Ratgeber 2.400 px, Werbemotiv genau das Format), Viren, bei JPG Metadaten-Segmente ohne Neukodierung entfernen; zu große Maße → fehler.datei.bildZuGross mit Hinweis, ein kleineres Foto zu wählen (ohne JS oder bei alten Browsern). Einziger Server-Rückfall: HEIC → JPG für Lebenslauf-Fotos, wenn der Browser HEIC nicht dekodiert (außerhalb Safari), begrenzt auf 3 je Konto und Tag, sonst fehler.datei.heic. |
| C33 | Übersetzung der Anzeigen (26.10., Bewertung Runde 2; zugesagt in Kundenliste und Plan): Azure AI Translator im Europa-Rechenzentrum (Plan Schnittstellen „Anbieter“), nur en und tr zum Livegang (ar mit 2b.3), nur die sechs Textfelder der Stelle, maschinell ohne Gegenlesen (Hinweis an der Anzeige, 1b 1.12), Verzögerung 2 Minuten nach der letzten Änderung, 3 Versuche, dann Zeile „Heute zu tun“ beim Super Admin; Firmenprofile, Inhalte und Vorab-Fragen werden nicht übersetzt (Plan: Profile bleiben zum Start deutsch). Fällt der Dienst aus, zeigt die Seite den deutschen Text mit Hinweis; nichts blockiert das Veröffentlichen. |
| C36 | Bewerben mit Code statt Kennwort: Beim ersten Bewerben bestätigt ein 6-stelliger Code an die eingetippte Adresse (Mail A12, Zweck bewerben, Baustein faktor/, dieselbe Bremse wie der E-Mail-Faktor) die Adresse direkt in Schritt 1; das Konto entsteht erst nach richtigem Code, bestätigt und ohne Kennwort (kennwort_hash leer). Danach geht die Bewerbung sofort an die Firma. Die Zustände „wartet auf Bestätigung“ und „verfallen“, die Mails B02 bis B04, die Fassung „Adresse ändern“ nach dem Senden und bewerbung-wartet-mail.ts entfallen; Tippfehler fängt der Textlink „E-Mail ändern“ im Code-Schritt ab. Anmelden später per Code an die E-Mail oder mit einem Kennwort, das die Person in Einstellungen › Kennwort setzt (kennwortSetzen.ts, A02). Ein Konto von der Seite Registrieren bleibt beim Kennwort-Weg mit B01. Rechtsfrage R8 (Haken oder Satz) gilt unverändert. |
| C37 | Bedienungs-Nachprüfung 27.10. (Bericht BEDIENUNG-NACHCHECK-2026-10-27, P-5050-BN; Wege ohne Kennwort zu Ende gedacht): (1) jedes vorhandene Konto sieht beim Bewerben zuerst „Code an {mail} senden“, das Kennwort ist aufklappbar; (2) die Anmeldeseite hat für alle Konten den Rand-Knopf „Ohne Kennwort anmelden: Code per E-Mail“; (3) volle Adresse und „E-Mail ändern“ im Code-Schritt; (4) A12 je Zweck mit eigenem Betreff und Schlusssatz; (5) Kennwortbestätigung per Code für Konten ohne Kennwort; (6) eigener Fehlersatz für E-Mail-Codes; (7) Knopf „Mit dieser E-Mail weiter“ und Überschrift „Code aus Ihrer E-Mail“; (8) keine A13 nach Code-Anmeldung, nie zwei E-Mail-Codes hintereinander, E-Mail-Faktor erst mit Kennwort; (9) „Anmeldung zusätzlich schützen“ statt „zweiter Faktor“ in allen Oberflächen und Mails; (11) neue Zeilen nur auf Klick; (14) Bestätigungsseiten nennen den Fortschritt. Die Sicherheitslinie bleibt: kontoStatus verrät nur „neu“ oder „vorhanden“ (_ Nr. 15). |
7.3 Textschlüssel
Vorhanden und genutzt: T 1.4 (bewerben.), 1.6 (oeffentlich.anmelden., .registrieren., .firmaReg., .kennwort., .kennwortNeu., .faktor.), 1.7 (konto. ohne die 2b-Schlüssel konto.lebenslauf.erfahrung … .mappe, Deckblatt), 1.8 (firma.*), 2 (Leerzustände), 3.1 bis 3.3, 4.1 bis 4.4, 5.1 bis 5.5, 6.0 bis 6.4, 7.1, 7.2, 7.4.
Ergänzt am 22.10.: neue Schlüssel in T 7.6 (konto.uebersicht.lebenslaufBandTitel/-Text, konto.einst.bewegung, fehler.team.schonEingeladen, firma.profil.ansprechperson/-Satz, firma.stelle.kopieTitel, gemeinsam.live.neu; am 26.10. dazu fehler.anmelden.falsch, fehler.faktor.falsch, fehler.feld.webseite), neue Mails A09 mail. (T 6.3) und F19 mail., F20 mail., F21 mail. (T 6.4). Mit vorhandenen Schlüsseln abgedeckt: Bestätigen-Zeile (konto.wichtig.kontoBestaetigen, firma.heute.mailBestaetigen), Geräte (konto.einst.geraete …), letzte Admin-Person (fehler.team.letzterAdmin), schon im Team (fehler.team.schonImTeam), Faktor-Pflicht (firma.team.faktorPflicht, .faktorStand), Termin in der Vergangenheit (fehler.feld.datumVergangen), Datei in Prüfung (fehler.datei.pruefungLaeuft: man kann weitermachen, kein „erneut versuchen“). Am 26.10. dazu T 7.8 (Papierkorb und pausierte Stellen: gemeinsam.papierkorb.*, fehler.papierkorb.weg, firma.stellen.gruppePausiert/.pilleBeendet, firma.heute.pausiert/.pausiertAbschluss, firma.rg.notizLoeschen, konto.rg.dateiErsetzt/.entwurfVerwerfen); firma.stellen.pilleArchiviert heißt jetzt .pillePausiert; fehler.stelle.verlaengernNichtMehr und status.stelle.archiviert sind gestrichen. Am 27.10. (C37, BN): neu bewerben.kontoGefundenAnsage, .kontoMitKennwort (ersetzt .kontoVorhandenCode), .mailAendern, .schritt1Code, .nameZeile; oeffentlich.anmelden.codeSenden, .codeHinweis, .codeFeld, .codeAnmelden; fehler.faktor.falschMail; konto.einst.faktorErstKennwort, .keinKennwort; gemeinsam.kennwortBestaetigen.titelCode, .textCode, .codeSenden; gemeinsam.datei.hochladen; Mail A12 in vier Fassungen; geändert bewerben.weiter1, .codeHinweis ({mail} statt {mailTeil}), gemeinsam.live.neu, die Faktor-Texte, A03, A09, F20.
Ergänzt am 26.10. (T 7.9): firma., ., ., . (Stellenformular); FragenBlock braucht zum Livegang keinen Schlüssel.
Ergänzt am 26.10. (T 7.10, Sicherheit): oeffentlich., ., ., ., ., .; fehler., fehler.; konto., ., ., ., ., ., ., ., ., ., .; konto., ., ., ., .; fehler., fehler., fehler., fehler.; gemeinsam., ., .; firma.; Text von fehler. (T 4.4) auf Wartezeit statt Sperre geändert; Mails A12 und A13 in T 6.3; A03 mit {faktorArt}.
Ergänzt am 26.10. (T 7.11, Übersetzung der Anzeigen, 1.18): vorhanden gemeinsam., ., . (1a), verwaltung. (T 7.3), verwaltung. (T 1.9); neu gemeinsam. (Umschalter zurück, H144), verwaltung., ., . (Karte 3 1.11 Nr. 3, nur Deutsch).
7.4 Sonstiges, vor dem Bau zu klären (keine Weiche, aber Material)
- AGB für Arbeitgeber: Text von Nomad (RECHTSTEXTE P-5050-RT Abschnitt 4), Link in oeffentlich.firmaReg.zustimmung zeigt auf /agb (1b 1.12).
- ClamAV und verschlüsselter Datenträger: Betrieb (Abschnitt 4) muss sie vor dem Livegang bereitstellen; Testumgebung läuft mit Stummel (C16).
- Fristen (P Sicherheit „bestätigt der Kunde, Mail Punkt 5“): Werte stehen in einstellungen.fristen und sind ohne Code änderbar.
- Befund FC 15/16 (Recruiter-Rechte, Ansprechperson entfernt) sind in P nachgezogen und hier umgesetzt; FC 1, 2, 3, 9, 10, 11 betreffen Abschnitt 3 (Verwaltung) und sind hier nur als Zustände/Adressen vorbereitet (nachbessern, gesperrt, Sperre Bewerberkonto, faktor-reset).
7.5 Ideen (nicht geplant)
- Browser-Push-Benachrichtigungen für neue Nachrichten (statt nur Mail und Live-Zahl).
- „Angemeldet bleiben“ je Gerät benennen (eigener Name statt Browser-Kennung).
- Bewerbung als Firma mit einem Klick an eine Kollegin weiterleiten („Bitte sieh dir das an“) als Notiz mit Erwähnung.
- Kalender-Abo (ICS-Feed) für alle Einladungen einer Firma.
- Entwurf der Bewerbung geräteübergreifend fortsetzen per Link in B01 („Bewerbung fortsetzen“).