Commit Graph

31 Commits

Author SHA1 Message Date
af7703b644 fix: replace ASCII-encoded umlauts with proper German characters in user-facing strings
Notification email and submission response used ae/oe instead of ä/ö.
2026-02-27 11:12:39 +01:00
580b9d5e3c feat: add admin panel, market submissions, and email notifications
- Admin CRUD endpoints for markets with role-based middleware
- Anonymous market submission with Cloudflare Turnstile verification
- SMTP email notifications on new submissions (LogSender fallback)
- Market status workflow (pending/approved/rejected) with admin notes
- Nullable location column for submissions without coordinates
- CLI tool for promoting users to admin role
- Slug generation package extracted from seed
- Rate limiting on submission endpoint (3/hour per IP)
- Mailpit added to docker-compose for local email testing
2026-02-27 11:03:44 +01:00
cd92e84696 chore: add pre-commit hook configuration
Local hooks for hygiene (whitespace, YAML, merge conflicts, large files),
Go toolchain (fmt, vet, mod tidy, build), and golangci-lint matching CI.
2026-02-23 05:22:30 +01:00
d23ddba1ca fix: skip logging for health and readiness probe endpoints
Suppress log output for /healthz and /readyz to reduce noise from
Kubernetes liveness/readiness probes hitting every 10 seconds.
2026-02-22 20:26:58 +01:00
cb2e8c4cde fix(seed): gofmt struct field alignment 2026-02-22 19:13:53 +01:00
78046848f2 feat(seed): enrich markets data with real web-researched info
- Reduced from 312 to 272 markets (removed 39 unverified/unconfirmed entries)
- All 272 markets now have real descriptions sourced from official websites
- Added admission prices (adult/child cents + notes) where available
- Added street addresses and corrected venue names
- Added opening hours for markets where published
- Updated websites to full https:// URLs
- Updated seedMarket struct with new fields: Street, Description,
  AdmissionAdultCents, AdmissionChildCents, AdmissionNotes
- Seed INSERT now uses description/admission from JSON instead of
  generating template descriptions; falls back to generated desc if empty
- Added jsonString() helper for SQL-safe JSON encoding
2026-02-22 19:09:21 +01:00
8b478a11b8 fix(deploy): use Recreate strategy to fit tenant CPU quota
Single-replica deployment with tight CPU quota (1 core) cannot run two
pods simultaneously during a rolling update. Recreate kills the old pod
before starting the new one.
2026-02-22 12:01:50 +01:00
3236318e72 fix(deploy): add resource limits to migrate job to fit tenant quota 2026-02-22 11:55:42 +01:00
9e6608384c fix(deploy): increase migrate job deadline to 300s 2026-02-22 11:47:06 +01:00
549df60f09 fix(seed): resolve lint issues (noctx, goconst) 2026-02-22 11:41:33 +01:00
993bab1218 fix(seed): skip seeding if database already contains markets 2026-02-22 11:39:26 +01:00
ffaee89243 feat(seed): add 311 real medieval markets for 2026
Scrape marktkalendarium.de for 2026 market data and replace the
placeholder seed with real events across DE/AT/CH.

- Embed 311 markets as JSON with name, dates, city, zip, venue,
  organizer and website
- Geocode coordinates via Nominatim with caching and rate limiting
- Auto-derive Bundesland from postal code prefix
- Generate descriptions based on event type keywords
- Support DATABASE_URL env var for direct production seeding
2026-02-22 11:38:14 +01:00
e092a8d054 fix(deploy): replace Dragonfly CRD with plain Valkey deployment
Tenant SA lacks dragonflydb.io CRD permissions. Use a standard
Valkey Deployment+Service instead. Also re-enable CNPG (created
via kubectl), migrate job, and add seccompProfile to migrate pod.
2026-02-22 10:53:33 +01:00
f48a29c433 fix(deploy): disable CNPG and migrate job (tenant SA lacks CRD permissions)
Postgres, Dragonfly, and NetworkPolicy must be provisioned by the
platform admin or via itsh.dev dashboard, not by the tenant SA.
2026-02-22 10:32:10 +01:00
7c2e2cebff fix(deploy): disable Dragonfly CRD (tenant SA lacks dragonflydb.io permission) 2026-02-22 10:25:50 +01:00
e99ab896d3 fix(deploy): disable NetworkPolicy (tenant SA lacks networkpolicies permission) 2026-02-22 10:22:18 +01:00
ae54910f51 fix(docker): use existing nobody user instead of creating UID 65534 2026-02-22 10:19:19 +01:00
f07eac1811 fix(ci): add gcc/musl-dev for race detector in test step 2026-02-22 10:15:17 +01:00
a796443b1c fix(lint): remove revive linter (only producing doc-comment noise) 2026-02-22 10:13:42 +01:00
3e42f59f96 fix(lint): exclude revive exported/package-comments via issues filter 2026-02-22 10:11:42 +01:00
3145dba255 fix(lint): resolve all golangci-lint v2 issues
- Disable revive exported/package-comments rules (style, not correctness)
- Use errors.Is instead of == for pgx.ErrNoRows comparisons
- Use errors.As instead of type assertion on validator errors
- Use http.NewRequestWithContext instead of client.Get (noctx)
- Check resp.Body.Close error return (errcheck)
- Run gofmt on files with formatting drift
2026-02-22 10:09:46 +01:00
dd5366f931 fix(lint): remove gosimple (merged into staticcheck in golangci-lint v2) 2026-02-22 10:05:37 +01:00
4b871c67cc fix(lint): remove goimports from linters (formatter in golangci-lint v2) 2026-02-22 10:04:09 +01:00
f6f07b2139 fix(deploy): add seccompProfile RuntimeDefault to satisfy PodSecurity restricted policy 2026-02-22 10:03:41 +01:00
a58368e9d0 fix(lint): move gofmt to formatters section for golangci-lint v2 2026-02-22 10:02:25 +01:00
015189e648 fix(ci): force GOTOOLCHAIN=local to compile golangci-lint with go1.25 2026-02-22 09:57:06 +01:00
a12c1b48f1 fix(ci): correct registry to somegit.dev, add golangci-lint v2 version field 2026-02-22 09:50:46 +01:00
10e1d15462 chore(deploy): remove superseded raw k8s manifests 2026-02-22 09:33:41 +01:00
7780c3378b feat(deploy): add Helm chart and update CI for k8s deployment
- Replace raw k8s manifests with a full Helm chart (deploy/helm/)
- Add CloudNativePG cluster with PostGIS extensions and hcloud-volumes storage
- Add DragonflyDB (Redis-compatible) cache via operator CRD
- Add migration Job as Helm pre-install/pre-upgrade hook
- Add NetworkPolicy restricting ingress to nginx-gateway, egress to DB/cache/DNS/HTTPS
- Add ServiceAccount with automountServiceAccountToken disabled
- Use HTTPRoute (Gateway API) instead of Ingress to match cluster setup
- Fix Dockerfile: explicit UID 65534, add golang-migrate CLI for migration Job
- Update CI: push immutable SHA tags, deploy via helm upgrade --install --atomic
2026-02-22 09:32:01 +01:00
a1d93f7a8e feat: implement MVP backend API
Go backend with Gin, pgx, Valkey (go-valkey), and PostGIS.

Domains:
- Market search with PostGIS geo-queries (ST_DWithin, ST_Distance),
  German full-text search (tsvector + ILIKE fallback for compound words),
  date range filtering, pagination, and slug-based detail endpoint
- Auth with email+password (bcrypt), JWT access tokens (15min),
  session tokens (30d, dual Valkey+Postgres storage), OAuth
  (Google/GitHub/Facebook), magic links, and TOTP 2FA
- User profile with CRUD, soft-delete (30d grace), and restore

Infrastructure:
- 6 database migrations (users, sessions, oauth_accounts, magic_links,
  markets with PostGIS+FTS, totp_secrets)
- Middleware: recovery, request ID, structured logging (slog), CORS,
  per-IP rate limiting, JWT auth
- Seed data: 10 medieval markets across DACH region
- Docker Compose (PostGIS 17 + Valkey 8), multi-stage Dockerfile,
  Woodpecker CI pipeline, Kubernetes manifests
- Justfile, golangci-lint config, env example
2026-02-18 05:52:20 +01:00
9784d93a4a initial commit 2026-02-18 04:49:23 +01:00