Commit Graph

119 Commits

Author SHA1 Message Date
7d07d47ec5 chore: convert to GitLab monorepo
- Merge backend, web, app, planning histories (118 commits preserved)
- Replace Woodpecker CI with .gitlab-ci.yml (path-based triggering)
- Switch mistral-go-sdk from somegit.dev to github.com/VikingOwl91/mistral-go-sdk v1.3.0
- Consolidate .pre-commit-config.yaml and .gitignore at repo root
- Remove per-service .woodpecker.yml files
2026-04-07 02:53:03 +02:00
d9e48ee007 merge: root history into monorepo 2026-04-07 02:45:51 +02:00
ca2e35113f merge: app history into monorepo 2026-04-07 02:45:51 +02:00
7b6bc90633 merge: web history into monorepo 2026-04-07 02:45:51 +02:00
01881e56bc fix(helm): update imagePullSecret to itsh-registry 2026-04-06 20:01:32 +02:00
a95d24876d fix(helm): update imagePullSecret to itsh-registry 2026-04-06 20:01:10 +02:00
e454e31472 fix(ci): switch container registry to registry.itsh.dev 2026-04-06 19:49:06 +02:00
cb996f46bb fix(ci): switch container registry to registry.itsh.dev 2026-04-06 19:48:56 +02:00
2455eda23b fix(ci): install pnpm directly, corepack removed in Node 25 2026-04-01 23:55:56 +02:00
ed98563739 refactor: switch package manager from bun to pnpm
- Replace bun with pnpm (v10.33.0) via corepack
- Upgrade all Docker images from node:22/bun to node:25-alpine
- Update CI pipeline, pre-commit hooks, and prettierignore
- Add packageManager field to package.json for version pinning
2026-04-01 23:52:30 +02:00
553ceb5d85 fix(helm): Helm 4 CI, startup probe, guaranteed QoS, config checksum
- Upgrade CI deploy to Helm 4.1 with --rollback-on-failure --wait=watcher
- Replace initialDelaySeconds with startup probe (15x2s=30s window)
- Set resources req=limit (100m/128Mi) for Guaranteed QoS class
- Add ConfigMap checksum annotation to trigger rollouts on config changes
2026-04-01 23:47:20 +02:00
53d7faae24 fix(helm): guaranteed QoS, config checksum, migration retry limit
- Set resources req=limit (100m/128Mi) for Guaranteed QoS class
- Add ConfigMap checksum annotation to trigger rollouts on config changes
- Add retry limit (60 attempts) to migration init container
- Use TARGETARCH in Dockerfile for multi-arch build support
2026-04-01 23:44:50 +02:00
482fcd180a feat(helm): add Go runtime tuning, startup probe, upgrade to Helm 4
- Set GOMAXPROCS and GOMEMLIMIT from cgroup limits to prevent
  thread oversubscription and unbounded GC memory growth
- Add startup probe (60s budget) to gate liveness/readiness during
  connection pool initialization
- Increase liveness failureThreshold to 5 to avoid restarts on
  transient issues
- Remove initialDelaySeconds (startup probe replaces this)
- Upgrade CI from alpine/helm:3.17 to alpine/helm:4.1
- Replace deprecated --atomic with --rollback-on-failure + --wait=watcher
2026-04-01 00:07:01 +02:00
74ee825039 fix(helm): switch migrate init container from busybox to alpine
busybox:1.37 nc -z is broken (outputs "punt!" and hangs).
Alpine 3.21 ships a working nc -z implementation.
2026-03-31 23:38:50 +02:00
08d83bc57e fix(helm): replace broken nc -z in migrate job init container
BusyBox 1.37 nc -z outputs "punt!" and hangs. Use nc -w 2 with
stdin redirect instead, which correctly tests TCP connectivity.
2026-03-31 23:06:51 +02:00
ab2484474e fix(helm): remove busybox init container blocking backend startup
BusyBox 1.37 nc -z is broken (outputs "punt!" and never exits),
causing the wait-for-cache init container to loop indefinitely.
The cache is healthy — the backend should handle reconnects itself.
2026-03-31 23:02:26 +02:00
99781b4cf3 fix(ci): update deploy namespace to tenant-2 2026-03-09 16:19:28 +01:00
1b329b8222 fix(ci): update deploy namespace to tenant-2 2026-03-09 16:19:27 +01:00
9c051df350 feat(helm): add wait-for-cache init container to backend deployment
Prevents the backend from starting before the DragonflyDB operator
has the cache pod ready and reachable. Mirrors the existing
wait-for-postgres pattern in the migration job.
2026-03-08 20:00:52 +01:00
3d17e25764 fix(helm): bump dragonfly memory limit to 512Mi
DragonflyDB requires 256MiB minimum per thread. With container
overhead the 256Mi limit is insufficient, causing immediate exit.
2026-03-08 19:43:05 +01:00
8f306059d8 fix(helm): lower resource limits to fit within tenant-quota (1 CPU)
Set web limits to 200m/256Mi to stay within the tenant-1
ResourceQuota of 1 CPU total.
2026-03-08 19:29:51 +01:00
b00e8df6db fix(helm): lower resource limits to fit within tenant-quota (1 CPU)
Set backend and cache limits to 200m/256Mi to stay within the
tenant-1 ResourceQuota of 1 CPU total.
2026-03-08 19:29:50 +01:00
62a9f682a0 feat(helm): add HTTPRoute sectionName and HTTP→HTTPS redirect, update resources
Add sectionName to HTTPRoute for HTTPS listener pinning and a separate
HTTP→HTTPS 301 redirect route. Update resources from req=limit to
request/limit separation for pay-as-you-go billing.
2026-03-08 19:04:30 +01:00
2e1eed543d feat(helm): use DragonflyDB operator CRD, add HTTPRoute sectionName and HTTP→HTTPS redirects
Replace manual Valkey Deployment+Service with DragonflyDB operator CRD.
Add sectionName to HTTPRoute for HTTPS listener pinning and a separate
HTTP→HTTPS 301 redirect route. Update resources from req=limit to
request/limit separation for pay-as-you-go billing. Fix NetworkPolicy
cache pod selector to match operator-managed labels.
2026-03-08 19:01:34 +01:00
41876cd698 fix: remove completion_args from agent conversation request
Mistral rejects completion_args when agent_id is set. The agent's
own configuration (set in Mistral UI) controls response format.
2026-03-05 21:37:37 +01:00
209efe5309 fix: override response format to text for agent conversations
Mistral rejects json response format when tools (web search) are
active. Override to text since the prompt already requests JSON
output in the instructions.
2026-03-05 21:32:03 +01:00
c7085e5337 chore: bump Go to 1.26 in CI and Dockerfile
Required by mistral-go-sdk which targets go 1.26.
2026-03-05 21:25:58 +01:00
340132626c refactor: replace hand-rolled Mistral HTTP client with mistral-go-sdk
Use the Conversations API (POST /v1/conversations) via the SDK for
Pass 1 agent calls instead of /agents/completions which doesn't
support built-in web search connectors. Pass 2 uses the SDK's
ChatComplete method.
2026-03-05 21:21:41 +01:00
02a03c3d41 feat: pass AI and Turnstile secrets via Helm deploy pipeline
Add Woodpecker secrets for AI_API_KEY, AI_AGENT_SIMPLE, and
TURNSTILE_SECRET_KEY. Create ci-secrets.yaml template and wire
them through the deploy step alongside existing SMTP secrets.
2026-03-05 18:41:42 +01:00
7937f43a06 fix: resolve golangci-lint dupl and goconst violations
Add nolint:dupl to Update handler (structurally similar to CreateEdition
by design). Extract "NULL" string literal to sqlNull constant.
2026-03-05 18:31:53 +01:00
612231d977 chore: normalize resources to 100m/100Mi and enable zero-downtime deploys
Set CPU and memory requests equal to limits (100m/100Mi). Switch rolling
update strategy to maxSurge=1, maxUnavailable=0 so new pods start
before old ones terminate.
2026-03-05 18:25:47 +01:00
bec253506e chore: normalize resources to 100m/100Mi and enable zero-downtime deploys
Set CPU and memory requests equal to limits (100m/100Mi) for backend,
cache, and web. Switch rolling update strategy to maxSurge=1,
maxUnavailable=0 so new pods start before old ones terminate.
Add readiness probe to cache deployment.
2026-03-05 18:24:58 +01:00
8db767bc84 Merge branch 'feat/admin-market-enhancements' 2026-03-05 18:18:20 +01:00
19a2c98a7c Merge branch 'feat/admin-panel-submissions' 2026-03-05 18:18:16 +01:00
5ea6afca3e feat: group market editions by series in search and admin list
Public search now deduplicates to one card per series with an edition
count badge. Admin list uses a grouped endpoint with expandable rows.
Market detail page shows an edition year switcher when multiple editions
exist. Admin detail page includes series edition management.
2026-03-05 18:14:47 +01:00
d6e6d35ae5 feat: series-grouped market display with edition switching
- Public search dedup: CTE with ROW_NUMBER picks best edition per series
  (nearest future, fallback most recent past), COUNT(*) OVER for edition_count
- Add EditionCount to Market model and MarketSummary DTO
- GetBySlug returns nearest-future edition by default, supports ?year= override
- GetBySlug returns sibling edition briefs for edition switcher UI
- New GET /admin/markets/grouped endpoint returns AdminSeriesGroup[] with
  series-level pagination and all editions per group
- Add AdminSearchGrouped to repository, service, handler, and routes
2026-03-05 18:11:27 +01:00
6f743210f5 feat: add edition creation for existing series, auto-match on submit
Admin endpoint POST /admin/series/:id/editions creates a new yearly
edition for an existing series, inheriting series-level defaults.

Public market submissions now auto-match against existing series using
trigram similarity (>0.6) on name + exact city match. Matched
submissions link to the existing series instead of creating duplicates.

Fix Gin route tree conflict by nesting markets and series groups under
a shared /admin parent group.
2026-03-05 17:08:13 +01:00
b5ac2620bf feat: market series/editions model, two-pass AI research, source-derived confidence
Split markets into market_series (persistent identity) + market_editions
(yearly instances). Migration preserves edition UUIDs from old market IDs
for URL backward compatibility. Edition statuses: rumored, confirmed,
active, completed, cancelled, archived.

AI research now uses two-pass pipeline: Pass 1 via pre-created Mistral
agent with web search for structured extraction, Pass 2 via
mistral-large-latest for description writing and field retry. Confidence
scoring is source-derived (source count + extraction type) instead of
LLM self-reported.
2026-03-05 16:38:43 +01:00
2d32a098cc feat: add search, sorting, and filtering to admin market list
- Search box for name/city filtering
- Clickable column headers for sorting (name, city, status, date, created)
- Sort direction toggle (asc/desc) with arrow indicators
- All filters preserved through pagination and sort changes
2026-03-05 15:22:13 +01:00
10da87735f feat: add sort and order params to admin market list
Supports sorting by name, city, date, created, status with asc/desc order.
2026-03-05 15:22:01 +01:00
aa7a982caf feat: add AI research, geocoding, duplicate detection, enriched market submit
- AI research via Mistral API for admin market editing
- Auto-geocoding via Nominatim OSM with rate limiting
- Public geocode endpoint (POST /api/v1/geocode)
- Duplicate detection using pg_trgm trigram similarity
- Extended SubmitMarketRequest with street, opening_hours, admission_info
- pg_trgm migration for fuzzy name matching
2026-03-05 15:18:44 +01:00
6f8df87f80 feat: add AI research, geocoding, enriched market forms and public submit upgrade
- AI research panel with structured display (opening hours, admission)
- Shared MarketForm component with admin/public mode
- Geocode button to derive coordinates from address
- Opening hours, admission info fields in all forms
- Currency-aware pricing, full European country list
- Public submit now includes all market fields
- Weekday normalization from date for AI research results
- Duplicate detection warning on admin detail view
2026-03-05 15:17:59 +01:00
0a59225e81 fix: match 2FA error code and escape TOTP pattern in login form
Backend returns code '2fa_required' but frontend checked for
'totp_required', so the TOTP input field never appeared. Also fix
the same Svelte pattern brace escaping issue as in TOTPSetup.
2026-02-27 14:55:50 +01:00
25c0a265a4 chore: remove OAuth buttons from login page 2026-02-27 14:54:58 +01:00
f839f32ddc chore: disable OAuth routes until provider apps are configured 2026-02-27 14:54:22 +01:00
18ac35c477 fix: escape regex braces in TOTP input pattern attribute
Svelte was interpreting {6} in pattern="[0-9]{6}" as an expression,
rendering the pattern as "[0-9]6" instead of the intended 6-digit regex.
2026-02-27 14:46:50 +01:00
dd4e6184ac feat: add user dropdown menu, password management, fix Turnstile keys
- Replace inline nav items with UserMenu dropdown (display name trigger,
  Profil/Sicherheit/Admin/Abmelden, click-outside/Escape to close)
- Add password set/change form to profile security section
- Fix Turnstile site key (extra A, swapped l/1)
2026-02-27 14:39:01 +01:00
841a69c59a feat: add password change endpoint, random medieval display names
- Add PUT /auth/password for setting/changing passwords (handles both
  first-time set for magic link/OAuth users and change for password users)
- Generate random medieval display names (e.g. Gaukler1025) for new
  magic link and OAuth users instead of leaving display_name empty
- Add has_password field to ProfileData response
2026-02-27 14:38:02 +01:00
bb6912d94d fix: add Turnstile site key to runtime ConfigMap
The page uses $env/dynamic/public which reads env vars at runtime,
not build time. The Docker build ARG/ENV only exists in the builder
stage and doesn't propagate to the Node.js runtime container.

Add PUBLIC_TURNSTILE_SITE_KEY to the Helm ConfigMap so it's
available as a process.env var when the SSR server runs.
2026-02-27 14:21:02 +01:00
fd879ba026 fix(deploy): use maxSurge=0 for rolling update to fit resource quota
maxSurge=1 requires a second pod during rollout, but the tenant
ResourceQuota (1 CPU limit) is already at 900m — the extra 250m
exceeds the cap and the pod can't schedule, causing a 5min timeout.

Switch to maxSurge=0/maxUnavailable=1 (kill-then-start) to stay
within quota. Matches the web deployment strategy.
2026-02-27 14:17:02 +01:00