12 KiB
Decision log
| ID | Status | Decision | Rationale |
|---|---|---|---|
| D-001 | Accepted | Use DevRunbook as a working name. | Communicates reusable operational development procedures; legal, domain and trademark clearance is still required. |
| D-002 | Accepted | Build a modular monolith for the MVP. | Keeps deployment and local development simple while preserving domain boundaries. |
| D-003 | Accepted | Canonical built-in content is Git-versioned YAML/Markdown. | Enables reviewable diffs, forks, reproducible releases and offline authoring. |
| D-004 | Accepted | PostgreSQL stores application state and search projections. | Supports self-hosting, transactions, full-text search and future team functionality without extra search infrastructure. |
| D-005 | Accepted | Direct arbitrary code execution is excluded from the MVP. | Avoids turning a prompt platform into a remote execution platform before isolation and approval controls exist. |
| D-006 | Accepted | First Gitea integration is read-only. | Repository intelligence delivers value without write-side risk. |
| D-007 | Accepted | Generated runs are immutable snapshots. | Historical reproducibility requires frozen playbook, profile, inputs and output. |
| D-008 | Accepted | Repository-derived content is untrusted evidence. | Prevents README, issues or source files from silently changing platform instructions. |
| D-009 | Accepted | Search starts with PostgreSQL FTS and structured filters. | Avoids a premature vector database and remains explainable. |
| D-010 | Accepted | Use Better Auth as the preferred authentication implementation with its Next.js integration and database-backed sessions. | It currently provides self-hosted email/password authentication, session management and reset primitives that fit the required stack. A blocker-level ADR may replace it only if Milestone 0 compatibility or security verification fails. |
| D-011 | Accepted | Deliver 28 P0 packages now and retain 44 P1/P2 concepts as non-executable backlog. | Prevents roadmap entries from being misrepresented as validated runtime content while preserving the broader product direction. |
| D-012 | Accepted | Represent conditional behavior with a closed, declarative AST. | Avoids arbitrary expression evaluation and makes validation, rendering and UI authoring deterministic. |
| D-013 | Accepted | Declare every package file and its role in playbook.yaml. |
Enables exact import boundaries, digesting, export policy and undeclared-file rejection. |
| D-014 | Accepted | Use RFC 8785-style canonical JSON rules and explicit self-digest omission. | Cross-platform integrity requires one byte-level algorithm rather than implementation-specific serialization. |
| D-015 | Accepted | Call composed output a generated task or Run Pack, not an executed run. | The MVP generates instructions and artifacts; it does not execute arbitrary repository commands. |
| D-016 | Accepted | Use local first-run ownership with secure sessions and workspace-scoped authorization. | A self-hosted product still needs a defined takeover boundary, recovery behavior and object-level access control. |
| D-017 | Accepted | Treat api/openapi.yaml and database/reference-schema.sql as implementation contracts that must remain synchronized with code and migrations. |
High-level prose alone is insufficient for autonomous implementation and integration tests. |
| D-018 | Accepted | Maintain an executable offline reference composer and 28 golden prompt fixtures. | Byte-level examples remove ambiguity from deterministic composition and provide cross-language conformance tests. |
| D-019 | Accepted | Use one lead Codex thread with bounded worktrees/subagents under an explicit execution protocol. | Parallelism is valuable only when canonical state, contracts and release evidence have one accountable owner. |
| D-020 | Accepted | Make the monorepo bootstrap structure and root command names normative. | Stable commands and package boundaries reduce autonomous implementation drift and simplify CI, operations and handoff. |
| D-021 | Accepted | Target Node.js 24 LTS with Next.js 16.2.12, React 19.2.8, TypeScript 5.9.3, pnpm 10.33.0, Drizzle ORM 0.45.2 and Better Auth 1.6.25. | These were stable, mutually compatible releases verified at Milestone 0; TypeScript 7 and Node 26 were avoided because the selected LTS and mature compiler line reduce bootstrap risk. |
| D-022 | Accepted | Integrate Better Auth through an application-owned persistence adapter rather than its stock Drizzle schema. | The stock adapter conflicts with mandatory hashed-session, explicit-revocation, dual-expiry and first-run transaction contracts; ADR-006 preserves those security boundaries. |
| D-023 | Accepted | Virtualize Better Auth's credential account over users.password_hash and add only users.email_verified plus nullable users.image to the reference user model. | This satisfies Better Auth 1.6.25's protocol model without duplicating credentials, storing raw session tokens, or introducing stock account/session tables that conflict with the v1.2 relational contract. |
| D-024 | Accepted | Store new local passwords in a versioned DevRunbook scrypt envelope and transparently upgrade Better Auth 1.6's unversioned default hash after a successful sign-in. | Better Auth's default salt:key value omits work factors, so parameter-upgrade detection is impossible without a self-describing envelope; custom hash/verify callbacks preserve Better Auth ownership of the credential protocol while making future rehash decisions deterministic. |
| D-025 | Accepted | Govern RepositoryProfile parsing, semantic validation, canonicalization and export in a framework-independent repository-intel package while retaining the published root JSON Schema. | Repository evidence is an untrusted interchange boundary used by HTTP, persistence and composition; one reusable implementation prevents route/UI drift and preserves exact Python/TypeScript digest parity. |
| D-026 | Accepted | Resolve the current repository profile as the highest immutable revision under a repository-row lock, and suppress a save when the candidate at the current revision has the same digest. | A mutable current-revision pointer is unnecessary, while row locking gives contiguous concurrent revisions and digest-based no-op suppression avoids meaningless history without weakening immutable snapshots. |
| D-027 | Accepted | Keep composeCanonicalPrompt as the byte-frozen reference-v1 formatter and make composePreview the authoritative governed resolver that filters conditions before formatting. | The supplied 28 fixtures define a compatibility byte contract, while runtime conditions still require the three-valued, fail-closed semantics in the v1.2 DSL; separating resolution from formatting satisfies both without silently rewriting golden evidence. |
| D-028 | Accepted | Resolve conditions, compatibility, scope, policies, provenance, lint, prompt bytes and digests exclusively on the server from immutable sources. | Clients and imported repository content are untrusted and cannot be allowed to weaken policy, spoof readiness or substitute historical snapshots. |
| D-029 | Accepted | Persist composer autosave state as workspace-scoped drafts with positive monotonic revisions and strong "draft:<revision>" ETags. | Atomic compare-and-swap updates preserve local conflict recovery and prevent concurrent autosaves from silently overwriting another editor. |
| D-030 | Accepted | Require a non-empty workspace-scoped idempotency key for every generated task and append its creation audit event in the same database transaction. | Immutable generation must be safely replayable, attributable and incapable of producing an unaudited successful record. |
| D-031 | Accepted | Let guided generation identify its persisted draft through a validated X-DevRunbook-Draft-Id header and reload that draft server-side. | The generic run API still supports direct authoritative composition, while the guided UI gains an auditable relational source and cannot substitute client-derived state after autosave. |
| D-032 | Accepted | Generate deterministic Run Packs synchronously from immutable run snapshots and verify historical imports entirely in bounded memory without extraction. | MVP exports are small and user-triggered; fixed ZIP metadata plus a canonical manifest makes bytes reproducible, while in-memory structural validation prevents filesystem traversal and binds re-import to the authorized historical run without adding an execution or extraction surface. |
| D-033 | Accepted | Collect Gitea evidence through a bounded read-only adapter, queue only opaque IDs, create an initial immutable profile once and retain the last complete local snapshot when remote access fails or is deleted. | Repository content and credentials are untrusted; reloading them inside authorized server and worker boundaries prevents secret-bearing jobs, while create-initial-only profile policy prevents a remote refresh from silently overwriting reviewed local knowledge. |
| D-034 | Accepted | Keep private package bytes, server lifecycle, objective evidence and editorial review as separate persisted claims, and permit publication only after an exact-digest transactional recheck. | Imported lifecycle text and reviewer opinion cannot be allowed to masquerade as validated evidence; digest binding makes later edits invalidate stale review and evaluation claims. |
| D-035 | Accepted | Validate and export private playbook archives deterministically in bounded memory without extraction, and clone published versions by rewriting every governed semantic-version reference before revalidation. | Authoring packages are small and untrusted; a no-extraction boundary prevents traversal/execution risk, while coherent manifest/example/evaluation identity preserves reproducibility across immutable versions. |
| D-036 | Accepted | Make password-confirmed personal-data export and anonymizing account deletion local, atomic and audit-recorded. | Self-hosted privacy operations must not depend on external identity providers; anonymization preserves immutable run and governance evidence without retaining the deleted user's direct identifiers. |
| D-037 | Accepted | Enforce artifact retention only through database-referenced storage keys while retaining immutable run snapshots and prompts. | Expired downloads can be removed safely without weakening historical reproducibility or accepting an operator-controlled filesystem path. |
| D-038 | Accepted | Run backup file access with the numeric web-runtime identity and stream archives across the container boundary. | Artifact volumes are intentionally mode 0700; matching the runtime identity preserves least privilege, while streaming avoids granting a helper container write access to the operator backup directory. |
| D-039 | Accepted | Remove package managers from long-running web and worker images after build. | npm, Corepack and Yarn are unnecessary at runtime and materially expand the vulnerability and executable-tool surface. |
| D-040 | Accepted | Provide an all-in-one PostgreSQL, migration, web and worker image for single-container Unraid DockerMan installations while retaining the modular Compose reference. | The operator explicitly prioritizes one manageable DockerMan container; one /config boundary preserves backup and migration behavior, PostgreSQL remains unexposed, and application processes still run as the unprivileged node identity. |
| D-041 | Accepted | Treat the selected-workspace cookie only as a user preference and re-authorize it against active memberships on every server-rendered request. | Multi-workspace navigation must be convenient without turning a client-controlled identifier into an authorization decision; missing, stale or unauthorized selections fall back deterministically to an authorized workspace. |