- 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
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
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
Branch pushes now build and push only 'latest'; tag pushes add the
v*-tag and update the k8s manifest. Removes the daily nightly-* and
per-commit sha-* tags that accumulated registry storage.
pnpm 11 treats ignored build scripts as a hard error during fresh
installs (CI/Docker), while the old onlyBuiltDependencies list is
deprecated. The stray 'allowBuilds: esbuild: set this to true or false'
placeholder was invalid YAML semantics and blocked the esbuild
postinstall, failing 'pnpm install --frozen-lockfile' in the Docker
builder stage (ERR_PNPM_IGNORED_BUILDS).
- 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
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
Push builds now bake VERSION=dev-YYYYMMDD and additionally tag the
image nightly-YYYYMMDD, so a dated, identifiable artifact exists without
creating a git tag. Explicit v* tags keep tagging IMAGE:vX.Y.Z.
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.
- 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
- 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
- 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
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
- 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)