diff --git a/artifacts/toolrate/src/i18n/locales/de.json b/artifacts/toolrate/src/i18n/locales/de.json index 43e1d99..3601692 100644 --- a/artifacts/toolrate/src/i18n/locales/de.json +++ b/artifacts/toolrate/src/i18n/locales/de.json @@ -69,7 +69,7 @@ }, "home": { "welcome": "Willkommen bei toolr", - "tagline": "Die Community-Plattform, auf der Ingenieure die Tools, die sie täglich nutzen, ehrlich bewerten.", + "tagline": "Bewerte dein Tool.", "totalTools": "Tools gesamt", "totalRatings": "Bewertungen gesamt", "avgRating": "Ø Bewertung", @@ -189,7 +189,7 @@ "nameOptional": "Name (optional)", "nameLabel": "Name", "anonymousPlaceholder": "Anonym", - "anonymousEngineer": "Anonymer Ingenieur", + "anonymousEngineer": "Anonymer Benutzer", "beFirstToReview": "Sei der Erste, der seine Gedanken zu diesem Tool teilt.", "shareExperience": "Teile deine Erfahrung mit {{name}}", "score": "Punktestand", diff --git a/artifacts/toolrate/src/i18n/locales/en.json b/artifacts/toolrate/src/i18n/locales/en.json index 7e3ad1f..c67dfd4 100644 --- a/artifacts/toolrate/src/i18n/locales/en.json +++ b/artifacts/toolrate/src/i18n/locales/en.json @@ -69,7 +69,7 @@ }, "home": { "welcome": "Welcome to toolr", - "tagline": "The community hub where engineers honestly rate the tools they use daily.", + "tagline": "Rate your Tool.", "totalTools": "Total Tools", "totalRatings": "Total Ratings", "avgRating": "Avg Rating", @@ -189,7 +189,7 @@ "nameOptional": "Name (Optional)", "nameLabel": "Name", "anonymousPlaceholder": "Anonymous", - "anonymousEngineer": "Anonymous Engineer", + "anonymousEngineer": "Anonymous User", "beFirstToReview": "Be the first to share your thoughts on this tool.", "shareExperience": "Share your experience with {{name}}", "score": "Score", diff --git a/artifacts/toolrate/src/pages/docs.tsx b/artifacts/toolrate/src/pages/docs.tsx index e5cca3a..1786d29 100644 --- a/artifacts/toolrate/src/pages/docs.tsx +++ b/artifacts/toolrate/src/pages/docs.tsx @@ -740,7 +740,7 @@ function ReleasesView({ versions }: { versions: ReleaseDoc[] }) { function ReleaseNoteView({ version, doc }: { version: string; doc: ReleaseDoc | null }) { const locale = useDocsLocale(); - const file = doc ? `releases/${localizedFile(doc.file, doc.fileEn, locale)}` : `releases/${version}.md`; + const file = doc ? `releases/${localizedFile(doc.file, doc.fileEn, locale)}` : `releases/${version}.de.md`; return (
diff --git a/docs/examples/import-tools.yaml b/docs/examples/import-tools.yaml new file mode 100644 index 0000000..8a5fe9e --- /dev/null +++ b/docs/examples/import-tools.yaml @@ -0,0 +1,295 @@ +# Beispiel-YAML zum Import in den Admin-Bereich (Tab „Tools" -> Importieren). +# Erwartetes Format pro Eintrag: +# name (Pflicht) +# description, category, websiteUrl, iconUrl (optional) +# features, tags (Listen oder | -getrennte Strings) +# Das Format wird automatisch erkannt; bei CSV den Trenner wählen. +# Fehlerhafte Zeilen werden übersprungen und mit Zeilennummer aufgelistet. + +- name: Slack + description: Team-Kommunikation mit Channels, Direktnachrichten und App-Integrationen + category: Kommunikation + websiteUrl: https://slack.com + features: + - Channels + - Videoanrufe + - App-Integrationen + tags: + - communication + - teamwork + +- name: Microsoft Teams + description: Chat, Besprechungen, Dateien und Zusammenarbeit in einer Plattform + category: Kommunikation + websiteUrl: https://www.microsoft.com/de-de/microsoft-365/microsoft-teams + features: + - Videokonferenzen + - Teamkanäle + - Office-Integration + tags: + - communication + - meetings + +- name: Zoom + description: Videokonferenzen und Webinare für Teams und externe Partner + category: Kommunikation + websiteUrl: https://zoom.us + features: + - Videokonferenzen + - Webinare + - Bildschirmfreigabe + tags: + - video + - meetings + +- name: Jira + description: Agile Projekt- und Issue-Verfolgung für Entwicklung und Betrieb + category: Projektmanagement + websiteUrl: https://www.atlassian.com/software/jira + features: + - Backlog + - Sprints + - Kanban-Boards + tags: + - agile + - project-management + +- name: Confluence + description: Kollaborative Wissensdatenbank und Dokumentation für Teams + category: Projektmanagement + websiteUrl: https://www.atlassian.com/software/confluence + features: + - Wikis + - Seitenbausteine + - Berechtigungen + tags: + - documentation + - knowledge-base + +- name: GitLab + description: DevOps-Plattform mit Git-Repositorys, CI/CD und Code-Review + category: Entwicklung + websiteUrl: https://about.gitlab.com + features: + - Git-Repositorys + - CI/CD + - Merge Requests + tags: + - devops + - git + +- name: GitHub + description: Versionsverwaltung, Code-Review und Collaboration auf Git-Basis + category: Entwicklung + websiteUrl: https://github.com + features: + - Repositories + - Pull Requests + - Actions + tags: + - git + - collaboration + +- name: Jenkins + description: Automatisierte Build- und Deploy-Pipelines für Softwareprojekte + category: CI/CD + websiteUrl: https://www.jenkins.io + features: + - Pipelines + - Plugins + - Job-Automatisierung + tags: + - ci + - cd + +- name: Docker + description: Container-Plattform zum Paketieren und Ausführen von Anwendungen + category: Entwicklung + websiteUrl: https://www.docker.com + features: + - Container + - Images + - Compose + tags: + - containers + - virtualization + +- name: Grafana + description: Observability- und Dashboard-Plattform für Metriken, Logs und Alerts + category: Monitoring + websiteUrl: https://grafana.com + features: + - Dashboards + - Alerts + - Datenquellen + tags: + - observability + - monitoring + +- name: Prometheus + description: Open-Source-Systeme zur Zeitreihen-Metrikerfassung und -Auswertung + category: Monitoring + websiteUrl: https://prometheus.io + features: + - Metriken + - Alerting + - Time-Series-Datenbank + tags: + - monitoring + - metrics + +- name: Datadog + description: Cloud-basierte Observability für Infrastruktur, APM und Logs + category: Monitoring + websiteUrl: https://www.datadoghq.com + features: + - Infrastruktur-Monitoring + - APM + - Log-Management + tags: + - observability + - saas + +- name: PagerDuty + description: Incident-Management und On-Call-Benachrichtigungen für Teams + category: Betrieb + websiteUrl: https://www.pagerduty.com + features: + - Alerting + - On-Call-Pläne + - Incident-Response + tags: + - incident-management + - on-call + +- name: Sentry + description: Fehlerüberwachung und Performance-Monitoring für Anwendungen + category: Monitoring + websiteUrl: https://sentry.io + features: + - Error-Tracking + - Releases + - Performance + tags: + - error-monitoring + - debugging + +- name: Terraform + description: Infrastructure-as-Code zur deklarativen Bereitstellung von Ressourcen + category: Infrastruktur + websiteUrl: https://www.terraform.io + features: + - Modules + - State-Management + - Provider + tags: + - iac + - infrastructure + +- name: Ansible + description: Agentenlose Automatisierung für Konfiguration, Deploy und Orchestrierung + category: Infrastruktur + websiteUrl: https://www.ansible.com + features: + - Playbooks + - Inventories + - Modules + tags: + - automation + - configuration + +- name: Elasticsearch + description: Verteilter Such- und Analytics-Server für Logs, Metriken und Daten + category: Datenbank + websiteUrl: https://www.elastic.co + features: + - Volltextsuche + - Aggregationen + - Skalierung + tags: + - search + - analytics + +- name: Kubernetes + description: Container-Orchestrierung für Deployment, Skalierung und Betrieb + category: Infrastruktur + websiteUrl: https://kubernetes.io + features: + - Pods + - Services + - Autoskalierung + tags: + - containers + - orchestration + +- name: Sonarqube + description: Statische Code-Analyse und Qualitätsmessung für Softwareprojekte + category: Entwicklung + websiteUrl: https://www.sonarsource.com/products/sonarqube + features: + - Code-Qualität + - Security-Scans + - Quality Gates + tags: + - code-quality + - static-analysis + +- name: Power BI + description: Business-Intelligence-Tool für Dashboards, Berichte und Datenanalyse + category: Analytics + websiteUrl: https://powerbi.microsoft.com + features: + - Dashboards + - Berichte + - Datenmodelle + tags: + - bi + - analytics + +- name: Google Workspace + description: Produktivitäts-Suite mit E-Mail, Docs, Drive und Meet + category: Produktivität + websiteUrl: https://workspace.google.com + features: + - Gmail + - Google Docs + - Google Drive + tags: + - suite + - productivity + +- name: Microsoft 365 + description: Office-Anwendungen, E-Mail und Cloud-Dienste für Unternehmen + category: Produktivität + websiteUrl: https://www.microsoft.com/microsoft-365 + features: + - Word + - Excel + - Outlook + tags: + - suite + - productivity + +- name: Slack Enterprise Grid + description: Slack-Verwaltung für große Organisationen mit erweiterten Sicherheitsfunktionen + category: Kommunikation + websiteUrl: https://slack.com + features: + - Enterprise-Admin + - Compliance + - Multi-Workspace + tags: + - communication + - enterprise + +- name: Atlassian Rovo + description: KI-Assistent für Suche und Zusammenarbeit über Atlassian-Produkte + category: Projektmanagement + websiteUrl: https://www.atlassian.com/software/rovo + features: + - KI-Suche + - Agenten + - Integrationen + tags: + - ai + - search \ No newline at end of file diff --git a/docs/handbook/administration.md b/docs/handbook/administration.de.md similarity index 96% rename from docs/handbook/administration.md rename to docs/handbook/administration.de.md index 6dffd85..dd4e3ad 100644 --- a/docs/handbook/administration.md +++ b/docs/handbook/administration.de.md @@ -73,6 +73,9 @@ Zentraler Zugriff auf den Tool-Katalog. category: Monitoring ``` + Eine umfangreichere, fertig importierbare Beispieldatei liegt unter + `docs/examples/import-tools.yaml` (24 gängige Enterprise-Tools). + Beim Import werden einzelne fehlerhafte Zeilen übersprungen und mit Zeilennummer aufgelistet; korrekte Zeilen werden trotzdem angelegt. Jeder Import erzeugt Audit-Log-Einträge. diff --git a/docs/handbook/administration.en.md b/docs/handbook/administration.en.md index 1e87800..7d49841 100644 --- a/docs/handbook/administration.en.md +++ b/docs/handbook/administration.en.md @@ -73,6 +73,9 @@ Central access to the tool catalog. category: Monitoring ``` + A larger, ready-to-import example file is located at + `docs/examples/import-tools.yaml` (24 common enterprise tools). + During import, individual faulty rows are skipped and listed with their row number; correct rows are still created. Every import produces audit-log entries. diff --git a/docs/handbook/analytics.md b/docs/handbook/analytics.de.md similarity index 100% rename from docs/handbook/analytics.md rename to docs/handbook/analytics.de.md diff --git a/docs/handbook/bewerten.md b/docs/handbook/bewerten.de.md similarity index 100% rename from docs/handbook/bewerten.md rename to docs/handbook/bewerten.de.md diff --git a/docs/handbook/datenmodell.md b/docs/handbook/datenmodell.de.md similarity index 100% rename from docs/handbook/datenmodell.md rename to docs/handbook/datenmodell.de.md diff --git a/docs/handbook/getting-started.md b/docs/handbook/getting-started.de.md similarity index 100% rename from docs/handbook/getting-started.md rename to docs/handbook/getting-started.de.md diff --git a/docs/handbook/index.md b/docs/handbook/index.de.md similarity index 95% rename from docs/handbook/index.md rename to docs/handbook/index.de.md index 66a8a7d..5988ccf 100644 --- a/docs/handbook/index.md +++ b/docs/handbook/index.de.md @@ -6,7 +6,7 @@ order: 1 # Willkommen bei toolr toolr ist eine Plattform zum **Entdecken, Bewerten und Vergleichen von -Entwicklungstools**. Nutzer:innen pflegen einen gemeinsamen Katalog von Tools, +Entwicklungstools**. Nutzer pflegen einen gemeinsamen Katalog von Tools, vergeben Bewertungen (Nützlichkeit & Bedienbarkeit) und nutzen Statistiken, um die richtige Wahl zu treffen. @@ -16,7 +16,7 @@ die richtige Wahl zu treffen. | --- | --- | --- | | **Tools durchsuchen** | Katalog filtern, sortieren und durchsuchen | Alle | | **Tool anlegen** | Neues Tool mit Beschreibung, Kategorie, Features & Tags eintragen | Angemeldet | -| **Tool bearbeiten/löschen** | Eigene Tools pflegen (Ersteller:in oder Admin) | Angemeldet | +| **Tool bearbeiten/löschen** | Eigene Tools pflegen (Ersteller oder Admin) | Angemeldet | | **Bewerten** | Nützlichkeit & Bedienbarkeit (1–5) plus Kommentar vergeben | Angemeldet | | **Merkliste** | Tools als Favoriten speichern | Premium | | **Vergleichen** | Tools nebeneinander gegenüberstellen | Premium | diff --git a/docs/handbook/konto.md b/docs/handbook/konto.de.md similarity index 100% rename from docs/handbook/konto.md rename to docs/handbook/konto.de.md diff --git a/docs/handbook/kosten.md b/docs/handbook/kosten.de.md similarity index 100% rename from docs/handbook/kosten.md rename to docs/handbook/kosten.de.md diff --git a/docs/handbook/papierkorb.md b/docs/handbook/papierkorb.de.md similarity index 100% rename from docs/handbook/papierkorb.md rename to docs/handbook/papierkorb.de.md diff --git a/docs/handbook/plaene.md b/docs/handbook/plaene.de.md similarity index 100% rename from docs/handbook/plaene.md rename to docs/handbook/plaene.de.md diff --git a/docs/handbook/redundanz.md b/docs/handbook/redundanz.de.md similarity index 100% rename from docs/handbook/redundanz.md rename to docs/handbook/redundanz.de.md diff --git a/docs/handbook/tastatur.md b/docs/handbook/tastatur.de.md similarity index 100% rename from docs/handbook/tastatur.md rename to docs/handbook/tastatur.de.md diff --git a/docs/handbook/tool-anlegen.md b/docs/handbook/tool-anlegen.de.md similarity index 100% rename from docs/handbook/tool-anlegen.md rename to docs/handbook/tool-anlegen.de.md diff --git a/docs/handbook/tool-bearbeiten.md b/docs/handbook/tool-bearbeiten.de.md similarity index 100% rename from docs/handbook/tool-bearbeiten.md rename to docs/handbook/tool-bearbeiten.de.md diff --git a/docs/handbook/tools-finden.md b/docs/handbook/tools-finden.de.md similarity index 99% rename from docs/handbook/tools-finden.md rename to docs/handbook/tools-finden.de.md index 4f1e984..214228b 100644 --- a/docs/handbook/tools-finden.md +++ b/docs/handbook/tools-finden.de.md @@ -47,7 +47,7 @@ Mit **Filter zurücksetzen** bzw. **Alle entfernen** räumst du sie wieder auf. - **Ansicht wechseln:** Raster / Tabelle / Zeilen. - **Dichte:** gemütlich / kompakt (Schieberegler). -Deine Auswahl wird gespeichert — lokal im Browser und für angemeldete Nutzer:innen +Deine Auswahl wird gespeichert — lokal im Browser und für angemeldete Nutzer zusätzlich serverseitig in den Präferenzen. Ansicht, Dichte, Suche, Filter und Sortierung werden dabei in die URL übernommen, sodass du Ergebnisse teilen kannst. diff --git a/docs/handbook/vergleichen.md b/docs/handbook/vergleichen.de.md similarity index 100% rename from docs/handbook/vergleichen.md rename to docs/handbook/vergleichen.de.md diff --git a/docs/handbook/watchlist.md b/docs/handbook/watchlist.de.md similarity index 100% rename from docs/handbook/watchlist.md rename to docs/handbook/watchlist.de.md diff --git a/docs/releases/v0.6.0.en.md b/docs/releases/v0.6.0.en.md deleted file mode 100644 index 8762f32..0000000 --- a/docs/releases/v0.6.0.en.md +++ /dev/null @@ -1,37 +0,0 @@ -# v0.6.0 — Release Notes - -**Date:** 2026-08-03 · **Tag:** [`v0.6.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.6.0) - -## New features - -- Complete modernization of all dependencies to the current major versions - (TypeScript 7, Vite 8, React 19.2, openid-client 6, zod 4, recharts 3, react-day-picker 10). - -## Fixes & improvements - -- CI build fixed via `allowBuilds` configuration for pnpm 11 - (build scripts for esbuild & Co. are no longer blocked). -- Image tagging simplified: only `latest` and `v*` tags, no more `nightly-*`/`sha-*` tags. -- All dependencies pinned exactly; automatic updates via Renovate prepared - (`renovate.json`, `docs/dependency-policy.md`). - -## API changes - -- No breaking changes to the API. openid-client internally migrated to v6 - (auth flow behaves identically). - -## Operations / upgrade - -- **Env vars:** unchanged. Node image pinned to `node:24.18.1-alpine`. -- **Migration:** no database migration required. -- **Breaking changes:** none. - -## Known limitations - -- `typedoc` (indirect orval dependency) shows a peer-dependency warning - (expects TypeScript 5.x/6.x, 7.x is installed) — harmless for build and runtime. - -## Links - -- Commit: [`2f66fff`](https://git.kubebase.de/admin/tool-evaluator/commit/2f66fff) -- Tag: [`v0.6.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.6.0) diff --git a/docs/releases/v0.6.0.md b/docs/releases/v0.6.0.md deleted file mode 100644 index 6e254c0..0000000 --- a/docs/releases/v0.6.0.md +++ /dev/null @@ -1,37 +0,0 @@ -# v0.6.0 — Release Notes - -**Datum:** 2026-08-03 · **Tag:** [`v0.6.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.6.0) - -## Neue Features - -- Vollständige Modernisierung aller Abhängigkeiten auf die aktuellen Hauptversionen - (TypeScript 7, Vite 8, React 19.2, openid-client 6, zod 4, recharts 3, react-day-picker 10). - -## Fixes & Verbesserungen - -- CI-Build durch `allowBuilds`-Konfiguration für pnpm 11 repariert - (Build-Scripts für esbuild & Co. werden nicht mehr blockiert). -- Image-Tagging vereinfacht: nur noch `latest` und `v*`-Tags, keine `nightly-*`/`sha-*`-Tags. -- Alle Dependencies exakt gepinnt; automatische Updates via Renovate vorbereitet - (`renovate.json`, `docs/dependency-policy.md`). - -## API-Änderungen - -- Keine Breaking Changes an der API. openid-client intern auf v6 migriert - (auth-Fluss verhält sich identisch). - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. Node-Image auf `node:24.18.1-alpine` gepinnt. -- **Migration:** keine Datenbank-Migration erforderlich. -- **Breaking Changes:** keine. - -## Bekannte Einschränkungen - -- `typedoc` (indirekte orval-Abhängigkeit) zeigt eine Peer-Dependency-Warnung - (erwartet TypeScript 5.x/6.x, installiert ist 7.x) — harmlos für Build & Laufzeit. - -## Links - -- Commit: [`2f66fff`](https://git.kubebase.de/admin/tool-evaluator/commit/2f66fff) -- Tag: [`v0.6.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.6.0) diff --git a/docs/releases/v0.7.0.en.md b/docs/releases/v0.7.0.en.md deleted file mode 100644 index 2348c6e..0000000 --- a/docs/releases/v0.7.0.en.md +++ /dev/null @@ -1,35 +0,0 @@ -# v0.7.0 — Release Notes - -**Date:** 2026-08-03 · **Tag:** [`v0.7.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.7.0) - -## New features - -- Version-bound **release documentation** in the app under `/docs` - (index + detail page per version, Markdown from `docs/releases/`). -- Generated release template (`docs/releases/TEMPLATE.md`) and - sync step for the frontend build. - -## Fixes & improvements - -- `tsx` bumped to 4.23.4 — last outdated dependency in the workspace - (`pnpm outdated -r` is now empty). - -## API changes - -- No breaking changes to the API. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. - -## Known limitations - -- The documentation is currently limited to release notes; a complete - API/field reference will follow in v0.8.0. - -## Links - -- Commit: [`520f917`](https://git.kubebase.de/admin/tool-evaluator/commit/520f917) -- Tag: [`v0.7.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.7.0) diff --git a/docs/releases/v0.7.0.md b/docs/releases/v0.7.0.md deleted file mode 100644 index daf5078..0000000 --- a/docs/releases/v0.7.0.md +++ /dev/null @@ -1,35 +0,0 @@ -# v0.7.0 — Release Notes - -**Datum:** 2026-08-03 · **Tag:** [`v0.7.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.7.0) - -## Neue Features - -- Version-gebundene **Release-Dokumentation** in der App unter `/docs` - (Index + Detailseite je Version, Markdown aus `docs/releases/`). -- Generiertes Release-Vorlage (`docs/releases/TEMPLATE.md`) und - Sync-Schritt für den Frontend-Build. - -## Fixes & Verbesserungen - -- `tsx` auf 4.23.4 angehoben — letzte veraltete Abhängigkeit im Workspace - (`pnpm outdated -r` ist jetzt leer). - -## API-Änderungen - -- Keine Breaking Changes an der API. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. - -## Bekannte Einschränkungen - -- Die Doku ist bisher auf Release-Notes beschränkt; eine vollständige - API-/Feld-Referenz folgt in v0.8.0. - -## Links - -- Commit: [`520f917`](https://git.kubebase.de/admin/tool-evaluator/commit/520f917) -- Tag: [`v0.7.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.7.0) diff --git a/docs/releases/v0.8.0.en.md b/docs/releases/v0.8.0.en.md deleted file mode 100644 index 671391b..0000000 --- a/docs/releases/v0.8.0.en.md +++ /dev/null @@ -1,46 +0,0 @@ -# v0.8.0 — Release Notes - -**Date:** 2026-08-03 · **Tag:** [`v0.8.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.0) - -## New features - -- **Complete documentation site** in mkdocs look under `/docs`: - - **Manual** with understandable explanations of all features - (Getting started, creating a tool, evaluations, comparing, watchlist, - analytics, administration, data model). - - **Automatically generated reference** from `lib/api-spec/openapi.yaml`: - all endpoints and data fields (type, required status, constraints) — - this guarantees that *every* feature is documented. - - **Search** across the manual, endpoints, and fields. - - **Version dropdown**: older releases keep their full field/endpoint - reference as a snapshot. - - **Repo link** to the source in the top right. -- **Help buttons (?) in forms** (NetBox style): next to each field, - an icon jumps directly to the field description in the docs. - -## Fixes & improvements - -- Docs generator `scripts/src/generate-docs.mjs` replaces the previous - `sync-release-docs.mjs` (OpenAPI parsing, manual, search index, snapshots). -- Documentation for v0.7.0 backfilled. - -## API changes - -- No breaking changes to the API. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. - -## Known limitations - -- Manual & reference apply to the current version; older versions - show their release notes and a reference snapshot, if generated at - release time (`node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`). - -## Links - -- Commit: [`6c92b63`](https://git.kubebase.de/admin/tool-evaluator/commit/6c92b63) -- Tag: [`v0.8.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.0) diff --git a/docs/releases/v0.8.0.md b/docs/releases/v0.8.0.md deleted file mode 100644 index 27e90d6..0000000 --- a/docs/releases/v0.8.0.md +++ /dev/null @@ -1,46 +0,0 @@ -# v0.8.0 — Release Notes - -**Datum:** 2026-08-03 · **Tag:** [`v0.8.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.0) - -## Neue Features - -- **Vollständige Dokumentations-Site** in mkdocs-Optik unter `/docs`: - - **Handbuch** mit verständlichen Erklärungen zu allen Features - (Erste Schritte, Tool anlegen, Bewertungen, Vergleichen, Merkliste, - Analytics, Administration, Datenmodell). - - **Automatisch generierte Referenz** aus `lib/api-spec/openapi.yaml`: - alle Endpunkte und Datenfelder (Typ, Pflichtstatus, Constraints) — - damit ist garantiert, dass *jedes* Feature dokumentiert ist. - - **Suche** über Handbuch, Endpunkte und Felder. - - **Versions-Dropdown**: ältere Releases behalten ihre vollständige - Feld-/Endpunkt-Referenz als Snapshot. - - **Repo-Link** oben rechts zur Quelle. -- **Hilfe-Buttons (?) in Formularen** (NetBox-Stil): neben jedem Feld - springt ein Icon direkt zur Feldbeschreibung in der Doku. - -## Fixes & Verbesserungen - -- Doku-Generator `scripts/src/generate-docs.mjs` ersetzt den bisherigen - `sync-release-docs.mjs` (OpenAPI-Parsing, Handbuch, Suchindex, Snapshots). -- Dokumentation für v0.7.0 nachgezogen. - -## API-Änderungen - -- Keine Breaking Changes an der API. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. - -## Bekannte Einschränkungen - -- Handbuch & Referenz gelten für die aktuelle Version; ältere Versionen - zeigen ihre Release-Notes und einen Referenz-Snapshot, sofern beim Release - erzeugt (`node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`). - -## Links - -- Commit: [`6c92b63`](https://git.kubebase.de/admin/tool-evaluator/commit/6c92b63) -- Tag: [`v0.8.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.0) diff --git a/docs/releases/v0.8.0/reference.json b/docs/releases/v0.8.0/reference.json deleted file mode 100644 index a3adfd9..0000000 --- a/docs/releases/v0.8.0/reference.json +++ /dev/null @@ -1,2782 +0,0 @@ -{ - "tags": [ - { - "name": "health", - "description": "Health operations", - "endpoints": [ - { - "operationId": "healthCheck", - "method": "GET", - "path": "/healthz", - "summary": "Health check", - "description": "Returns server health status", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Healthy", - "schema": { - "kind": "ref", - "value": "HealthStatus" - } - } - ] - }, - { - "operationId": "getVersion", - "method": "GET", - "path": "/version", - "summary": "Build version information", - "description": "Returns the running build version, commit SHA and build date", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Version information", - "schema": { - "kind": "ref", - "value": "VersionInfo" - } - } - ] - } - ] - }, - { - "name": "tools", - "description": "Tool management", - "endpoints": [ - { - "operationId": "listTools", - "method": "GET", - "path": "/tools", - "summary": "List all tools", - "description": "", - "parameters": [ - { - "name": "category", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "search", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "sort", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "newest, top_rated, most_reviewed, name_asc, name_desc, recently_updated" - }, - { - "name": "tags", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated tags; tool must include all of them", - "constraints": "" - }, - { - "name": "features", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated features; tool must include all of them", - "constraints": "" - }, - { - "name": "minRating", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "number" - }, - "description": "Minimum average combined rating (0-5)", - "constraints": "0–5" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "List of tools", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - } - ] - }, - { - "operationId": "createTool", - "method": "POST", - "path": "/tools", - "summary": "Create a new tool", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ToolInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created tool", - "schema": { - "kind": "ref", - "value": "Tool" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listCompareTools", - "method": "GET", - "path": "/compare", - "summary": "Compare tools side by side (premium)", - "description": "", - "parameters": [ - { - "name": "ids", - "in": "query", - "required": true, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated tool ids", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Tools in requested order", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - }, - { - "status": "401", - "description": "Authentication required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Premium feature required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getToolRatingHistory", - "method": "GET", - "path": "/tools/{id}/rating-history", - "summary": "Get a tool's rating history over time", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Rating history", - "schema": { - "kind": "array", - "value": "RatingHistoryItem" - } - }, - { - "status": "400", - "description": "Invalid id", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getTool", - "method": "GET", - "path": "/tools/{id}", - "summary": "Get a tool by ID", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Tool details", - "schema": { - "kind": "ref", - "value": "ToolWithStats" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateTool", - "method": "PATCH", - "path": "/tools/{id}", - "summary": "Update a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ToolUpdate" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated tool", - "schema": { - "kind": "ref", - "value": "Tool" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteTool", - "method": "DELETE", - "path": "/tools/{id}", - "summary": "Delete a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listTrashedTools", - "method": "GET", - "path": "/tools/trash", - "summary": "List trashed (soft-deleted) tools", - "description": "", - "parameters": [ - { - "name": "search", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "List of trashed tools", - "schema": { - "kind": "array", - "value": "Tool" - } - }, - { - "status": "403", - "description": "Feature \"trash\" requires a higher tier", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "trashTools", - "method": "POST", - "path": "/tools/trash", - "summary": "Move tools to trash (admin)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Tools trashed", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteTrashedTools", - "method": "DELETE", - "path": "/tools/trash", - "summary": "Permanently delete trashed tools (admin)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "restoreTools", - "method": "POST", - "path": "/tools/trash/restore", - "summary": "Restore trashed tools", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Tools restored", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Feature \"trash\" requires a higher tier", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "emptyTrash", - "method": "POST", - "path": "/tools/trash/empty", - "summary": "Permanently delete all trashed tools (admin)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Trash emptied", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listCategories", - "method": "GET", - "path": "/categories", - "summary": "List all distinct tool categories", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Categories list", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - }, - { - "operationId": "listAllFeatures", - "method": "GET", - "path": "/features/all", - "summary": "List all distinct feature strings across all tools", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "All known features", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - }, - { - "operationId": "listAllTags", - "method": "GET", - "path": "/tags/all", - "summary": "List all distinct tag strings across all tools", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "All known tags", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - } - ] - }, - { - "name": "ratings", - "description": "Tool ratings", - "endpoints": [ - { - "operationId": "listToolRatings", - "method": "GET", - "path": "/tools/{id}/ratings", - "summary": "List ratings for a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Ratings list", - "schema": { - "kind": "array", - "value": "Rating" - } - } - ] - }, - { - "operationId": "createRating", - "method": "POST", - "path": "/tools/{id}/ratings", - "summary": "Submit a rating for a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "RatingInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created rating", - "schema": { - "kind": "ref", - "value": "Rating" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "404", - "description": "Tool not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "analytics", - "description": "Analytics and aggregated statistics", - "endpoints": [ - { - "operationId": "getAnalyticsSummary", - "method": "GET", - "path": "/analytics/summary", - "summary": "Overall platform statistics", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Platform-level summary stats", - "schema": { - "kind": "ref", - "value": "AnalyticsSummary" - } - } - ] - }, - { - "operationId": "getTopTools", - "method": "GET", - "path": "/analytics/top-tools", - "summary": "Top-rated tools", - "description": "", - "parameters": [ - { - "name": "limit", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - }, - { - "name": "metric", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "usefulness, usability, combined" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Top tools list", - "schema": { - "kind": "array", - "value": "TopToolEntry" - } - } - ] - }, - { - "operationId": "getAnalyticsByCategory", - "method": "GET", - "path": "/analytics/by-category", - "summary": "Rating statistics grouped by category", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Per-category statistics", - "schema": { - "kind": "array", - "value": "CategoryStats" - } - } - ] - }, - { - "operationId": "getRatingDistribution", - "method": "GET", - "path": "/analytics/rating-distribution", - "summary": "Distribution of rating scores across the platform", - "description": "", - "parameters": [ - { - "name": "toolId", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Rating score distribution", - "schema": { - "kind": "ref", - "value": "RatingDistribution" - } - } - ] - } - ] - }, - { - "name": "auth", - "description": "Authentication", - "endpoints": [ - { - "operationId": "getAuthMode", - "method": "GET", - "path": "/auth/mode", - "summary": "Get authentication mode (oidc or local)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Auth mode", - "schema": { - "kind": "ref", - "value": "AuthMode" - } - } - ] - }, - { - "operationId": "getCsrfToken", - "method": "GET", - "path": "/auth/csrf", - "summary": "Get a CSRF token for state-changing requests", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "CSRF token", - "schema": { - "kind": "ref", - "value": "CsrfToken" - } - } - ] - }, - { - "operationId": "localLogin", - "method": "POST", - "path": "/auth/login", - "summary": "Local username/password login", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "LocalLoginInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Logged in successfully", - "schema": { - "kind": "ref", - "value": "AuthUser" - } - }, - { - "status": "401", - "description": "Invalid credentials", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getMe", - "method": "GET", - "path": "/auth/me", - "summary": "Get current authenticated user", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Current user info", - "schema": { - "kind": "ref", - "value": "AuthUser" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "changeMyPassword", - "method": "POST", - "path": "/auth/me/password", - "summary": "Change own password (local users only)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ChangePasswordInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Password changed", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "400", - "description": "Invalid input or wrong current password", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "422", - "description": "OIDC user - password is managed by the identity provider", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "429", - "description": "Too many attempts", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getPasswordRedirect", - "method": "GET", - "path": "/auth/password-redirect", - "summary": "Get redirect URL for managing credentials in the identity provider", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Redirect URL (null in local mode)", - "schema": { - "kind": "ref", - "value": "PasswordRedirect" - } - } - ] - }, - { - "operationId": "getMePreferences", - "method": "GET", - "path": "/auth/me/preferences", - "summary": "Get current user's browse preferences", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "User preferences", - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateMePreferences", - "method": "PUT", - "path": "/auth/me/preferences", - "summary": "Update current user's browse preferences", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated preferences", - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getMeWatchlist", - "method": "GET", - "path": "/auth/me/watchlist", - "summary": "Get current user's watchlist tools (premium)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Watchlist tools in saved order", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Premium feature required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "users", - "description": "User management (admin only)", - "endpoints": [ - { - "operationId": "listUsers", - "method": "GET", - "path": "/users", - "summary": "List all local users (admin only)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "User list", - "schema": { - "kind": "array", - "value": "User" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Forbidden", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "createUser", - "method": "POST", - "path": "/users", - "summary": "Create a new local user (admin only)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserCreateInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created user", - "schema": { - "kind": "ref", - "value": "User" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "409", - "description": "Username already exists", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateUser", - "method": "PATCH", - "path": "/users/{id}", - "summary": "Update user role (admin only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserRoleUpdate" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated user", - "schema": { - "kind": "ref", - "value": "User" - } - }, - { - "status": "404", - "description": "User not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteUser", - "method": "DELETE", - "path": "/users/{id}", - "summary": "Delete a user (admin only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - } - ] - }, - { - "operationId": "setUserPassword", - "method": "PATCH", - "path": "/users/{id}/password", - "summary": "Set/reset a user's password (admin only, local users only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "SetPasswordInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Password updated", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "404", - "description": "User not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "422", - "description": "OIDC user - password is managed by the identity provider", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "429", - "description": "Too many attempts", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "audit", - "description": "Audit log", - "endpoints": [ - { - "operationId": "listAuditLogs", - "method": "GET", - "path": "/audit-logs", - "summary": "List audit log entries (admin only)", - "description": "", - "parameters": [ - { - "name": "entityType", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "entityId", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - }, - { - "name": "limit", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Audit log entries", - "schema": { - "kind": "array", - "value": "AuditLog" - } - } - ] - } - ] - } - ], - "schemas": [ - { - "name": "HealthStatus", - "description": "", - "fields": [ - { - "name": "status", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "VersionInfo", - "description": "", - "fields": [ - { - "name": "version", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "commitSha", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "buildDate", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "trashRetentionDays", - "type": { - "kind": "type", - "value": "integer" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuthMode", - "description": "", - "fields": [ - { - "name": "mode", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "oidc, local" - } - ] - }, - { - "name": "CsrfToken", - "description": "", - "fields": [ - { - "name": "token", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "LocalLoginInput", - "description": "", - "fields": [ - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "User", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - }, - { - "name": "authProvider", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "local, oidc" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "UserCreateInput", - "description": "", - "fields": [ - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 2 chars" - }, - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - } - ] - }, - { - "name": "UserRoleUpdate", - "description": "", - "fields": [ - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - } - ] - }, - { - "name": "ChangePasswordInput", - "description": "", - "fields": [ - { - "name": "currentPassword", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "newPassword", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - } - ] - }, - { - "name": "SetPasswordInput", - "description": "", - "fields": [ - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - } - ] - }, - { - "name": "PasswordRedirect", - "description": "", - "fields": [ - { - "name": "url", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuditLog", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "entityType", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "entityId", - "type": { - "kind": "type", - "value": "integer | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "action", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "userId", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "changes", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "Tool", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "updatedAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "deletedAt", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "date-time" - }, - { - "name": "deletedBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "RatingHistoryItem", - "description": "", - "fields": [ - { - "name": "date", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "combined", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolWithStats", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "updatedAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "ratingCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgCombined", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolInput", - "description": "", - "fields": [ - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolUpdate", - "description": "", - "fields": [ - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "TrashToolsInput", - "description": "", - "fields": [ - { - "name": "ids", - "type": { - "kind": "array", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "min 1 items, max 500 items" - } - ] - }, - { - "name": "Rating", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "toolId", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "comment", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "reviewerName", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "RatingInput", - "description": "", - "fields": [ - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "comment", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "reviewerName", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AnalyticsSummary", - "description": "", - "fields": [ - { - "name": "totalTools", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "totalRatings", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgCombined", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "categoriesCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "mostRatedTool", - "type": { - "kind": "ref", - "value": "ToolWithStats" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "TopToolEntry", - "description": "", - "fields": [ - { - "name": "tool", - "type": { - "kind": "ref", - "value": "ToolWithStats" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "score", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "ratingCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "CategoryStats", - "description": "", - "fields": [ - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "toolCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "totalRatings", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "RatingDistribution", - "description": "", - "fields": [ - { - "name": "usefulness", - "type": { - "kind": "array", - "value": "ScoreBucket" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usability", - "type": { - "kind": "array", - "value": "ScoreBucket" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ScoreBucket", - "description": "", - "fields": [ - { - "name": "score", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "count", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuthUser", - "description": "", - "fields": [ - { - "name": "sub", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "preferredUsername", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - }, - { - "name": "entitlements", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "isLocal", - "type": { - "kind": "type", - "value": "boolean" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "UserPreferences", - "description": "", - "fields": [ - { - "name": "view", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "grid, table, rows" - }, - { - "name": "density", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "cozy, compact" - }, - { - "name": "watchlist", - "type": { - "kind": "array", - "value": "integer" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ErrorResponse", - "description": "", - "fields": [ - { - "name": "error", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - } - ] -} \ No newline at end of file diff --git a/docs/releases/v0.8.1.en.md b/docs/releases/v0.8.1.en.md deleted file mode 100644 index a865280..0000000 --- a/docs/releases/v0.8.1.en.md +++ /dev/null @@ -1,47 +0,0 @@ -# v0.8.1 — Release Notes - -**Date:** 2026-08-03 · **Tag:** [`v0.8.1`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.1) - -## New features - -- **Standalone docs page**: The documentation is now available as its own, - mkdocs-like page at `toolr.kubebase.de/docs` — without the app shell - (own header with repo link, version dropdown, search, theme toggle - and link back to the app). -- **Navigation renamed**: The sidebar entry is now called **"Help"** - and leads to the standalone docs. -- **User guide completely revised**: 17 manual pages with - step-by-step instructions for all features (finding tools, creating a - tool, evaluating, watchlist, comparing, costs, analytics, plans, - administration, redundancy, trash, keyboard shortcuts, data model). - -## Fixes & improvements - -- Reference links are now case-insensitive - (schema/endpoint slugs such as `toolinput` and `ToolInput` both work). -- Manual links to endpoint anchors corrected (PascalCase operation IDs). -- Outdated, broken manual links (`vergleichen`, `watchlist` …) replaced. -- Documentation table headers and notice texts in the docs page - internationalized via i18n (de/en). - -## API changes - -- No changes to the API. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. The docs page is reachable under `/docs` as - before; only the presentation is now standalone. - -## Known limitations - -- Manual & reference apply to the current version; older versions show - their release notes and a reference snapshot, if generated at release time - (`node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`). - -## Links - -- Commit: [`fdf2d74`](https://git.kubebase.de/admin/tool-evaluator/commit/fdf2d74) -- Tag: [`v0.8.1`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.1) diff --git a/docs/releases/v0.8.1.md b/docs/releases/v0.8.1.md deleted file mode 100644 index f6cab2c..0000000 --- a/docs/releases/v0.8.1.md +++ /dev/null @@ -1,47 +0,0 @@ -# v0.8.1 — Release Notes - -**Datum:** 2026-08-03 · **Tag:** [`v0.8.1`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.1) - -## Neue Features - -- **Standalone-Doku-Seite**: Die Dokumentation steht jetzt als eigene, - mkdocs-artige Seite unter `toolr.kubebase.de/docs` — ohne die App-Shell - (eigene Kopfzeile mit Repo-Link, Versions-Dropdown, Suche, Theme-Umschalter - und Link zurück zur App). -- **Navigation umbenannt**: Der Seitenleisten-Eintrag heißt jetzt **„Hilfe"** - und führt zur Standalone-Doku. -- **User Guide komplett überarbeitet**: 17 Handbuch-Seiten mit - Schritt-für-Schritt-Anleitungen für alle Funktionen (Tools finden, Tool - anlegen, Bewerten, Merkliste, Vergleichen, Kosten, Analytics, Pläne, - Administration, Redundanz, Papierkorb, Tastenkürzel, Datenmodell). - -## Fixes & Verbesserungen - -- Referenz-Links sind jetzt unabhängig von Groß-/Kleinschreibung - (Schema-/Endpoint-Slugs wie `toolinput` und `ToolInput` funktionieren beide). -- Handbuch-Links auf Endpunkt-Anker korrigiert (PascalCase-OperationIds). -- Veraltete, kaputte Handbuch-Links (`vergleichen`, `watchlist` …) ersetzt. -- Dokumentations-Tabellenkopfzeilen und Hinweistexte in der Doku-Seite über - i18n internationalisiert (de/en). - -## API-Änderungen - -- Keine Änderungen an der API. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. Die Doku-Seite ist unter `/docs` erreichbar wie - bisher; lediglich die Darstellung ist nun eigenständig. - -## Bekannte Einschränkungen - -- Handbuch & Referenz gelten für die aktuelle Version; ältere Versionen zeigen - ihre Release-Notes und einen Referenz-Snapshot, sofern beim Release erzeugt - (`node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`). - -## Links - -- Commit: [`fdf2d74`](https://git.kubebase.de/admin/tool-evaluator/commit/fdf2d74) -- Tag: [`v0.8.1`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.1) diff --git a/docs/releases/v0.8.1/handbook/administration.en.md b/docs/releases/v0.8.1/handbook/administration.en.md deleted file mode 100644 index 9fe7806..0000000 --- a/docs/releases/v0.8.1/handbook/administration.en.md +++ /dev/null @@ -1,61 +0,0 @@ - -# Administration - -The **Admin** area (`/admin`) is exclusively accessible to admins. -Without the admin role, access is denied. - -> At the top right, the **Redundancy dashboard** button leads to the automatic -> duplicate detection (see [Redundancy](/docs/handbook/redundanz)). - -## "Users" tab - -Management of local accounts. - -- **Add user:** username (required), password (at least 6 characters), - email (optional), **role** (User/Admin), **plan** (Free/Premium/Enterprise). -- **Edit user:** set role, plan and (for local accounts) a new password. - For OIDC accounts, password management is offered in the identity provider - (e.g. Keycloak). -- **Delete user:** permanently removes the account (not for your own account). - -API reference: -[`POST /users`](/docs/reference/endpoints/users#createUser), -[`PATCH /users/{id}`](/docs/reference/endpoints/users#updateUser), -[`DELETE /users/{id}`](/docs/reference/endpoints/users#deleteUser). - -## "Tools" tab - -Central access to the tool catalog. - -- **Search** for tools. -- View, edit or move individual tools to the trash. -- **Bulk action:** select multiple tools and move them to the trash - (confirmation dialog; soft-deleted tools are removed from all public views - and can be restored or permanently deleted). - -## "Audit log" tab - -Chronological log of all creation, change and deletion operations -(max. 100 entries): action, entity + ID, timestamp, executing person and -changed fields. - -API reference: [`GET /audit-logs`](/docs/reference/endpoints/audit#listAuditLogs). - -## "System" tab - -Version information of the running instance: - -- **Version** (e.g. `v0.8.1`), -- **Commit** (7-digit SHA, linked to the repository), -- **Build date**, -- **Trash retention** ("N days" or "Forever"). - -## Tool links (Admin) - -On the detail page of a tool you can manage **links** as an admin -(own/"manual" as well as automatically detected ones): - -- **Link tool:** dialog with tool ID, **relationship type** - (Similar / Replaces / Superseded by) and optional notes. -- Relationship types are displayed as badges on the detail page. -- Manual links can be removed again via the trash icon. diff --git a/docs/releases/v0.8.1/handbook/administration.md b/docs/releases/v0.8.1/handbook/administration.md deleted file mode 100644 index 585e0ce..0000000 --- a/docs/releases/v0.8.1/handbook/administration.md +++ /dev/null @@ -1,61 +0,0 @@ - -# Administration - -Der Bereich **Admin** (`/admin`) ist ausschließlich für Admins zugänglich. -Ohne Admin-Rolle erscheint eine Zugriffsverweigerung. - -> Oben rechts führt die Schaltfläche **Redundanz-Dashboard** zur automatischen -> Doppelungs-Erkennung (siehe [Redundanz](/docs/handbook/redundanz)). - -## Tab „Nutzer" - -Verwaltung der lokalen Konten. - -- **Nutzer hinzufügen:** Benutzername (Pflicht), Passwort (mind. 6 Zeichen), - E-Mail (optional), **Rolle** (User/Admin), **Tarif** (Free/Premium/Enterprise). -- **Nutzer bearbeiten:** Rolle, Tarif und (für lokale Konten) ein neues Passwort - setzen. Für OIDC-Konten wird die Passwortverwaltung im Identitätsanbieter - (z. B. Keycloak) angeboten. -- **Nutzer löschen:** Entfernt das Konto endgültig (nicht für das eigene Konto). - -API-Referenz: -[`POST /users`](/docs/reference/endpoints/users#createUser), -[`PATCH /users/{id}`](/docs/reference/endpoints/users#updateUser), -[`DELETE /users/{id}`](/docs/reference/endpoints/users#deleteUser). - -## Tab „Tools" - -Zentraler Zugriff auf den Tool-Katalog. - -- **Suchen** nach Tools. -- Tools einzeln ansehen, bearbeiten oder in den Papierkorb verschieben. -- **Massenaktion:** mehrere Tools auswählen und in den Papierkorb verschieben - (Bestätigungsdialog; soft gelöschte Tools sind aus allen öffentlichen Ansichten - entfernt und können wiederhergestellt oder endgültig gelöscht werden). - -## Tab „Audit-Log" - -Chronologisches Protokoll aller Anlage-, Änderungs- und Löschvorgänge -(max. 100 Einträge): Aktion, Entität + ID, Zeitstempel, ausführende Person und -geänderte Felder. - -API-Referenz: [`GET /audit-logs`](/docs/reference/endpoints/audit#listAuditLogs). - -## Tab „System" - -Versionsinformationen der laufenden Instanz: - -- **Version** (z. B. `v0.8.1`), -- **Commit** (7-stelliger SHA, verlinkt zum Repository), -- **Build-Datum**, -- **Papierkorb-Aufbewahrung** („N Tage" oder „Für immer"). - -## Tool-Verknüpfungen (Admin) - -Auf der Detailseite eines Tools kannst du als Admin **Verknüpfungen** -(eigene/„manual" sowie automatisch erkannte) verwalten: - -- **Tool verknüpfen:** Dialog mit Tool-ID, **Beziehungstyp** - (Ähnlich / Ersetzt / Abgelöst durch) und optionalen Notizen. -- Beziehungstypen werden als Badges auf der Detailseite angezeigt. -- Manuelle Verknüpfungen lassen sich per Papierkorb-Icon wieder entfernen. diff --git a/docs/releases/v0.8.1/handbook/getting-started.md b/docs/releases/v0.8.1/handbook/getting-started.md deleted file mode 100644 index 0fd7820..0000000 --- a/docs/releases/v0.8.1/handbook/getting-started.md +++ /dev/null @@ -1,53 +0,0 @@ - -# Erste Schritte - -Diese Seite führt dich durch die wichtigsten Abläufe in toolr — vom ersten -Besuch bis zum Anlegen und Bewerten eines Tools. - -## 1. Anmelden - -Die meisten Aktionen (Tool anlegen, bewerten, Watchlist, Vergleichen) erfordern -ein Konto. Klicke unten links auf **Anmelden**. Je nach Konfiguration der -Instanz hast du zwei Möglichkeiten: - -- **Lokale Konten:** Benutzername + Passwort. Der Zugang wird von einem Admin - angelegt (siehe [Administration](/docs/handbook/administration)). -- **OIDC (SSO):** Anmelden mit dem konfigurierten Identitätsanbieter (z. B. - Keycloak). - -Welcher Modus aktiv ist, steht im Endpunkt -[`GET /auth/mode`](/docs/reference/endpoints/auth#getAuthMode). Details findest -du im Abschnitt [Anmelden & Konto](/docs/handbook/konto). - -## 2. Tools finden - -Öffne den Bereich **Tools durchsuchen**: - -- **Suchen** — Volltextsuche über Name & Beschreibung (Tastenkürzel `/`). -- **Filtern** — nach Kategorie, Tags, Features und Mindestbewertung - (`minRating`). -- **Sortieren** — nach Aktualität, Top-Bewertung, meistbewertet, Name - (auf-/absteigend) oder letztem Update. - -Alle Optionen im Detail: [Tools finden & durchsuchen](/docs/handbook/tools-finden). - -## 3. Tool anlegen - -Gehe auf **Tool hinzufügen** und fülle das Formular aus. Details zu jedem Feld -findest du im Abschnitt [Tool anlegen](/docs/handbook/tool-anlegen) und in der -[Feld-Referenz](/docs/reference/schemas/toolinput). - -## 4. Bewerten - -Auf der Detailseite eines Tools kannst du **Nützlichkeit** und **Bedienbarkeit** -(jeweils 1–5) vergeben und optional einen Kommentar hinterlassen. Deine -Bewertung fließt sofort in die Statistiken ein. -Siehe [Bewerten](/docs/handbook/bewerten). - -## 5. Weiterführend - -- [Tools vergleichen](/docs/handbook/vergleichen) -- [Watchlist](/docs/handbook/watchlist) -- [Analytics](/docs/handbook/analytics) -- [Pläne & Berechtigungen](/docs/handbook/plaene) -- [Administration](/docs/handbook/administration) diff --git a/docs/releases/v0.8.1/handbook/index.en.md b/docs/releases/v0.8.1/handbook/index.en.md deleted file mode 100644 index 490c2c5..0000000 --- a/docs/releases/v0.8.1/handbook/index.en.md +++ /dev/null @@ -1,51 +0,0 @@ - -# Welcome to toolr - -toolr is a platform for **discovering, rating and comparing development -tools**. Users maintain a shared catalog of tools, submit ratings -(usefulness & usability) and use statistics to make the right choice. - -## What can you do with toolr? - -| Function | Description | Visibility | -| --- | --- | --- | -| **Browse tools** | Filter, sort and search the catalog | Everyone | -| **Create a tool** | Add a new tool with description, category, features & tags | Logged in | -| **Edit/delete tools** | Maintain your own tools (creator or admin) | Logged in | -| **Rate** | Submit usefulness & usability (1–5) plus a comment | Logged in | -| **Watchlist** | Save tools as favorites | Premium | -| **Compare** | View tools side by side | Premium | -| **Record costs** | Enter license and cost models per tool | Premium | -| **Analytics** | Statistics, top tools, distributions | Everyone | -| **Trash** | Restore soft-deleted tools or delete them permanently | Premium | -| **Admin** | User management, audit log, system information | Admin | -| **Redundancy detection** | Automatic duplicate detection | Admin | - -## How this documentation is organized - -- **User Guide** (these pages): step-by-step instructions for all - functions — from the [Getting Started](/docs/handbook/getting-started) to - [Administration](/docs/handbook/administration). -- **API Reference**: automatically generated from the OpenAPI specification — - all [endpoints](/docs/reference/endpoints/tools) and - [data fields](/docs/reference/schemas/toolinput) of the current version. -- **Release Notes**: what is new in each [version](/docs/releases/v0.8.1). - -## Getting started - -The fastest way: - -1. **Sign in** — without an account you can only browse - (see [Getting Started](/docs/handbook/getting-started#1-anmelden)). -2. **Find tools** — search, filters and sorting in the - [Browse tools](/docs/handbook/tools-finden) section. -3. **Create a tool** — via "Add tool" - ([guide](/docs/handbook/tool-anlegen)). -4. **Rate** — on the detail page of a tool - ([guide](/docs/handbook/bewerten)). - -## Contact & source code - -The source code is available at -[git.kubebase.de/admin/tool-evaluator](https://git.kubebase.de/admin/tool-evaluator) — -you can reach it at any time via the repository icon in the top right corner. diff --git a/docs/releases/v0.8.1/handbook/konto.md b/docs/releases/v0.8.1/handbook/konto.md deleted file mode 100644 index 40aae3d..0000000 --- a/docs/releases/v0.8.1/handbook/konto.md +++ /dev/null @@ -1,53 +0,0 @@ - -# Anmelden & Konto - -## Anmelden - -Klicke unten links in der Seitenleiste auf **Anmelden**. Je nach Konfiguration -der Instanz: - -- **Lokale Konten:** Benutzername und Passwort eingeben. Die Konten werden von - einem Admin angelegt (siehe [Administration](/docs/handbook/administration)). -- **OIDC (SSO):** Du wirst an den konfigurierten Identitätsanbieter - weitergeleitet und meldest dich dort an. - -Der aktive Modus steht im Endpunkt -[`GET /auth/mode`](/docs/reference/endpoints/auth#getAuthMode). - -> Die Login-Seite erreichst du direkt unter `/login`. Nach erfolgreicher -> Anmeldung wirst du zur ursprünglich aufgerufenen Seite zurückgeleitet. - -## Benutzerprofil - -Dein Profil (Avatar, Name, E-Mail, Tarif) siehst du unten links im -Benutzermenü. Dort stehen dir folgende Aktionen zur Verfügung: - -- **Watchlist** — deine gespeicherten Tools (nur mit dem entsprechenden Tarif). -- **Papierkorb** — wiederherstellbare, gelöschte Tools (Premium/Enterprise). -- **Passwort ändern** — für lokale Konten direkt in toolr; für OIDC-Konten wird - die Passwortverwaltung im Identitätsanbieter angeboten. -- **Abmelden** — beendet deine Sitzung. - -## Passwort ändern (lokales Konto) - -1. Öffne das Benutzermenü unten links. -2. Wähle **Passwort ändern**. -3. Gib das **aktuelle** sowie ein **neues** Passwort ein (mind. 6 Zeichen) und - bestätige es. -4. Speichern — das Passwort wird sofort übernommen. - -API-Referenz: [`POST /auth/me/password`](/docs/reference/endpoints/auth#changeMyPassword). - -## Anzeigeeinstellungen - -Über die Schaltflächen oben rechts kannst du: - -- **Sprache** wechseln (Deutsch / Englisch), -- **Theme** umschalten (Hell / Dunkel / System), -- die **Listenansicht** und **Dichte** im Bereich Tools durchsuchen anpassen - (siehe [Tools finden & durchsuchen](/docs/handbook/tools-finden)). - -Deine Präferenzen (inkl. Watchlist) werden im Endpunkt -[`GET /auth/me/preferences`](/docs/reference/endpoints/auth#getMePreferences) -gespeichert und über [`PUT /auth/me/preferences`](/docs/reference/endpoints/auth#updateMePreferences) -aktualisiert. diff --git a/docs/releases/v0.8.1/handbook/plaene.en.md b/docs/releases/v0.8.1/handbook/plaene.en.md deleted file mode 100644 index f73d6dc..0000000 --- a/docs/releases/v0.8.1/handbook/plaene.en.md +++ /dev/null @@ -1,41 +0,0 @@ - -# Plans & Permissions - -toolr distinguishes **plans** (tier) and **roles**. Admins bypass all feature -restrictions. - -## Plans - -| Plan | Description | -| --- | --- | -| **Free** | Basic functions: search, filter, view, analytics | -| **Premium** | Additionally watchlist, compare, trash, costs | -| **Enterprise** | All premium features + extended support | - -### Feature permissions - -Premium/Enterprise unlock the following features: - -| Feature | Function | Learn more | -| --- | --- | --- | -| `compare` | Compare tools | [Compare](/docs/handbook/vergleichen) | -| `watchlist` | Favorites list | [Watchlist](/docs/handbook/watchlist) | -| `trash` | Trash (soft-deleted tools) | [Trash](/docs/handbook/papierkorb) | -| `costs` | Record cost/license models | [Recording costs](/docs/handbook/kosten) | - -If you are missing a feature, the app shows an **upgrade notice** with a link -to the plan management. - -## Roles - -| Role | Permissions | -| --- | --- | -| **User** | Standard account: create/rate tools, edit your own tools | -| **Admin** | All user rights + administration, audit log, redundancy, empty trash, tool links | - -Admins pass **all** feature checks — even without a premium plan. - -## Plan/role management - -The assignment of role and plan is managed by admins in the -[Administration](/docs/handbook/administration) section (tab "Users"). diff --git a/docs/releases/v0.8.1/handbook/plaene.md b/docs/releases/v0.8.1/handbook/plaene.md deleted file mode 100644 index d4546b7..0000000 --- a/docs/releases/v0.8.1/handbook/plaene.md +++ /dev/null @@ -1,41 +0,0 @@ - -# Pläne & Berechtigungen - -toolr unterscheidet **Tarife** (Tier) und **Rollen**. Admins umgehen alle -Feature-Beschränkungen. - -## Tarife - -| Tarif | Beschreibung | -| --- | --- | -| **Free** | Grundfunktionen: suchen, filtern, ansehen, Analytics | -| **Premium** | Zusätzlich Watchlist, Vergleichen, Papierkorb, Kosten | -| **Enterprise** | Alle Premium-Features + erweiterter Support | - -### Feature-Berechtigungen - -Premium/Enterprise schalten folgende Features frei: - -| Feature | Funktion | Mehr erfahren | -| --- | --- | --- | -| `compare` | Tools vergleichen | [Vergleichen](/docs/handbook/vergleichen) | -| `watchlist` | Favoritenliste | [Watchlist](/docs/handbook/watchlist) | -| `trash` | Papierkorb (soft gelöschte Tools) | [Papierkorb](/docs/handbook/papierkorb) | -| `costs` | Kosten-/Lizenzmodelle erfassen | [Kosten erfassen](/docs/handbook/kosten) | - -Fehlt dir ein Feature, zeigt die App einen **Upgrade-Hinweis** mit Link zur -Tarifverwaltung. - -## Rollen - -| Rolle | Berechtigungen | -| --- | --- | -| **User** | Standard-Konto: Tools anlegen/bewerten, eigene Tools bearbeiten | -| **Admin** | Alle User-Rechte + Verwaltung, Audit-Log, Redundanz, Papierkorb leeren, Tool-Verknüpfungen | - -Admins passieren **alle** Feature-Checks — auch ohne Premium-Tarif. - -## Tarif-/Rollenverwaltung - -Die Zuordnung von Rolle und Tarif wird durch Admins im Bereich -[Administration](/docs/handbook/administration) (Tab „Nutzer") verwaltet. diff --git a/docs/releases/v0.8.1/handbook/tastatur.md b/docs/releases/v0.8.1/handbook/tastatur.md deleted file mode 100644 index 7eb6f17..0000000 --- a/docs/releases/v0.8.1/handbook/tastatur.md +++ /dev/null @@ -1,36 +0,0 @@ - -# Tastenkürzel & Kommandopalette - -## Kommandopalette - -Die Kommandopalette ist die zentrale Schnellnavigation: - -- Öffnen mit **`⌘K`** (macOS) bzw. **`Ctrl+K`** (Windows/Linux). -- Alternativ über die Suchleiste oben rechts („Tools suchen… ⌘K") oder das - Such-Icon auf Mobilgeräten. - -### Leerer Zustand - -Ohne Eingabe zeigt die Palette: - -- **Zuletzt angesehen** — die letzten 5 Tools, die du besucht hast. -- **Navigation** — Tools durchsuchen, Tool hinzufügen, Analytics sowie - (abhängig von Berechtigungen) Watchlist, Papierkorb und Admin. - -### Suche - -Tippe, um live nach Tools zu suchen (max. 10 Ergebnisse, inkl. Bewertung -`X.X★`). - -## Tastenkürzel im Überblick - -| Kürzel | Aktion | -| --- | --- | -| `⌘K` / `Ctrl+K` | Kommandopalette öffnen | -| `/` | Suche im Bereich „Tools durchsuchen" fokussieren | - -## Weitere Hinweise - -- **Zuletzt angesehen** wird lokal im Browser gespeichert (max. 5 Einträge). -- Die Seitenleiste (linke Navigation) ist auf Desktop einklappbar; der - Breadcrumb oben zeigt deinen aktuellen Ort. diff --git a/docs/releases/v0.8.1/handbook/tools-finden.md b/docs/releases/v0.8.1/handbook/tools-finden.md deleted file mode 100644 index c976515..0000000 --- a/docs/releases/v0.8.1/handbook/tools-finden.md +++ /dev/null @@ -1,67 +0,0 @@ - -# Tools finden & durchsuchen - -Der Bereich **Tools durchsuchen** (`/tools`) ist der Einstieg in den Katalog. -Hier kombinierst du Suche, Filter und Sortierung, um genau die Tools zu finden, -die dich interessieren. - -## Suche - -- Die **Suchleiste** durchsucht Name und Beschreibung (Volltext). -- Tastenkürzel: Drücke **`/`**, um die Suche zu fokussieren. -- Die Eingabe ist deaktiviert (Debounce), damit bei jedem Tastendruck sofort - nachgefiltert wird. - -## Filtern - -Über die Schaltfläche **Filter** (mit Badge für die Anzahl aktiver Filter) -öffnest du den Filter-Popover mit: - -- **Tags** — Auswahl über Checkboxen (scrollbare Liste). -- **Features** — Auswahl über Checkboxen. -- **Mindestbewertung** — Schieberegler von 0 bis 5 (Schritte von 0,5); zeigt - z. B. „3.0+" an. - -Aktive Filter erscheinen als **entfernbare Chips** über der Ergebnisliste. -Mit **Filter zurücksetzen** bzw. **Alle entfernen** räumst du sie wieder auf. - -## Sortieren - -Über das Dropdown **Sortieren** stehen folgende Optionen zur Verfügung: - -| Sortierung | Beschreibung | -| --- | --- | -| Neueste | Neue Tools zuerst | -| Top bewertet | Nach kombinierter Bewertung | -| Meistbewertet | Nach Anzahl der Bewertungen | -| Name (A–Z) | Alphabetisch aufsteigend | -| Name (Z–A) | Alphabetisch absteigend | -| Zuletzt aktualisiert | Nach letztem Update | - -## Ansicht & Dichte - -- **Ansicht wechseln:** Raster / Tabelle / Zeilen. -- **Dichte:** gemütlich / kompakt (Schieberegler). - -Deine Auswahl wird gespeichert — lokal im Browser und für angemeldete Nutzer:innen -zusätzlich serverseitig in den Präferenzen. Ansicht, Dichte, Suche, Filter und -Sortierung werden dabei in die URL übernommen, sodass du Ergebnisse teilen -kannst. - -## Tabellenansicht - -In der Tabellenansicht sind die Spalten **Tool**, **Bewertung** und **Anzahl -Bewertungen** sortierbar. Beim Überfahren einer Zeile erscheint eine Vorschau -mit Bewertungsdetails, Tags und Mini-Balken. - -## Auswählen für Vergleich & Watchlist - -- Auf jeder Karte/Zeile findest du ein **Vergleichs-Icon**, mit dem du Tools zur - [Vergleichsleiste](/docs/handbook/vergleichen) hinzufügst. -- Das **Lesezeichen-Icon** speichert Tools in deiner - [Watchlist](/docs/handbook/watchlist) (nur mit dem entsprechenden Tarif). - -## API - -Alle Such-, Filter- und Sortierparameter entsprechen den Query-Parametern von -[`GET /tools`](/docs/reference/endpoints/tools#listTools). diff --git a/docs/releases/v0.8.1/reference.json b/docs/releases/v0.8.1/reference.json deleted file mode 100644 index a3adfd9..0000000 --- a/docs/releases/v0.8.1/reference.json +++ /dev/null @@ -1,2782 +0,0 @@ -{ - "tags": [ - { - "name": "health", - "description": "Health operations", - "endpoints": [ - { - "operationId": "healthCheck", - "method": "GET", - "path": "/healthz", - "summary": "Health check", - "description": "Returns server health status", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Healthy", - "schema": { - "kind": "ref", - "value": "HealthStatus" - } - } - ] - }, - { - "operationId": "getVersion", - "method": "GET", - "path": "/version", - "summary": "Build version information", - "description": "Returns the running build version, commit SHA and build date", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Version information", - "schema": { - "kind": "ref", - "value": "VersionInfo" - } - } - ] - } - ] - }, - { - "name": "tools", - "description": "Tool management", - "endpoints": [ - { - "operationId": "listTools", - "method": "GET", - "path": "/tools", - "summary": "List all tools", - "description": "", - "parameters": [ - { - "name": "category", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "search", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "sort", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "newest, top_rated, most_reviewed, name_asc, name_desc, recently_updated" - }, - { - "name": "tags", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated tags; tool must include all of them", - "constraints": "" - }, - { - "name": "features", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated features; tool must include all of them", - "constraints": "" - }, - { - "name": "minRating", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "number" - }, - "description": "Minimum average combined rating (0-5)", - "constraints": "0–5" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "List of tools", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - } - ] - }, - { - "operationId": "createTool", - "method": "POST", - "path": "/tools", - "summary": "Create a new tool", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ToolInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created tool", - "schema": { - "kind": "ref", - "value": "Tool" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listCompareTools", - "method": "GET", - "path": "/compare", - "summary": "Compare tools side by side (premium)", - "description": "", - "parameters": [ - { - "name": "ids", - "in": "query", - "required": true, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated tool ids", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Tools in requested order", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - }, - { - "status": "401", - "description": "Authentication required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Premium feature required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getToolRatingHistory", - "method": "GET", - "path": "/tools/{id}/rating-history", - "summary": "Get a tool's rating history over time", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Rating history", - "schema": { - "kind": "array", - "value": "RatingHistoryItem" - } - }, - { - "status": "400", - "description": "Invalid id", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getTool", - "method": "GET", - "path": "/tools/{id}", - "summary": "Get a tool by ID", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Tool details", - "schema": { - "kind": "ref", - "value": "ToolWithStats" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateTool", - "method": "PATCH", - "path": "/tools/{id}", - "summary": "Update a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ToolUpdate" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated tool", - "schema": { - "kind": "ref", - "value": "Tool" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteTool", - "method": "DELETE", - "path": "/tools/{id}", - "summary": "Delete a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listTrashedTools", - "method": "GET", - "path": "/tools/trash", - "summary": "List trashed (soft-deleted) tools", - "description": "", - "parameters": [ - { - "name": "search", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "List of trashed tools", - "schema": { - "kind": "array", - "value": "Tool" - } - }, - { - "status": "403", - "description": "Feature \"trash\" requires a higher tier", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "trashTools", - "method": "POST", - "path": "/tools/trash", - "summary": "Move tools to trash (admin)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Tools trashed", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteTrashedTools", - "method": "DELETE", - "path": "/tools/trash", - "summary": "Permanently delete trashed tools (admin)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "restoreTools", - "method": "POST", - "path": "/tools/trash/restore", - "summary": "Restore trashed tools", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Tools restored", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Feature \"trash\" requires a higher tier", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "emptyTrash", - "method": "POST", - "path": "/tools/trash/empty", - "summary": "Permanently delete all trashed tools (admin)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Trash emptied", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listCategories", - "method": "GET", - "path": "/categories", - "summary": "List all distinct tool categories", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Categories list", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - }, - { - "operationId": "listAllFeatures", - "method": "GET", - "path": "/features/all", - "summary": "List all distinct feature strings across all tools", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "All known features", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - }, - { - "operationId": "listAllTags", - "method": "GET", - "path": "/tags/all", - "summary": "List all distinct tag strings across all tools", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "All known tags", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - } - ] - }, - { - "name": "ratings", - "description": "Tool ratings", - "endpoints": [ - { - "operationId": "listToolRatings", - "method": "GET", - "path": "/tools/{id}/ratings", - "summary": "List ratings for a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Ratings list", - "schema": { - "kind": "array", - "value": "Rating" - } - } - ] - }, - { - "operationId": "createRating", - "method": "POST", - "path": "/tools/{id}/ratings", - "summary": "Submit a rating for a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "RatingInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created rating", - "schema": { - "kind": "ref", - "value": "Rating" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "404", - "description": "Tool not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "analytics", - "description": "Analytics and aggregated statistics", - "endpoints": [ - { - "operationId": "getAnalyticsSummary", - "method": "GET", - "path": "/analytics/summary", - "summary": "Overall platform statistics", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Platform-level summary stats", - "schema": { - "kind": "ref", - "value": "AnalyticsSummary" - } - } - ] - }, - { - "operationId": "getTopTools", - "method": "GET", - "path": "/analytics/top-tools", - "summary": "Top-rated tools", - "description": "", - "parameters": [ - { - "name": "limit", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - }, - { - "name": "metric", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "usefulness, usability, combined" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Top tools list", - "schema": { - "kind": "array", - "value": "TopToolEntry" - } - } - ] - }, - { - "operationId": "getAnalyticsByCategory", - "method": "GET", - "path": "/analytics/by-category", - "summary": "Rating statistics grouped by category", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Per-category statistics", - "schema": { - "kind": "array", - "value": "CategoryStats" - } - } - ] - }, - { - "operationId": "getRatingDistribution", - "method": "GET", - "path": "/analytics/rating-distribution", - "summary": "Distribution of rating scores across the platform", - "description": "", - "parameters": [ - { - "name": "toolId", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Rating score distribution", - "schema": { - "kind": "ref", - "value": "RatingDistribution" - } - } - ] - } - ] - }, - { - "name": "auth", - "description": "Authentication", - "endpoints": [ - { - "operationId": "getAuthMode", - "method": "GET", - "path": "/auth/mode", - "summary": "Get authentication mode (oidc or local)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Auth mode", - "schema": { - "kind": "ref", - "value": "AuthMode" - } - } - ] - }, - { - "operationId": "getCsrfToken", - "method": "GET", - "path": "/auth/csrf", - "summary": "Get a CSRF token for state-changing requests", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "CSRF token", - "schema": { - "kind": "ref", - "value": "CsrfToken" - } - } - ] - }, - { - "operationId": "localLogin", - "method": "POST", - "path": "/auth/login", - "summary": "Local username/password login", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "LocalLoginInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Logged in successfully", - "schema": { - "kind": "ref", - "value": "AuthUser" - } - }, - { - "status": "401", - "description": "Invalid credentials", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getMe", - "method": "GET", - "path": "/auth/me", - "summary": "Get current authenticated user", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Current user info", - "schema": { - "kind": "ref", - "value": "AuthUser" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "changeMyPassword", - "method": "POST", - "path": "/auth/me/password", - "summary": "Change own password (local users only)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ChangePasswordInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Password changed", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "400", - "description": "Invalid input or wrong current password", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "422", - "description": "OIDC user - password is managed by the identity provider", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "429", - "description": "Too many attempts", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getPasswordRedirect", - "method": "GET", - "path": "/auth/password-redirect", - "summary": "Get redirect URL for managing credentials in the identity provider", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Redirect URL (null in local mode)", - "schema": { - "kind": "ref", - "value": "PasswordRedirect" - } - } - ] - }, - { - "operationId": "getMePreferences", - "method": "GET", - "path": "/auth/me/preferences", - "summary": "Get current user's browse preferences", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "User preferences", - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateMePreferences", - "method": "PUT", - "path": "/auth/me/preferences", - "summary": "Update current user's browse preferences", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated preferences", - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getMeWatchlist", - "method": "GET", - "path": "/auth/me/watchlist", - "summary": "Get current user's watchlist tools (premium)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Watchlist tools in saved order", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Premium feature required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "users", - "description": "User management (admin only)", - "endpoints": [ - { - "operationId": "listUsers", - "method": "GET", - "path": "/users", - "summary": "List all local users (admin only)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "User list", - "schema": { - "kind": "array", - "value": "User" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Forbidden", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "createUser", - "method": "POST", - "path": "/users", - "summary": "Create a new local user (admin only)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserCreateInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created user", - "schema": { - "kind": "ref", - "value": "User" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "409", - "description": "Username already exists", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateUser", - "method": "PATCH", - "path": "/users/{id}", - "summary": "Update user role (admin only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserRoleUpdate" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated user", - "schema": { - "kind": "ref", - "value": "User" - } - }, - { - "status": "404", - "description": "User not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteUser", - "method": "DELETE", - "path": "/users/{id}", - "summary": "Delete a user (admin only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - } - ] - }, - { - "operationId": "setUserPassword", - "method": "PATCH", - "path": "/users/{id}/password", - "summary": "Set/reset a user's password (admin only, local users only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "SetPasswordInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Password updated", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "404", - "description": "User not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "422", - "description": "OIDC user - password is managed by the identity provider", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "429", - "description": "Too many attempts", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "audit", - "description": "Audit log", - "endpoints": [ - { - "operationId": "listAuditLogs", - "method": "GET", - "path": "/audit-logs", - "summary": "List audit log entries (admin only)", - "description": "", - "parameters": [ - { - "name": "entityType", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "entityId", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - }, - { - "name": "limit", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Audit log entries", - "schema": { - "kind": "array", - "value": "AuditLog" - } - } - ] - } - ] - } - ], - "schemas": [ - { - "name": "HealthStatus", - "description": "", - "fields": [ - { - "name": "status", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "VersionInfo", - "description": "", - "fields": [ - { - "name": "version", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "commitSha", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "buildDate", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "trashRetentionDays", - "type": { - "kind": "type", - "value": "integer" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuthMode", - "description": "", - "fields": [ - { - "name": "mode", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "oidc, local" - } - ] - }, - { - "name": "CsrfToken", - "description": "", - "fields": [ - { - "name": "token", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "LocalLoginInput", - "description": "", - "fields": [ - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "User", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - }, - { - "name": "authProvider", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "local, oidc" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "UserCreateInput", - "description": "", - "fields": [ - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 2 chars" - }, - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - } - ] - }, - { - "name": "UserRoleUpdate", - "description": "", - "fields": [ - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - } - ] - }, - { - "name": "ChangePasswordInput", - "description": "", - "fields": [ - { - "name": "currentPassword", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "newPassword", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - } - ] - }, - { - "name": "SetPasswordInput", - "description": "", - "fields": [ - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - } - ] - }, - { - "name": "PasswordRedirect", - "description": "", - "fields": [ - { - "name": "url", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuditLog", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "entityType", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "entityId", - "type": { - "kind": "type", - "value": "integer | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "action", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "userId", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "changes", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "Tool", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "updatedAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "deletedAt", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "date-time" - }, - { - "name": "deletedBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "RatingHistoryItem", - "description": "", - "fields": [ - { - "name": "date", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "combined", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolWithStats", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "updatedAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "ratingCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgCombined", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolInput", - "description": "", - "fields": [ - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolUpdate", - "description": "", - "fields": [ - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "TrashToolsInput", - "description": "", - "fields": [ - { - "name": "ids", - "type": { - "kind": "array", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "min 1 items, max 500 items" - } - ] - }, - { - "name": "Rating", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "toolId", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "comment", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "reviewerName", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "RatingInput", - "description": "", - "fields": [ - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "comment", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "reviewerName", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AnalyticsSummary", - "description": "", - "fields": [ - { - "name": "totalTools", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "totalRatings", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgCombined", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "categoriesCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "mostRatedTool", - "type": { - "kind": "ref", - "value": "ToolWithStats" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "TopToolEntry", - "description": "", - "fields": [ - { - "name": "tool", - "type": { - "kind": "ref", - "value": "ToolWithStats" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "score", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "ratingCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "CategoryStats", - "description": "", - "fields": [ - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "toolCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "totalRatings", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "RatingDistribution", - "description": "", - "fields": [ - { - "name": "usefulness", - "type": { - "kind": "array", - "value": "ScoreBucket" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usability", - "type": { - "kind": "array", - "value": "ScoreBucket" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ScoreBucket", - "description": "", - "fields": [ - { - "name": "score", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "count", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuthUser", - "description": "", - "fields": [ - { - "name": "sub", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "preferredUsername", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - }, - { - "name": "entitlements", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "isLocal", - "type": { - "kind": "type", - "value": "boolean" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "UserPreferences", - "description": "", - "fields": [ - { - "name": "view", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "grid, table, rows" - }, - { - "name": "density", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "cozy, compact" - }, - { - "name": "watchlist", - "type": { - "kind": "array", - "value": "integer" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ErrorResponse", - "description": "", - "fields": [ - { - "name": "error", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - } - ] -} \ No newline at end of file diff --git a/docs/releases/v0.8.2.en.md b/docs/releases/v0.8.2.en.md deleted file mode 100644 index d3b3224..0000000 --- a/docs/releases/v0.8.2.en.md +++ /dev/null @@ -1,35 +0,0 @@ -# v0.8.2 — Release Notes - -**Date:** 2026-08-04 · **Tag:** [`v0.8.2`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.2) - -## Fixes & improvements - -- **Mobile navigation in the docs**: The left navigation bar (manual, - endpoints, schemas) was completely hidden below `lg` (1024px). - There is now a menu button in the header that opens a side - navigation drawer with the same content — on small screens - the docs remain fully navigable. -- **Version dropdown shows the selected version**: When switching to a - different release (`/docs/releases/vX.Y.Z`), the dropdown wrongly stayed on - "current". The displayed version is now also derived from the releases route. - -## API changes - -- No changes to the API. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. - -## Known limitations - -- Manual & reference apply to the current version; older versions show - their release notes and a reference snapshot, if generated at release time - (`node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`). - -## Links - -- Commit: [`33cf261`](https://git.kubebase.de/admin/tool-evaluator/commit/33cf261) -- Tag: [`v0.8.2`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.2) diff --git a/docs/releases/v0.8.2.md b/docs/releases/v0.8.2.md deleted file mode 100644 index 4613159..0000000 --- a/docs/releases/v0.8.2.md +++ /dev/null @@ -1,36 +0,0 @@ -# v0.8.2 — Release Notes - -**Datum:** 2026-08-04 · **Tag:** [`v0.8.2`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.2) - -## Fixes & Verbesserungen - -- **Mobile Navigation in der Doku**: Die linke Navigationsleiste (Handbuch, - Endpunkte, Schemas) wurde unterhalb von `lg` (1024px) komplett ausgeblendet. - Es gibt jetzt einen Menü-Button im Kopfbereich, der ein seitliches - Navigations-Drawer mit demselben Inhalt öffnet — auf kleinen Bildschirmen - bleibt die Doku voll navigierbar. -- **Versions-Dropdown zeigt die gewählte Version an**: Beim Wechsel zu einem - anderen Release (`/docs/releases/vX.Y.Z`) blieb das Dropdown fälschlich auf - „aktuell". Die angezeigte Version wird jetzt auch aus der releases-Route - abgeleitet. - -## API-Änderungen - -- Keine Änderungen an der API. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. - -## Bekannte Einschränkungen - -- Handbuch & Referenz gelten für die aktuelle Version; ältere Versionen zeigen - ihre Release-Notes und einen Referenz-Snapshot, sofern beim Release erzeugt - (`node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`). - -## Links - -- Commit: [`33cf261`](https://git.kubebase.de/admin/tool-evaluator/commit/33cf261) -- Tag: [`v0.8.2`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.2) diff --git a/docs/releases/v0.8.2/handbook/analytics.en.md b/docs/releases/v0.8.2/handbook/analytics.en.md deleted file mode 100644 index 7450a33..0000000 --- a/docs/releases/v0.8.2/handbook/analytics.en.md +++ /dev/null @@ -1,29 +0,0 @@ - -# Analytics - -The **Analytics** area (`/analytics`) is a public dashboard with -metrics and charts based on all tools and ratings. - -## Metrics (KPI cards) - -- **Number of tools** — how many tools are recorded in the catalog. -- **Number of ratings** — how many ratings were submitted in total. -- **Active categories** — how many categories exist. -- **Average rating** — global combined value. - -## Charts - -| Chart | Content | -| --- | --- | -| **Top 8 tools** | Bar chart of the tools with the highest combined score (0–5) | -| **Tools per category** | Radar chart of the number of tools per category | -| **Score distribution** | Two horizontal bar charts (usefulness & usability) per star | - -The charts are interactive (tooltips on hover). - -## API - -- [`GET /analytics/summary`](/docs/reference/endpoints/analytics#getAnalyticsSummary) -- [`GET /analytics/top-tools`](/docs/reference/endpoints/analytics#getTopTools) -- [`GET /analytics/by-category`](/docs/reference/endpoints/analytics#getAnalyticsByCategory) -- [`GET /analytics/rating-distribution`](/docs/reference/endpoints/analytics#getRatingDistribution) diff --git a/docs/releases/v0.8.2/handbook/analytics.md b/docs/releases/v0.8.2/handbook/analytics.md deleted file mode 100644 index 3cfacd8..0000000 --- a/docs/releases/v0.8.2/handbook/analytics.md +++ /dev/null @@ -1,29 +0,0 @@ - -# Analytics - -Der Bereich **Analytics** (`/analytics`) ist ein öffentliches Dashboard mit -Kennzahlen und Diagrammen auf Basis aller Tools und Bewertungen. - -## Kennzahlen (KPI-Karten) - -- **Anzahl Tools** — wie viele Tools sind im Katalog erfasst. -- **Anzahl Bewertungen** — wie viele Bewertungen wurden insgesamt abgegeben. -- **Aktive Kategorien** — wie viele Kategorien existieren. -- **Durchschnittliche Bewertung** — globaler kombinierter Wert. - -## Diagramme - -| Diagramm | Inhalt | -| --- | --- | -| **Top 8 Tools** | Balkendiagramm der Tools mit der höchsten kombinierten Punktzahl (0–5) | -| **Tools je Kategorie** | Radar-Diagramm der Tool-Anzahl pro Kategorie | -| **Punkteverteilung** | Zwei horizontale Balken-Diagramme (Nützlichkeit & Bedienbarkeit) pro Stern | - -Die Diagramme sind interaktiv (Tooltips beim Überfahren). - -## API - -- [`GET /analytics/summary`](/docs/reference/endpoints/analytics#getAnalyticsSummary) -- [`GET /analytics/top-tools`](/docs/reference/endpoints/analytics#getTopTools) -- [`GET /analytics/by-category`](/docs/reference/endpoints/analytics#getAnalyticsByCategory) -- [`GET /analytics/rating-distribution`](/docs/reference/endpoints/analytics#getRatingDistribution) diff --git a/docs/releases/v0.8.2/handbook/bewerten.en.md b/docs/releases/v0.8.2/handbook/bewerten.en.md deleted file mode 100644 index 7ccd0c8..0000000 --- a/docs/releases/v0.8.2/handbook/bewerten.en.md +++ /dev/null @@ -1,39 +0,0 @@ - -# Rating - -On the detail page of a tool you can share your experience. Click on -**Submit a rating** (requires an account). - -## Form fields - -| Field | Required | Notes | -| --- | --- | --- | -| **Usefulness** | Yes | 1–5 stars | -| **Usability** | Yes | 1–5 stars | -| **Comment** | No | Free text | -| **Name** | No | Defaults to "Anonymous" | - -Next to the fields, the **? icon** links directly to the associated field -description in the [data model reference](/docs/reference/schemas/ratinginput). - -## What happens after submitting? - -- Your rating is saved immediately and appears in the **rating list** of the - detail page. -- The **averages** (usefulness, usability, combined) and the **score - distribution** are updated. -- The **statistics** in the [Analytics](/docs/handbook/analytics) section are - recalculated. - -## Statistic sections on the detail page - -- **Rating overview:** usefulness & usability as an average with progress - bars. -- **Score distribution:** number of ratings per star (1★–5★). -- **History:** line chart of combined/individual values over time - (only visible once there are several ratings). - -## API - -- [`POST /tools/{id}/ratings`](/docs/reference/endpoints/ratings#createRating) — Submit a rating -- [`GET /tools/{id}/ratings`](/docs/reference/endpoints/ratings#listToolRatings) — Ratings of a tool diff --git a/docs/releases/v0.8.2/handbook/bewerten.md b/docs/releases/v0.8.2/handbook/bewerten.md deleted file mode 100644 index b4d054e..0000000 --- a/docs/releases/v0.8.2/handbook/bewerten.md +++ /dev/null @@ -1,39 +0,0 @@ - -# Bewerten - -Auf der Detailseite eines Tools kannst du deine Erfahrung teilen. Klicke auf -**Bewertung abgeben** (erfordert ein Konto). - -## Formularfelder - -| Feld | Pflicht | Hinweise | -| --- | --- | --- | -| **Nützlichkeit** | Ja | 1–5 Sterne | -| **Bedienbarkeit** | Ja | 1–5 Sterne | -| **Kommentar** | Nein | Freitext | -| **Name** | Nein | Standard „Anonym" | - -Neben den Feldern führt das **?‑Icon** direkt zur zugehörigen Feldbeschreibung -in der [Datenmodell-Referenz](/docs/reference/schemas/ratinginput). - -## Was passiert nach dem Abgeben? - -- Deine Bewertung wird sofort gespeichert und erscheint in der - **Bewertungsliste** der Detailseite. -- Die **Durchschnittswerte** (Nützlichkeit, Bedienbarkeit, Kombiniert) und die - **Punkteverteilung** werden aktualisiert. -- Die **Statistiken** im Bereich [Analytics](/docs/handbook/analytics) werden - neu berechnet. - -## Statistik-Bereiche auf der Detailseite - -- **Bewertungsübersicht:** Nützlichkeit & Bedienbarkeit als Durchschnitt mit - Fortschrittsbalken. -- **Punkteverteilung:** Anzahl der Bewertungen pro Stern (1★–5★). -- **Verlauf:** Linienchart der kombinierten/Teilwerte über die Zeit - (erst ab mehreren Bewertungen sichtbar). - -## API - -- [`POST /tools/{id}/ratings`](/docs/reference/endpoints/ratings#createRating) — Bewertung abgeben -- [`GET /tools/{id}/ratings`](/docs/reference/endpoints/ratings#listToolRatings) — Bewertungen eines Tools diff --git a/docs/releases/v0.8.2/handbook/datenmodell.en.md b/docs/releases/v0.8.2/handbook/datenmodell.en.md deleted file mode 100644 index 99d602e..0000000 --- a/docs/releases/v0.8.2/handbook/datenmodell.en.md +++ /dev/null @@ -1,70 +0,0 @@ - -# Data model - -This chapter explains the central data objects of toolr at the application -level. The complete, automatically generated reference of all fields, -types and constraints can be found in the -[API reference](/docs/reference/schemas/tool). - -## Tool - -The heart of it all: a tool recorded in the catalog. - -| Property | Description | -| --- | --- | -| `id` | Unique identifier | -| `name` | Display name | -| `description` | Description (what does the tool do?) | -| `category` | Category assignment | -| `websiteUrl` | Official website (optional) | -| `iconUrl` | Logo/icon URL (optional) | -| `features` | List of capabilities | -| `tags` | List of keywords | -| `createdAt` / `updatedAt` | Timestamps | -| `createdBy` | Person who created it | -| `deletedAt` / `deletedBy` | Soft deletion (trash) | - -Input forms use the derived schemas -[`ToolInput`](/docs/reference/schemas/toolinput) and -[`ToolUpdate`](/docs/reference/schemas/toolupdate). -Aggregated views are provided by [`ToolWithStats`](/docs/reference/schemas/toolwithstats) -(e.g. with average rating). - -## Rating (Bewertung) - -A single rating for a tool: - -- `usefulness` (Nützlichkeit, 1–5) and `usability` (Bedienbarkeit, 1–5) -- optional `comment` and a display name (`reviewerName`) -- timestamp - -Input schema: [`RatingInput`](/docs/reference/schemas/ratinginput). - -## User & Auth - -- [`User`](/docs/reference/schemas/user) — user account with role (User/Admin) - and plan (Free/Premium/Enterprise). -- [`AuthUser`](/docs/reference/schemas/authuser) — the logged-in profile - including `entitlements` (available features). -- [`UserPreferences`](/docs/reference/schemas/userpreferences) — view and - density preferences as well as the `watchlist` (list of tool IDs). - -## Analytics - -The statistics endpoints provide aggregated data: - -- [`AnalyticsSummary`](/docs/reference/schemas/analyticssummary) — global - metrics (number of tools/ratings, categories, average). -- [`TopToolEntry`](/docs/reference/schemas/TopToolEntry) — an entry of the - top tools.- [`CategoryStats`](/docs/reference/schemas/categorystats) — number of tools per - category. -- [`RatingDistribution`](/docs/reference/schemas/ratingdistribution) — - score distribution (usefulness & usability). -- [`ScoreBucket`](/docs/reference/schemas/scorebucket) — a value bucket. - -## Additional - -- [`VersionInfo`](/docs/reference/schemas/versioninfo) — version, commit SHA, - build date and trash retention of the running instance. -- [`AuditLog`](/docs/reference/schemas/auditlog) — a log entry - (action, entity, timestamp, actor, changes). diff --git a/docs/releases/v0.8.2/handbook/datenmodell.md b/docs/releases/v0.8.2/handbook/datenmodell.md deleted file mode 100644 index 618e160..0000000 --- a/docs/releases/v0.8.2/handbook/datenmodell.md +++ /dev/null @@ -1,70 +0,0 @@ - -# Datenmodell - -Dieses Kapitel erklärt die zentralen Datenobjekte von toolr auf Ebene der -Anwendung. Die vollständige, automatisch generierte Referenz aller Felder, -Typen und Constraints findest du in der -[API-Referenz](/docs/reference/schemas/tool). - -## Tool - -Das Herzstück: ein im Katalog erfasstes Werkzeug. - -| Eigenschaft | Beschreibung | -| --- | --- | -| `id` | Eindeutige Kennung | -| `name` | Anzeigename | -| `description` | Beschreibung (Was macht das Tool?) | -| `category` | Kategorie-Zuordnung | -| `websiteUrl` | Offizielle Website (optional) | -| `iconUrl` | Logo-/Icon-URL (optional) | -| `features` | Liste von Fähigkeiten | -| `tags` | Liste von Schlagwörtern | -| `createdAt` / `updatedAt` | Zeitstempel | -| `createdBy` | Erstellende Person | -| `deletedAt` / `deletedBy` | Soft-Löschung (Papierkorb) | - -Eingabe-Formulare verwenden die abgeleiteten Schemas -[`ToolInput`](/docs/reference/schemas/toolinput) und -[`ToolUpdate`](/docs/reference/schemas/toolupdate). -Aggregierte Ansichten liefert [`ToolWithStats`](/docs/reference/schemas/toolwithstats) -(z. B. mit Durchschnittsbewertung). - -## Rating (Bewertung) - -Eine einzelne Bewertung zu einem Tool: - -- `usefulness` (Nützlichkeit, 1–5) und `usability` (Bedienbarkeit, 1–5) -- optional `comment` und ein Anzeigename (`reviewerName`) -- Zeitstempel - -Eingabe-Schema: [`RatingInput`](/docs/reference/schemas/ratinginput). - -## User & Auth - -- [`User`](/docs/reference/schemas/user) — Benutzerkonto mit Rolle (User/Admin) - und Tarif (Free/Premium/Enterprise). -- [`AuthUser`](/docs/reference/schemas/authuser) — das angemeldete Profil - inklusive `entitlements` (verfügbare Features). -- [`UserPreferences`](/docs/reference/schemas/userpreferences) — Ansichts- und - Dichte-Präferenzen sowie die `watchlist` (Liste von Tool-IDs). - -## Analytics - -Die Statistik-Endpunkte liefern aggregierte Daten: - -- [`AnalyticsSummary`](/docs/reference/schemas/analyticssummary) — globale - Kennzahlen (Anzahl Tools/Bewertungen, Kategorien, Durchschnitt). -- [`TopToolEntry`](/docs/reference/schemas/TopToolEntry) — ein Eintrag der - Top-Tools.- [`CategoryStats`](/docs/reference/schemas/categorystats) — Tool-Anzahl je - Kategorie. -- [`RatingDistribution`](/docs/reference/schemas/ratingdistribution) — - Punkteverteilung (Nützlichkeit & Bedienbarkeit). -- [`ScoreBucket`](/docs/reference/schemas/scorebucket) — ein Werte-Bucket. - -## Weitere - -- [`VersionInfo`](/docs/reference/schemas/versioninfo) — Version, Commit-SHA, - Build-Datum und Papierkorb-Aufbewahrung der laufenden Instanz. -- [`AuditLog`](/docs/reference/schemas/auditlog) — ein Protokolleintrag - (Aktion, Entität, Zeitstempel, Akteur, Änderungen). diff --git a/docs/releases/v0.8.2/handbook/getting-started.en.md b/docs/releases/v0.8.2/handbook/getting-started.en.md deleted file mode 100644 index 98344ef..0000000 --- a/docs/releases/v0.8.2/handbook/getting-started.en.md +++ /dev/null @@ -1,53 +0,0 @@ - -# Getting Started - -This page guides you through the most important workflows in toolr — from your -first visit to creating and rating a tool. - -## 1. Sign in - -Most actions (create a tool, rate, watchlist, compare) require -an account. Click **Sign in** in the bottom left corner. Depending on the -instance configuration you have two options: - -- **Local accounts:** username + password. Access is created by an admin - (see [Administration](/docs/handbook/administration)). -- **OIDC (SSO):** sign in with the configured identity provider (e.g. - Keycloak). - -Which mode is active is shown by the -[`GET /auth/mode`](/docs/reference/endpoints/auth#getAuthMode) endpoint. Details -can be found in the [Sign in & account](/docs/handbook/konto) section. - -## 2. Find tools - -Open the **Browse tools** section: - -- **Search** — full-text search across name & description (shortcut `/`). -- **Filter** — by category, tags, features and minimum rating - (`minRating`). -- **Sort** — by newest, top-rated, most rated, name - (ascending/descending) or last update. - -All options in detail: [Find & browse tools](/docs/handbook/tools-finden). - -## 3. Create a tool - -Go to **Add tool** and fill in the form. Details for each field can be found -in the [Create a tool](/docs/handbook/tool-anlegen) section and in the -[field reference](/docs/reference/schemas/toolinput). - -## 4. Rate - -On the detail page of a tool you can submit **usefulness** and **usability** -(1–5 each) and optionally leave a comment. Your -rating is immediately reflected in the statistics. -See [Rating](/docs/handbook/bewerten). - -## 5. Further reading - -- [Compare tools](/docs/handbook/vergleichen) -- [Watchlist](/docs/handbook/watchlist) -- [Analytics](/docs/handbook/analytics) -- [Plans & permissions](/docs/handbook/plaene) -- [Administration](/docs/handbook/administration) diff --git a/docs/releases/v0.8.2/handbook/index.json b/docs/releases/v0.8.2/handbook/index.json deleted file mode 100644 index 4dc0aa7..0000000 --- a/docs/releases/v0.8.2/handbook/index.json +++ /dev/null @@ -1,138 +0,0 @@ -[ - { - "slug": "index", - "file": "index.md", - "title": "Überblick", - "order": 1, - "fileEn": "index.en.md", - "titleEn": "Overview" - }, - { - "slug": "getting-started", - "file": "getting-started.md", - "title": "Erste Schritte", - "order": 2, - "fileEn": "getting-started.en.md", - "titleEn": "Getting Started" - }, - { - "slug": "konto", - "file": "konto.md", - "title": "Anmelden & Konto", - "order": 3, - "fileEn": "konto.en.md", - "titleEn": "Login & Account" - }, - { - "slug": "tools-finden", - "file": "tools-finden.md", - "title": "Tools finden & durchsuchen", - "order": 4, - "fileEn": "tools-finden.en.md", - "titleEn": "Find & browse tools" - }, - { - "slug": "tool-anlegen", - "file": "tool-anlegen.md", - "title": "Tool anlegen", - "order": 5, - "fileEn": "tool-anlegen.en.md", - "titleEn": "Create a tool" - }, - { - "slug": "tool-bearbeiten", - "file": "tool-bearbeiten.md", - "title": "Tool bearbeiten & löschen", - "order": 6, - "fileEn": "tool-bearbeiten.en.md", - "titleEn": "Edit & delete tools" - }, - { - "slug": "bewerten", - "file": "bewerten.md", - "title": "Bewerten", - "order": 7, - "fileEn": "bewerten.en.md", - "titleEn": "Rating" - }, - { - "slug": "watchlist", - "file": "watchlist.md", - "title": "Watchlist", - "order": 8, - "fileEn": "watchlist.en.md", - "titleEn": "Watchlist" - }, - { - "slug": "vergleichen", - "file": "vergleichen.md", - "title": "Vergleichen", - "order": 9, - "fileEn": "vergleichen.en.md", - "titleEn": "Compare" - }, - { - "slug": "analytics", - "file": "analytics.md", - "title": "Analytics", - "order": 10, - "fileEn": "analytics.en.md", - "titleEn": "Analytics" - }, - { - "slug": "plaene", - "file": "plaene.md", - "title": "Pläne & Berechtigungen", - "order": 11, - "fileEn": "plaene.en.md", - "titleEn": "Plans & Permissions" - }, - { - "slug": "kosten", - "file": "kosten.md", - "title": "Kosten erfassen", - "order": 12, - "fileEn": "kosten.en.md", - "titleEn": "Recording Costs" - }, - { - "slug": "administration", - "file": "administration.md", - "title": "Administration", - "order": 13, - "fileEn": "administration.en.md", - "titleEn": "Administration" - }, - { - "slug": "redundanz", - "file": "redundanz.md", - "title": "Redundanz-Dashboard", - "order": 14, - "fileEn": "redundanz.en.md", - "titleEn": "Redundancy dashboard" - }, - { - "slug": "papierkorb", - "file": "papierkorb.md", - "title": "Papierkorb", - "order": 15, - "fileEn": "papierkorb.en.md", - "titleEn": "Trash" - }, - { - "slug": "tastatur", - "file": "tastatur.md", - "title": "Tastenkürzel & Kommandopalette", - "order": 16, - "fileEn": "tastatur.en.md", - "titleEn": "Keyboard shortcuts & command palette" - }, - { - "slug": "datenmodell", - "file": "datenmodell.md", - "title": "Datenmodell", - "order": 17, - "fileEn": "datenmodell.en.md", - "titleEn": "Data model" - } -] \ No newline at end of file diff --git a/docs/releases/v0.8.2/handbook/index.md b/docs/releases/v0.8.2/handbook/index.md deleted file mode 100644 index f527a6e..0000000 --- a/docs/releases/v0.8.2/handbook/index.md +++ /dev/null @@ -1,52 +0,0 @@ - -# Willkommen bei toolr - -toolr ist eine Plattform zum **Entdecken, Bewerten und Vergleichen von -Entwicklungstools**. Nutzer:innen pflegen einen gemeinsamen Katalog von Tools, -vergeben Bewertungen (Nützlichkeit & Bedienbarkeit) und nutzen Statistiken, um -die richtige Wahl zu treffen. - -## Was kannst du mit toolr tun? - -| Funktion | Beschreibung | Sichtbarkeit | -| --- | --- | --- | -| **Tools durchsuchen** | Katalog filtern, sortieren und durchsuchen | Alle | -| **Tool anlegen** | Neues Tool mit Beschreibung, Kategorie, Features & Tags eintragen | Angemeldet | -| **Tool bearbeiten/löschen** | Eigene Tools pflegen (Ersteller:in oder Admin) | Angemeldet | -| **Bewerten** | Nützlichkeit & Bedienbarkeit (1–5) plus Kommentar vergeben | Angemeldet | -| **Watchlist** | Tools als Favoriten speichern | Premium | -| **Vergleichen** | Tools nebeneinander gegenüberstellen | Premium | -| **Kosten erfassen** | Lizenz- und Kostenmodelle je Tool eintragen | Premium | -| **Analytics** | Statistiken, Top-Tools, Verteilungen | Alle | -| **Papierkorb** | Soft-gelöschte Tools wiederherstellen oder endgültig löschen | Premium | -| **Admin** | Nutzerverwaltung, Audit-Log, Systeminformationen | Admin | -| **Redundanz** | Automatische Doppelungs-Erkennung | Admin | - -## Wie diese Doku aufgebaut ist - -- **User Guide** (diese Seiten): Schritt-für-Schritt-Anleitungen für alle - Funktionen — von den [Ersten Schritten](/docs/handbook/getting-started) bis - zur [Administration](/docs/handbook/administration). -- **API-Referenz**: automatisch aus der OpenAPI-Spezifikation generiert — alle - [Endpunkte](/docs/reference/endpoints/tools) und - [Datenfelder](/docs/reference/schemas/toolinput) der aktuellen Version. -- **Release-Notes**: Was ist in welcher [Version](/docs/releases/v0.8.1) neu. - -## Der Einstieg - -Der schnellste Weg: - -1. **Anmelden** — ohne Konto kannst du nur stöbern - (siehe [Erste Schritte](/docs/handbook/getting-started#1-anmelden)). -2. **Tools finden** — Suche, Filter und Sortierung im Bereich - [Tools durchsuchen](/docs/handbook/tools-finden). -3. **Tool anlegen** — über „Tool hinzufügen" - ([Anleitung](/docs/handbook/tool-anlegen)). -4. **Bewerten** — auf der Detailseite eines Tools - ([Anleitung](/docs/handbook/bewerten)). - -## Kontakt & Quellcode - -Der Quellcode liegt unter -[git.kubebase.de/admin/tool-evaluator](https://git.kubebase.de/admin/tool-evaluator) — -über das Repository-Icon oben rechts erreichst du ihn jederzeit. diff --git a/docs/releases/v0.8.2/handbook/konto.en.md b/docs/releases/v0.8.2/handbook/konto.en.md deleted file mode 100644 index 22360df..0000000 --- a/docs/releases/v0.8.2/handbook/konto.en.md +++ /dev/null @@ -1,52 +0,0 @@ - -# Login & Account - -## Logging in - -Click **Login** at the bottom left of the sidebar. Depending on the -configuration of the instance: - -- **Local accounts:** enter username and password. The accounts are created - by an admin (see [Administration](/docs/handbook/administration)). -- **OIDC (SSO):** you are redirected to the configured identity provider and - log in there. - -The active mode is available at the endpoint -[`GET /auth/mode`](/docs/reference/endpoints/auth#getAuthMode). - -> You can reach the login page directly at `/login`. After a successful -> login you are redirected back to the page you originally requested. - -## User profile - -You can see your profile (avatar, name, email, plan) at the bottom left in -the user menu. There you have the following actions available: - -- **Watchlist** — your saved tools (only with the corresponding plan). -- **Trash** — restorable, deleted tools (Premium/Enterprise). -- **Change password** — directly in toolr for local accounts; for OIDC - accounts, password management is offered in the identity provider. -- **Logout** — ends your session. - -## Changing your password (local account) - -1. Open the user menu at the bottom left. -2. Select **Change password**. -3. Enter the **current** and a **new** password (min. 6 characters) and - confirm it. -4. Save — the password takes effect immediately. - -API reference: [`POST /auth/me/password`](/docs/reference/endpoints/auth#changeMyPassword). - -## Display settings - -Using the buttons at the top right you can: - -- switch the **language** (German / English), -- toggle the **theme** (Light / Dark / System), -- adjust the **list view** and **density** in the Browse tools section - (see [Finding & browsing tools](/docs/handbook/tools-finden)). - -Your preferences (incl. watchlist) are saved at the endpoint -[`GET /auth/me/preferences`](/docs/reference/endpoints/auth#getMePreferences) -and updated via [`PUT /auth/me/preferences`](/docs/reference/endpoints/auth#updateMePreferences). diff --git a/docs/releases/v0.8.2/handbook/kosten.en.md b/docs/releases/v0.8.2/handbook/kosten.en.md deleted file mode 100644 index 1cf7a3a..0000000 --- a/docs/releases/v0.8.2/handbook/kosten.en.md +++ /dev/null @@ -1,35 +0,0 @@ - -# Recording Costs - -On the detail page of a tool you can enter cost and license models so that -the total costs per tool become transparent. - -> Costs is a **premium feature** (`costs`, Premium/Enterprise). Admins always -> have access. - -## Adding costs - -Click **Add costs** in the costs section of the detail page and fill out the -form: - -| Field | Notes | -| --- | --- | -| **License type** | Free / Subscription / One-Time / Usage-Based | -| **Billing period** | Only for "Subscription": Monthly / Quarterly / Annually | -| **Costs** | Amount as a number | -| **Currency** | EUR / USD / GBP / CHF | -| **Notes** | Optional free text | - -Saving creates the entry. Each cost entry is displayed as a card with -license badge, billing period, amount (`Amount Currency` or "Free") and -notes. - -## Editing & deleting costs - -Hovering over a cost card shows the **Edit** (pencil) and **Delete** (trash) -actions. - -## API - -The cost data is managed via the tool endpoints -(see [API reference](/docs/reference/endpoints/tools)). diff --git a/docs/releases/v0.8.2/handbook/kosten.md b/docs/releases/v0.8.2/handbook/kosten.md deleted file mode 100644 index 8904047..0000000 --- a/docs/releases/v0.8.2/handbook/kosten.md +++ /dev/null @@ -1,35 +0,0 @@ - -# Kosten erfassen - -Auf der Detailseite eines Tools kannst du Kosten- und Lizenzmodelle eintragen, -damit die Gesamtkosten je Tool transparent werden. - -> Kosten ist ein **Premium-Feature** (`costs`, Premium/Enterprise). Admins -> haben immer Zugriff. - -## Kosten hinzufügen - -Klicke auf **Kosten hinzufügen** im Kosten-Bereich der Detailseite und fülle -das Formular aus: - -| Feld | Hinweise | -| --- | --- | -| **Lizenztyp** | Free / Subscription / One-Time / Usage-Based | -| **Abrechnungszeitraum** | Nur für „Subscription": Monatlich / Quartalsweise / Jährlich | -| **Kosten** | Betrag als Zahl | -| **Währung** | EUR / USD / GBP / CHF | -| **Notizen** | Optionaler Freitext | - -Speichern legt den Eintrag an. Jeder Kosten-Eintrag wird als Karte mit -Lizenz-Badge, Abrechnungszeitraum, Betrag (`Betrag Währung` bzw. „Free") und -Notizen angezeigt. - -## Kosten bearbeiten & löschen - -Beim Überfahren einer Kosten-Karte erscheinen die Aktionen **Bearbeiten** -(Bleistift) und **Löschen** (Papierkorb). - -## API - -Die Kosten-Daten werden über die Tool-Endpunkte verwaltet -(siehe [API-Referenz](/docs/reference/endpoints/tools)). diff --git a/docs/releases/v0.8.2/handbook/papierkorb.en.md b/docs/releases/v0.8.2/handbook/papierkorb.en.md deleted file mode 100644 index 7111def..0000000 --- a/docs/releases/v0.8.2/handbook/papierkorb.en.md +++ /dev/null @@ -1,40 +0,0 @@ - -# Trash - -The **trash** (`/trash`) contains soft-deleted tools. With trash access -they can be restored; permanent deletion is reserved for admins. - -> The trash is a **premium feature** (`trash`, Premium/Enterprise). -> Admins always have access. - -## Access - -The trash can be reached via the user menu or the sidebar. -Without the `trash` permission, a hint about changing the plan appears. - -## Restoring - -- Select one or more tools (checkboxes). -- Click on **Restore (N)** — the tools appear again in all - public views. - -> Restoring is available to anyone with trash access. - -## Permanently delete (admin only) - -- **Delete (N)** **permanently** removes the selected tools — including - all ratings, costs and links. This cannot be undone. -- **Empty trash** permanently removes all soft-deleted tools. - -## Table - -The trash lists: name, category, **Deleted on** (`tt.MM.jjjj HH:mm`), -**Deleted by** as well as actions (Restore; Delete admin only). The search -filters by name. - -## API - -- [`GET /tools/trash`](/docs/reference/endpoints/tools#listTrashedTools) — list -- [`POST /tools/trash/restore`](/docs/reference/endpoints/tools#restoreTools) — restore -- [`DELETE /tools/trash`](/docs/reference/endpoints/tools#deleteTrashedTools) — permanently delete (admin) -- [`POST /tools/trash/empty`](/docs/reference/endpoints/tools#emptyTrash) — empty trash (admin) diff --git a/docs/releases/v0.8.2/handbook/papierkorb.md b/docs/releases/v0.8.2/handbook/papierkorb.md deleted file mode 100644 index 3179c74..0000000 --- a/docs/releases/v0.8.2/handbook/papierkorb.md +++ /dev/null @@ -1,41 +0,0 @@ - -# Papierkorb - -Der **Papierkorb** (`/trash`) enthält soft gelöschte Tools. Mit Papierkorb-Zugang -können sie wiederhergestellt werden; endgültiges Löschen ist Admins vorbehalten. - -> Der Papierkorb ist ein **Premium-Feature** (`trash`, Premium/Enterprise). -> Admins haben immer Zugriff. - -## Zugang - -Der Papierkorb ist über das Benutzermenü oder die Seitenleiste erreichbar. -Ohne `trash`-Berechtigung erscheint ein Hinweis auf den Tarifwechsel. - -## Wiederherstellen - -- Markiere ein oder mehrere Tools (Checkboxen). -- Klicke auf **Wiederherstellen (N)** — die Tools erscheinen wieder in allen - öffentlichen Ansichten. - -> Wiederherstellen steht jeder Person mit Papierkorb-Zugang zur Verfügung. - -## Endgültig löschen (nur Admin) - -- **Löschen (N)** entfernt die ausgewählten Tools **endgültig** — inklusive - aller Bewertungen, Kosten und Verknüpfungen. Das kann nicht rückgängig - gemacht werden. -- **Papierkorb leeren** entfernt alle soft gelöschten Tools endgültig. - -## Tabelle - -Der Papierkorb listet: Name, Kategorie, **Gelöscht am** (`tt.MM.jjjj HH:mm`), -**Gelöscht von** sowie Aktionen (Wiederherstellen; Löschen nur Admin). Die Suche -filtert nach Namen. - -## API - -- [`GET /tools/trash`](/docs/reference/endpoints/tools#listTrashedTools) — Liste -- [`POST /tools/trash/restore`](/docs/reference/endpoints/tools#restoreTools) — Wiederherstellen -- [`DELETE /tools/trash`](/docs/reference/endpoints/tools#deleteTrashedTools) — Endgültig löschen (Admin) -- [`POST /tools/trash/empty`](/docs/reference/endpoints/tools#emptyTrash) — Papierkorb leeren (Admin) diff --git a/docs/releases/v0.8.2/handbook/redundanz.en.md b/docs/releases/v0.8.2/handbook/redundanz.en.md deleted file mode 100644 index 27825b3..0000000 --- a/docs/releases/v0.8.2/handbook/redundanz.en.md +++ /dev/null @@ -1,38 +0,0 @@ - -# Redundancy dashboard - -The **Redundancy dashboard** (`/admin/redundancy`) is an admin tool for -automatic detection of duplicate or strongly overlapping tools — per -category — including cost and rating comparison. - -> Access is reserved exclusively for admins (the API is -> admin-protected). - -## Layout - -- **Per category** a group is shown: name of the category, - number of tools and comparisons as well as the **total monthly costs** - if applicable (e.g. `€X.XX/mo total`). -- Each tool is displayed as a card: name, monthly costs, number of - ratings, combined rating, license badges and number of features. - -## Comparisons & recommendations - -For each tool pair the following appears: - -- Tool A vs. Tool B, each with rating (`X.X ★`) and monthly costs. -- **Overlap** in percent (progress bar in the middle). -- A **recommendation** with confidence color: - - **high** (green), **medium** (yellow), **low** (gray) -- The recommended, better tool is marked with a "thumbs up" and justified. - -## Manual rating - -You can rate a pair manually: click on Tool A or Tool B to -record which one is better. The selection is saved and the -display is updated. - -## API - -- [`GET /api/admin/redundancy`](#) — load data (admin-protected) -- [`POST /api/admin/redundancy/evaluate`](#) — save manual rating diff --git a/docs/releases/v0.8.2/handbook/redundanz.md b/docs/releases/v0.8.2/handbook/redundanz.md deleted file mode 100644 index 7521ffe..0000000 --- a/docs/releases/v0.8.2/handbook/redundanz.md +++ /dev/null @@ -1,38 +0,0 @@ - -# Redundanz-Dashboard - -Das **Redundanz-Dashboard** (`/admin/redundancy`) ist ein Admin-Werkzeug zur -automatischen Erkennung doppelter oder stark überlappender Tools — jeweils -pro Kategorie — inklusive Kosten- und Bewertungsvergleich. - -> Der Zugriff ist ausschließlich Admins vorbehalten (die API ist -> admin-geschützt). - -## Aufbau - -- **Pro Kategorie** wird eine Gruppe angezeigt: Name der Kategorie, - Anzahl Tools und Vergleiche sowie ggf. die **gesamten monatlichen Kosten** - (z. B. `€X.XX/mo gesamt`). -- Jedes Tool wird als Karte dargestellt: Name, monatliche Kosten, Anzahl der - Bewertungen, kombinierte Bewertung, Lizenz-Badges und Feature-Anzahl. - -## Vergleiche & Empfehlungen - -Für jedes Tool-Paar erscheint: - -- Tool A vs. Tool B, jeweils mit Bewertung (`X.X ★`) und monatlichen Kosten. -- **Überlappung** in Prozent (Fortschrittsbalken in der Mitte). -- Eine **Empfehlung** mit Konfidenz-Farbe: - - **hoch** (grün), **mittel** (gelb), **niedrig** (grau) -- Das empfohlene, bessere Tool wird mit „Daumen hoch" markiert und begründet. - -## Manuelle Bewertung - -Du kannst ein Paar manuell bewerten: Klicke auf Tool A oder Tool B, um -festzuhalten, welches besser ist. Die Auswahl wird gespeichert und die -Darstellung aktualisiert. - -## API - -- [`GET /api/admin/redundancy`](#) — Daten laden (admin-geschützt) -- [`POST /api/admin/redundancy/evaluate`](#) — manuelle Bewertung speichern diff --git a/docs/releases/v0.8.2/handbook/tastatur.en.md b/docs/releases/v0.8.2/handbook/tastatur.en.md deleted file mode 100644 index 2eddf47..0000000 --- a/docs/releases/v0.8.2/handbook/tastatur.en.md +++ /dev/null @@ -1,36 +0,0 @@ - -# Keyboard shortcuts & command palette - -## Command palette - -The command palette is the central quick navigation: - -- Open with **`⌘K`** (macOS) or **`Ctrl+K`** (Windows/Linux). -- Alternatively via the search bar at the top right ("Search tools… ⌘K") or the - search icon on mobile devices. - -### Empty state - -Without input, the palette shows: - -- **Recently viewed** — the last 5 tools you visited. -- **Navigation** — browse tools, add tool, analytics as well as - (depending on permissions) watchlist, trash and admin. - -### Search - -Type to search for tools live (max. 10 results, incl. rating -`X.X★`). - -## Overview of keyboard shortcuts - -| Shortcut | Action | -| --- | --- | -| `⌘K` / `Ctrl+K` | Open command palette | -| `/` | Focus search in the "Browse tools" area | - -## Additional notes - -- **Recently viewed** is stored locally in the browser (max. 5 entries). -- The sidebar (left navigation) can be collapsed on desktop; the - breadcrumb at the top shows your current location. diff --git a/docs/releases/v0.8.2/handbook/tool-anlegen.en.md b/docs/releases/v0.8.2/handbook/tool-anlegen.en.md deleted file mode 100644 index 45618cf..0000000 --- a/docs/releases/v0.8.2/handbook/tool-anlegen.en.md +++ /dev/null @@ -1,46 +0,0 @@ - -# Create a tool - -To add a new tool to the catalog, click **Add tool** -(`/tools/new`). Creating a tool requires an account — without being signed in -a notice with a login button appears. - -## Form fields - -| Field | Required | Notes | -| --- | --- | --- | -| **Name** | Yes | At least 2 characters | -| **Category** | Yes | Dropdown; new categories can be created directly | -| **Website URL** | No | Valid URL (e.g. `https://...`) | -| **Icon / Logo URL** | No | Valid URL; preview is shown live | -| **Description** | Yes | At least 10 characters; describe what the tool does | -| **Features** | No | Dynamic list with autocomplete (max. 6) | -| **Tags** | No | Dynamic list with autocomplete | - -Next to each field, the **? icon** takes you directly to the corresponding -field description in the [data model reference](/docs/reference/schemas/toolinput). - -### Category - -- Type to search for existing categories. -- Select **+ Create "..."** to create a new category. - -### Features & tags - -- **Add feature** / **Add tag** appends a new row. -- The input fields suggest existing features/tags - (autocomplete, max. 6 suggestions). -- Use the **×** button to remove individual rows. -- Features and tags help with filtering and finding tools again. - -## Save - -Click **Add tool**. After successful creation you will be redirected to the -detail page of the new tool. - -## API - -- [`POST /tools`](/docs/reference/endpoints/tools#createTool) — create a tool -- [`GET /categories`](/docs/reference/endpoints/tools#listCategories) — categories -- [`GET /features/all`](/docs/reference/endpoints/tools#listAllFeatures) — features -- [`GET /tags/all`](/docs/reference/endpoints/tools#listAllTags) — tags diff --git a/docs/releases/v0.8.2/handbook/tool-anlegen.md b/docs/releases/v0.8.2/handbook/tool-anlegen.md deleted file mode 100644 index db93745..0000000 --- a/docs/releases/v0.8.2/handbook/tool-anlegen.md +++ /dev/null @@ -1,46 +0,0 @@ - -# Tool anlegen - -Um ein neues Tool zum Katalog hinzuzufügen, klicke auf **Tool hinzufügen** -(`/tools/new`). Das Anlegen erfordert ein Konto — ohne Anmeldung erscheint ein -Hinweis mit Login-Button. - -## Formularfelder - -| Feld | Pflicht | Hinweise | -| --- | --- | --- | -| **Name** | Ja | Mind. 2 Zeichen | -| **Kategorie** | Ja | Auswahlliste; neue Kategorien lassen sich direkt anlegen | -| **Website URL** | Nein | Gültige URL (z. B. `https://...`) | -| **Icon / Logo URL** | Nein | Gültige URL; Vorschau wird live angezeigt | -| **Beschreibung** | Ja | Mind. 10 Zeichen; beschreibe, was das Tool tut | -| **Features** | Nein | Dynamische Liste mit Autovervollständigung (max. 6) | -| **Tags** | Nein | Dynamische Liste mit Autovervollständigung | - -Neben jedem Feld führt das **?‑Icon** direkt zur zugehörigen Feldbeschreibung -in der [Datenmodell-Referenz](/docs/reference/schemas/toolinput). - -### Kategorie - -- Tippe, um nach bestehenden Kategorien zu suchen. -- Wähle **+ Erstelle „..."**, um eine neue Kategorie anzulegen. - -### Features & Tags - -- **Feature hinzufügen** / **Tag hinzufügen** hängt eine neue Zeile an. -- Die Eingabefelder schlagen bestehende Features/Tags vor - (Autovervollständigung, max. 6 Vorschläge). -- Mit dem **×**‑Button entfernst du einzelne Zeilen. -- Features und Tags helfen beim Filtern und Wiederfinden. - -## Speichern - -Klicke auf **Tool hinzufügen**. Nach erfolgreicher Anlage wirst du auf die -Detailseite des neuen Tools weitergeleitet. - -## API - -- [`POST /tools`](/docs/reference/endpoints/tools#createTool) — Tool anlegen -- [`GET /categories`](/docs/reference/endpoints/tools#listCategories) — Kategorien -- [`GET /features/all`](/docs/reference/endpoints/tools#listAllFeatures) — Features -- [`GET /tags/all`](/docs/reference/endpoints/tools#listAllTags) — Tags diff --git a/docs/releases/v0.8.2/handbook/tool-bearbeiten.en.md b/docs/releases/v0.8.2/handbook/tool-bearbeiten.en.md deleted file mode 100644 index 9921517..0000000 --- a/docs/releases/v0.8.2/handbook/tool-bearbeiten.en.md +++ /dev/null @@ -1,32 +0,0 @@ - -# Edit & delete tools - -## Editing - -On the detail page of a tool you will find the **Edit** button -(only for the person who created the tool, as well as for admins). - -The edit page (`/tools/:id/edit`) contains the same fields as when -creating (name, category, website/icon URL, description, features, tags) — -already filled with the current values. - -- **Save** applies the changes. -- **Cancel** takes you back to the detail page. - -API reference: [`PATCH /tools/{id}`](/docs/reference/endpoints/tools#updateTool). - -## Deleting - -Via **Delete** on the detail page the tool is removed. The behavior -depends on your plan: - -- **With trash access** (Premium/Enterprise or Admin): the tool is - **soft deleted** — it disappears from all public views, but can - be restored or permanently deleted in the [trash](/docs/handbook/papierkorb). -- **Without trash access:** the tool is **permanently** deleted and cannot - be restored. - -Deletion is only possible for the person who created the tool, as well as -for admins. - -API reference: [`DELETE /tools/{id}`](/docs/reference/endpoints/tools#deleteTool). diff --git a/docs/releases/v0.8.2/handbook/tool-bearbeiten.md b/docs/releases/v0.8.2/handbook/tool-bearbeiten.md deleted file mode 100644 index 7f2fd3f..0000000 --- a/docs/releases/v0.8.2/handbook/tool-bearbeiten.md +++ /dev/null @@ -1,33 +0,0 @@ - -# Tool bearbeiten & löschen - -## Bearbeiten - -Auf der Detailseite eines Tools findest du die Schaltfläche **Bearbeiten** -(nur für die Person, die das Tool angelegt hat, sowie für Admins). - -Die Bearbeitungsseite (`/tools/:id/edit`) enthält dieselben Felder wie beim -Anlegen (Name, Kategorie, Website/Icon-URL, Beschreibung, Features, Tags) — -bereits mit den aktuellen Werten befüllt. - -- **Speichern** übernimmt die Änderungen. -- **Abbrechen** führt zurück zur Detailseite. - -API-Referenz: [`PATCH /tools/{id}`](/docs/reference/endpoints/tools#updateTool). - -## Löschen - -Über **Löschen** auf der Detailseite wird das Tool entfernt. Das Verhalten -hängt von deinem Tarif ab: - -- **Mit Papierkorb-Zugang** (Premium/Enterprise oder Admin): Das Tool wird - **soft gelöscht** — es verschwindet aus allen öffentlichen Ansichten, kann - aber im [Papierkorb](/docs/handbook/papierkorb) wiederhergestellt oder - endgültig gelöscht werden. -- **Ohne Papierkorb-Zugang:** Das Tool wird **endgültig** gelöscht und kann - nicht wiederhergestellt werden. - -Die Löschung ist nur für die Person, die das Tool angelegt hat, sowie für -Admins möglich. - -API-Referenz: [`DELETE /tools/{id}`](/docs/reference/endpoints/tools#deleteTool). diff --git a/docs/releases/v0.8.2/handbook/tools-finden.en.md b/docs/releases/v0.8.2/handbook/tools-finden.en.md deleted file mode 100644 index 6483d44..0000000 --- a/docs/releases/v0.8.2/handbook/tools-finden.en.md +++ /dev/null @@ -1,66 +0,0 @@ - -# Find & browse tools - -The **Browse tools** section (`/tools`) is your entry point to the catalog. -Here you combine search, filters and sorting to find exactly the tools -you are interested in. - -## Search - -- The **search bar** searches name and description (full text). -- Shortcut: Press **`/`** to focus the search. -- The input is debounced so that filtering happens immediately with each - keystroke. - -## Filter - -Via the **Filter** button (with a badge for the number of active filters) -you open the filter popover with: - -- **Tags** — selection via checkboxes (scrollable list). -- **Features** — selection via checkboxes. -- **Minimum rating** — slider from 0 to 5 (in steps of 0.5); shows - e.g. "3.0+". - -Active filters appear as **removable chips** above the result list. -Use **Reset filters** or **Remove all** to clear them again. - -## Sort - -The **Sort** dropdown offers the following options: - -| Sort | Description | -| --- | --- | -| Newest | New tools first | -| Top rated | By combined rating | -| Most rated | By number of ratings | -| Name (A–Z) | Alphabetically ascending | -| Name (Z–A) | Alphabetically descending | -| Last updated | By last update | - -## View & density - -- **Switch view:** grid / table / rows. -- **Density:** comfortable / compact (slider). - -Your selection is saved — locally in the browser and, for logged-in users, -additionally on the server in the preferences. View, density, search, filters -and sorting are reflected in the URL so you can share results. - -## Table view - -In the table view the columns **Tool**, **Rating** and **Number of -ratings** are sortable. Hovering over a row shows a preview -with rating details, tags and mini bars. - -## Selecting for comparison & watchlist - -- On every card/row you find a **compare icon** that lets you add tools to the - [compare bar](/docs/handbook/vergleichen). -- The **bookmark icon** saves tools to your - [watchlist](/docs/handbook/watchlist) (only with the corresponding plan). - -## API - -All search, filter and sort parameters correspond to the query parameters of -[`GET /tools`](/docs/reference/endpoints/tools#listTools). diff --git a/docs/releases/v0.8.2/handbook/vergleichen.en.md b/docs/releases/v0.8.2/handbook/vergleichen.en.md deleted file mode 100644 index b2e0635..0000000 --- a/docs/releases/v0.8.2/handbook/vergleichen.en.md +++ /dev/null @@ -1,42 +0,0 @@ - -# Compare - -With the compare function you can put several tools **side by side** — -ideal for making a well-informed decision. - -> Comparing is a **premium feature** (Premium/Enterprise) and is always -> available to admins. - -## Selecting tools - -1. In the **Browse tools** section, click the **compare icon** (scales) on - each card/row. -2. The **compare bar** appears at the bottom with the selected tools as - chips. You can remove individual tools (×) or clear the selection. -3. Click **Compare (N)** to go to the compare view. - -> Without a premium plan the button is locked (lock icon). The dialog takes -> you to the plan switch -> (see [Plans & permissions](/docs/handbook/plaene)). - -## The compare view - -The view shows a table with one column per tool. Rows: - -| Row | Content | -| --- | --- | -| **Rating** | Stars + value (e.g. `4.2/5`) | -| **Usefulness** | Value (X.X/5) | -| **Usability** | Value (X.X/5) | -| **Number of ratings** | Count | -| **Description** | Text | -| **Features** | Badges | -| **Tags** | Badges | -| **Last updated** | Date | - -The **best value** per row is highlighted (with trophy icon). - -## API - -The compare view reads the data via -[`GET /compare`](/docs/reference/endpoints/tools#listCompareTools). diff --git a/docs/releases/v0.8.2/handbook/vergleichen.md b/docs/releases/v0.8.2/handbook/vergleichen.md deleted file mode 100644 index ddcf0de..0000000 --- a/docs/releases/v0.8.2/handbook/vergleichen.md +++ /dev/null @@ -1,42 +0,0 @@ - -# Vergleichen - -Mit der Vergleichsfunktion stellst du mehrere Tools **nebeneinander** gegenüber — -ideal, um eine fundierte Entscheidung zu treffen. - -> Vergleichen ist ein **Premium-Feature** (Premium/Enterprise) und steht Admins -> immer zur Verfügung. - -## Tools auswählen - -1. Im Bereich **Tools durchsuchen** klickst du auf jeder Karte/Zeile auf das - **Vergleichs-Icon** (Waage). -2. Unten erscheint die **Vergleichsleiste** mit den ausgewählten Tools als - Chips. Du kannst einzelne Tools entfernen (×) oder die Auswahl leeren. -3. Klicke auf **Vergleichen (N)**, um zur Vergleichsansicht zu gelangen. - -> Ohne Premium-Tarif ist der Button gesperrt (Schloss-Icon). Über den -> Dialog gelangst du zum Tarifwechsel -> (siehe [Pläne & Berechtigungen](/docs/handbook/plaene)). - -## Die Vergleichsansicht - -Die Ansicht zeigt eine Tabelle mit einer Spalte pro Tool. Zeilen: - -| Zeile | Inhalt | -| --- | --- | -| **Bewertung** | Sterne + Wert (z. B. `4.2/5`) | -| **Nützlichkeit** | Wert (X.X/5) | -| **Bedienbarkeit** | Wert (X.X/5) | -| **Anzahl Bewertungen** | Anzahl | -| **Beschreibung** | Text | -| **Features** | Badges | -| **Tags** | Badges | -| **Zuletzt aktualisiert** | Datum | - -Der **beste Wert** pro Zeile wird hervorgehoben (mit Trophäen-Icon). - -## API - -Die Vergleichsansicht liest die Daten über -[`GET /compare`](/docs/reference/endpoints/tools#listCompareTools). diff --git a/docs/releases/v0.8.2/handbook/watchlist.en.md b/docs/releases/v0.8.2/handbook/watchlist.en.md deleted file mode 100644 index 55da963..0000000 --- a/docs/releases/v0.8.2/handbook/watchlist.en.md +++ /dev/null @@ -1,33 +0,0 @@ - -# Watchlist - -The **watchlist** is a personal favorites list. You can open and compare the -tools in it at any time with a click. - -> The watchlist is a **premium feature** (Premium/Enterprise) and is always -> available to admins. - -## Prerequisite - -You need a plan with the `watchlist` permission. If it is missing, a note -about switching plans appears at the bookmark -(see [Plans & permissions](/docs/handbook/plaene)). - -## Saving a tool - -- On every card/row in the **Browse tools** section you will find the - **bookmark icon**. -- A click saves the tool to your watchlist — the icon becomes filled. -- Clicking it again removes it. - -## Viewing the watchlist - -Open the watchlist via the user menu or the sidebar. It shows all saved tools -as cards. The filled bookmark on a card removes the tool from the list. - -## Where is the watchlist stored? - -The watchlist is a list of tool IDs in your **user preferences**. This way it -is linked to your account across devices. - -API reference: [`GET /auth/me/watchlist`](/docs/reference/endpoints/auth#getMeWatchlist). diff --git a/docs/releases/v0.8.2/handbook/watchlist.md b/docs/releases/v0.8.2/handbook/watchlist.md deleted file mode 100644 index 783da0c..0000000 --- a/docs/releases/v0.8.2/handbook/watchlist.md +++ /dev/null @@ -1,34 +0,0 @@ - -# Watchlist - -Die **Watchlist** ist eine persönliche Favoritenliste. Tools darin kannst du -jederzeit per Klick wieder aufrufen und vergleichen. - -> Die Watchlist ist ein **Premium-Feature** (Premium/Enterprise) und steht -> Admins immer zur Verfügung. - -## Voraussetzung - -Du benötigst einen Tarif mit `watchlist`-Berechtigung. Fehlt diese, erscheint -beim Lesezeichen ein Hinweis auf den Tarifwechsel -(siehe [Pläne & Berechtigungen](/docs/handbook/plaene)). - -## Tool speichern - -- Auf jeder Karte/Zeile im Bereich **Tools durchsuchen** findest du das - **Lesezeichen-Icon**. -- Ein Klick speichert das Tool in deiner Watchlist — das Icon wird gefüllt. -- Ein erneuter Klick entfernt es wieder. - -## Watchlist ansehen - -Öffne die Watchlist über das Benutzermenü oder die Seitenleiste. Sie zeigt alle -gespeicherten Tools als Karten. Das gefüllte Lesezeichen auf einer Karte -entfernt das Tool aus der Liste. - -## Wo wird die Watchlist gespeichert? - -Die Watchlist ist eine Liste von Tool-IDs in deinen **Benutzerpräferenzen**. -Damit ist sie geräteübergreifend mit deinem Konto verbunden. - -API-Referenz: [`GET /auth/me/watchlist`](/docs/reference/endpoints/auth#getMeWatchlist). diff --git a/docs/releases/v0.8.2/reference.json b/docs/releases/v0.8.2/reference.json deleted file mode 100644 index a3adfd9..0000000 --- a/docs/releases/v0.8.2/reference.json +++ /dev/null @@ -1,2782 +0,0 @@ -{ - "tags": [ - { - "name": "health", - "description": "Health operations", - "endpoints": [ - { - "operationId": "healthCheck", - "method": "GET", - "path": "/healthz", - "summary": "Health check", - "description": "Returns server health status", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Healthy", - "schema": { - "kind": "ref", - "value": "HealthStatus" - } - } - ] - }, - { - "operationId": "getVersion", - "method": "GET", - "path": "/version", - "summary": "Build version information", - "description": "Returns the running build version, commit SHA and build date", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Version information", - "schema": { - "kind": "ref", - "value": "VersionInfo" - } - } - ] - } - ] - }, - { - "name": "tools", - "description": "Tool management", - "endpoints": [ - { - "operationId": "listTools", - "method": "GET", - "path": "/tools", - "summary": "List all tools", - "description": "", - "parameters": [ - { - "name": "category", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "search", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "sort", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "newest, top_rated, most_reviewed, name_asc, name_desc, recently_updated" - }, - { - "name": "tags", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated tags; tool must include all of them", - "constraints": "" - }, - { - "name": "features", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated features; tool must include all of them", - "constraints": "" - }, - { - "name": "minRating", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "number" - }, - "description": "Minimum average combined rating (0-5)", - "constraints": "0–5" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "List of tools", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - } - ] - }, - { - "operationId": "createTool", - "method": "POST", - "path": "/tools", - "summary": "Create a new tool", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ToolInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created tool", - "schema": { - "kind": "ref", - "value": "Tool" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listCompareTools", - "method": "GET", - "path": "/compare", - "summary": "Compare tools side by side (premium)", - "description": "", - "parameters": [ - { - "name": "ids", - "in": "query", - "required": true, - "type": { - "kind": "type", - "value": "string" - }, - "description": "Comma-separated tool ids", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Tools in requested order", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - }, - { - "status": "401", - "description": "Authentication required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Premium feature required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getToolRatingHistory", - "method": "GET", - "path": "/tools/{id}/rating-history", - "summary": "Get a tool's rating history over time", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Rating history", - "schema": { - "kind": "array", - "value": "RatingHistoryItem" - } - }, - { - "status": "400", - "description": "Invalid id", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getTool", - "method": "GET", - "path": "/tools/{id}", - "summary": "Get a tool by ID", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Tool details", - "schema": { - "kind": "ref", - "value": "ToolWithStats" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateTool", - "method": "PATCH", - "path": "/tools/{id}", - "summary": "Update a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ToolUpdate" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated tool", - "schema": { - "kind": "ref", - "value": "Tool" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteTool", - "method": "DELETE", - "path": "/tools/{id}", - "summary": "Delete a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "404", - "description": "Not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listTrashedTools", - "method": "GET", - "path": "/tools/trash", - "summary": "List trashed (soft-deleted) tools", - "description": "", - "parameters": [ - { - "name": "search", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "List of trashed tools", - "schema": { - "kind": "array", - "value": "Tool" - } - }, - { - "status": "403", - "description": "Feature \"trash\" requires a higher tier", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "trashTools", - "method": "POST", - "path": "/tools/trash", - "summary": "Move tools to trash (admin)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Tools trashed", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteTrashedTools", - "method": "DELETE", - "path": "/tools/trash", - "summary": "Permanently delete trashed tools (admin)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "restoreTools", - "method": "POST", - "path": "/tools/trash/restore", - "summary": "Restore trashed tools", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "TrashToolsInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Tools restored", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Feature \"trash\" requires a higher tier", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "emptyTrash", - "method": "POST", - "path": "/tools/trash/empty", - "summary": "Permanently delete all trashed tools (admin)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Trash emptied", - "schema": { - "kind": "type", - "value": "object" - } - }, - { - "status": "403", - "description": "Admin required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "listCategories", - "method": "GET", - "path": "/categories", - "summary": "List all distinct tool categories", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Categories list", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - }, - { - "operationId": "listAllFeatures", - "method": "GET", - "path": "/features/all", - "summary": "List all distinct feature strings across all tools", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "All known features", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - }, - { - "operationId": "listAllTags", - "method": "GET", - "path": "/tags/all", - "summary": "List all distinct tag strings across all tools", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "All known tags", - "schema": { - "kind": "array", - "value": "string" - } - } - ] - } - ] - }, - { - "name": "ratings", - "description": "Tool ratings", - "endpoints": [ - { - "operationId": "listToolRatings", - "method": "GET", - "path": "/tools/{id}/ratings", - "summary": "List ratings for a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Ratings list", - "schema": { - "kind": "array", - "value": "Rating" - } - } - ] - }, - { - "operationId": "createRating", - "method": "POST", - "path": "/tools/{id}/ratings", - "summary": "Submit a rating for a tool", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "RatingInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created rating", - "schema": { - "kind": "ref", - "value": "Rating" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "404", - "description": "Tool not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "analytics", - "description": "Analytics and aggregated statistics", - "endpoints": [ - { - "operationId": "getAnalyticsSummary", - "method": "GET", - "path": "/analytics/summary", - "summary": "Overall platform statistics", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Platform-level summary stats", - "schema": { - "kind": "ref", - "value": "AnalyticsSummary" - } - } - ] - }, - { - "operationId": "getTopTools", - "method": "GET", - "path": "/analytics/top-tools", - "summary": "Top-rated tools", - "description": "", - "parameters": [ - { - "name": "limit", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - }, - { - "name": "metric", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "usefulness, usability, combined" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Top tools list", - "schema": { - "kind": "array", - "value": "TopToolEntry" - } - } - ] - }, - { - "operationId": "getAnalyticsByCategory", - "method": "GET", - "path": "/analytics/by-category", - "summary": "Rating statistics grouped by category", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Per-category statistics", - "schema": { - "kind": "array", - "value": "CategoryStats" - } - } - ] - }, - { - "operationId": "getRatingDistribution", - "method": "GET", - "path": "/analytics/rating-distribution", - "summary": "Distribution of rating scores across the platform", - "description": "", - "parameters": [ - { - "name": "toolId", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Rating score distribution", - "schema": { - "kind": "ref", - "value": "RatingDistribution" - } - } - ] - } - ] - }, - { - "name": "auth", - "description": "Authentication", - "endpoints": [ - { - "operationId": "getAuthMode", - "method": "GET", - "path": "/auth/mode", - "summary": "Get authentication mode (oidc or local)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Auth mode", - "schema": { - "kind": "ref", - "value": "AuthMode" - } - } - ] - }, - { - "operationId": "getCsrfToken", - "method": "GET", - "path": "/auth/csrf", - "summary": "Get a CSRF token for state-changing requests", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "CSRF token", - "schema": { - "kind": "ref", - "value": "CsrfToken" - } - } - ] - }, - { - "operationId": "localLogin", - "method": "POST", - "path": "/auth/login", - "summary": "Local username/password login", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "LocalLoginInput" - } - }, - "responses": [ - { - "status": "200", - "description": "Logged in successfully", - "schema": { - "kind": "ref", - "value": "AuthUser" - } - }, - { - "status": "401", - "description": "Invalid credentials", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getMe", - "method": "GET", - "path": "/auth/me", - "summary": "Get current authenticated user", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Current user info", - "schema": { - "kind": "ref", - "value": "AuthUser" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "changeMyPassword", - "method": "POST", - "path": "/auth/me/password", - "summary": "Change own password (local users only)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "ChangePasswordInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Password changed", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "400", - "description": "Invalid input or wrong current password", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "422", - "description": "OIDC user - password is managed by the identity provider", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "429", - "description": "Too many attempts", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getPasswordRedirect", - "method": "GET", - "path": "/auth/password-redirect", - "summary": "Get redirect URL for managing credentials in the identity provider", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Redirect URL (null in local mode)", - "schema": { - "kind": "ref", - "value": "PasswordRedirect" - } - } - ] - }, - { - "operationId": "getMePreferences", - "method": "GET", - "path": "/auth/me/preferences", - "summary": "Get current user's browse preferences", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "User preferences", - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateMePreferences", - "method": "PUT", - "path": "/auth/me/preferences", - "summary": "Update current user's browse preferences", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated preferences", - "schema": { - "kind": "ref", - "value": "UserPreferences" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "getMeWatchlist", - "method": "GET", - "path": "/auth/me/watchlist", - "summary": "Get current user's watchlist tools (premium)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Watchlist tools in saved order", - "schema": { - "kind": "array", - "value": "ToolWithStats" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Premium feature required", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "users", - "description": "User management (admin only)", - "endpoints": [ - { - "operationId": "listUsers", - "method": "GET", - "path": "/users", - "summary": "List all local users (admin only)", - "description": "", - "parameters": [], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "User list", - "schema": { - "kind": "array", - "value": "User" - } - }, - { - "status": "401", - "description": "Not authenticated", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "403", - "description": "Forbidden", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "createUser", - "method": "POST", - "path": "/users", - "summary": "Create a new local user (admin only)", - "description": "", - "parameters": [], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserCreateInput" - } - }, - "responses": [ - { - "status": "201", - "description": "Created user", - "schema": { - "kind": "ref", - "value": "User" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "409", - "description": "Username already exists", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "updateUser", - "method": "PATCH", - "path": "/users/{id}", - "summary": "Update user role (admin only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "UserRoleUpdate" - } - }, - "responses": [ - { - "status": "200", - "description": "Updated user", - "schema": { - "kind": "ref", - "value": "User" - } - }, - { - "status": "404", - "description": "User not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - }, - { - "operationId": "deleteUser", - "method": "DELETE", - "path": "/users/{id}", - "summary": "Delete a user (admin only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "204", - "description": "Deleted", - "schema": { - "kind": "type", - "value": "any" - } - } - ] - }, - { - "operationId": "setUserPassword", - "method": "PATCH", - "path": "/users/{id}/password", - "summary": "Set/reset a user's password (admin only, local users only)", - "description": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": { - "required": true, - "schema": { - "kind": "ref", - "value": "SetPasswordInput" - } - }, - "responses": [ - { - "status": "204", - "description": "Password updated", - "schema": { - "kind": "type", - "value": "any" - } - }, - { - "status": "400", - "description": "Validation error", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "404", - "description": "User not found", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "422", - "description": "OIDC user - password is managed by the identity provider", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - }, - { - "status": "429", - "description": "Too many attempts", - "schema": { - "kind": "ref", - "value": "ErrorResponse" - } - } - ] - } - ] - }, - { - "name": "audit", - "description": "Audit log", - "endpoints": [ - { - "operationId": "listAuditLogs", - "method": "GET", - "path": "/audit-logs", - "summary": "List audit log entries (admin only)", - "description": "", - "parameters": [ - { - "name": "entityType", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "string" - }, - "description": "", - "constraints": "" - }, - { - "name": "entityId", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - }, - { - "name": "limit", - "in": "query", - "required": false, - "type": { - "kind": "type", - "value": "integer" - }, - "description": "", - "constraints": "" - } - ], - "requestBody": null, - "responses": [ - { - "status": "200", - "description": "Audit log entries", - "schema": { - "kind": "array", - "value": "AuditLog" - } - } - ] - } - ] - } - ], - "schemas": [ - { - "name": "HealthStatus", - "description": "", - "fields": [ - { - "name": "status", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "VersionInfo", - "description": "", - "fields": [ - { - "name": "version", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "commitSha", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "buildDate", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "trashRetentionDays", - "type": { - "kind": "type", - "value": "integer" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuthMode", - "description": "", - "fields": [ - { - "name": "mode", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "oidc, local" - } - ] - }, - { - "name": "CsrfToken", - "description": "", - "fields": [ - { - "name": "token", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "LocalLoginInput", - "description": "", - "fields": [ - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "User", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - }, - { - "name": "authProvider", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "local, oidc" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "UserCreateInput", - "description": "", - "fields": [ - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 2 chars" - }, - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - } - ] - }, - { - "name": "UserRoleUpdate", - "description": "", - "fields": [ - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - } - ] - }, - { - "name": "ChangePasswordInput", - "description": "", - "fields": [ - { - "name": "currentPassword", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "newPassword", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - } - ] - }, - { - "name": "SetPasswordInput", - "description": "", - "fields": [ - { - "name": "password", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 6 chars" - } - ] - }, - { - "name": "PasswordRedirect", - "description": "", - "fields": [ - { - "name": "url", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuditLog", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "entityType", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "entityId", - "type": { - "kind": "type", - "value": "integer | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "action", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "userId", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "username", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "changes", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "Tool", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "updatedAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "deletedAt", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "date-time" - }, - { - "name": "deletedBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "RatingHistoryItem", - "description": "", - "fields": [ - { - "name": "date", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "combined", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolWithStats", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdBy", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "updatedAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - }, - { - "name": "ratingCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgCombined", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolInput", - "description": "", - "fields": [ - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ToolUpdate", - "description": "", - "fields": [ - { - "name": "name", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "min 1 chars" - }, - { - "name": "description", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "websiteUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "iconUrl", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "features", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "tags", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "TrashToolsInput", - "description": "", - "fields": [ - { - "name": "ids", - "type": { - "kind": "array", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "min 1 items, max 500 items" - } - ] - }, - { - "name": "Rating", - "description": "", - "fields": [ - { - "name": "id", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "toolId", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "comment", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "reviewerName", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "createdAt", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "date-time" - } - ] - }, - { - "name": "RatingInput", - "description": "", - "fields": [ - { - "name": "usefulness", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "usability", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "1–5" - }, - { - "name": "comment", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "reviewerName", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AnalyticsSummary", - "description": "", - "fields": [ - { - "name": "totalTools", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "totalRatings", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgCombined", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "categoriesCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "mostRatedTool", - "type": { - "kind": "ref", - "value": "ToolWithStats" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "TopToolEntry", - "description": "", - "fields": [ - { - "name": "tool", - "type": { - "kind": "ref", - "value": "ToolWithStats" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "score", - "type": { - "kind": "type", - "value": "number" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "ratingCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "CategoryStats", - "description": "", - "fields": [ - { - "name": "category", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "toolCount", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "totalRatings", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsefulness", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "avgUsability", - "type": { - "kind": "type", - "value": "number | null" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "RatingDistribution", - "description": "", - "fields": [ - { - "name": "usefulness", - "type": { - "kind": "array", - "value": "ScoreBucket" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "usability", - "type": { - "kind": "array", - "value": "ScoreBucket" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ScoreBucket", - "description": "", - "fields": [ - { - "name": "score", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "count", - "type": { - "kind": "type", - "value": "integer" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "AuthUser", - "description": "", - "fields": [ - { - "name": "sub", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - }, - { - "name": "email", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "name", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "preferredUsername", - "type": { - "kind": "type", - "value": "string | null" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "role", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "admin, user" - }, - { - "name": "tier", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "free, premium, enterprise" - }, - { - "name": "entitlements", - "type": { - "kind": "array", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "" - }, - { - "name": "isLocal", - "type": { - "kind": "type", - "value": "boolean" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "UserPreferences", - "description": "", - "fields": [ - { - "name": "view", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "grid, table, rows" - }, - { - "name": "density", - "type": { - "kind": "type", - "value": "string" - }, - "required": false, - "description": "", - "constraints": "cozy, compact" - }, - { - "name": "watchlist", - "type": { - "kind": "array", - "value": "integer" - }, - "required": false, - "description": "", - "constraints": "" - } - ] - }, - { - "name": "ErrorResponse", - "description": "", - "fields": [ - { - "name": "error", - "type": { - "kind": "type", - "value": "string" - }, - "required": true, - "description": "", - "constraints": "" - } - ] - } - ] -} \ No newline at end of file diff --git a/docs/releases/v0.8.3.en.md b/docs/releases/v0.8.3.en.md deleted file mode 100644 index 8998402..0000000 --- a/docs/releases/v0.8.3.en.md +++ /dev/null @@ -1,49 +0,0 @@ -# v0.8.3 — Release Notes - -**Date:** 2026-08-04 · **Tag:** [`v0.8.3`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.3) - -## New features - -- **Version-based documentation**: Each release now carries a - complete docs snapshot (manual + API reference). Via the - version dropdown you can reach the docs of the respective version - (`/docs/vX.Y.Z/…`) — including the manual and reference as they - applied at release time. The last 7 versions remain available. -- **Help buttons in forms (NetBox style)**: For evaluation, tool - create/edit, costs, comparing, watchlist and analytics there is now - a help icon that leads directly to the matching guide in the manual. - -## Fixes & improvements - -- **Gitea tag links fixed**: `…/tags/vX.Y.Z` was a 404 page; the - correct URL is `/releases/tag/vX.Y.Z` (in all release notes and the - docs page). -- Version switching now leads to the docs of the selected version instead of - just the release page; old `/docs/vX.Y.Z` redirects are removed. -- Docs generator: `--snapshot` creates manual + reference per version; on - build, the snapshots of the last 7 versions are included. - -## API changes - -- No changes to the API. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. New release notes must use the correct - tag link (see `docs/releases/TEMPLATE.md`). For versions before - this release, snapshots can be created retroactively: - `node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`. - -## Known limitations - -- Older releases without a snapshot (e.g. v0.6.0) only show their release notes, - no manual/reference. Backfill with `--snapshot`. -- The docs version corresponds to the state of the docs at the time the - snapshot was created; manual changes apply from the respective next release. - -## Links - -- Commit: [`3bb4598`](https://git.kubebase.de/admin/tool-evaluator/commit/3bb4598) -- Tag: [`v0.8.3`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.3) diff --git a/docs/releases/v0.8.3.md b/docs/releases/v0.8.3.md deleted file mode 100644 index 3cc81a4..0000000 --- a/docs/releases/v0.8.3.md +++ /dev/null @@ -1,49 +0,0 @@ -# v0.8.3 — Release Notes - -**Datum:** 2026-08-04 · **Tag:** [`v0.8.3`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.3) - -## Neue Features - -- **Versionsbasierte Dokumentation**: Jedes Release trägt jetzt einen - vollständigen Doku-Snapshot (Handbuch + API-Referenz). Über das - Versions-Dropdown gelangst du zur Doku der jeweiligen Version - (`/docs/vX.Y.Z/…`) — inklusive Handbuch und Referenz, wie sie zum - Release-Zeitpunkt galten. Die letzten 7 Versionen bleiben verfügbar. -- **Hilfe-Buttons in Formularen (NetBox-Stil)**: Bei Bewertung, Tool - anlegen/bearbeiten, Kosten, Vergleichen, Merkliste und Analytics gibt es - jetzt ein Hilfe-Icon, das direkt zur passenden Anleitung im Handbuch führt. - -## Fixes & Verbesserungen - -- **Gitea-Tag-Links korrigiert**: `…/tags/vX.Y.Z` war eine 404-Seite; die - korrekte URL lautet `/releases/tag/vX.Y.Z` (in allen Release-Notes und der - Doku-Seite). -- Versions-Wechsel führt jetzt zur Doku der gewählten Version statt direkt - nur zur Release-Seite; alte `/docs/vX.Y.Z`-Redirects entfallen. -- Doku-Generator: `--snapshot` erzeugt Handbuch + Referenz pro Version; beim - Build werden die Snapshots der letzten 7 Versionen eingespielt. - -## API-Änderungen - -- Keine Änderungen an der API. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. Neue Release-Notes müssen den korrekten - Tag-Link verwenden (siehe `docs/releases/TEMPLATE.md`). Für Versionen vor - diesem Release können Snapshots nachträglich erzeugt werden: - `node scripts/src/generate-docs.mjs --snapshot vX.Y.Z`. - -## Bekannte Einschränkungen - -- Ältere Releases ohne Snapshot (z. B. v0.6.0) zeigen nur ihre Release-Notes, - kein Handbuch/keine Referenz. Mit `--snapshot` nachpflegen. -- Die Doku-Version entspricht dem Doku-Stand zum Zeitpunkt der Erstellung des - Snapshots; Änderungen am Handbuch gelten ab dem jeweils nächsten Release. - -## Links - -- Commit: [`3bb4598`](https://git.kubebase.de/admin/tool-evaluator/commit/3bb4598) -- Tag: [`v0.8.3`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.3) diff --git a/docs/releases/v0.8.4.en.md b/docs/releases/v0.8.4.en.md deleted file mode 100644 index c668e2f..0000000 --- a/docs/releases/v0.8.4.en.md +++ /dev/null @@ -1,45 +0,0 @@ -# v0.8.4 — Release Notes - -**Date:** 2026-08-04 · **Tag:** [`v0.8.4`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.4) - -## New features - -- **Full app localization (German/English)**: All pages and components are - now translated — tool detail page, admin area, trash, redundancy dashboard, - compare, watchlist, analytics, create and edit tool, admin tools tab, - category combobox and theme toggle. The language picker in the top right - switches the whole UI. -- **Bilingual documentation**: The manual (all 17 pages) and the release - notes are now available in German and English. The docs page has a - language switcher that switches content, navigation titles and search. - Versioned docs snapshots (v0.8.1, v0.8.2) also contain the English pages. - -## Fixes & improvements - -- All remaining hardcoded UI strings replaced with `t()` calls; the locales - are in sync (453 keys per language, 0 missing). -- API reference: table headers (Name/In), required badges and request body - labels in the docs are translated. -- Docs search respects the active language (separate index per language). - -## API changes - -- No changes to the API. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. The docs generator output now includes - additional English files (`*.en.md`) and `search.en.json`; these are - generated automatically during the build. - -## Known limitations - -- Versioned docs snapshots before v0.8.1 (e.g. v0.6.0) do not contain - English manual pages; the German version is used as fallback there. - -## Links - -- Commit: [`3de59cc`](https://git.kubebase.de/admin/tool-evaluator/commit/3de59cc) -- Tag: [`v0.8.4`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.4) diff --git a/docs/releases/v0.8.4.md b/docs/releases/v0.8.4.md deleted file mode 100644 index db2c936..0000000 --- a/docs/releases/v0.8.4.md +++ /dev/null @@ -1,48 +0,0 @@ -# v0.8.4 — Release Notes - -**Datum:** 2026-08-04 · **Tag:** [`v0.8.4`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.4) - -## Neue Features - -- **Komplette Lokalisierung der App (Deutsch/Englisch)**: Alle Seiten und - Komponenten sind jetzt übersetzt — Tool-Detailseite, Verwaltung, Papierkorb, - Redundanz-Dashboard, Vergleichen, Merkliste, Analytics, Tool anlegen und - bearbeiten, Admin-Bereich inkl. Tools-Tab, Kategorie-Combobox und - Theme-Umschalter. Die Sprachauswahl oben rechts wechselt die gesamte - Oberfläche. -- **Dokumentation zweisprachig**: Handbuch (alle 17 Seiten) und Release-Notes - sind jetzt in Deutsch und Englisch verfügbar. In der Doku gibt es einen - Sprach-Umschalter, der Inhalte, Navigationstitel und Suche umschaltet. - Auch versionierte Doku-Snapshots (v0.8.1, v0.8.2) enthalten die englischen - Seiten. - -## Fixes & Verbesserungen - -- Alle verbliebenen hartkodierten UI-Strings durch `t()`-Aufrufe ersetzt; - die Locales sind synchron (453 Keys pro Sprache, 0 fehlend). -- API-Referenz: Tabellen-Header (Name/In), Pflicht-Badges und - Request-Body-Label der Doku übersetzt. -- Suche in der Doku berücksichtigt die aktive Sprache (eigener Index pro - Sprache). - -## API-Änderungen - -- Keine Änderungen an der API. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. Die Doku-Generator-Ausgabe umfasst jetzt - zusätzliche englische Dateien (`*.en.md`) und `search.en.json`; beim Build - werden diese automatisch erzeugt. - -## Bekannte Einschränkungen - -- Versionierte Doku-Snapshots vor v0.8.1 (z. B. v0.6.0) enthalten keine - englischen Handbuch-Seiten; dort greift die deutsche Fassung als Fallback. - -## Links - -- Commit: [`3de59cc`](https://git.kubebase.de/admin/tool-evaluator/commit/3de59cc) -- Tag: [`v0.8.4`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.4) diff --git a/docs/releases/v0.8.5.en.md b/docs/releases/v0.8.5.en.md deleted file mode 100644 index a5eb6b4..0000000 --- a/docs/releases/v0.8.5.en.md +++ /dev/null @@ -1,45 +0,0 @@ -# v0.8.5 — Release Notes - -**Date:** 2026-08-04 · **Tag:** [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5) - -## New features - -- **Help buttons across the app**: The main pages (Home, Browse tools, Trash, - Redundancy dashboard, Admin tools) as well as the premium dialog and the - password dialog now show a book icon next to the title that links directly - to the matching manual page (following the existing buttons on the tool - detail, create, edit, compare, watchlist and analytics pages). - -## Fixes & improvements - -- **Translated submit button when creating a tool**: The "Submit Tool" / - "Adding Tool…" button was still hardcoded and appeared in English in the - German UI. It is now translated, e.g. "Tool einreichen" / "Füge Tool - hinzu…" in German. -- **More translated UI strings**: View mode (Grid/Table/Rows), list density - (Compact/Comfortable), minimum rating in the filter and the password hint - "min. 6 characters" are now translated correctly. -- **Consistent docs terminology**: The manual now consistently calls the - watchlist "Merkliste" in all German pages and release notes; the English - version stays "Watchlist". The `watchlist` permission name and the URLs - are unchanged. -- All locales are in sync (462 keys per language, 0 missing). - -## API changes - -- No changes to the API. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. - -## Known limitations - -- None. - -## Links - -- Commit: [`70e72da`](https://git.kubebase.de/admin/tool-evaluator/commit/70e72da) -- Tag: [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5) diff --git a/docs/releases/v0.8.5.md b/docs/releases/v0.8.5.md deleted file mode 100644 index e94bcc4..0000000 --- a/docs/releases/v0.8.5.md +++ /dev/null @@ -1,46 +0,0 @@ -# v0.8.5 — Release Notes - -**Datum:** 2026-08-04 · **Tag:** [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5) - -## Neue Features - -- **Hilfe-Buttons in der gesamten App**: Auf den Hauptseiten (Start, Tools - durchsuchen, Papierkorb, Redundanz-Dashboard, Admin-Tools) sowie in - Premium-Dialog und Passwort-Dialog gibt es jetzt ein Buch-Icon neben dem - Titel, das direkt zur passenden Anleitung im Handbuch verlinkt (analog zu - den bestehenden Buttons auf Tool-Detail-, Anlegen-, Bearbeiten-, - Vergleichen-, Merkliste- und Analytics-Seiten). - -## Fixes & Verbesserungen - -- **Submit-Button beim Tool-Anlegen übersetzt**: Der Button „Submit Tool" / - „Adding Tool…" war noch hartkodiert und erschien auf Deutsch auf Englisch. - Jetzt: „Tool einreichen" / „Füge Tool hinzu…" (bzw. die englischen - Entsprechungen). -- **Weitere übersetzte UI-Strings**: Ansichtsmodus (Raster/Tabelle/Zeilen), - Listendichte (Kompakt/Komfortabel), Mindestbewertung im Filter sowie der - Passwort-Hinweis „min. 6 Zeichen" werden jetzt korrekt übersetzt. -- **Doku-Terminologie konsistent**: Das Handbuch heißt die Merkliste jetzt - einheitlich „Merkliste" (statt „Watchlist") in allen deutschen Seiten und - Release-Notes; die englische Fassung bleibt „Watchlist". Die - Permissions-Bezeichnung `watchlist` und die URLs sind unverändert. -- Alle Locales synchron (462 Keys pro Sprache, 0 fehlend). - -## API-Änderungen - -- Keine Änderungen an der API. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. - -## Bekannte Einschränkungen - -- Keine. - -## Links - -- Commit: [`70e72da`](https://git.kubebase.de/admin/tool-evaluator/commit/70e72da) -- Tag: [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5) diff --git a/docs/releases/v0.8.6.en.md b/docs/releases/v0.8.6.en.md deleted file mode 100644 index 0424564..0000000 --- a/docs/releases/v0.8.6.en.md +++ /dev/null @@ -1,49 +0,0 @@ -# v0.8.6 — Release Notes - -**Date:** 2026-08-04 · **Tag:** [`v0.8.6`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.6) - -## New features - -- **Bulk tool import in the admin area (premium)**: Admins can now create - multiple tools at once via the new **Import** button in the "Tools" tab. - The format is detected automatically (CSV, JSON or YAML); for CSV the - delimiter can be chosen (auto-detect, comma, semicolon or tab). Data can be - pasted directly or uploaded as a file. Faulty rows are skipped and listed - with their row number while correct rows are still created. Every import - produces audit-log entries. The feature is enabled via the `tool-import` - feature (premium/enterprise); admins always pass the check. - -## Improvements - -- **NetBox-style help buttons**: The previously attached book icon and the - `FieldHelp` question marks (which showed a German tooltip in the English - layout) have been removed. Forms (create tool, edit tool, rate, password - dialog) now show a "Hilfe"/"Help" outline button with a question-mark icon - at the top right that opens the corresponding handbook page — fully - localized. -- All locales are in sync (482 keys per language, 0 missing). - -## API changes - -- **New:** `POST /admin/tools/import` (admin + `tool-import` feature). - Request body: `format` (`auto|csv|json|yaml`, default `auto`), `delimiter` - (`auto|comma|semicolon|tab`, default `auto`), `data` (string). Response: - `{ imported, total, errors: [{ row, error }] }`. - -## Operations / upgrade - -- **Env vars:** unchanged. -- **Migration:** none. -- **Breaking changes:** none. The import endpoint is only available to - premium/enterprise admins; free/user accounts keep standard access. - -## Known limitations - -- CSV columns whose header does not map to a supported field are ignored; - only the defined fields (`name`, `description`, `category`, `websiteUrl`, - `iconUrl`, `features`, `tags`) are taken over. - -## Links - -- Commit: [`8f2fd89`](https://git.kubebase.de/admin/tool-evaluator/commit/8f2fd89) -- Tag: [`v0.8.6`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.6) \ No newline at end of file diff --git a/docs/releases/v0.8.6.md b/docs/releases/v0.8.6.md deleted file mode 100644 index f4bcbfd..0000000 --- a/docs/releases/v0.8.6.md +++ /dev/null @@ -1,50 +0,0 @@ -# v0.8.6 — Release Notes - -**Datum:** 2026-08-04 · **Tag:** [`v0.8.6`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.6) - -## Neue Features - -- **Bulk-Tool-Import im Admin (Premium)**: Admins können über den neuen Button - **Importieren** im Tab „Tools" mehrere Tools gleichzeitig anlegen. Das Format - wird automatisch erkannt (CSV, JSON oder YAML); für CSV ist der Trenner - wählbar (automatisch, Komma, Semikolon oder Tabulator). Daten lassen sich - direkt einfügen oder als Datei hochladen. Fehlerhafte Zeilen werden übersprungen - und mit Zeilennummer aufgelistet, korrekte weiterhin angelegt. Jeder Import - erzeugt Audit-Log-Einträge. Das Feature ist über das `tool-import`-Feature - (Premium/Enterprise) freigeschaltet; Admins passieren den Check immer. - -## Verbesserungen - -- **Hilfe-Buttons im NetBox-Stil**: Das zuvor angebundene Buch-Icon und die - `FieldHelp`-Fragezeichen (die im englischen Layout deutschen Tooltip zeigten) - wurden entfernt. Formulare (Tool anlegen, Tool bearbeiten, Bewerten, - Passwort-Dialog) haben jetzt oben rechts einen „Hilfe"/„Help"-Outline-Button mit - Fragezeichen-Icon, der die zugehörige Handbuch-Seite öffnet — vollständig - übersetzt. -- Alle Locales synchron (482 Keys pro Sprache, 0 fehlend). - -## API-Änderungen - -- **Neu:** `POST /admin/tools/import` (Admin + `tool-import`-Feature). - Request-Body: `format` (`auto|csv|json|yaml`, Default `auto`), `delimiter` - (`auto|comma|semicolon|tab`, Default `auto`), `data` (String). Antwort: - `{ imported, total, errors: [{ row, error }] }`. - -## Betrieb / Upgrade - -- **Env-Vars:** unverändert. -- **Migration:** keine. -- **Breaking Changes:** keine. Der Import-Endpunkt ist ausschließlich für - Premium/Enterprise-Admins; Free-/User-Konten erhalten weiterhin den Standard- - Zugriff. - -## Bekannte Einschränkungen - -- CSV-Spalten, die in der Kopfzeile nicht als unterstützte Felder erkannt werden, - werden ignoriert; nur die definierten Felder (`name`, `description`, - `category`, `websiteUrl`, `iconUrl`, `features`, `tags`) werden übernommen. - -## Links - -- Commit: [`8f2fd89`](https://git.kubebase.de/admin/tool-evaluator/commit/8f2fd89) -- Tag: [`v0.8.6`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.6) \ No newline at end of file diff --git a/docs/releases/v0.9.0.de.md b/docs/releases/v0.9.0.de.md new file mode 100644 index 0000000..2a61930 --- /dev/null +++ b/docs/releases/v0.9.0.de.md @@ -0,0 +1,46 @@ +# v0.9.0 — Release Notes + +**Datum:** 2026-08-05 · **Tag:** [`v0.9.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.9.0) + +## Neue Features + +- **Neuausrichtung der Versionierung:** Die Dokumentation startet mit dieser + Version neu bei `v0.9.0`. Ältere Release-Notizen und Versionen-Snapshots + (v0.6.0–v0.8.6) wurden entfernt. Das Handbuch und die Referenz (API/Admin) + sind jetzt wieder für jede Version verfügbar — auch für neuere Versionen. +- **Sprachsuffixe:** Alle Dokumentationsdateien verwenden jetzt einheitlich die + Suffixe `.de.md` und `.en.md`. Damit lassen sich später weitere Sprachen + ergänzen; die App liefert automatisch die passende Sprachfassung. +- **Import — fertige Beispieldatei:** Unter `docs/examples/import-tools.yaml` + liegt eine sofort importierbare YAML-Beispieldatei mit 24 gängigen + Enterprise-Tools (Kategorien wie Kommunikation, Monitoring, CI/CD, + Infrastruktur). Die Datei ist in der Administration-Dokumentation verlinkt. + +## Fixes & Verbesserungen + +- Der Versionsumschalter zeigt die Dokumentation jetzt auch für neuere + Versionen korrekt an (vorher fehlende Versionen-Snapshots machten Handbuch und + Referenz nicht verfügbar). +- Wording bereinigt: Die Tagline und Platzhaltertexte ohne Berufsbezeichnung + („Bewerte dein Tool." / „Rate your Tool.", „Anonymer Benutzer" / + „Anonymous User"). Es werden keine Gender-Sonderformen mehr verwendet + (`Nutzer:innen` → `Nutzer`, `Ersteller:in` → `Ersteller`). + +## API-Änderungen + +- Keine Änderungen gegenüber v0.8.6 (siehe `lib/api-spec/openapi.yaml`). + +## Betrieb / Upgrade + +- **Migration:** keine. Bereits vorhandene Tools-, Bewertungs- und Konto-Daten + bleiben unverändert. +- **Breaking Changes:** keine. + +## Bekannte Einschränkungen + +- Keine im Rahmen dieses Releases. + +## Links + +- Commit: [``](https://git.kubebase.de/admin/tool-evaluator/commit/) +- Tag: [`v0.9.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.9.0) \ No newline at end of file diff --git a/docs/releases/v0.9.0.en.md b/docs/releases/v0.9.0.en.md new file mode 100644 index 0000000..fb7976d --- /dev/null +++ b/docs/releases/v0.9.0.en.md @@ -0,0 +1,46 @@ +# v0.9.0 — Release Notes + +**Date:** 2026-08-05 · **Tag:** [`v0.9.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.9.0) + +## New Features + +- **Versioning reset:** Documentation starts fresh at `v0.9.0` with this + release. Older release notes and version snapshots (v0.6.0–v0.8.6) have been + removed. The handbook and reference (API/admin) are now available again for + every version — including newer versions. +- **Language suffixes:** All documentation files now consistently use the + `.de.md` and `.en.md` suffixes. This makes it easy to add more languages + later; the app automatically serves the matching language variant. +- **Import — ready-to-use example file:** A ready-to-import YAML example file + with 24 common enterprise tools is provided at + `docs/examples/import-tools.yaml` (categories such as communication, + monitoring, CI/CD, infrastructure). The file is linked from the + administration documentation. + +## Fixes & Polish + +- The version switcher now displays documentation correctly for newer versions + as well (previously, missing version snapshots made the handbook and + reference unavailable). +- Wording cleanup: tagline and placeholder texts no longer reference a specific + job title ("Rate your Tool.", "Anonymous User"). No gender-specific forms are + used anymore. + +## API Changes + +- No changes compared to v0.8.6 (see `lib/api-spec/openapi.yaml`). + +## Operations / Upgrade + +- **Migration:** none. Existing tool, rating, and account data remain + unchanged. +- **Breaking Changes:** none. + +## Known Limitations + +- None within the scope of this release. + +## Links + +- Commit: [``](https://git.kubebase.de/admin/tool-evaluator/commit/) +- Tag: [`v0.9.0`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.9.0) \ No newline at end of file diff --git a/docs/releases/v0.8.2/handbook/administration.md b/docs/releases/v0.9.0/handbook/administration.de.md similarity index 62% rename from docs/releases/v0.8.2/handbook/administration.md rename to docs/releases/v0.9.0/handbook/administration.de.md index 585e0ce..87b386d 100644 --- a/docs/releases/v0.8.2/handbook/administration.md +++ b/docs/releases/v0.9.0/handbook/administration.de.md @@ -32,6 +32,49 @@ Zentraler Zugriff auf den Tool-Katalog. - **Massenaktion:** mehrere Tools auswählen und in den Papierkorb verschieben (Bestätigungsdialog; soft gelöschte Tools sind aus allen öffentlichen Ansichten entfernt und können wiederhergestellt oder endgültig gelöscht werden). +- **Importieren** (Premium): über die Schaltfläche **Importieren** oben rechts + können mehrere Tools gleichzeitig angelegt werden. Das Format wird automatisch + erkannt (CSV, JSON oder YAML); für CSV lässt sich der Trenner wählen + (automatisch, Komma, Semikolon oder Tabulator). Die Daten lassen sich direkt + ins Formular einfügen oder als Datei hochladen. + + Unterstützte Felder: `name` (Pflicht), `description`, `category`, `websiteUrl`, + `iconUrl`, `features`, `tags` (`features`/`tags` sind mit `|` getrennte Listen). + + **CSV-Beispiel:** + + ```csv + name;description;category;features;tags + Grafana;Observability- und Dashboard-Plattform;Monitoring;Dashboards|Alerts;devops + Prometheus;Zeitreihen-Datenbank;Monitoring;Metrics;devops + ``` + + **JSON-Beispiel:** + + ```json + [ + { "name": "Grafana", "category": "Monitoring", "features": ["Dashboards"] }, + { "name": "Prometheus", "category": "Monitoring" } + ] + ``` + + **YAML-Beispiel:** + + ```yaml + - name: Grafana + category: Monitoring + features: + - Dashboards + - name: Prometheus + category: Monitoring + ``` + + Eine umfangreichere, fertig importierbare Beispieldatei liegt unter + `docs/examples/import-tools.yaml` (24 gängige Enterprise-Tools). + + Beim Import werden einzelne fehlerhafte Zeilen übersprungen und mit Zeilennummer + aufgelistet; korrekte Zeilen werden trotzdem angelegt. Jeder Import erzeugt + Audit-Log-Einträge. ## Tab „Audit-Log" diff --git a/docs/releases/v0.8.2/handbook/administration.en.md b/docs/releases/v0.9.0/handbook/administration.en.md similarity index 61% rename from docs/releases/v0.8.2/handbook/administration.en.md rename to docs/releases/v0.9.0/handbook/administration.en.md index 9fe7806..e5b1e38 100644 --- a/docs/releases/v0.8.2/handbook/administration.en.md +++ b/docs/releases/v0.9.0/handbook/administration.en.md @@ -32,6 +32,49 @@ Central access to the tool catalog. - **Bulk action:** select multiple tools and move them to the trash (confirmation dialog; soft-deleted tools are removed from all public views and can be restored or permanently deleted). +- **Import** (premium): via the **Import** button at the top right, multiple + tools can be created at once. The format is detected automatically (CSV, + JSON or YAML); for CSV the delimiter can be chosen (auto-detect, comma, + semicolon or tab). Data can be pasted directly into the form or uploaded + as a file. + + Supported fields: `name` (required), `description`, `category`, `websiteUrl`, + `iconUrl`, `features`, `tags` (`features`/`tags` are `|`-separated lists). + + **CSV example:** + + ```csv + name;description;category;features;tags + Grafana;Observability and dashboard platform;Monitoring;Dashboards|Alerts;devops + Prometheus;Time-series database;Monitoring;Metrics;devops + ``` + + **JSON example:** + + ```json + [ + { "name": "Grafana", "category": "Monitoring", "features": ["Dashboards"] }, + { "name": "Prometheus", "category": "Monitoring" } + ] + ``` + + **YAML example:** + + ```yaml + - name: Grafana + category: Monitoring + features: + - Dashboards + - name: Prometheus + category: Monitoring + ``` + + A larger, ready-to-import example file is located at + `docs/examples/import-tools.yaml` (24 common enterprise tools). + + During import, individual faulty rows are skipped and listed with their row + number; correct rows are still created. Every import produces audit-log + entries. ## "Audit log" tab diff --git a/docs/releases/v0.8.1/handbook/analytics.md b/docs/releases/v0.9.0/handbook/analytics.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/analytics.md rename to docs/releases/v0.9.0/handbook/analytics.de.md diff --git a/docs/releases/v0.8.1/handbook/analytics.en.md b/docs/releases/v0.9.0/handbook/analytics.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/analytics.en.md rename to docs/releases/v0.9.0/handbook/analytics.en.md diff --git a/docs/releases/v0.8.1/handbook/bewerten.md b/docs/releases/v0.9.0/handbook/bewerten.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/bewerten.md rename to docs/releases/v0.9.0/handbook/bewerten.de.md diff --git a/docs/releases/v0.8.1/handbook/bewerten.en.md b/docs/releases/v0.9.0/handbook/bewerten.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/bewerten.en.md rename to docs/releases/v0.9.0/handbook/bewerten.en.md diff --git a/docs/releases/v0.8.1/handbook/datenmodell.md b/docs/releases/v0.9.0/handbook/datenmodell.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/datenmodell.md rename to docs/releases/v0.9.0/handbook/datenmodell.de.md diff --git a/docs/releases/v0.8.1/handbook/datenmodell.en.md b/docs/releases/v0.9.0/handbook/datenmodell.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/datenmodell.en.md rename to docs/releases/v0.9.0/handbook/datenmodell.en.md diff --git a/docs/releases/v0.8.2/handbook/getting-started.md b/docs/releases/v0.9.0/handbook/getting-started.de.md similarity index 94% rename from docs/releases/v0.8.2/handbook/getting-started.md rename to docs/releases/v0.9.0/handbook/getting-started.de.md index 0fd7820..b5d6906 100644 --- a/docs/releases/v0.8.2/handbook/getting-started.md +++ b/docs/releases/v0.9.0/handbook/getting-started.de.md @@ -6,7 +6,7 @@ Besuch bis zum Anlegen und Bewerten eines Tools. ## 1. Anmelden -Die meisten Aktionen (Tool anlegen, bewerten, Watchlist, Vergleichen) erfordern +Die meisten Aktionen (Tool anlegen, bewerten, Merkliste, Vergleichen) erfordern ein Konto. Klicke unten links auf **Anmelden**. Je nach Konfiguration der Instanz hast du zwei Möglichkeiten: @@ -47,7 +47,7 @@ Siehe [Bewerten](/docs/handbook/bewerten). ## 5. Weiterführend - [Tools vergleichen](/docs/handbook/vergleichen) -- [Watchlist](/docs/handbook/watchlist) +- [Merkliste](/docs/handbook/watchlist) - [Analytics](/docs/handbook/analytics) - [Pläne & Berechtigungen](/docs/handbook/plaene) - [Administration](/docs/handbook/administration) diff --git a/docs/releases/v0.8.1/handbook/getting-started.en.md b/docs/releases/v0.9.0/handbook/getting-started.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/getting-started.en.md rename to docs/releases/v0.9.0/handbook/getting-started.en.md diff --git a/docs/releases/v0.8.1/handbook/index.md b/docs/releases/v0.9.0/handbook/index.de.md similarity index 90% rename from docs/releases/v0.8.1/handbook/index.md rename to docs/releases/v0.9.0/handbook/index.de.md index f527a6e..fb4d3d5 100644 --- a/docs/releases/v0.8.1/handbook/index.md +++ b/docs/releases/v0.9.0/handbook/index.de.md @@ -2,7 +2,7 @@ # Willkommen bei toolr toolr ist eine Plattform zum **Entdecken, Bewerten und Vergleichen von -Entwicklungstools**. Nutzer:innen pflegen einen gemeinsamen Katalog von Tools, +Entwicklungstools**. Nutzer pflegen einen gemeinsamen Katalog von Tools, vergeben Bewertungen (Nützlichkeit & Bedienbarkeit) und nutzen Statistiken, um die richtige Wahl zu treffen. @@ -12,13 +12,14 @@ die richtige Wahl zu treffen. | --- | --- | --- | | **Tools durchsuchen** | Katalog filtern, sortieren und durchsuchen | Alle | | **Tool anlegen** | Neues Tool mit Beschreibung, Kategorie, Features & Tags eintragen | Angemeldet | -| **Tool bearbeiten/löschen** | Eigene Tools pflegen (Ersteller:in oder Admin) | Angemeldet | +| **Tool bearbeiten/löschen** | Eigene Tools pflegen (Ersteller oder Admin) | Angemeldet | | **Bewerten** | Nützlichkeit & Bedienbarkeit (1–5) plus Kommentar vergeben | Angemeldet | -| **Watchlist** | Tools als Favoriten speichern | Premium | +| **Merkliste** | Tools als Favoriten speichern | Premium | | **Vergleichen** | Tools nebeneinander gegenüberstellen | Premium | | **Kosten erfassen** | Lizenz- und Kostenmodelle je Tool eintragen | Premium | | **Analytics** | Statistiken, Top-Tools, Verteilungen | Alle | | **Papierkorb** | Soft-gelöschte Tools wiederherstellen oder endgültig löschen | Premium | +| **Import** | Mehrere Tools per CSV, JSON oder YAML anlegen | Admin (Premium) | | **Admin** | Nutzerverwaltung, Audit-Log, Systeminformationen | Admin | | **Redundanz** | Automatische Doppelungs-Erkennung | Admin | diff --git a/docs/releases/v0.8.2/handbook/index.en.md b/docs/releases/v0.9.0/handbook/index.en.md similarity index 96% rename from docs/releases/v0.8.2/handbook/index.en.md rename to docs/releases/v0.9.0/handbook/index.en.md index 490c2c5..5231030 100644 --- a/docs/releases/v0.8.2/handbook/index.en.md +++ b/docs/releases/v0.9.0/handbook/index.en.md @@ -18,6 +18,7 @@ tools**. Users maintain a shared catalog of tools, submit ratings | **Record costs** | Enter license and cost models per tool | Premium | | **Analytics** | Statistics, top tools, distributions | Everyone | | **Trash** | Restore soft-deleted tools or delete them permanently | Premium | +| **Import** | Create multiple tools via CSV, JSON or YAML | Admin (premium) | | **Admin** | User management, audit log, system information | Admin | | **Redundancy detection** | Automatic duplicate detection | Admin | diff --git a/docs/releases/v0.8.1/handbook/index.json b/docs/releases/v0.9.0/handbook/index.json similarity index 81% rename from docs/releases/v0.8.1/handbook/index.json rename to docs/releases/v0.9.0/handbook/index.json index 4dc0aa7..1ab56d9 100644 --- a/docs/releases/v0.8.1/handbook/index.json +++ b/docs/releases/v0.9.0/handbook/index.json @@ -1,7 +1,7 @@ [ { "slug": "index", - "file": "index.md", + "file": "index.de.md", "title": "Überblick", "order": 1, "fileEn": "index.en.md", @@ -9,7 +9,7 @@ }, { "slug": "getting-started", - "file": "getting-started.md", + "file": "getting-started.de.md", "title": "Erste Schritte", "order": 2, "fileEn": "getting-started.en.md", @@ -17,7 +17,7 @@ }, { "slug": "konto", - "file": "konto.md", + "file": "konto.de.md", "title": "Anmelden & Konto", "order": 3, "fileEn": "konto.en.md", @@ -25,7 +25,7 @@ }, { "slug": "tools-finden", - "file": "tools-finden.md", + "file": "tools-finden.de.md", "title": "Tools finden & durchsuchen", "order": 4, "fileEn": "tools-finden.en.md", @@ -33,7 +33,7 @@ }, { "slug": "tool-anlegen", - "file": "tool-anlegen.md", + "file": "tool-anlegen.de.md", "title": "Tool anlegen", "order": 5, "fileEn": "tool-anlegen.en.md", @@ -41,7 +41,7 @@ }, { "slug": "tool-bearbeiten", - "file": "tool-bearbeiten.md", + "file": "tool-bearbeiten.de.md", "title": "Tool bearbeiten & löschen", "order": 6, "fileEn": "tool-bearbeiten.en.md", @@ -49,7 +49,7 @@ }, { "slug": "bewerten", - "file": "bewerten.md", + "file": "bewerten.de.md", "title": "Bewerten", "order": 7, "fileEn": "bewerten.en.md", @@ -57,15 +57,15 @@ }, { "slug": "watchlist", - "file": "watchlist.md", - "title": "Watchlist", + "file": "watchlist.de.md", + "title": "Merkliste", "order": 8, "fileEn": "watchlist.en.md", "titleEn": "Watchlist" }, { "slug": "vergleichen", - "file": "vergleichen.md", + "file": "vergleichen.de.md", "title": "Vergleichen", "order": 9, "fileEn": "vergleichen.en.md", @@ -73,7 +73,7 @@ }, { "slug": "analytics", - "file": "analytics.md", + "file": "analytics.de.md", "title": "Analytics", "order": 10, "fileEn": "analytics.en.md", @@ -81,7 +81,7 @@ }, { "slug": "plaene", - "file": "plaene.md", + "file": "plaene.de.md", "title": "Pläne & Berechtigungen", "order": 11, "fileEn": "plaene.en.md", @@ -89,7 +89,7 @@ }, { "slug": "kosten", - "file": "kosten.md", + "file": "kosten.de.md", "title": "Kosten erfassen", "order": 12, "fileEn": "kosten.en.md", @@ -97,7 +97,7 @@ }, { "slug": "administration", - "file": "administration.md", + "file": "administration.de.md", "title": "Administration", "order": 13, "fileEn": "administration.en.md", @@ -105,7 +105,7 @@ }, { "slug": "redundanz", - "file": "redundanz.md", + "file": "redundanz.de.md", "title": "Redundanz-Dashboard", "order": 14, "fileEn": "redundanz.en.md", @@ -113,7 +113,7 @@ }, { "slug": "papierkorb", - "file": "papierkorb.md", + "file": "papierkorb.de.md", "title": "Papierkorb", "order": 15, "fileEn": "papierkorb.en.md", @@ -121,7 +121,7 @@ }, { "slug": "tastatur", - "file": "tastatur.md", + "file": "tastatur.de.md", "title": "Tastenkürzel & Kommandopalette", "order": 16, "fileEn": "tastatur.en.md", @@ -129,7 +129,7 @@ }, { "slug": "datenmodell", - "file": "datenmodell.md", + "file": "datenmodell.de.md", "title": "Datenmodell", "order": 17, "fileEn": "datenmodell.en.md", diff --git a/docs/releases/v0.8.2/handbook/konto.md b/docs/releases/v0.9.0/handbook/konto.de.md similarity index 94% rename from docs/releases/v0.8.2/handbook/konto.md rename to docs/releases/v0.9.0/handbook/konto.de.md index 40aae3d..1fc81aa 100644 --- a/docs/releases/v0.8.2/handbook/konto.md +++ b/docs/releases/v0.9.0/handbook/konto.de.md @@ -22,7 +22,7 @@ Der aktive Modus steht im Endpunkt Dein Profil (Avatar, Name, E-Mail, Tarif) siehst du unten links im Benutzermenü. Dort stehen dir folgende Aktionen zur Verfügung: -- **Watchlist** — deine gespeicherten Tools (nur mit dem entsprechenden Tarif). +- **Merkliste** — deine gespeicherten Tools (nur mit dem entsprechenden Tarif). - **Papierkorb** — wiederherstellbare, gelöschte Tools (Premium/Enterprise). - **Passwort ändern** — für lokale Konten direkt in toolr; für OIDC-Konten wird die Passwortverwaltung im Identitätsanbieter angeboten. @@ -47,7 +47,7 @@ API-Referenz: [`POST /auth/me/password`](/docs/reference/endpoints/auth#changeMy - die **Listenansicht** und **Dichte** im Bereich Tools durchsuchen anpassen (siehe [Tools finden & durchsuchen](/docs/handbook/tools-finden)). -Deine Präferenzen (inkl. Watchlist) werden im Endpunkt +Deine Präferenzen (inkl. Merkliste) werden im Endpunkt [`GET /auth/me/preferences`](/docs/reference/endpoints/auth#getMePreferences) gespeichert und über [`PUT /auth/me/preferences`](/docs/reference/endpoints/auth#updateMePreferences) aktualisiert. diff --git a/docs/releases/v0.8.1/handbook/konto.en.md b/docs/releases/v0.9.0/handbook/konto.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/konto.en.md rename to docs/releases/v0.9.0/handbook/konto.en.md diff --git a/docs/releases/v0.8.1/handbook/kosten.md b/docs/releases/v0.9.0/handbook/kosten.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/kosten.md rename to docs/releases/v0.9.0/handbook/kosten.de.md diff --git a/docs/releases/v0.8.1/handbook/kosten.en.md b/docs/releases/v0.9.0/handbook/kosten.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/kosten.en.md rename to docs/releases/v0.9.0/handbook/kosten.en.md diff --git a/docs/releases/v0.8.1/handbook/papierkorb.md b/docs/releases/v0.9.0/handbook/papierkorb.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/papierkorb.md rename to docs/releases/v0.9.0/handbook/papierkorb.de.md diff --git a/docs/releases/v0.8.1/handbook/papierkorb.en.md b/docs/releases/v0.9.0/handbook/papierkorb.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/papierkorb.en.md rename to docs/releases/v0.9.0/handbook/papierkorb.en.md diff --git a/docs/releases/v0.8.2/handbook/plaene.md b/docs/releases/v0.9.0/handbook/plaene.de.md similarity index 84% rename from docs/releases/v0.8.2/handbook/plaene.md rename to docs/releases/v0.9.0/handbook/plaene.de.md index d4546b7..2c79230 100644 --- a/docs/releases/v0.8.2/handbook/plaene.md +++ b/docs/releases/v0.9.0/handbook/plaene.de.md @@ -9,7 +9,7 @@ Feature-Beschränkungen. | Tarif | Beschreibung | | --- | --- | | **Free** | Grundfunktionen: suchen, filtern, ansehen, Analytics | -| **Premium** | Zusätzlich Watchlist, Vergleichen, Papierkorb, Kosten | +| **Premium** | Zusätzlich Merkliste, Vergleichen, Papierkorb, Kosten | | **Enterprise** | Alle Premium-Features + erweiterter Support | ### Feature-Berechtigungen @@ -19,9 +19,10 @@ Premium/Enterprise schalten folgende Features frei: | Feature | Funktion | Mehr erfahren | | --- | --- | --- | | `compare` | Tools vergleichen | [Vergleichen](/docs/handbook/vergleichen) | -| `watchlist` | Favoritenliste | [Watchlist](/docs/handbook/watchlist) | +| `watchlist` | Favoritenliste | [Merkliste](/docs/handbook/watchlist) | | `trash` | Papierkorb (soft gelöschte Tools) | [Papierkorb](/docs/handbook/papierkorb) | | `costs` | Kosten-/Lizenzmodelle erfassen | [Kosten erfassen](/docs/handbook/kosten) | +| `tool-import` | Tools per CSV/JSON/YAML importieren (Admin) | [Administration](/docs/handbook/administration) | Fehlt dir ein Feature, zeigt die App einen **Upgrade-Hinweis** mit Link zur Tarifverwaltung. diff --git a/docs/releases/v0.8.2/handbook/plaene.en.md b/docs/releases/v0.9.0/handbook/plaene.en.md similarity index 92% rename from docs/releases/v0.8.2/handbook/plaene.en.md rename to docs/releases/v0.9.0/handbook/plaene.en.md index f73d6dc..29cce75 100644 --- a/docs/releases/v0.8.2/handbook/plaene.en.md +++ b/docs/releases/v0.9.0/handbook/plaene.en.md @@ -22,6 +22,7 @@ Premium/Enterprise unlock the following features: | `watchlist` | Favorites list | [Watchlist](/docs/handbook/watchlist) | | `trash` | Trash (soft-deleted tools) | [Trash](/docs/handbook/papierkorb) | | `costs` | Record cost/license models | [Recording costs](/docs/handbook/kosten) | +| `tool-import` | Import tools via CSV/JSON/YAML (admin) | [Administration](/docs/handbook/administration) | If you are missing a feature, the app shows an **upgrade notice** with a link to the plan management. diff --git a/docs/releases/v0.8.1/handbook/redundanz.md b/docs/releases/v0.9.0/handbook/redundanz.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/redundanz.md rename to docs/releases/v0.9.0/handbook/redundanz.de.md diff --git a/docs/releases/v0.8.1/handbook/redundanz.en.md b/docs/releases/v0.9.0/handbook/redundanz.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/redundanz.en.md rename to docs/releases/v0.9.0/handbook/redundanz.en.md diff --git a/docs/releases/v0.8.2/handbook/tastatur.md b/docs/releases/v0.9.0/handbook/tastatur.de.md similarity index 93% rename from docs/releases/v0.8.2/handbook/tastatur.md rename to docs/releases/v0.9.0/handbook/tastatur.de.md index 7eb6f17..96489bf 100644 --- a/docs/releases/v0.8.2/handbook/tastatur.md +++ b/docs/releases/v0.9.0/handbook/tastatur.de.md @@ -15,7 +15,7 @@ Ohne Eingabe zeigt die Palette: - **Zuletzt angesehen** — die letzten 5 Tools, die du besucht hast. - **Navigation** — Tools durchsuchen, Tool hinzufügen, Analytics sowie - (abhängig von Berechtigungen) Watchlist, Papierkorb und Admin. + (abhängig von Berechtigungen) Merkliste, Papierkorb und Admin. ### Suche diff --git a/docs/releases/v0.8.1/handbook/tastatur.en.md b/docs/releases/v0.9.0/handbook/tastatur.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/tastatur.en.md rename to docs/releases/v0.9.0/handbook/tastatur.en.md diff --git a/docs/releases/v0.8.1/handbook/tool-anlegen.md b/docs/releases/v0.9.0/handbook/tool-anlegen.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/tool-anlegen.md rename to docs/releases/v0.9.0/handbook/tool-anlegen.de.md diff --git a/docs/releases/v0.8.1/handbook/tool-anlegen.en.md b/docs/releases/v0.9.0/handbook/tool-anlegen.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/tool-anlegen.en.md rename to docs/releases/v0.9.0/handbook/tool-anlegen.en.md diff --git a/docs/releases/v0.8.1/handbook/tool-bearbeiten.md b/docs/releases/v0.9.0/handbook/tool-bearbeiten.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/tool-bearbeiten.md rename to docs/releases/v0.9.0/handbook/tool-bearbeiten.de.md diff --git a/docs/releases/v0.8.1/handbook/tool-bearbeiten.en.md b/docs/releases/v0.9.0/handbook/tool-bearbeiten.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/tool-bearbeiten.en.md rename to docs/releases/v0.9.0/handbook/tool-bearbeiten.en.md diff --git a/docs/releases/v0.8.2/handbook/tools-finden.md b/docs/releases/v0.9.0/handbook/tools-finden.de.md similarity index 94% rename from docs/releases/v0.8.2/handbook/tools-finden.md rename to docs/releases/v0.9.0/handbook/tools-finden.de.md index c976515..a0f8add 100644 --- a/docs/releases/v0.8.2/handbook/tools-finden.md +++ b/docs/releases/v0.9.0/handbook/tools-finden.de.md @@ -43,7 +43,7 @@ Mit **Filter zurücksetzen** bzw. **Alle entfernen** räumst du sie wieder auf. - **Ansicht wechseln:** Raster / Tabelle / Zeilen. - **Dichte:** gemütlich / kompakt (Schieberegler). -Deine Auswahl wird gespeichert — lokal im Browser und für angemeldete Nutzer:innen +Deine Auswahl wird gespeichert — lokal im Browser und für angemeldete Nutzer zusätzlich serverseitig in den Präferenzen. Ansicht, Dichte, Suche, Filter und Sortierung werden dabei in die URL übernommen, sodass du Ergebnisse teilen kannst. @@ -54,12 +54,12 @@ In der Tabellenansicht sind die Spalten **Tool**, **Bewertung** und **Anzahl Bewertungen** sortierbar. Beim Überfahren einer Zeile erscheint eine Vorschau mit Bewertungsdetails, Tags und Mini-Balken. -## Auswählen für Vergleich & Watchlist +## Auswählen für Vergleich & Merkliste - Auf jeder Karte/Zeile findest du ein **Vergleichs-Icon**, mit dem du Tools zur [Vergleichsleiste](/docs/handbook/vergleichen) hinzufügst. - Das **Lesezeichen-Icon** speichert Tools in deiner - [Watchlist](/docs/handbook/watchlist) (nur mit dem entsprechenden Tarif). + [Merkliste](/docs/handbook/watchlist) (nur mit dem entsprechenden Tarif). ## API diff --git a/docs/releases/v0.8.1/handbook/tools-finden.en.md b/docs/releases/v0.9.0/handbook/tools-finden.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/tools-finden.en.md rename to docs/releases/v0.9.0/handbook/tools-finden.en.md diff --git a/docs/releases/v0.8.1/handbook/vergleichen.md b/docs/releases/v0.9.0/handbook/vergleichen.de.md similarity index 100% rename from docs/releases/v0.8.1/handbook/vergleichen.md rename to docs/releases/v0.9.0/handbook/vergleichen.de.md diff --git a/docs/releases/v0.8.1/handbook/vergleichen.en.md b/docs/releases/v0.9.0/handbook/vergleichen.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/vergleichen.en.md rename to docs/releases/v0.9.0/handbook/vergleichen.en.md diff --git a/docs/releases/v0.8.1/handbook/watchlist.md b/docs/releases/v0.9.0/handbook/watchlist.de.md similarity index 64% rename from docs/releases/v0.8.1/handbook/watchlist.md rename to docs/releases/v0.9.0/handbook/watchlist.de.md index 783da0c..eb25bf1 100644 --- a/docs/releases/v0.8.1/handbook/watchlist.md +++ b/docs/releases/v0.9.0/handbook/watchlist.de.md @@ -1,10 +1,10 @@ -# Watchlist +# Merkliste -Die **Watchlist** ist eine persönliche Favoritenliste. Tools darin kannst du +Die **Merkliste** ist eine persönliche Favoritenliste. Tools darin kannst du jederzeit per Klick wieder aufrufen und vergleichen. -> Die Watchlist ist ein **Premium-Feature** (Premium/Enterprise) und steht +> Die Merkliste ist ein **Premium-Feature** (Premium/Enterprise) und steht > Admins immer zur Verfügung. ## Voraussetzung @@ -17,18 +17,18 @@ beim Lesezeichen ein Hinweis auf den Tarifwechsel - Auf jeder Karte/Zeile im Bereich **Tools durchsuchen** findest du das **Lesezeichen-Icon**. -- Ein Klick speichert das Tool in deiner Watchlist — das Icon wird gefüllt. +- Ein Klick speichert das Tool in deiner Merkliste — das Icon wird gefüllt. - Ein erneuter Klick entfernt es wieder. -## Watchlist ansehen +## Merkliste ansehen -Öffne die Watchlist über das Benutzermenü oder die Seitenleiste. Sie zeigt alle +Öffne die Merkliste über das Benutzermenü oder die Seitenleiste. Sie zeigt alle gespeicherten Tools als Karten. Das gefüllte Lesezeichen auf einer Karte entfernt das Tool aus der Liste. -## Wo wird die Watchlist gespeichert? +## Wo wird die Merkliste gespeichert? -Die Watchlist ist eine Liste von Tool-IDs in deinen **Benutzerpräferenzen**. +Die Merkliste ist eine Liste von Tool-IDs in deinen **Benutzerpräferenzen**. Damit ist sie geräteübergreifend mit deinem Konto verbunden. -API-Referenz: [`GET /auth/me/watchlist`](/docs/reference/endpoints/auth#getMeWatchlist). +API-Referenz: [`GET /auth/me/watchlist`](/docs/reference/endpoints/auth#getMeMerkliste). diff --git a/docs/releases/v0.8.1/handbook/watchlist.en.md b/docs/releases/v0.9.0/handbook/watchlist.en.md similarity index 100% rename from docs/releases/v0.8.1/handbook/watchlist.en.md rename to docs/releases/v0.9.0/handbook/watchlist.en.md diff --git a/docs/releases/v0.7.0/reference.json b/docs/releases/v0.9.0/reference.json similarity index 97% rename from docs/releases/v0.7.0/reference.json rename to docs/releases/v0.9.0/reference.json index a3adfd9..caa9761 100644 --- a/docs/releases/v0.7.0/reference.json +++ b/docs/releases/v0.9.0/reference.json @@ -2206,6 +2206,78 @@ } ] }, + { + "name": "ToolImportBody", + "description": "", + "fields": [ + { + "name": "format", + "type": { + "kind": "type", + "value": "string" + }, + "required": false, + "description": "", + "constraints": "auto, csv, json, yaml" + }, + { + "name": "delimiter", + "type": { + "kind": "type", + "value": "string" + }, + "required": false, + "description": "", + "constraints": "auto, comma, semicolon, tab" + }, + { + "name": "data", + "type": { + "kind": "type", + "value": "string" + }, + "required": true, + "description": "", + "constraints": "" + } + ] + }, + { + "name": "ToolImportResponse", + "description": "", + "fields": [ + { + "name": "imported", + "type": { + "kind": "type", + "value": "integer" + }, + "required": true, + "description": "", + "constraints": "" + }, + { + "name": "total", + "type": { + "kind": "type", + "value": "integer" + }, + "required": true, + "description": "", + "constraints": "" + }, + { + "name": "errors", + "type": { + "kind": "array", + "value": "object" + }, + "required": true, + "description": "", + "constraints": "" + } + ] + }, { "name": "ToolUpdate", "description": "", diff --git a/scripts/src/generate-docs.mjs b/scripts/src/generate-docs.mjs index 4bc6270..26f7132 100644 --- a/scripts/src/generate-docs.mjs +++ b/scripts/src/generate-docs.mjs @@ -25,20 +25,20 @@ const handbookDir = resolve(root, "docs/handbook"); const releasesDir = resolve(root, "docs/releases"); const targetDir = resolve(root, "artifacts/toolrate/public/docs"); -const isReleaseFile = (name) => /^v\d+\.\d+\.\d+\.md$/.test(name); +const isReleaseFile = (name) => /^v\d+\.\d+\.\d+\.de\.md$/.test(name); const isEnReleaseFile = (name) => /^v\d+\.\d+\.\d+\.en\.md$/.test(name); -const isHandbookFile = (name) => /\.md$/.test(name) && !name.endsWith(".en.md"); +const isHandbookFile = (name) => /\.de\.md$/.test(name); const isEnHandbookFile = (name) => /\.en\.md$/.test(name); -const enName = (file) => (file.endsWith(".md") ? `${file.slice(0, -3)}.en.md` : null); -const deName = (file) => (file.endsWith(".en.md") ? `${file.slice(0, -6)}.md` : null); +const enName = (file) => (file.endsWith(".de.md") ? `${file.slice(0, -6)}.en.md` : null); +const deName = (file) => (file.endsWith(".en.md") ? `${file.slice(0, -6)}.de.md` : null); // --------------------------------------------------------------------------- // Version helpers // --------------------------------------------------------------------------- function parseVersion(name) { - return name.replace(/\.md$/, ""); + return name.replace(/\.(de|en)\.md$/, ""); } function cmp(a, b) { @@ -198,7 +198,7 @@ function parseHandbook(content) { } function slugify(name) { - return name.replace(/\.md$/, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-"); + return name.replace(/\.(de|en)?\.md$/, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-"); } async function readFileOptional(path) { @@ -328,7 +328,7 @@ async function buildSearchIndex(reference, handbookPages, releaseVersions) { } for (const version of releaseVersions) { - const file = join(releasesDir, `${version}.md`); + const file = join(releasesDir, `${version}.de.md`); const content = await readFile(file, "utf8"); const base = { title: version, @@ -418,9 +418,9 @@ async function main() { const version = parseVersion(name); const content = await readFile(join(releasesDir, name), "utf8"); await copyFile(join(releasesDir, name), join(targetDir, "releases", name)); - const enName = `${version}.en.md`; - const enContent = await readFileOptional(join(releasesDir, enName)); - if (enContent) await copyFile(join(releasesDir, enName), join(targetDir, "releases", enName)); + const releaseEnName = enName(name); + const enContent = await readFileOptional(join(releasesDir, releaseEnName)); + if (enContent) await copyFile(join(releasesDir, releaseEnName), join(targetDir, "releases", releaseEnName)); const snapDir = join(releasesDir, version); const hasReference = await stat(join(snapDir, "reference.json")) .then(() => true) @@ -459,7 +459,7 @@ async function main() { versions.push({ version, file: `releases/${name}`, - fileEn: enContent ? `releases/${enName}` : null, + fileEn: enContent ? `releases/${releaseEnName}` : null, title: extractTitle(content) ?? version, titleEn: enContent ? extractTitle(enContent) ?? version : null, date: extractDate(content) ?? null,