This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user