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

213 lines
7.9 KiB
Markdown

# 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`.
```text
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
```text
Browser → Next.js route → Library query use case → PostgreSQL projection → response DTO
```
### Prompt composition
```text
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.
```text
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
```text
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.