# https://github.com/ThreatRecall/zettelforge Project Manual

Generated at: 2026-07-06 22:40:06 UTC

## Table of Contents

- [Overview & System Architecture](#page-1)
- [Memory Pipeline: Extraction, Storage & Retrieval](#page-2)
- [Detection Rules, OSINT & Integrations](#page-3)
- [Operations, Security & Deployment](#page-4)

<a id='page-1'></a>

## Overview & System Architecture

### Related Pages

Related topics: [Memory Pipeline: Extraction, Storage & Retrieval](#page-2), [Detection Rules, OSINT & Integrations](#page-3), [Operations, Security & Deployment](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/ThreatRecall/zettelforge/blob/main/README.md)
- [ARCHITECTURE.md](https://github.com/ThreatRecall/zettelforge/blob/main/ARCHITECTURE.md)
- [docs/explanation/architecture.md](https://github.com/ThreatRecall/zettelforge/blob/main/docs/explanation/architecture.md)
- [docs/explanation/design-philosophy-dual-hemisphere.md](https://github.com/ThreatRecall/zettelforge/blob/main/docs/explanation/design-philosophy-dual-hemisphere.md)
- [docs/explanation/two-phase-pipeline.md](https://github.com/ThreatRecall/zettelforge/blob/main/docs/explanation/two-phase-pipeline.md)
- [docs/explanation/zettelkasten-philosophy.md](https://github.com/ThreatRecall/zettelforge/blob/main/docs/explanation/zettelkasten-philosophy.md)
</details>

# Overview & System Architecture

ZettelForge is a threat-intelligence knowledge management system built on the Zettelkasten note-taking methodology. It ingests CTI inputs — YARA rules, Sigma rules, OSINT feeds, free-form reports — extracts structured entities (IPs, hashes, CVEs, detection rule references), and persists them as atomic, linked "memory notes" inside a knowledge graph. Retrieval and recall operate on that graph instead of on ad-hoc documents, so emergent structure can replace fixed taxonomy. Source: [README.md:1-60]()

## Design Philosophy

ZettelForge explicitly separates its concerns into two cooperating "hemispheres." The left hemisphere covers ingestion, indexing, and graph construction — turning raw CTI text and rules into typed entities and relations. The right hemisphere covers recall, synthesis, and response — answering analyst queries by traversing the graph and composing notes. The split keeps write paths (potentially adversarial) isolated from read paths (used to influence analyst decisions), which is foundational to the project's security posture. Source: [docs/explanation/design-philosophy-dual-hemisphere.md:1-90]()

The project borrows directly from Niklas Luhmann's Zettelkasten practice: each note is atomic, each note has a stable identifier, and notes connect via typed relations rather than folders or tags. This lets the corpus grow into structure organically and lets analysts follow links across notes instead of searching by keyword. Source: [docs/explanation/zettelkasten-philosophy.md:1-70]()

## Two-Phase Pipeline

Write traffic flows through a two-phase pipeline. Phase 1 normalizes and validates incoming material, extracts entities, and emits candidate `MemoryNote` objects. Phase 2 applies project-specific defenses — quarantine, audit, or block — and only then commits the note into the knowledge graph. Separating extract from commit means adversarial content can be dropped or quarantined before it can influence retrieval. Source: [docs/explanation/two-phase-pipeline.md:1-130]()

Detection rules have their own branch of the pipeline. YARA and Sigma content is parsed into first-class entities (rules, CCCS tiers, sources) and the resulting notes carry a typed `DetectionMeta` extension in their metadata, so per-rule provenance survives beyond the note body. Source: [ARCHITECTURE.md:40-180]()

| Phase   | Responsibility                          | On policy violation |
|---------|-----------------------------------------|---------------------|
| Extract | Parse inputs, build entities, emit notes | Reject malformed input |
| Defend  | Run memory-defense policy, persist to KG | Quarantine, audit, or block |

## Architecture Layers

The high-level architecture is composed of four cooperating layers. Collectors and ingest adapters sit at the edge; the core pipeline of extractors and the entity indexer sits in the middle; the knowledge graph and memory store sit beneath; and the recall / response surface — including the RFC-015 web GUI and the recall endpoints — sits on top. Optional capabilities, such as the AGE-120 OSINT live enrichers, are opt-in extras, so their network reachability is not a baseline property of the library. Source: [docs/explanation/architecture.md:1-200]()

```mermaid
flowchart LR
  A[CTI Sources<br/>YARA / Sigma / OSINT / Reports] --> B[Ingest Adapters]
  B --> C[Two-Phase Pipeline<br/>extract -> defend]
  C --> D[Entity Indexer]
  D --> E[Knowledge Graph<br/>+ Memory Notes]
  E --> F[Recall / Web GUI<br/>RFC-015]
  C -.policy.-> G[Memory Defense<br/>audit / block / quarantine]
  G -.reject or quarantine.-> C
```

Security and governance are layered on top of the pipeline rather than retrofitted. Memory-defense modes (audit, block, quarantine), the AGE-127 prompt-injection / retrieval-poisoning guardrails, and an architecture-governance ratchet (currently enforced at 67% in CI, with a stated target of 80%) all live in named configuration namespaces. That lets operators disable or replace policy enforcement in one place without restructuring the core pipeline. Source: [ARCHITECTURE.md:200-360]()

## Release Trajectory

Recent releases trace the architectural direction. v2.6.x shipped the RFC-015 web GUI and a config editor (with v2.6.1 and v2.6.2 fixing review blockers in the `/config` page). v2.7.0 introduced write-time MemSAD memory defenses together with the RFC-017 threat model. v2.8.0 extended the RFC-016 OSINT layer with passive ingest and live AGE-120 enrichers, added AGE-127 prompt-injection guardrails across the memory pipeline, and laid the RFC-018 enrichment-job ledger as Phase 0. The recurring pattern is: extend the core pipeline, then harden the read path, then expose configuration through the GUI. Source: [README.md:60-200]()

---

<a id='page-2'></a>

## Memory Pipeline: Extraction, Storage & Retrieval

### Related Pages

Related topics: [Overview & System Architecture](#page-1), [Detection Rules, OSINT & Integrations](#page-3), [Operations, Security & Deployment](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/zettelforge/memory_manager.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/memory_manager.py)
- [src/zettelforge/memory_store.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/memory_store.py)
- [src/zettelforge/memory_updater.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/memory_updater.py)
- [src/zettelforge/memory_evolver.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/memory_evolver.py)
- [src/zettelforge/vector_memory.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/vector_memory.py)
- [src/zettelforge/vector_retriever.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/vector_retriever.py)
- [src/zettelforge/entity_indexer.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/entity_indexer.py)
</details>

# Memory Pipeline: Extraction, Storage & Retrieval

The Memory Pipeline is the substrate that turns unstructured cyber-threat-intelligence (CTI) text — incident reports, IOC feeds, YARA/Sigma rules, OSINT observations — into structured, queryable, defensible knowledge. It coordinates ingestion, persistence, semantic recall, and lifecycle evolution while enforcing write-time safety checks against prompt-injection and retrieval-poisoning attempts.

## Pipeline Overview

The pipeline is split into four cooperating layers. `memory_manager.py` is the orchestrator that callers (agents, REST endpoints, OSINT executors) invoke to ingest notes. It delegates persistence to `memory_store.py`, vector indexing to `vector_memory.py`, and lifecycle rewrites to `memory_updater.py` / `memory_evolver.py`. Recall is served by `vector_retriever.py`, which performs semantic lookups and returns candidate `MemoryNote` objects for downstream reasoning.

```mermaid
flowchart LR
  A[CTI Text] --> B[memory_manager]
  B --> C[entity_indexer]
  C --> D[MemoryNote + Metadata]
  B --> E[MemSAD defenses]
  E -- audit --> P[(memory_store)]
  E -- block --> X[Reject]
  E -- quarantine --> Q[Quarantine]
  D --> P
  P --> F[vector_memory]
  F --> G[(Vector index)]
  H[Recall query] --> I[vector_retriever]
  G --> I
  I --> J[Notes + provenance]
  P --> K[memory_updater/evolver]
  K --> P
```

Defenses are applied on the write path before a note is committed, ensuring that even if raw text contains adversarial instructions, the persisted store remains trustworthy.

## Extraction: From Text to MemoryNotes

`memory_manager.py` is the entry point for new content. It normalizes the input, hands the text to `entity_indexer.py` for IOC extraction, and stitches the entities together with a typed metadata envelope into a `MemoryNote`. The `EntityExtractor` recognizes IPv4 and, since the community-driven addition tracked in issue #47, IPv6 addresses; YARA rule references (issue #46); Sigma rule IDs (issue #45); and other CTI-specific identifiers.

Detection-rule ingest (YARA, Sigma) produces richer per-rule metadata — CCCS tier, source provenance, rule references — that historically only lived in the note body. Issue #71 calls for promoting this into a typed `DetectionMeta` extension on `MemoryNote.Metadata` so that downstream consumers (KG resolvers, recall rankers) can branch on structured fields rather than re-parsing markdown. `Source: [src/zettelforge/entity_indexer.py]()` `Source: [src/zettelforge/memory_manager.py]()`

## Storage: Notes, Vectors, and Write-Time Defenses

Two stores back each note. `memory_store.py` holds the canonical, addressable record: identifier, body, timestamps, tags, and the structured `Metadata` envelope. `vector_memory.py` materializes an embedding view used for semantic recall; the vector store is treated as a derived index and can be rebuilt from the canonical store if it drifts.

Two distinct defense regimes guard the write path:

- **MemSAD** (added in v2.7.0) implements audit / block / quarantine modes selected via `governance.memory_defense`. Block prevents the note from being stored; quarantine diverts it to a holding area for human review; audit allows storage with an attached warning. `Source: [src/zettelforge/memory_store.py]()`
- **AGE-127 guardrails** (added in v2.8.0) run across the memory pipeline to neutralize prompt-injection and retrieval-poisoning patterns before they propagate into the vector index or into prompt context assembled by a retriever. `Source: [src/zettelforge/vector_memory.py]()`

Together these layers ensure the canonical store is the source of truth, while the vector index inherits the same cleanliness guarantees.

## Retrieval & Evolution

`vector_retriever.py` resolves a recall request into ranked candidate notes. It queries `vector_memory.py`, optionally joins results against metadata filters (e.g., only `DetectionMeta`-bearing notes for a Sigma lookup), and surfaces provenance so that the calling agent can credit or attribute the material. Issue #176 records follow-ups that improve OSINT→recall visibility, so collectors can justify why an enricher’s data appears in a result.

Lifecycle changes — corrections, supersessions, fact decay, and KG-backed enrichment from RFC-016 collectors — flow through `memory_updater.py` and `memory_evolver.py`. RFC-016 Phase 1.5 (issue #154) wires `osint` collectors to the same manager, so the Knowledge Graph ingest path and the note path share a single, defense-aware commit boundary. Updaters are expected to re-run the same MemSAD and AGE-127 gates as fresh writes; evolves are the bridge between per-note edits and broader schema/shape changes. `Source: [src/zettelforge/memory_updater.py]()` `Source: [src/zettelforge/memory_evolver.py]()` `Source: [src/zettelforge/vector_retriever.py]()`

## Operational Notes

Callers should treat `memory_manager` as the only sanctioned ingest entry point so that defenses cannot be bypassed by writing to the store directly. When extending entity extraction, add the corresponding regex in `entity_indexer.py` and a typed field on `MemoryNote.Metadata` so recallers can index on structure instead of text. For detection-rule content, prefer attaching a `DetectionMeta` envelope so downstream resolvers can iterate without re-parsing. For new recall patterns, prefer composing existing `vector_retriever` filters over ad-hoc text scans; this keeps the retrieval-poisoning guardrails effective and keeps provenance intact.

---

<a id='page-3'></a>

## Detection Rules, OSINT & Integrations

### Related Pages

Related topics: [Overview & System Architecture](#page-1), [Memory Pipeline: Extraction, Storage & Retrieval](#page-2), [Operations, Security & Deployment](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/zettelforge/detection/__init__.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/detection/__init__.py)
- [src/zettelforge/detection/base.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/detection/base.py)
- [src/zettelforge/detection/consumers.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/detection/consumers.py)
- [src/zettelforge/detection/explainer.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/detection/explainer.py)
- [src/zettelforge/sigma/__init__.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/sigma/__init__.py)
- [src/zettelforge/sigma/cli.py](https://github.com/ThreatRecall/zettelforge/sigma/cli.py)
</details>

# Detection Rules, OSINT & Integrations

The `detection/` and `sigma/` packages together form ZettelForge's ingestion layer for security detection content and its hook into the broader knowledge-graph memory pipeline. They treat YARA and Sigma rules as first-class artifacts, convert them into `MemoryNote` records with typed metadata, and expose a CLI surface for bulk import. OSINT collectors (RFC-016) and live AGE-120 enrichers layer on top of this foundation to pull external context for entities surfaced by detection content.

## Detection Package Layout

The `src/zettelforge/detection/` package exposes a small public surface through `__init__.py`, re-exporting the abstract `DetectionRule` type and the rule-to-entities conversion helper used by the rest of the pipeline. `Source: [src/zettelforge/detection/__init__.py:1-40]()`

`base.py` defines the `DetectionRule` abstract base class that both YARA and Sigma implementations extend. The base encapsulates common attributes — rule identifier, title, description, severity, references, and tags — and exposes a `rule_to_entities` method that materializes transient `Entity` and `Relation` objects for the knowledge graph. This method is the boundary where a parsed detection artifact becomes a graph-addressable object. `Source: [src/zettelforge/detection/base.py:1-120]()`

The `DetectionMeta` concept mentioned in Phase 4 review (issue #71) is intended to extend `MemoryNote.Metadata` so that per-rule metadata such as YARA's CCCS tier or Sigma's status fields survive on the persisted note rather than only on the transient entity/relations returned by `rule_to_entities`. This addresses governance drift detected when CCCS tier data was being lost at the persist boundary. `Source: [src/zettelforge/detection/base.py:80-140]()`

## Sigma Subpackage

The `src/zettelforge/sigma/` subpackage mirrors the `detection/` shape with its own `__init__.py` and a `cli.py` entry point. The CLI is the operator-facing surface for bulk detection ingest added in v2.8.0, accepting a directory of Sigma rule YAML files and streaming them through the parsing and entity-extraction pipeline. `Source: [src/zettelforge/sigma/__init__.py:1-30]()`

Sigma rule ID extraction (issue #45) lives alongside the entity extractor in `src/zettelforge/entity_indexer.py`, recognizing patterns like `sigma:apt28_cobalt_strike` and `Sigma Rule: win_susp_powershell_encoded_cmd` from CTI text. Once extracted, rule IDs are resolved through the same detection-rule registry that the `sigma` subpackage consults, producing bidirectional links between CTI notes and the Sigma rules they cite. `Source: [src/zettelforge/sigma/cli.py:1-80]()`

## Consumers and Explainability

`consumers.py` is where detection rules meet the memory pipeline. It accepts parsed `DetectionRule` instances and writes them as `MemoryNote` records, applying the same write-time MemSAD defenses introduced in v2.7.0 (audit, block, and quarantine modes governed by `governance.memory_defense`). Consumers also handle bulk detection-ingest hardening from v2.8.0 — deduping by rule identity, validating metadata completeness before persist, and emitting audit log entries for downstream provenance queries. `Source: [src/zettelforge/detection/consumers.py:1-160]()`

`explainer.py` provides a reverse-direction capability: given a detection rule that has already been ingested, it can surface which CTI notes, OSINT records, or recall results cite it. This is the read path used by recall queries that want to answer "why did this rule fire in our context?" — it walks the knowledge graph from a rule back through its relations and renders an explanation suitable for a security analyst. `Source: [src/zettelforge/detection/explainer.py:1-100]()`

## OSINT Layer and Integrations

RFC-016 introduces an OSINT collector scaffold that pairs with the detection layer: when `rule_to_entities` produces entities (IPs, hashes, domains), the OSINT executor can match them against registered collectors to produce validated `CollectorTuple` rows for knowledge-graph ingest. Issue #154 tracks the executor, KG ingest, resolver wiring, and BGP path for this flow. `Source: [src/zettelforge/detection/base.py:100-180]()`

AGE-120 enrichers (live OSINT) sit behind an opt-in `[osint]` extra and add maigret-style username lookups and similar network calls. Follow-ups tracked in issue #176 harden the event-loop handling and improve OSINT→recall visibility so enrichments show up in the same query surface as detection rules. `Source: [src/zettelforge/detection/consumers.py:120-200]()`

| Layer | Component | Input | Output |
|-------|-----------|-------|--------|
| Parse | `detection/base.py` | Rule source (YARA/Sigma) | `DetectionRule` + entities |
| Persist | `detection/consumers.py` | `DetectionRule` | `MemoryNote` with `DetectionMeta` |
| Ingest | `sigma/cli.py` | Rule directory | Bulk note records |
| Recall | `detection/explainer.py` | Rule ID | Citing notes and relations |
| Enrich | RFC-016 collectors | Entity | `CollectorTuple` rows |

AGE-127 prompt-injection and retrieval-poisoning guardrails, also shipped in v2.8.0, run across this whole stack: detection rule bodies and OSINT collector outputs pass through the same content-sanitization filters as the rest of the memory pipeline, so an attacker cannot smuggle malicious instructions through a Sigma rule's `description` field or an OSINT collector's free-text response. `Source: [src/zettelforge/detection/consumers.py:60-120]()`

---

<a id='page-4'></a>

## Operations, Security & Deployment

### Related Pages

Related topics: [Overview & System Architecture](#page-1), [Memory Pipeline: Extraction, Storage & Retrieval](#page-2), [Detection Rules, OSINT & Integrations](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/zettelforge/memory_defense.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/memory_defense.py)
- [src/zettelforge/governance_validator.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/governance_validator.py)
- [src/zettelforge/config.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/config.py)
- [src/zettelforge/backend_factory.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/backend_factory.py)
- [src/zettelforge/edition.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/edition.py)
- [src/zettelforge/llm_client.py](https://github.com/ThreatRecall/zettelforge/blob/main/src/zettelforge/llm_client.py)
</details>

# Operations, Security & Deployment

## Overview

Operations, Security & Deployment in ZettelForge is the cross-cutting concern of keeping the memory pipeline safe, configurable, and observable across editions and LLM backends. It spans three overlapping concerns:

- **Memory defenses** at write time to prevent poisoning and prompt-injection.
- **Governance enforcement** that ratchets a coverage target upward rather than letting it drift down.
- **Runtime configuration and backend selection** that determines which features are available, which LLM is invoked, and how telemetry is shaped.

This page is bounded to the security and operational primitives that sit on top of the core knowledge graph; the retrieval/recall side and OSINT collectors are described elsewhere.

## Memory Defense and Threat Model

ZettelForge v2.7.0 introduced write-time MemSAD memory defenses, and v2.8.0 extended them with AGE-127 prompt-injection and retrieval-poisoning guardrails. The defenses live in a dedicated module so that the same enforcement runs in front of any ingest path — rule loading, OSINT rows, and raw CTI notes all funnel through the same gate.

The defense module is configured through the `governance.memory_defense` namespace and supports three operating modes:

- **audit** — observe and log policy violations without blocking writes.
- **block** — refuse the write and raise a structured error to the caller.
- **quarantine** — accept the write into a separate, low-trust store and tag it for downstream review.

The mode is selected at deployment time and applies uniformly to the memory pipeline, which is what makes the defenses usable as an organization-wide control rather than a per-feature flag. RFC-017 captures the threat model and rollout plan that the module implements.

Source: [src/zettelforge/memory_defense.py:1-120]()

## Governance and the Coverage Ratchet

Governance is enforced through a dedicated validator that is wired into the CI pipeline. The validator checks structural coverage of governance rules and refuses to merge if coverage regresses below the current threshold.

Issue #51 tracks ratcheting the threshold from 67% toward 80% in small steps. The plan is intentionally conservative: hold CI at 67% to prevent regression, track the delta explicitly, and only raise the bar after the existing rules are actually enforced — a direct response to the kind of governance drift flagged in external code review, where an 80% target had been walked back to 67% to match reality.

Source: [src/zettelforge/governance_validator.py:1-80]()

## Configuration, Editions, and Backend Selection

Runtime configuration is loaded by `config.py`, which exposes a typed settings object. The settings object is consumed by the rest of the system; the web GUI's `/config` page (added in RFC-015, hotfixed in v2.6.1 and v2.6.2) renders it and writes changes back through a single `saveConfigForm` endpoint. v2.6.1 fixed a `NameError` caused by a closure-scoped `_to_dict`, and v2.6.2 surfaced enum-style settings as dropdowns so free-text input could no longer silently desync the typed model.

Feature availability is gated by an `edition.py` module. Editions determine which modules — for example, OSINT enrichers from RFC-016, or the AGE-120 live enrichers from v2.8.0 — are importable. Code paths that depend on a feature guard against being loaded under the wrong edition rather than failing at runtime.

The `backend_factory.py` module selects the LLM backend (local vs. hosted) based on the active configuration, and `llm_client.py` wraps the chosen provider with generation-budget controls. v2.8.0 made those budgets configurable, which is the primary deployment-time knob for cost and latency on the LLM path.

Source: [src/zettelforge/config.py:1-120]()
Source: [src/zettelforge/edition.py:1-80]()
Source: [src/zettelforge/backend_factory.py:1-100]()
Source: [src/zettelforge/llm_client.py:1-120]()

## Deployment Workflow

A typical deployment flow ties the modules above together:

1. **Load configuration** via `config.py`; resolve the active edition via `edition.py`.
2. **Construct the LLM backend** through `backend_factory.py`, applying generation budgets from settings.
3. **Initialize memory defense** in the mode specified under `governance.memory_defense`.
4. **Run governance validation** in CI to confirm coverage has not regressed.
5. **Serve the web GUI**, where the `/config` page now reflects the typed settings and saves through a working endpoint.

| Stage | Module | Output |
|---|---|---|
| Settings load | `config.py` | Typed settings object |
| Edition gate | `edition.py` | Feature flags |
| Backend select | `backend_factory.py`, `llm_client.py` | Configured LLM client |
| Memory guard | `memory_defense.py` | Audit / block / quarantine policy |
| CI gate | `governance_validator.py` | Pass/fail on coverage threshold |

## Operational Notes

- The `/config` Save Changes button (broken in v2.6.0, fixed in v2.6.1) now persists typed values; v2.6.2 surfaces enums as dropdowns to remove free-text drift.
- OSINT collectors and the AGE-120 enrichers are opt-in via the `[osint]` extra, which keeps the default deployment surface small.
- Memory-defense mode and the governance coverage threshold are the two deployment-time controls most likely to be changed during incident response.
- v2.8.0 also lays the RFC-018 Phase 0 enrichment job ledger foundation; operators should expect a new ledger file to appear alongside the knowledge graph in the next phase.

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: ThreatRecall/zettelforge

Summary: Found 11 structured pitfall item(s), including 2 high/blocking item(s). Top priority: Security or permission risk - Security or permission risk requires verification.

## 1. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ThreatRecall/zettelforge/issues/71

## 2. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ThreatRecall/zettelforge/issues/176

## 3. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/ThreatRecall/zettelforge

## 4. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/ThreatRecall/zettelforge

## 5. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/ThreatRecall/zettelforge

## 6. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/ThreatRecall/zettelforge

## 7. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/ThreatRecall/zettelforge

## 8. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ThreatRecall/zettelforge/issues/36

## 9. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/ThreatRecall/zettelforge/issues/154

## 10. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/ThreatRecall/zettelforge

## 11. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/ThreatRecall/zettelforge

<!-- canonical_name: ThreatRecall/zettelforge; human_manual_source: deepwiki_human_wiki -->
