# Architecture This document defines Scriptorium's current application architecture and durable development boundaries. ## System Shape Scriptorium is an executable application with three entry paths: CLI `run`, CLI `render`, and the HTTP service started by `serve`. It does not expose a reusable root Go package. The application consumes [Promptkit v0.1.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md) through its supported root package. Promptkit owns prompt execution, preparation, source formats, built-in profiles, model-client behavior, and validation. Scriptorium owns application configuration, executable adapters, prepared-run presentation, process behavior, and HTTP deployment policy. The concrete package inventory is maintained in the [internal overview](../internal/overview.md). ## Dependency Direction ```text cmd/scriptorium | v CLI and HTTP adapters, configuration, defaults, and formatting | v gitea.maximumdirect.net/eric/promptkit ``` - Retained application packages may import Promptkit's root package. - They must not import Promptkit `internal` packages. - They must not import the removed Scriptorium root facade or recreate former framework package families. - Adapter-owned interfaces use Promptkit public values when a consumer-side substitution boundary is needed. - Scriptorium passes omitted framework settings as zero values so Promptkit applies its own defaults. The repository architecture guard enforces these import and removal invariants. ## Retained Boundaries - `internal/adapter/cli` owns commands, flags, configuration precedence, process streams, output files, summaries, and exit codes. - `internal/adapter/http` owns routes, strict JSON DTOs, size limits, response mapping, status mapping, and the restricted artifact reader. - `internal/config` owns discovery and strict decoding of Scriptorium application configuration. - `internal/defaults` owns Scriptorium application and HTTP defaults only. - `internal/format` owns deterministic prepared-run text and JSON presentation. - Promptkit owns framework orchestration and contracts. Its [format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md) and [outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/integrations/openai-compatible-chat.md) are canonical. ## HTTP Artifact Security Boundary Ordinary CLI file loading is provided by Promptkit. Scriptorium's HTTP adapter injects a restricted `promptkit.ArtifactReader` for inbound HTTP requests. That reader denies file references without an artifact root, enforces the configured byte limit, and applies Scriptorium's lexical root-containment rule. The operating system still follows symlinks after the lexical check. The [HTTP API](../api.md) owns observable request outcomes, and [operations](../operations.md) owns deployment permissions and root selection. ## State, Errors, And Secrets Scriptorium has no durable run-state store, checkpoint, cache, or resume mechanism. Recovery is a new request after correcting inputs, configuration, or environment. Adapters map Promptkit public error identities into CLI exits or HTTP statuses without classifying by message text. Raw API keys are not accepted in Scriptorium configuration, CLI arguments, or HTTP payloads, and resolved secrets must not be emitted. ## Architectural Invariants - External YAML and JSON decoding remains strict. - CLI and HTTP behavior remains presentation and transport logic rather than framework orchestration. - Explicit numeric request overrides preserve presence, including zero. - HTTP artifact containment and byte limits remain Scriptorium policy. - No application package depends on Promptkit implementation packages. ## Non-Goals - Do not recreate an in-process Scriptorium framework API or compatibility facade. - Do not copy Promptkit types, defaults, built-in profiles, or implementation into Scriptorium. - Do not move CLI, inbound HTTP, process, or deployment policy into Promptkit. - Do not add durable workflow, archive, or resume behavior. Work that is not implemented belongs in `docs/roadmap/`.