a57b481a7e
Merge feature/inbox-2: POST /api/requests/{id}/draft (AI German reply draft, never auto-send), extract OpenAiChatClient to Ai/, privacy stripping, 8 tests [god-QA pending]
2026-06-06 10:37:56 +02:00
27424c574f
Merge feature/feat-14c: Charakterbogen as preferred AI character source (suppress admin notes, weave traits to prose), +4 tests [god-QA pending]
2026-06-06 10:37:45 +02:00
8aab9d34f7
INBOX-2: POST /api/requests/{id}/draft - deutscher KI-Antwortentwurf (Datenminimierung: nur Anfragetext+ForSale-Liste, Zitat/Signatur-Stripping, 503 AiKeyMissing / 502 Upstream, speichert DraftReply)
2026-06-06 10:36:02 +02:00
6dabb5572c
INBOX-2: extract provider-agnostic OpenAiChatClient from SaleAdService (shared AI wire, public surface unchanged)
2026-06-06 10:36:01 +02:00
5ec04984c9
FEAT-14c: Charakterbogen im Sale-Ad-Prompt - Traits+Notiz als bevorzugte Charakterquelle (Notizen-Fallback), Webe-Regel statt Stichwortliste im Systemprompt; 4 Tests
2026-06-06 10:29:38 +02:00
2f089a902d
GEN-3b: import notation normalization (Uw=G, Sls, deaf flag, tags)
...
genotype.py:
- Uw/uw aliased to G/g (same locus) so the D2 conflict group + pure-Uw
cases stop being conflicts (Gg == Uwuw).
- Sls/WP recognized as a SECOND spotting locus (S(l)s(l)=WP het); carried
into mapped8locus alongside Sp (Sp+Sls = Superschecke).
- dea/Dea/taub/hörend -> hearing/deaf phenotype FLAG (not a locus).
- WFNZ/RV/GV/DP -> provenance/breeding tags (not genotype, not conflicts).
- test_genotype.py: zero-dep unit tests for all four.
extract.py: surface deaf+tags on animals; dedup conflict detection now
compares the NORMALIZED genotype key (mapped8locus) instead of the raw
string, so Uw=G no longer triggers a conflict. Result: Konflikte 32 -> 27,
Zucht-Splits stays 0. Dedup identity = name + DOB + Zucht.
Backend: Gerbil.IsDeaf (bool?) + additive migration AddGerbilDeafFlag
(has-pending-model-changes clean) + GerbilDto/GerbilInput round-trip.
ImportService sets IsDeaf from animal.deaf and preserves Sls + tags + deaf
in RawImportData (kept out of the 8-locus compact Genotype contract until
GEN-3a adopts them).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 10:26:01 +02:00
68366ad8c9
INBOX-3: SMTP send + Gmail threading (POST /api/requests/{id}/send)
...
- IGmailMailSender (mockable) + MailKit GmailMailSender (smtp.gmail.com:587 STARTTLS, App
Password). SendReplyService builds a threaded reply: In-Reply-To = original Message-Id,
References = stored chain + original (deduped), Subject = 'Re: ' (no double-prefix); sends,
then sets Status=Answered + AnsweredAt + stores sent body in DraftReply. Never auto-sends.
- POST /api/requests/{id}/send {body}: 200 updated RequestDto; 404 unknown; 503 MailNotConfigured;
502 MailAuthFailed (UI hint: re-enter App Password). No entity change (no migration).
- Tests (fake SMTP): threading headers, Answered transition, no-double-Re, not-configured +
auth-failure keep status; BuildMimeMessage header mapping. Live send gated on App Password.
2026-06-06 09:50:24 +02:00
958a2dbac0
INBOX-0: regenerate AddRequestsAndMailSettings migration after rebase onto WEB-0 (clean snapshot: CMS + INBOX, Up adds only Requests+MailSettings)
2026-06-06 09:43:01 +02:00
5d7cbc66bf
INBOX-0: Gmail request inbox backend (MailKit) + Request entity + sync/triage endpoints
...
- Request entity (GmailMessageId unique, ThreadId, threading headers, From*, Subject, BodyText,
ReceivedAt, Status enum-as-string New|InProgress|Assigned|Answered|Abandoned, AssignedContactId? FK,
DraftReply?, AnsweredAt?). MailSettings singleton (GmailAddress, AppPassword ENCRYPTED via Data
Protection, PollInterval, Folder, LastUid). Migration AddRequestsAndMailSettings.
- IGmailMailReader (mockable) + MailKit GmailMailReader (imap.gmail.com:993 SSL, envelope+X-GM-THRID
+body). RequestSyncService: dedup on Message-Id, track LastUid. MailKit 4.17.0.
- Endpoints: POST /api/requests/sync, GET /api/requests (Gridify, filter status), GET /api/requests/{id},
PUT triage (status+assignedContactId), GET/PUT /api/mail-settings (App Password never returned).
- Tests (in-memory DB + canned reader): sync dedup/idempotency/config-guard, HTTP sync->triage->assign,
mail-settings secrecy. + gitignore the runtime photo-storage/ dir (god housekeeping).
2026-06-06 09:39:36 +02:00
94f055f9bf
WEB-0: CMS content model + /api/site-snapshot + Page/Block CRUD
...
- Entities: Site (singleton, navOrder JSON), Page (slug/title/seoDescription/status enum),
Block (single table, Type enum + Data JSON; RichText=Markdown), Media. Migration
AddCmsEntities, seeds 6 Jimdo-mirror pages (placeholder Heading each; abgabetiere also an
auto AbgabetiereList block) + Site singleton nav.
- GET /api/site-snapshot: one JSON doc (site nav + pages + ordered blocks {id,order,type,data});
AbgabetiereList(auto) resolved from live ForSale gerbils -> {name, farbschlag, group(=Becken),
photos[urls], aiSaleText:null} (no price per god). SiteSnapshotService.
- CRUD: GET/POST/PUT/DELETE pages; add/update/delete blocks; PUT .../blocks/order reorder.
Block type allowlisted by enum; data validated as JSON object.
2026-06-06 09:21:20 +02:00
3afb04f646
FEAT-14a: Charakterbogen on Gerbil (traits + note) + sale-ad request extension
...
- Gerbil.CharacterTraits (List<string>, JSON text column, opaque labels) + CharacterNote
(string?). On GerbilDto + Input; round-trips on GET/POST/PUT. Additive migration.
- SaleAdAnimal gains Traits (German labels) + CharacterNote; prompt builder emits
"Charakter: …" + "Charakter-Notiz: …" lines for the AI Verkaufstext.
- Tests: traits/note round-trip (POST->GET via SQLite host), empty-default, prompt inclusion.
2026-06-06 09:10:30 +02:00
09f11cb4e3
SEARCH-1: separator-insensitive NameSearch + OriginBreeder (Herkunft) filter
...
- Gerbil.NameSearch (lowercase, strip whitespace/.-_) auto-synced in ApplicationContext
.SaveChanges; Gridify-filterable so 'clan kleine chaoten' matches 'Clan-Kleine-Chaoten'
(client strips separators the same way). GerbilSearch.Normalize shared helper.
- Gerbil.OriginBreeder (free-text Herkunft) on DTO+Input, set by the FEAT-8 import from the
source Zucht (imported animals have no OriginContact). Gridify-filterable.
- GET /gerbils/breeders: distinct non-empty OriginBreeder values for the Herkunft dropdown.
- Migration AddSearchFields (+ NameSearch backfill SQL for existing rows).
2026-06-06 09:01:12 +02:00
e87d0aafea
Merge feature/export-1: Datenexport (zip JSON+German CSVs) on /einstellungen + CI flake-cap [god-QA pending result-gate]
...
# Conflicts:
# GerbilManager.Tests/GerbilManager.Tests.csproj
# GerbilManagerWebAPI/Program.cs
# gerbil-manager-web/src/App.tsx
# gerbil-manager-web/src/components/AppShell.tsx
# gerbil-manager-web/src/pages/EinstellungenPage.tsx
2026-06-06 08:06:38 +02:00
db53fad5a4
Merge feature/feat-13: Abgabevertrag phase B — SaleContract+wizard, /einstellungen Zuchtprofil, contract endpoints w/ transactional Abgabe, Kontakt structured fields [god-QA: 40/40+47/47+e2e 56/56]
...
# Conflicts:
# GerbilManager.Tests/GerbilManager.Tests.csproj
# GerbilManagerWebAPI/Program.cs
2026-06-06 08:00:55 +02:00
0c05a5acf1
FEAT-13: SaleContract + BreederSettings entities (additive migration, join table justified in code docs), /contracts + /settings/breeder-profile Minimal-API endpoints w/ Abgabe-completion transaction + SQLite-backed endpoint round-trip tests (21/21)
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 07:55:34 +02:00
b7ee48401a
FEAT-8c: loader tests (in-memory DB + fixture) + public test helpers
...
6 tests: dry-run categorisation (no writes), execute loads conflict-free + links
high-confidence + quarantines conflict/stub, idempotency, ComposeGenotype (caret strip
+ ?? fill), ParseDate. Added EF InMemory to the test project.
2026-06-06 07:55:30 +02:00
ac5ab9d0ba
FEAT-8c: import loader — /import/dry-run + /import/execute (gated)
...
- Additive migration: Gerbil.RawImportData + Litter.PairingCode (Zuchtnummer der Verpaarung).
- ImportService consumes tools/import/output (animals.json + litters.json): litters first
(authoritative), then conflict-free animals with a DOB; high-confidence (hoch) litter links
set LitterId, date-only/ambiguous links quarantined; conflicts + stubs never loaded.
Genotype mapped8locus -> frozen compact string; rawGenotype+unmappedTokens preserved in
RawImportData; Farbschlag matched to ColorVariety; gender inferred from litter role;
provenance ImportSource/ExternalRef; idempotent (ExternalRef / Name+Date). Photos copied to store.
- ImportEndpoints: POST /import/dry-run (no writes, Julian-readable report) + /import/execute (gated).
2026-06-06 07:55:30 +02:00
f86a044143
EXPORT-1: GET /export - Zip mit export.json (volle Treue) + deutschen Excel-CSVs (Semikolon, BOM, TT.MM.JJJJ) + LIESMICH; 9 Tests (Escaping + API-Round-Trip)
2026-06-06 07:50:42 +02:00
42718606a9
Merge feature/ops-1: TrueNAS deployment (compose + backup sidecar + nginx proxy + prod Dockerfiles), Gitea CI draft, German ops guide [god-QA: 18/18+47/47+e2e 48/48]
2026-06-06 07:42:18 +02:00
36c97e8a7a
FEAT-12a: tests - prompt assembly, 503-unconfigured matrix, stub-provider parsing/auth, completions-URL config matrix (Gemini/Groq/Mistral/Ollama)
2026-06-06 07:37:42 +02:00
d9e5a757e9
FEAT-12a: POST /gerbils/sale-ad endpoint (503 AiKeyMissing when unconfigured, 502 AiUpstreamError) + DI wiring
2026-06-06 07:37:42 +02:00
f6bb13ca2f
FEAT-12a: provider-agnostic sale-ad AI core - AiOptions (env-only), German prompt builder w/ few-shot, OpenAI-compatible chat-completions client (no SDK)
2026-06-06 07:37:42 +02:00
daa6683405
FEAT-13: SaleContract + BreederSettings entities (additive migration, join table justified in code docs), /contracts + /settings/breeder-profile Minimal-API endpoints w/ Abgabe-completion transaction + SQLite-backed endpoint round-trip tests (21/21)
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 07:34:25 +02:00
2f2e5b1f56
OPS-1: Dockerfiles (net10 API + nginx frontend) + production config
...
- GerbilManagerWebAPI/Dockerfile: net7->net10 multi-stage; build context=repo
root (includes ServiceDefaults); port 8080 (.NET 10 container default)
- gerbil-manager-web/Dockerfile: drop VITE_API_BASE_URL build-arg; nginx proxies
/api/* to api:8080 (strip prefix), /scalar, /openapi/ -- one published port 80
- gerbil-manager-web/src/api/client.ts: default API_BASE_URL /api (relative),
no hostname coupling at build time; Aspire still injects absolute LAN URL in dev
- GerbilManagerWebAPI/Program.cs: run EF Migrate() at startup always (not Dev-only)
- GerbilManager.ServiceDefaults/Extensions.cs: expose /health + /alive in all
environments (compose healthcheck requires them in Production)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com >
2026-06-06 07:31:19 +02:00
aa79f9dbe5
Revert OPS-1 Windows-plan commits ( dada3af, 6a37f9e): superseded by TrueNAS deployment target; re-landed on main against GIT-3 — content preserved on Dwight's branch-to-be
2026-06-06 07:12:20 +02:00
3b3497079b
Merge feature/feat-13: Abgabevertrag generator phase A (template + pure OpenXml generator + 10 tests) [god-QA: 18/18]
2026-06-06 07:11:30 +02:00
dada3af968
OPS-1: startup scripts, autostart task, backup task, ops README, production config
...
- appsettings.Production.json: Photos:RootPath -> C:\gerbil-data\photos so
photo files land on a stable host path when ASPNETCORE_ENVIRONMENT=Production
- Start-GerbilManager.ps1: creates data dirs, sets Production env, launches
AppHost minimised; saves PID for Stop script
- Stop-GerbilManager.ps1: kills AppHost + Vite node processes by PID / port
- Register-AutoStart.ps1: Windows Scheduled Task on user logon (RunLevel Highest)
- Register-BackupTask.ps1: daily 03:00 Scheduled Task for Backup script
- deploy/README.md: Julian ops guide — start/stop commands, phone URL, DHCP
reservation, firewall rule (Public-profile Wi-Fi), backup/restore procedures,
prerequisites checklist, troubleshooting table (German)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com >
2026-06-06 07:11:09 +02:00
cbe77c927a
FEAT-13: ContractGenerator (pure OpenXml, embedded template, per-animal table cloning) + BreederProfile/ContractData records + 10 xUnit tests incl. schema validation & PII guard
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 07:09:07 +02:00
188b33618e
DATA-2: amendments — GerbilStatus.ForSale, Contact structured fields, 73-variety seed
...
- GerbilStatus += ForSale ("Abzugeben", FEAT-12 sale listing); enum-as-string, no DB change.
- Contact: contactInfo -> structured email/phone/address (FEAT-13 sale contracts); name/notes kept.
- ColorVariety seed 18 -> 73 from Kevin's GEN-2 colorVarietySeed.generated.json (18 frozen first).
- Regenerated InitialCreate migration (Contacts email/phone/address cols, 73 seed rows).
2026-06-06 01:07:19 +02:00
f3b1ecb7a3
FEAT-13: Abgabevertrag placeholder template from her sample contract (18 {{tokens}}, PII scrubbed incl. docProps/mailto-rel, animal photos removed, Zucht logo kept, boilerplate verbatim)
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 01:03:25 +02:00
7627468b82
DATA-2: optional list params + normalize frontend's '==' Gridify operator
...
- GridifyParams wrapper: nullable page/pageSize/filter/orderBy so list endpoints
work with no query params (Gridify's non-nullable int Page made [AsParameters]
treat them as required -> 400). Defaults page=1,pageSize=20.
- Normalize incoming filter '==' -> '=' : the frontend gridify.ts emits '==' for
equals (its convention) but Gridify's equals is '='. Safe (values are escaped;
!= >= <= =* contain no '=='). Fixes status==Active (frontend default that 500'd).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 01:00:35 +02:00
263ba32e3c
DATA-2: fresh Npgsql InitialCreate migration + ColorVariety seed (18)
...
8 tables (Gerbils, Litters, Contacts, Enclosures, ColorVarieties, GerbilPhotos,
HealthRecords, WeightRecords); enums as text columns; ColorVariety HasData seed
of the 18 GEN-1 base varieties. Replaces the prior pre-DATA-2 InitialCreate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 00:54:56 +02:00
180d53b203
DATA-2: new schema entities + Minimal API endpoints + Scalar + DAL teardown
...
- Entities: Breeder->Contact, +Enclosure/ColorVariety/GerbilPhoto/HealthRecord/WeightRecord;
Gerbil expanded (single Genotype text col, Status/Gender enums-as-string, FK ids,
ImportSource/ExternalRef provenance); Litter Strength->TotalBorn +ExpectedGoHomeDate/Notes.
ColorVariety HasData seed = 18 from GEN-1 catalog. Gerbil<->Litter cycle handled
(SetNull/Restrict). Enums stored as strings.
- Minimal API (no controllers): Endpoints/*.cs MapGroup+TypedResults for gerbils, litters,
contacts, enclosures, color-varieties, health/weight-records, inbreeding (converted from
controller, same routes/shapes), photos (Oscar contract: GET array/POST multipart/DELETE,
url /photos/files/{fileName}). Gridify paged {items,totalCount,page,pageSize}, camelCase,
409 conflict-deletes, flat FK ids, litter parent-gender validation (400 {code,...}).
- Scalar replaces Swashbuckle (AddOpenApi/MapOpenApi + MapScalarApiReference at /scalar);
launchUrl swagger->scalar. GenericRepository/UnitOfWork/Converters deleted; DbContext direct.
- InbreedingService reads real FK props now; pure calculator + 8 tests untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 00:53:49 +02:00
0c94a6ecd3
FEAT-1b: Inzuchtkoeffizient endpoints via Wright path method
...
- PedigreeCalculator: pure, EF-free Wright path-method engine (recursive F_A,
per-common-ancestor contributions, generationsAvailable, cycle guards)
- InbreedingService: loads pedigree from ApplicationContext shadow FKs
(Gerbils.LitterId, Litters.FatherId/MotherId) into in-memory maps
- InbreedingController: GET /gerbils/{id}/inbreeding-coefficient,
POST /genetics/test-inbreeding (hypothetical pairing for Probeverpaarung)
- Injects ApplicationContext directly; no Program.cs change (Dwight owns it)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-06 00:10:19 +02:00
3cf6413fcc
ARCH-2b: permissive LAN CORS + bind API on 0.0.0.0, drop HTTPS redirect
...
- AddCors lan policy (AllowAnyOrigin/Header/Method) — trusted home LAN, no auth
- Widen ASPNETCORE_URLS host localhost/127.0.0.1 -> 0.0.0.0 (keep Aspire-assigned port)
- Remove dev HTTPS redirection so phones reach the API over plain HTTP
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-05 23:46:59 +02:00
9b9cf2b35a
ARCH-2: apply EF migrations on startup in Development
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-05 23:37:42 +02:00
cc589b13d0
ARCH-2: fresh Npgsql initial migration
...
uuid keys, text columns, Gender persisted as text via EnumToStringConverter,
Litter.Date as timestamptz. Replaces deleted SqlServer initialCreate (no prod data).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-05 23:37:21 +02:00
84de905469
ARCH-2: wire PostgreSQL through Aspire
...
- AppHost: AddPostgres(postgres).WithDataVolume() + AddDatabase(gerbilmanager),
WebAPI project resource WithReference/WaitFor on the db (Aspire-generated credentials)
- WebAPI: AddNpgsqlDbContext<ApplicationContext>(gerbilmanager) replaces manual
AddDbContext/UseNpgsql + appsettings connection string
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-05 23:36:06 +02:00
4d541fe9cd
ARCH-2: add Aspire AppHost + ServiceDefaults (Aspire 13.4.2)
...
- New projects GerbilManager.AppHost / GerbilManager.ServiceDefaults (templates)
- Added both to GerbilManager.slnx
- WebAPI references ServiceDefaults; AddServiceDefaults + MapDefaultEndpoints wired
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-05 23:35:15 +02:00
8820cc7751
ARCH-2: swap EF provider to Npgsql, drop SqlServer migrations + conn strings
...
- Microsoft.EntityFrameworkCore.SqlServer -> Npgsql.EntityFrameworkCore.PostgreSQL 10.0.2
- UseSqlServer -> UseNpgsql (Aspire-injected gerbilmanager connection)
- Removed hardcoded sa connection strings from appsettings*.json
- Deleted SqlServer-flavored initial migration (fresh Npgsql one follows; no prod data)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-05 23:34:00 +02:00
b041d84b18
ARCH-2: bump TFM to net10.0, EF Core/OpenApi to 10.0.8, Swashbuckle to 10.2.1
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-05 23:32:47 +02:00
c337c3dfd5
Resolve all warnings
2023-10-30 22:08:02 +01:00
08983ba30d
Adjust
2023-10-30 21:58:56 +01:00
5792d2fcf4
Add database commits
2023-10-30 21:22:06 +01:00
6556e17146
Add first sanity check
2023-10-30 21:20:19 +01:00
d3d2b4b989
Implement generic repo pattern and unitofwork
2023-10-30 20:56:37 +01:00
Julian
dee8de7a15
Fix nullable
2023-10-30 17:18:23 +01:00
Julian
d58f874162
Add docker support
2023-10-30 16:39:14 +01:00
136ce48385
Fix reference empty guid
2023-10-23 21:42:56 +02:00
64a065058a
mark required fields
2023-10-23 21:34:00 +02:00