diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 211f69c..460a245 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -233,7 +233,8 @@ Fachliche Annahmen, getroffen weil das Lastenheft an der Stelle keine eindeutige - `pod-hardening`: Frontend mit `readOnlyRootFilesystem`, `emptyDir` auf `/tmp` und `/app/.next/cache`, ohne Service-Account-Token, Ressourcen laut Spec §7. - `backend-roles`: `APICORE_ROLE=api` samt initContainern `migrate` und `seed` im Deployment `apicore-backend`, Deployment `apicore-worker`, CronJobs `apicore-job-`. Das neue Backend-Image (CMD nur `node dist/main.js`) geht nur zusammen mit dieser Komponente live. Ohne `APICORE_ROLE` bricht es den Start in Produktion ab, und ohne die initContainer liefe keine Migration. - `api-hpa`: HPA `apicore-backend` (`autoscaling/v2`, 1–2 Pods bei 70 % CPU); entfernt `replicas` aus dem Deployment. -- `overlays/encry/`: Namespace `apicore`, ConfigMaps, Ingresses (Traefik, Middleware `apicore-cloudflare-only@kubernetescrd`, cert-manager `letsencrypt-prod` mit HTTP-01), Image-Digests. Hosts, ConfigMap-Werte und Digests sind bis zum Rollout Platzhalter (`example.com`, `sha256:000…`). +- `overlays/encry/`: Namespace `apicore`, ConfigMaps, Ingresses (Traefik, Middleware `apicore-cloudflare-only@kubernetescrd`, cert-manager `letsencrypt-prod` mit HTTP-01), Image-Digests. Die ConfigMap-Werte sind seit 2026-10-15 die Live-Werte aus dem Cluster (Runbook Schritt 1, Commit `6e3e9ae`). Hosts und TLS in `ingress-*.yaml` und die Image-Digests sind bis zum Rollout noch Platzhalter (`example.com`, `sha256:000…`). +- `scripts/ensure-secrets.sh`: ergänzt fehlende Schlüssel in `apicore-backend-secret` und `apicore-telegram`, ohne vorhandene Werte zu ändern, und gibt nur Schlüsselnamen aus (`--dry-run` zeigt nur an). Die Secrets selbst legt der Inhaber an. - `tests/`: `manifest-policy.test.mjs` prüft das gerenderte Overlay (NetworkPolicies nach Kubernetes-Semantik, Pod-Härtung, Ressourcen, CronJobs, Migration, Digests, Live-Selektoren) und jeden Rollout-Schritt (DNS, Ingress, api → Postgres und alle DB-Clients bleiben erreichbar). `render-stages.mjs` rendert die Schritte 1, 2, 3 und 5 aus dem Overlay. Die CI (`.gitea/workflows/manifests.yml`, nur `push` und `workflow_dispatch`, kein `pull_request`, weil der Runner im Cluster läuft) rendert mit `kubectl kustomize`, validiert mit `kubeconform -strict` und führt den Test aus; kubectl, kubeconform und yq mit festen Versionen und SHA-256. - **Telegram-Secret.** `apicore-telegram` (Schlüssel `TELEGRAM_BOT_TOKEN`) bindet nur `apicore-worker` ein: als einzelne `secretKeyRef`-Variable mit `optional: true` am Haupt-Container, ohne `envFrom`, ohne Volume, nicht im initContainer. Die api bekommt das Secret nie. Fehlt es, startet der Worker normal, nur die Telegram-Schleifen laufen nicht. `TELEGRAM_BOT_USERNAME` steht in der ConfigMap `apicore-backend-config` (api und Worker lesen sie per `envFrom`; leerer Platzhalter, bis der Bot angelegt ist); das Token steht nie in einer ConfigMap. `manifest-policy.test.mjs` prüft für den Zielstand und jede Rollout-Stufe mit Worker: genau ein Worker-Pod, genau eine Token-Variable ohne Klartextwert, kein anderer Pod mit `TELEGRAM_BOT_TOKEN`. Einrichtung bei BotFather: je Umgebung ein eigener Bot, Gruppen aus (`/setjoingroups` → Disable), kein Webhook (der Worker ruft `getUpdates`). Der Worker läuft mit `replicas: 1`, weil der Versand das annimmt (Annahme 46); Claims und Empfangs-Lease bleiben auch mit mehr Pods korrekt. @@ -279,7 +280,7 @@ initContainer haben die Ressourcen der CronJob-Pods. Alle App-Pods laufen ohne S **Images:** Das Base-Image `node:22-alpine` ist in beiden Dockerfiles per Digest gepinnt; ein Update ist ein bewusster Commit mit neuem Digest. Die CI taggt nur noch `sha-` und Versionen, kein `latest`. Das Overlay setzt die Digests der gebauten Images. Bis Schritt 3 bleibt beim Backend der Digest des laufenden Images. -**Rollout:** nur nach dem Runbook im Plan `docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md`, jeder Schritt mit Freigabe des Inhabers: 0 Digests, 1 Overlay auf den Ist-Stand (Diff leer), 2 NetworkPolicies, 3 Rollen und Pod-Härtung, 4 Schlüssel trennen, 5 HPA. +**Rollout:** nur nach dem Runbook im Plan `docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md`, jeder Schritt mit Freigabe des Inhabers: 0 Digests, 1 Overlay auf den Ist-Stand (Diff leer), 2 NetworkPolicies, 3 Rollen und Pod-Härtung, 4 Schlüssel trennen, 5 HPA. Stand 2026-10-16: Im Cluster wurde noch kein Schritt angewendet; vorbereitet sind nur die ConfigMap-Werte aus Schritt 1. Live laufen das Backend-Image `sha-f5b1964` und ein Frontend-Image vom 2026-10-12, im Namespace gelten nur die drei Policies aus `rke2-cluster`. Fortschritt: Gitea-Issue „Rollout in den Cluster“ (#28). ## 8. Backup & Restore @@ -293,7 +294,7 @@ Der Seed (`node dist/seed.js`) läuft als zweiter initContainer `seed` nur im `a Scheitert die Migration, scheitert der initContainer und der neue Pod startet nicht. Wegen `maxSurge: 1` und `maxUnavailable: 0` läuft der alte Pod weiter. Die Hauptprozesse starten ohne Prisma-CLI. Die `startupProbe` der api (bis 5 Minuten) bleibt für das alte Image, das die Migration noch im `CMD` ausführt. -**Erster Admin-Zugang:** `prisma/seed.ts` legt beim allerersten Start (leere `User`-Tabelle) einen Administrator an (`SEED_ADMIN_EMAIL`/`SEED_ADMIN_PASSWORD`, Default `admin@apicore.local`/`ChangeMe123!`) und gibt URL (`FRONTEND_ORIGIN`), Benutzername und Passwort einmalig im Container-Log aus. Existiert der User schon (auch deaktiviert), passiert nichts – kein erneutes Log, kein erneutes Anlegen, damit spätere Passwortänderungen nicht durch veraltete Logs verwirrend überschrieben wirken und Zugangsdaten nicht bei jedem Neustart in die Logs wandern. Ersetzen: neuen Admin über `/settings/users` anlegen, dann den alten deaktivieren (Löschen gibt es nicht, siehe "Historie statt Löschen") – die Lockout-Sperre in `UsersService.assertNotLastSystemRoleUser` verhindert ohnehin, den letzten aktiven Admin zu deaktivieren. +**Erster Admin-Zugang:** `prisma/seed.ts` legt einen Administrator an, wenn es noch keinen Benutzer mit der Adresse `SEED_ADMIN_EMAIL` gibt (Standard `admin@apicore.local`). Das Passwort kommt aus `SEED_ADMIN_PASSWORD`; fehlt es, erzeugt der Seed ein zufälliges (kein fest eingebautes Standardpasswort). Er gibt URL (`FRONTEND_ORIGIN`), Benutzername und Passwort einmalig im Container-Log aus. Existiert der User schon (auch deaktiviert), passiert nichts – kein erneutes Log, kein erneutes Anlegen, damit spätere Passwortänderungen nicht durch veraltete Logs verwirrend überschrieben wirken und Zugangsdaten nicht bei jedem Neustart in die Logs wandern. Ersetzen: neuen Admin über `/settings/users` anlegen, dann den alten deaktivieren (Löschen gibt es nicht, siehe "Historie statt Löschen") – die Lockout-Sperre in `UsersService.assertNotLastSystemRoleUser` verhindert ohnehin, den letzten aktiven Admin zu deaktivieren. **Datensicherung:** Seit der Entscheidung, PostgreSQL selbst im Cluster zu betreiben (siehe CLAUDE.md), liegt die Backup-Verantwortung bei diesem Projekt, nicht mehr bei einem externen Cluster-/DBA-Betrieb. Umgesetzt als anwendungsseitiges `BackupModule` (`ApiCore-Backend/src/backup/`) statt der ursprünglich hier vorgesehenen reinen `pg_dump`/PITR-Strategie: diff --git a/ApiCore-Backend/.env.example b/ApiCore-Backend/.env.example index 8855f47..98359ad 100644 --- a/ApiCore-Backend/.env.example +++ b/ApiCore-Backend/.env.example @@ -56,6 +56,16 @@ BACKUP_CRON_SCHEDULE="0 3 * * *" # Wie viele der neuesten Backup-Dateien behalten werden, aeltere werden nach # jedem Lauf geloescht (Standard: 14). BACKUP_RETENTION_COUNT=14 +# Obergrenze fuer eine einzuspielende Backup-Datei in Bytes (Standard 50 MB, +# hoechstens 256 MB, weil der Upload komplett im RAM verarbeitet wird). +# Export und Zeitplan warnen, wenn eine Sicherung groesser wird. +# BACKUP_MAX_IMPORT_BYTES=52428800 + +# Erster Administrator (prisma/seed.ts): wird angelegt, wenn es noch keinen +# Benutzer mit dieser Adresse gibt. Ohne Passwort erzeugt der Seed ein +# zufaelliges und gibt es einmalig im Log aus. +# SEED_ADMIN_EMAIL=admin@apicore.local +# SEED_ADMIN_PASSWORD= # Encryption keys, one per purpose (AES-256-GCM, key derived per purpose with # HKDF): TOTP secrets, webhook signing secrets, backup files. Required in diff --git a/ApiCore-Backend/README.md b/ApiCore-Backend/README.md index 8f0f65f..6a28450 100644 --- a/ApiCore-Backend/README.md +++ b/ApiCore-Backend/README.md @@ -1,98 +1,44 @@ -

- Nest Logo -

+# ApiCore-Backend -[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 -[circleci-url]: https://circleci.com/gh/nestjs/nest +NestJS-API von ApiCore (TypeScript, Prisma, PostgreSQL). Alle fachlichen Funktionen liegen unter `/api/v1/...`. Überblick über das ganze Projekt: [`../README.md`](../README.md), Architektur: [`../ARCHITECTURE.md`](../ARCHITECTURE.md). -

A progressive Node.js framework for building efficient and scalable server-side applications.

-

-NPM Version -Package License -NPM Downloads -CircleCI -Discord -Backers on Open Collective -Sponsors on Open Collective - Donate us - Support us - Follow us on Twitter -

- - -## Description - -[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. - -## Project setup +## Einrichten ```bash -$ npm install +npm install +cp .env.example .env # DATABASE_URL, JWT- und Verschlüsselungs-Schlüssel setzen +npx prisma migrate dev # Schema anwenden (nur lokal; gegen Produktion nur migrate deploy) +npm run start:dev # http://localhost:3001 ``` -## Compile and run the project +Alle Variablen mit Bedeutung stehen in [`.env.example`](.env.example). Swagger unter `/api/v1/docs` ist nur mit `ENABLE_SWAGGER=true` erreichbar. + +## Laufrollen + +Ein Build, drei Einstiegspunkte (`ARCHITECTURE.md` Abschnitt 10): + +| Befehl | Rolle | Zweck | +|---|---|---| +| `npm run start:dev` / `node dist/main.js` | `api` (lokal ohne `APICORE_ROLE`: `all`) | HTTP-API; mit `all` laufen API und Worker in einem Prozess, nur für Entwicklung und Tests | +| `npm run worker` (`node dist/worker.js`) | `worker` | Zustellung der Outbox `DomainEvent`, Webhooks, Kalender-Sync, Wetter, Telegram; Health auf Port 3002 | +| `npm run job -- ` (`node dist/cli.js `) | `job` | `cleanup`, `daily-evaluation`, `task-templates`, `app-backup`, `rekey` (auch `rekey --dry-run`); im Cluster als CronJobs | + +In Produktion ist `APICORE_ROLE` Pflicht und `all` verboten. Migrationen laufen im Cluster als initContainer `migrate` (`prisma migrate deploy`), der Seed als initContainer `seed` (`node dist/seed.js`). + +## Prüfen ```bash -# development -$ npm run start - -# watch mode -$ npm run start:dev - -# production mode -$ npm run start:prod +npm run lint # eslint mit --fix +npm run typecheck # tsc --noEmit +npm test # Jest-Unit-Tests +npm run test:e2e # Jest-e2e gegen die Datenbank aus .env.test (vorher migrieren) +npm run build # dist/main.js, dist/worker.js, dist/cli.js, dist/seed.js ``` -## Run tests +Die e2e-Suites laufen parallel (`maxWorkers: 4` in `test/jest-e2e.json`) und scheitern dabei derzeit sporadisch; mit `npm run test:e2e -- --runInBand` sind sie grün ([Issue #32](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/32)). Der Image-Build (`Dockerfile`) führt Lint, Typecheck und Unit-Tests aus und bricht bei Fehlern ab; die e2e-Tests laufen dort nicht. -```bash -# unit tests -$ npm run test +## Aufbau -# e2e tests -$ npm run test:e2e - -# test coverage -$ npm run test:cov -``` - -## Deployment - -When you're ready to deploy your NestJS application to production, there are some key steps you can take to ensure it runs as efficiently as possible. Check out the [deployment documentation](https://docs.nestjs.com/deployment) for more information. - -If you are looking for a cloud-based platform to deploy your NestJS application, check out [Mau](https://mau.nestjs.com), our official platform for deploying NestJS applications on AWS. Mau makes deployment straightforward and fast, requiring just a few simple steps: - -```bash -$ npm install -g @nestjs/mau -$ mau deploy -``` - -With Mau, you can deploy your application in just a few clicks, allowing you to focus on building features rather than managing infrastructure. - -## Resources - -Check out a few resources that may come in handy when working with NestJS: - -- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework. -- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy). -- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/). -- Deploy your application to AWS with the help of [NestJS Mau](https://mau.nestjs.com) in just a few clicks. -- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com). -- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com). -- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs). -- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com). - -## Support - -Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). - -## Stay in touch - -- Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec) -- Website - [https://nestjs.com](https://nestjs.com/) -- Twitter - [@nestframework](https://twitter.com/nestframework) - -## License - -Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). +- `src//`: ein NestJS-Modul je Fachbereich (z. B. `colonies`, `inspections`, `treatments`, `honey-batches`, `compliance`, `hive`), dazu Querschnitt in `common`, `prisma`, `domain-events`, `worker`, `jobs`, `runtime`. +- `prisma/schema.prisma` und `prisma/migrations/` sind die einzige Quelle des Schemas; `prisma db push` wird nirgends verwendet. +- `test/`: e2e-Specs und gemeinsame Fixtures (u. a. `test/fixtures/hive-ops/`, die auch das Frontend nutzt). diff --git a/ApiCore-Frontend/README.md b/ApiCore-Frontend/README.md index e215bc4..3cab885 100644 --- a/ApiCore-Frontend/README.md +++ b/ApiCore-Frontend/README.md @@ -1,36 +1,32 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# ApiCore-Frontend -## Getting Started +Next.js-Oberfläche von ApiCore (App Router, TypeScript, Tailwind, shadcn/ui, TanStack Query). Die App spricht nur über die API des Backends; sie hat keinen eigenen Datenbankzugriff. Überblick über das ganze Projekt: [`../README.md`](../README.md), Seitenstruktur: [`../ARCHITECTURE.md`](../ARCHITECTURE.md) Abschnitt 2. -First, run the development server: +## Einrichten ```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +npm install +cp .env.example .env.local # API_URL, z. B. http://localhost:3001/api/v1 +npm run dev # http://localhost:3000 ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +`API_URL` ist eine Laufzeit-Variable: Im Cluster kommt sie aus der ConfigMap `apicore-frontend-config`, ein neuer Wert braucht keinen neuen Build. -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +Diese Next.js-Version (16) weicht von älteren ab; vor Änderungen die mitgelieferte Doku unter `node_modules/next/dist/docs/` lesen (siehe [`AGENTS.md`](AGENTS.md)). -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +## Prüfen -## Learn More +```bash +npm run lint +npm run typecheck # next typegen && tsc --noEmit +npm test # Vitest + React Testing Library +npm run build +``` -To learn more about Next.js, take a look at the following resources: +Der Image-Build (`Dockerfile`) führt Lint, Typecheck und Tests aus und bricht bei Fehlern ab. -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +## Offline -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +- Offline-Warteschlange in IndexedDB (`src/lib/offline/`), Band „Offline – X Einträge warten“, Sync bei Wiederverbindung mit Idempotenz-Schlüssel. +- Service Worker (`public/sw.js`, `public/sw-routes.js`) mit App-Hülle und Offline-Seiten unter `src/app/(app)/offline/` für den Kaltstart ohne Netz. +- „Stand laden“ holt die Daten eines Stands auf das Gerät; Abmelden löscht Pakete und Caches. Tokens werden nie gespeichert. diff --git a/CLAUDE.md b/CLAUDE.md index 3cdd047..d7bb2c0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,21 +1,26 @@ # ApiCore – Projektkontext für Claude Code -Digitale Imkereiverwaltung für Wabenhain. Fachliche Quelle der Wahrheit: [`docs/lastenheft.md`](docs/lastenheft.md). Architektur- und Modulschnitt: [`ARCHITECTURE.md`](ARCHITECTURE.md). Fortschritt/Aufgaben: [`TASKS.md`](TASKS.md). +Digitale Imkereiverwaltung für Wabenhain. Fachliche Quelle der Wahrheit: [`docs/lastenheft.md`](docs/lastenheft.md). Architektur- und Modulschnitt: [`ARCHITECTURE.md`](ARCHITECTURE.md). Fortschritt/Aufgaben: [`TASKS.md`](TASKS.md). Projektstand, offene Punkte und Inhaber-Aufgaben: Gitea-Issues, Einstieg über das Übersichts-Issue (verlinkt in [`README.md`](README.md)). ## Ordnerstruktur ``` ApiCore/ +├── README.md Einstieg: Zweck, Start, Prüfen, Betrieb, Doku-Landkarte, Projektstand ├── docs/lastenheft.md Fachliches Lastenheft (verbindlich) +├── docs/pruefung-2026-09.md Prüfberichte, Sicherheitsaudit, Bestandsbuch, AuDHD-Regeln +├── docs/erp-inventar-export.md Vertrag der Schnittstelle zu ERPNext +├── docs/superpowers/ specs/ (Designs je Teilprojekt) und plans/ (Umsetzungspläne mit Tasks, Rollout-Runbook) ├── ApiCore-Backend/ NestJS API (TypeScript, Prisma, PostgreSQL) ├── ApiCore-Frontend/ Next.js App Router (TypeScript, Tailwind, shadcn/ui) -├── deploy/k8s/ Kubernetes-Manifeste (Deployment, Service, Ingress, ConfigMap/Secret-Vorlagen) +├── deploy/k8s/ Kustomize: base/, components/, overlays/encry/, tests/, scripts/ (ARCHITECTURE.md Abschnitt 7) +├── .gitea/workflows/ CI: Backend-Image, Frontend-Image, Manifest-Prüfung ├── CLAUDE.md Diese Datei -├── ARCHITECTURE.md Modulschnitt, Auth-Flow, Entscheidungen/Abweichungen -└── TASKS.md Abhakbare Aufgabenliste (MVP / v1.x / Später) +├── ARCHITECTURE.md Modulschnitt, Auth-Flow, Entscheidungen/Abweichungen, Annahmen +└── TASKS.md Abhakbare Aufgabenliste (MVP / v1.x / Später / Fahrplan T3–T7 / Beute) ``` -Ein Git-Repo für beide Projekte gemeinsam, Root ist `ApiCore/`. Feature-Branches pro Modul, siehe TASKS.md. +Ein Git-Repo für beide Projekte gemeinsam, Root ist `ApiCore/`. Gearbeitet wird direkt auf `main`; größere Vorhaben bekommen vorher eine Spec und einen Plan unter `docs/superpowers/`. Commits werden gebündelt gepusht, weil jeder Push auf `main` die Image-Builds startet. Ausrollen ins Cluster nur mit Freigabe des Inhabers. ## Tech-Stack @@ -34,7 +39,7 @@ Voraussetzung Backend: laufende PostgreSQL-Instanz, `.env` mit `DATABASE_URL` (s cd ApiCore-Backend npm install npx prisma migrate dev # Schema anwenden -npm run start:dev # http://localhost:3001, Swagger unter /api/v1/docs +npm run start:dev # http://localhost:3001, Swagger unter /api/v1/docs nur mit ENABLE_SWAGGER=true # Frontend cd ApiCore-Frontend diff --git a/README.md b/README.md new file mode 100644 index 0000000..9b48192 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# ApiCore + +Digitale Imkereiverwaltung der Imkerei Wabenhain. ApiCore führt Bienenstände, Völker, Königinnen, Durchsichten, Varroa, Behandlungen und Fütterungen, die Kette Ernte → Schleuderung → Honigcharge → Lager → Abfüllung, Etiketten, Bestand und Herstellung. Dazu kommen Compliance (Bestandsbuch für Tierarzneimittel, Etikett-Pflichtangaben, Behördenpaket, Prüfbereitschaft), ein Saison-Autopilot mit Vorschlägen und ein Offline-Modus für die Arbeit am Stand. + +Fachliche Quelle der Wahrheit ist das Lastenheft [`docs/lastenheft.md`](docs/lastenheft.md). + +## Projektstand + +Was gebaut, geprüft, gemergt und ausgerollt ist, was offen ist und was der Inhaber tun muss, steht im Übersichts-Issue: +**[Projektstand und Übersicht](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/44)** · Inhaber-Aufgaben: [Sammelliste](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/43) + +Kurzfassung (Stand 2026-10-16): + +- Im Cluster läuft seit 2026-10-12 das Backend-Image `sha-f5b1964` mit dem Frontend vom selben Tag. +- Auf `main` fertig, aber noch nicht ausgerollt: Paket 0, Plattform-Rückgrat (Laufrollen `api`/`worker`/`job`, Ereignis-Outbox), T3 Erfassung am Stand, T4 Logik-Ketten und Saison-Autopilot, T6 Compliance, ERP-Inventar-Export und Beute L1. Der Rollout läuft nur Schritt für Schritt mit Freigabe des Inhabers ([Issue #28](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/28)). +- In Arbeit: Beute in 3D (L2–L5). Geplant: T5 Optik, T7 Spracherfassung. + +Die abhakbare Aufgabenliste je Modul steht in [`TASKS.md`](TASKS.md). + +## Aufbau + +``` +ApiCore/ +├── ApiCore-Backend/ NestJS-API (TypeScript, Prisma, PostgreSQL), /api/v1 +├── ApiCore-Frontend/ Next.js App Router (TypeScript, Tailwind, shadcn/ui), PWA +├── deploy/k8s/ Kustomize: base, components, overlays/encry, tests, scripts +├── docs/ Lastenheft, Prüfberichte, Schnittstellen, Specs und Pläne +├── .gitea/workflows/ CI: Backend-Image, Frontend-Image, Manifest-Prüfung +├── ARCHITECTURE.md Module, Datenfluss, Annahmen, Kubernetes, Backup, Sicherheit +├── CLAUDE.md Arbeitsregeln für Claude Code +└── TASKS.md Aufgabenliste +``` + +- **Backend:** NestJS 11, Prisma 7 gegen PostgreSQL 18, class-validator, JWT mit Refresh-Rotation, MFA (TOTP), Entra-ID-SSO, Rechte über `@RequirePermission` (fail-closed). Ein Image läuft in drei Rollen: `api` (HTTP), `worker` (Zustellung der Outbox, Webhooks, Kalender-Sync, Wetter, Telegram) und `job` (Kubernetes-CronJobs). Fachliche Folgen hängen an der Transactional Outbox `DomainEvent` in Postgres. Details: [`ARCHITECTURE.md`](ARCHITECTURE.md) Abschnitt 10. +- **Frontend:** Next.js 16 (App Router), TanStack Query, Vitest und React Testing Library. Offline-Warteschlange in IndexedDB, Service Worker mit App-Hülle für den Kaltstart ohne Netz. +- **Schnittstellen nach außen:** Wabenhain-Shop über `GET /api/v1/shop-sync` mit API-Schlüssel ([`docs/pruefung-2026-09.md`](docs/pruefung-2026-09.md)), ERPNext über `GET /api/v1/export/inventar/*` ([`docs/erp-inventar-export.md`](docs/erp-inventar-export.md)), Webhooks mit HMAC-Signatur, Microsoft-365-Kalender, Telegram-Erinnerungen, Wetter von Open-Meteo. + +## Lokal starten + +Voraussetzungen: Node.js 22, eine laufende PostgreSQL-Instanz. + +```bash +# Backend +cd ApiCore-Backend +cp .env.example .env # DATABASE_URL und Secrets eintragen +npm install +npx prisma migrate dev # Schema anwenden +npm run start:dev # http://localhost:3001, Rolle "all" (API + Worker in einem Prozess) + +# Frontend +cd ApiCore-Frontend +cp .env.example .env.local # API_URL zeigt auf das Backend +npm install +npm run dev # http://localhost:3000 +``` + +Gibt es noch keinen Benutzer mit `SEED_ADMIN_EMAIL` (Standard `admin@apicore.local`), legt der Seed (`npx prisma db seed` lokal, im Cluster der initContainer `seed`) einen Administrator an und gibt das Passwort einmalig im Log aus (siehe [`ARCHITECTURE.md`](ARCHITECTURE.md) Abschnitt 8). + +## Prüfen + +Je Projekt einzeln: + +```bash +# ApiCore-Backend/ +npm run lint && npm run typecheck && npm test && npm run build +npm run test:e2e # braucht eine Test-Datenbank; bei Problemen mit -- --runInBand + +# ApiCore-Frontend/ +npm run lint && npm run typecheck && npm test && npm run build + +# Manifeste (Repo-Root) +kubectl kustomize deploy/k8s/overlays/encry | kubeconform -strict -summary - +node --test deploy/k8s/tests/manifest-policy.test.mjs +``` + +Die CI baut bei jedem Push auf `main` die Images (Lint, Typecheck und Unit-Tests laufen im Image-Build) und prüft die Manifeste. Die Backend-e2e-Tests laufen bisher nur lokal ([Issue #32](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/32)). + +## Betrieb + +- RKE2-Cluster, Namespace `apicore`, Ingress über Traefik hinter Cloudflare. +- `deploy/k8s` ist die Quelle der Wahrheit (Kustomize). Rollout nur nach dem Runbook im Plan [`docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md`](docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md), jeder Schritt mit Freigabe des Inhabers. Vorher immer `kubectl diff -k deploy/k8s/overlays/encry`. +- Fehlende Secrets ergänzt `deploy/k8s/scripts/ensure-secrets.sh`; Werte stehen nie im Repo. +- Backups: In-App-Backup (verschlüsselt, CronJob `app-backup`) und täglicher `pg_dump` (CronJob `apicore-db-backup`), siehe [`ARCHITECTURE.md`](ARCHITECTURE.md) Abschnitte 7 und 8. + +## Doku + +| Datei | Inhalt | +|---|---| +| [`docs/lastenheft.md`](docs/lastenheft.md) | Fachliches Lastenheft (verbindlich) | +| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Modulschnitt, Auth, Rückverfolgbarkeit, Annahmen, Kubernetes, Backup, API-Sicherheit, Rückgrat, T4, T6, Beute | +| [`TASKS.md`](TASKS.md) | Aufgabenliste je Modul und Teilprojekt | +| [`docs/pruefung-2026-09.md`](docs/pruefung-2026-09.md) | Prüfmatrix, Bestandsbuch, Überwinterung, Sicherheitsaudit, AuDHD-Anpassung | +| [`docs/erp-inventar-export.md`](docs/erp-inventar-export.md) | Vertrag der Schnittstelle zu ERPNext | +| [`docs/superpowers/specs/`](docs/superpowers/specs/) | Designs: Bestandsabgleich, Rückgrat und Fahrplan, T4, T5, T6, T7, Beute | +| [`docs/superpowers/plans/`](docs/superpowers/plans/) | Umsetzungspläne mit Tasks und Rollout-Runbook | diff --git a/deploy/k8s/overlays/encry/kustomization.yaml b/deploy/k8s/overlays/encry/kustomization.yaml index 2bc90d8..1f48683 100644 --- a/deploy/k8s/overlays/encry/kustomization.yaml +++ b/deploy/k8s/overlays/encry/kustomization.yaml @@ -6,8 +6,9 @@ # Gewollte Platzhalter, nie so anwenden: # - Image-Digests sha256:000...: Runbook Schritt 0 traegt die Digests der # CI-Builds (sha-) und von postgres:18.6-alpine ein. -# - Hosts in ingress-*.yaml und Werte in configmap-*.yaml: Runbook Schritt 1 -# uebernimmt sie aus dem Live-Stand. +# - Hosts und TLS in ingress-*.yaml: Runbook Schritt 1 uebernimmt sie aus dem +# Live-Stand. Die Werte in configmap-*.yaml sind seit 2026-10-15 schon die +# Live-Werte (Commit 6e3e9ae). # # Backend-Digest: Das neue Image (CMD nur `node dist/main.js`) geht erst # zusammen mit components/backend-roles live (Runbook Schritt 3). Bis dahin diff --git a/docs/pruefung-2026-09.md b/docs/pruefung-2026-09.md index 1a7ae86..7791464 100644 --- a/docs/pruefung-2026-09.md +++ b/docs/pruefung-2026-09.md @@ -1,7 +1,8 @@ # Prüfung & Verbesserung ApiCore / Wabenhain – Arbeitsstand September 2026 -Branch in ApiCore: `improve/integrity-sync-audhd` (nicht gemergt, nicht gepusht). -Wabenhain: Commits direkt auf `main` (nicht gepusht). +ApiCore: entstanden auf dem Branch `improve/integrity-sync-audhd`, inzwischen vollständig in `main` (Commits vom 2026-09-27 bis 2026-10-01, ausgerollt mit dem Backend-Image `sha-f5b1964` am 2026-10-12). +Wabenhain: Commits direkt auf `main`, gepusht (u. a. `d38f430`, `5642f0c`, `3bc0693` liegen auf `origin/main`). +Offene Punkte aus diesem Bericht werden als Gitea-Issues geführt (ApiCore #39 „Offene Fachfragen aus der Prüfung September 2026“, #9 „AuDHD-Anpassung: Restpunkte“). Verifikationsstufen: **CR** = durch Codeprüfung beurteilt, **AT** = automatisiert getestet, **MP** = manuell im Browser geprüft (Desktop 1366 px + Mobil 390 px), **NV** = nicht verifiziert. @@ -63,8 +64,8 @@ Umgesetzt in Wabenhain `d38f430` (AT: Entscheidungslogik; CR: DB-Ablauf der Serv 1. ~~Zuständigkeit pro Feld im Sync~~ – erledigt. 2. ~~Eigene, versionierte Sync-Schnittstelle~~ – erledigt: `GET /api/v1/shop-sync` (Vertragsversion 1, Feld-Allowlist, Berechtigung `shop-sync:read`). Bewusst ohne „geändert seit“: kleine Datenmenge, Voll-Abgleich heilt verpasste Läufe selbst. Wabenhain nutzt sie seit `5642f0c`; seit `3bc0693` ausschließlich (kein Rückfall auf andere Endpunkte). 3. ~~Nur-Lese-API-Schlüssel~~ – erledigt: Verwaltung → Automatisierung → API-Schlüssel. Nur Hash gespeichert, Klartext einmalig angezeigt, Scope nur `shop-sync:read`, widerrufbar, optional befristet, „zuletzt benutzt“ sichtbar. Wabenhain liest nur noch `APICORE_API_KEY`; der Passwort-Login ist entfernt (`3bc0693`). -4. Ende-zu-Ende-Test beider Systeme gegen Test-Instanzen. -5. Merge/Push. +4. Ende-zu-Ende-Test beider Systeme gegen Test-Instanzen (offen, Issue #39). +5. ~~Merge/Push~~ – erledigt. ## Offen / Entscheidungen diff --git a/docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md b/docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md index 42ec5a1..652e014 100644 --- a/docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md +++ b/docs/superpowers/plans/2026-10-13-plattform-rueckgrat.md @@ -1,5 +1,7 @@ # Plattform-Rückgrat Implementation Plan +**Status (2026-10-16):** Alle 26 Tasks umgesetzt und gemergt (Commits `c01a388`, `cdd30cf`, Merge `7097fcd`). Nicht ausgerollt; das Rollout-Runbook unten ist noch bei keinem Schritt angewendet. Issues: [#13](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/13) (Paket), [#28](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/28) (Rollout). + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** ApiCore läuft aus einem Image in drei Rollen (`api`, `worker`, `job`). Fachliche Folgen hängen nicht mehr an direkten Service-Aufrufen nach dem Commit, sondern an einer dauerhaften Outbox (`DomainEvent`), die der Worker genau einmal je Handler zustellt. Zeitgesteuerte Arbeit läuft als Kubernetes-CronJob. Rate-Limits zählen über alle Pods. Schlüssel sind je Zweck getrennt. Die öffentliche Herkunftsseite verrät keinen Standort. Die Manifeste in `deploy/k8s` werden wieder zur Quelle der Wahrheit. diff --git a/docs/superpowers/plans/2026-10-13-t3-erfassung-am-stand.md b/docs/superpowers/plans/2026-10-13-t3-erfassung-am-stand.md index c41c290..6d1a5e7 100644 --- a/docs/superpowers/plans/2026-10-13-t3-erfassung-am-stand.md +++ b/docs/superpowers/plans/2026-10-13-t3-erfassung-am-stand.md @@ -1,5 +1,7 @@ # T3 Erfassung am Stand Implementation Plan +**Status (2026-10-16):** Tasks 1–17 umgesetzt und gemergt (Commits `c01a388`, `cdd30cf`). Offen nur die manuelle Prüfung der Foto-Metadaten auf einem echten Telefon. Nicht ausgerollt. Issues: [#14](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/14), [#38](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/38), Rollout [#28](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/28). + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Ein Imker erfasst am Bienenstand mit Handschuhen und ohne Netz Durchsichten, Varroa, Behandlungen und Fütterungen schnell und korrekt. Dazu gehören Standrunde, Sammelerfassung, Offline-Standmodus mit echtem Kaltstart und eine Navigation, über die jeder Bereich erreichbar ist. diff --git a/docs/superpowers/plans/2026-10-13-t4-logik-ketten.md b/docs/superpowers/plans/2026-10-13-t4-logik-ketten.md index 07de8fe..fc1bd8c 100644 --- a/docs/superpowers/plans/2026-10-13-t4-logik-ketten.md +++ b/docs/superpowers/plans/2026-10-13-t4-logik-ketten.md @@ -1,5 +1,7 @@ # T4 Logik-Ketten und Saison-Autopilot Implementation Plan +**Status (2026-10-16):** T4a (Tasks 1–22), T4b (23–33) und T4c (34–38) umgesetzt und gemergt (Wellen 1–11, zuletzt `9760ce1`, Browser-Fixes `7a14801`). Nicht ausgerollt. Issues: [#15](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/15), Folgepunkt `packagingSize` [#36](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/36), Rollout [#28](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/28). + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Was der Imker erfasst, wirkt weiter: Aus Durchsicht, Messung, Ableger, Behandlung und Pflanzenentwicklung entstehen datierte Vorschläge, je Volk „die nächsten 3 Schritte“ mit Begründung, Warnungen entlang der Honig-Kette, ein Bewegungsbuch der Honigcharge und Erinnerungen in der App und per Telegram. Automatik plant nie heimlich: Sie schlägt vor, der Imker übernimmt oder verwirft. diff --git a/docs/superpowers/plans/2026-10-14-t5-optik.md b/docs/superpowers/plans/2026-10-14-t5-optik.md index f3df62b..59881e7 100644 --- a/docs/superpowers/plans/2026-10-14-t5-optik.md +++ b/docs/superpowers/plans/2026-10-14-t5-optik.md @@ -1,5 +1,7 @@ # T5 Optik mit eigener Handschrift Implementation Plan +**Status (2026-10-16):** Noch nicht begonnen. Vorher Plan-Review und die Bewegungs-Sprache aus Beute-Spec §12.4 ergänzen; Inhaber-Fragen der Spec §16 vorläufig mit A/A/A. Issue: [#26](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/26). + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** ApiCore ist draußen am Stand lesbar und bedienbar (Sonne, Handschuhe, eine Hand) und erkennbar eine Imker-App: vier geprüfte Farbsätze (hell, dunkel, Sonne hell, Sonne dunkel), ein durchgesetzter Baukasten und die Wabenzelle als einziges Motiv (Waben-Standkarte, Mini-Waben-Marker, Lebenslinie, Bienenjahr-Rad, Markenzeichen). diff --git a/docs/superpowers/plans/2026-10-14-t6-compliance.md b/docs/superpowers/plans/2026-10-14-t6-compliance.md index b4b1e9e..3b2c404 100644 --- a/docs/superpowers/plans/2026-10-14-t6-compliance.md +++ b/docs/superpowers/plans/2026-10-14-t6-compliance.md @@ -1,5 +1,7 @@ # T6 Compliance-Autopilot „prüfungsfest“ Implementation Plan +**Status (2026-10-16):** Tasks 1–19 umgesetzt und gemergt (Wellen 1–6, `8a31c42` bis `8188e4c`, Browser-Fixes `e712c5d`). Nicht ausgerollt. Issues: [#16](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/16), Inhaber-Punkte nach dem Rollout [#34](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/34), Rollout [#28](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/28). + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Bei einer Kontrolle durch Veterinäramt oder Lebensmittelüberwachung legt Imkerei Wabenhain alles Verlangte sofort vor: ein Bestandsbuch ohne „FEHLT“ (Katalog und Packungen füllen die Behandlung vor und buchen ab), Etiketten nur mit Pflichtangaben, ein Behördenpaket (Änderungshinweis, Anzeige als PDF, TSK-Zählung, Sperrbezirk) und eine Seite „Prüfbereitschaft“ mit jedem offenen Punkt in Rot und einem Knopf zum Beheben. diff --git a/docs/superpowers/specs/2026-10-12-plattform-rueckgrat-und-fahrplan-design.md b/docs/superpowers/specs/2026-10-12-plattform-rueckgrat-und-fahrplan-design.md index 02cadb3..55f0e80 100644 --- a/docs/superpowers/specs/2026-10-12-plattform-rueckgrat-und-fahrplan-design.md +++ b/docs/superpowers/specs/2026-10-12-plattform-rueckgrat-und-fahrplan-design.md @@ -1,5 +1,7 @@ # Plattform-Rückgrat und Ausbau-Fahrplan — Design +**Status (2026-10-16):** Rückgrat gebaut ([#13](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/13)), Paket 0 erledigt ([#12](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/12)), T3 ([#14](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/14)), T4 ([#15](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/15)) und T6 ([#16](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/16)) gebaut; nichts davon ausgerollt ([#28](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/28)). T5 ([#26](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/26)) und T7 ([#27](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/27)) haben eigene Specs, sind aber noch nicht gebaut. Die Liste „Offen“ in Abschnitt 11 ist der Befund vom 2026-10-12, nicht der heutige Stand. + Stand: 2026-10-12 · Betrifft: ApiCore (Backend, Frontend, `deploy/k8s`) ## 1. Ziel diff --git a/docs/superpowers/specs/2026-10-14-t7-sprache-design.md b/docs/superpowers/specs/2026-10-14-t7-sprache-design.md index ade438c..cf4b223 100644 --- a/docs/superpowers/specs/2026-10-14-t7-sprache-design.md +++ b/docs/superpowers/specs/2026-10-14-t7-sprache-design.md @@ -1,5 +1,7 @@ # T7 „Freihand“ (Spracherfassung) — Design +**Status (2026-10-16):** Spec fertig. Der Umsetzungsplan `docs/superpowers/plans/2026-10-16-t7-sprache.md` (6 Lieferungen, 25 Tasks) ist lokal geschrieben, aber noch nicht gepusht. Inhaber-Fragen aus Abschnitt 15 offen, noch nicht gebaut. Issue: [#27](https://git.encry.de/Nick.Rosenloecher/ApiCore/issues/27). + Stand: 2026-10-14 · Betrifft: ApiCore (Backend, Frontend, Whisper-Image, `deploy/k8s`) · Grundlage: Spec `2026-10-12-plattform-rueckgrat-und-fahrplan-design.md` §1, §2, §3, §5, §7 und §10 „T7“, Inhaber-Entscheidungen vom 2026-10-13, Muster aus T3 (Offline-Warteschlange v3, Foto-Warteschlange, Hinweise „Letztes Mal“) und T6 (Vorbelegung nur sichtbar, Annahmen als Einstellungen) ## 1. Ziel