Files
DevRunbook-Public/docs/06-technical-architecture.md
T
DevRunbook release export cfd2804e27
Managed validation / full (push) Successful in 3m18s
Publish DevRunbook source
2026-09-03 04:09:17 +02:00

7.9 KiB

06 — Technical architecture

Architecture decision

Build the MVP as a modular monolith with two deployable process roles from one repository:

  • web: UI, API and synchronous domain operations;
  • worker: imports, Gitea synchronization, artifact generation and maintenance jobs.

Both use PostgreSQL. Built-in playbook packages are mounted or copied into the application image and imported idempotently. No Redis, Elasticsearch or vector database is required for the MVP.

Required workspace

Routine implementation choices are fixed in docs/25-implementation-defaults.md.

apps/
  web/                    Next.js application and route adapters
  worker/                 background process entry point
packages/
  domain/                 entities, value objects, policies, domain errors
  application/            use cases and ports
  persistence/            PostgreSQL repositories and migrations
  playbook-schema/        JSON Schema, semantic validation and canonicalization
  prompt-engine/          composition, linting, provenance and rendering
  repository-intel/       profile normalization, findings and adapters
  integrations-gitea/     Gitea adapter
  artifacts/              Markdown and ZIP generation
  ui/                     reusable design-system components
  config/                 environment parsing and feature flags
content/
  playbooks/              canonical built-in packages
  fixtures/               non-sensitive evaluation fixtures
schemas/                  published interchange schemas
docs/

The bootstrap layout and canonical root commands in docs/40-bootstrap-repository-contract.md are normative. A materially different repository structure requires a blocker-level ADR before Milestone 1 and proof that package boundaries, deployment simplicity and every acceptance criterion remain equivalent. Do not bury domain logic in React components, server actions or HTTP handlers.

Main request flows

Library read

Browser → Next.js route → Library query use case → PostgreSQL projection → response DTO

Prompt composition

Browser → Composition API
        → load immutable playbook version
        → load selected profile revision
        → normalize and validate input
        → resolve policies and compatibility
        → compose prompt blocks
        → lint rendered prompt
        → return preview + provenance + findings

Preview is ephemeral. Final generation creates an immutable generated_run transactionally.

Built-in package import

The runtime imports the 28 P0 package directories under content/playbooks/; the 72-entry seed catalog remains a roadmap and is not silently exposed as executable content.

Worker startup/job
  → enumerate package directories
  → structural schema validation
  → semantic validation
  → canonicalize
  → compute digest
  → upsert playbook identity
  → insert missing immutable version
  → update search projection
  → report package-specific errors

One invalid package must not hide errors in other packages. The release build should fail if bundled packages are invalid.

Gitea synchronization

Scheduled/manual job
  → load encrypted credential
  → verify base URL and capability snapshot
  → bounded API collection
  → normalize evidence
  → store immutable snapshot
  → derive findings
  → optionally propose a new profile revision

The job must support cancellation, per-step timeouts, rate-limit handling and safe partial failure. A partially collected snapshot is never marked complete.

Technology guidance

Frontend

  • Next.js App Router with TypeScript;
  • server rendering for library and detail views where useful;
  • client components only for interactive composer, editors and visualizations;
  • Tailwind CSS and an accessible component foundation;
  • Monaco or CodeMirror for schema-aware YAML/Markdown authoring;
  • a small motion library for functional animation;
  • URL-driven filter state;
  • browser tests using Playwright.

Backend

  • route handlers or a thin API layer;
  • Zod or equivalent validation at transport boundaries;
  • explicit use-case classes/functions;
  • PostgreSQL with a typed migration/ORM layer;
  • a PostgreSQL-backed job table and worker polling/notification mechanism;
  • object artifacts on local disk in MVP, behind a storage port for future S3-compatible support.

During Milestone 0, Codex must verify current stable package compatibility before selecting exact versions. It may not replace the architecture or prohibited-technology boundaries merely because another starter template is familiar.

API style

Use REST-style JSON endpoints with generated OpenAPI documentation. Favor explicit resources and actions over mirroring database tables.

Examples:

  • GET /api/playbooks
  • GET /api/playbooks/{slug}/versions/{version}
  • POST /api/compositions/preview
  • POST /api/runs
  • POST /api/runs/{id}/artifacts/run-pack
  • POST /api/playbook-imports
  • POST /api/repositories/{id}/snapshots

Background jobs

Initial job types:

  • built-in playbook import;
  • user playbook import;
  • Gitea capability refresh;
  • repository snapshot collection;
  • Run Pack generation;
  • artifact retention cleanup;
  • stale integration health check;
  • optional search projection rebuild.

Job records require state, attempt count, lease owner, lease expiry, progress, error code, redacted error detail and timestamps. Jobs must be idempotent or use idempotency keys.

Configuration

Environment values are parsed once into a typed configuration object. Invalid production configuration fails fast.

Required categories:

  • database URL;
  • public base URL;
  • session/auth secrets;
  • encryption master key and key version;
  • content directory;
  • artifact storage directory;
  • maximum import/artifact sizes;
  • allowed Gitea network ranges or host policy;
  • log level;
  • retention settings;
  • feature flags.

Never expose server-only configuration through client bundles.

Storage model

PostgreSQL

Structured application data, canonical package JSON, prompt text, provenance and audit events.

Content directory

Read-only built-in playbook packages distributed with the application. Development mode can watch changes; production imports at startup or explicit migration job.

Artifact directory

Generated ZIP and Markdown files using opaque storage keys. Downloads require authorization; filenames are metadata, not direct filesystem paths.

Failure and degraded-mode design

  • Database unavailable: readiness fails; liveness remains healthy while process is alive.
  • Gitea unavailable: local app and last snapshots continue working.
  • Package import failure: existing valid versions remain available; admin sees precise package errors.
  • Artifact storage unavailable: prompt generation still succeeds, binary export shows a recoverable error.
  • Worker unavailable: synchronous reads/composition work; jobs show queued/stalled state.

Identity and first run

Authentication, workspace authorization and setup lifecycle follow docs/26-authentication-authorization.md and docs/31-first-run-and-instance-lifecycle.md. Database relations follow database/reference-schema.sql.

Migration policy

  • forward migrations are reviewed and idempotent where possible;
  • destructive changes require a two-release expand/migrate/contract strategy;
  • application startup must not silently apply irreversible migrations in production unless explicitly configured;
  • backup guidance appears before migrations with destructive potential;
  • migration version is exposed in admin health.

Architectural constraints

  • no domain import from framework-specific code;
  • adapters depend inward on ports, never the reverse;
  • external API payloads are mapped to internal normalized models;
  • generated prompt output is based only on immutable snapshots;
  • direct forge writes require a separate future ADR and permission model;
  • direct code execution requires a separate isolation architecture and is prohibited in MVP code paths.