docs: AirCard-Implementierungsplan + Spec-Korrekturen aus Plan-Review
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0cd12c1ed3
commit
ba93d8f8c5
2 files changed
+415
-9
No files matched your search
@@ -48,7 +48,7 @@ Gitea knso/AirCardIOS ── Push main ── Webhook ──► aircard-build: g
|
||||
**Warum `/v1` über die eigene Domain:** Appwrite setzt das Session-Cookie auf die Domain des Requests (`'.' + Host`).
|
||||
Läuft `/v1` über `aircard-ios.org`, ist das Cookie first-party (`.aircard-ios.org`, Secure, HttpOnly),
|
||||
Safari blockiert es nicht, und das SDK braucht keinen localStorage-Fallback. Geprüft im Quellcode von Appwrite 1.8.1 und per Probe-Request mit Host `aircard-ios.org` (200 auf `/v1/health/version`).
|
||||
Der Header-Matcher `X-Appwrite-Project: aircard` sorgt dafür, dass über diese Domain nur das AirCard-Projekt erreichbar ist (keine Console, kein Portal). Das Web-SDK sendet den Header bei jedem Aufruf.
|
||||
Der Header-Matcher `X-Appwrite-Project: aircard` schaltet die Route nur für SDK-Aufrufe frei (das Web-SDK sendet den Header bei jedem Aufruf). Er isoliert **nicht**: Appwrite wertet `?project=` vor dem Header aus – wie unter appwrite.webklar.com ohnehin öffentlich. Dateien werden deshalb nie über `getFileView`/`getFilePreview`-URLs (Projekt als Query, ohne Header) geladen, sondern per `fetch` mit Header. Alle anderen `/v1`-Pfade beantwortet nginx mit 404, damit ein Routingfehler nicht als Seite durchgeht.
|
||||
|
||||
**Fallback**, falls die Route im Live-Test scheitert: Endpoint `https://appwrite.webklar.com/v1` wie bei eship (Web-Plattform `aircard-ios.org` eintragen, SDK nutzt dann den Cookie-Fallback).
|
||||
|
||||
@@ -99,7 +99,7 @@ Der Header-Matcher `X-Appwrite-Project: aircard` sorgt dafür, dass über diese
|
||||
|
||||
Unten links (x 0–620, y 779–969) bleibt frei, weil Wallet dort die letzten vier Ziffern einblendet.
|
||||
*Nur Bild* zeichnet nur das Hintergrundbild.
|
||||
Details **Hell** = Chip-Linien, Nummer, PLATINUM, Kontaktlos-Symbol und einfarbige Logos in Weiß (#FFFFFF); **Dunkel** = in #111111. Der Chip selbst ist eine helle bzw. dunkle Metallfläche (Verlauf).
|
||||
Details **Hell** = Nummer, PLATINUM, Kontaktlos-Symbol und einfarbige Logos in Weiß (#FFFFFF); **Dunkel** = in #111111. Der Chip ist eine helle bzw. dunkle Metallfläche (Verlauf) mit Kontaktlinien in Dunkelgrau (#7A7A7A) bzw. fast Schwarz (#0A0A0A), unabhängig von der Details-Farbe.
|
||||
|
||||
### Logo-Varianten (Kartennetzwerk, 18 Stück)
|
||||
|
||||
@@ -109,10 +109,10 @@ Details **Hell** = Chip-Linien, Nummer, PLATINUM, Kontaktlos-Symbol und einfarbi
|
||||
| Mastercard | Farbe (Symbol), Metallisches Silber (Symbol als Verlauf), Wortmarke (Symbol + „mastercard“ darunter), Silber + Text, Klassisch (altes Logo mit „MasterCard“ in den Kreisen) |
|
||||
| UnionPay | Farbe, Metallisches Silber, Weißer Rahmen (Farblogo mit weißer Kontur), Englisch (ohne chinesische Zeichen) |
|
||||
| American Express | Blau (Blue Box), Umriss (weiß/transparent), Select (Blue Box, kleiner) |
|
||||
| JCB | Farbe |
|
||||
| Discover | Wortmarke |
|
||||
| JCB | JCB |
|
||||
| Discover | Discover |
|
||||
|
||||
Dazu bei *Logo*: AirCards Symbol, AirCards Text, Apple, Kein Logo.
|
||||
Dazu bei *Logo*: AirCards · Symbol, AirCards · Text, Apple, Kein Logo (Wortlaut wie im Screenshot).
|
||||
Das AirCards-Symbol und der AirCards-Schriftzug werden nach dem Screenshot neu gezeichnet (eigenes SVG).
|
||||
|
||||
Quellen: bereinigte SVGs aus `/root/reports/aircard-marks-research/` (Wikimedia Commons bzw. offizielle Dateien, mit svgo bereinigt).
|
||||
@@ -170,14 +170,14 @@ Dateien unter `/home/webklar/apps/aircard-ios.org/`:
|
||||
|---|---|
|
||||
| `build/` | Klon des Repos (Arbeitsordner des Build-Containers) |
|
||||
| `out/` | gebaute Seite, von nginx ausgeliefert |
|
||||
| `deploy.sh` | aus ticket abgeleitet: Repo `knso/AirCardIOS`, Branch `main`, Unterordner `web/`, `npm ci`, `vite build`, `dist/` → `out/` |
|
||||
| `deploy.sh` | nach dem Vorbild ticket: Repo `knso/AirCardIOS`, Branch `main`, Unterordner `web/`, `npm ci`, `vite build`, `dist/` → `out/`; merkt sich den zuletzt **versuchten** Commit, damit ein kaputter Build nicht alle 15 Minuten wiederholt wird |
|
||||
| `webhook-server.js` | Kopie von ticket mit eigenen Variablen, Port 8087, **schlägt fehl, wenn das Secret fehlt** (statt durchzulassen) |
|
||||
| `nginx/aircard-ios.org.conf` | SPA-Fallback auf `index.html`, `^~ /assets/` 1 Jahr Cache, `index.html` ohne Cache, Sicherheits-Header, gzip |
|
||||
| `nginx/aircard-ios.org.conf` | SPA-Fallback auf `index.html`, `^~ /assets/` 1 Jahr Cache, `index.html` ohne Cache, `^~ /v1/` → 404, Sicherheits-Header, gzip |
|
||||
| `dev/` | Arbeitskopie für die Entwicklung (nicht gemountet) |
|
||||
|
||||
Compose (`/home/webklar/apps/docker-compose.yml`, vorher Backup `docker-compose.yml.bak-2026-10-04-aircard`):
|
||||
|
||||
- `aircard-build`: `node:20-alpine`, `init: true`, `mem_limit: 768m`, `NODE_OPTIONS=--max-old-space-size=512`, Build-Variablen `VITE_APPWRITE_ENDPOINT=https://aircard-ios.org/v1` und `VITE_APPWRITE_PROJECT_ID=aircard`, Webhook-Router `Host(aircard-ios.org) && Path(/webhook/deploy)` mit Priorität 200.
|
||||
- `aircard-build`: `node:22-alpine`, `init: true`, `mem_limit: 768m`, `NODE_OPTIONS=--max-old-space-size=512`, Build-Variablen `VITE_APPWRITE_ENDPOINT=https://aircard-ios.org/v1` und `VITE_APPWRITE_PROJECT_ID=aircard`, Webhook-Router `Host(aircard-ios.org) && Path(/webhook/deploy)` mit Priorität 200.
|
||||
- `aircard`: `nginx:alpine`, `mem_limit: 64m`, Router `Host(aircard-ios.org)` (websecure, Let's Encrypt) + HTTP→HTTPS-Weiterleitung.
|
||||
- Appwrite-Route als Datei `/home/webklar/apps/traefik/dynamic/aircard.yml` (Hot-Reload, kein Eingriff am Appwrite-Container): `Host(aircard-ios.org) && PathPrefix(/v1) && Header(X-Appwrite-Project, aircard)` → `appwrite@docker`, Priorität 150.
|
||||
- Gestartet wird **nur** `docker compose up -d aircard-build aircard` (ein nacktes `up -d` würde eship-build und lernen-build wieder anlegen).
|
||||
@@ -208,7 +208,7 @@ Last auf dem Server: nginx ca. 7 MB, Build-Container im Leerlauf 20–50 MB, bei
|
||||
- **Unit-Tests (Vitest)** für die reinen Module: `geometry` (alle Boxen im Canvas, Netzwerk-Logo in der Box rechts unten, nichts im Wallet-Freibereich), `crop` (Cover-Fit für Hoch-/Querformat, Zoom-Grenzen, Verschieben bleibt in der Fläche), `config` (Rundlauf serialize/parse, kaputtes JSON → Standard, unbekannte Variante → Standard), Dateiprüfung (Typ/Größe), `marks` (alle 18 Netzwerk- und 4 Logo-Varianten registriert, jede SVG-Datei vorhanden und ladbar).
|
||||
- **Setup-Skript**: `--check` gegen das echte Projekt muss „alles vorhanden“ melden.
|
||||
- **Abnahme nach Deploy** (im Browser über Claude in Chrome):
|
||||
- `curl -H 'X-Appwrite-Project: aircard' https://aircard-ios.org/v1/health/version` → `1.8.1`; ohne Header → Seite, nicht Appwrite.
|
||||
- `curl -H 'X-Appwrite-Project: aircard' https://aircard-ios.org/v1/health/version` → `1.8.1`; ohne Header → 404 von nginx.
|
||||
- HTTP → 301 HTTPS, Deep-Link `/karten` → 200, unsignierter POST auf `/webhook/deploy` → 401.
|
||||
- Bild hochladen, jede Vorlage, Stichprobe Netzwerk-Varianten, Hell/Dunkel, Download → PNG 1536 × 969.
|
||||
- Registrieren, Speichern, Neuladen, Karte öffnen, Umbenennen, Löschen. Cookie `a_session_aircard` mit Domain `.aircard-ios.org`, kein `cookieFallback` im localStorage.
|
||||
|
||||
Reference in new issue
Block a user