Update hex values → CSS var references, fix font (Merriweather→Tinos),
card pattern (border-brand-sand→border-line, bg-white→bg-surface),
and contrast table to remove hardcoded hex in favour of --palette-* names.
Addresses Leonie's review blocker on PR #446.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Brand colors, font name, dev port, route tree, and card pattern were
all outdated relative to layout.css and the current route structure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- docs/README.md: remove duplicate infrastructure/ entry at end of folder tree
- ocr-service/CLAUDE.md: add **LLM reminder:** prefix to ALLOWED_PDF_HOSTS
SSRF warning (consistent with all other machine-readable instructions)
- backend/CLAUDE.md: restore ResponseStatusException note for simple controller
validation — avoids LLMs reaching for DomainException for trivial checks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- person/README.md: findAll(String q) and findByName(String firstName, String lastName)
- notification/README.md: replace 'None inbound' with actual outbound dep on DocumentService.findTitlesByIds
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- notification: remove phantom NotificationPreferenceRepository entity; fix
notifyReply signature (DocumentComment + Set<UUID>, not parentComment/reply)
- tag: correct delete(UUID) description — TagService.delete() is called BY
DocumentService.deleteTagCascading(), not the other way around
- person: fix findOrCreateByAlias to single-String signature; type classification
is internal to PersonTypeClassifier
- dashboard: replace fabricated cross-domain calls with verified ones
(removed NotificationService + GeschichteService; added TranscriptionService,
UserService, CommentService per actual DashboardService imports)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- notification/README.md: notifyMentions second param is DocumentComment, not String contextUrl
- document/README.md: transcription queue methods take int limit param
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Security checklist: OCR_TRAINING_TOKEN → APP_OCR_TRAINING_TOKEN (backend)
plus TRAINING_TOKEN (OCR service); both must share the same value
- Bootstrap: clarify docker-compose.prod.yml is not committed — must be
created from docs/infrastructure/production-compose.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use correct container name archive-db (not familienarchiv-db-1) in
§5 backup/restore commands — verified against docker-compose.yml
- Add KRAKEN_MODEL_PATH to OCR service env vars table (was missing;
set at docker-compose.yml:92 as /app/models/german_kurrent.mlmodel)
Refs #399
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers: topology diagram (Mermaid), OCR memory/VPS sizing table,
dev-vs-prod differences, complete env vars table (all vars verified
against docker-compose.yml and application.yaml, including APP_ADMIN_*
and ALLOWED_PDF_HOSTS gaps not in .env.example), security checklist
before first boot, bootstrap sequence, logs, backup current state vs
planned, common operational tasks, and known limitations with ADR links.
Closes#399
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Clarify docs/ARCHITECTURE.md link with interim pointer to
docs/architecture/c4-diagrams.md until DOC-2 PR merges
- Remove ./mvnw checkstyle:check — no checkstyle plugin in pom.xml;
replace with ./mvnw test and ./mvnw clean package -DskipTests
Refs #398
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers environment setup, daily workflow, three walkthroughs (add domain,
add endpoint, add frontend page), and a conventions reference. All file
paths verified against current main. Walkthroughs follow TDD order (Red
before Green). Resolves all persona feedback from issue #398.
Closes#398
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Single pointer line at the top: humans read README.md, LLMs read CLAUDE.md.
No existing content removed — full migration is DOC-7's responsibility.
Refs #395
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Five-section front door for new contributors: product description,
subsystem map, quick-start (local dev + full Docker variant), where-to-go-next
with TODO markers for DOC-2/4/5, and one-line private license.
Corrects stale port reference (3000→5173, per vite.config.ts).
Links docs/GLOSSARY.md, docs/adr/, docs/architecture/c4-diagrams.md,
and Gitea issue tracker with LAN qualifier.
Closes#395
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a glossary pointer in the Code Style section so contributors
encounter domain terminology (Person vs AppUser, etc.) at the right moment.
Refs #397
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a temporary GLOSSARY link at the top of the C4 diagrams document.
DOC-2 (ARCHITECTURE.md) will own the permanent cross-reference when it lands.
Refs #397
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Disambiguates all overloaded terms in the codebase: Person vs AppUser,
Chronik (internal) vs Aktivität (user-facing), TranscriptionBlock polygon
vs bounding box, DocumentVersion append-only convention, OcrJob lifecycle,
SenderModel as persistent entity, Audit log DB-layer caveat, and more.
Includes Pending Terms section for audit follow-ups (#388–#392).
Refs #397
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces a separate reset@familyarchive.local / reset123 seed account
(e2e profile only) so the password-reset flow test never touches the
shared admin credentials.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
getByRole('button', { name: 'Fertig' }) matched two buttons at 1440px width:
the transcribe-mode Fertig button and 'Alle als fertig markieren'. Add exact: true.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All page.goto() calls in documents.spec.ts now use relative paths (/documents/{id})
so Playwright's configured baseURL is the single source of truth. Removes the
fragility of keeping process.env.E2E_BASE_URL in sync with playwright.config.ts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The test was using tagId=nonexistent-tag-id which is not a recognised search parameter;
the correct param is tag= (tag name). Updated the test and the coverage report to
accurately describe what is verified: text + tag filter AND combination. The sender
filter test remains an acknowledged gap noted in the report.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four concerns addressed:
- Persistence: reloads the detail page after save and re-asserts the tag link,
making the report's "after page reload" claim accurate
- Unique title: adds stamp to document title to prevent accumulation across runs
- Cleanup: afterAll deletes the test document
- Selector: replaces getByText(newTagName) with a[href*="?tag="] scoped to the tag link
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three concerns addressed:
- Race condition: "Familie" tag is renamed by admin tests; now seeds a unique
timestamped tag via a throwaway document PUT so J3 never depends on seeded data
- Chip selector: replaces getByText(/Familie/) with a[href*="?tag="] scoped to the
actual tag link in the metadata section
- Cleanup: afterAll deletes both the test document and the seeder document
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous regex /Importiert|Dokument|Import|Läuft|DONE|laufend/i was too broad —
it would match almost any German text on the page including unrelated copy. Replaced
with /Import läuft|Import abgeschlossen|Fehler:/ which matches only the three status
messages the mass import feature actually emits.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds docs/audits/e2e-coverage-report.md mapping all 12 critical journeys
to their test files. Fills the 6 coverage gaps with new e2e tests:
- J1: Register via invite code (auth.spec.ts)
- J3: Edit document tags via TagInput (documents.spec.ts)
- J4: Create brand-new tag via TagInput (documents.spec.ts)
- J5: Add SPOUSE_OF relationship on person edit page (persons.spec.ts)
- J6: Multi-filter search (text + date, text + tagId) (documents.spec.ts)
- J10: Notification bell opens dropdown (notification-deep-link.spec.ts)
- J11: Non-admin blocked from /admin/* (permissions.spec.ts)
- J12: Mass import trigger shows status (admin.spec.ts)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
35/35 mutations DETECTED across document, person, tag, user, geschichte,
notification, and OCR domains. No tautological tests found — the suite
is trustworthy on all critical paths. Closes issue #403.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
statusLabel() was a one-line alias for formatDocumentStatus() with no
additional behaviour. Remove it and update DocumentStatusChip.svelte to
call formatDocumentStatus() directly. Remove the corresponding alias
test suite from the spec file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the --ignore-pattern CLI flag with an entry in the ignores array in
eslint.config.js where ESLint's flat config manages all ignore rules. Add
inline comment explaining that $lib/paraglide and $lib/generated are
intentionally omitted from the boundaries/elements list and treated as external.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds src/lib/tag/__fixtures__/cross-domain.fixture.ts — a permanent fixture
that demonstrates the boundaries rule firing on a tag → person import. The
fixture is excluded from npm run lint via --ignore-pattern; run
npm run lint:boundary-demo to see it produce an error (exit 1).
Documents the full allow-list, the escape hatches ($lib/shared/ move, explicit
rule entry, eslint-disable-next-line), and the verify command in COLLABORATING.md.
Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds eslint-plugin-boundaries with one element type per Tier-1 domain and an
explicit allow-list encoding the architectural dependency graph:
- document may import from: shared, person, tag, ocr, activity, conversation
- geschichte may import from: shared, person, document
- ocr may import from: shared, document
- activity may import from: shared, notification
- all others (person, tag, user, notification, conversation): shared only
- routes may import from any domain
Default is 'disallow', so any unlisted cross-domain import is an error.
Two eslint-disable-next-line comments remain in shared/discussion where
person-domain helpers (getInitials, formatLifeDateRange) are needed to render
participant metadata; moving them to shared would lose the person-type context.
Closes#410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MissionControlStrip is a document-processing pipeline visualiser — it
imports document-domain components (SegmentationColumn, TranscriptionColumn,
ReadyColumn) and belongs in the document domain. It was placed in
shared/dashboard, creating a shared → document coupling that the upcoming
boundaries rule would block.
Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FieldLabelBadge is a generic UI primitive (additive/replace badge used in form
field labels). It lived in the document domain but was already imported by
PersonTypeahead (person domain), creating a person → document coupling.
Moving it to shared/primitives eliminates that cross-domain dependency.
Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These functions describe DocumentStatus display logic (dot colours, readable
labels) and belong in the document domain. They were incorrectly placed in
personFormat.ts. Moving them to documentStatusLabel.ts removes the
person → document dependency and prepares the codebase for the
boundaries/dependencies ESLint rule.
Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds eslint-plugin-boundaries@6.0.2 and eslint-import-resolver-typescript@4.4.4
as pinned devDependencies. Also adds the lint:boundary-demo script for running
the ESLint boundaries rule against the fixture file, and updates the lint script
to exclude __fixtures__ directories.
Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MassImportService delegates to other domain services (no direct repo
access), and AuditService only touches its own AuditLogRepository —
both pass the boundary rule cleanly. Closes the known hole flagged
by Sara and Markus in PR #428.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace substring contains() with a regex exact-segment match so a
domain whose name is a substring of another (e.g. "tag" in "tagging")
cannot silently escape the predicate and produce a false negative.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>