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

ComponentTechnology
LanguageVanilla JS (ES6+)
StorageIndexedDB (4 stores: documents, versions, settings, folders)
MarkdownCustom in-browser renderer
EncryptionPBKDF2-SHA256 (310,000 iterations) + AES-256-GCM via SubtleCrypto
TestingVitest
OfflineService Worker
CI/CDGitHub Actions (security.yml — TruffleHog + Trivy + Semgrep)
Zonestaging/

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_CRYPTO wrapper intercepts save/get for the content field
  • storage-crypto.js — First extracted module from the monolithic app.js; handles PBKDF2 key derivation and AES-256-GCM encryption/decryption
  • style.css — Catppuccin theme styling
  • service-worker.js — Offline capability

IndexedDB database name: DocForgeDB v3.

Key Decisions

DecisionRationale
Zero external runtime dependenciesBrowser-native APIs only — no build step, no npm install, works from file://
IndexedDB for persistenceLocal-first; 4 stores cover all data concerns without a backend
PBKDF2 + AES-256-GCM via SubtleCryptoEncrypts document content only; title, folderId, and dates stay plaintext for sidebar listing without requiring vault unlock
Passphrase never persistedAES key held in module closure for session duration only; vault salt stored as base64 in settings store
_encrypted: true flag as authoritative markerStorageCrypto.isEncrypted() is a secondary heuristic (base64 detection); the flag is the source of truth
Content-only encryptionPartial encryption allows search and listing without unlocking the vault
XSS mitigation in vault prompt UIDOM APIs used exclusively (no innerHTML) after security hook flagged risk
Security CI in calibration modeAll 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.js is the first extracted module (Phase 5 of staging remediation plan)

Lessons Learned

  • Partial encryption is a viable UX strategy — encrypting only the content field 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 _encrypted flag and are read as-is; re-saving after unlock encrypts them transparently. No destructive migration required.
  • Module extraction over monolith — storage-crypto.js was the first module extracted from a 2742-line app.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