initiales Projektsetup als skeleton für fresh flask + architecture
This commit is contained in:
1 parent
34dc6b3fcb
commit
e5935be1e4
7 files changed
+320
-3
No files matched your search
@@ -0,0 +1,33 @@
|
|||||||
|
# AGENTS.md – Steuerzentrale für KI-Coding-Agenten
|
||||||
|
|
||||||
|
Dieses Dokument enthält strikte Anweisungen für KI-Assistenten und Coder-Agenten (z. B. Continue, Copilot, lokale LLMs), die an diesem Repository arbeiten.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Code-Style, Header- & Dokumentationspflicht
|
||||||
|
|
||||||
|
Jede neu erstellte oder modifizierte Quelltext-Datei (`.py`, `.j2`, `.html`, `.js`, `.css`) **MUSS** den standardisierten Dateikopf sowie entsprechende In-Code-Dokumentation tragen.
|
||||||
|
|
||||||
|
* **Dateikopf-Standard:** Autor `Björn Runden <br@runden.net>`.
|
||||||
|
* **PyDoc & Docstrings:** Jede Klasse, Funktion und Methode in Python-Dateien muss PyDoc-Docstrings enthalten.
|
||||||
|
* **Jinja2 / HTML-Kommentare:** Logikführende Jinja2-Templates (Schleifen, Makros, Modale, Bedingungen) müssen mit Kommentar-Blöcken versehen werden.
|
||||||
|
* **Details & Beispiele:** Read [`docs/coding-standards.md`](./docs/coding-standards.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Architektur-Vorgaben
|
||||||
|
|
||||||
|
* **Flask Blueprints:** Der Code MUSS modular über Flask-Blueprints strukturiert werden (keine monolithische `app.py`).
|
||||||
|
* **Datenbank:** Zugriff NIEMALS direkt über Roh-SQL oder Datenbank-CLIs, sondern AUSSCHLIESSLICH über **Flask-SQLAlchemy**.
|
||||||
|
* **Migrationen:** Schema-Änderungen müssen über **Flask-Migrate** (`flask db migrate`) abgebildet werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Regelwerke & Dokumente
|
||||||
|
|
||||||
|
Bitte lies vor der Bearbeitung spezifischer Module die folgenden Dokumente im Repository:
|
||||||
|
|
||||||
|
* **Header & PyDoc Standards:** Read [`docs/coding-standards.md`](./docs/coding-standards.md)
|
||||||
|
* **System-Architektur & DB:** Read [`ARCHITEKTUR.md`](./ARCHITEKTUR.md)
|
||||||
|
* **CI/CD & Deployment:** Read [`docs/deployment.md`](./docs/deployment.md)
|
||||||
|
* **Dev-Environment & Mocks:** Read [`docs/dev-guide.md`](./docs/dev-guide.md)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# ARCHITEKTUR.md – Systemarchitektur & Datenkonzept
|
||||||
|
|
||||||
|
## 1. Übersicht
|
||||||
|
|
||||||
|
Formeleon folgt einer entkoppelten Architektur:
|
||||||
|
* **Public Form API (`/api/v1`):** Nimmt Formular-Submissions von externen Mandanten-Webseiten entgegen.
|
||||||
|
* **Admin Dashboard (`/admin`):** Verwaltung von Mandanten, Formular-Layouts und Submissions.
|
||||||
|
* **Form Embed Snippet:** Ein leichtes JS-Script, das dynamisch Formulare rendert und Sicherheits-Tokens verarbeitet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Ordnerstruktur (Blueprint-Muster)
|
||||||
|
|
||||||
|
```text
|
||||||
|
formeleon/
|
||||||
|
├── AGENTS.md
|
||||||
|
├── ARCHITEKTUR.md
|
||||||
|
├── README.md
|
||||||
|
├── README.EN.md
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── Dockerfile
|
||||||
|
├── requirements.txt
|
||||||
|
├── app.py # Anwendungs-Initialisierung & Blueprint-Registration
|
||||||
|
├── models.py # SQLAlchemy Datenmodelle
|
||||||
|
├── routes/
|
||||||
|
│ ├── api.py # Blueprint: Public Submissions & Handshake (@api_bp)
|
||||||
|
│ ├── admin.py # Blueprint: Admin Panel & Config (@admin_bp)
|
||||||
|
│ └── auth.py # Blueprint: OIDC / Zitadel Handler (@auth_bp)
|
||||||
|
├── services/
|
||||||
|
│ ├── recaptcha.py # reCAPTCHA Validation & Mocking
|
||||||
|
│ ├── exporter.py # Stream-Export Logik (CSV/JSON/YAML)
|
||||||
|
│ └── mailer.py # E-Mail Versand (SMTP Relay)
|
||||||
|
├── static/
|
||||||
|
│ ├── js/ # Snippets & Mithril.js Admin UI
|
||||||
|
│ └── css/ # Bootstrap / Custom Styles
|
||||||
|
└── docs/
|
||||||
|
├── coding-standards.md # Header & PyDoc Spezifikation
|
||||||
|
├── deployment.md
|
||||||
|
└── dev-guide.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Datenmodell (SQLAlchemy)
|
||||||
|
|
||||||
|
Das Datenmodell nutzt ein flexibles JSON-Payload-Feld für die dynamischen Formulareingaben, um Schema-Änderungen pro Mandant ohne Tabellen-Umbau zu ermöglichen.
|
||||||
|
|
||||||
|
* **Tenant:** ID, Name, Public Key, Allowed Origins.
|
||||||
|
* **FormConfig:** ID, Tenant_ID, Name, Form-Structure (JSON).
|
||||||
|
* **Submission:** ID, FormConfig_ID, Payload (JSON), IP_Hash, Created_At.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Formeleon 🦎
|
||||||
|
|
||||||
|
> Multi-tenant, highly flexible form generator with seamless website integration and built-in bot protection.
|
||||||
|
|
||||||
|
*Diese Dokumentation auf Deutsch lesen: [README.md](./README.md)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Overview
|
||||||
|
|
||||||
|
Formeleon is a centrally hosted service (ChamäleonCloud) allowing multi-tenant clients to embed dynamic web forms into any website via a simple HTML/JavaScript snippet.
|
||||||
|
|
||||||
|
### Key Features
|
||||||
|
* **Seamless Integration:** Embed via lightweight JS snippet.
|
||||||
|
* **Flexible Schemas:** Dynamic JSON payloads stored via SQLAlchemy.
|
||||||
|
* **Security First:** OIDC authentication (Zitadel), Public-Key handshakes, Origin/Referer validation, and reCAPTCHA v3 integration.
|
||||||
|
* **UX & Anti-Bot:** Interactive button state management (traffic light / spinner).
|
||||||
|
* **Export & Reporting:** On-demand HTTP streaming exports (CSV/JSON/YAML) and automated email dumps.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Tech Stack
|
||||||
|
|
||||||
|
* **Backend:** Python 3.12, Flask (Blueprints), Flask-SQLAlchemy, Flask-Migrate
|
||||||
|
* **Frontend (Admin UI):** Bootstrap 5, Mithril.js
|
||||||
|
* **Auth:** OIDC / Zitadel
|
||||||
|
* **Deployment:** Docker, Gunicorn, Gitea Actions
|
||||||
@@ -1,3 +1,60 @@
|
|||||||
# README.md
|
# Formeleon 🦎
|
||||||
## Formeleon. Sichere Formulare nach Maß
|
|
||||||
|
> Mandantenfähiger, hochflexibler Formular-Generator mit nahtloser Website-Integration und integriertem Bot-Schutz.
|
||||||
|
|
||||||
|
*Read this in English: [README.EN.md](./README.EN.md)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Überblick
|
||||||
|
|
||||||
|
Formeleon ist ein zentral gehosteter Service (ChamäleonCloud), der es Webseitenbetreibern (Mandanten) ermöglicht, dynamische Formulare ohne Backend-Aufwand per HTML/JavaScript-Snippet in bestehende Webseiten einzubetten.
|
||||||
|
|
||||||
|
### Kern-Features
|
||||||
|
* **Nahtlose Integration:** Einbettung via JS-Snippet ("Chamäleon-Effekt").
|
||||||
|
* **Maximale Feldvariabilität:** Dynamische JSON-Payloads via SQLite/SQLAlchemy.
|
||||||
|
* **Integrierte Sicherheit:** OIDC-Integration (Zitadel), Public-Key Handshake, Origin/Referer-Validierung & reCAPTCHA v3 Support.
|
||||||
|
* **UX & Bot-Protection:** Integriertes Ampel-System (Laderad/Clearance) für Absende-Buttons.
|
||||||
|
* **Reporting & Export:** Daten-Exports (CSV/JSON/YAML) per Stream oder automatisierte E-Mail-Dumps.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Tech-Stack
|
||||||
|
|
||||||
|
* **Backend:** Python 3.12, Flask (Blueprint-Architektur), Flask-SQLAlchemy, Flask-Migrate (Alembic)
|
||||||
|
* **Frontend (Admin-Panel):** Bootstrap 5, Mithril.js / HTML5
|
||||||
|
* **Authentication:** OIDC via Zitadel (Admin-Panel)
|
||||||
|
* **Deployment:** Docker, Gunicorn, Gitea Actions (Runner)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Schnellstart (Dev-Mode)
|
||||||
|
|
||||||
|
1. **Repository klonen & Umgebung einrichten:**
|
||||||
|
```bash
|
||||||
|
python3 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Umgebungsvariablen konfigurieren:**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# DEV_MODE=true ist standardmäßig aktiviert
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Datenbank initialisieren & starten:**
|
||||||
|
```bash
|
||||||
|
flask db upgrade
|
||||||
|
flask run --port=5000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Dokumentation
|
||||||
|
|
||||||
|
* [`AGENTS.md`](./AGENTS.md) – Regelwerk und Anweisungen für KI-Coding-Agenten.
|
||||||
|
* [`ARCHITEKTUR.md`](./ARCHITEKTUR.md) – Detaillierte Systemarchitektur und Datenmodelle.
|
||||||
|
* [`docs/coding-standards.md`](./docs/coding-standards.md) – Header- und PyDoc-Dokumentationsstandards.
|
||||||
|
* [`docs/deployment.md`](./docs/deployment.md) – CI/CD-Pipeline und Docker-Deployment-Guide.
|
||||||
|
* [`docs/dev-guide.md`](./docs/dev-guide.md) – Entwickler-Handbuch, Mocking & Seeding.
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# Coding Standards & Header-Spezifikation
|
||||||
|
|
||||||
|
Dieses Dokument definiert die Richtlinien für Dateiköpfe, Dokumentation und Code-Kommentare im Projekt **Formeleon**. Alle von KI-Agenten oder Entwicklern erstellten Quelltexte müssen diesen Vorgaben entsprechen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Autor & Metadaten
|
||||||
|
|
||||||
|
* **Autor:** Björn Runden (`br@runden.net`)
|
||||||
|
* **Sprache im Code:** Englisch (Variablen, Funktionen, Modulnamen, Code-Kommentare).
|
||||||
|
* **Sprache der Dokumentation:** Deutsch.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Python Dateiköpfe & PyDoc Standards
|
||||||
|
|
||||||
|
### 2.1 Datei-Header (`.py`)
|
||||||
|
Jede Python-Datei beginnt mit folgendem Header:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# ==============================================================================
|
||||||
|
# Formeleon - Multi-tenant Form Generator
|
||||||
|
# Author: Björn Runden <br@runden.net>
|
||||||
|
# Module: <Modulname / Pfad>
|
||||||
|
# Description: <Kurze Beschreibung des Moduls>
|
||||||
|
# ==============================================================================
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 PyDoc für Funktionen, Methoden & Klassen
|
||||||
|
Jede Klasse, Funktion und Methode **MUSS** über einen PyDoc-Docstring dokumentiert sein:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def validate_handshake_token(public_key: str, origin: str) -> bool:
|
||||||
|
"""
|
||||||
|
Validates the client handshake request against the tenant registry.
|
||||||
|
|
||||||
|
:param public_key: Public API key transmitted by the client snippet.
|
||||||
|
:param origin: Origin/Referer header provided by the client request.
|
||||||
|
:return: True if the request origin matches allowed domains for the tenant, False otherwise.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Jinja2 & HTML Standards (`.j2`, `.html`)
|
||||||
|
|
||||||
|
### 3.1 Datei-Header
|
||||||
|
Jedes Jinja2-Template oder HTML-File beginnt mit einem Kommentar-Header:
|
||||||
|
|
||||||
|
```html
|
||||||
|
{# ==============================================================================
|
||||||
|
Formeleon - Multi-tenant Form Generator
|
||||||
|
Author: Björn Runden <br@runden.net>
|
||||||
|
Template: <Template Name>
|
||||||
|
Description: <Zweck des Templates>
|
||||||
|
============================================================================== #}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Dokumentation von Jinja2-Logik
|
||||||
|
Einfache Variablenersetzungen (`{{ user.name }}`) benötigen keinen Kommentar. Logikführende Blöcke (Schleifen, Modale, Bedingungen, Makros) **MÜSSEN** dokumentiert werden:
|
||||||
|
|
||||||
|
```html
|
||||||
|
{# Iterates over active form fields and renders the corresponding input control #}
|
||||||
|
{% for field in form_fields %}
|
||||||
|
<div class="mb-3">
|
||||||
|
{# Render dynamic field label #}
|
||||||
|
<label for="{{ field.id }}" class="form-label">{{ field.label }}</label>
|
||||||
|
<input type="{{ field.type }}" id="{{ field.id }}" name="{{ field.name }}" class="form-control">
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. JavaScript / CSS Standards (`.js`, `.css`)
|
||||||
|
|
||||||
|
### 4.1 Datei-Header
|
||||||
|
```javascript
|
||||||
|
/==============================================================================
|
||||||
|
* Formeleon - Multi-tenant Form Generator
|
||||||
|
* Author: Björn Runden <br@runden.net>
|
||||||
|
* Script: <Script Name>
|
||||||
|
* Description: <Zweck des Scripts>
|
||||||
|
*============================================================================*/
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Deployment & CI/CD Guide
|
||||||
|
|
||||||
|
## 1. Gitea Actions Workflow
|
||||||
|
|
||||||
|
Bei einem Push auf den `main`-Branch oder einem Release-Tag führt der Gitea-Runner automatisiert folgende Schritte auf dem Zielserver aus:
|
||||||
|
|
||||||
|
1. Code-Update via `git pull`.
|
||||||
|
2. Erstellen/Aktualisieren der Docker-Images.
|
||||||
|
3. Zero-Downtime Restart der Container via Docker Compose.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Docker Setup
|
||||||
|
|
||||||
|
Das System läuft in einem schlanken Gunicorn-Container hinter einem Reverse Proxy.
|
||||||
|
|
||||||
|
### `docker-compose.yml` (Auszug)
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
volumes:
|
||||||
|
- sqlite_data:/app/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
sqlite_data:
|
||||||
|
```
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Developer Guide & Local Emulation
|
||||||
|
|
||||||
|
## 1. Local Auth Bypass (Zitadel-Dummy)
|
||||||
|
|
||||||
|
Für die lokale Entwicklung auf `127.0.0.1` oder benutzerdefinierten Dev-Domains kann die OIDC-Authentifizierung umgangen werden.
|
||||||
|
|
||||||
|
In der `.env`:
|
||||||
|
```env
|
||||||
|
DEV_MODE=true
|
||||||
|
DEV_USER_ROLE=admin
|
||||||
|
DEV_TENANT_ID=tenant_dev_123
|
||||||
|
```
|
||||||
|
|
||||||
|
Ist `DEV_MODE=true` gesetzt, injiziert die Middleware automatisch eine Mock-Session für den angegebenen Dev-User, ohne Redirects zu Zitadel auszuführen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. reCAPTCHA v3 Mocking
|
||||||
|
|
||||||
|
Im Dev-Modus wird die Google reCAPTCHA API nicht kontaktiert.
|
||||||
|
|
||||||
|
* **Erfolg-Simulation:** Standardmäßig gibt der Mock-Service einen Score von `0.9` zurück.
|
||||||
|
* **Fehlschlag-Simulation:** Durch Setzen von `MOCK_RECAPTCHA_SCORE=0.1` in der `.env` kann das Abweisen von Spam-Submissions lokal getestet werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. CLI Commands & Maintenance
|
||||||
|
|
||||||
|
* **Datenbank-Seeding:** `flask seed-db` (Erstellt Test-Mandanten und Beispiel-Formulare).
|
||||||
|
* **E-Mail Dump Trigger:** `flask run-scheduled-export --tenant-id=<ID> --period=daily` (Führt datenbank-agnostischen Export via SQLAlchemy aus und versendet die Mail).
|
||||||
Reference in new issue
Block a user