finalize methods implementation

This commit is contained in:
overcuriousity 2025-07-19 18:54:31 +02:00
parent 1d048e816c
commit a8cc30d5ac
7 changed files with 245 additions and 33 deletions

View File

@ -2,6 +2,7 @@
export interface Props { export interface Props {
tool: { tool: {
name: string; name: string;
type?: string;
description: string; description: string;
domains: string[]; domains: string[];
phases: string[]; phases: string[];
@ -19,6 +20,9 @@ export interface Props {
const { tool } = Astro.props; const { tool } = Astro.props;
// Check if this is a method vs software
const isMethod = tool.type === 'method';
// Check if tool has a valid project URL (means we're hosting it) // Check if tool has a valid project URL (means we're hosting it)
const hasValidProjectUrl = tool.projectUrl !== undefined && const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null && tool.projectUrl !== null &&
@ -28,17 +32,20 @@ const hasValidProjectUrl = tool.projectUrl !== undefined &&
// Check if tool has knowledgebase entry // Check if tool has knowledgebase entry
const hasKnowledgebase = tool.knowledgebase === true; const hasKnowledgebase = tool.knowledgebase === true;
// Determine card styling based on hosting status (derived from projectUrl) // Determine card styling based on type and hosting status
const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card'); const cardClass = isMethod ? 'card card-method tool-card' :
hasValidProjectUrl ? 'card card-hosted tool-card' :
(tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card');
--- ---
<div class={cardClass} onclick={`window.showToolDetails('${tool.name}')`} style="cursor: pointer; border-left: 4px solid ${hasValidProjectUrl ? 'var(--color-hosted)' : tool.license !== 'Proprietary' ? 'var(--color-oss)' : 'var(--color-border)'};"> <div class={cardClass} onclick={`window.showToolDetails('${tool.name}')`} style="cursor: pointer; border-left: 4px solid ${isMethod ? 'var(--color-method)' : hasValidProjectUrl ? 'var(--color-hosted)' : tool.license !== 'Proprietary' ? 'var(--color-oss)' : 'var(--color-border)'};">
<!-- Card Header with Fixed Height --> <!-- Card Header with Fixed Height -->
<div class="tool-card-header"> <div class="tool-card-header">
<h3>{tool.name}</h3> <h3>{tool.name}</h3>
<div class="tool-card-badges"> <div class="tool-card-badges">
{hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>} {isMethod && <span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>}
{tool.license !== 'Proprietary' && <span class="badge badge-success">OSS</span>} {!isMethod && hasValidProjectUrl && <span class="badge badge-primary">Self-Hosted</span>}
{!isMethod && tool.license !== 'Proprietary' && <span class="badge badge-success">OSS</span>}
{hasKnowledgebase && <span class="badge badge-error">📖</span>} {hasKnowledgebase && <span class="badge badge-error">📖</span>}
</div> </div>
</div> </div>
@ -77,7 +84,7 @@ const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.lice
<polyline points="14 2 14 8 20 8"></polyline> <polyline points="14 2 14 8 20 8"></polyline>
</svg> </svg>
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;"> <span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;">
{tool.license === 'Proprietary' ? 'Prop.' : tool.license.split(' ')[0]} {isMethod ? 'Methode' : tool.license === 'Proprietary' ? 'Prop.' : tool.license?.split(' ')[0]}
</span> </span>
</div> </div>
</div> </div>
@ -91,7 +98,12 @@ const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.lice
<!-- Buttons - Fixed at Bottom --> <!-- Buttons - Fixed at Bottom -->
<div class="tool-card-buttons" onclick="event.stopPropagation();"> <div class="tool-card-buttons" onclick="event.stopPropagation();">
{hasValidProjectUrl ? ( {isMethod ? (
<!-- Method button -->
<a href={tool.projectUrl || tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button" style="background-color: var(--color-method); border-color: var(--color-method);">
Zur Methode
</a>
) : hasValidProjectUrl ? (
<!-- Two buttons for hosted tools --> <!-- Two buttons for hosted tools -->
<div class="button-row"> <div class="button-row">
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary"> <a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">

View File

@ -251,6 +251,11 @@ const sortedTags = Object.entries(tagFrequency)
tool.projectUrl.trim() !== ""; tool.projectUrl.trim() !== "";
} }
// Check if item is a method
function isMethod(tool) {
return tool.type === 'method';
}
// Update matrix highlighting based on current filters // Update matrix highlighting based on current filters
function updateMatrixHighlighting() { function updateMatrixHighlighting() {
const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view'); const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
@ -324,8 +329,8 @@ const sortedTags = Object.entries(tagFrequency)
return false; return false;
} }
// Proprietary filter // Proprietary filter (skip for methods since they don't have licenses)
if (!includeProprietary && tool.license === 'Proprietary') { if (!includeProprietary && !isMethod(tool) && tool.license === 'Proprietary') {
return false; return false;
} }
@ -337,13 +342,21 @@ const sortedTags = Object.entries(tagFrequency)
return true; return true;
}); });
// Sort filtered results: server-based first, proprietary last // Sort filtered results: methods first, then self-hosted, then OSS, proprietary last
filtered.sort((a, b) => { filtered.sort((a, b) => {
const aMethod = isMethod(a);
const bMethod = isMethod(b);
const aHosted = isToolHosted(a); const aHosted = isToolHosted(a);
const bHosted = isToolHosted(b); const bHosted = isToolHosted(b);
const aProprietary = a.license === 'Proprietary'; const aProprietary = !aMethod && a.license === 'Proprietary';
const bProprietary = b.license === 'Proprietary'; const bProprietary = !bMethod && b.license === 'Proprietary';
// Methods first
//if (aMethod && !bMethod) return -1;
//if (!aMethod && bMethod) return 1;
// If both are methods or both are tools
if (aMethod === bMethod) {
// Self-hosted tools first (regardless of license) // Self-hosted tools first (regardless of license)
if (aHosted && !bHosted) return -1; if (aHosted && !bHosted) return -1;
if (!aHosted && bHosted) return 1; if (!aHosted && bHosted) return 1;
@ -353,13 +366,13 @@ const sortedTags = Object.entries(tagFrequency)
if (!aProprietary && bProprietary) return -1; if (!aProprietary && bProprietary) return -1;
if (aProprietary && !bProprietary) return 1; if (aProprietary && !bProprietary) return 1;
} }
}
return 0; return 0;
}); });
// Update matrix highlighting // Update matrix highlighting
updateMatrixHighlighting(); updateMatrixHighlighting();
// Emit custom event with filtered results // Emit custom event with filtered results
window.dispatchEvent(new CustomEvent('toolsFiltered', { detail: filtered })); window.dispatchEvent(new CustomEvent('toolsFiltered', { detail: filtered }));
} }

View File

@ -107,13 +107,17 @@ domains.forEach((domain: any) => {
{phases.map((phase: any) => ( {phases.map((phase: any) => (
<td class="matrix-cell" data-domain={domain.id} data-phase={phase.id}> <td class="matrix-cell" data-domain={domain.id} data-phase={phase.id}>
{matrix[domain.id][phase.id].map((tool: any) => { {matrix[domain.id][phase.id].map((tool: any) => {
const isMethod = tool.type === 'method';
const hasValidProjectUrl = tool.projectUrl !== undefined && const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null && tool.projectUrl !== null &&
tool.projectUrl !== "" && tool.projectUrl !== "" &&
tool.projectUrl.trim() !== ""; tool.projectUrl.trim() !== "";
const chipClass = isMethod ? 'tool-chip-method' :
hasValidProjectUrl ? 'tool-chip-hosted' :
tool.license !== 'Proprietary' ? 'tool-chip-oss' : '';
return ( return (
<span <span
class={`tool-chip ${hasValidProjectUrl ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`} class={`tool-chip ${chipClass}`}
data-tool-name={tool.name} data-tool-name={tool.name}
onclick={`window.showToolDetails('${tool.name}')`} onclick={`window.showToolDetails('${tool.name}')`}
title={`${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`} title={`${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`}
@ -392,6 +396,7 @@ domains.forEach((domain: any) => {
// Re-populate with filtered tools based on domains × phases // Re-populate with filtered tools based on domains × phases
filtered.forEach(tool => { filtered.forEach(tool => {
const isMethod = tool.type === 'method';
const hasValidProjectUrl = tool.projectUrl !== undefined && const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null && tool.projectUrl !== null &&
tool.projectUrl !== "" && tool.projectUrl !== "" &&
@ -405,7 +410,10 @@ domains.forEach((domain: any) => {
const cell = document.querySelector(`[data-domain="${domain}"][data-phase="${phase}"]`); const cell = document.querySelector(`[data-domain="${domain}"][data-phase="${phase}"]`);
if (cell) { if (cell) {
const chip = document.createElement('span'); const chip = document.createElement('span');
chip.className = `tool-chip ${hasValidProjectUrl ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`; const chipClass = isMethod ? 'tool-chip-method' :
hasValidProjectUrl ? 'tool-chip-hosted' :
tool.license !== 'Proprietary' ? 'tool-chip-oss' : '';
chip.className = `tool-chip ${chipClass}`;
chip.setAttribute('title', `${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`); chip.setAttribute('title', `${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`);
chip.innerHTML = `${tool.name}${tool.knowledgebase === true ? '<span style="margin-left: 0.25rem; font-size: 0.6875rem;">📖</span>' : ''}`; chip.innerHTML = `${tool.name}${tool.knowledgebase === true ? '<span style="margin-left: 0.25rem; font-size: 0.6875rem;">📖</span>' : ''}`;
chip.onclick = () => window.showToolDetails(tool.name); chip.onclick = () => window.showToolDetails(tool.name);

View File

@ -1,5 +1,6 @@
tools: tools:
- name: Autopsy - name: Autopsy
type: software
description: >- description: >-
Die führende Open-Source-Alternative zu kommerziellen Forensik-Suiten mit Die führende Open-Source-Alternative zu kommerziellen Forensik-Suiten mit
intuitiver grafischer Oberfläche. Besonders stark in der Timeline-Analyse, intuitiver grafischer Oberfläche. Besonders stark in der Timeline-Analyse,
@ -34,6 +35,7 @@ tools:
- artifact-extraction - artifact-extraction
- keyword-search - keyword-search
- name: Volatility 3 - name: Volatility 3
type: software
description: >- description: >-
Das Schweizer Taschenmesser der Memory-Forensik, unverzichtbar für die Das Schweizer Taschenmesser der Memory-Forensik, unverzichtbar für die
Analyse von RAM-Dumps. Mit über 100 Plugins extrahiert es Prozesse, Analyse von RAM-Dumps. Mit über 100 Plugins extrahiert es Prozesse,
@ -69,6 +71,7 @@ tools:
- scripting - scripting
- process-analysis - process-analysis
- name: TheHive 5 - name: TheHive 5
type: software
description: >- description: >-
Moderne Security-Orchestrierungs-Plattform für die koordinierte Moderne Security-Orchestrierungs-Plattform für die koordinierte
Incident-Response im Team. Integriert nahtlos mit MISP, Cortex und anderen Incident-Response im Team. Integriert nahtlos mit MISP, Cortex und anderen
@ -103,6 +106,7 @@ tools:
- incident-tracking - incident-tracking
statusUrl: https://uptime.example.lab/api/badge/1/status statusUrl: https://uptime.example.lab/api/badge/1/status
- name: MISP - name: MISP
type: software
description: >- description: >-
Das Rückgrat des modernen Threat-Intelligence-Sharings mit über 40.000 Das Rückgrat des modernen Threat-Intelligence-Sharings mit über 40.000
aktiven Instanzen weltweit. Ermöglicht den strukturierten Austausch von aktiven Instanzen weltweit. Ermöglicht den strukturierten Austausch von
@ -136,6 +140,7 @@ tools:
- automation - automation
statusUrl: https://status.mikoshi.de/api/badge/34/status statusUrl: https://status.mikoshi.de/api/badge/34/status
- name: Timesketch - name: Timesketch
type: software
description: >- description: >-
Google's Open-Source-Lösung für kollaborative Timeline-Analyse großer Google's Open-Source-Lösung für kollaborative Timeline-Analyse großer
Datensätze. Visualisiert und korreliert Ereignisse aus verschiedenen Datensätze. Visualisiert und korreliert Ereignisse aus verschiedenen
@ -168,6 +173,7 @@ tools:
- correlation - correlation
statusUrl: https://uptime.example.lab/api/badge/3/status statusUrl: https://uptime.example.lab/api/badge/3/status
- name: Wireshark - name: Wireshark
type: software
description: >- description: >-
Der unangefochtene König der Netzwerk-Protokoll-Analyse mit Support für Der unangefochtene König der Netzwerk-Protokoll-Analyse mit Support für
über 3000 Protokolle. Unverzichtbar für die Untersuchung von über 3000 Protokolle. Unverzichtbar für die Untersuchung von
@ -203,6 +209,7 @@ tools:
- visualization - visualization
- filtering - filtering
- name: Magnet AXIOM - name: Magnet AXIOM
type: software
description: >- description: >-
Die Rolls-Royce unter den kommerziellen Forensik-Suiten mit Die Rolls-Royce unter den kommerziellen Forensik-Suiten mit
beeindruckender Automatisierung. Glänzt besonders bei Cloud-Forensik mit beeindruckender Automatisierung. Glänzt besonders bei Cloud-Forensik mit
@ -237,6 +244,7 @@ tools:
- automated-analysis - automated-analysis
- reporting - reporting
- name: Cellebrite UFED - name: Cellebrite UFED
type: software
description: >- description: >-
Der Goldstandard der mobilen Forensik mit legendären Der Goldstandard der mobilen Forensik mit legendären
Entsperrungsfähigkeiten für aktuelle Smartphones. Nutzt Zero-Day-Exploits Entsperrungsfähigkeiten für aktuelle Smartphones. Nutzt Zero-Day-Exploits
@ -268,6 +276,7 @@ tools:
- hardware-interface - hardware-interface
- automated-analysis - automated-analysis
- name: Cuckoo Sandbox 3 - name: Cuckoo Sandbox 3
type: software
description: >- description: >-
Die führende Open-Source-Sandbox für automatisierte Malware-Analyse in Die führende Open-Source-Sandbox für automatisierte Malware-Analyse in
isolierten Umgebungen. Zeichnet Systemaufrufe, Netzwerkverkehr und isolierten Umgebungen. Zeichnet Systemaufrufe, Netzwerkverkehr und
@ -299,6 +308,7 @@ tools:
- virtualization - virtualization
- automated-analysis - automated-analysis
- name: Ghidra - name: Ghidra
type: software
description: >- description: >-
NSAs Geschenk an die Reverse-Engineering-Community als mächtige NSAs Geschenk an die Reverse-Engineering-Community als mächtige
Alternative zu IDA Pro. Der Decompiler verwandelt Maschinencode zurück in Alternative zu IDA Pro. Der Decompiler verwandelt Maschinencode zurück in
@ -330,6 +340,7 @@ tools:
- scripting - scripting
- static-analysis - static-analysis
- name: Plaso (log2timeline) - name: Plaso (log2timeline)
type: software
description: >- description: >-
Der industrielle Staubsauger für Zeitstempel - extrahiert aus hunderten Der industrielle Staubsauger für Zeitstempel - extrahiert aus hunderten
Quellen eine Super-Timeline. Parst Windows-Event-Logs, Browser-Historie, Quellen eine Super-Timeline. Parst Windows-Event-Logs, Browser-Historie,
@ -364,6 +375,7 @@ tools:
- artifact-extraction - artifact-extraction
- scripting - scripting
- name: CyberChef - name: CyberChef
type: software
description: >- description: >-
Das digitale Schweizer Taschenmesser für Daten-Manipulation mit über 300 Das digitale Schweizer Taschenmesser für Daten-Manipulation mit über 300
Operations. Von Base64-Dekodierung über Verschlüsselung bis zur Operations. Von Base64-Dekodierung über Verschlüsselung bis zur
@ -395,6 +407,7 @@ tools:
- visualization - visualization
- parsing - parsing
- name: Velociraptor - name: Velociraptor
type: software
description: >- description: >-
Die nächste Evolution der Endpoint-Forensik mit skalierbarer Die nächste Evolution der Endpoint-Forensik mit skalierbarer
Remote-Collection-Architektur. Die mächtige VQL-Abfragesprache ermöglicht Remote-Collection-Architektur. Die mächtige VQL-Abfragesprache ermöglicht
@ -434,6 +447,7 @@ tools:
- hunting - hunting
statusUrl: https://status.mikoshi.de/api/badge/33/status statusUrl: https://status.mikoshi.de/api/badge/33/status
- name: GRR Rapid Response - name: GRR Rapid Response
type: software
description: >- description: >-
Googles Antwort auf Enterprise-Scale-Forensik für die Untersuchung von Googles Antwort auf Enterprise-Scale-Forensik für die Untersuchung von
Flotten mit tausenden Clients. Sammelt gezielt Artefakte und führt Flotten mit tausenden Clients. Sammelt gezielt Artefakte und führt
@ -469,6 +483,7 @@ tools:
- live-forensics - live-forensics
- fleet-management - fleet-management
- name: Arkime - name: Arkime
type: software
description: >- description: >-
Das Heavy-Metal-Tool für Full-Packet-Capture mit der Fähigkeit, Petabytes Das Heavy-Metal-Tool für Full-Packet-Capture mit der Fähigkeit, Petabytes
an Netzwerkverkehr zu speichern. Indiziert in Echtzeit Metadaten für an Netzwerkverkehr zu speichern. Indiziert in Echtzeit Metadaten für
@ -502,6 +517,7 @@ tools:
- api - api
- big-data - big-data
- name: NetworkMiner - name: NetworkMiner
type: software
description: >- description: >-
Der benutzerfreundliche kleine Bruder von Wireshark mit Fokus auf Forensik Der benutzerfreundliche kleine Bruder von Wireshark mit Fokus auf Forensik
statt Live-Analyse. Extrahiert automatisch übertragene Dateien, Bilder und statt Live-Analyse. Extrahiert automatisch übertragene Dateien, Bilder und
@ -534,6 +550,7 @@ tools:
- parsing - parsing
- session-reconstruction - session-reconstruction
- name: ExifTool - name: ExifTool
type: software
description: >- description: >-
Der Metadaten-Maestro, der aus über 1000 Dateiformaten verborgene Der Metadaten-Maestro, der aus über 1000 Dateiformaten verborgene
Informationen extrahiert. Findet GPS-Koordinaten in Fotos, Autoren in Informationen extrahiert. Findet GPS-Koordinaten in Fotos, Autoren in
@ -568,6 +585,7 @@ tools:
- scripting - scripting
- batch-processing - batch-processing
- name: Chainalysis - name: Chainalysis
type: software
description: >- description: >-
Der Platzhirsch der Blockchain-Forensik mit Zugriff auf die größte Der Platzhirsch der Blockchain-Forensik mit Zugriff auf die größte
Krypto-Intelligence-Datenbank weltweit. Clustering-Algorithmen Krypto-Intelligence-Datenbank weltweit. Clustering-Algorithmen
@ -598,6 +616,7 @@ tools:
- api - api
- reporting - reporting
- name: Neo4j - name: Neo4j
type: software
description: >- description: >-
Die führende Graph-Datenbank verwandelt komplexe Beziehungsgeflechte in Die führende Graph-Datenbank verwandelt komplexe Beziehungsgeflechte in
verständliche Visualisierungen. Mit Cypher-Queries lassen sich verständliche Visualisierungen. Mit Cypher-Queries lassen sich
@ -635,6 +654,7 @@ tools:
- query-language - query-language
statusUrl: https://status.mikoshi.de/api/badge/32/status statusUrl: https://status.mikoshi.de/api/badge/32/status
- name: QGIS - name: QGIS
type: software
description: >- description: >-
Das Open-Source-GIS-Kraftpaket für die Visualisierung von Geodaten in Das Open-Source-GIS-Kraftpaket für die Visualisierung von Geodaten in
forensischen Untersuchungen. Erstellt aus GPS-Logs von Smartphones forensischen Untersuchungen. Erstellt aus GPS-Logs von Smartphones
@ -667,6 +687,7 @@ tools:
- scripting - scripting
- reporting - reporting
- name: Nextcloud - name: Nextcloud
type: software
description: >- description: >-
Die Open-Source-Cloud-Suite als sichere Kollaborations-Zentrale für Die Open-Source-Cloud-Suite als sichere Kollaborations-Zentrale für
Forensik-Teams. Bietet verschlüsselte Dateifreigabe, Office-Integration Forensik-Teams. Bietet verschlüsselte Dateifreigabe, Office-Integration
@ -703,6 +724,7 @@ tools:
- document-management - document-management
statusUrl: https://status.mikoshi.de/api/badge/11/status statusUrl: https://status.mikoshi.de/api/badge/11/status
- name: Gitea - name: Gitea
type: software
description: >- description: >-
Das leichtgewichtige Git-Repository für die Versionierung von Das leichtgewichtige Git-Repository für die Versionierung von
Forensik-Skripten und Dokumentation. Perfekt für die Verwaltung von Forensik-Skripten und Dokumentation. Perfekt für die Verwaltung von
@ -733,6 +755,7 @@ tools:
- ci-cd - ci-cd
statusUrl: https://status.mikoshi.de/api/badge/18/status statusUrl: https://status.mikoshi.de/api/badge/18/status
- name: Binwalk - name: Binwalk
type: software
description: >- description: >-
Der Firmware-Flüsterer, der aus IoT-Geräten und Routern ihre Geheimnisse Der Firmware-Flüsterer, der aus IoT-Geräten und Routern ihre Geheimnisse
extrahiert. Erkennt eingebettete Dateisysteme, komprimierte Archive und extrahiert. Erkennt eingebettete Dateisysteme, komprimierte Archive und
@ -763,6 +786,7 @@ tools:
- extraction - extraction
- scripting - scripting
- name: LibreOffice - name: LibreOffice
type: software
description: >- description: >-
Die freie Office-Suite, die mehr kann als nur Berichte schreiben. Calc Die freie Office-Suite, die mehr kann als nur Berichte schreiben. Calc
eignet sich hervorragend für die Analyse von CSV-Exporten und Log-Dateien. eignet sich hervorragend für die Analyse von CSV-Exporten und Log-Dateien.
@ -802,6 +826,7 @@ tools:
- data-processing - data-processing
- scripting - scripting
- name: Microsoft Office 365 - name: Microsoft Office 365
type: software
description: >- description: >-
Der Industriestandard für professionelle Dokumentation mit nahtloser Der Industriestandard für professionelle Dokumentation mit nahtloser
Cloud-Integration. Excel's Power Query verwandelt komplexe Cloud-Integration. Excel's Power Query verwandelt komplexe
@ -842,6 +867,7 @@ tools:
- cloud-based - cloud-based
- reporting - reporting
- name: GraphSense - name: GraphSense
type: software
description: >- description: >-
Die europäische Alternative zu Chainalysis mit Open-Source-Kern und Fokus Die europäische Alternative zu Chainalysis mit Open-Source-Kern und Fokus
auf Privatsphäre. Clustering-Qualität noch nicht auf Chainalysis-Niveau, auf Privatsphäre. Clustering-Qualität noch nicht auf Chainalysis-Niveau,
@ -872,6 +898,7 @@ tools:
- api - api
- big-data - big-data
- name: FTK Imager - name: FTK Imager
type: software
description: >- description: >-
Der Oldtimer unter den Imaging-Tools, aber immer noch zuverlässig wie ein Der Oldtimer unter den Imaging-Tools, aber immer noch zuverlässig wie ein
Schweizer Uhrwerk. Erstellt bit-genaue Kopien von Festplatten mit Schweizer Uhrwerk. Erstellt bit-genaue Kopien von Festplatten mit
@ -901,6 +928,7 @@ tools:
- verification - verification
- write-blocking - write-blocking
- name: Guymager - name: Guymager
type: software
description: >- description: >-
Das schlanke Linux-Imaging-Tool mit Fokus auf Performance und Das schlanke Linux-Imaging-Tool mit Fokus auf Performance und
Zuverlässigkeit. Multi-threaded Design nutzt moderne CPUs optimal für Zuverlässigkeit. Multi-threaded Design nutzt moderne CPUs optimal für
@ -929,6 +957,7 @@ tools:
- multi-threading - multi-threading
- write-blocking - write-blocking
- name: Fuji - name: Fuji
type: software
description: >- description: >-
Der Geheimtipp für macOS-Forensiker - Live-Imaging ohne Der Geheimtipp für macOS-Forensiker - Live-Imaging ohne
Kernel-Modifikationen. Umgeht geschickt Apples Sicherheitsmechanismen für Kernel-Modifikationen. Umgeht geschickt Apples Sicherheitsmechanismen für
@ -957,6 +986,7 @@ tools:
- filesystem - filesystem
- macos-specific - macos-specific
- name: ALEAPP - name: ALEAPP
type: software
description: >- description: >-
Android-Forensik leicht gemacht - parst dutzende Apps und System-Artefakte Android-Forensik leicht gemacht - parst dutzende Apps und System-Artefakte
automatisch. Von WhatsApp-Chats über Standortdaten bis zu gelöschten automatisch. Von WhatsApp-Chats über Standortdaten bis zu gelöschten
@ -989,6 +1019,7 @@ tools:
- reporting - reporting
- timeline-analysis - timeline-analysis
- name: iLEAPP - name: iLEAPP
type: software
description: >- description: >-
Das iOS-Pendant zu ALEAPP mit Fokus auf Apple's geschlossenem Ökosystem. Das iOS-Pendant zu ALEAPP mit Fokus auf Apple's geschlossenem Ökosystem.
Extrahiert versteckte Schätze aus iPhone-Backups inklusive gelöschter Extrahiert versteckte Schätze aus iPhone-Backups inklusive gelöschter
@ -1021,6 +1052,7 @@ tools:
- reporting - reporting
- ios-specific - ios-specific
- name: VLEAPP - name: VLEAPP
type: software
description: >- description: >-
Die Zukunft der Fahrzeug-Forensik für vernetzte Autos und Die Zukunft der Fahrzeug-Forensik für vernetzte Autos und
Infotainment-Systeme. Parst CAN-Bus-Daten, GPS-Tracks und Infotainment-Systeme. Parst CAN-Bus-Daten, GPS-Tracks und
@ -1052,6 +1084,7 @@ tools:
- gps-analysis - gps-analysis
- can-bus - can-bus
- name: Kali Linux - name: Kali Linux
type: software
description: >- description: >-
Die Schweizer Armee-Messer-Distribution mit über 600 vorinstallierten Die Schweizer Armee-Messer-Distribution mit über 600 vorinstallierten
Security-Tools. Von Forensik über Penetration Testing bis Reverse Security-Tools. Von Forensik über Penetration Testing bis Reverse
@ -1086,6 +1119,7 @@ tools:
- virtualization - virtualization
- arm-support - arm-support
- name: dd - name: dd
type: software
description: >- description: >-
Das Unix-Urgestein für bit-genaues Kopieren von Datenträgern seit 1974. Das Unix-Urgestein für bit-genaues Kopieren von Datenträgern seit 1974.
Minimalistisch aber mächtig - der Goldstandard für forensische Disk-Images Minimalistisch aber mächtig - der Goldstandard für forensische Disk-Images
@ -1115,6 +1149,7 @@ tools:
- unix-tool - unix-tool
- scripting - scripting
- name: dcfldd - name: dcfldd
type: software
description: >- description: >-
Die forensische Weiterentwicklung von dd mit eingebauter Die forensische Weiterentwicklung von dd mit eingebauter
Hash-Verifizierung. Zeigt Fortschrittsbalken, splittet große Images und Hash-Verifizierung. Zeigt Fortschrittsbalken, splittet große Images und
@ -1143,6 +1178,7 @@ tools:
- progress-monitoring - progress-monitoring
- split-output - split-output
- name: ewfacquire - name: ewfacquire
type: software
description: >- description: >-
Das Kommandozeilen-Tool für Expert Witness Format (E01) Images mit Das Kommandozeilen-Tool für Expert Witness Format (E01) Images mit
Kompression. Teil der libewf-Suite, erstellt gerichtsfeste Images mit Kompression. Teil der libewf-Suite, erstellt gerichtsfeste Images mit
@ -1172,6 +1208,7 @@ tools:
- metadata - metadata
- verification - verification
- name: PhotoRec - name: PhotoRec
type: software
description: >- description: >-
Der Datenretter in der Not - findet gelöschte Dateien ohne Der Datenretter in der Not - findet gelöschte Dateien ohne
Dateisystem-Strukturen. Signature-basiertes Carving für über 300 Dateisystem-Strukturen. Signature-basiertes Carving für über 300
@ -1203,6 +1240,7 @@ tools:
- signature-based - signature-based
- cross-platform - cross-platform
- name: Kismet - name: Kismet
type: software
description: >- description: >-
Der WLAN-Schnüffler der Extraklasse für Wireless-Forensik und Der WLAN-Schnüffler der Extraklasse für Wireless-Forensik und
Sicherheitsaudits. Passives Monitoring deckt versteckte Netzwerke, Rogue Sicherheitsaudits. Passives Monitoring deckt versteckte Netzwerke, Rogue
@ -1232,6 +1270,7 @@ tools:
- passive-scanning - passive-scanning
- api - api
- name: OSFMount - name: OSFMount
type: software
description: >- description: >-
Mountet Disk-Images als virtuelle Laufwerke unter Windows für komfortable Mountet Disk-Images als virtuelle Laufwerke unter Windows für komfortable
Analyse. Unterstützt alle gängigen Formate von RAW über E01 bis zu Analyse. Unterstützt alle gängigen Formate von RAW über E01 bis zu
@ -1260,6 +1299,7 @@ tools:
- virtual-drive - virtual-drive
- format-support - format-support
- name: Thumbcache Viewer - name: Thumbcache Viewer
type: software
description: >- description: >-
Spezialist für Windows Thumbnail-Caches mit Zugriff auf gelöschte Spezialist für Windows Thumbnail-Caches mit Zugriff auf gelöschte
Bildvorschauen. Extrahiert Thumbnails aus thumbcache_*.db Dateien Bildvorschauen. Extrahiert Thumbnails aus thumbcache_*.db Dateien
@ -1289,6 +1329,7 @@ tools:
- thumbnail-extraction - thumbnail-extraction
- deleted-data - deleted-data
- name: RegRipper - name: RegRipper
type: software
description: >- description: >-
Der Windows-Registry-Experte mit hunderten Plugins für automatisierte Der Windows-Registry-Experte mit hunderten Plugins für automatisierte
Analyse. Extrahiert USB-Historie, installierte Software, Analyse. Extrahiert USB-Historie, installierte Software,
@ -1320,6 +1361,7 @@ tools:
- plugin-system - plugin-system
- artifact-extraction - artifact-extraction
- name: YARA - name: YARA
type: software
description: >- description: >-
Die Pattern-Matching-Engine für Malware-Jäger und Threat Hunter. Die Pattern-Matching-Engine für Malware-Jäger und Threat Hunter.
Regelbasierte Suche nach Strings, Byte-Sequenzen und regulären Ausdrücken. Regelbasierte Suche nach Strings, Byte-Sequenzen und regulären Ausdrücken.
@ -1351,6 +1393,7 @@ tools:
- library - library
- signature-based - signature-based
- name: Strings - name: Strings
type: software
description: >- description: >-
Das simple Tool mit großer Wirkung - extrahiert lesbare Texte aus Das simple Tool mit großer Wirkung - extrahiert lesbare Texte aus
Binärdateien. Findet URLs, Passwörter, Pfade und andere Binärdateien. Findet URLs, Passwörter, Pfade und andere
@ -1381,6 +1424,7 @@ tools:
- text-search - text-search
- cross-platform - cross-platform
- name: MaxMind GeoIP - name: MaxMind GeoIP
type: software
description: >- description: >-
Die Geolocation-Datenbank für IP-Adressen-Zuordnung zu Ländern und Die Geolocation-Datenbank für IP-Adressen-Zuordnung zu Ländern und
Städten. Unverzichtbar für die Analyse von Netzwerk-Logs und Städten. Unverzichtbar für die Analyse von Netzwerk-Logs und
@ -1412,6 +1456,7 @@ tools:
- enrichment - enrichment
- library - library
- name: SIFT Workstation - name: SIFT Workstation
type: software
description: >- description: >-
SANS' kuratierte Ubuntu-Distribution vollgepackt mit Forensik-Tools und SANS' kuratierte Ubuntu-Distribution vollgepackt mit Forensik-Tools und
Skripten. Über 500 Tools vorinstalliert, vorkonfiguriert und dokumentiert Skripten. Über 500 Tools vorinstalliert, vorkonfiguriert und dokumentiert
@ -1443,6 +1488,7 @@ tools:
- documentation - documentation
- ubuntu-based - ubuntu-based
- name: Tsurugi Linux - name: Tsurugi Linux
type: software
description: >- description: >-
Die von Forensikern entwickelte Forensik-Distribution mit Fokus auf Die von Forensikern entwickelte Forensik-Distribution mit Fokus auf
Benutzerfreundlichkeit. Besonders stark bei Mobile- und Malware-Forensik Benutzerfreundlichkeit. Besonders stark bei Mobile- und Malware-Forensik
@ -1472,6 +1518,7 @@ tools:
- mobile-focus - mobile-focus
- lightweight - lightweight
- name: Parrot Security OS - name: Parrot Security OS
type: software
description: >- description: >-
Die Datenschutz-fokussierte Alternative zu Kali mit Forensik-Werkzeugen. Die Datenschutz-fokussierte Alternative zu Kali mit Forensik-Werkzeugen.
AnonSurf für anonymisierte Ermittlungen und verschlüsselte Kommunikation AnonSurf für anonymisierte Ermittlungen und verschlüsselte Kommunikation
@ -1502,6 +1549,7 @@ tools:
- lightweight - lightweight
- anonymization - anonymization
- name: Eric Zimmerman Tools - name: Eric Zimmerman Tools
type: software
description: >- description: >-
Die Tool-Sammlung des Windows-Forensik-Gurus für Artefakt-Analyse. Von Die Tool-Sammlung des Windows-Forensik-Gurus für Artefakt-Analyse. Von
ShellBags über Prefetch bis zu Amcache - jedes Tool ein Spezialist. Die ShellBags über Prefetch bis zu Amcache - jedes Tool ein Spezialist. Die
@ -1530,6 +1578,7 @@ tools:
- tool-collection - tool-collection
- artifact-extraction - artifact-extraction
- name: Impacket - name: Impacket
type: software
description: >- description: >-
Python-Bibliothek für Netzwerk-Protokoll-Manipulation und Python-Bibliothek für Netzwerk-Protokoll-Manipulation und
Windows-Forensik. Ermöglicht Remote-Zugriff auf Windows-Systeme für Windows-Forensik. Ermöglicht Remote-Zugriff auf Windows-Systeme für
@ -1562,6 +1611,7 @@ tools:
- scripting - scripting
- api - api
- name: RSA NetWitness - name: RSA NetWitness
type: software
description: >- description: >-
Enterprise-Grade SIEM und Forensik-Plattform für große Netzwerke. Enterprise-Grade SIEM und Forensik-Plattform für große Netzwerke.
Korreliert Logs, Packets und Endpoints für 360-Grad-Sicht auf Incidents. Korreliert Logs, Packets und Endpoints für 360-Grad-Sicht auf Incidents.
@ -1593,6 +1643,7 @@ tools:
- machine-learning - machine-learning
- enterprise - enterprise
- name: X-Ways Forensics - name: X-Ways Forensics
type: software
description: >- description: >-
Der deutsche Präzisionsskalpell unter den Forensik-Tools mit Der deutsche Präzisionsskalpell unter den Forensik-Tools mit
unübertroffener Effizienz. Besonders geschätzt für blitzschnelle Searches unübertroffener Effizienz. Besonders geschätzt für blitzschnelle Searches
@ -1622,6 +1673,7 @@ tools:
- german-made - german-made
- hex-editor - hex-editor
- name: EnCase - name: EnCase
type: software
description: >- description: >-
Der Veteran der kommerziellen Forensik-Tools mit 25 Jahren Der Veteran der kommerziellen Forensik-Tools mit 25 Jahren
Gerichtserfahrung. EnScript-Programmierung ermöglicht maßgeschneiderte Gerichtserfahrung. EnScript-Programmierung ermöglicht maßgeschneiderte
@ -1652,6 +1704,7 @@ tools:
- certification - certification
- scripting - scripting
- name: FRED - name: FRED
type: software
description: >- description: >-
Forensic Recovery of Evidence Device - spezialisierte Hardware für Forensic Recovery of Evidence Device - spezialisierte Hardware für
Imaging. Kombiniert Write-Blocker, Imager und Analyse-Workstation in einem Imaging. Kombiniert Write-Blocker, Imager und Analyse-Workstation in einem
@ -1680,6 +1733,7 @@ tools:
- professional-lab - professional-lab
- integrated-system - integrated-system
- name: ICSpector - name: ICSpector
type: software
description: >- description: >-
Ein von Microsoft entwickeltes Open-Source-Framework, das eine besondere Ein von Microsoft entwickeltes Open-Source-Framework, das eine besondere
Nische bedient: Die Datensammlung bei Industriekontrollsystemen und Nische bedient: Die Datensammlung bei Industriekontrollsystemen und
@ -1703,6 +1757,104 @@ tools:
- python - python
- binary - binary
- scripting - scripting
- name: "Live Memory Acquisition Procedure"
type: method
description: >-
Standardisiertes Verfahren zur forensisch korrekten Akquisition des
Arbeitsspeichers laufender Systeme. Umfasst Bewertung der
Systemkritikalität, Auswahl geeigneter Tools, Minimierung der
System-Kontamination und Dokumentation der Chain of Custody. Essentiell
für die Sicherung flüchtiger Beweise wie Prozess-Informationen,
Netzwerkverbindungen und Verschlüsselungsschlüssel.
domains:
- incident-response
- law-enforcement
- malware-analysis
phases:
- data-collection
platforms: []
domain-agnostic-software: null
skillLevel: advanced
accessType: null
url: https://www.nist.gov/publications/guide-integrating-forensic-techniques-incident-response
projectUrl:
license: null
knowledgebase: false
tags:
- memory-acquisition
- volatile-evidence
- live-forensics
- ram-dump
- evidence-preservation
- procedure
- name: "Rapid Incident Response Triage on macOS"
type: method
description: >-
Spezialisierte Methodik für die schnelle Incident Response auf
macOS-Systemen mit Fokus auf die Sammlung kritischer forensischer
Artefakte in unter einer Stunde. Adressiert die Lücke zwischen
Windows-zentrierten IR-Prozessen und macOS-spezifischen
Sicherheitsarchitekturen. Nutzt Tools wie Aftermath für effiziente
Datensammlung ohne zeitaufwändige Full-Disk-Images. Besonders wertvoll
für Unternehmensumgebungen mit gemischten Betriebssystem-Landschaften.
domains:
- incident-response
- law-enforcement
- malware-analysis
phases:
- data-collection
- examination
platforms: []
domain-agnostic-software: null
skillLevel: intermediate
accessType: null
url: https://www.sans.org/white-papers/rapid-incident-response-on-macos-actionable-insights-under-hour/
projectUrl:
license: null
knowledgebase:
tags:
- macos
- rapid-response
- triage
- incident-response
- aftermath
- enterprise
- methodology
- apple
- name: "Aftermath"
type: software
description: >-
Jamf's Open-Source-Tool für die schnelle Sammlung forensischer Artefakte
auf macOS-Systemen. Sammelt kritische Daten wie Prozessinformationen,
Netzwerkverbindungen, Dateisystem-Metadaten und Systemkonfigurationen
ohne Full-Disk-Imaging. Speziell entwickelt für die Rapid-Response-Triage
in Enterprise-Umgebungen mit macOS-Geräten. Normalisiert Zeitstempel und
erstellt durchsuchbare Ausgabeformate für effiziente Analyse.
domains:
- incident-response
- law-enforcement
- malware-analysis
phases:
- data-collection
- examination
platforms:
- macOS
domain-agnostic-software: null
skillLevel: intermediate
accessType: download
url: https://github.com/jamf/aftermath/
projectUrl: ''
license: Apache 2.0
knowledgebase: false
tags:
- macos
- incident-response
- triage
- artifact-collection
- rapid-response
- jamf
- enterprise
- commandline
domains: domains:
- id: incident-response - id: incident-response
name: Incident Response & Breach-Untersuchung name: Incident Response & Breach-Untersuchung

View File

@ -337,6 +337,7 @@ const tools = data.tools;
(window as any).switchToAIView = () => switchToView('ai'); (window as any).switchToAIView = () => switchToView('ai');
function createToolCard(tool) { function createToolCard(tool) {
const isMethod = tool.type === 'method';
const hasValidProjectUrl = tool.projectUrl !== undefined && const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null && tool.projectUrl !== null &&
tool.projectUrl !== "" && tool.projectUrl !== "" &&
@ -345,7 +346,9 @@ function createToolCard(tool) {
const hasKnowledgebase = tool.knowledgebase === true; const hasKnowledgebase = tool.knowledgebase === true;
const cardDiv = document.createElement('div'); const cardDiv = document.createElement('div');
const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card'); const cardClass = isMethod ? 'card card-method tool-card' :
hasValidProjectUrl ? 'card card-hosted tool-card' :
(tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card');
cardDiv.className = cardClass; cardDiv.className = cardClass;
cardDiv.style.cursor = 'pointer'; cardDiv.style.cursor = 'pointer';
cardDiv.onclick = () => (window as any).showToolDetails(tool.name); cardDiv.onclick = () => (window as any).showToolDetails(tool.name);
@ -354,8 +357,9 @@ function createToolCard(tool) {
<div class="tool-card-header"> <div class="tool-card-header">
<h3>${tool.name}</h3> <h3>${tool.name}</h3>
<div class="tool-card-badges"> <div class="tool-card-badges">
${hasValidProjectUrl ? '<span class="badge badge-primary">CC24-Server</span>' : ''} ${isMethod ? '<span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>' : ''}
${tool.license !== 'Proprietary' ? '<span class="badge badge-success">OSS</span>' : ''} ${!isMethod && hasValidProjectUrl ? '<span class="badge badge-primary">Self-Hosted</span>' : ''}
${!isMethod && tool.license !== 'Proprietary' ? '<span class="badge badge-success">OSS</span>' : ''}
${hasKnowledgebase ? '<span class="badge badge-error">📖</span>' : ''} ${hasKnowledgebase ? '<span class="badge badge-error">📖</span>' : ''}
</div> </div>
</div> </div>
@ -392,7 +396,7 @@ function createToolCard(tool) {
<polyline points="14 2 14 8 20 8"></polyline> <polyline points="14 2 14 8 20 8"></polyline>
</svg> </svg>
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;"> <span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;">
${tool.license === 'Proprietary' ? 'Prop.' : tool.license.split(' ')[0]} ${isMethod ? 'Methode' : tool.license === 'Proprietary' ? 'Prop.' : tool.license?.split(' ')[0] || 'N/A'}
</span> </span>
</div> </div>
</div> </div>
@ -402,7 +406,11 @@ function createToolCard(tool) {
</div> </div>
<div class="tool-card-buttons" onclick="event.stopPropagation();"> <div class="tool-card-buttons" onclick="event.stopPropagation();">
${hasValidProjectUrl ? ` ${isMethod ? `
<a href="${tool.projectUrl || tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button" style="background-color: var(--color-method); border-color: var(--color-method);">
Zur Methode
</a>
` : hasValidProjectUrl ? `
<div class="button-row"> <div class="button-row">
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary"> <a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
Homepage Homepage

View File

@ -26,6 +26,8 @@
--color-hosted-bg: #f3f0ff; --color-hosted-bg: #f3f0ff;
--color-oss: #10b981; --color-oss: #10b981;
--color-oss-bg: #ecfdf5; --color-oss-bg: #ecfdf5;
--color-method: #3a90ed;
--color-method-bg: #f3f4f6;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 5%); --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 5%);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 10%); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 10%);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 10%); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 10%);
@ -53,6 +55,8 @@
--color-hosted-bg: #2e1065; --color-hosted-bg: #2e1065;
--color-oss: #34d399; --color-oss: #34d399;
--color-oss-bg: #064e3b; --color-oss-bg: #064e3b;
--color-method: #8bbdfa;
--color-method-bg: #2e4e81;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 30%); --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 30%);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 40%); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 40%);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 50%); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 50%);
@ -278,6 +282,11 @@ input[type="checkbox"] {
border-color: var(--color-oss); border-color: var(--color-oss);
} }
.card-method {
background-color: var(--color-method-bg);
border-color: var(--color-method);
}
.grid-auto-fit { .grid-auto-fit {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 350px)); grid-template-columns: repeat(auto-fill, minmax(300px, 350px));
@ -390,6 +399,10 @@ input[type="checkbox"] {
background: linear-gradient(to right, transparent 0%, var(--color-oss-bg) 70%); background: linear-gradient(to right, transparent 0%, var(--color-oss-bg) 70%);
} }
.card-method .tool-tags-container::after {
background: linear-gradient(to right, transparent 0%, var(--color-method-bg) 70%);
}
.tool-card-buttons { .tool-card-buttons {
margin-top: auto; margin-top: auto;
flex-shrink: 0; flex-shrink: 0;
@ -538,6 +551,11 @@ input[type="checkbox"] {
color: white; color: white;
} }
.tool-chip-method {
background-color: var(--color-method);
color: white;
}
/* Consolidated Badge System */ /* Consolidated Badge System */
.badge { .badge {
display: inline-flex; display: inline-flex;

View File

@ -5,19 +5,20 @@ import { z } from 'zod';
const ToolSchema = z.object({ const ToolSchema = z.object({
name: z.string(), name: z.string(),
type: z.string(),
description: z.string(), description: z.string(),
domains: z.array(z.string()).optional().nullable().default([]), domains: z.array(z.string()).optional().nullable().default([]),
phases: z.array(z.string()).optional().nullable().default([]), phases: z.array(z.string()).optional().nullable().default([]),
platforms: z.array(z.string()).default([]), platforms: z.array(z.string()).default([]),
skillLevel: z.string(), skillLevel: z.string(),
url: z.string(), url: z.string(),
license: z.string(), license: z.string().optional().nullable(),
tags: z.array(z.string()).default([]), tags: z.array(z.string()).default([]),
// Optional fields that can be null, undefined, or empty // Optional fields that can be null, undefined, or empty
projectUrl: z.string().optional().nullable(), projectUrl: z.string().optional().nullable(),
knowledgebase: z.boolean().optional().nullable(), knowledgebase: z.boolean().optional().nullable(),
statusUrl: z.string().optional().nullable(), statusUrl: z.string().optional().nullable(),
accessType: z.string().optional(), accessType: z.string().optional().nullable(),
'domain-agnostic-software': z.array(z.string()).optional().nullable(), 'domain-agnostic-software': z.array(z.string()).optional().nullable(),
}); });