Commit Graph

588 Commits

Author SHA1 Message Date
Marcel
d76ee5fa31 fix(security): restrict DRAFT list to author — prevent cross-user draft leak
GeschichteService.list() now applies hasAuthor(currentUser()) whenever
status == DRAFT, so BLOG_WRITE users cannot read other users' unpublished stories.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 15:56:47 +02:00
Marcel
5146aeb568 feat(document): add DocumentSort.UPDATED_AT for reader dashboard feed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 15:56:47 +02:00
Marcel
5cd6ecc624 refactor(documents): split getDensity into resolve/load/aggregate (#385)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 11:44:37 +02:00
Marcel
86de118d63 refactor(documents): bundle density filters into a record (#385)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 11:42:38 +02:00
Marcel
00f35ab675 docs(documents): link density TODO to follow-up #481 (#385)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 11:39:47 +02:00
Marcel
c0a1f04df5 chore(documents): density endpoint produces=application/json (#385)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 11:38:29 +02:00
Marcel
c9be6cc165 test(documents): @Transactional rollback in DocumentDensityIntegrationTest (#385)
Replaces @DirtiesContext(AFTER_EACH_TEST_METHOD), which restarted
the full Spring context per test (≈10–15s × 7), with @Transactional
rollback. Each test still sees a clean slate via the spring-test
default rollback, but the context is shared across the class.

Wall time for this class dropped from 35s to 17.87s in local runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 10:53:48 +02:00
Marcel
ffe617dba8 docs(documents): note nullable minDate/maxDate on DocumentDensityResult (#385)
The empty-result case returns null for both bounds, which the TS
codegen surfaces as optional. Future contributors should not "fix"
the missing @Schema(REQUIRED) — it is deliberate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 10:52:03 +02:00
Marcel
47841b9110 refactor(documents): YearMonth.from(d).toString() for density key (#385)
YearMonth.from(d).toString() emits the same canonical YYYY-MM string
as the previous String.format("%04d-%02d", …) call but reads as a
single intent-revealing expression. Existing assertions on
"1915-08", "1916-01", … pin the output format unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 10:51:21 +02:00
Marcel
360db1ae33 chore(documents): drop V61 timeline density index migration (#385)
The index was added in anticipation of a SQL GROUP BY aggregation,
but DocumentService.getDensity aggregates in memory via
findAll(spec).stream(). The index is never touched by the current
query plan. Per Markus's round-2 review: drop the unused migration
to avoid mismatched rationale-vs-implementation debt. Revisit when
the archive crosses 50k rows (TODO already in getDensity Javadoc).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 10:49:24 +02:00
Marcel
6aceafda8e docs(documents): TODO for SQL aggregation at 50k rows (#385)
Documents the in-memory aggregation trade-off in getDensity so the next
perf audit knows the row-count threshold at which to revisit. Addresses
Markus's review concern.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 09:20:49 +02:00
Marcel
e92e9e452e feat(documents): make density endpoint filter-reactive (#385)
Density bars now recompute when other filters change so the chart always
matches the list it sits above. Selectable filters: q, senderId, receiverId,
tag (multi), tagQ, status, tagOp. Date bounds (from/to) are deliberately
omitted — the chart is the surface for picking those, so it must always
span the broader space the user is selecting within.

Architectural shift: drop the native SQL GROUP BY in favour of in-memory
grouping over the existing Specification-driven findAll. This composes for
free with all the search predicates (FTS-rank-then-filter, sender/receiver,
tag-with-descendants, tagQ partial match, status, tagOp) and keeps the
density implementation a thin layer on top of searchDocuments. At the
current archive size (~5k docs) this stays well under the p95 200ms target;
Cache-Control: max-age=300 absorbs repeated browse loads.

- Removes findDensityByMonth, findMinMaxDocumentDate, DocumentDateRangeProjection.
- Replaces DocumentService.getDensity(LocalDate, LocalDate) with the
  filter-aware overload.
- Endpoint accepts the same query params as /api/documents/search minus
  paging+sort+from+to.
- DocumentDensityIntegrationTest rewritten as @SpringBootTest covering
  no-filter / sender / tag / status / sender+tag combos via real PostgreSQL.
- DocumentServiceTest unit tests updated to the new signature.
- DocumentControllerTest tests forwarding of senderId+tag+tagOp and q+status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 23:06:47 +02:00
Marcel
1060be7def feat(documents): add GET /api/documents/density endpoint (#385)
Authenticated read endpoint backing the timeline density widget. Optional
from/to LocalDate query params narrow the aggregation. Response carries
Cache-Control: private, max-age=300 so repeated browse sessions skip the
aggregation query (per Tobias' devops review). No @RequirePermission needed —
inherits the global anyRequest().authenticated() rule.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 21:52:36 +02:00
Marcel
fbf4725e97 feat(documents): add DocumentService.getDensity (#385)
Maps the repository's Object[] rows into a DocumentDensityResult and pairs
them with the archive-wide min/max meta_date range. Read-only, no
@Transactional needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 21:50:05 +02:00
Marcel
c90b42d045 feat(documents): add density and date-range repository queries (#385)
Native SQL aggregations backing GET /api/documents/density:
- findDensityByMonth groups documents by truncated meta_date with optional
  from/to bounds (frontend fills zero-count gaps).
- findMinMaxDocumentDate returns the earliest/latest meta_date via projection,
  null on empty archive.

Covered by DocumentDensityIntegrationTest (Testcontainers PostgreSQL): empty
archive, single+multi-month grouping, from/to bounds, null meta_date exclusion,
min/max edge cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 21:47:59 +02:00
Marcel
e61e3797d1 feat(documents): add DocumentDensityResult and MonthBucket records (#385)
Response shape for the upcoming GET /api/documents/density endpoint.
minDate and maxDate are nullable (null on empty archive); buckets is always
present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 21:43:34 +02:00
Marcel
ce0c013f0f feat(documents): add document_date index for density aggregation (#385)
Issue #385 introduces GET /api/documents/density which aggregates documents
by month via date_trunc. Adding the index now keeps the query cheap as the
archive grows and removes a future-investigation tax.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 21:43:28 +02:00
Marcel
baa0a9811c chore: merge main into branch; resolve ChronikRow conflict
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 4m21s
CI / OCR Service Tests (pull_request) Successful in 42s
CI / Backend Unit Tests (pull_request) Failing after 3m36s
CI / Unit & Component Tests (push) Failing after 3m46s
CI / OCR Service Tests (push) Successful in 31s
CI / Backend Unit Tests (push) Failing after 3m17s
TODO/SECURITY placeholders from main are superseded by the #454 implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 20:05:12 +02:00
Marcel
9ef3c82398 fix(review): address review blockers from PR #475
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / OCR Service Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 3m51s
CI / OCR Service Tests (pull_request) Successful in 47s
CI / Backend Unit Tests (pull_request) Failing after 3m31s
- CommentData.java: add @Nullable on annotationId to match codebase convention
- DashboardService: isEmpty() → isBlank() for commentPreview null-guard
- ChronikRow.svelte: always set aria-label on comment rows (not only when preview present)
- ChronikRow.svelte.spec.ts: add test for aria-label on comment row without preview

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 19:54:56 +02:00
Marcel
708fd9d63e refactor(comment): promote CommentData to top-level record in comment package
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m32s
CI / OCR Service Tests (push) Successful in 47s
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 3m32s
CI / OCR Service Tests (pull_request) Successful in 38s
CI / Backend Unit Tests (pull_request) Failing after 3m25s
Moves the nested `CommentData` record out of `CommentService` into its own
`document/comment/CommentData.java` file, removing the cross-domain coupling
where `DashboardService` depended on an inner type of `CommentService`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 19:47:27 +02:00
Marcel
abe8ab8668 refactor(comment): remove dead findAnnotationIdsByIds; fix aria-label i18n; rename misleading test
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m36s
CI / OCR Service Tests (pull_request) Successful in 35s
CI / Backend Unit Tests (pull_request) Failing after 3m24s
CI / Unit & Component Tests (push) Failing after 3m30s
CI / OCR Service Tests (push) Successful in 38s
CI / Backend Unit Tests (push) Failing after 3m22s
- Remove `findAnnotationIdsByIds` from CommentService — no production caller exists now
  that DashboardService uses `findDataByIds` directly; along with its test coverage
- Fix aria-label construction in ChronikRow: pass actorName to i18n message function
  instead of manually prepending the actor, so all locales render correctly
- Rename `findDataByIds_does_not_truncate_at_exactly_120_chars` →
  `findDataByIds_preserves_content_at_exactly_120_chars` for accurate description

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 19:05:46 +02:00
Marcel
e877847b7e feat(dashboard): add commentPreview to ActivityFeedItemDTO; wire via findDataByIds()
ActivityFeedItemDTO gains a nullable commentPreview field (plain-text, 120 chars max).
DashboardService.getActivity() now calls findDataByIds() once instead of
findAnnotationIdsByIds(), halving DB round-trips for the Chronik page load.
Empty-string previews are normalised to null so the frontend can use ?? cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 17:55:02 +02:00
Marcel
7c25d08506 feat(comment): add findDataByIds() — batch-fetch annotationId + plain-text preview in one query
Replaces the single-purpose findAnnotationIdsByIds() (kept as delegation shim).
Introduces CommentData record (annotationId + preview) and stripAndTruncate()
using Jsoup.parse().text() for DOM-safe HTML stripping. Truncates to 120 chars.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 17:49:40 +02:00
Marcel
0fa90d58cb cleanup(legibility): convert TODOs to issue refs; justify naming violators
CLEANUP-2 (#413): convert two actionable TODOs to issue-referenced stubs
- +layout.server.ts:29 → TODO(#453) for dedicated admin stats endpoint
- ChronikRow.svelte: TODO(#454) for commentPreview; keep SECURITY line
  as standalone comment (XSS guard stays co-located with the risk)

CLEANUP-3 (#414): add one-line justification comments to both naming
violators — SecurityUtils and GlobalExceptionHandler are both justified
by framework convention; no rename needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 09:25:55 +02:00
Marcel
50b18f0849 docs(legibility): fix three review blockers in DOC-7
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m29s
CI / OCR Service Tests (push) Successful in 32s
CI / Backend Unit Tests (push) Failing after 3m29s
- 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>
2026-05-06 07:41:02 +02:00
Marcel
86c13a230c docs(legibility): migrate CLAUDE.md rules into human docs — DOC-7
Processes all 7 CLAUDE.md files according to the 3-bucket classification.
Migration targets (CONTRIBUTING.md, docs/ARCHITECTURE.md, docs/DEPLOYMENT.md,
domain READMEs) are introduced by DOC-2/4/5/6 — this PR must merge last.

### scripts/CLAUDE.md → scripts/README.md
New `scripts/README.md` with full script documentation (preserving the
⚠️ destructive-operation warning on reset-db.sh). `scripts/CLAUDE.md`
reduced to a pointer + "document new scripts in README.md" reminder.

### .devcontainer/CLAUDE.md → .devcontainer/README.md
New `.devcontainer/README.md` with all configuration, usage, and limitations.
`devcontainer/CLAUDE.md` reduced to a single pointer line.

### docs/CLAUDE.md → docs/README.md
New `docs/README.md` covering the folder structure, ADR guide, infrastructure
docs, and specs folder. `docs/CLAUDE.md` reduced to pointer + ADR reminder.

### ocr-service/CLAUDE.md
Reduced to pointer to `ocr-service/README.md` (content migrated in DOC-6).
Kept LLM reminders: single-node constraint, ALLOWED_PDF_HOSTS SSRF risk.

### backend/CLAUDE.md
- Layering Rules → pointer to docs/ARCHITECTURE.md
- Error Handling → pointer to CONTRIBUTING.md + reminder
- Security/Permissions → pointer to docs/ARCHITECTURE.md + reminder
- Package Structure → tagged TODO post-REFACTOR-1
- Fixed errors.ts path to frontend/src/lib/shared/errors.ts
- Added ANNOTATE_ALL + BLOG_WRITE to permission list
- Key Entities, Entity Code Style, Services → kept (Bucket-2)

### root CLAUDE.md
- Stack, Infrastructure, Dev Container → pointers
- Layering Rules, Error Handling, Security, OpenAPI, API Client,
  Date Handling, UI Components, Frontend Error Handling → pointers + reminders
- Package Structure → tagged TODO post-REFACTOR-1
- Domain Model, Entity Code Style, Form Actions, Styling → kept (Bucket-2)

### frontend/CLAUDE.md
- API Client Pattern, Date Handling → pointers + reminders
- Key UI Components → pointer to domain READMEs
- Styling, Form Actions, How to Run, Vite Proxy, i18n → kept (Bucket-2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 07:41:02 +02:00
Marcel
513fda2888 fix(docs): correct person/notification domain README signatures
Some checks failed
CI / OCR Service Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
- 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>
2026-05-06 07:36:38 +02:00
Marcel
995c696c6a docs(legibility): fix four more signature/accuracy blockers in domain READMEs
- 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>
2026-05-06 07:36:38 +02:00
Marcel
9b2ed48689 docs(legibility): fix two method signature blockers in domain READMEs
- 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>
2026-05-06 07:36:38 +02:00
Marcel
a1b89670c0 docs(legibility): add 18 per-domain README.md files (DOC-6)
Backend (9): document, person, tag, user, geschichte, notification,
ocr, audit, dashboard.
Frontend (8): document, person, tag, user, geschichte, notification,
ocr, shared.
OCR service (1): ocr-service/README.md.

Each README covers: what the domain owns, explicit non-ownership,
public surface (verified by grep against the codebase), internal
layout, and cross-domain dependencies.

Closes #400
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 07:36:38 +02:00
Marcel
39e7ee2c71 fix(e2e): use dedicated reset user instead of admin in password-reset test
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m34s
CI / OCR Service Tests (push) Successful in 37s
CI / Backend Unit Tests (push) Failing after 3m13s
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>
2026-05-05 21:17:00 +02:00
Marcel
0981355247 test(archunit): add Rule 2 coverage for importing and audit domains
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / OCR Service Tests (push) Successful in 36s
CI / Unit & Component Tests (pull_request) Failing after 3m33s
CI / OCR Service Tests (pull_request) Successful in 36s
CI / Backend Unit Tests (pull_request) Failing after 3m24s
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>
2026-05-05 17:59:08 +02:00
Marcel
0dd58556a7 test(archunit): fix foreignJpaRepositoryFor exact-segment matching
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>
2026-05-05 17:57:47 +02:00
Marcel
22ec808b2d test(backend): add ArchUnit domain boundary enforcement (Rules 1–4)
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m28s
CI / OCR Service Tests (push) Successful in 35s
CI / Backend Unit Tests (push) Failing after 3m17s
CI / Unit & Component Tests (pull_request) Failing after 3m25s
CI / OCR Service Tests (pull_request) Successful in 30s
CI / Backend Unit Tests (pull_request) Failing after 3m19s
Rules enforced:
- Rule 1: no @RestController may inject a JpaRepository directly (preserves @RequirePermission AOP enforcement)
- Rule 2: @Service classes access only their own domain's repositories, never a foreign domain's
- Rule 3: no @Configuration class (except @SpringBootApplication) in domain packages
- Rule 4: all @Entity classes reside in a domain package

Rule 5 (URL prefix per controller domain) deferred — tracked in #427.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 17:13:41 +02:00
Marcel
548df84219 test(annotation): wire TranscriptionBlockRepository mock and add cascade test
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m21s
CI / OCR Service Tests (pull_request) Successful in 32s
CI / Backend Unit Tests (pull_request) Failing after 3m20s
CI / Unit & Component Tests (push) Failing after 3m6s
CI / OCR Service Tests (push) Successful in 33s
CI / Backend Unit Tests (push) Failing after 3m9s
AnnotationService was changed to call transcriptionBlockRepository
directly, but the test still mocked TranscriptionService — causing a
NPE and leaving the cascade path uncovered.

Replace the @Mock TranscriptionService with @Mock
TranscriptionBlockRepository, update the two existing delete-test
verifications, and add a dedicated
deleteAnnotation_cascadesToTranscriptionBlocks test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:25:41 +02:00
Marcel
ef43cba4d7 refactor(document): remove dead DocumentService.updateThumbnailMetadata()
No production code calls this method since ThumbnailService was changed
to write thumbnail metadata via documentRepository.save() directly.
Removing the unreachable wrapper eliminates false coverage and noise
during future security audits.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:24:06 +02:00
Marcel
3db5b48cda test(document): remove dead updateThumbnailMetadata test
ThumbnailService now calls documentRepository.save() directly.
DocumentService.updateThumbnailMetadata() has no production callers,
so its test describes behaviour that no longer exists in the
production path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:22:58 +02:00
Marcel
16dacd8f4c fix(test): update ThumbnailAsyncRunnerTest to use DocumentRepository
ThumbnailAsyncRunner was changed to inject DocumentRepository directly
(breaking the DocumentService cycle), but the test still passed
DocumentService to the constructor — a type mismatch that prevented
the test suite from compiling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:22:23 +02:00
Marcel
fbbe0789d0 fix(document): break DocumentService ↔ ThumbnailAsyncRunner ↔ ThumbnailService cycle
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m29s
CI / OCR Service Tests (push) Successful in 38s
CI / Backend Unit Tests (push) Failing after 1m54s
CI / Unit & Component Tests (pull_request) Failing after 28s
CI / OCR Service Tests (pull_request) Successful in 36s
CI / Backend Unit Tests (pull_request) Failing after 1m49s
Spring Framework 7 prohibits constructor injection cycles even with @Lazy.
Replace DocumentService dependencies in ThumbnailAsyncRunner and ThumbnailService
with direct DocumentRepository calls — both are intra-domain reads/saves.
Update ThumbnailServiceTest to mock DocumentRepository accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 15:56:05 +02:00
Marcel
7e6e809aa4 fix(annotation): break AnnotationService ↔ TranscriptionService cycle
Spring Framework 7 prohibits constructor injection cycles even with @Lazy.
Replace the TranscriptionService dependency in AnnotationService with a
direct TranscriptionBlockRepository call for the cascade-delete, which is
an intra-domain operation within the document package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 15:55:33 +02:00
Marcel
c0d8704d6d docs: remove stale ExcelService from CLAUDE.md
ExcelService was deleted in fa60c5be. Both the root and backend
CLAUDE.md still listed it under importing/ and in the services table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:25:40 +02:00
Marcel
5f1c539fad docs: update package structure docs to reflect domain-based layout
Some checks failed
CI / Unit & Component Tests (push) Failing after 3m40s
CI / OCR Service Tests (push) Successful in 28s
CI / Backend Unit Tests (push) Failing after 3m0s
CI / Unit & Component Tests (pull_request) Failing after 3m39s
CI / Backend Unit Tests (pull_request) Failing after 3m27s
CI / OCR Service Tests (pull_request) Successful in 41s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:02:14 +02:00
Marcel
27e7fa9170 refactor(cleanup): delete empty legacy packages, move remaining test files to domain packages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 12:59:02 +02:00
Marcel
5e53a261fc refactor(shared): move remaining services to domain packages (stats→dashboard, filestorage, importing, notification, exception)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 12:55:51 +02:00
Marcel
930b1d23ce refactor(security): move SecurityConfig to security/ package
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 12:48:29 +02:00
Marcel
af2c983fe2 refactor(user): move user domain to user/ package, rename DataInitializer to UserDataInitializer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 12:45:30 +02:00
Marcel
e85057bed2 refactor(document): move document domain core to document/ package
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 12:39:20 +02:00
Marcel
bb7d872a61 refactor(document): move document sub-packages transcription/annotation/comment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 12:23:28 +02:00
Marcel
c0a1c9ff5f refactor(ocr): move ocr domain to package org.raddatz.familienarchiv.ocr
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 11:41:19 +02:00
Marcel
b41e1335d2 refactor(person/relationship): move relationship sub-package under person domain
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 11:35:09 +02:00