- README.md: stack, run-locally, test/check/build, structure tree, data model summary, anti-abuse layers, scope notes, issue origin pointer. - docs/plans/feedback-feature.md: copied verbatim from flexsiebels for self-containment (single source of truth in this repo from now on).
75 lines
2.8 KiB
Markdown
75 lines
2.8 KiB
Markdown
# fdbck.msbls.de
|
|
|
|
Per-link feedback forms and live-chat masks. Anonymous, slug-gated, no auth required for participants.
|
|
|
|
Spun out from `m/flexsiebels.de` issue #63 — full design at [`docs/plans/feedback-feature.md`](docs/plans/feedback-feature.md).
|
|
|
|
## Stack
|
|
|
|
SvelteKit 5 + Svelte 5 + bun + `@sveltejs/adapter-node`. Postgres + Supabase auth. Schema: `fdbck.feedback_{instances,submissions,posts}` on `supa.flexsiebels.de` (msupabase).
|
|
|
|
## Run locally
|
|
|
|
```sh
|
|
cp .env.example .env # fill SUPABASE_*
|
|
bun install
|
|
bun run dev
|
|
```
|
|
|
|
## Test + check
|
|
|
|
```sh
|
|
bun run test # rate-limit + public-scope unit tests
|
|
bun run check # svelte-check (type errors / a11y)
|
|
bun run build # adapter-node production build → ./build
|
|
```
|
|
|
|
## Deploy
|
|
|
|
Dockerfile uses `oven/bun:latest`. Dokploy app: `fdbck.msbls.de`. DNS via Hostinger (handled out of band).
|
|
|
|
## Structure
|
|
|
|
```
|
|
src/
|
|
hooks.server.ts — auth + public-scope policy gate
|
|
lib/server/
|
|
auth.ts — cookie JWT + Supabase refresh
|
|
fdb.ts — Postgres `fdbck` schema accessor
|
|
feedback.ts — slug generator + DB helpers + rate-limit constants
|
|
public-scope.ts — anonymous-DB-access fail-closed gate
|
|
rate-limit.ts — in-memory token bucket
|
|
schemas.ts — Zod request validation
|
|
supabase.ts — admin + anon client singletons
|
|
routes/
|
|
+page.svelte — landing
|
|
f/[slug]/ — public participant page (form + live chat)
|
|
admin/feedback/ — m's admin (list + detail + create)
|
|
api/
|
|
auth/ — sign-in / sign-out
|
|
public/feedback/ — anonymous slug-gated endpoints
|
|
admin/feedback/ — owner-scoped admin endpoints
|
|
```
|
|
|
|
## Data model (canonical: design doc §5)
|
|
|
|
- `fdbck.feedback_instances` — slug, title, description, owner_user_id, form_definition (jsonb), chat_enabled, status (`open` | `closed`), closed_at
|
|
- `fdbck.feedback_submissions` — instance_id, display_name (nullable = anonymous), client_session_id, answers (jsonb), client_ip, user_agent
|
|
- `fdbck.feedback_posts` — instance_id, display_name, client_session_id, body, hidden (m soft-moderate), client_ip, user_agent
|
|
|
|
## Anti-abuse layers
|
|
|
|
- 32-char base62 slugs (~190 bits entropy)
|
|
- in-memory rate-limit (30 posts / 5 min, 10 submits / 5 min, per IP+slug)
|
|
- honeypot field on forms + chat (silently dropped)
|
|
- body length caps + closing kill-switch
|
|
- noindex meta + `robots.txt` Disallow: /
|
|
|
|
## Out of scope (v1)
|
|
|
|
Drag-drop form-builder · post reactions · realtime/SSE · CAPTCHA · trusted-tier owner sharing · branding/theming · auto-notifications. All have a clean upgrade path on the existing schema.
|
|
|
|
## Issue origin
|
|
|
|
`m/flexsiebels.de#63` — m PWA-voice 2026-05-05: *"Im Wesentlichen quasi Microsoft Forms und Teams-Feedback in einem auf einer Webseite."*
|