DocForge
Zero-dependency markdown document editor and knowledge management system with local-first IndexedDB storage. Single-page application running entirely in the browser — no server, no cloud sync.
Overview
DocForge provides a full-featured markdown editing environment with split-pane live preview, 20+ built-in document templates, folder organization, version history, and export to 8 formats. All data is persisted locally via IndexedDB in the browser. A service worker enables offline use. The app ships as a single HTML file (docforge_v1.html) with no external runtime dependencies.
Currently in staging/ zone under ops-core compliance evaluation.
Tech Stack
| Component | Technology |
|---|---|
| Language | Vanilla JS (ES6+) |
| Storage | IndexedDB (4 stores: documents, versions, settings, folders) |
| Markdown | Custom in-browser renderer |
| Encryption | PBKDF2-SHA256 (310,000 iterations) + AES-256-GCM via SubtleCrypto |
| Testing | Vitest |
| Offline | Service Worker |
| CI/CD | GitHub Actions (security.yml — TruffleHog + Trivy + Semgrep) |
| Zone | staging/ |
Architecture
docforge_v1.html— Single-page application entry point (138KB)app.js— Main application logic (2742 lines, modularization in progress)db.js— IndexedDB wrapper and store management (178 lines);DB_CRYPTOwrapper intercepts save/get for thecontentfieldstorage-crypto.js— First extracted module from the monolithicapp.js; handles PBKDF2 key derivation and AES-256-GCM encryption/decryptionstyle.css— Catppuccin theme stylingservice-worker.js— Offline capability
IndexedDB database name: DocForgeDB v3.
Key Decisions
| Decision | Rationale |
|---|---|
| Zero external runtime dependencies | Browser-native APIs only — no build step, no npm install, works from file:// |
| IndexedDB for persistence | Local-first; 4 stores cover all data concerns without a backend |
| PBKDF2 + AES-256-GCM via SubtleCrypto | Encrypts document content only; title, folderId, and dates stay plaintext for sidebar listing without requiring vault unlock |
| Passphrase never persisted | AES key held in module closure for session duration only; vault salt stored as base64 in settings store |
_encrypted: true flag as authoritative marker | StorageCrypto.isEncrypted() is a secondary heuristic (base64 detection); the flag is the source of truth |
| Content-only encryption | Partial encryption allows search and listing without unlocking the vault |
| XSS mitigation in vault prompt UI | DOM APIs used exclusively (no innerHTML) after security hook flagged risk |
| Security CI in calibration mode | All new staging repos start in calibration through 2026-04-13 to establish baseline before switching to enforcing mode |
Current Status
Zone: staging/ (evaluation) Last Updated: 2026-03-13
Compliance Progress
-
.github/workflows/security.yml— TruffleHog + Trivy + Semgrep -
SECURITY.md— Vulnerability reporting -
.github/PULL_REQUEST_TEMPLATE.md— PR checklist -
.github/CODEOWNERS— Default ownership -
.security-config.yml— Calibration mode (through 2026-04-13)
Known Gaps
- Test coverage below 60% target (remediation plan Phase 4)
- CI/CD lint + test pipeline pending (security.yml deployed; general CI next)
- App.js modularization ongoing —
storage-crypto.jsis the first extracted module (Phase 5 of staging remediation plan)
Lessons Learned
- Partial encryption is a viable UX strategy — encrypting only the
contentfield while leaving metadata plaintext allows search and sidebar listing without vault unlock, eliminating a significant friction point. - DOM API discipline for security — vault passphrase UI must use DOM APIs exclusively. Any innerHTML usage in a vault prompt is an XSS risk flagged by the security hook.
- Migration path for existing records — documents written before encryption have no
_encryptedflag and are read as-is; re-saving after unlock encrypts them transparently. No destructive migration required. - Module extraction over monolith —
storage-crypto.jswas the first module extracted from a 2742-lineapp.js. Full modularization is a staged effort; extract by concern, not by size.
See Also
- cryptographic-key-exchange — pattern for PBKDF2 + AES-GCM key derivation, directly applied in
storage-crypto.js - cipher — @ap/crypto shared library; related cryptographic tooling in the AP ecosystem
- athenaeum — related knowledge management project for comparison of local-first vs. server-backed approaches