Commit Graph

60 Commits

Author SHA1 Message Date
opencode e164d51574 feat: compare limit 9, format-aware import placeholder, help links
- Raise compare limit from 8 to 9 (server + client, toast on overflow)
- Make import textarea placeholder match selected format (CSV/JSON/YAML/auto)
- Add GuideHelp links to admin create/edit user dialogs and tool import dialog
2026-08-05 07:40:47 +02:00
opencode 6eb3dfd8f9 docs: cut to v0.9.0 with unified .de/.en naming
- Remove all prior release notes and version snapshots (v0.6.0-v0.8.6)
- Rename handbook to *.de.md; keep *.en.md
- New release notes v0.9.0.de.md/.en.md with v0.9.0 snapshot
- generate-docs.mjs: .de/.en convention incl. search index and en-fallback
- docs.tsx: release fallback now uses version.de.md
- Wording: neutral tagline, anonymous user, no gender forms
- Add docs/examples/import-tools.yaml and link from administration docs
2026-08-05 00:13:41 +02:00
opencode 8f2fd89847 feat(import): bulk tool import (CSV/JSON/YAML) for admins; NetBox-style help button
Build & Push Docker Image / build (push) Successful in 2m49s
- Add POST /admin/tools/import with format auto-detect, CSV delimiters
  (comma/semicolon/tab), per-row validation via CreateToolBody, bulk insert,
  audit log entries per imported tool; gated by new 'tool-import' feature
  flag (premium/enterprise; admins always pass)
- Add tool-import-dialog UI (format tabs, delimiter select, textarea, file
  upload, result/error list) behind hasFeature('tool-import')
- Replace FieldHelp question marks and bare GuideHelp links with a NetBox-style
  'Hilfe/Help' outline button (HelpCircle + text) in form headers only
- Sync locales to 482 keys per language (de/en), update handbook docs
  (administration import section, index/plaene feature tables), regenerate
  API client + zod schemas, add yaml dependency
2026-08-04 23:09:11 +02:00
opencode 70e72dac71 fix(i18n): translate submit button, density/view toggles; rename watchlist guide to Merkliste; add guide help buttons
Build & Push Docker Image / build (push) Successful in 2m31s
2026-08-04 20:43:36 +02:00
opencode 3de59ccaaf feat(i18n): full app + docs localization (de/en)
Build & Push Docker Image / build (push) Successful in 2m33s
- translate remaining pages/components (admin, analytics, redundancy,
  trash, compare, browse, watchlist, admin tools tab, category combobox,
  theme toggle, tool preview card, tool-new/edit) to t() calls
- locales: 453 keys each, parity verified
- docs: bilingual handbook + release notes via *.en.md variants,
  language-aware docs.tsx (markdown paths, nav titles, search index),
  LanguageSwitcher in docs header
- generate-docs: emit per-locale handbook/release/search output,
  localized index.json fields (fileEn/titleEn), en-aware snapshots
2026-08-04 08:35:05 +02:00
opencode 3bb4598d04 feat(docs): version-based docs, correct Gitea tag links, form guide help
- each release now carries a full docs snapshot (reference + handbook)
  under docs/releases/<v>/; the docs frontend loads a version's snapshot
  for /docs/vX.Y.Z/* and shows the handbook/reference of that version
- version dropdown navigates to /docs/<version> (docs home) instead of
  the release notes page; old /docs/vX.Y.Z redirect removed
- generator: --snapshot writes handbook + reference; build copies
  versioned snapshots (last 7 versions) into /docs/versions/<v>/
- fix Gitea tag links: /admin/tool-evaluator/tags/<v> was 404, correct
  URL is /releases/tag/<v>
- add GuideHelp button to forms/pages linking to the matching handbook
  guide (rating, tool add/edit, costs, compare, watchlist, analytics)
2026-08-04 07:31:47 +02:00
opencode 33cf261777 fix(docs): mobile nav drawer and version dropdown state
Build & Push Docker Image / build (push) Successful in 2m30s
- sidebar was hidden below lg with no replacement; add a Sheet-based
  nav drawer opened from a menu button in the header
- version dropdown stayed on 'aktuell' for /docs/releases/* pages because
  only first-segment versions were parsed; derive header version from the
  releases route too
2026-08-04 06:58:07 +02:00
opencode fdf2d741a1 feat(docs): standalone docs page, Hilfe nav entry, rewritten user guide
- docs route renders without the app shell (own header, back-to-app link,
  theme toggle)
- nav entry renamed to Hilfe (de) / Help (en)
- reference links now case-insensitive (schema/tag slugs)
- handbook rewritten as 17-page user guide with links into the API reference
- release notes v0.8.1 added
2026-08-03 22:52:14 +02:00
opencode 6c92b6358d feat(docs): mkdocs-style documentation site served at /docs
Full documentation hub replacing the release-notes-only view:
- Handbook pages (docs/handbook) for all features and admin/betrieb
- API reference generated from lib/api-spec/openapi.yaml via
  scripts/src/generate-docs.mjs (replaces sync-release-docs.mjs):
  endpoints, schemas/fields, search index, per-release snapshots
- mkdocs layout: sidebar nav, right TOC with scrollspy, search overlay,
  version dropdown, repo link
- FieldHelp (?) buttons in forms linking to reference field docs
- v0.7.0 release notes backfilled, v0.8.0 release notes added
2026-08-03 22:15:54 +02:00
opencode 520f917723 feat(docs): version-bound release documentation served at /docs
Build & Push Docker Image / build (push) Successful in 2m35s
Adds a docs pipeline so each release has a version-bound Markdown
document (docs/releases/vX.Y.Z.md) rendered publicly in the app:

- sync-release-docs.mjs copies docs/releases/*.md into the toolrate
  public dir and generates index.json before every dev/build
- /docs lists all releases; /docs/:version renders the sanitized
  Markdown (marked + DOMPurify, typography styles)
- template + workflow documented in docs/README.md
- current release (v0.6.0) documented as the first entry
2026-08-03 16:41:08 +02:00
opencode 2f66fff993 chore(deps): upgrade all dependencies to latest and pin exact
Build & Push Docker Image / build (push) Failing after 1m18s
Policy: every direct dependency is now an exact pin; lockfile + --frozen-lockfile keep builds reproducible; save-exact=true enforced.

Toolchain:
- pnpm 10.26 -> 11.18 (lockfile migrated; supportedArchitectures moved to pnpm-workspace.yaml)
- typescript 5.9 -> 7.0, vite 7 -> 8, @vitejs/plugin-react 5 -> 6
- esbuild override 0.27.3 -> 0.28.1 (closes GHSA-g7r4-m6w7-qqqr); added @esbuild/darwin-arm64 for local dev
- orval 8.9 -> 8.23, regenerated clients

Backend (prod image):
- openid-client 5.7 -> 6.8 (rewritten OIDC flow in routes/auth.ts: discovery + functional API, PKCE/state, fetchUserInfo, buildEndSessionUrl)
- pino 9 -> 10, pino-http 10 -> 11, thread-stream 3 -> 4
- zod 3.25 -> 4.4 (catalog; supported by drizzle-zod 0.8.3)
- pg 8.20 -> 8.22; removed deprecated @types/bcryptjs

Frontend:
- react/react-dom 19.1.0 -> 19.2.8 (catalog pin lifted; expo note removed)
- react-day-picker 9 -> 10 (table classname -> month_grid)
- recharts 2 -> 3 (TooltipContentProps + DefaultLegendContentProps typing; safe keys)
- react-resizable-panels 2 -> 4 (Group/Separator rename)
- date-fns 3 -> 4, @hookform/resolvers 3 -> 5, lucide-react 0.545 -> 1.28
- all @radix-ui/*, tailwind, types, and remaining patch/minor deps bumped to latest

Security/process:
- overrides for body-parser >=2.3.0 (GHSA-v422-hmwv-36x6) + markdown-it/linkify-it/brace-expansion/fast-uri (dev tooling)
- pnpm audit now reports 0 vulnerabilities (prod and full)
- CI audit gate added to build.yaml; docs/dependency-policy.md; renovate.json
- Dockerfile pins node:24.18.1-alpine and pnpm@11.18.0
2026-08-03 12:56:00 +02:00
opencode bcae59626f feat(security): add CSRF protection for all state-changing API routes
Build & Push Docker Image / build (push) Successful in 2m16s
- Synchronizer token stored in session; GET /auth/csrf to obtain it
- csrfProtection middleware requires X-CSRF-Token on non-safe methods
- customFetch injects the header via setCsrfTokenGetter
- toolrate boot loads token; reload after local login (session regenerate)
- OpenAPI GET /auth/csrf + CsrfToken schema, orval regenerated
2026-08-03 10:30:13 +02:00
opencode f851305d78 fix(tools): OR'ed where clauses now AND'd so search excludes soft-deleted tools; localize delete confirm dialog
Build & Push Docker Image / build (push) Successful in 2m25s
2026-08-03 08:48:08 +02:00
opencode 743b177c89 fix(auth): password min length 6 + show/hide toggle on password inputs
Build & Push Docker Image / build (push) Successful in 2m21s
2026-08-03 08:01:52 +02:00
opencode 68a81ec775 feat(auth): password change (self + admin reset) with rate limiting; dedupe watchlist to user menu
Build & Push Docker Image / build (push) Successful in 2m19s
2026-08-03 07:43:24 +02:00
opencode 63f0bdbab6 fix(nav): trim sidebar items, fix collapsed sidebar overflow, add add-tool buttons on home/browse
Build & Push Docker Image / build (push) Successful in 2m18s
2026-08-03 06:12:01 +02:00
opencode 4648614556 docs: replace Replit config/docs with README; drop Replit files
Build & Push Docker Image / build (push) Successful in 2m29s
2026-08-03 05:43:13 +02:00
opencode ab24f99b90 fix(nav): restore sidebar collapse state from cookie; cmd+k search shows tools only while typing; mobile header search
Build & Push Docker Image / build (push) Successful in 3m22s
2026-08-02 15:08:37 +02:00
opencode c6755b586b feat(nav): collapsible sidebar + mobile drawer, user menu, breadcrumbs, polished cmd+k, header search
Build & Push Docker Image / build (push) Successful in 2m46s
2026-08-02 14:55:18 +02:00
opencode 2f38889726 fix: compact filter popover; feat: i18n (de/en)
Build & Push Docker Image / build (push) Successful in 2m31s
2026-08-02 13:42:53 +02:00
opencode 95bf49509c fix: white home page - coerce pg numeric strings for top-tools ratings
Build & Push Docker Image / build (push) Successful in 2m32s
2026-08-02 13:10:28 +02:00
opencode d033b20dfb feat: watchlist (premium), mobile bottom nav
Build & Push Docker Image / build (push) Successful in 2m35s
2026-08-02 13:00:10 +02:00
opencode c77610786b feat: compare (premium), rating-history trend, hover previews
Build & Push Docker Image / build (push) Successful in 2m47s
2026-08-02 12:48:02 +02:00
opencode 0c27982098 ci: dev version includes UTC time (dev-YYYYMMDD-HHmm)
Build & Push Docker Image / build (push) Successful in 2m36s
Phase 1: browse power-up
- faceted filters: tags + features (array containment) and min rating
  on listTools; new ?tags=?features=?minRating= URL params with chips
- global Cmd+K command palette (cmdk) with tool search + navigation
- mini usefulness/usability bars on grid cards, wide cards and table rows
2026-08-02 11:51:25 +02:00
opencode 620b12d4b6 fix: view toggle stuck after selecting table/rows
Build & Push Docker Image / build (push) Successful in 10m7s
URL param had precedence over the user's toggle choice, so once
?view=table|rows was in the URL the override could never win. User
selection now takes precedence; URL param only applies on first load.
2026-08-02 10:15:43 +02:00
opencode 78244c3197 feat: user-chosen browse views with grid/list toggle and profile sync
Build & Push Docker Image / build (push) Successful in 2m25s
- view modes grid | table | rows + density cozy/compact, persisted via
  localStorage and shareable ?view=?density= URL params (URL wins)
- table view: sortable columns (name, rating, reviews), new sort options
  name_asc/name_desc/recently_updated (backend enum + handler)
- live debounced search, removable filter chips, '/' focuses search
- virtualization via @tanstack/react-virtual for table and rows views
- profile sync: users.preferences jsonb + GET/PUT /api/auth/me/preferences;
  preference precedence URL > server profile > localStorage > default
- add local rollup/lightningcss/tailwindcss oxide native binaries for macos dev
2026-08-02 09:34:53 +02:00
opencode 803802a5b6 feat: show live build version in web UI
Build & Push Docker Image / build (push) Successful in 2m36s
- /api/version returns version, commitSha, buildDate, trashRetentionDays
- CI passes COMMIT_SHA (full), BUILD_DATE and VERSION (git tag) as
  docker build args; Dockerfile bakes them as env
- sidebar footer shows version/sha linked to the Gitea commit
- admin System tab shows version, commit link, build date, trash retention
2026-08-02 02:13:27 +02:00
opencode 2f20b1e5c2 feat: trash (soft delete) with admin tool management
Build & Push Docker Image / build (push) Successful in 2m15s
- tools: add deletedAt/deletedBy, soft delete via DELETE /tools/:id when
  actor has trash entitlement, else immediate hard delete
- trash endpoints: GET /tools/trash, POST /tools/trash (admin bulk),
  POST /tools/trash/restore, DELETE /tools/trash, POST /tools/trash/empty
- trash feature for premium/enterprise; exclude trashed from all public
  surfaces (browse, categories, features, tags, similar, ratings, costs,
  analytics, redundancy)
- TRASH_RETENTION_DAYS env (0 = keep forever) with hourly purge job
- frontend: /trash page (premium+, restore for all, permanent delete +
  empty for admin), admin Tools tab with multi-select bulk trash,
  sidebar Trash link, tool-detail delete hint
2026-08-02 02:02:16 +02:00
opencode 32df998399 fix: return existing cost on empty PATCH body instead of 500
Build & Push Docker Image / build (push) Successful in 2m14s
2026-08-02 01:31:55 +02:00
opencode 6b8ca92c37 feat: allow premium+ users to manage costs
Build & Push Docker Image / build (push) Successful in 2m19s
- costs routes drop requireAdmin, keep auth + costs feature check
- useAuth exposes hasFeature(feature) based on entitlements
- tool-detail costs section gated by hasFeature('costs') instead of isAdmin
2026-08-02 01:27:28 +02:00
opencode 01c70085db feat: tiered costs feature + admin tier management + tag selection
Build & Push Docker Image / build (push) Successful in 6m52s
- costs: nullable notes (fix create without notes), drop renewalDate
  (schema + API + UI), gate POST/PATCH/DELETE to admin + costs feature
- feature middleware: admin-aware hasFeature + getEntitlements union;
  /auth/me and login return resolved entitlements
- users: tier enum (free/premium/enterprise) in create/update/list,
  admin UI tier select + tier badge
- tags: GET /tags/all, TagInput autocomplete in new/edit tool forms,
  feature suggestions on focus, query invalidation on create/update
- openapi: nullable ToolUpdate urls, ToolUpdate tier fields, listAllTags
- Dockerfile: push-force to drop renewal_date column
2026-08-02 01:10:47 +02:00
opencode cd4efd16f6 feat(toolrate): rebrand to toolr + logo links home
Build & Push Docker Image / build (push) Successful in 2m33s
- visible brand text changed to toolr (sidebar, mobile header, topbar
  fallback, login, 404, home heading, index.html title/og/twitter meta)
- brand logo now links to / in sidebar, mobile header, login, 404
- internal identifiers unchanged: package name, localStorage key
2026-08-01 20:20:01 +02:00
opencode ccc295f92f feat(toolrate): desktop topbar theme toggle + dark-mode amber/gold
Build & Push Docker Image / build (push) Successful in 9m55s
- ThemeToggle moved from sidebar footer to new desktop topbar (top-right),
  page title shown left; mobile header + login unchanged
- dark theme primary switched from neon orange to amber/gold (38 92% 50%),
  primary-foreground to dark navy for contrast; ring + chart-1 harmonized
- light theme stays orange
2026-08-01 20:00:03 +02:00
opencode d244a537ea feat(toolrate): light/dark/system theme toggle with FOUC guard
Build & Push Docker Image / build (push) Successful in 2m30s
- use-theme hook: localStorage (toolrate-theme, default system), matchMedia
  change listener, shared singleton listener, sets .dark + color-scheme
- ThemeToggle: lightbulb quick toggle (light/dark) + dropdown (light/dark/system)
- Sidebar footer + mobile header + standalone login page
- inline script in index.html to apply theme pre-render (no FOUC)
- recharts axis ticks use hsl(var(--foreground)) for dark-mode readability
2026-08-01 19:47:39 +02:00
opencode db397a14bc fix: security hardening, validation, cache and analytics fixes
Build & Push Docker Image / build (push) Successful in 4m32s
Backend security:
- Admin-gate /admin/redundancy (GET+POST) with zod validation and tool existence checks
- Restrict CORS to same-origin (plus CORS_ORIGIN allowlist) and SameSite=Lax cookie
- Validate returnTo to prevent open redirect in the OIDC flow
- Validate/coerce relations body, reject self-relations and non-admin 'recommended'
- Add central JSON error middleware (no more Express HTML 500s)
- Fail fast at startup when SESSION_SECRET/VOTER_SECRET missing in production

Backend correctness:
- Stop leaking voterToken in the create-rating response
- Allow clearing websiteUrl/iconUrl (nullable in UpdateToolBody, frontend sends null)
- Regenerate session after login/callback (session fixation) and add OIDC state check
- Block self-demotion and last-admin demotion in user PATCH
- Set created_by to NULL on user delete (FK-safe)
- Validate cost create/update bodies with zod
- Unique index (tool_id, voter_token) + 409 on race duplicate ratings
- Clamp audit limit, escape ilike wildcards in search, O(N) analytics queries

Frontend:
- tools-browse reads and syncs URL query params (fixes home 'View all' links)
- Invalidate analytics/top-tools/categories/features caches after mutations
- Sync category combobox input when the value changes externally
- Hide Write a Review for anonymous users, drop unreachable rating guard
2026-08-01 19:11:00 +02:00
opencode 0c6a35e841 fix: category cache refresh, API 404, redundancy mapping, cost/relation authz, voterToken exposure
Build & Push Docker Image / build (push) Successful in 8m33s
- Invalidate categories/features queries after creating/editing tools so new
  categories appear immediately in search, browse dropdown and tool form
- Always refetch categories/features when the combobox/suggestion inputs mount
- Return JSON 404 for unmatched /api routes instead of the SPA index.html
- Read the manually confirmed 'better tool' from the recommendation notes
  instead of using the min tool id in the redundancy dashboard
- Require admin for cost/relation update+delete endpoints
- Stop exposing the voter token in the ratings list response
- Fix parseInt type error on user id params (Express 5 params typing)
2026-08-01 15:25:06 +02:00
henry fd51146049 Update artifacts/api-server/src/app.ts
Build & Push Docker Image / build (push) Successful in 1m48s
2026-07-31 17:32:00 +00:00
root 5d71e60e7d feat: Docker Compose support 2026-07-30 00:19:31 +02:00
root 857d2e11a8 feat: automatic recommendations + manual evaluation in redundancy analysis 2026-07-29 23:51:28 +02:00
root 44cc29b8fe feat: billing period for subscriptions, costs in redundancy analysis 2026-07-29 23:46:58 +02:00
root deabe36727 fix: customFetch returns parsed body, not Response object 2026-07-29 23:38:39 +02:00
root 331bdd0957 fix: clean login page, avoid esbuild regex parse error 2026-07-29 23:33:19 +02:00
root 5115d13616 fix: use ArrowLeft icon instead of HTML entity in login page 2026-07-29 23:28:04 +02:00
root 7bda8f95f3 feat: back-to-home links on login and 404 pages 2026-07-29 23:19:27 +02:00
root 45f0b80055 feat: costs UI on tool detail + tier badge in sidebar 2026-07-29 23:18:19 +02:00
root ba413f5ee9 fix: use static SQL for user column migration 2026-07-29 23:08:22 +02:00
root 7bfdac6104 fix: add migration for new user columns (tier, auth_provider, etc.) 2026-07-29 22:50:15 +02:00
root 59badeaa48 feat: auth foundation, similar tools, costs, redundancy, anonymous voting 2026-07-29 21:59:29 +02:00
root 8b3b7c9955 remove Replit branding (meta description, dev banner) 2026-07-29 20:18:10 +02:00
root 612ada8849 fix: tool card category badge overflow on narrow viewports 2026-07-29 20:17:39 +02:00