managarten/apps/api
Till JS e99fea1938 feat(forms): M3b public-submit endpoint — schließt den Public-Loop
Server-side Public-Submit für unlisted-shared Forms (Plan
docs/plans/forms-module.md M3.b):

- POST /api/v1/forms/public/:token/submit (apps/api):
  - Token-resolve via unlistedSnapshots-Tabelle (eq, limit 1).
  - Hard-blocks: 404 unbekannt, 410 revoked/expired, 400 wrong
    collection, 400 invalid JSON.
  - Schema-validiert serverseitig: filtert eingehende answers auf
    field-IDs aus dem Snapshot (anti-injection), prüft required
    Antwort-Felder + required consent-Felder.
  - Hashed IP (SHA-256, hex) als Anti-Spam-Fingerprint, plus
    User-Agent + Referer truncated, in submitterMeta.
  - Schreibt sync_changes(table='formResponses', op='insert', data,
    field_meta, actor='system:forms-public-submit', origin='system')
    in einer Transaktion mit set_config('app.current_user_id') für
    RLS — mirror vom articles import-extractor.
  - Token-scoped rate-limit (10/min) + IP-scoped (30/min), gleiche
    Architektur wie unlisted/public-routes.
  - Returns { ok: true, responseId, submittedAt }.

- SharedFormView (apps/mana/apps/web): handleSubmit POSTet jetzt an
  ${PUBLIC_MANA_API_URL || origin:3060}/api/v1/forms/public/:token/submit.
  Submitting-State (Disabled-Button + "Sende ..."), Error-Block bei
  Server-Fehlern, Submitter-Block (Name + Email, beide optional). Der
  DEV-Hinweis ist weg.

Encryption: server speichert plaintext im sync_changes-Blob. Der
Client-side Decrypt-Path ist no-op für non-encrypted shapes
(record-helpers.ts:241), also kein Crash beim Pull. Encrypted-at-rest
für public submissions ist M6 ZK-Mode (eigener per-Form-Key der
Form-Owner client-seitig hält).

Mounted pre-auth in apps/api/src/index.ts neben unlisted/public.

apps/api buildet (1769 modules, no TS errors). svelte-check:
0 errors in forms/. Forms-Modul ist End-to-End nutzbar — User legt
Form an, publisht, setzt visibility=unlisted, kopiert Share-Link,
externe Person füllt aus + sendet, Antwort landet im
ResponsesView des Owners.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 00:44:42 +02:00
..
drizzle feat(unlisted): M8.1 — backend foundation for shareable-link snapshots 2026-04-24 17:12:13 +02:00
scripts feat(wardrobe): module foundation — garments + outfits space-scoped data layer (M1) 2026-04-23 18:27:37 +02:00
src feat(forms): M3b public-submit endpoint — schließt den Public-Loop 2026-04-29 00:44:42 +02:00
Dockerfile fix(infra): include shared-ai + shared-rss in mana-api Dockerfile installer 2026-04-23 02:34:22 +02:00
drizzle.config.ts feat(unlisted): M8.1 — backend foundation for shareable-link snapshots 2026-04-24 17:12:13 +02:00
drizzle.presi.config.ts fix(presi): wire up db:push for presi schema via @mana/api 2026-04-12 14:32:44 +02:00
package.json feat(wardrobe): module foundation — garments + outfits space-scoped data layer (M1) 2026-04-23 18:27:37 +02:00
tsconfig.json fix(api): unblock tsc by dropping rootDir and allowing .ts imports 2026-04-15 18:51:26 +02:00