knowledgebase overhaul

This commit is contained in:
overcuriousity 2025-07-20 22:59:08 +02:00
parent e7800724bb
commit e78e738295
21 changed files with 2575 additions and 1582 deletions

12
.astro/content.d.ts vendored
View File

@ -162,6 +162,16 @@ declare module 'astro:content' {
};
type DataEntryMap = {
"knowledgebase": Record<string, {
id: string;
render(): Render[".md"];
slug: string;
body: string;
collection: "knowledgebase";
data: InferEntrySchema<"knowledgebase">;
rendered?: RenderedContent;
filePath?: string;
}>;
};
@ -194,6 +204,6 @@ declare module 'astro:content' {
LiveContentConfig['collections'][C]['loader']
>;
export type ContentConfig = typeof import("../src/content.config.mjs");
export type ContentConfig = typeof import("../src/content/config.js");
export type LiveContentConfig = never;
}

File diff suppressed because one or more lines are too long

1
.astro/types.d.ts vendored
View File

@ -1 +1,2 @@
/// <reference types="astro/client" />
/// <reference path="content.d.ts" />

215
README.md
View File

@ -4,16 +4,17 @@ Ein kuratiertes Verzeichnis für digitale Forensik- und Incident-Response-Tools
## 🎯 Projektübersicht
CC24-Hub bietet eine strukturierte Übersicht über bewährte DFIR-Tools und -Methoden mit intelligenten Empfehlungsfunktionen. Das Projekt orientiert sich am NIST-Framework (SP 800-86) und kategorisiert nach forensischen Domänen und Untersuchungsphasen.
CC24-Hub bietet eine strukturierte Übersicht über bewährte DFIR-Tools, -Methoden und -Konzepte mit intelligenten Empfehlungsfunktionen. Das Projekt orientiert sich am NIST-Framework (SP 800-86) und kategorisiert nach forensischen Domänen und Untersuchungsphasen.
### Hauptfunktionen
- **KI-gestützte Empfehlungen**: Workflow- und Tool-Vorschläge basierend auf forensischen Szenarien
- **Tools & Methoden**: Software-Tools UND forensische Verfahren/Prozeduren
- **Drei Kategorien**: Software-Tools, forensische Methoden UND Grundlagenkonzepte
- **Matrix-Ansicht**: Visualisierung nach Domänen × Prozess-Phasen
- **Erweiterte Filter**: Suche nach Name, Tags, Domäne, Phase, Lizenz
- **CC24-Server Integration**: Direkte SSO-Links zu gehosteten Instanzen
- **Knowledgebase**: Erweiterte Dokumentation mit praktischen Erkenntnissen
- **Konzept-Verlinkung**: Automatische Verknüpfung zwischen Tools und Grundlagenkonzepten
- **Status-Monitoring**: Live-Überwachung verfügbarer Services
- **Responsive Design**: Dark/Light Mode, Mobile-optimiert
@ -22,7 +23,7 @@ CC24-Hub bietet eine strukturierte Übersicht über bewährte DFIR-Tools und -Me
- **Framework**: [Astro](https://astro.build/) mit Server-Side Rendering
- **Backend**: Node.js mit API-Routen für KI und Authentifizierung
- **Styling**: Vanilla CSS mit CSS Custom Properties
- **Datenformat**: YAML für Tool-/Methoden-Definitionen
- **Datenformat**: YAML für Tool-/Methoden-/Konzept-Definitionen
- **KI-Integration**: Mistral AI über OpenAI-kompatible API
- **Authentifizierung**: OIDC (OpenID Connect) mit JWT-Sessions
- **Node.js**: >=18.0.0
@ -248,16 +249,16 @@ Nextcloud OIDC Einstellungen (sollte auch mit anderen OIDC-Anwendungen klappen):
- **Redirect URI**: `https://your-domain.com/auth/callback`
- **Logout URI**: `https://your-domain.com`
## 🔧 Tool-/Methoden-Datenformat
## 🔧 Datenformat & Kategorien
Einträge werden in `src/data/tools.yaml` definiert:
Die CC24-Hub verwaltet drei Kategorien von Einträgen in `src/data/tools.yaml`:
### Software-Tool Beispiel
### 1. Software-Tools
```yaml
tools:
- name: "Autopsy"
icon: "📱"
icon: "📦"
type: "software"
description: "Die führende Open-Source-Alternative zu kommerziellen Forensik-Suiten"
domains: ["incident-response", "law-enforcement"]
@ -266,18 +267,19 @@ tools:
skillLevel: "intermediate"
accessType: "download"
url: "https://www.autopsy.com/"
projectUrl: "https://autopsy.cc24.dev" # CC24-Server URL
projectUrl: "https://autopsy.cc24.dev" # CC24-Server URL (optional)
license: "Apache 2.0"
knowledgebase: true # Hat erweiterte Dokumentation
related_concepts: ["Hash Functions & Digital Signatures", "SQL Query Fundamentals"] # Verknüpfung zu Konzepten
tags: ["gui", "filesystem", "timeline-analysis"]
statusUrl: "https://status.example.com/badge/1/status"
statusUrl: "https://status.example.com/badge/1/status" # Status-Badge URL (optional)
```
### Forensische Methode Beispiel
### 2. Forensische Methoden
```yaml
- name: "Live Memory Acquisition Procedure"
icon: "🧠"
icon: "📋"
type: "method"
description: "Standardisiertes Verfahren zur forensisch korrekten Akquisition des Arbeitsspeichers"
domains: ["incident-response", "law-enforcement"]
@ -289,9 +291,30 @@ tools:
projectUrl: null
license: null
knowledgebase: false
related_concepts: null # Können optional Konzepte verknüpfen
tags: ["memory-acquisition", "volatile-evidence", "procedure"]
```
### 3. Grundlagenkonzepte (NEU)
```yaml
- name: "Regular Expressions (Regex)"
icon: "🔤"
type: "concept"
description: "Pattern matching language for searching, extracting, and manipulating text"
domains: ["incident-response", "malware-analysis"]
phases: ["examination", "analysis"]
platforms: [] # Konzepte haben keine Plattformen
skillLevel: "intermediate"
accessType: null
url: "https://regexr.com/"
projectUrl: null
license: null
knowledgebase: true # Erweiterte Erklärung in Knowledgebase
related_concepts: null # Konzepte verweisen nicht auf andere Konzepte
tags: ["pattern-matching", "text-processing", "log-analysis"]
```
### Verfügbare Kategorien
**Domänen:**
@ -314,6 +337,135 @@ tools:
- `collaboration-general` - Übergreifend & Kollaboration
- `specific-os` - Betriebssysteme
## 📚 Knowledgebase-System
### Erweiterte Dokumentation erstellen
Die Knowledgebase bietet detaillierte Artikel für Tools, Methoden und Konzepte. So erstellen Sie neue Einträge:
#### 1. Knowledgebase-Flag setzen
Setzen Sie in `src/data/tools.yaml` das Flag:
```yaml
knowledgebase: true
```
#### 2. Artikel-Datei erstellen
Erstellen Sie eine Markdown-Datei in `src/content/knowledgebase/`:
**Dateiname-Schema:** `[tool-name-slug].md`
**Beispiel:** `src/content/knowledgebase/autopsy.md`
```markdown
---
title: "Autopsy - Umfassende Forensik-Suite"
tool_name: "Autopsy"
description: "Detaillierte Anleitung und Best Practices für Autopsy"
last_updated: 2024-01-15
author: "CC24-Team"
difficulty: "intermediate"
categories: ["filesystem-analysis", "timeline-analysis"]
tags: ["gui", "windows", "linux", "open-source"]
sections:
overview: true
installation: true
configuration: true
usage_examples: true
best_practices: true
troubleshooting: true
advanced_topics: false
review_status: "published"
---
# Übersicht
Autopsy ist eine grafische Benutzeroberfläche für The Sleuth Kit (TSK) und bietet...
## Installation
### Windows
1. Download der neuesten Version von [autopsy.com](https://www.autopsy.com/)
2. Ausführung des Installers mit Administratorrechten
3. ...
## Konfiguration
### Grundeinstellungen
- Arbeitsverzeichnis festlegen
- Hash-Algorithmen auswählen
- ...
## Verwendungsbeispiele
### Fall 1: Gelöschte Dateien wiederherstellen
1. Neuen Fall erstellen
2. Image hinzufügen
3. ...
## Best Practices
- Immer Hash-Verifikation durchführen
- Regelmäßige Backups der Case-Datenbank
- ...
## Troubleshooting
### Problem: Autopsy startet nicht
**Lösung:** Java-Version überprüfen...
### Problem: Langsame Performance
**Lösung:** RAM-Zuteilung erhöhen...
## Weiterführende Themen
- Integration mit externen Tools
- Custom Modules entwickeln
- ...
```
#### 3. Schema-Validierung
Das System validiert automatisch folgende Felder:
**Pflichtfelder:**
- `title`: Anzeigename des Artikels
- `tool_name`: Exakter Name aus tools.yaml
- `description`: Kurze Beschreibung
- `last_updated`: Datum der letzten Aktualisierung
- `difficulty`: `novice|beginner|intermediate|advanced|expert`
**Optionale Felder:**
- `author`: Standard "CC24-Team"
- `categories`: Array von Kategorien
- `tags`: Array von Tags
- `sections`: Welche Abschnitte enthalten sind
- `review_status`: `draft|review|published` (Standard: `published`)
#### 4. Automatische Verlinkung
- Artikel sind automatisch über `/knowledgebase/[tool-slug]` erreichbar
- Links werden automatisch in Tool-Details angezeigt
- Suchfunktion indiziert Artikel-Inhalte
### Konzept-Verlinkung
Tools können mit Grundlagenkonzepten verknüpft werden:
```yaml
# Tool-Definition
- name: "Autopsy"
related_concepts: ["Hash Functions & Digital Signatures", "SQL Query Fundamentals"]
# Konzept-Definition
- name: "Hash Functions & Digital Signatures"
type: "concept"
description: "Cryptographic principles for data integrity verification"
```
Die KI-Empfehlungen nutzen diese Verlinkungen für Hintergrundwissen-Empfehlungen.
## 🤖 KI-Integration
### Workflow-Empfehlungen
@ -322,6 +474,9 @@ Beschreibung forensischer Szenarien für maßgeschneiderte Workflows mit phasenb
### Tool-spezifische Empfehlungen
Konkrete Tool-Vorschläge für spezifische Probleme mit detaillierten Begründungen, Implementierungsansätzen und Vor-/Nachteilen.
### Konzept-Integration
Die KI berücksichtigt automatisch verknüpfte Grundlagenkonzepte und empfiehlt relevantes Hintergrundwissen.
**API-Endpunkt:** `/api/ai/query`
- **Rate Limiting**: 10 Anfragen pro Minute pro Benutzer
- **Modi**: `workflow` (Szenario-basiert) oder `tool` (Problem-spezifisch)
@ -338,31 +493,42 @@ OIDC-Integration mit JWT-Sessions:
- `src/utils/auth.ts` - Kern-Authentifizierungslogik
- `src/pages/api/auth/` - Auth-API-Endpunkte
## 📚 Weitere Funktionen
## 📁 Datei-Referenz
### Knowledgebase
Erweiterte Dokumentation für Tools mit `knowledgebase: true` in `/knowledgebase`. Bietet praktische Erkenntnisse, Konfigurationshinweise und Lektionen aus der Praxis.
### Wichtige Konfigurationsdateien
- `src/data/tools.yaml` - Hauptdatenbank für Tools, Methoden und Konzepte
- `src/content/config.ts` - Schema für Knowledgebase-Artikel
- `src/utils/dataService.js` - Datenverarbeitungslogik
- `src/styles/global.css` - Zentrale Stylesheet-Definitionen
### Status-Monitoring
Live-Überwachung gehosteter Services in `/status` mit automatischen Status-Badges und direkten Zugriffs-Links.
### Tool-Editor
Standalone WYSIWYG-Editor unter `/dfir_yaml_editor.html` für die Verwaltung der `tools.yaml` mit Bulk-Operationen und Validierung.
### Content-Verzeichnisse
- `src/content/knowledgebase/` - Knowledgebase-Artikel (Markdown)
- `src/components/` - Wiederverwendbare UI-Komponenten
- `src/pages/api/` - Backend-API-Endpunkte
## 🤝 Beitragen
### Tool/Methode hinzufügen
### Tool/Methode/Konzept hinzufügen
**Option 1: Direkte YAML-Bearbeitung**
1. Fork des Repositories erstellen
2. `src/data/tools.yaml` bearbeiten
3. Pull Request mit Beschreibung erstellen
3. Bei Bedarf Knowledgebase-Artikel erstellen
4. Pull Request mit Beschreibung erstellen
**Option 2: Web-Editor verwenden**
1. YAML-Editor öffnen (`/dfir_yaml_editor.html`)
2. Tool/Methode hinzufügen
2. Eintrag hinzufügen (Tool/Methode/Konzept)
3. YAML exportieren und in Pull Request einreichen
### Knowledgebase-Artikel erweitern
1. Tool in `tools.yaml` identifizieren
2. `knowledgebase: true` setzen
3. Artikel in `src/content/knowledgebase/[slug].md` erstellen
4. Schema-Validierung beachten
5. Pull Request einreichen
### Korrekturen & Verbesserungen
- Bug Reports und Feature Requests über Issues melden
@ -381,6 +547,11 @@ Standalone WYSIWYG-Editor unter `/dfir_yaml_editor.html` für die Verwaltung der
- Redirect-URIs im OIDC-Provider registriert?
- `AUTH_SECRET` mindestens 32 Zeichen?
**Knowledgebase-Artikel werden nicht angezeigt:**
- `knowledgebase: true` in tools.yaml gesetzt?
- Markdown-Datei existiert in `src/content/knowledgebase/`?
- Schema-Validierung erfolgreich?
**Logs prüfen:**
```bash
# Anwendungs-Logs

View File

@ -1,20 +1,16 @@
// astro.config.mjs - SSR configuration for authentication
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
// Server-side rendering for authentication and API routes
output: 'server',
adapter: node({
mode: 'standalone'
}),
// Build configuration
build: {
assets: '_astro'
},
// Development server
server: {
port: 4321,
host: true

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
},
"dependencies": {
"@astrojs/node": "^9.3.0",
"astro": "^5.3.0",
"astro": "^5.12.0",
"cookie": "^0.6.0",
"dotenv": "^16.4.5",
"jose": "^5.2.0",

View File

@ -383,7 +383,45 @@ document.addEventListener('DOMContentLoaded', () => {
return `<p style="margin: 0; line-height: 1.6; color: var(--color-text);">${text}</p>`;
}
// Display results for workflow mode (existing functionality)
// NEW: Function to render background knowledge concepts
function renderBackgroundKnowledge(backgroundKnowledge) {
if (!backgroundKnowledge || backgroundKnowledge.length === 0) {
return '';
}
const conceptLinks = backgroundKnowledge.map(concept => `
<div class="concept-recommendation" style="background-color: var(--color-concept-bg); border: 1px solid var(--color-concept); border-radius: 0.5rem; padding: 1rem; margin-bottom: 0.75rem;">
<div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.5rem;">
<button class="concept-link"
onclick="event.stopPropagation(); window.showToolDetails('${concept.concept_name}', 'secondary')"
style="background: none; border: none; color: var(--color-concept); font-weight: 600; cursor: pointer; text-decoration: underline; font-size: 0.875rem; padding: 0;"
onmouseover="this.style.color='var(--color-concept-hover)';"
onmouseout="this.style.color='var(--color-concept)';">
📚 ${concept.concept_name}
</button>
<span class="badge" style="background-color: var(--color-concept); color: white; font-size: 0.625rem;">Hintergrundwissen</span>
</div>
<p style="margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-secondary);">
${concept.relevance}
</p>
</div>
`).join('');
return `
<div class="card" style="margin-bottom: 2rem; border-left: 4px solid var(--color-concept);">
<h4 style="margin: 0 0 1rem 0; color: var(--color-concept); display: flex; align-items: center; gap: 0.5rem;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
</svg>
Empfohlenes Hintergrundwissen
</h4>
${conceptLinks}
</div>
`;
}
// Display results for workflow mode (ENHANCED with concepts)
function displayWorkflowResults(recommendation, originalQuery) {
// Group tools by phase
const toolsByPhase = {};
@ -434,6 +472,8 @@ document.addEventListener('DOMContentLoaded', () => {
</div>
` : ''}
${renderBackgroundKnowledge(recommendation.background_knowledge)}
${phaseOrder.map((phase, index) => {
const phaseTools = toolsByPhase[phase];
if (phaseTools.length === 0) return '';
@ -540,7 +580,7 @@ document.addEventListener('DOMContentLoaded', () => {
aiResults.appendChild(tempDiv);
}
// Display results for tool-specific mode (new functionality)
// Display results for tool-specific mode (ENHANCED with concepts)
function displayToolResults(recommendation, originalQuery) {
function getSuitabilityText(score) {
const suitabilityTexts = {
@ -597,6 +637,8 @@ document.addEventListener('DOMContentLoaded', () => {
</div>
` : ''}
${renderBackgroundKnowledge(recommendation.background_knowledge)}
<div class="tool-recommendations-grid" style="display: grid; gap: 1.5rem;">
${recommendation.recommended_tools?.map((toolRec, index) => {
const fullTool = tools.find(t => t.name === toolRec.name);

29
src/content/config.ts Normal file
View File

@ -0,0 +1,29 @@
import { defineCollection, z } from 'astro:content';
const knowledgebaseCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
tool_name: z.string(),
description: z.string(),
last_updated: z.date(),
author: z.string().default('CC24-Team'),
difficulty: z.enum(['novice', 'beginner', 'intermediate', 'advanced', 'expert']),
categories: z.array(z.string()).default([]),
tags: z.array(z.string()).default([]),
sections: z.object({
overview: z.boolean().default(true),
installation: z.boolean().default(false),
configuration: z.boolean().default(false),
usage_examples: z.boolean().default(true),
best_practices: z.boolean().default(true),
troubleshooting: z.boolean().default(false),
advanced_topics: z.boolean().default(false),
}).default({}),
review_status: z.enum(['draft', 'review', 'published']).default('published'),
})
});
export const collections = {
knowledgebase: knowledgebaseCollection,
};

View File

@ -0,0 +1,141 @@
---
title: "Kali Linux - Die Hacker-Distribution für Forensik & Penetration Testing"
tool_name: "Kali Linux"
description: "Leitfaden zur Installation, Nutzung und Best Practices für Kali Linux die All-in-One-Plattform für Security-Profis."
last_updated: 2025-07-20
author: "CC24-Team"
difficulty: "intermediate"
categories: ["incident-response", "forensics", "penetration-testing"]
tags: ["live-boot", "tool-collection", "penetration-testing", "forensics-suite", "virtualization", "arm-support"]
sections:
overview: true
installation: true
configuration: true
usage_examples: true
best_practices: true
troubleshooting: true
advanced_topics: true
review_status: "published"
---
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
# Übersicht
Kali Linux ist eine auf Debian basierende Linux-Distribution, die speziell für Penetration Testing, digitale Forensik, Reverse Engineering und Incident Response entwickelt wurde. Mit über 600 vorinstallierten Tools ist sie ein unverzichtbares Werkzeug für Security-Experten, Ermittler und forensische Analysten. Die Live-Boot-Funktion erlaubt es, Systeme ohne Spuren zu hinterlassen zu analysieren ideal für forensische Untersuchungen.
## Installation
### Option 1: Live-System (USB/DVD)
1. ISO-Image von [kali.org](https://www.kali.org/get-kali/) herunterladen.
2. Mit **Rufus** oder **balenaEtcher** auf einen USB-Stick schreiben.
3. Vom USB-Stick booten (ggf. Boot-Reihenfolge im BIOS anpassen).
4. Kali kann direkt ohne Installation im Live-Modus verwendet werden.
### Option 2: Installation auf Festplatte
1. ISO-Image booten und **Graphical Install** wählen.
2. Schritt-für-Schritt durch den Installationsassistenten navigieren:
- Sprache, Zeitzone und Tastaturlayout auswählen
- Partitionierung konfigurieren (automatisch oder manuell)
- Benutzerkonten erstellen
3. Nach Installation Neustart durchführen.
### Option 3: Virtuelle Maschine (VM)
- Offizielle VM-Images für VirtualBox und VMware von der [Kali-Website](https://www.kali.org/get-kali/#kali-virtual-machines)
- Importieren, ggf. Netzwerkbrücke und Shared Folders aktivieren
## Konfiguration
### Netzwerkeinstellungen
- Konfiguration über `nmtui` oder `/etc/network/interfaces`
- VPN und Proxy-Integration über GUI oder Terminal
### Updates & Paketquellen
```bash
sudo apt update && sudo apt full-upgrade
````
> Hinweis: `kali-rolling` ist die Standard-Distribution für kontinuierliche Updates.
### Sprache & Lokalisierung
```bash
sudo dpkg-reconfigure locales
sudo dpkg-reconfigure keyboard-configuration
```
## Verwendungsbeispiele
### 1. Netzwerkscan mit Nmap
```bash
nmap -sS -T4 -A 192.168.1.0/24
```
### 2. Passwort-Cracking mit John the Ripper
```bash
john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
```
### 3. Forensik mit Autopsy
```bash
autopsy &
```
### 4. Android-Analyse mit MobSF (in Docker)
```bash
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p 8000:8000 mobsf
```
## Best Practices
* Nutze immer **aktuelle Snapshots** oder VM-Clones vor gefährlichen Tests
* Verwende separate Netzwerke (z.B. Host-only oder NAT) für Tests
* Deaktiviere automatisches WLAN bei forensischen Analysen
* Prüfe und aktualisiere regelmäßig Toolsets (`apt`, `git`, `pip`)
* Halte deine ISO-Images versioniert für forensische Reproduzierbarkeit
## Troubleshooting
### Problem: Keine Internetverbindung nach Installation
**Lösung:** Netzwerkadapter prüfen, ggf. mit `ifconfig` oder `ip a` überprüfen, DHCP aktivieren.
### Problem: Tools fehlen nach Update
**Lösung:** Tool-Gruppen wie `kali-linux-default` manuell nachinstallieren:
```bash
sudo apt install kali-linux-default
```
### Problem: „Permission Denied“ bei Tools
**Lösung:** Root-Rechte nutzen oder mit `sudo` ausführen.
## Weiterführende Themen
* **Kustomisierung von Kali ISOs** mit `live-build`
* **NetHunter**: Kali für mobile Geräte (Android)
* **Kali Purple**: Defensive Security Suite
* Integration mit **Cloud-Infrastrukturen** via WSL oder Azure
---
**Links & Ressourcen:**
* Offizielle Website: [https://kali.org](https://kali.org/)
* Dokumentation: [https://docs.kali.org/](https://docs.kali.org/)
* GitLab Repo: [https://gitlab.com/kalilinux](https://gitlab.com/kalilinux)
* Discord-Community: [https://discord.com/invite/kali-linux](https://discord.com/invite/kali-linux)

View File

@ -0,0 +1,133 @@
---
title: "MISP - Plattform für Threat Intelligence Sharing"
tool_name: "MISP"
description: "Das Rückgrat des modernen Threat-Intelligence-Sharings mit über 40.000 aktiven Instanzen weltweit."
last_updated: 2025-07-20
author: "CC24-Team"
difficulty: "intermediate"
categories: ["incident-response", "law-enforcement", "malware-analysis", "network-forensics", "cloud-forensics"]
tags: ["web-based", "threat-intelligence", "api", "correlation", "ioc-sharing", "automation"]
sections:
overview: true
installation: true
configuration: true
usage_examples: true
best_practices: true
troubleshooting: true
advanced_topics: false
review_status: "published"
---
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
# Übersicht
**MISP (Malware Information Sharing Platform & Threat Sharing)** ist eine freie Open-Source-Plattform zur strukturierten Erfassung, Speicherung, Analyse und gemeinsamen Nutzung von Cyber-Bedrohungsdaten. Mit über 40.000 Instanzen weltweit ist MISP der De-facto-Standard für den Austausch von Indicators of Compromise (IoCs) und Threat Intelligence zwischen CERTs, SOCs, Strafverfolgungsbehörden und anderen sicherheitsrelevanten Organisationen.
Die föderierte Architektur ermöglicht einen kontrollierten, dezentralen Austausch von Informationen über vertrauenswürdige Partner hinweg. Durch Taxonomien, Tags und integrierte APIs ist eine automatische Anreicherung, Korrelation und Verarbeitung von Informationen in SIEMs, Firewalls oder Endpoint-Lösungen möglich.
## Installation
### Voraussetzungen
- **Server-Betriebssystem:** Linux (empfohlen: Debian/Ubuntu)
- **Abhängigkeiten:** MariaDB/MySQL, PHP, Apache/Nginx, Redis
- **Ressourcen:** Mindestens 4 GB RAM, SSD empfohlen
### Installationsschritte
```bash
# Beispiel für Debian/Ubuntu:
sudo apt update && sudo apt install -y curl gnupg git python3 python3-pip redis-server mariadb-server apache2 php libapache2-mod-php
# MISP klonen
git clone https://github.com/MISP/MISP.git /var/www/MISP
# Setup-Skript nutzen
cd /var/www/MISP && bash INSTALL/INSTALL.debian.sh
````
Weitere Details: [Offizielle Installationsanleitung](https://misp.github.io/MISP/INSTALL.debian/)
## Konfiguration
### Webserver
* HTTPS aktivieren (Let's Encrypt oder Reverse Proxy)
* PHP-Konfiguration anpassen (`upload_max_filesize`, `memory_limit`, `post_max_size`)
### Benutzerrollen
* Administrator, Org-Admin, Analyst etc.
* Zugriffsbeschränkungen nach Organisation/Feed definierbar
### Feeds und Galaxies
* Aktivierung von Feeds (z.B. CIRCL, Abuse.ch, OpenCTI)
* Nutzung von Galaxies zur Klassifizierung (APT-Gruppen, Malware-Familien)
## Verwendungsbeispiele
### Beispiel 1: Import von IoCs aus externem Feed
1. Feed aktivieren unter **Administration → List Feeds**
2. Feed synchronisieren
3. Ereignisse durchsuchen, analysieren, ggf. mit eigenen Daten korrelieren
### Beispiel 2: Automatisierte Anbindung an SIEM
* REST-API-Token erstellen
* API-Calls zur Abfrage neuer Events (z.B. mit Python, Logstash oder MISP Workbench)
* Integration in Security-Systeme über JSON/STIX export
## Best Practices
* Regelmäßige Backups der Datenbank
* Taxonomien konsistent verwenden
* Nutzung der Sighting-Funktion zur Validierung von IoCs
* Vertrauensstufen (TLP, PAP) korrekt setzen
* Nicht nur konsumieren auch teilen!
## Troubleshooting
### Problem: MISP-Feeds laden nicht
**Lösung:**
* Internetverbindung prüfen
* Cronjobs aktiv?
* Logs prüfen: `/var/www/MISP/app/tmp/logs/error.log`
### Problem: API gibt 403 zurück
**Lösung:**
* Ist der API-Key korrekt und aktiv?
* Rechte des Benutzers überprüfen
* IP-Filter im MISP-Backend beachten
### Problem: Hohe Datenbanklast
**Lösung:**
* Indizes optimieren
* Redis aktivieren
* Alte Events regelmäßig archivieren oder löschen
## Weiterführende Themen
* STIX2-Import/Export
* Erweiterungen mit MISP Modules (z.B. für Virustotal, YARA)
* Föderierte Netzwerke und Community-Portale
* Integration mit OpenCTI oder TheHive
---
**Links:**
* 🌐 [Offizielle Projektseite](https://misp-project.org/)
* 📦 [CC24-MISP-Instanz](https://misp.cc24.dev)
* 📊 [Status-Monitoring](https://status.mikoshi.de/api/badge/34/status)
Lizenz: **AGPL-3.0**

View File

@ -0,0 +1,124 @@
---
title: "Nextcloud - Sichere Kollaborationsplattform"
tool_name: "Nextcloud"
description: "Detaillierte Anleitung und Best Practices für Nextcloud in forensischen Einsatzszenarien"
last_updated: 2025-07-20
author: "CC24-Team"
difficulty: "novice"
categories: ["collaboration-general"]
tags: ["web-based", "collaboration", "file-sharing", "api", "encryption", "document-management"]
sections:
overview: true
installation: true
configuration: true
usage_examples: true
best_practices: true
troubleshooting: true
advanced_topics: false
review_status: "published"
---
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
# Übersicht
Nextcloud ist eine Open-Source-Cloud-Suite, die speziell für die sichere Zusammenarbeit entwickelt wurde. Sie eignet sich ideal für forensische Teams, da sie eine DSGVO-konforme Umgebung mit verschlüsselter Dateiablage, Office-Integration und Videokonferenzen bereitstellt. Zusätzlich bietet Nextcloud einen integrierten SSO-Provider, der das Identitätsmanagement für andere forensische Tools stark vereinfacht.
Skalierbar von kleinen Raspberry-Pi-Installationen bis hin zu hochverfügbaren Multi-Node-Setups.
- **Website:** [nextcloud.com](https://nextcloud.com/)
- **Demo/Projektinstanz:** [cloud.cc24.dev](https://cloud.cc24.dev)
- **Statusseite:** [Mikoshi Status](https://status.mikoshi.de/api/badge/11/status)
- **Lizenz:** AGPL-3.0
---
## Installation
### Voraussetzungen
- Linux-Server oder Raspberry Pi
- PHP 8.1 oder höher
- MariaDB/PostgreSQL
- Webserver (Apache/Nginx)
- SSL-Zertifikat (empfohlen: Let's Encrypt)
### Installationsschritte (Ubuntu Beispiel)
```bash
sudo apt update && sudo apt upgrade
sudo apt install apache2 mariadb-server libapache2-mod-php php php-mysql \
php-gd php-xml php-mbstring php-curl php-zip php-intl php-bcmath unzip
wget https://download.nextcloud.com/server/releases/latest.zip
unzip latest.zip -d /var/www/
chown -R www-data:www-data /var/www/nextcloud
````
Danach den Web-Installer im Browser aufrufen (`https://<your-domain>/nextcloud`) und Setup abschließen.
## Konfiguration
* **Trusted Domains** in `config.php` definieren
* SSO mit OpenID Connect aktivieren
* Dateiverschlüsselung aktivieren (`Settings → Security`)
* Benutzer und Gruppen über LDAP oder SAML integrieren
## Verwendungsbeispiele
### Gemeinsame Fallbearbeitung
1. Ermittlungsordner als geteiltes Gruppenverzeichnis anlegen
2. Versionierung und Kommentare zu forensischen Berichten aktivieren
3. Vorschau für Office-Dateien, PDFs und Bilder direkt im Browser nutzen
### Videokonferenzen mit "Nextcloud Talk"
* Sichere Kommunikation zwischen Ermittlern und Sachverständigen
* Ende-zu-Ende-verschlüsselt
* Bildschirmfreigabe möglich
### Automatischer Dateiimport per API
* REST-Schnittstelle nutzen, um z.B. automatisch Logdateien oder Exportdaten hochzuladen
* Ideal für Anbindung an SIEM, DLP oder Analyse-Pipelines
## Best Practices
* Zwei-Faktor-Authentifizierung aktivieren
* Tägliche Backups der Datenbank und Datenstruktur
* Nutzung von OnlyOffice oder Collabora für revisionssichere Dokumentenbearbeitung
* Zugriff regelmäßig überprüfen, insbesondere bei externen Partnern
## Troubleshooting
### Problem: Langsame Performance
**Lösung:** APCu aktivieren und Caching optimieren (`config.php → 'memcache.local'`).
### Problem: Dateien erscheinen nicht im Sync
**Lösung:** Cronjob für `files:scan` konfigurieren oder manuell ausführen:
```bash
sudo -u www-data php /var/www/nextcloud/occ files:scan --all
```
### Problem: Fehlermeldung "Trusted domain not set"
**Lösung:** In `config/config.php` Eintrag `trusted_domains` korrekt konfigurieren:
```php
'trusted_domains' =>
array (
0 => 'yourdomain.tld',
1 => 'cloud.cc24.dev',
),
```
## Weiterführende Themen
* **Integration mit Forensik-Plattformen** (über WebDAV, API oder SSO)
* **Custom Apps entwickeln** für spezielle Ermittlungs-Workflows
* **Auditing aktivieren**: Nutzung und Änderungen nachvollziehen mit Protokollierungsfunktionen

View File

@ -0,0 +1,110 @@
---
title: "Regular Expressions (Regex) Musterbasierte Textanalyse"
tool_name: "Regular Expressions (Regex)"
description: "Pattern matching language für Suche, Extraktion und Manipulation von Text in forensischen Analysen."
last_updated: 2025-07-20
author: "CC24-Team"
difficulty: "intermediate"
categories: ["incident-response", "malware-analysis", "network-forensics", "fraud-investigation"]
tags: ["pattern-matching", "text-processing", "log-analysis", "string-manipulation", "search-algorithms"]
sections:
overview: true
installation: false
configuration: false
usage_examples: true
best_practices: true
troubleshooting: false
advanced_topics: true
review_status: "published"
---
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
# Übersicht
**Regular Expressions (Regex)** sind ein leistungsfähiges Werkzeug zur Erkennung, Extraktion und Transformation von Zeichenfolgen anhand vordefinierter Muster. In der digitalen Forensik sind Regex-Ausdrücke unverzichtbar: Sie helfen beim Auffinden von IP-Adressen, Hash-Werten, Dateipfaden, Malware-Signaturen oder Kreditkartennummern in großen Mengen unstrukturierter Daten wie Logdateien, Netzwerktraces oder Memory Dumps.
Regex ist nicht auf eine bestimmte Plattform oder Software beschränkt es wird in nahezu allen gängigen Programmiersprachen, Texteditoren und forensischen Tools unterstützt.
## Verwendungsbeispiele
### 1. IP-Adressen extrahieren
```regex
\b(?:\d{1,3}\.){3}\d{1,3}\b
````
Verwendung:
* Finden von IP-Adressen in Firewall-Logs oder Packet Captures.
* Beispiel-Zeile:
```
Connection from 192.168.1.101 to port 443 established
```
### 2. E-Mail-Adressen identifizieren
```regex
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
```
Verwendung:
* Erkennung von kompromittierten Accounts in Phishing-E-Mails.
* Analyse von Useraktivitäten oder Kommunikationsverläufen.
### 3. Hash-Werte erkennen (z.B. SHA-256)
```regex
\b[A-Fa-f0-9]{64}\b
```
Verwendung:
* Extraktion von Malware-Hashes aus Memory Dumps oder YARA-Logs.
### 4. Zeitstempel in Logdateien extrahieren
```regex
\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}
```
Verwendung:
* Zeitsensitive Korrelationsanalysen (z.B. bei Intrusion Detection oder Timeline-Rekonstruktionen).
## Best Practices
* **Regex testen**: Nutze Plattformen wie [regexr.com](https://regexr.com/) oder [regex101.com](https://regex101.com/) zur Validierung.
* **Performance beachten**: Komplexe Ausdrücke können ineffizient sein und Systeme verlangsamen verwende Lazy Quantifiers (`*?`, `+?`) bei Bedarf.
* **Escape-Zeichen korrekt anwenden**: Spezielle Zeichen wie `.` oder `\` müssen bei Bedarf mit `\\` oder `\.` maskiert werden.
* **Portabilität prüfen**: Unterschiedliche Regex-Engines (z.B. Python `re`, PCRE, JavaScript) interpretieren manche Syntax leicht unterschiedlich.
* **Lesbarkeit fördern**: Verwende benannte Gruppen (`(?P<name>...)`) und Kommentare (`(?x)`), um reguläre Ausdrücke besser wartbar zu machen.
## Weiterführende Themen
### Lookaheads und Lookbehinds
Mit **Lookaheads** (`(?=...)`) und **Lookbehinds** (`(?<=...)`) können Bedingungen formuliert werden, ohne dass der Text Teil des Matchs wird.
Beispiel: Alle `.exe`-Dateinamen **ohne** das Wort `safe` davor matchen:
```regex
(?<!safe\s)[\w-]+\.exe
```
### Regex in Forensik-Tools
* **YARA**: Unterstützt Regex zur Erstellung von Malware-Signaturen.
* **Wireshark**: Filtert Payloads anhand von Regex-ähnlicher Syntax.
* **Splunk & ELK**: Verwenden Regex für Logparsing und Visualisierung.
* **Volatility Plugins**: Extrahieren Artefakte mit Regex-basierten Scans.
---
> 🔤 **Regex ist ein universelles Werkzeug für Analysten, Ermittler und Entwickler, um versteckte Informationen schnell und flexibel aufzuspüren.**
>
> Nutze es überall dort, wo Textdaten eine Rolle spielen.

View File

@ -0,0 +1,161 @@
---
title: "Velociraptor Skalierbare Endpoint-Forensik mit VQL"
tool_name: "Velociraptor"
description: "Detaillierte Anleitung und Best Practices für Velociraptor Remote-Forensik der nächsten Generation"
last_updated: 2025-07-20
author: "CC24-Team"
difficulty: "advanced"
categories: ["incident-response", "malware-analysis", "network-forensics"]
tags: ["web-based", "endpoint-monitoring", "artifact-extraction", "scripting", "live-forensics", "hunting"]
sections:
overview: true
installation: true
configuration: true
usage_examples: true
best_practices: true
troubleshooting: true
advanced_topics: true
review_status: "published"
---
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
# Übersicht
Velociraptor ist ein Open-Source-Tool zur Endpoint-Forensik mit Fokus auf Skalierbarkeit, Präzision und Geschwindigkeit. Es ermöglicht die zielgerichtete Erfassung und Analyse digitaler Artefakte über eine eigene Query Language VQL (Velociraptor Query Language). Die Architektur erlaubt remote Zugriff auf tausende Endpoints gleichzeitig, ohne dass vollständige Disk-Images erforderlich sind.
## Hauptmerkmale
- 🌐 Web-basierte Benutzeroberfläche
- 💡 VQL mächtige, SQL-ähnliche Abfragesprache
- 🚀 Hochskalierbare Hunt-Funktionalität
- 🔍 Artefaktbasierte Sammlung (ohne Full-Image)
- 🖥️ Plattformunterstützung für Windows, macOS, Linux
- 📦 Apache 2.0 Lizenz Open Source
Weitere Infos: [velociraptor.app](https://www.velociraptor.app/)
Projektspiegel: [raptor.cc24.dev](https://raptor.cc24.dev)
Status: ![Status](https://status.mikoshi.de/api/badge/33/status)
---
## Installation
### Voraussetzungen
- Python ≥ 3.9
- Adminrechte auf dem System
- Firewall-Freigaben für Webport (Standard: 8000)
### Installation unter Linux/macOS
```bash
wget https://github.com/Velocidex/velociraptor/releases/latest/download/velociraptor
chmod +x velociraptor
sudo mv velociraptor /usr/local/bin/
````
### Installation unter Windows
1. Download der `.exe` von der [Release-Seite](https://github.com/Velocidex/velociraptor/releases)
2. Ausführung in PowerShell mit Adminrechten:
```powershell
.\velociraptor.exe config generate > server.config.yaml
```
---
## Konfiguration
### Server Setup
1. Generiere die Konfigurationsdatei:
```bash
velociraptor config generate > server.config.yaml
```
2. Starte den Server:
```bash
velociraptor --config server.config.yaml frontend
```
3. Zugriff über Browser via `https://<hostname>:8000`
### Client Deployment
* MSI/EXE für Windows, oder `deb/rpm` für Linux
* Unterstützt automatische Registrierung am Server
* Deployment über GPO, Puppet, Ansible etc. möglich
---
## Verwendungsbeispiele
### 1. Live-Memory-Artefakte sammeln
```vql
SELECT * FROM Artifact.MemoryInfo()
```
### 2. Hunt starten auf verdächtige Prozesse
```vql
SELECT * FROM pslist()
WHERE Name =~ "mimikatz|cobaltstrike"
```
### 3. Dateiinhalt extrahieren
```vql
SELECT * FROM glob(globs="C:\\Users\\*\\AppData\\*.dat")
```
---
## Best Practices
* Erstelle eigene Artefakte für unternehmensspezifische Bedrohungsmodelle
* Verwende "Notebook"-Funktion für strukturierte Analysen
* Nutze "Labels", um Endpoints zu organisieren (z.B. `location:Berlin`)
* Kombiniere Velociraptor mit SIEM/EDR-Systemen über REST API
---
## Troubleshooting
### Problem: Keine Verbindung vom Client zum Server
**Lösung:**
* Ports freigegeben? (Default: 8000/tcp)
* TLS-Zertifikate korrekt generiert?
* `server.config.yaml` auf korrekte `public_ip` prüfen
### Problem: Hunt hängt in Warteschleife
**Lösung:**
* Genügend Worker-Prozesse aktiv?
* Endpoint online?
* `log_level` auf `debug` setzen und Log analysieren
---
## Weiterführende Themen
* Eigene Artefakte schreiben mit VQL
* Integration mit ELK Stack
* Automatisiertes Incident Response Playbook
* Velociraptor als IR-as-a-Service einsetzen
---
🧠 **Tipp:** Die Lernkurve bei VQL ist steil aber mit hohem ROI. Testumgebung aufsetzen und mit Community-Artefakten starten.
📚 Weitere Ressourcen:
* [Offizielle Doku](https://docs.velociraptor.app/)
* [YouTube Channel](https://www.youtube.com/c/VelociraptorDFIR)
* [Community auf Discord](https://www.velociraptor.app/community/)

View File

@ -1,6 +1,5 @@
tools:
- name: Autopsy
icon: 📦
type: software
description: >-
Die führende Open-Source-Alternative zu kommerziellen Forensik-Suiten mit
@ -9,6 +8,16 @@ tools:
Plugin-Architektur erlaubt Erweiterungen für spezielle
Untersuchungsszenarien. Zwar komplexer als kommerzielle Lösungen, aber
dafür vollständig transparent und kostenfrei.
skillLevel: intermediate
url: https://www.autopsy.com/
tags:
- gui
- filesystem
- timeline-analysis
- carving
- artifact-extraction
- keyword-search
icon: 📦
domains:
- incident-response
- law-enforcement
@ -18,26 +27,15 @@ tools:
phases:
- examination
- analysis
related_concepts:
- SQL Query Fundamentals
- Hash Functions & Digital Signatures
platforms:
- Windows
- Linux
related_concepts:
- "SQL Query Fundamentals"
- "Hash Functions & Digital Signatures"
domain-agnostic-software: null
skillLevel: intermediate
accessType: download
url: https://www.autopsy.com/
projectUrl: ''
accessType: Download
license: Apache 2.0
knowledgebase: false
tags:
- gui
- filesystem
- timeline-analysis
- carving
- artifact-extraction
- keyword-search
- name: Volatility 3
icon: 📦
type: software
@ -62,8 +60,8 @@ tools:
- Linux
- macOS
related_concepts:
- "Hash Functions & Digital Signatures"
- "Regular Expressions (Regex)"
- Hash Functions & Digital Signatures
- Regular Expressions (Regex)
domain-agnostic-software: null
skillLevel: advanced
accessType: download
@ -170,8 +168,8 @@ tools:
platforms:
- Web
related_concepts:
- "Regular Expressions (Regex)"
- "SQL Query Fundamentals"
- Regular Expressions (Regex)
- SQL Query Fundamentals
domain-agnostic-software: null
skillLevel: intermediate
accessType: server-based
@ -609,7 +607,7 @@ tools:
- Linux
- macOS
related_concepts:
- "Regular Expressions (Regex)"
- Regular Expressions (Regex)
domain-agnostic-software: null
skillLevel: novice
accessType: download
@ -682,7 +680,7 @@ tools:
- macOS
- Web
related_concepts:
- "SQL Query Fundamentals"
- SQL Query Fundamentals
domain-agnostic-software: null
skillLevel: intermediate
accessType: server-based
@ -973,7 +971,7 @@ tools:
platforms:
- Windows
related_concepts:
- "Hash Functions & Digital Signatures"
- Hash Functions & Digital Signatures
domain-agnostic-software: null
skillLevel: beginner
accessType: download
@ -1005,7 +1003,7 @@ tools:
platforms:
- Linux
related_concepts:
- "Hash Functions & Digital Signatures"
- Hash Functions & Digital Signatures
domain-agnostic-software: null
skillLevel: novice
accessType: download
@ -1072,7 +1070,7 @@ tools:
- Linux
- macOS
related_concepts:
- "SQL Query Fundamentals"
- SQL Query Fundamentals
domain-agnostic-software: null
skillLevel: intermediate
accessType: download
@ -1240,7 +1238,7 @@ tools:
platforms:
- Linux
related_concepts:
- "Hash Functions & Digital Signatures"
- Hash Functions & Digital Signatures
domain-agnostic-software: null
skillLevel: intermediate
accessType: download
@ -1480,8 +1478,8 @@ tools:
- Linux
- macOS
related_concepts:
- "Regular Expressions (Regex)"
- "Hash Functions & Digital Signatures"
- Regular Expressions (Regex)
- Hash Functions & Digital Signatures
accessType: download
license: BSD-3-Clause
knowledgebase: false
@ -1504,7 +1502,7 @@ tools:
- Linux
- macOS
related_concepts:
- "Regular Expressions (Regex)"
- Regular Expressions (Regex)
domain-agnostic-software: null
skillLevel: novice
accessType: built-in
@ -1977,9 +1975,10 @@ tools:
icon: 🔤
type: concept
description: >-
Pattern matching language for searching, extracting, and manipulating text.
Essential for log analysis, malware signature creation, and data extraction from
unstructured sources. Forms the backbone of many forensic tools and custom scripts.
Pattern matching language for searching, extracting, and manipulating
text. Essential for log analysis, malware signature creation, and data
extraction from unstructured sources. Forms the backbone of many forensic
tools and custom scripts.
domains:
- incident-response
- malware-analysis
@ -1996,21 +1995,21 @@ tools:
url: https://regexr.com/
projectUrl: null
license: null
knowledgebase: false
knowledgebase: true
tags:
- pattern-matching
- text-processing
- log-analysis
- string-manipulation
- search-algorithms
- name: SQL Query Fundamentals
icon: 🗃️
type: concept
description: >-
Structured Query Language for database interrogation and analysis. Critical for
examining application databases, SQLite artifacts from mobile devices, and
browser history databases. Enables complex correlation and filtering of large datasets.
Structured Query Language for database interrogation and analysis.
Critical for examining application databases, SQLite artifacts from
mobile devices, and browser history databases. Enables complex
correlation and filtering of large datasets.
domains:
- incident-response
- mobile-forensics
@ -2034,14 +2033,14 @@ tools:
- data-correlation
- mobile-artifacts
- browser-forensics
- name: Hash Functions & Digital Signatures
icon: 🔐
type: concept
description: >-
Cryptographic principles for data integrity verification and authentication.
Fundamental for evidence preservation, malware identification, and establishing
chain of custody. Understanding of MD5, SHA, and digital signature validation.
Cryptographic principles for data integrity verification and
authentication. Fundamental for evidence preservation, malware
identification, and establishing chain of custody. Understanding of MD5,
SHA, and digital signature validation.
domains:
- incident-response
- law-enforcement

12
src/env.d.ts vendored
View File

@ -9,10 +9,16 @@ declare global {
getStoredTheme: () => string;
};
toolsData: any[];
showToolDetails: (toolName: string) => void;
hideToolDetails: () => void;
showToolDetails: (toolName: string, modalType?: string) => void;
hideToolDetails: (modalType?: string) => void;
hideAllToolDetails: () => void;
toggleKbEntry: (entryId: string) => void;
toggleDomainAgnosticSection: (sectionId: string) => void;
restoreAIResults?: () => void;
switchToAIView?: () => void;
clearTagFilters?: () => void;
clearAllFilters?: () => void;
}
}
// Also declare the modules that might not be recognized

View File

@ -94,6 +94,17 @@ function createWorkflowSystemPrompt(toolsData: any): string {
skillLevel: tool.skillLevel,
license: tool.license,
tags: tool.tags,
related_concepts: tool.related_concepts || []
}));
// NEW: Include concepts for background knowledge
const conceptsList = toolsData.concepts.map((concept: any) => ({
name: concept.name,
description: concept.description,
domains: concept.domains,
phases: concept.phases,
skillLevel: concept.skillLevel,
tags: concept.tags
}));
// Get regular phases (no more filtering needed)
@ -135,9 +146,12 @@ function createWorkflowSystemPrompt(toolsData: any): string {
return `Du bist ein DFIR (Digital Forensics and Incident Response) Experte, der Ermittlern bei der Auswahl von Software und Methoden hilft.
VERFÜGBARE DATENBASIS:
VERFÜGBARE TOOLS/METHODEN:
${JSON.stringify(toolsList, null, 2)}
VERFÜGBARE HINTERGRUNDWISSEN-KONZEPTE:
${JSON.stringify(conceptsList, null, 2)}
UNTERSUCHUNGSPHASEN (NIST Framework):
${phasesDescription}
@ -152,6 +166,8 @@ WICHTIGE REGELN:
5. Deutsche Antworten für deutsche Anfragen, English for English queries
6. Bewerbe NIEMALS Proprietäre Software fälschlicherweise als Open-Source-Software, erkenne aber an, falls diese besser geeignet sein könnte.
7. Bevorzuge alles, was nicht proprietär ist (license != "Proprietary"), aber erkenne an, wenn proprietäre Software besser geeignet ist.
8. WICHTIG: Erwähne relevante Hintergrundwissen-Konzepte wenn Tools verwendet werden, die related_concepts haben
9. Konzepte sind NICHT Tools - empfehle sie nicht als actionable Schritte, sondern als Wissensbasis
SOFTWARE/METHODEN-AUSWAHL NACH PHASE:
${phaseDescriptions}
@ -164,13 +180,19 @@ ANTWORT-FORMAT (strict JSON):
"scenario_analysis": "Detaillierte Analyse des Szenarios auf Deutsch/English",
"recommended_tools": [
{
"name": "EXAKTER Name aus der Database",
"name": "EXAKTER Name aus der Tools-Database",
"priority": "high|medium|low",
"phase": "${validPhases}",
"justification": "Warum diese Methode für diese Phase und Szenario geeignet ist"
}
],
"workflow_suggestion": "Vorgeschlagener Untersuchungsablauf",
"background_knowledge": [
{
"concept_name": "EXAKTER Name aus der Konzepte-Database",
"relevance": "Warum dieses Konzept für das Szenario relevant ist, und bei welchen der empfohlenen Methoden/Tools."
}
],
"additional_notes": "Wichtige Überlegungen und Hinweise"
}
@ -189,14 +211,28 @@ function createToolSystemPrompt(toolsData: any): string {
license: tool.license,
tags: tool.tags,
url: tool.url,
projectUrl: tool.projectUrl
projectUrl: tool.projectUrl,
related_concepts: tool.related_concepts || []
}));
// NEW: Include concepts for background knowledge
const conceptsList = toolsData.concepts.map((concept: any) => ({
name: concept.name,
description: concept.description,
domains: concept.domains,
phases: concept.phases,
skillLevel: concept.skillLevel,
tags: concept.tags
}));
return `Du bist ein DFIR (Digital Forensics and Incident Response) Experte, der bei der Auswahl spezifischer Software/Methoden für konkrete Probleme hilft.
VERFÜGBARE DATENBASIS:
VERFÜGBARE TOOLS/METHODEN:
${JSON.stringify(toolsList, null, 2)}
VERFÜGBARE HINTERGRUNDWISSEN-KONZEPTE:
${JSON.stringify(conceptsList, null, 2)}
WICHTIGE REGELN:
1. Analysiere das spezifische Problem/die Anforderung sorgfältig
2. Empfehle 1-3 Tools, sortiert nach Eignung (beste Empfehlung zuerst)
@ -207,13 +243,15 @@ WICHTIGE REGELN:
7. Erwähne sowohl Stärken als auch Schwächen/Limitationen
8. Schlage alternative Ansätze vor, wenn sinnvoll
9. Gib grundsätzliche Hinweise, WIE das Tool konkret eingesetzt wird
10. WICHTIG: Erwähne relevante Hintergrundwissen-Konzepte wenn Tools verwendet werden, die related_concepts haben
11. Konzepte sind NICHT Tools - empfehle sie nicht als actionable Schritte, sondern als Wissensbasis
ANTWORT-FORMAT (strict JSON):
{
"problem_analysis": "Detaillierte Analyse des Problems/der Anforderung",
"recommended_tools": [
{
"name": "EXAKTER Name aus der Database",
"name": "EXAKTER Name aus der Tools-Database",
"rank": 1,
"suitability_score": "high|medium|low",
"detailed_explanation": "Detaillierte Erklärung, warum dieses Tool/diese Methode das Problem löst",
@ -223,6 +261,12 @@ ANTWORT-FORMAT (strict JSON):
"alternatives": "Alternative Ansätze oder ergänzende Tools/Methoden, falls relevant"
}
],
"background_knowledge": [
{
"concept_name": "EXAKTER Name aus der Konzepte-Database",
"relevance": "Warum dieses Konzept für die empfohlenen Tools/das Problem relevant ist, und für welche der empfohlenen Methoden/Tools."
}
],
"additional_considerations": "Wichtige Überlegungen, Voraussetzungen oder Warnungen"
}
@ -353,12 +397,13 @@ export const POST: APIRoute = async ({ request }) => {
});
}
// Validate tool names against database based on mode
// Validate tool names and concept names against database
const validToolNames = new Set(toolsData.tools.map((t: any) => t.name));
const validConceptNames = new Set(toolsData.concepts.map((c: any) => c.name));
let validatedRecommendation;
if (mode === 'workflow') {
// Existing validation for workflow mode
validatedRecommendation = {
...recommendation,
recommended_tools: recommendation.recommended_tools?.filter((tool: any) => {
@ -367,10 +412,16 @@ export const POST: APIRoute = async ({ request }) => {
return false;
}
return true;
}) || [],
background_knowledge: recommendation.background_knowledge?.filter((concept: any) => {
if (!validConceptNames.has(concept.concept_name)) {
console.warn(`AI referenced unknown concept: ${concept.concept_name}`);
return false;
}
return true;
}) || []
};
} else {
// New validation for tool mode
validatedRecommendation = {
...recommendation,
recommended_tools: recommendation.recommended_tools?.filter((tool: any) => {
@ -385,12 +436,19 @@ export const POST: APIRoute = async ({ request }) => {
suitability_score: tool.suitability_score || 'medium', // Default suitability
pros: Array.isArray(tool.pros) ? tool.pros : [],
cons: Array.isArray(tool.cons) ? tool.cons : []
})) || []
})) || [],
background_knowledge: recommendation.background_knowledge?.filter((concept: any) => {
if (!validConceptNames.has(concept.concept_name)) {
console.warn(`AI referenced unknown concept: ${concept.concept_name}`);
return false;
}
return true;
}) || []
};
}
// Log successful query
console.log(`[AI Query] Mode: ${mode}, User: ${userId}, Query length: ${sanitizedQuery.length}, Tools: ${validatedRecommendation.recommended_tools.length}`);
console.log(`[AI Query] Mode: ${mode}, User: ${userId}, Query length: ${sanitizedQuery.length}, Tools: ${validatedRecommendation.recommended_tools.length}, Concepts: ${validatedRecommendation.background_knowledge?.length || 0}`);
return new Response(JSON.stringify({
success: true,

View File

@ -2,11 +2,10 @@
import BaseLayout from '../layouts/BaseLayout.astro';
import { getToolsData } from '../utils/dataService.js';
// Load tools data
const data = await getToolsData();
// Filter tools that have knowledgebase entries
// Filter tools that have knowledgebase flag set to true
const knowledgebaseTools = data.tools.filter((tool: any) => tool.knowledgebase === true);
// Sort alphabetically by name
@ -26,7 +25,7 @@ knowledgebaseTools.sort((a: any, b: any) => a.name.localeCompare(b.name));
</p>
</div>
<!-- Search and Filter -->
<!-- Search -->
<div style="margin-bottom: 2rem;">
<input
type="text"
@ -56,219 +55,167 @@ knowledgebaseTools.sort((a: any, b: any) => a.name.localeCompare(b.name));
</svg>
<h3 style="color: var(--color-text-secondary); margin-bottom: 0.5rem;">Noch keine Knowledgebase-Einträge</h3>
<p class="text-muted">
Knowledgebase-Einträge werden automatisch angezeigt, sobald Datenbankeinträge das Attribut "knowledgebase: true" haben. Wenn hier noch nichts drinsteht, habe ich noch nichts dazu geschrieben.
Knowledgebase-Einträge werden automatisch angezeigt, sobald Datenbankeinträge das Attribut "knowledgebase: true" haben.
</p>
</div>
) : (
<div id="kb-entries">
{knowledgebaseTools.map((tool: any, index: number) => (
<article class="kb-entry card kb-entry-collapsed" id={`kb-${tool.name.toLowerCase().replace(/\s+/g, '-')}`} data-tool-name={tool.name.toLowerCase()}>
<!-- Collapsed Header (default state) -->
<div class="kb-entry-header" onclick={`toggleKbEntry('${tool.name.toLowerCase().replace(/\s+/g, '-')}')`} style="cursor: pointer;">
{knowledgebaseTools.map((tool: any, index: number) => {
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
const toolSlug = tool.name.toLowerCase()
.replace(/[^a-z0-9\s-]/g, '') // Remove special characters
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/-+/g, '-') // Remove duplicate hyphens
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
return (
<article
class="kb-entry card"
id={`kb-${toolSlug}`}
data-tool-name={tool.name.toLowerCase()}
>
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="display: flex; align-items: center; gap: 1rem;">
<h3 style="margin: 0; color: var(--color-primary);">{tool.name}</h3>
<div style="display: flex; gap: 0.5rem;">
{(() => {
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
return (
<>
<h3 style="margin: 0; color: var(--color-primary);">
{tool.icon && <span style="margin-right: 0.5rem;">{tool.icon}</span>}
{tool.name}
</h3>
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
<!-- Type indicator badges -->
{tool.type === 'concept' && <span class="badge" style="background-color: var(--color-concept); color: white;">Konzept</span>}
{tool.type === 'method' && <span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>}
{tool.type === 'software' && <span class="badge" style="background-color: var(--color-primary); color: white;">Software</span>}
{hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>}
{tool.license !== 'Proprietary' && <span class="badge badge-success">Open Source</span>}
<span class="badge badge-error">Infos 📖</span>
</>
);
})()}
</div>
</div>
<div class="kb-expand-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</div>
</div>
<p class="text-muted" style="font-size: 0.875rem; margin: 0.5rem 0 0 0;">
{tool.description}
</p>
</div>
{tool.license !== 'Proprietary' && tool.type !== 'concept' && tool.type !== 'method' && <span class="badge badge-success">Open Source</span>}
<!-- Expanded Content (hidden by default) -->
<div class="kb-entry-content" style="display: none;">
<!-- Quick Info -->
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin: 1.5rem 0; padding: 1rem; background-color: var(--color-bg-secondary); border-radius: 0.5rem;">
<div>
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Plattformen</strong>
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.platforms.join(', ')}</p>
</div>
<div>
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Skill Level</strong>
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.skillLevel}</p>
</div>
<div>
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Lizenz</strong>
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.license}</p>
</div>
<div>
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Phasen</strong>
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.phases.join(', ')}</p>
<!-- Difficulty indicator -->
<span class="badge" style="background-color: var(--color-text-secondary); color: white; font-size: 0.75rem;">
{tool.skillLevel || 'intermediate'}
</span>
</div>
</div>
<!-- Knowledge Content Area -->
<div class="kb-content">
<h4 style="margin-bottom: 1rem; color: var(--color-text); font-size: 1.125rem;">Praktische Erkenntnisse</h4>
{tool.knowledgebaseContent ? (
<div style="line-height: 1.7;">
<p>{tool.knowledgebaseContent}</p>
</div>
) : (
<div style="padding: 2rem; text-align: center; background-color: var(--color-bg-secondary); border-radius: 0.5rem; border: 2px dashed var(--color-border);">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--color-text-secondary)" stroke-width="1.5" style="margin-bottom: 0.75rem;">
<path d="M14.828 14.828a4 4 0 0 1-5.656 0"/>
<path d="M9 9a3 3 0 1 1 6 0c0 .749-.269 1.433-.73 1.96L11 14v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1l-3.27-3.04A3 3 0 0 1 5 9a3 3 0 0 1 6 0"/>
<path d="M12 17h.01"/>
</svg>
<p class="text-muted" style="margin: 0; font-style: italic;">
Inhalt wird manuell hinzugefügt
</p>
</div>
)}
</div>
<!-- Action Links -->
<div style="display: flex; gap: 1rem; margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--color-border);">
{(() => {
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
return (
<>
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<!-- Action button -->
<a href={`/knowledgebase/${toolSlug}`} class="btn btn-primary" style="font-size: 0.8125rem;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
Software-Homepage
Artikel öffnen
</a>
{hasValidProjectUrl && (
<a href={tool.projectUrl} target="_blank" rel="noopener noreferrer" class="btn btn-primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<circle cx="12" cy="12" r="10"/>
<path d="M12 16l4-4-4-4"/>
<path d="M8 12h8"/>
</svg>
Zugreifen
</a>
)}
</>
);
})()}
</div>
<!-- Description -->
<p style="margin: 1rem 0; color: var(--color-text-secondary); line-height: 1.5;">
{tool.description}
</p>
<!-- Tags and Metadata -->
<div style="display: flex; gap: 1rem; flex-wrap: wrap; align-items: center; margin-top: 1rem;">
{tool.tags && tool.tags.length > 0 && (
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem;">
{tool.tags.map((tag: string) => (
<span class="tag" style="font-size: 0.75rem;">{tag}</span>
))}
</div>
)}
{tool.phases && tool.phases.length > 0 && (
<div style="font-size: 0.8125rem; color: var(--color-text-secondary);">
<strong>Phasen:</strong> {tool.phases.join(', ')}
</div>
)}
{tool.platforms && tool.platforms.length > 0 && tool.type !== 'concept' && tool.type !== 'method' && (
<div style="font-size: 0.8125rem; color: var(--color-text-secondary);">
<strong>Plattformen:</strong> {tool.platforms.join(', ')}
</div>
)}
</div>
</article>
))}
);
})}
</div>
)}
</div>
<!-- No Results Message -->
<div id="no-kb-results" style="display: none; text-align: center; padding: 4rem 0;">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="var(--color-text-secondary)" stroke-width="1.5" style="margin-bottom: 1rem;">
<circle cx="11" cy="11" r="8"/>
<path d="M21 21l-4.35-4.35"/>
</svg>
<!-- No Results -->
<div id="no-kb-results" class="card" style="text-align: center; padding: 3rem; display: none;">
<h3 style="color: var(--color-text-secondary); margin-bottom: 0.5rem;">Keine Ergebnisse gefunden</h3>
<p class="text-muted">Versuchen Sie es mit anderen Suchbegriffen.</p>
</div>
</section>
</BaseLayout>
<style>
/* Simplified knowledgebase styles */
.kb-entry {
margin-bottom: 1.5rem;
border-left: 4px solid var(--color-accent);
transition: var(--transition-fast);
}
.kb-entry:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.dark .kb-entry:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
</style>
<script>
// Toggle knowledgebase entry expansion
function toggleKbEntry(entryId: string) {
const entry = document.getElementById(`kb-${entryId}`);
if (!entry) return;
const content = entry.querySelector('.kb-entry-content') as HTMLElement;
const icon = entry.querySelector('.kb-expand-icon svg') as HTMLElement;
if (!content || !icon) return;
const isExpanded = entry.classList.contains('kb-entry-expanded');
if (isExpanded) {
// Collapse
entry.classList.remove('kb-entry-expanded');
entry.classList.add('kb-entry-collapsed');
content.style.display = 'none';
icon.style.transform = 'rotate(0deg)';
} else {
// Expand
entry.classList.remove('kb-entry-collapsed');
entry.classList.add('kb-entry-expanded');
content.style.display = 'block';
icon.style.transform = 'rotate(180deg)';
}
}
// Make toggle function globally available
(window as any).toggleKbEntry = toggleKbEntry;
// Search functionality
// Enhanced knowledgebase functionality with search
document.addEventListener('DOMContentLoaded', () => {
const searchInput = document.getElementById('kb-search') as HTMLInputElement;
const entries = document.querySelectorAll('.kb-entry');
const visibleCount = document.getElementById('visible-count');
const noResults = document.getElementById('no-kb-results');
const entriesContainer = document.getElementById('kb-entries');
const searchInput = document.getElementById('kb-search') as HTMLInputElement | null;
const entries = document.querySelectorAll('.kb-entry') as NodeListOf<HTMLElement>;
const visibleCount = document.getElementById('visible-count') as HTMLElement | null;
const noResults = document.getElementById('no-kb-results') as HTMLElement | null;
if (!searchInput || !entries.length) return;
// Check if page loaded with hash for specific entry
if (window.location.hash && window.location.hash.startsWith('#kb-')) {
const targetId = window.location.hash.replace('#kb-', '');
setTimeout(() => toggleKbEntry(targetId), 100);
function updateVisibleCount(count: number) {
if (visibleCount) {
visibleCount.textContent = count.toString();
}
}
searchInput.addEventListener('input', () => {
const searchTerm = searchInput.value.toLowerCase().trim();
function filterEntries(searchTerm: string) {
let visibleEntries = 0;
entries.forEach(entry => {
entries.forEach((entry) => {
const toolName = entry.getAttribute('data-tool-name') || '';
const entryText = entry.textContent?.toLowerCase() || '';
const matches = entryText.includes(searchTerm.toLowerCase()) ||
toolName.includes(searchTerm.toLowerCase());
if (searchTerm === '' ||
toolName.includes(searchTerm) ||
entryText.includes(searchTerm)) {
(entry as HTMLElement).style.display = 'block';
if (matches) {
entry.style.display = 'block';
visibleEntries++;
} else {
(entry as HTMLElement).style.display = 'none';
entry.style.display = 'none';
}
});
// Update count
if (visibleCount) {
visibleCount.textContent = visibleEntries.toString();
}
updateVisibleCount(visibleEntries);
// Show/hide no results message
if (noResults && entriesContainer) {
if (visibleEntries === 0 && searchTerm !== '') {
(noResults as HTMLElement).style.display = 'block';
(entriesContainer as HTMLElement).style.display = 'none';
} else {
(noResults as HTMLElement).style.display = 'none';
(entriesContainer as HTMLElement).style.display = 'block';
if (noResults) {
noResults.style.display = visibleEntries === 0 && searchTerm.length > 0 ? 'block' : 'none';
}
}
// Search functionality
if (searchInput) {
searchInput.addEventListener('input', (e) => {
const target = e.target as HTMLInputElement;
filterEntries(target.value);
});
}
});
</script>

View File

@ -0,0 +1,169 @@
---
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
import { getToolsData } from '../../utils/dataService.js';
// Prerender these pages at build time
export const prerender = true;
export async function getStaticPaths() {
const knowledgebaseEntries = await getCollection('knowledgebase');
console.log('Building static paths for:', knowledgebaseEntries.map(e => e.slug));
return knowledgebaseEntries.map((entry) => {
return {
params: { slug: entry.slug },
props: { entry },
};
});
}
const { entry }: { entry: any } = Astro.props;
// Render the content
const { Content } = await entry.render();
// Load tools data to get the tool details
const data = await getToolsData();
const tool = data.tools.find((t: any) => t.name === entry.data.tool_name);
if (!tool) {
console.warn(`Tool not found for knowledgebase entry: ${entry.data.tool_name}`);
return Astro.redirect('/knowledgebase');
}
// Determine tool type for styling
const isMethod = tool.type === 'method';
const isConcept = tool.type === 'concept';
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
---
<BaseLayout title={entry.data.title} description={entry.data.description}>
<article style="max-width: 900px; margin: 0 auto;">
<!-- Header -->
<header style="margin-bottom: 2rem; padding: 2rem; background: linear-gradient(135deg, var(--color-bg-secondary) 0%, var(--color-bg-tertiary) 100%); border-radius: 1rem; border: 1px solid var(--color-border);">
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;">
<div style="flex: 1;">
<h1 style="margin: 0 0 0.5rem 0; color: var(--color-primary);">
{tool.icon && <span style="margin-right: 0.75rem; font-size: 1.5rem;">{tool.icon}</span>}
{entry.data.title}
</h1>
<p style="margin: 0; color: var(--color-text-secondary); font-size: 1.125rem;">
{entry.data.description}
</p>
</div>
<div style="display: flex; flex-direction: column; gap: 0.5rem; align-items: end;">
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
{isConcept && <span class="badge" style="background-color: var(--color-concept); color: white;">Konzept</span>}
{isMethod && <span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>}
{!isMethod && !isConcept && <span class="badge" style="background-color: var(--color-primary); color: white;">Software</span>}
{!isMethod && !isConcept && hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>}
{!isMethod && !isConcept && tool.license !== 'Proprietary' && <span class="badge badge-success">Open Source</span>}
<span class="badge badge-error">📖</span>
</div>
</div>
</div>
<!-- Metadata -->
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--color-border);">
<div>
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Schwierigkeit</strong>
<p style="margin: 0; font-size: 0.9375rem;">{entry.data.difficulty}</p>
</div>
<div>
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Letztes Update</strong>
<p style="margin: 0; font-size: 0.9375rem;">{entry.data.last_updated.toLocaleDateString('de-DE')}</p>
</div>
<div>
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Autor</strong>
<p style="margin: 0; font-size: 0.9375rem;">{entry.data.author}</p>
</div>
{entry.data.categories && entry.data.categories.length > 0 && (
<div>
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Kategorien</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.25rem;">
{entry.data.categories.map((cat: string) => (
<span class="tag" style="font-size: 0.75rem;">{cat}</span>
))}
</div>
</div>
)}
</div>
</header>
<!-- Navigation -->
<nav style="margin-bottom: 2rem; position: relative; z-index: 50;">
<a href="/knowledgebase" class="btn btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<polyline points="15,18 9,12 15,6"></polyline>
</svg>
Zurück zur Knowledgebase
</a>
</nav>
<!-- Content -->
<div class="card" style="padding: 2rem;">
<div class="kb-content markdown-content" style="line-height: 1.7;">
<Content />
</div>
</div>
<!-- Tool Actions -->
<div class="card" style="margin-top: 2rem; background-color: var(--color-bg-secondary);">
<h3 style="margin: 0 0 1rem 0; color: var(--color-text);">Tool-Aktionen</h3>
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
{isConcept ? (
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="background-color: var(--color-concept); border-color: var(--color-concept);">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
Mehr erfahren
</a>
) : isMethod ? (
<a href={tool.projectUrl || tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="background-color: var(--color-method); border-color: var(--color-method);">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
Zur Methode
</a>
) : (
<>
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
Software-Homepage
</a>
{hasValidProjectUrl && (
<a href={tool.projectUrl} target="_blank" rel="noopener noreferrer" class="btn btn-primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<circle cx="12" cy="12" r="10"/>
<path d="M12 16l4-4-4-4"/>
<path d="M8 12h8"/>
</svg>
Zugreifen
</a>
)}
</>
)}
<a href="/" class="btn btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
<polyline points="9,22 9,12 15,12 15,22"/>
</svg>
Zur Hauptseite
</a>
</div>
</div>
</article>
</BaseLayout>

View File

@ -614,7 +614,10 @@ input[type="checkbox"] {
}
.badge-primary { background-color: var(--color-primary); color: white; }
.badge-secondary { background-color: var(--color-bg-secondary); color: var(--color-text); border: 1px solid var(--color-border); }
.badge-success { background-color: var(--color-accent); color: white; }
.badge-accent { background-color: var(--color-accent); color: white; }
.badge-warning { background-color: var(--color-warning); color: white; }
.badge-error { background-color: var(--color-error); color: white; }
/* Tags */
@ -1258,20 +1261,8 @@ Collaboration Section Collapse */
border-radius: 0.5rem;
}
.kb-expand-icon {
transition: var(--transition-medium);
color: var(--color-text-secondary);
}
.kb-expand-icon svg { transition: var(--transition-medium); }
.kb-entry-content {
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid var(--color-border);
animation: slideDown 0.3s ease-out;
}
.kb-content { line-height: 1.7; }
/* Footer */
@ -1494,3 +1485,92 @@ footer {
padding: 0.25rem 0.375rem;
}
}
.markdown-content h1,
.markdown-content h2,
.markdown-content h3,
.markdown-content h4,
.markdown-content h5,
.markdown-content h6 {
margin-top: 2rem;
margin-bottom: 1rem;
}
.markdown-content h1:first-child,
.markdown-content h2:first-child,
.markdown-content h3:first-child {
margin-top: 0;
}
.markdown-content p {
margin-bottom: 1rem;
}
.markdown-content ul,
.markdown-content ol {
margin-bottom: 1rem;
padding-left: 1.5rem;
}
.markdown-content li {
margin-bottom: 0.5rem;
}
.markdown-content pre {
background-color: var(--color-bg-tertiary);
border: 1px solid var(--color-border);
border-radius: 0.5rem;
padding: 1rem;
margin: 1.5rem 0;
overflow-x: auto;
font-size: 0.875rem;
}
.markdown-content code:not(pre code) {
background-color: var(--color-bg-secondary);
border: 1px solid var(--color-border);
border-radius: 0.25rem;
padding: 0.125rem 0.375rem;
font-size: 0.875rem;
}
.markdown-content table {
width: 100%;
border-collapse: collapse;
margin: 1.5rem 0;
background-color: var(--color-bg);
border-radius: 0.5rem;
overflow: hidden;
border: 1px solid var(--color-border);
}
.markdown-content th,
.markdown-content td {
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid var(--color-border);
}
.markdown-content th {
background-color: var(--color-bg-secondary);
font-weight: 600;
}
.markdown-content blockquote {
border-left: 4px solid var(--color-primary);
background-color: var(--color-bg-secondary);
padding: 1rem 1.5rem;
margin: 1.5rem 0;
border-radius: 0 0.5rem 0.5rem 0;
}
.markdown-content hr {
border: none;
border-top: 1px solid var(--color-border);
margin: 2rem 0;
}

View File

@ -51,6 +51,7 @@ interface ToolsData {
interface CompressedToolsData extends Omit<ToolsData, 'tools'> {
tools: any[];
concepts: any[]; // NEW: Add concepts for AI background knowledge
}
let cachedData: ToolsData | null = null;
@ -128,21 +129,30 @@ export async function getToolsData(): Promise<ToolsData> {
return cachedRandomizedData;
}
// Get compressed data for AI (removes projectUrl and statusUrl, excludes concepts)
// Get compressed data for AI (excludes concepts from tools, but includes them separately for background knowledge)
export async function getCompressedToolsDataForAI(): Promise<CompressedToolsData> {
if (!cachedCompressedData) {
const data = await getToolsData();
// Filter out concepts and compress remaining tools
// Separate tools and concepts
const compressedTools = data.tools
.filter(tool => tool.type !== 'concept') // Exclude concepts from AI
.filter(tool => tool.type !== 'concept') // Exclude concepts from tool recommendations
.map(tool => {
const { projectUrl, statusUrl, ...compressedTool } = tool;
return compressedTool;
});
// Extract concepts for background knowledge - keep essential fields only
const concepts = data.tools
.filter(tool => tool.type === 'concept')
.map(concept => {
const { projectUrl, statusUrl, platforms, accessType, license, ...compressedConcept } = concept;
return compressedConcept;
});
cachedCompressedData = {
tools: compressedTools,
concepts: concepts,
domains: data.domains,
phases: data.phases,
'domain-agnostic-software': data['domain-agnostic-software']