Zuletzt geöffnet als Sprungliste, ohne Verlauf

Die letzte offene Zeile aus TASKS.md. Sie blieb offen, weil eine Spur über
jeden Aktenaufruf schnell etwas anderes wird als eine Bequemlichkeit.

Vier Festlegungen halten sie auf der richtigen Seite:

  - Kein Verlauf. Der Primärschlüssel (userId, targetType, targetId) lässt je
    Nutzer und Datensatz genau eine Zeile zu, die überschrieben wird. Die
    Tabelle kann nicht sagen, wie oft oder in welcher Reihenfolge gearbeitet
    wurde. Zwanzig Einträge, älteres fällt hinten heraus.
  - Nur die eigene. Keine Ansicht, kein Adminbereich, keine Funktion mit
    fremder Kennung. Jede Abfrage nimmt p.userId.
  - Jederzeit löschbar, ohne Rückfrage und ohne Grabstein.
  - Vorabrufe zählen nicht. Ohne die Prüfung auf next-router-prefetch stünde
    dort, worüber jemand mit der Maus gefahren ist.

Gelesen wird über dieselben Sichtbarkeitsfragmente wie überall: eine
vorgemerkte Kennung ist keine Berechtigung. Steigt eine Akte über die
Freigabestufe, verschwindet sie ohne Lücke und ohne Platzhalter; Personalakten
brauchen zusätzlich personnel.read. Das Zugriffsprotokoll bleibt unberührt und
bleibt die einzige Auskunft darüber, wer wann was gelesen hat.

Sie steht auf der Übersicht und im leeren Feld der Kommandopalette. Der zweite
Ort ist der eigentliche.

Nebenbei: NEXT_DIST_DIR, damit ein Build neben einem laufenden
Entwicklungsserver nicht dasselbe .next-Verzeichnis abräumt.
This commit is contained in:
Harlekin
2026-09-03 10:52:23 +02:00
parent b911c1bd9a
commit db40c5d3b2
18 changed files with 621 additions and 10 deletions
+50
View File
@@ -0,0 +1,50 @@
import { after } from 'next/server'
import { headers } from 'next/headers'
import { noteOpened } from '@/lib/recent/service'
import type { RecentTarget } from '@afis/db'
/**
* Einen Sprung vormerken, aus einer Seite heraus.
*
* Zwei Dinge macht diese Schicht, die die Datenschicht nicht machen kann:
*
* **Vorabrufe zählen nicht.** Next holt die Seiten hinter sichtbaren Links im
* Voraus. Ohne diese Prüfung stünde in der Liste, worüber jemand mit der Maus
* gefahren ist — die Übersicht allein würde sie mit zehn Akten füllen, die
* niemand geöffnet hat. Das wäre nicht nur falsch, es wäre die unangenehmere
* Sorte falsch: eine Aufzeichnung von Aufmerksamkeit statt von Handlung.
*
* **Es kostet die Seite nichts.** Der Schreibvorgang läuft in `after()`, also
* nachdem die Antwort raus ist. Eine Merkliste darf keine Akte langsamer
* machen; geht sie verloren, ist nichts verloren.
*/
export async function trackOpen(
userId: string,
targetType: RecentTarget,
targetId: string,
): Promise<void> {
if (await istVorabruf()) return
after(async () => {
try {
await noteOpened(userId, targetType, targetId)
} catch {
// Eine Merkliste ist kein Grund, eine Aktenansicht scheitern zu lassen.
}
})
}
/**
* Die Kopfzeilen, mit denen Next und die Browser einen Vorabruf ankündigen.
* Lieber eine zu viel geprüft als einen Sprung erfunden.
*/
async function istVorabruf(): Promise<boolean> {
const kopf = await headers()
return (
kopf.get('next-router-prefetch') === '1' ||
kopf.has('next-router-segment-prefetch') ||
kopf.get('purpose') === 'prefetch' ||
kopf.get('x-purpose') === 'prefetch' ||
kopf.get('x-moz') === 'prefetch'
)
}