Commit graph

13 commits

Author SHA1 Message Date
Till JS
90816de934 feat(api): Auto-Apply von Drizzle-Migrations beim Boot
Some checks are pending
CI / validate (push) Waiting to run
Folge-Adoption nach Pageta (mana/docs/playbooks/MIGRATIONS_BOOTSTRAP.md).
Versionierte Migrations lagen schon im Repo (src/db/migrations/), aber
ohne Auto-Apply-Hook würde ein Volume-Reset die DB schema-leer lassen
und Container-Restart liefe dann auf 500er gegen fehlende Tabellen.

- src/db/migrate.ts (runMigrations-Helper mit onnotice-Suppress)
- src/index.ts top-level-await Hook hinter _RUN_MIGRATIONS
- infrastructure/docker-compose.production.yml: _RUN_MIGRATIONS='true'

Idempotent über drizzle.__drizzle_migrations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 14:30:06 +02:00
Till JS
372832d266 refactor(big-bang): cards → wordeck im gesamten Code-Layer
Some checks are pending
CI / validate (push) Waiting to run
Phase 2 des cards→wordeck Big-Bang-Rebrand:

- 4 package.json: @cards/* → @wordeck/*
- packages/cards-domain/ → packages/wordeck-domain/
- 41+12 Files: from '@cards/domain' → '@wordeck/domain'
- pgSchema('cards') → pgSchema('wordeck') (Drizzle-Schema)
- 17 Files: process.env.CARDS_* → process.env.WORDECK_*
- docker-compose Service-Names: cards-* → wordeck-*
- docker-compose Volume: /Volumes/ManaData/cards → wordeck
- env-vars in compose: CARDS_DB_PASSWORD/_API_VERSION/_DSGVO_SERVICE_KEY etc. → WORDECK_*
- Log-Prefixes + Error-Strings + manifest-id 'cards' → 'wordeck'
- CORS-Origin cardecky.mana.how → wordeck.com
- .env.production.example umbenannt + S3-Key entfernt (kein MinIO mehr)

Type-Check 0 Errors in api+domain+web, 51/51 Domain-Tests grün.

DB-Rename + Container/Volume-Rename auf mana-server folgen in nächstem
Commit nach Verzeichnis-Rename.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 22:39:42 +02:00
Till JS
e3c84a9249 feat(text-only): Wordeck-Cutoff für Image-Occlusion + Audio + MinIO
Some checks are pending
CI / validate (push) Waiting to run
Ω-1: Text-Only-Architektur ist scharfgestellt.

Code-Cleanup:
- 4 Components gelöscht: ImageOcclusionEditor, ImageOcclusionView,
  AudioFrontView, AudioUploadField
- 3 API-Module gelöscht: routes/media.ts, services/storage.ts,
  db/schema/media.ts (mediaRefs + mediaFiles), routes/decks-from-image.ts
- packages/cards-domain: image-occlusion.ts + Tests entfernt,
  CardTypeSchema reduziert auf basic/basic-reverse/cloze/typing/multiple-choice
- 3 Web-Routes (study/[deckId], cards/new, cards/[id]/edit) bereinigt:
  Image-Occlusion- und Audio-Front-Code-Pfade raus
- anki/import.ts text-only: kein Media-Upload mehr, img/sound werden
  ersatzlos gestrippt
- 21 weitere Files bereinigt: dto, health, me, dsgvo, tools, cards,
  decks, share-handlers, marketplace/decks, marketplace/fork,
  marketplace/pull-requests, AnkiImport.svelte

DB-Migrationen (noch nicht gerannt, idempotent):
- 0004_wordeck_text_only.sql: DELETE image-occlusion/audio (0 betroffene
  Rows), media_files-Tabelle DROP, media_refs-Spalte DROP, CHECK
  cards.type IN (basic, basic-reverse, cloze, type-in, multiple-choice)
- 0005_wordeck_license_rename.sql: Cardecky-Personal-Use-1.0 →
  Wordeck-Personal-Use-1.0, Cardecky-Pro-Only-1.0 → Wordeck-Pro-Only-1.0,
  Default + CHECK + Backfill

Infrastruktur:
- docker-compose.production.yml: cards-minio-Service raus, MinIO-Envs
  aus cards-api raus, CARDS_PUBLIC_URL + PUBLIC_CARDS_API_URL auf
  wordeck.com / api.wordeck.com
- App-Manifest schon vorher auf wordeck umgestellt

Type-Check grün (api, domain, web — alle 3 Sub-Pakete).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 21:23:30 +02:00
Till JS
e68d53bfbb feat(infra): PUBLIC_APPLE_TEAM_ID für AASA-Endpoint
Some checks are pending
CI / validate (push) Waiting to run
mana e.V. Apple-Developer-Team-ID QP3GLU8PH3 ins cards-web-Service-
Environment in docker-compose.production.yml. Wird zur Runtime von
$env/dynamic/public aufgelöst und in
/.well-known/apple-app-site-association eingesetzt — Apple matched
das mit dem applinks:cardecky.mana.how-Entitlement in cards-native
(Bundle ev.mana.cards).

Aktivierung: docker compose -f docker-compose.production.yml up -d cards-web
auf mana-server. Verify nach Deploy:
  curl https://cardecky.mana.how/.well-known/apple-app-site-association
  → "appID":"QP3GLU8PH3.ev.mana.cards" statt XXXXXXXXXX.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 13:17:27 +02:00
Till JS
e1ddbf34b3 security(cards): fail-secure dev-stub, headers, rate-limit, dsgvo audit
Some checks are pending
CI / validate (push) Waiting to run
Behebt live verifiziertes Auth-Bypass auf cardecky-api.mana.how
(X-User-Id → founder-Tier) und zieht im selben Patch das fehlende
Operations-/Compliance-Fundament nach.

* Auth-Middleware fail-secure: opt-in via CARDS_AUTH_DEV_STUB="true"
  (war opt-out, Default true). Compose-Default flipped auf "false",
  NODE_ENV="production" für cards-api ergänzt, env-Template
  dokumentiert. vitest.config.ts + tests/setup.ts aktivieren den
  Stub gezielt für Test-Suiten.
* Security-Headers: Hono secureHeaders() in apps/api,
  SvelteKit hooks.server.ts mit X-Frame/X-Content-Type/Referrer/
  HSTS in apps/web. CSP bewusst ausgelassen — eigener Sprint.
* CORS-localhost-Whitelist nur außerhalb Prod.
* Rate-Limiting (in-memory sliding window, dependency-frei) auf
  share.receive 60/min/IP, media.upload 30/min/user,
  decks.generate + decks.from-image 10/min/user, dsgvo.* 10/min/IP.
* Health-Endpoint mit echter DB- und MinIO-Probe; /healthz bleibt
  Liveness, /healthz/details ist Readiness mit 503 bei Failure.
* DSGVO-Honesty: storage_ok + storage_error im Response (statt
  schluckend console.warn), Account-UI zeigt Fehler-Toast.
* Audit-Log: strukturierte JSON-Zeile (kind: "audit") auf stdout
  für /dsgvo/export, /dsgvo/delete, /me/export, /me/delete.
* Bug-Fix: duplizierte case "multiple-choice"-Clause in fsrs.ts.

Verifiziert: apps/api 17 Files / 104 Tests grün, apps/web check
0 errors. Deploy auf Mac Mini steht noch aus.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:56:03 +02:00
Till JS
5859e202c5 feat(cards): deck management UI + production auth portal wiring
Deck schema, API routes, and SvelteKit UI for creating and browsing decks
(DeckStack component, inline creation, floating nav). Production compose
updated with PUBLIC_AUTH_WEB_URL so cards-web redirects to auth.mana.how
for login/register instead of the raw API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 18:50:27 +02:00
Till JS
87a7a31ece fix(web): SvelteKit-env via \$env/dynamic/public statt import.meta.env
Some checks are pending
CI / validate (push) Waiting to run
Bug: Browser-Client requested localhost:3081 statt cardecky-api.mana.how
nach Login. Ursache: API_BASE und authBaseUrl() lasen die Variable
über import.meta.env.PUBLIC_*, was unter SvelteKit nicht zuverlässig
inlined wird (Vite-direct, ohne SvelteKit-Wrapper-Hook).

Fix: \$env/dynamic/public liest die env zur Runtime aus den Node-
Server-Variablen (adapter-node) — Browser bekommt sie über den
SSR-Init-Snapshot. Damit muss die Variable nur als runtime-env am
Container hängen, nicht als Build-Arg.

docker-compose.production.yml: PUBLIC_CARDS_API_URL und
PUBLIC_MANA_AUTH_URL aus build.args nach environment verschoben.
Build-Pipeline: cards-web muss neu gebaut werden, sonst greift der
Wechsel von static→dynamic env nicht.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:03:35 +02:00
Till JS
5b6d096f56 fix(prod-compose): pass MANA_AUTH_URL/MANA_CREDITS_URL/SERVICE_KEY/DEV_STUB into cards-api container
Some checks are pending
CI / validate (push) Waiting to run
2026-05-08 20:45:55 +02:00
Till JS
0dff79826d fix(prod): public URLs auf cardecky.* (war cards.* — bookmarks via nginx-301)
Some checks are pending
CI / validate (push) Waiting to run
2026-05-08 20:18:10 +02:00
Till JS
78a6c8fc77 fix(prod-compose): cards-api port 3091→3191 (3091 belegt)
Some checks are pending
CI / validate (push) Waiting to run
2026-05-08 20:13:46 +02:00
Till JS
464aee1661 fix(prod-compose): cards-minio port 9110→9210 (cadvisor belegt 9110)
Some checks are pending
CI / validate (push) Waiting to run
2026-05-08 20:13:06 +02:00
Till JS
a993cc28ca fix(prod-compose): cards-api needs NPM_AUTH_TOKEN build-arg
Some checks are pending
CI / validate (push) Waiting to run
cards-web hatte den Arg, cards-api nicht — Build schlägt 401 gegen
Verdaccio fehl, weil das .npmrc im Container die env nicht aufgelöst
bekommt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 20:10:39 +02:00
Till JS
045903b5b9 Phase 10a: Production-Deploy-Stack (Mac Mini)
Some checks are pending
CI / validate (push) Waiting to run
infrastructure/docker-compose.production.yml mit 4 Services:
  - cards-postgres :5436    (Plattform-Postgres :5432, Dev :5435 belegt)
  - cards-minio :9110/9111  (Plattform-MinIO :9000/9001 belegt)
  - cards-api :3091         (alt war :3072 — Cutover via Tunnel-Reroute)
  - cards-web :5181         (alt war :5180)

Persistente Volumes auf /Volumes/ManaData/cards/{postgres,minio} —
außerhalb des Repo-Verzeichnisses (überlebt repo-wipes, gleicher
Pfad wie mana-platform-Daten).

Dockerfiles:
  - apps/api: oven/bun:1.1-alpine, single-stage. pnpm via npm install.
    Verdaccio-Auth via NPM_AUTH_TOKEN-Build-Arg + .npmrc.
  - apps/web: 2-stage node:20-alpine. SvelteKit-build mit
    PUBLIC_CARDS_API_URL als Build-Arg (kommt direkt in den
    Client-Bundle via vite). Runtime startet adapter-node-Bundle
    direkt mit `node build/index.js`.

infrastructure/.env.production.example als committable Skeleton —
echte .env.production bleibt git-ignored. Vier Secrets nötig:
CARDS_DB_PASSWORD, CARDS_S3_SECRET_KEY, CARDS_DSGVO_SERVICE_KEY,
NPM_AUTH_TOKEN.

Hard-Cutover-Plan: alte mana-app-cards-{server,web} bleiben kurz
parallel laufend, Tunnel zeigt nach dem Build/Verify-Cycle auf die
neuen Container, dann werden die alten gestoppt + entfernt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 20:09:19 +02:00