Commit Graph
30 Commits
Author SHA1 Message Date
maro 906ea764ac feat: configure Payload SMTP email adapter 2026-09-16 21:35:40 +02:00
maro e26da639ce fix: add missing globals migration and await seed
CI / test (push) Canceled after 0s
CI / build-image (push) Canceled after 0s
2026-09-16 21:23:55 +02:00
maro 7c2b0ec2b5 fix: make setup safe in repository directory 2026-09-16 20:49:28 +02:00
maro 16bcdd2383 Reapply "ci: use GitHub Container Registry"
This reverts commit caf586f1ad.
2026-09-16 20:37:41 +02:00
maro caf586f1ad Revert "ci: use GitHub Container Registry"
This reverts commit b29b017341.
2026-09-16 20:37:12 +02:00
maro b29b017341 ci: use GitHub Container Registry 2026-09-16 20:31:07 +02:00
maro f03e0e17de Document GitHub Actions deployment secrets
CI / test (push) Canceled after 0s
CI / build-image (push) Canceled after 0s
2026-09-16 19:45:43 +02:00
maro 8c88b48580 Synchronize dependency lockfile for CI
CI / test (push) Canceled after 0s
CI / build-image (push) Canceled after 0s
2026-09-16 19:41:54 +02:00
maro 32e37d277f Add GitHub Actions build and deploy workflows
CI / test (push) Canceled after 0s
CI / build-image (push) Canceled after 0s
2026-09-16 19:40:40 +02:00
maro d0864e2911 Integrate LiveKit SFU and harden booking workflow 2026-09-16 19:38:28 +02:00
maro f1cd07b3ad CI/CD: build the Docker image once on main, promote it on release tags
CI / test (push) Failing after 11m55s
CI / build-image (push) Skipped
Previously release.yml fully rebuilt and re-ran lint/typecheck/test/build
from source on every tag push, duplicating what ci.yml had already just
verified on main. Now ci.yml builds and pushes the image (tagged by commit
SHA) once, right after its checks pass, but only for pushes to main.
release.yml no longer builds anything: it pulls that exact image, retags
it as the release version + latest, and deploys it.

This guarantees the deployed image is byte-for-byte what CI verified, and
turns "tag a commit that was never pushed to main or hasn't finished CI"
into a loud, immediate failure (no image to promote) instead of a rebuild
that silently skips the checks.
2026-09-06 22:24:07 +02:00
maro 526a908c80 Redesign: warmer, more editorial visual pass; remove stray em dashes
CI / test (push) Successful in 3m42s
Release / test (push) Successful in 3m44s
Release / build-and-deploy (push) Successful in 8m59s
Replaces em dashes with en dashes across all hardcoded copy, emails, and
seed content, then reworks the site's visual language so it reads as
deliberately designed rather than assembled from generic components:

- New ArrowLink component replaces ad hoc "Mehr erfahren ->" links and
  ghost buttons; one shared FormField (TextField/TextAreaField) replaces
  7 near-duplicate field styles across every form
- Navbar loses its glassmorphism blur for a solid warm background, gets a
  subtle active-link underline and a softer, warmer mega-menu
- PageHeader supports per-page blob tone/position and a compact mode
  instead of an identical band on every interior page
- Homepage: the core offer is featured large instead of four equal cards,
  the philosophy section gets a single calmer accent blob, blog teasers
  now show their cover image like the real /aktuelles page does
- Booking calendar and widget: 44px touch targets throughout (month nav,
  day cells, time slots, cancel action), a visible "today" ring, and
  responsive padding so the calendar isn't cramped on small screens
- Quieter, warmer empty states on /termine and /aktuelles

No functional changes: all interaction logic (nav menus, forms, booking,
CMS data fetching) is untouched, only markup and styling.
v1.1.0
2026-09-06 22:00:28 +02:00
maro 65b6eeac51 Add privacy-friendly analytics and cookie consent, integrated into the CMS
Adds a first-party analytics system with no third-party trackers and no
persistent per-visitor identifiers: events are grouped into sessions via a
daily-rotating pseudonymous hash (IP+UA+host, HMAC-salted, never stored raw).

- New "Analytics" section in the Payload admin, gated by a canViewAnalytics
  permission on Users, following the existing custom-admin-view pattern
  used by the calendar feature
- Sessions, page views, unique visitors, top/entry/exit pages, events,
  device/browser breakdown, date range filter with period comparison
- Raw events and daily aggregate rollups as their own collections, with
  configurable retention and a cron endpoint that rolls up before purging
- Cookie consent banner (necessary/preferences/statistics) with categories
  and copy editable from a new CMS global; a track() helper that is a
  complete no-op without statistics consent, so nothing is ever sent
  before a visitor opts in
- track() calls wired into the booking flow, contact form, and navigation
2026-09-06 21:59:59 +02:00
maro 82c4261a81 Fix security and correctness issues found in full-codebase audit
- Restrict meetingPassword field so it isn't leaked via the public REST/GraphQL API
- Fix booking slot computation to use Europe/Berlin time instead of the server's UTC clock
- Reset email verification when a customer changes their email address
- Fix ICS calendar injection via unescaped carriage returns in event descriptions
- Bind WebRTC meeting kicks to a persistent client id so they survive a rejoin
- Move the meeting signaling token out of the WebSocket query string into the first message
- Prevent duplicate signaling connections from leaking when the same participant reconnects
- Use the rightmost X-Forwarded-For entry for rate limiting (single trusted reverse proxy)
- Use constant-time comparison for the cron endpoint's bearer token
- Remove SVG from allowed Media upload types (stored-XSS risk, unused anyway)
- Add baseline security headers and a CSP to next.config.ts
- Fix CI/CD script injection via unsanitized git ref names in release.yml
2026-09-06 21:59:39 +02:00
maro 1b7dbad843 Add initial Payload migration
CI / test (push) Successful in 3m18s
Release / test (push) Successful in 3m13s
Release / build-and-deploy (push) Successful in 9m6s
v1.0.1
2026-08-26 00:45:59 +00:00
maroandClaude Sonnet 5 8d60d48bd0 Fix .env writer: quote values so shell metacharacters don't break source
CI / test (push) Successful in 3m14s
deploy.sh sources .env directly as bash (`set -a; source .env`), but
setup.sh wrote raw unquoted values. The default SMTP_FROM ("ANOUMA
<no-reply@...>") contains `<`/`>`, which bash parses as redirections,
failing with "syntax error near unexpected token `newline'" on every
deploy. Both scripts' env_set now write double-quoted values with
backslashes/quotes escaped — valid for both `source` and Docker
Compose's env_file parsing (which strips matching quotes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 02:12:24 +02:00
maroandClaude Sonnet 5 8d88363583 Fix release deploy: use bash for the deploy step's set -o pipefail
CI / test (push) Successful in 3m14s
Release / test (push) Successful in 3m10s
Release / build-and-deploy (push) Successful in 43s
Gitea Actions runs `run:` steps with `sh` by default, which doesn't
support bash's `set -o pipefail` ("Illegal option -o pipefail",
exit 2). node:22-bookworm-slim (Debian) includes bash, so declaring
shell: bash for this step fixes it without changing the base image.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v1.0.0
2026-08-26 01:13:45 +02:00
maroandClaude Sonnet 5 eca8e24fd9 Fix release deploy: use a Node-based image so checkout's JS action runs
CI / test (push) Successful in 2m58s
Release / test (push) Successful in 3m0s
Release / build-and-deploy (push) Failing after 36s
docker:27-cli is Alpine with no Node.js, but actions/checkout@v4 is a
JS action that needs a Node runtime in the job container — it failed
at Checkout with exit 127. node:22-bookworm-slim already has Node
(same reason the test job's node:22-alpine works); Docker CLI and
openssh-client are added via apt instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 00:42:29 +02:00
maroandClaude Sonnet 5 517f640666 Fix release deploy: give build-and-deploy a container with Docker CLI
CI / test (push) Successful in 3m5s
Release / test (push) Successful in 3m0s
Release / build-and-deploy (push) Failing after 10s
The runner (gitea-anouma-runner) runs as a Docker container itself
(gitea/runner:3) with the host's docker.sock mounted in, but no
`docker` CLI binary. A job with no `container:` runs directly inside
that minimal runner image, so `docker login/build/push` failed with
"docker: command not found". Using docker:27-cli gives the job the
CLI; the runner mounts the same host socket into it automatically
(sibling containers), and openssh-client is installed for the deploy
step's ssh call.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 00:33:10 +02:00
maroandClaude Sonnet 5 27aa625c0e Fix CI: run next typegen before tsc so route-aware types resolve
CI / test (push) Successful in 3m14s
Release / test (push) Successful in 3m7s
Release / build-and-deploy (push) Failing after 34s
This Next.js version generates LayoutProps/PageProps/RouteContext
into .next/types only via `next dev`, `next build`, or `next typegen`
(see node_modules/next/dist/docs .../06-cli/next.md). Typecheck ran
`tsc --noEmit` standalone before Build, so those globals didn't exist
yet, failing with "Cannot find name 'LayoutProps'".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 23:46:32 +02:00
maroandClaude Sonnet 5 bd38781502 Fix CI: scope NODE_ENV=production to the build step only
CI / test (push) Failing after 1m24s
Setting it job-wide made `npm ci` treat NODE_ENV=production as an
implicit --omit=dev, silently skipping eslint/typescript/test
devDependencies and failing Lint with "eslint: not found".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 23:43:12 +02:00
maroandClaude Sonnet 5 0cb99243c7 Trigger empty commit to test Gitea Actions after moving repo hooks to local disk
CI / test (push) Failing after 48s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 23:40:42 +02:00
maroandClaude Sonnet 5 5af7158368 Trigger empty commit to re-test Gitea Actions after hook resync
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 23:17:35 +02:00
maroandClaude Sonnet 5 8c2aadeda0 Trigger empty commit to test Gitea Actions/webhook pipeline
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 23:10:44 +02:00
maroandClaude Sonnet 5 56b2a6497b Overhaul deployment to Gitea Actions CI/CD, remove update.sh
Production no longer builds from source or self-updates via cron/git pull:
setup.sh now only provisions the server once (Docker, /opt/anouma, a
restricted `anouma-deploy` SSH user whose key can only ever run
deploy.sh, generated secrets). All future deployments run through
.gitea/workflows/ci.yml (lint/typecheck/test/build on every push) and
release.yml (on a vX.Y.Z tag: build the image, push it to the Gitea
registry, then SSH-trigger deploy.sh on the server), which pulls,
migrates, restarts, healthchecks, backs up the database first, and
automatically rolls back the code on a failed healthcheck.

docker-compose.yml's app service now runs a registry image
(${ANOUMA_IMAGE}) instead of building locally.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 22:58:09 +02:00
maroandClaude Sonnet 5 1cd15aff25 Add email verification, personal calendar feed, and full SEO implementation
- Customer accounts now require email verification (hashed, single-use,
  time-limited tokens) before they can request/confirm bookings, with
  resend flows on login/account/booking widget and rate limiting.
- Admins get a private, rotatable iCalendar (ICS) subscription feed of
  their confirmed bookings and public events, timezone-correct for
  Europe/Berlin including DST, never exposing meeting passwords.
- Adds a full SEO layer: per-page canonical/OG/Twitter metadata with
  CMS-editable overrides and content-derived fallbacks, a dynamic
  sitemap.xml and robots.txt driven by real published content, JSON-LD
  (Organization/LocalBusiness, WebSite, WebPage, BreadcrumbList, Service,
  Event, BlogPosting) that never fabricates data, and a CMS-managed
  redirect table for changed slugs.
- Global ANOUMA-naming audit: the brand name is never used to label
  personal account/calendar areas anywhere in the app, CMS, or emails.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 22:57:31 +02:00
maroandClaude Sonnet 5 50c39a70e0 Add full Docker deployment: setup.sh, update.sh, healthcheck, TURN support
- setup.sh: interactive/non-interactive one-shot installer (build, DB
  healthcheck, migrate, seed, start), idempotent secret generation, NPM
  reverse-proxy network auto-detection and optional join, optional
  AUTO_UPDATE cron install.
- update.sh: release-tag-gated updates only (never bare main), DB backup
  with retention before every update, lock file against concurrent runs,
  automatic code rollback on failed post-update healthcheck.
- Dockerfile: multi-stage build, non-root user, built-in HEALTHCHECK against
  the new /api/health route, wholesale COPY so new source dirs (e.g.
  scripts/) never silently go missing at runtime.
- docker-compose.yml: internal anouma-network (configurable), named volume
  for Postgres, app depends_on postgres healthy, no unnecessary published
  ports; docker-compose.override.yml.example documents joining an existing
  NPM network without ever touching NPM itself.
- Fix host-detection: isHost was Boolean(user), wrongly granting host
  privileges to logged-in customers; now checks user.collection === "users".
- Wire configurable STUN/TURN servers through to the WebRTC client
  (lib/meeting/iceServers.ts) so a TURN server can be added later via env
  vars only, no code changes.
- DEPLOYMENT.md, updated README.md and .env.example documenting the whole
  flow: NPM integration, env vars, WebRTC, updates, backups, rollback.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 21:50:28 +02:00
maro d3d53e68a9 Ignore stray installer files (.rpm/.deb/.AppImage) to avoid accidental commits 2026-08-25 21:13:35 +02:00
maro 5d83c0dc1e Add calendar-based booking system: accounts, availability, admin calendar
- Customer accounts (separate auth collection) with /konto area
- Availability + AvailabilityOverrides collections driving real slot calculation
- BookingRequests with race-safe confirmation (Postgres advisory lock + transaction)
- Booking emails (request received, admin notify, confirmed, rejected, alternative proposed/accepted, cancelled)
- Confirmed online bookings auto-create a private linked video-call Event
- Custom Payload admin calendar view (month grid + day schedule)
- Wired booking widget into offer pages and /termin-buchen
2026-08-25 16:52:34 +02:00
maro 45261a0461 Initial commit: ANOUMA website with Payload CMS, WebRTC meetings, and booking system
- Next.js 16 App Router site with the ANOUMA design system
- Payload CMS (PostgreSQL) for offers, events, posts and page content
- WebRTC video-call system with custom signaling server
- SMTP email reminders and booking-request notifications
- Customer accounts, calendar-based availability, and booking workflow
2026-08-25 16:40:51 +02:00