docs: README im Root, Backend/Frontend-READMEs, Statuszeilen (2026-10-16)
Neues README im Root mit Zweck, Aufbau, Start, Prüfbefehlen, Betrieb und Projektstand (Issues #44, #43). Backend- und Frontend-README ersetzen die Framework-Vorlagen. CLAUDE.md: Ordnerstruktur und echte Arbeitsweise (main, gebündelt pushen, Rollout nur mit Freigabe). ARCHITECTURE §7/§8: Live-ConfigMap, ensure-secrets.sh, korrektes Admin-Seed-Verhalten. .env.example um BACKUP_MAX_IMPORT_BYTES und SEED_ADMIN_* ergänzt. Statuszeilen in Plänen Rückgrat, T3–T6 und Specs Fahrplan, T7. Refs #42 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
b48fb157c8
commit
ec8c95056d
15 files changed
+194
-125
No files matched your search
+4
-3
@@ -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.
|
- `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-<name>`. 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.
|
- `backend-roles`: `APICORE_ROLE=api` samt initContainern `migrate` und `seed` im Deployment `apicore-backend`, Deployment `apicore-worker`, CronJobs `apicore-job-<name>`. 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.
|
- `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.
|
- `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.
|
- **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-<commit>` und Versionen, kein `latest`. Das Overlay setzt die Digests der gebauten Images. Bis Schritt 3 bleibt beim Backend der Digest des laufenden Images.
|
**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-<commit>` 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
|
## 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.
|
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 `[email protected]`/`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 `[email protected]`). 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:
|
**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:
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,16 @@ BACKUP_CRON_SCHEDULE="0 3 * * *"
|
|||||||
# Wie viele der neuesten Backup-Dateien behalten werden, aeltere werden nach
|
# Wie viele der neuesten Backup-Dateien behalten werden, aeltere werden nach
|
||||||
# jedem Lauf geloescht (Standard: 14).
|
# jedem Lauf geloescht (Standard: 14).
|
||||||
BACKUP_RETENTION_COUNT=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.
|
||||||
|
# [email protected]
|
||||||
|
# SEED_ADMIN_PASSWORD=
|
||||||
|
|
||||||
# Encryption keys, one per purpose (AES-256-GCM, key derived per purpose with
|
# Encryption keys, one per purpose (AES-256-GCM, key derived per purpose with
|
||||||
# HKDF): TOTP secrets, webhook signing secrets, backup files. Required in
|
# HKDF): TOTP secrets, webhook signing secrets, backup files. Required in
|
||||||
|
|||||||
+32
-86
@@ -1,98 +1,44 @@
|
|||||||
<p align="center">
|
# ApiCore-Backend
|
||||||
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
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).
|
||||||
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
|
||||||
|
|
||||||
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
## Einrichten
|
||||||
<p align="center">
|
|
||||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
|
||||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
|
||||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
|
||||||
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
|
||||||
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
|
||||||
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
|
||||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
|
||||||
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg" alt="Donate us"/></a>
|
|
||||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
|
|
||||||
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow" alt="Follow us on Twitter"></a>
|
|
||||||
</p>
|
|
||||||
<!--[](https://opencollective.com/nest#backer)
|
|
||||||
[](https://opencollective.com/nest#sponsor)-->
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
|
||||||
|
|
||||||
## Project setup
|
|
||||||
|
|
||||||
```bash
|
```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 -- <name>` (`node dist/cli.js <name>`) | `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
|
```bash
|
||||||
# development
|
npm run lint # eslint mit --fix
|
||||||
$ npm run start
|
npm run typecheck # tsc --noEmit
|
||||||
|
npm test # Jest-Unit-Tests
|
||||||
# watch mode
|
npm run test:e2e # Jest-e2e gegen die Datenbank aus .env.test (vorher migrieren)
|
||||||
$ npm run start:dev
|
npm run build # dist/main.js, dist/worker.js, dist/cli.js, dist/seed.js
|
||||||
|
|
||||||
# production mode
|
|
||||||
$ npm run start:prod
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 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
|
## Aufbau
|
||||||
# unit tests
|
|
||||||
$ npm run test
|
|
||||||
|
|
||||||
# e2e tests
|
- `src/<modul>/`: ein NestJS-Modul je Fachbereich (z. B. `colonies`, `inspections`, `treatments`, `honey-batches`, `compliance`, `hive`), dazu Querschnitt in `common`, `prisma`, `domain-events`, `worker`, `jobs`, `runtime`.
|
||||||
$ npm run test:e2e
|
- `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).
|
||||||
# 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).
|
|
||||||
+20
-24
@@ -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
|
```bash
|
||||||
npm run dev
|
npm install
|
||||||
# or
|
cp .env.example .env.local # API_URL, z. B. http://localhost:3001/api/v1
|
||||||
yarn dev
|
npm run dev # http://localhost:3000
|
||||||
# or
|
|
||||||
pnpm dev
|
|
||||||
# or
|
|
||||||
bun dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
## Offline
|
||||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
||||||
|
|
||||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
- 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.
|
||||||
## Deploy on Vercel
|
- „Stand laden“ holt die Daten eines Stands auf das Gerät; Abmelden löscht Pakete und Caches. Tokens werden nie gespeichert.
|
||||||
|
|
||||||
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.
|
|
||||||
@@ -1,21 +1,26 @@
|
|||||||
# ApiCore – Projektkontext für Claude Code
|
# 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
|
## Ordnerstruktur
|
||||||
|
|
||||||
```
|
```
|
||||||
ApiCore/
|
ApiCore/
|
||||||
|
├── README.md Einstieg: Zweck, Start, Prüfen, Betrieb, Doku-Landkarte, Projektstand
|
||||||
├── docs/lastenheft.md Fachliches Lastenheft (verbindlich)
|
├── 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-Backend/ NestJS API (TypeScript, Prisma, PostgreSQL)
|
||||||
├── ApiCore-Frontend/ Next.js App Router (TypeScript, Tailwind, shadcn/ui)
|
├── 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
|
├── CLAUDE.md Diese Datei
|
||||||
├── ARCHITECTURE.md Modulschnitt, Auth-Flow, Entscheidungen/Abweichungen
|
├── ARCHITECTURE.md Modulschnitt, Auth-Flow, Entscheidungen/Abweichungen, Annahmen
|
||||||
└── TASKS.md Abhakbare Aufgabenliste (MVP / v1.x / Später)
|
└── 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
|
## Tech-Stack
|
||||||
|
|
||||||
@@ -34,7 +39,7 @@ Voraussetzung Backend: laufende PostgreSQL-Instanz, `.env` mit `DATABASE_URL` (s
|
|||||||
cd ApiCore-Backend
|
cd ApiCore-Backend
|
||||||
npm install
|
npm install
|
||||||
npx prisma migrate dev # Schema anwenden
|
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
|
# Frontend
|
||||||
cd ApiCore-Frontend
|
cd ApiCore-Frontend
|
||||||
|
|||||||
@@ -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 `[email protected]`), 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 |
|
||||||
@@ -6,8 +6,9 @@
|
|||||||
# Gewollte Platzhalter, nie so anwenden:
|
# Gewollte Platzhalter, nie so anwenden:
|
||||||
# - Image-Digests sha256:000...: Runbook Schritt 0 traegt die Digests der
|
# - Image-Digests sha256:000...: Runbook Schritt 0 traegt die Digests der
|
||||||
# CI-Builds (sha-<commit>) und von postgres:18.6-alpine ein.
|
# CI-Builds (sha-<commit>) und von postgres:18.6-alpine ein.
|
||||||
# - Hosts in ingress-*.yaml und Werte in configmap-*.yaml: Runbook Schritt 1
|
# - Hosts und TLS in ingress-*.yaml: Runbook Schritt 1 uebernimmt sie aus dem
|
||||||
# uebernimmt sie aus dem Live-Stand.
|
# 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
|
# Backend-Digest: Das neue Image (CMD nur `node dist/main.js`) geht erst
|
||||||
# zusammen mit components/backend-roles live (Runbook Schritt 3). Bis dahin
|
# zusammen mit components/backend-roles live (Runbook Schritt 3). Bis dahin
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# Prüfung & Verbesserung ApiCore / Wabenhain – Arbeitsstand September 2026
|
# Prüfung & Verbesserung ApiCore / Wabenhain – Arbeitsstand September 2026
|
||||||
|
|
||||||
Branch in ApiCore: `improve/integrity-sync-audhd` (nicht gemergt, 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` (nicht gepusht).
|
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,
|
Verifikationsstufen: **CR** = durch Codeprüfung beurteilt, **AT** = automatisiert getestet,
|
||||||
**MP** = manuell im Browser geprüft (Desktop 1366 px + Mobil 390 px), **NV** = nicht verifiziert.
|
**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.
|
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).
|
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`).
|
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.
|
4. Ende-zu-Ende-Test beider Systeme gegen Test-Instanzen (offen, Issue #39).
|
||||||
5. Merge/Push.
|
5. ~~Merge/Push~~ – erledigt.
|
||||||
|
|
||||||
## Offen / Entscheidungen
|
## Offen / Entscheidungen
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Plattform-Rückgrat Implementation Plan
|
# 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.
|
> **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.
|
**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.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# T3 Erfassung am Stand Implementation Plan
|
# 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.
|
> **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.
|
**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.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# T4 Logik-Ketten und Saison-Autopilot Implementation Plan
|
# 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.
|
> **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.
|
**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.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# T5 Optik mit eigener Handschrift Implementation Plan
|
# 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.
|
> **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).
|
**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).
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# T6 Compliance-Autopilot „prüfungsfest“ Implementation Plan
|
# 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.
|
> **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.
|
**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.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Plattform-Rückgrat und Ausbau-Fahrplan — Design
|
# 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`)
|
Stand: 2026-10-12 · Betrifft: ApiCore (Backend, Frontend, `deploy/k8s`)
|
||||||
|
|
||||||
## 1. Ziel
|
## 1. Ziel
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# T7 „Freihand“ (Spracherfassung) — Design
|
# 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)
|
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
|
## 1. Ziel
|
||||||
|
|||||||
Reference in new issue
Block a user