Skip to content
Developer Guide

Architecture overview

The stack, the Django app layout, and a map from user-facing features to the code that implements them.

This page maps RedScribe’s stack, its Django app boundaries, and the order requests flow through middleware, so you can find the code that owns a given feature and understand what already ran by the time your view or template gets a request.

RedScribe is a monolithic Django project. It uses server-rendered templates plus HTMX for interactivity, with no separate frontend build or SPA framework for the app itself. The only client-side JavaScript bundles are the Tiptap rich-text editor, a CVSS calculator widget, and a password-strength meter, covered in Frontend asset builds.

Layer Technology
Backend framework Django, server-rendered templates
Interactivity HTMX (no SPA framework)
Styling Tailwind CSS, compiled from tailwind-src/input.css
Rich text editing Tiptap (ProseMirror-based), bundled from editor-src/main.js
Database PostgreSQL
PDF rendering WeasyPrint
Word (.docx) generation python-docx + docxtpl (Jinja2-driven templating over a real .docx)
Auth Django’s own auth, django-allauth for OAuth, django-otp for TOTP MFA
App server gunicorn, behind nginx in production
Static files WhiteNoise (compressed/manifest storage in prod)

Two independent settings modules select dev versus prod behavior, config.settings.dev and config.settings.prod, both layered on config.settings.base. See Local development for what actually differs between them.

INSTALLED_APPS (from config/settings/base.py), each a directory under apps/:

App Owns
apps.accounts Users, roles/permissions (permissions_registry.py), login/MFA/session middleware, password validators, user & role management screens
apps.engagements The Engagement model, status lifecycle, membership, scope-change approval
apps.crypto Per-engagement AES-256-GCM encryption, the instance root key, encrypted-blob file access
apps.findings Findings, the review/QA workflow, the vulnerability catalogue, classifications, scanner import (Nmap/Burp/Nuclei), field visibility (ContentSectionDefinition), comment threads
apps.checklist Checklist templates and per-engagement runs
apps.reports Report Profiles, the report IR, all four exporters, branding, and trends (see Report rendering pipeline)
apps.audit The hash-chained append-only audit log, request-logging middleware, retention/purge
apps.notifications In-app + email notifications, per-user preferences
apps.search Global search across engagements/findings
apps.feature_flags The single-row instance-wide FeatureFlags toggle set
apps.backup Server-side-only encrypted pg_dump/pg_restore backup/restore
apps.clients Client companies, client-portal accounts, the client portal itself, finding view-tracking
apps.licensing Commercial license key verification and the footer’s “Licensed to X” display

Route ownership matches this 1:1. See config/urls.py for the full URL include list, also the fastest way to see every top-level route in the app.

MIDDLEWARE in config/settings/base.py runs, notably: IdleTimeoutMiddleware → MFAEnforcementMiddleware → ClientPortalAccessMiddleware → AuditLogMiddleware (audit logging runs last, so it sees the final, fully-processed request/response, including whatever the earlier middleware decided, like a forced MFA redirect).

  • templates/base/ holds shared chrome that every app’s templates extend: base.html (the sidebar and top bar), settings_base.html (the admin settings area, with its menu in _settings_nav.html, driven by the settings_pages template tag), and partials like _breadcrumbs.html, _pagination.html, _toasts.html, _import_preview.html, and _shortcuts.html.
  • templates/<app>/ is one directory per app, mirroring the apps/ layout.
  • static/vendor/ holds built JS bundles (redscribe-editor.bundle.js, redscribe-datepicker.bundle.js, redscribe-password-strength.bundle.js) and vendored third-party files (cvss40.js, flatpickr.min.css), built from editor-src/, datepicker-src/, strength-src/. See Frontend asset builds.
  • static/js/ holds small, unbundled scripts loaded only by the pages that need them, all CSP-safe (no inline handlers): autosave with conflict detection (redscribe-autosave.js), import previews (redscribe-import-preview.js), keyboard shortcuts declared through data-shortcut attributes (redscribe-shortcuts.js), and hover/focus details for the posture grid and trends chart (redscribe-hover-detail.js).
  • static/css/tailwind.css is compiled from tailwind-src/input.css. editor.css is hand-matched to the same color tokens (see COLOR_SCHEME.md in the repo root) since the editor iframe isn’t run through Tailwind.
  • static/fonts/ holds self hosted Plus Jakarta Sans (UI) and JetBrains Mono / Source Code Pro (code/mono).
Feature Key files
Engagement lifecycle & scope changes apps/engagements/lifecycle.py, views.py, models.py
Finding review/QA workflow apps/findings/review.py, review_views.py
Vulnerability catalogue approval apps/findings/catalogue_views.py, catalogue_io.py
Scanner import apps/findings/scan_import.py, apps/findings/importers/{nmap,burp,nuclei}.py
Field visibility / content sections apps/findings/field_visibility_views.py, models.ContentSectionDefinition
Checklist runs apps/checklist/services.py, item_views.py
Report IR & exporters apps/reports/report_ir.py, assembly.py, block_registry.py, {md,html,pdf,docx}_export.py (see Report rendering pipeline)
Per-engagement encryption apps/crypto/services.py, root_key.py
Audit log / chain integrity apps/audit/integrity.py, middleware.py, retention.py
Backup/restore apps/backup/pg.py, crypto.py, impact.py
License key verification apps/licensing/verify.py, status.py

The app itself is a fairly ordinary Django monolith, but how it’s deployed and what stays safe under concurrent load is its own topic. See Scaling & concurrency model for the single box deployment shape, which parts of the app are protected by a real Postgres lock versus an in-process one, and what changes as usage grows toward the higher end of the sizing table.