# Cicadel dev: complete framework documentation Framework philosophy, implementation reports and contributor material. This is separate from the application-development guides. Source: development checkout. --- Source: `PLAN.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/PLAN.md # Cicadel framework plan **Scope update:** [batteries.md](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md) is the authoritative long-term battery inventory and support policy. Checked items below record bounded foundation work, not complete Django-equivalent batteries. Model-generated PostgreSQL migrations now have a verified experimental installable; remaining package-system contracts and public release work remain separate. ## 1. Product direction Build a Go web framework that helps a Django developer become productive without first designing a framework of their own. Preserve familiar project organization, route configuration, settings, and model-centered development while keeping Go code explicit and understandable. The first release should support a conventional server-rendered, database-backed application. JSON responses belong in the core HTTP layer, but a full API toolkit is a later feature. Success means a developer can create a project, add an app, define a model, apply a migration, register a route, and render a page by following one coherent tutorial. Deployment should produce a conventional Go executable with documented configuration and database requirements. The checklist tracks implemented and verified work. Public APIs remain experimental until the external beta and stable-release gates are satisfied. ## 2. Design principles - Put familiar concepts in familiar places: settings, URLs, apps, models, views, templates, and management commands. - Favor explicit registration and dependency injection over runtime discovery, global mutable state, or import side effects. - Build on standard Go HTTP interfaces so existing middleware and tooling can integrate. - Choose one mature ORM for the first release. Expose its capabilities directly, adding thin framework integration only where it improves the application workflow. - Treat schema migrations as versioned, reviewable changes. Do not silently mutate production schemas at startup. - Establish secure defaults and clear errors before adding convenience features. - Build reusable, composable UI components inspired by React and Django Cotton: explicit props, children, named slots and isolated scope. Do not adopt Django’s template language or inheritance system. - Measure performance against representative workloads and preserve time for documentation and maintainability. ## 3. Architecture and ownership | Area | Cicadel owns | Integration boundary | | --- | --- | --- | | Application | Startup, app registration, dependency wiring, shutdown | Explicit composition; no required global application | | Settings | Typed configuration contract, loading, validation | Environment and caller-provided values; secrets excluded from logs | | URLs | App route inclusion, namespacing, names and reversal | Standard HTTP handlers; router choice validated in a prototype | | HTTP | Response helpers, errors, middleware composition | Standard request contexts, cancellation, and HTTP interfaces | | Database | Connection lifecycle, configuration, command integration | Selected ORM owns querying, relationships, and transactions | | Migrations | App discovery through registration, ordering, CLI workflow | Chosen migration engine owns execution history and locking | | Component UI | Component contracts, composition, namespaces, compilation and rendering | React/Cotton-inspired Go server rendering with contextual escaping; existing `html/template` is a temporary prototype | | Static assets | Development serving and production asset lookup | Embedded assets or external serving, with explicit configuration | | CLI | Project/app scaffolding and management commands | Build-time Go code and subprocesses with clear errors | | Security | Sessions, CSRF integration, security defaults | Established cryptographic primitives and reviewed dependencies | | Testing | App construction helpers and request/database fixtures | Standard Go tests and HTTP test utilities | | Operations | Health hooks, logs, graceful shutdown, observability hooks | Standard deployment and telemetry integrations | Framework source organization can differ from generated application organization. The familiar layout is a contract with application developers, not a requirement to force all framework internals into Django-shaped files. ## 4. Implementation checklist ### Validate the foundation Resolve the choices that affect the rest of the framework before committing to public APIs. - [x] Write short architecture decisions for the supported Go version, module layout, HTTP routing, settings, ORM, migration tooling, and initial database support. - [x] Evaluate mature Go ORM candidates using maintenance activity, documentation, releases, licensing, transaction support, relationships, context cancellation, pooling, migration compatibility, testability, and direct access to advanced queries. - [x] Prototype a related-model query, transaction rollback, pagination, a constraint violation, and migration execution against the leading ORM candidate. - [x] Start database validation with PostgreSQL. PostgreSQL is the only supported and planned backend; other databases are excluded. - [x] Define the generated project layout and public/private package boundaries. - [x] Specify benchmark workloads and an initial threat model covering configuration, HTTP input, templates, sessions, and database access. **Done when:** architecture decisions explain the choices and tradeoffs, and a small prototype proves the ORM and migration workflow. Do not build a generic multi-ORM abstraction. ### A complete request-to-database-to-page path Deliver the smallest framework that can run a real example application. - [x] Implement explicit application construction, app registration, startup validation, and graceful shutdown. - [x] Load typed settings with documented precedence: defaults, project configuration, then explicit environment overrides. - [x] Support root and app `urls.go` files, HTTP method routing, path parameters, route names, and duplicate-route diagnostics. - [x] Provide HTML, JSON, redirect, and error response helpers, with request contexts passed through database operations. - [x] Integrate ORM connection setup, cleanup, transactions, and explicit migration commands. - [x] Implement namespaced template lookup and project overrides using `html/template`. - [x] Build an articles example with list and detail pages backed by related database records. - [x] Add tests for request routing, configuration failures, database integration, template escaping, and shutdown behavior. **Done when:** the example starts from an empty database using documented commands, applies migrations, serves database-backed HTML and JSON, and builds into a Go executable. This is an internal milestone, not yet a production-ready release. ### The Django-familiar development workflow Make starting and growing an application consistent. - [x] Add a `cicadel` CLI for `startproject` and `startapp`. - [x] Define the generated `manage.go` entry point and commands for development serving, configuration checks, and migrations. - [x] Keep production builds on standard Go commands; define a development reload approach separately. - [x] Add named URL reversal with namespaces and explicit errors for missing or invalid parameters. - [x] Define middleware order and app initialization order, with diagnostics for dependency cycles. - [x] Add development static-file serving, embedded-template support, and a documented production asset strategy. - [x] Make development errors useful while ensuring production responses do not expose stack traces or secrets. - [x] Write the first complete tutorial and a Django-to-Cicadel concept guide. **Done when:** a new developer can scaffold an app and complete the tutorial without modifying framework internals. CI builds and runs the generated project to catch scaffold drift. ### Safe interactive applications Support browser forms and authenticated workflows before claiming production readiness. - [x] Establish request size limits, parsing rules, validation errors, and reusable form handling without assuming a Django-style metaclass system. - [x] Define sessions, secure cookie defaults, rotation, expiry, logout invalidation, and storage boundaries. - [x] Implement CSRF protection for cookie-authenticated state changes and document its middleware requirements. - [x] Add authentication and authorization primitives using established password hashing and explicit permission checks. - [x] Define redirect validation, proxy trust, host validation, and deployment-dependent security settings. - [x] Document ORM parameterization and unsafe raw-query boundaries, template trusted-content escape hatches, and file-upload limits. - [x] Extend the example with sign-in and authorized create/edit actions, including validation errors. - [x] Test unauthorized access, CSRF rejection, session rotation, escaping, and rollback on failed writes. **Done when:** the example supports authenticated edits, security behavior is documented and tested, and a focused security review has resolved release-blocking issues. ### Implement composable component UI The earlier template-definition prototype does not complete the intended engine. [The component UI design](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md) supersedes the earlier decision to retain Go template syntax as the public UI model. - [x] Record React/Django Cotton component composition as the UI direction, independently of Django backend conventions. - [x] Specify and implement component authoring/compiler contracts: explicit typed props, children, named slots, isolated scope, nesting and reusable layouts. - [x] Implement safe attribute merging, contextual escaping and explicit trusted-content boundaries across components and slots. - [x] Integrate package namespaces, overrides, component libraries, embedded assets, source diagnostics and a development regenerate/restart workflow. - [x] Define concurrent rendering, cancellation, cache isolation and production compilation/validation behavior. - [x] Convert scaffolding, articles, forms and catalog/admin to the component engine and publish a prototype migration guide. - [x] Complete the detailed acceptance checklist in docs/component-ui.md with functional, security and integration tests. - [x] Keep accessible form labels/errors in the existing examples and exclude native i18n/l10n; carry those requirements into the component system. **Done when:** a newly generated app composes reusable components and an external component library with typed props, children and named slots; escaping, isolation, diagnostics and production rendering are verified. The generated-consumer test and component verification record provide completion evidence; legacy template tests remain compatibility coverage. ### Production reliability and performance Make operational behavior predictable and measure the original performance motivation. - [x] Add structured logging hooks, request IDs, health/readiness hooks, and optional tracing/metrics integration. - [x] Document HTTP timeouts, database pool limits, cancellation, shutdown deadlines, and reverse-proxy configuration. - [x] Verify migration locking, partial-failure behavior, and coordination across multiple application instances. Document database backup and forward-repair procedures. - [x] Run unit and integration suites, race checks, dependency vulnerability checks, and targeted fuzzing of request/configuration boundaries in CI. - [x] Benchmark routing, middleware, ORM reads/writes, and rendered responses; report latency distributions, throughput, allocations, and error rates under load. - [x] Compare a minimal Go HTTP baseline and, where useful, an equivalent Django application with matched database, queries, hardware, workload, and deployment conditions. Publish versions and methodology alongside results. - [x] Exercise deployment from a clean build, including assets, migrations, configuration, and graceful termination. **Done when:** deployment is reproducible, operational limits are documented, and measured results identify acceptable overhead and remaining bottlenecks. Performance targets should be set from the baseline, not invented in advance. ### Public beta and stable release Validate the framework through more than its own demonstration app. - [x] Build a second application with different relationships and permissions to uncover assumptions in the first example. - [x] Publish current API documentation, tutorials, a changelog, and development policy. - [x] Establish semantic versioning, deprecation policy, release automation, and a private security-reporting process. - [ ] Obtain an independent security review of the framework and resolve release-blocking findings. - [ ] Run a beta period, prioritize failures in real workflows, and settle public API naming and package boundaries. - [ ] Freeze the initial stable scope and document unsupported features and database limitations. **Done when:** independent projects can follow the documented workflow, critical issues are resolved, and public contracts have enough evidence to support a stable release. ## Installable applications: current first priority New batteries should start as installable apps using the same public contracts as third-party authors. Promotion to first-party/contrib maintenance must preserve identity, migration history and user configuration; first-party capabilities become core defaults, with one canonical implementation and workflow. - [x] Implement manifests, app API compatibility, dependency version bounds, ordering and collision checks. - [x] Integrate namespaced commands, typed configuration checks, route-scoped middleware and app-owned resources. - [x] Implement dependency-ordered startup and reverse cleanup, including partial failure and graceful HTTP shutdown. - [x] Integrate package-owned PostgreSQL SQL migrations with provider checks and no automatic data deletion on removal. - [x] Generate `project/apps.go` and independently distributable modules with `startpackage` and a lifecycle test helper. - [x] Test actual Go-module installation, upgrade and removal in an independently generated host, including PostgreSQL data retention. - [ ] Complete remaining DEV-04 contracts and module extraction before calling the full package battery complete. See [the installable-app guide](https://cicadel.fauzaanu.com/en/dev/topics/installable-apps/index.md) and the detailed [package checklist](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md#package-system-acceptance-checklist). ## 5. Complete battery roadmap **PostgreSQL only:** do not add other database backends or provider-parity work. See [AGENTS.md](https://github.com/fauzaanu/cicadel/blob/main/AGENTS.md). The earlier foundation established prototypes and integration seams. It did not complete these broader batteries. Track their full support boundaries, relative difficulty, exclusions and acceptance evidence in [batteries.md](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md). - [ ] Finish the complete reusable package system (DEV-04 and the PKG acceptance checklist), extending the now-implemented installable-app foundation. - [x] Generate migrations from changes to `models.go`, multiple model files or a `models/` package (MIG-01–06), with historical model state and reviewable artifacts. - [x] Verify PostgreSQL migration/type/constraint conformance for the documented installable subset (DB-05 remains broader). SQLite, MySQL and MariaDB are excluded, not pending work. - [x] Complete typed forms and model-derived forms (FORM-01–03); see [completed forms contract](https://cicadel.fauzaanu.com/en/dev/topics/forms-completion/index.md). - [x] Implement and verify the FORM-02 model-form contract: typed allowlists, authorized atomic saves, relationships, uniqueness and hooks. See [model forms](https://cicadel.fauzaanu.com/en/dev/topics/model-forms/index.md). - [x] Implement FORM-03 bounded formsets and inline related-object editing as an installable core module; verify atomic saves and concurrent collection limits in a generated consumer. - [x] Finish standalone typed binding, validators, widgets and accessible errors (FORM-01). - [x] Add revision-based stale-edit protection, bounded file-upload lifecycle (FILE-01), and shared model-form/inline admin integration. - [x] Deliver reusable browser accounts, password recovery and session-revocation workflows with the accounts starter; broader identity/admin work remains tracked under AUTH-01–05. - [x] Deliver configurable logging and SMTP/MIME email to the scopes in [logging](https://cicadel.fauzaanu.com/en/dev/topics/logging/index.md) and [email](https://cicadel.fauzaanu.com/en/dev/topics/email/index.md). - [ ] Complete optional administration beyond the existing limited CRUD prototype (ADMIN-01–04). - [ ] Complete selected HTTP/template/static-assets and developer-tool batteries to the scopes in the inventory. - [ ] Complete optional email delivery, file/storage, caching and background-task batteries beyond existing integrations (SVC/FILE rows). - [ ] Deliver comparatively small pagination, flash-message, sitemap and managed-redirect batteries one at a time. - [ ] Extract first-party modules and prove external packages can integrate without modifying core. Native i18n/l10n, humanization and GIS/GeoJSON tooling are third-party-only. Correct Unicode handling, accessibility and time-zone-safe timestamps remain core responsibilities. No Django package compatibility, automatic project conversion, in-house ORM or queue broker is promised. ## 6. Decision ownership and execution Implementation decisions are delegated to the implementing agent. Research, choose, document the rationale, and proceed without asking the project owner questions. Keep the Django-familiar conventions and Go-native implementation principles above. - [x] Record the ORM and migration-tool selection. - [x] Record routing, URL reversal, and middleware contracts. - [x] Record supported Go and database versions and CI coverage. - [x] Record public import paths and package boundaries. - [x] Record the development reload and asset packaging approach. - [x] Record the session/authentication design and extension points. - [x] Record the component-first UI direction and prototype transition policy. - [x] Finalize and verify `.templ` authoring, typed props/slots, versioned exports and exact compatible project overrides. Work through this checklist in dependency order. Check an item only after its implementation and relevant verification are complete, with evidence in the repository. External beta adoption and independent security review must remain unchecked until they actually happen. No calendar estimates or phase durations are assigned. ## 7. First implementation target **settings → registered app → `urls.go` → view → ORM query → template → response** Use an articles application to validate framework boundaries, then continue through the remaining checklist. Commit and push this checklist before implementation begins, and keep subsequent progress visible in commits and this document. ## Verification evidence - Architecture and dependency choices: [architecture decisions](https://cicadel.fauzaanu.com/en/dev/internals/architecture/index.md). - Application workflow and scaffold: [tutorial](https://cicadel.fauzaanu.com/en/dev/intro/tutorial/index.md), generated-project tests, articles and catalog HTTP integration tests. - PostgreSQL: real migration, lock contention, constraints, relations, rollback and context-cancellation tests. - Security: session rotation/invalidation, CSRF rejection, role/ownership authorization and escaping tests. - Jobs: River migration, transactional enqueue rollback, committed job execution. - Full local race suite passes on Go 1.26.10 and PostgreSQL 18.4. [GitHub CI run 40868174638](https://github.com/fauzaanu/Cicadel/actions/runs/40868174638) passed race/integration tests, vet, routing fuzzing, vulnerability checking, and builds. - Performance evidence: [methodology](https://cicadel.fauzaanu.com/en/dev/howto/performance/index.md), HTTP latency/throughput/error results, routing/template allocations, and ORM allocations. - Deployment smoke test: compiled executable run outside the source tree against a fresh database; migrations, checks, embedded HTML, JSON, readiness, and SIGTERM shutdown passed. - [Release policy](https://cicadel.fauzaanu.com/en/dev/releases/releases/index.md), draft-release workflow, [security-reporting process](https://cicadel.fauzaanu.com/en/dev/sources/SECURITY.md), [API index](https://cicadel.fauzaanu.com/en/dev/ref/api/index.md), and [self-review](https://cicadel.fauzaanu.com/en/dev/internals/security-review/index.md) are implemented. The prerelease workflow is configured but has not published a release. - No independent beta adoption or external security review is claimed. ## Remaining work and release gates The bounded foundation work above has repository evidence. Substantial battery implementation remains in section 5 and [batteries.md](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md); the project is not complete merely because its original prototype checklist was checked off. Independent security review, real-user beta feedback and the resulting stable-scope freeze also remain open. Implementation choices continue to be delegated to the implementing agent, within the recorded support policy. ### Installable development and model migrations - [x] Create and validate the `cicadel-installables` skill with detailed package-development references. - [x] Add offline build-command registration without runtime hooks or database requirements. - [x] Implement a separate model-migration installable with recorded snapshots and PostgreSQL SQL generation for documented PostgreSQL additions and explicit alterations. - [x] Demonstrate models split across files, preview/check generation and explicit application through Goose. - [x] Test PostgreSQL creation, upgrades preserving data, constraints and reverse/reapply behavior; include nested module in CI. - [x] Complete the bounded migration acceptance checklist in `batteries.md`; see `docs/automated-migrations-progress.md` for evidence and explicit unsupported features. Public versioned distribution remains unverified. - [x] Evaluate first-party GORM GEN query generation from the same authored model registry; `contrib/querygen` verifies reproducible output and PostgreSQL query execution with GORM v1.31.2. ### Component implementation evidence - [x] Compile `.templ` through a pinned parser/IR and Go generator with Cicadel source frames, deterministic hashes, policy diagnostics and read-only stale/type checks. - [x] Register typed library exports and project overrides; validate required assets before runtime startup. Use request-owned buffers with bounded atomic responses. - [x] Convert starter, articles and catalog/admin; preserve permission and CSRF tests. - [x] Install an external library in a generated host through a local Go proxy and verify slots, overrides, security/isolation, and compiled execution outside source. - [x] Record unit/integration/race/fuzz/vet and benchmark evidence in [component verification](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md). - Remaining scope: broader FORM/ADMIN/package batteries, streaming/client runtime/active-content adapters, independent security review and stable API adoption. These are not claimed by the initial server component battery. ### Component authoring and first-party Tailwind - [x] Add a dedicated portable `cicadel-components` skill with composition, forms, defaults, overrides, Tailwind and diagnostic repair patterns. - [x] Publish a React-to-Cicadel guide whose complete source snippets are compiled and tested in a generated project, including HTTP escaping and required slots. - [x] Make Tailwind v4 the default starter CSS pipeline, with explicit pinned standalone-tool installation and checksum verification on every build/check. - [x] Build and check CSS atomically, resolve explicitly listed Go package class sources, serve embedded output and retain an opt-out for alternative CSS systems. - [x] Verify actual compiler output, stale/error paths, installed-library CSS and outside-source-tree production HTTP behavior; record commands and evidence in [authoring verification](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-authoring-verification.md). - Automatic HMR, asset hashing/collection, arbitrary npm plugin compatibility and untested standalone platforms remain outside this implementation. ### Application foundation completion - [x] Cover all operational settings with explicit environment overrides, safe diagnostics and isolated test configuration. - [x] Complete command discovery/help, namespaced metadata, usage statuses and generated-executable invocation tests. - [x] Add structured severity-based checks, deployment-only hooks, JSON output and failure thresholds while preserving legacy error identity. - [x] Implement content-hash development watching, component/CSS regeneration, successful-build-before-stop replacement and bounded child shutdown. - [x] Verify generated component reload, failed-build recovery, port conflicts, subprocess reaping and scaffold validation; document upgrades and model layouts. See [foundation contracts and acceptance evidence](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md). The separate DEV-04 reusable-package checklist and optional DEV-08 database tooling remain tracked in the inventory; external release gates remain open. ### Installable runtime model contributions - [x] Add typed, app-owned runtime model declarations and offline discovery, enforcing unique PostgreSQL table and Go-type ownership across packages. - [x] Preserve dependency ordering and descriptor isolation for catalog consumers. - [ ] Connect optional tooling to the catalog where appropriate; historical migration snapshots remain separately recorded and authoritative. ### Runtime catalog query integration - The core `contrib/querygen` module now accepts app-owned model declarations, validates ownership and GORM table agreement before generation, and snapshots factory configuration. Explicit model lists remain supported. Regression coverage includes deterministic generated output and invocation from a separate Go-module host. - This advances the remaining catalog/tooling contract; it does not complete module extraction or the broader DEV-04 battery. ### Cache backend integration progress - Added context-aware cache backends with explicit miss/error semantics, an adapter preserving the existing local API, immutable alias registries and versioned namespace isolation. Race-tested cancellation, expiry, ownership, failure propagation and concurrent use; see [cache contract](https://cicadel.fauzaanu.com/en/dev/topics/cache/index.md). - Shared providers and provider conformance remain open under SVC-01. ### Concurrent cache loading - Added a reusable per-client loader that coalesces concurrent misses, rechecks cache state before loading, isolates returned bytes, propagates failures for retry, and cancels abandoned work without canceling remaining waiters. - Shared/distributed providers and HTTP caching remain separate unfinished work. ### Bounded cache loading - Added opt-in bounded loader construction with concurrent-execution admission, operation deadlines, explicit overload errors and retained slots for abandoned callbacks until they return. Existing loader construction remains compatible. - Continued the recent cache reliability work as a bounded completion; this does not complete SVC-01 or supersede DEV-04's higher-level delivery priority. - Shared providers, provider conformance and module extraction remain unchecked; see `docs/cache.md` for the public contract and regression evidence. --- Source: `README.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/README.md # Cicadel Cicadel brings Django’s structure and development speed to Go, with an AI-first philosophy, modern design and Go’s fast runtime. ## Philosophy Building a complete web application should feel coherent and move quickly. Cicadel combines Django-familiar projects, apps, settings and routes with Go’s type safety, compiled performance and straightforward deployment. AI-first means designing for developers and their AI tools: predictable conventions, explicit contracts, typed components and clear documentation make applications easier to understand, generate and maintain. Modern design starts with composable `.templ` components, typed props and slots, and a first-party Tailwind CSS workflow. GORM and PostgreSQL provide the data foundation, while core batteries are composed through installable Go modules. The goal is Django-like productivity with the performance and simplicity of Go. [Documentation](https://cicadel.fauzaanu.com/en/dev/) · [Get started](https://cicadel.fauzaanu.com/en/dev/intro/tutorial/index.md) · [API reference](https://cicadel.fauzaanu.com/en/dev/ref/api/index.md) · [Architecture](https://cicadel.fauzaanu.com/en/dev/internals/architecture/index.md) · [MIT license](https://github.com/fauzaanu/cicadel/blob/main/LICENSE) > [!IMPORTANT] > **Status: experimental.** Working foundations and verified feature subsets are implemented. Independent security review, external beta adoption and stable scope approval remain open. ## Progress overview **Implemented** = the linked scope has recorded implementation evidence. **Partial** = working foundations with broader contracts still open. Neither means stable or production-ready. | Workstream | Status | Delivered scope | Evidence / remaining work | | :--- | :---: | :--- | :--- | | Application foundation | 🟢 Implemented | Registration, settings, routing, lifecycle, scaffolding, command help, deployment checks and development reload | [Foundation contracts and evidence](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md) | | Component UI | 🟢 Implemented | Typed props, children, named slots, escaping, library exports and overrides | [Verification](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md) · [Authoring](https://cicadel.fauzaanu.com/en/dev/howto/component-authoring/index.md) | | Tailwind workflow | 🟢 Implemented | Pinned standalone tool, CSS generation and offline UI checks | [Build workflow](https://cicadel.fauzaanu.com/en/dev/howto/tailwind/index.md) | | Typed forms and model forms | 🟢 Implemented | Binding, validation, widgets, authorized saves, stale-edit checks and bounded uploads | [Forms contract](https://cicadel.fauzaanu.com/en/dev/topics/forms-completion/index.md) · [Model forms](https://cicadel.fauzaanu.com/en/dev/topics/model-forms/index.md) | | Formsets | 🟢 Implemented | Atomic add/edit/delete collections and authorized inline editing | [Core installable module](https://cicadel.fauzaanu.com/en/dev/ref/formsets/index.md) | | Browser accounts | 🟡 Partial | Sign-in, recovery, password changes, logout and session revocation | [Starter and boundaries](https://cicadel.fauzaanu.com/en/dev/topics/authentication/index.md); broader identity/admin work remains | | Model-driven migrations | 🟡 Partial | Recorded model history, reviewable SQL, dependency graphs and supported recovery | [Acceptance evidence](https://cicadel.fauzaanu.com/en/dev/sources/contrib/migrations/ACCEPTANCE.md); documented PostgreSQL subset | | Installable apps | 🟡 Partial | Manifests, dependency checks, commands, resources, migrations and lifecycle | [Package checklist](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md#package-system-acceptance-checklist); contracts and extraction remain | | Email | 🟢 Implemented | Verified-TLS SMTP, MIME, attachments, reusable batches and development backends | [Supported contract](https://cicadel.fauzaanu.com/en/dev/topics/email/index.md) | | Logging | 🟢 Implemented | Named routing, levels, handlers, rotation, redaction and correlated errors | [Supported contract](https://cicadel.fauzaanu.com/en/dev/topics/logging/index.md) | | Administration | 🟡 Partial | Model CRUD, forms and inline integration | [Battery inventory](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md); complete ADMIN-01–04 scope remains | | Cache, storage and jobs | 🟡 Partial | Storage interfaces, process-local caching and River integration | [Integrations](https://cicadel.fauzaanu.com/en/dev/topics/extensions/index.md); complete backend and lifecycle contracts remain | | Application testing | 🟡 Partial | Lifecycle fixtures, cookie-aware clients, disposable PostgreSQL databases and query budgets | [Testing guide](https://cicadel.fauzaanu.com/en/dev/topics/testing/index.md); broader test-backend contracts remain | | Operations and performance | 🟡 Partial | Operational guidance, benchmark evidence and CI checks | [Operations](https://cicadel.fauzaanu.com/en/dev/howto/operations/index.md) · [Measurements](https://cicadel.fauzaanu.com/en/dev/howto/performance/index.md); external validation remains | ## Completed implementation milestones Checked items describe bounded work recorded in [PLAN.md](https://cicadel.fauzaanu.com/en/dev/sources/PLAN.md), not completion of every related battery. - [x] Establish architecture decisions and PostgreSQL-backed ORM/migration prototypes. - [x] Deliver the request → route → database → rendered-page workflow. - [x] Scaffold projects and apps with management commands and a complete tutorial. - [x] Add sessions, CSRF protection and authorized editing to the example application. - [x] Replace the prototype UI authoring model with compiled components. - [x] Verify component composition in a generated host using an external library. - [x] Deliver typed forms, model forms, formsets and admin inline integration. - [x] Generate reviewable migrations from explicitly registered model declarations. - [x] Verify the documented PostgreSQL migration subset and upgrade/recovery paths. - [x] Deliver the browser accounts starter, email and configurable logging. - [x] Build a second example application with different relationships and permissions. - [x] Record operational guidance, performance methodology and release policy. ## Active priority · installable applications The package foundation is working. The full reusable-app battery remains open. - [x] Define manifests, API compatibility, dependency bounds and collision checks. - [x] Integrate namespaced commands, configuration checks and owned resources. - [x] Run startup and cleanup in dependency order, including failed initialization. - [x] Integrate package migrations without deleting data on package removal. - [x] Generate independent modules with `startpackage`. - [x] Verify installation, upgrades and removal in a generated host. - [ ] Finish typed contribution contracts across the full package surface. - [ ] Extract remaining first-party batteries into independent modules. - [ ] Verify an external translation extension through public hooks. - [ ] Verify a second external package combining components/assets, commands and migration upgrade/removal behavior. [Detailed acceptance checklist →](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md#package-system-acceptance-checklist) ## Remaining delivery queue Order follows the [battery roadmap](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md#delivery-order-and-comparatively-small-batteries). These are scope checkpoints, not delivery dates. | Priority | Work to finish | Completion boundary | | :---: | :--- | :--- | | 1 | Reusable package system | Close remaining DEV-04 contracts and prove external integration | | 2 | Migration scope | Extend and verify the documented PostgreSQL operation subset | | 3 | Contained utility batteries | Complete pagination, flash messages, sitemaps and managed redirects individually | | 4 | Application workflows | Close remaining account/admin, static-asset and developer-tool contracts | | 5 | Optional services | Complete selected cache, task, storage and test-backend contracts with generated-consumer evidence | | 6 | External validation | Resolve independent review and beta findings before freezing stable scope |
Migration progress and boundaries - [x] Separate migration generation from execution; no startup `AutoMigrate`. - [x] Discover explicitly registered models across files and packages. - [x] Record deterministic historical state and generate reviewable SQL. - [x] Support declared schema alterations, data operations and dependency graphs. - [x] Check history integrity and support documented concurrent-index recovery. - [x] Verify clean installs, upgrades and data preservation on PostgreSQL. - [ ] Publish a versioned release and durable compatibility guarantees. Advanced indexes, native enum/domain lifecycle and implicit join generation are outside inferred operations. Other database backends are excluded, not pending. [Supported operations](https://cicadel.fauzaanu.com/en/dev/ref/migrations/index.md) · [Verification record](https://cicadel.fauzaanu.com/en/dev/sources/docs/automated-migrations-progress.md) · [Typed query generation](https://cicadel.fauzaanu.com/en/dev/ref/querygen/index.md)
## Release gates - [x] Document current APIs, tutorials and development policy. - [x] Establish release automation and private security reporting. - [ ] Obtain an independent security review and resolve blocking findings. - [ ] Validate independent beta applications and resolve real workflow failures. - [ ] Settle public API naming and package boundaries. - [ ] Freeze the initial stable scope and document remaining limitations. [Release policy](https://cicadel.fauzaanu.com/en/dev/releases/releases/index.md) · [Security review record](https://cicadel.fauzaanu.com/en/dev/internals/security-review/index.md) ## Tracking rules and scope - [batteries.md](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md) owns full capability status and support decisions; [PLAN.md](https://cicadel.fauzaanu.com/en/dev/sources/PLAN.md) records implementation milestones. - Mark work complete only with documented boundaries and linked verification evidence. A dependency or example alone does not complete a battery. - Keep this summary aligned with those trackers when a feature changes. No overall completion percentage is claimed: the workstreams differ in size and scope. - PostgreSQL is the only supported database. Native i18n/l10n, GIS and other explicitly excluded ecosystem features remain third-party concerns. - Public APIs remain experimental until the release gates above are closed. --- Source: `batteries.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/batteries.md # Cicadel batteries This is the long-term capability inventory and support policy. It records the bigger picture before implementation, including features we deliberately will not build. It takes precedence over broad completion claims in the original [implementation plan](https://cicadel.fauzaanu.com/en/dev/sources/PLAN.md). A working helper, dependency wrapper, or example is a foundation—not a complete battery. Baseline: Django **6.1** documentation, reviewed **2026-10-29**. The official stable documentation resolved to this version during review. This inventory groups public capabilities into maintainable units rather than listing every API symbol. Review it against Django's [contents](https://docs.djangoproject.com/en/6.1/contents/), [topic index](https://docs.djangoproject.com/en/6.1/topics/), [reference](https://docs.djangoproject.com/en/6.1/ref/), and [contrib inventory](https://docs.djangoproject.com/en/6.1/ref/contrib/) when updating the baseline. Django ecosystem packages are distinguished from Django itself below. ## Product boundaries - Keep the core small and familiar: project/app conventions, settings, URLs, model-centered data access, complete migration workflows, forms, templates, security, and development tools. - **Default styling:** Tailwind CSS has first-party support through the component build/check workflow. Generated apps use it by default; alternative CSS libraries remain supported. See [Tailwind](https://cicadel.fauzaanu.com/en/dev/howto/tailwind/index.md). - **Component-first UI:** adopt React-style composition and Django Cotton-inspired reusable components with props, children and named slots. Django’s template language/inheritance model is not the UI foundation. See [the component engine design](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md). - Use mature Go libraries where appropriate. Cicadel still owns the consistency, documentation, failure behavior, and tests of every battery it promises. - **No native internationalization or localization.** Translation catalogs, language negotiation, localized URLs, locale-specific formatting, and humanization belong to third-party packages. The earlier experimental `locale` package has been removed. Unicode text, accessible HTML, correct timestamps, and time-zone-safe storage remain requirements. - **No first-party GeoDjango equivalent.** Spatial models, GIS database adapters, geometry operations, map widgets, GIS serializers/GeoJSON tooling, and geographic data import/export belong outside the supported core. Ordinary JSON may contain geographic data; that does not create a GIS support commitment. - **First implementation priority: installable applications.** Develop new batteries as independently installable apps through the public contract, then consider first-party/contrib maintenance once they mature. First-party capabilities become core defaults through these installable contracts. Build the package integration system so excluded capabilities can be supplied externally. Use Go modules for distribution; do not build a new dependency resolver or require runtime-loaded binaries. - Feature selection is a product decision, not a claim that we have measured what most Django users use. Browser/AI translation may help some applications, but it does not replace every server-side localization requirement; those requirements remain addressable through packages. - This is a long-term backlog with dependency order and complexity estimates, not calendar durations or a promise to reproduce all of Django. ## How to read and update this tracker **Target:** `Core` = first-party supported foundation; `Package` = first-party supported, core battery packaged as an installable module; `Third-party` = extension route only, no first-party implementation commitment; `No port` = Django-specific mechanism we intentionally replace with Go conventions. Core/Package means a decision to fully support the stated Cicadel scope eventually, not current readiness or Django API compatibility. **Current:** `Partial` = repository code covers part of the battery; `Absent` = not implemented; `Dependency` = available directly through Go or an upstream library, not a verified Cicadel battery; `Excluded` = intentionally outside first-party scope. No row is marked complete merely because its underlying library has that feature. Accounts, formsets, migrations and query generation have independent modules; further package extraction and published release compatibility remain work. **Effort:** `S` = comparatively small and contained; `M` = several contracts/integrations; `L` = substantial cross-cutting work; `XL` = major subsystem with long-term compatibility obligations. These are engineering judgments, not time estimates. Security-sensitive work still needs careful testing even if labeled S. A selected battery becomes **Complete** only when its documented scope works end to end in a newly generated application, default configuration is usable, errors and recovery are defined, public APIs and upgrades are documented, and conformance tests pass for every claimed provider/version. Record the evidence and remaining limitations alongside the row. Implementation tasks can be checked off without declaring the parent battery complete. ## Project conventions, packages, and developer tools Django references: [applications](https://docs.djangoproject.com/en/6.1/ref/applications/), [management commands](https://docs.djangoproject.com/en/6.1/ref/django-admin/), [system checks](https://docs.djangoproject.com/en/6.1/topics/checks/), and [reusable apps](https://docs.djangoproject.com/en/6.1/intro/reusable-apps/). | ID | Battery | Target | Current | Effort | Completion gap / intended scope | | --- | --- | --- | --- | --- | --- | | DEV-01 | Project and app scaffolding | Core | Complete | M | Validated project/app scaffolds, generated executable invocation, documented model layouts and non-overwriting upgrade workflow; [foundation evidence](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md). | | DEV-02 | Settings and environment configuration | Core | Complete | M | Typed constructor options, every operational environment override, isolated lookups, copied hosts and redacted diagnostics; [settings contract](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md#configuration-and-registration). | | DEV-03 | App registry, dependencies and lifecycle | Core | Complete | L | Explicit dependency-ordered startup, reverse/partial-failure cleanup, immutable descriptors, resource ownership and readiness; [foundation contract](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md#configuration-and-registration). | | DEV-04 | Reusable app/package installation | Core | Partial | XL | First working contract ships: Go-module install, manifests, compatibility checks, commands/resources/migrations and lifecycle. Typed component contracts are now verified; model contracts and module extraction remain. See PKG checklist and installable-app guide. | | DEV-05 | Built-in and custom management commands | Core | Complete | M | Unified discovery, per-command help, custom flags, namespaced commands and process exit statuses tested in generated executables; [command contract](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md#management-commands). | | DEV-06 | Extensible system/deployment checks | Core | Complete | M | Namespaced severity diagnostics, deployment-only checks, JSON output and failure thresholds; [check contract](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md#structured-system-and-deployment-checks). | | DEV-07 | Development server, reload and diagnostics | Core | Complete | M | Content-hash watching, component/CSS builds, failed-build recovery, bounded shutdown, port-conflict diagnostics and generated component reload; [development contract](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md#development-rebuild-and-restart). | | DEV-08 | Database shell and model/schema inspection commands | Package | Absent | M | Explicit provider-aware diagnostics and command availability; no secret leakage. | | DEV-09 | Interactive Python model shell | No port | Excluded | — | Use Go programs, tests and supported inspection commands; no embedded Python/Go interpreter commitment. | | DEV-10 | Django class inheritance/decorators/import magic | No port | Excluded | — | Deliver equivalent workflows through functions, interfaces and explicit composition. | Evidence: [foundation completion](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md), [application.go](https://github.com/fauzaanu/cicadel/blob/main/application.go), [settings](https://github.com/fauzaanu/cicadel/blob/main/settings/settings.go), [management](https://github.com/fauzaanu/cicadel/blob/main/management/management.go), [scaffold](https://github.com/fauzaanu/cicadel/blob/main/internal/scaffold/scaffold.go). The [installable-app foundation](https://cicadel.fauzaanu.com/en/dev/topics/installable-apps/index.md) implements dependency-ordered startup/cleanup; the full package battery remains partial. ## Models, queries, databases, and migrations **Database scope: PostgreSQL only.** SQLite, MySQL, MariaDB and other backends are excluded from the framework and this roadmap. Do not implement or test provider parity. This supersedes earlier multi-provider plans; see [AGENTS.md](https://github.com/fauzaanu/cicadel/blob/main/AGENTS.md). Django references: [models/databases](https://docs.djangoproject.com/en/6.1/topics/db/), [database backends](https://docs.djangoproject.com/en/6.1/ref/databases/), [migrations](https://docs.djangoproject.com/en/6.1/topics/migrations/), [multiple databases](https://docs.djangoproject.com/en/6.1/topics/db/multi-db/), [fixtures](https://docs.djangoproject.com/en/6.1/topics/db/fixtures/), and [serialization](https://docs.djangoproject.com/en/6.1/topics/serialization/). | ID | Battery | Target | Current | Effort | Completion gap / intended scope | | --- | --- | --- | --- | --- | --- | | DB-01 | Model fields, relations, constraints, indexes | Core | Partial | L | Supported GORM mapping contract, validation, relationships/deletion behavior, model metadata and provider tests. | | DB-02 | Query API, eager loading, aggregation, expressions, bulk operations | Core | Partial | L | Keep native GORM access; document/test supported query behavior, cancellation, errors and common performance pitfalls. | | DB-03 | Transactions, savepoints and post-commit hooks | Core | Partial | L | PostgreSQL semantics, nested behavior, rollback and commit callbacks; current transaction use is insufficient alone. | | DB-04 | Connection lifecycle, pools and database errors | Core | Partial | M | Consistent provider setup, bounded failures, health, cleanup and error mapping. | | DB-05 | PostgreSQL provider | Core | Partial | L | Current sole integrated provider; complete migration/type/constraint conformance before a full-support claim. | | DB-06 | SQLite provider | Excluded | Excluded | — | PostgreSQL-only framework; not an implementation target. | | DB-07 | MySQL provider | Excluded | Excluded | — | PostgreSQL-only framework; not an implementation target. | | DB-08 | MariaDB compatibility | Excluded | Excluded | — | PostgreSQL-only framework; not an implementation target. | | DB-09 | Oracle and additional backends | Third-party | Excluded | — | Provider extension contract; no first-party Oracle promise. | | DB-10 | Multiple database aliases and query/migration routing | Package | Absent | L | Explicit selection, checks and migration placement; no distributed transactions or cross-database foreign-key promise. | | DB-11 | Custom fields, managers/query helpers, raw SQL escape hatches | Core | Dependency | L | Document extension metadata, serialization, parameterization and migration participation. | | DB-12 | Composite keys, inheritance/proxy-style model patterns | Package | Dependency | L | Test deliberate Go equivalents and their admin/forms/migration limits; no Python inheritance emulation. | | DB-13 | Legacy database introspection (`inspectdb` workflow) | Package | Absent | L | Generate reviewable model declarations, preserve unmapped features and report ambiguities. | | DB-14 | Fixtures, load/dump, natural identifiers and initial data | Package | Absent | L | Dependency ordering, stable references, transactions, validation and excluded secrets. | | DB-15 | Backend-specific fields, indexes and search | Package | Dependency | L | PostgreSQL-specific features need explicit migration semantics and verified support. | | DB-16 | Query instrumentation and optimization diagnostics | Core | Partial | M | Query counts/timing and safe diagnostics; general HTTP logging is not database instrumentation. | | DB-17 | Tablespace placement | Third-party | Excluded | — | Provider/operations extension, not core configuration. | | MIG-01 | Model changes → generated migrations (`makemigrations`) | Core | Partial | XL | The core `contrib/migrations` module reads registered GORM models and generates immutable PostgreSQL history, with explicit rename/removal/conversion declarations. See its supported operation matrix. | | MIG-02 | Apply, inspect, plan and reverse migrations | Core | Partial | XL | Checksum-aware runner supplies execution, status, dependency plans, SQL preview, target rollback and schema verification. | | MIG-03 | Cross-app migration dependencies and branch merging | Core | Partial | XL | Implemented version-level graph, pinned cross-app references, conflict diagnosis and explicit compatible merges. | | MIG-04 | Historical model state and data migrations | Core | Partial | XL | Immutable historical snapshots and recorded schema/data SQL replay independently of current models. | | MIG-05 | Migration squashing, replacement and upgrades | Core | Partial | XL | Verified replacement bundles support fresh and partially applied histories; originals must be retained. | | MIG-06 | Schema-editor/provider capability contract | Core | Partial | XL | Versioned PostgreSQL renderer and capability validation; transactional DDL and explicit concurrent-index recovery are tested. | Evidence: [database integration](https://github.com/fauzaanu/cicadel/blob/main/database/database.go), [SQL migration runner](https://github.com/fauzaanu/cicadel/blob/main/database/migrations.go), [PostgreSQL tests](https://github.com/fauzaanu/cicadel/blob/main/database/database_test.go). GORM capabilities and Goose execution do not establish Django-style migration completeness. ## HTTP, templates, forms, and files Django references: [URL dispatch](https://docs.djangoproject.com/en/6.1/topics/http/urls/), [requests/responses](https://docs.djangoproject.com/en/6.1/ref/request-response/), [middleware](https://docs.djangoproject.com/en/6.1/topics/http/middleware/), [generic views](https://docs.djangoproject.com/en/6.1/topics/class-based-views/), [templates](https://docs.djangoproject.com/en/6.1/topics/templates/), [forms](https://docs.djangoproject.com/en/6.1/topics/forms/), [model forms](https://docs.djangoproject.com/en/6.1/topics/forms/modelforms/), [formsets](https://docs.djangoproject.com/en/6.1/topics/forms/formsets/), [uploads](https://docs.djangoproject.com/en/6.1/topics/http/file-uploads/), and [staticfiles](https://docs.djangoproject.com/en/6.1/ref/contrib/staticfiles/). | ID | Battery | Target | Current | Effort | Completion gap / intended scope | | --- | --- | --- | --- | --- | --- | | HTTP-01 | URL inclusion, names, reversal and parameter conversion | Core | Partial | M | Existing single-segment routing; complete converter/error/mount contracts and URL helper integration. | | HTTP-02 | Request parsing, responses, cookies and shortcuts | Core | Partial | M | Stable parsing/error contracts, streaming/files, content negotiation where promised and response tests. | | HTTP-03 | Middleware and request lifecycle | Core | Partial | M | Ordering, error handling, context ownership and streaming-compatible composition. | | HTTP-04 | Reusable list/detail/create/update/delete view helpers | Package | Absent | M | Go composition with forms, pagination and object-level permission checks. | | HTTP-05 | Conditional responses, ETags, modified dates and caching headers | Core | Dependency | M | Consistent helpers and behavior tests; standard-library availability alone is not integration. | | HTTP-06 | Compression and common redirect/slash middleware | Package | Dependency | M | Explicit ordering, cache variation and security-sensitive compression defaults. | | HTTP-07 | Async request handling and streaming | Core | Dependency | L | Go concurrency/cancellation equivalents; no WSGI/ASGI compatibility promise. | | TPL-01 | UI loading, namespaces, overrides and layout composition | Core | Complete | L | Typed namespaces, explicit compatible project overrides and layout composition; [verified scope](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md). | | TPL-02 | Context and rendering extensibility (Django counterpart: processors/tags/filters) | Core | Complete | L | Explicit typed props/dependencies and Go helpers; no implicit context processors or Django tags/filters. [Evidence](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md). | | TPL-03 | Deferred/template responses and fragment rendering | Package | Absent | M | Middleware-safe rendering lifecycle and buffered/streamed behavior. | | TPL-04 | Component engine: props, children, slots and isolated composition | Core | Complete | XL | Pinned parser/IR, Go type checking, explicit children/slots, diagnostics and bounded safe server rendering. [Scope/evidence](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md). | | TPL-05 | Reusable component libraries and application integration | Core | Complete | L | Versioned library exports, overrides/assets, starter/articles/admin conversion and independent generated-host installation. [Evidence](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md). | | FORM-01 | Typed fields, validators, binding, widgets and accessible errors | Core | Complete | L | Standalone typed fields, reusable/cross-field validators, immutable binding, accessible widgets and generated-consumer verification. See [completed forms contract](https://cicadel.fauzaanu.com/en/dev/topics/forms-completion/index.md). | | FORM-02 | Model-derived forms and persistence | Core | Complete | L | Explicit GORM field allowlists, typed binding, authorized locked updates, scoped foreign keys, constraint errors and transactional hooks. See [contract and acceptance evidence](https://cicadel.fauzaanu.com/en/dev/topics/model-forms/index.md); inline collections are provided by FORM-03. | | FORM-03 | Formsets and inline related-object editing | Package | Complete | L | Core `contrib/formsets`: bounded integer-key collections, explicit identity/deletion, scoped inline ownership, parent locking, cross-row validation and atomic saves. See [contract and tests](https://cicadel.fauzaanu.com/en/dev/ref/formsets/index.md); nested/automatic UI editing is excluded. | | FILE-01 | Upload parsing, file fields and storage integration | Core | Complete | L | Bounded multipart parsing, required/clear fields, content validation, random storage keys, compensating cleanup, model persistence and multipart CSRF. See [lifecycle contract](https://cicadel.fauzaanu.com/en/dev/topics/forms-completion/index.md#file-fields-and-persistence). | | FILE-02 | Local storage and replaceable remote storage | Core | Partial | M | Backend errors, collision policy, read/write/delete/URL contracts; signed URLs currently require a caller-provided signer. | | FILE-03 | Static discovery, collection, hashed manifests and development serving | Package | Partial | L | Dedicated serving plus first-party Tailwind compilation, explicit package class sources and embedded CSS are implemented. General asset collection, hashed manifests and automatic development serving remain. | | FILE-04 | Image fields and validation | Package | Absent | M | Format/dimension checks and safe decoding through established libraries, not an image editor. | Evidence: [urls](https://github.com/fauzaanu/cicadel/blob/main/urls/urls.go), [templates](https://github.com/fauzaanu/cicadel/blob/main/templates/templates.go), [forms](https://github.com/fauzaanu/cicadel/blob/main/forms/forms.go), [response](https://github.com/fauzaanu/cicadel/blob/main/response/response.go), [storage](https://github.com/fauzaanu/cicadel/blob/main/storage/storage.go), [static](https://github.com/fauzaanu/cicadel/blob/main/static/static.go). ## Authentication, security, sessions, and administration Django references: [authentication](https://docs.djangoproject.com/en/6.1/topics/auth/), [default auth workflows](https://docs.djangoproject.com/en/6.1/topics/auth/default/), [custom authentication](https://docs.djangoproject.com/en/6.1/topics/auth/customizing/), [sessions](https://docs.djangoproject.com/en/6.1/topics/http/sessions/), [security](https://docs.djangoproject.com/en/6.1/topics/security/), [signing](https://docs.djangoproject.com/en/6.1/topics/signing/), and [admin](https://docs.djangoproject.com/en/6.1/ref/contrib/admin/). | ID | Battery | Target | Current | Effort | Completion gap / intended scope | | --- | --- | --- | --- | --- | --- | | AUTH-01 | Users, authentication backends and current-user context | Package | Partial | L | Reusable PostgreSQL users, explicit credential backend, disabled-user enforcement and current-user middleware in [accounts](https://cicadel.fauzaanu.com/en/dev/ref/accounts/index.md). | | AUTH-02 | Password hashing, validation and upgrades | Package | Partial | L | Password policy hooks, bounded bcrypt input/cost and compare-and-swap rehash upgrades in accounts; PostgreSQL workflow tests cover upgrades. | | AUTH-03 | Login/logout, password change/reset and session revocation | Package | Partial | L | Accounts service and JSON login/logout, password change/reset, injected recovery delivery, single-use tokens and revocation implemented. Browser HTML pages, cookie/CSRF integration and an accounts starter now ship; public registration/verification and admin integration remain application or later-package work. | | AUTH-04 | Groups, permissions and authorization | Package | Partial | L | Persisted groups, memberships and exact model/action permissions in accounts; object access remains an explicit host policy with no implicit bypass. | | AUTH-05 | Session API, lifecycle, cleanup and store choices | Core | Partial | L | Accounts provides PostgreSQL bearer sessions, absolute/idle lifetime configuration, revocation and accounts:cleanup. Reusable SCS browser bridging now resolves account revocation on every request; PostgreSQL browser sessions have an additive package migration. | | SEC-01 | CSRF protection | Core | Partial | L | Session token protection exists; full form/AJAX/upload integration, origins/proxies and documented failure behavior. | | SEC-02 | Escaping, safe SQL, host/redirect validation and input limits | Core | Partial | L | Existing primitives; enforce their integration and test escape hatches across supported workflows. | | SEC-03 | Security middleware and deployment checks | Core | Partial | L | HTTPS/HSTS/proxy policy, CSP, clickjacking, referrer/opener policies and coherent checks; some headers already present. | | SEC-04 | Cryptographic signing, timestamped tokens and key rotation | Core | Absent | M | Purpose separation, expiration, tamper resistance, rotation and failure tests using standard primitives. | | ADMIN-01 | Model registration, CRUD and permission-safe forms | Package | Partial | XL | CRUD now uses shared model forms, revisions and atomic inline formsets; broader administration/account integration remains separately tracked. | | ADMIN-02 | Search, filters, ordering, pagination and actions | Package | Absent | L | Safe bounded queries, permission-aware actions and configurable list behavior. | | ADMIN-03 | Relations, inlines, widgets and customization | Package | Partial | XL | Explicit atomic inlines and shared widgets are implemented; autocomplete, read-only fields and broader customization remain. | | ADMIN-04 | Audit history, admin checks and staff access | Package | Absent | L | Attributed changes, reusable staff policy, checks and tested extension contracts. | Evidence: [security primitives](https://github.com/fauzaanu/cicadel/blob/main/security/security.go), [admin prototype](https://github.com/fauzaanu/cicadel/blob/main/admin/admin.go), [articles](https://github.com/fauzaanu/cicadel/blob/main/examples/articles/project/application_test.go), [catalog](https://github.com/fauzaanu/cicadel/blob/main/examples/catalog/project/application_test.go). Passing example tests does not complete auth or admin as batteries. ## Shared services, core modules, and testing Django references: [cache](https://docs.djangoproject.com/en/6.1/topics/cache/), [email](https://docs.djangoproject.com/en/6.1/topics/email/), [tasks](https://docs.djangoproject.com/en/6.1/topics/tasks/), [testing](https://docs.djangoproject.com/en/6.1/topics/testing/), [logging](https://docs.djangoproject.com/en/6.1/topics/logging/), [signals](https://docs.djangoproject.com/en/6.1/topics/signals/), and [contrib](https://docs.djangoproject.com/en/6.1/ref/contrib/). | ID | Battery | Target | Current | Effort | Completion gap / intended scope | | --- | --- | --- | --- | --- | --- | | SVC-01 | Cache API, aliases, backends and invalidation | Package | Partial | L | Context-aware backend errors, isolated aliases/versioned keys, bounded local adapter and cancellation-aware coalesced loading implemented; shared providers, consistency operations and provider conformance remain. See [cache contract](https://cicadel.fauzaanu.com/en/dev/topics/cache/index.md). | | SVC-02 | Per-view/site/template fragment caching | Package | Absent | L | Correct variation, authentication boundaries and explicit invalidation; cannot leak private responses. | | SVC-03 | Email messages, transport backends, attachments and testing | Package | Complete | L | Verified-TLS SMTP, reusable batches, MIME text/HTML, CC/BCC, reply-to, attachments and development backends are implemented; see [supported email contract](https://cicadel.fauzaanu.com/en/dev/topics/email/index.md). | | SVC-04 | Background task definitions, enqueueing, results and backend contracts | Package | Partial | L | River integration is useful but provider-specific; finish command/config/test contracts and task observability. | | SVC-05 | Logging, exception reporting and sensitive-data filtering | Core | Complete | M | Named routing, levels/filters, JSON/text/custom handlers, file rotation, error-email hooks, grouped redaction, correlated panic events and private query timing are implemented; see [logging contract](https://cicadel.fauzaanu.com/en/dev/topics/logging/index.md). | | SVC-06 | Paginator and reusable page links | Core | Partial | S | Offset validation exists; page/count/boundary/link behavior and template helpers remain. | | SVC-07 | Temporary user/flash messages | Core | Absent | S | Consume-once messages, levels, session/cookie lifecycle and template integration. | | SVC-08 | Signals and lifecycle events | Core | Partial | M | Explicit typed hooks with ordering and cleanup; observer callback/GORM hooks do not yet form a package-wide event contract. | | CONTRIB-01 | Content types and generic model relationships | Third-party | Excluded | — | Keep generic polymorphic persistence out of the core; auth/admin metadata should not require it. | | CONTRIB-02 | Database-backed flat pages | Third-party | Excluded | — | Content-management app rather than framework foundation. | | CONTRIB-03 | Database-managed redirects | Package | Absent | S | Separate from HTTP redirect safety; status/lookup/admin/cache behavior. | | CONTRIB-04 | Sitemap generation | Package | Absent | S | Escaped XML, chunking/indexes, URL construction and tests. | | CONTRIB-05 | RSS/Atom syndication feeds | Third-party | Excluded | — | Ordinary reusable app using Go XML libraries and package hooks. | | CONTRIB-06 | Sites/multiple-domain content registry | Third-party | Excluded | — | Application tenancy/content policy, not mandatory global state. | | CONTRIB-07 | Generated admin documentation | Third-party | Excluded | — | API/package metadata may enable external documentation tools. | | TEST-01 | Request client, test settings and assertions | Core | Partial | M | Standard `httptest` is used; provide coherent app fixtures and package testing helpers. | | TEST-02 | Test databases, transactions, fixtures and provider matrix | Core | Partial | L | Disposable PostgreSQL tests exist; isolation and every promised provider must be supported. | | TEST-03 | Live-server testing helpers | Package | Dependency | M | Go server lifecycle and deterministic readiness; browser tooling is external and is not needed for framework verification. | | TEST-04 | Email/task/cache test backends and query assertions | Core | Partial | M | Capture and task integration tests exist; unified backend contracts and query-count assertions remain. | Django's Tasks framework includes task APIs and development/test backends; production execution requires an external backend/worker. Do not count a production worker fleet as a battery Django itself ships. Cicadel's River integration is a chosen implementation, not a claim of Python task compatibility. See [Django Tasks](https://docs.djangoproject.com/en/6.1/topics/tasks/). ## Explicit exclusions and adjacent ecosystem features Django references: [internationalization/localization](https://docs.djangoproject.com/en/6.1/topics/i18n/), [time zones](https://docs.djangoproject.com/en/6.1/topics/i18n/timezones/), [humanize](https://docs.djangoproject.com/en/6.1/ref/contrib/humanize/), and [GeoDjango](https://docs.djangoproject.com/en/6.1/ref/contrib/gis/). | ID | Capability | Target | Current | Effort | Policy | | --- | --- | --- | --- | --- | --- | | EX-01 | Translation catalogs, pluralization, extraction and compilation | Third-party | Excluded | — | No native translation runtime or commands. | | EX-02 | Locale selection, negotiation and localized URLs | Third-party | Excluded | — | Request/template hooks permit optional packages; no native locale middleware. | | EX-03 | Localized dates/numbers/input formats and humanization | Third-party | Excluded | — | No first-party locale formatter or bundled catalogs. | | EX-04 | GIS models, spatial backends, geometry and map admin | Third-party | Excluded | — | No first-party GeoDjango equivalent. | | EX-05 | GeoJSON/GIS serializers and geographic imports | Third-party | Excluded | — | Basic JSON encoding remains available; geospatial semantics are external. | | TIME-01 | Correct timestamps, UTC storage and explicit time zones | Core | Partial | M | Keep temporal correctness; this is not a translation/locale-formatting battery. | | EXTRA-01 | REST framework, OpenAPI, API auth conventions | Package | Partial | L | Cicadel JSON helpers exist; a full REST framework is an additional product, not Django core. | | EXTRA-02 | WebSockets/channels and realtime infrastructure | Third-party | Excluded | — | Do not confuse Django async HTTP support with a bundled Channels stack. | | EXTRA-03 | Social login, OAuth/OIDC, MFA, account registration workflows | Third-party | Excluded | — | Provider integrations beyond the selected account battery; core hooks must permit them. | | EXTRA-04 | CORS middleware and API-specific policies | Package | Absent | M | Adjacent integration, not a claim that Django ships a general CORS middleware package. | | EXTRA-05 | Debug toolbar, profiling UI, CMS and full-text search service | Third-party | Excluded | — | Development/product extensions; provider-native query/search features remain separately tracked. | ## Complete component UI battery TPL-01/02/04/05 follow [the component UI acceptance checklist](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md#acceptance-checklist). The initial server component contract is complete with [recorded verification](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md), including a generated host consuming an independent module. The `html/template` package remains compatibility-only. Django template syntax is not a compatibility target. React-like UI composition does not imply a React dependency or an implemented client-side reactive runtime. ## Complete migration battery: acceptance checklist **Parent batteries:** MIG-01–06, DB-01 and DB-05. This is a major subsystem. Management now uses the recorded-history runner. Existing Goose-only databases require verified adoption; handwritten histories require reviewed import metadata. Django generates changes against recorded model history, not simply against whatever a developer's live database happens to contain. Cicadel needs an equivalent reliable workflow, adapted to Go. See [Django migration workflow and historical models](https://docs.djangoproject.com/en/6.1/topics/migrations/). - [x] Define a versioned, deterministic model-state format covering fields, types, nullability, defaults, relations, keys, constraints, indexes and custom-field metadata. - [x] Define discovery for `apps//models.go`, multiple model declaration files, and `apps//models/*.go`; use Go package/type analysis, respecting imports and build constraints, rather than regex or a filename-only scan. - [x] Tie discovery to explicitly installed apps; generate or validate an explicit model registry without runtime directory scanning or hidden import side effects. Diagnose incompatible build-tag model sets. - [x] Implement `makemigrations` to compare discovered declarations with recorded historical state, emitting stable, reviewable migration files; an unchanged model must generate nothing. - [x] Keep model-state diffing independent of database drift inspection. Detect drift separately; never use an arbitrary development database as the sole canonical schema history. - [x] Represent changes as versioned operations with provider rendering; preserve generated artifacts and historical adapters after current Go model types evolve. - [x] Implement additions, alterations, deletion, indexes, unique/check constraints, foreign keys and relationship tables on PostgreSQL. - [x] Handle renames and ambiguous/destructive changes through explicit declarative hints/flags and diagnostics; never silently guess a drop/create or invent a data backfill. Noninteractive runs fail clearly when intent is missing. - [x] Support nullable/default/backfill transitions and data migrations without requiring today's model structs to represent yesterday's schema. - [x] Build a version-level dependency graph spanning apps and packages; detect cycles, missing history and divergent branches; support explicit merge migrations. - [x] Supply `migrate`, `showmigrations`, `sqlmigrate`, plan/dry-run output, target versions, supported rollback and `makemigrations --check` for CI. - [x] Separate generating from applying migrations. No schema mutation on web startup, model import, or file save. - [x] Establish locking, history integrity, interruption/retry behavior and checksums/immutability rules for already-applied artifacts. - [x] Define and test PostgreSQL transactional DDL rollback and explicit recovery for supported nontransactional SQL. - [x] Test clean installs and upgrades with real PostgreSQL databases; publish exact supported versions, types and unsupported-operation diagnostics. - [x] Support package-supplied migrations, installation order, upgrades and removal policy without silently deleting user tables. - [x] Support historical-state data operations, migration squashing/replacements and projects upgrading from different prior states. - [x] Provide a documented transition for existing app-scoped Goose SQL histories; never reinterpret executed SQL as a portable model graph without explicit conversion evidence. - [x] Prove the whole workflow in a generated app with model declarations split across files/folders, related models, a rename, a non-null backfill, package upgrades and PostgreSQL. PostgreSQL is the only supported and planned database. Other providers are excluded, not unfinished acceptance requirements. Acceptance evidence: [module checklist](https://cicadel.fauzaanu.com/en/dev/sources/contrib/migrations/ACCEPTANCE.md), [generated consumer upgrade](https://github.com/fauzaanu/cicadel/blob/main/contrib/migrations/scaffold/scaffold_test.go), [lifecycle walkthrough](https://github.com/fauzaanu/cicadel/blob/main/contrib/migrations/example/workflow/main_test.go), and [verification record](https://cicadel.fauzaanu.com/en/dev/sources/docs/automated-migrations-progress.md). These checks cover the documented operation subset. Parent batteries remain Partial because the installable is experimental and has no published versioned release; advanced indexes, native enum/domain lifecycle and implicit join generation are excluded from inferred operations. This is not universal GORM or Django feature parity. ## Package system: acceptance checklist **Parent battery:** DEV-04. This is a composition boundary for core batteries and third-party extensions, including external localization. Go modules solve fetching/version selection; Cicadel must solve application integration. Django's [reusable-app workflow](https://docs.djangoproject.com/en/6.1/intro/reusable-apps/) is the reference, not a requirement to recreate Python packaging. - [x] Specify package identity, Go module/version, required Cicadel API range, app dependencies, capabilities and optional provider requirements. - [x] Use normal `go.mod`/`go.sum` pinning and standard Go installation; document private modules, reproducible builds and upgrades without a second resolver/registry. - [x] Provide explicit installation/registration and clear missing-dependency, incompatible-version, duplicate-name and cycle errors. - [ ] Define typed contribution contracts for routes, model metadata/migrations, commands, settings/checks, middleware, lifecycle hooks, component libraries/render helpers and static assets. - [x] Establish namespaces, override precedence and resource ownership; an installed package must not silently replace another package's routes, commands or settings. - [x] Run startup/shutdown hooks in dependency order with cleanup after failed initialization; document concurrent request behavior and test isolation. - [x] Define package database support and migration ownership; optional packages must not claim more providers than their conformance suite proves. - [ ] Extract first-party batteries into independently usable modules as appropriate, composing them into the standard core project. - [x] Supply a package scaffold, author tutorial and conformance harness; test installation in an independent application rather than only inside this repository. - [ ] Verify an external example can add translation middleware/template helpers through public hooks without importing a native Cicadel locale engine or patching core. The sample is a contract test, not a supported translation product. - [ ] Verify a second external package contributes commands, templates/assets and versioned migrations; exercise upgrade, disablement and removal without automatic data deletion. - [x] Document trusted-code execution, supply-chain responsibility, compatible version ranges, deprecation and security reporting. Installed Go packages execute with application privileges; this is not a sandbox. Implemented evidence: [public app contracts](https://github.com/fauzaanu/cicadel/blob/main/apps.go), [lifecycle](https://github.com/fauzaanu/cicadel/blob/main/lifecycle.go), [management integration](https://github.com/fauzaanu/cicadel/blob/main/management/management.go), [package scaffold](https://github.com/fauzaanu/cicadel/blob/main/internal/scaffold/package.go), [external install/upgrade/removal test](https://github.com/fauzaanu/cicadel/blob/main/internal/scaffold/package_test.go), and [author/consumer guide](https://cicadel.fauzaanu.com/en/dev/topics/installable-apps/index.md). Capabilities currently mean the typed contributions present on `App`; typed component exports, required assets and project overrides are implemented; runtime model contributions now expose explicit table/type ownership through `App.Models` and `ModelRegistry`; historical snapshots remain a separate migration-generator contract. The namespace contract permits only explicit compatible local-project component overrides; other contributions cannot be silently replaced. Provider evidence is PostgreSQL only. The external fixture already proves commands, assets, SQL migration upgrades and data retention on removal. A second external component module now proves templates/assets, typed slots and overrides in a generated application. The combined second-package commands/migrations/upgrade-removal item remains open: those lifecycle paths are verified in the existing first fixture, not redundantly claimed for the new component-only library. Accounts, formsets, migrations and query generation have independent modules. Other first-party integrations still share the root module; complete extraction is not claimed. No runtime binary plugin loader, automatic network installation during startup, global side-effect registry, or custom package marketplace is required for the first complete version. ## Delivery order and comparatively small batteries Work on one bounded battery at a time. Finish its acceptance evidence before calling it complete; split large batteries into unchecked subitems rather than weakening the definition. 1. **Package foundation (DEV-03/04/05/06):** the composition boundary for core defaults and third-party extensions. Establish contracts before growing more integrations. 2. **Model state and provider contracts (DB-01, MIG-01/06):** groundwork for model-driven migrations; follow the migration checklist incrementally. 3. **Small contained gaps:** reusable pagination (SVC-06), flash messages (SVC-07), optional sitemap generation (CONTRIB-04), and optional managed redirects (CONTRIB-03). Each still needs package/config/test integration and its own acceptance checklist. 4. **Complete common application workflows:** component engine and reusable forms/model forms, account lifecycle, static assets, mail delivery, then admin built on those completed contracts. 5. **Finish PostgreSQL migrations and durable compatibility:** do not let quick wins substitute for this central Django-familiar battery. 6. **Other selected optional services:** cache backends, task ergonomics, fixtures and diagnostics, driven by applications and their integration tests. No feature becomes mandatory merely because it appears in Django. Third-party-only rows remain visible so future contributors can see that omission was intentional. Revisit a support decision explicitly, with reasons and dependency impact, before expanding core. ## Maintenance rules - Keep stable IDs when splitting batteries; record superseded scope rather than deleting inconvenient gaps. - When implementing a row, add its detailed checklist and evidence here or in a linked design document. Link code/tests and provider/version coverage before changing status to Complete. - Keep [PLAN.md](https://cicadel.fauzaanu.com/en/dev/sources/PLAN.md) for concrete implementation tasks and historical foundation work. Its checked boxes do not imply that the larger batteries in this file are complete. - Update README, API docs and release scope together when support policy changes. A dependency present in `go.mod` is not itself a promised user-facing capability. - Maintain exclusions alongside supported work; never quietly reintroduce native i18n/l10n or GIS through a convenience dependency. ## Migration installable progress - [x] Detailed installable-development skill with authoring, lifecycle, data and verification references. - [x] Separate `contrib/migrations` Go module and offline `migrations:makemigrations` command. - [x] Explicit model registration across Go files; deterministic snapshots recorded inside SQL files. - [x] PostgreSQL table creation, additive columns/indexes and same-app belongs-to foreign keys. - [x] Read-only preview/check, no-op detection and rejection of unsupported or edited histories. - [x] PostgreSQL create/upgrade/data-preservation and reverse/reapply integration tests. - [x] Automatic source discovery, verified baseline/adoption, recorded data operations and declared supported schema alterations. - [x] PostgreSQL conformance for the documented supported subset and migration graph/history workflow above. - [x] Evaluate an first-party GORM GEN installable for type-safe query generation from authored models; test version compatibility and reproducible regeneration. GEN is complementary to schema migrations. Evidence: [migration module and limitations](https://cicadel.fauzaanu.com/en/dev/ref/migrations/index.md), [tests](https://github.com/fauzaanu/cicadel/blob/main/contrib/migrations/generate_test.go), [GORM GEN documentation](https://gorm.io/gen/index.html). ## Browser accounts, email and logging evidence [Authentication](https://cicadel.fauzaanu.com/en/dev/topics/authentication/index.md), [email](https://cicadel.fauzaanu.com/en/dev/topics/email/index.md) and [logging](https://cicadel.fauzaanu.com/en/dev/topics/logging/index.md) define current supported scope and exclusions. Browser account tests use real PostgreSQL, generated-consumer tests cover provisioning/login/password changes, SMTP tests use verified local TLS servers, and logging tests cover routing/redaction/failures. Authentication remains Partial as a broader battery because public signup/verification, broader identity-provider workflows and administration integration are not bundled by this change. SMTPUTF8/DSN, automatic mail queues, arbitrary free-text secret detection and third-party log exporters are outside the documented email/logging scope. --- Source: `contrib/formsets/TESTING.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/contrib/formsets/TESTING.md # Verification Run from this directory against a disposable PostgreSQL 18 database: ```sh export CICADEL_TEST_DATABASE_URL='postgres:///cicadel_formsets_test?host=/tmp&sslmode=disable' go run github.com/fauzaanu/cicadel/cmd/cicadel ui check --json go test -race ./... go vet ./... go test . -run '^$' -fuzz FuzzManagement -fuzztime 5s go run golang.org/x/vuln/cmd/govulncheck@latest ./... go build ./... ``` `TestGeneratedConsumer` creates a fresh project, uses explicit local module replacements, registers the app, and runs a PostgreSQL HTTP workflow with the race detector. No module publication or remote installation is claimed. Database tests skip without the environment variable; CI supplies it. Root `go test ./...` does not include this nested module; `.github/workflows/formsets.yml` runs its checks. Verified on 2026-10-31 with Go 1.26.10 and PostgreSQL 18.4: package race tests (including the generated consumer), vet, build, and vulnerability scanning passed. The management-input fuzz run completed 159,842 executions without failure. The repository's strict root integration run also passed with zero skipped tests; component-library, migrations and querygen module checks were run independently. --- Source: `contrib/migrations/ACCEPTANCE.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/contrib/migrations/ACCEPTANCE.md # Automated migration acceptance Existing format-1 SQL files are immutable. Core Goose execution remains available while the installable evolves. Check items only with implementation and test evidence. ## Discovery and query generation - [x] Generate deterministic explicit registries from opted-in model declarations in `models.go` and `models/*.go` using Go package analysis. - [x] Honor build tags, exclude helper structs and tests, diagnose stale registries, and run without a database. - [x] Keep explicit registration available and scope discovery to explicitly selected app packages. - [x] Verify optional GORM GEN against GORM v1.31.2, reproducible output and compiled queries against a real database in a separate consumer. ## PostgreSQL schema - [x] Require explicit source/target rename declarations; reject undeclared removals and conversions before writing files. - [x] Test column/table removal, type/null/default transitions, backfills, index/constraint changes and relationship/key variants. - [x] Version PostgreSQL capabilities and schema rendering; reject unsupported operations before execution. - [x] Test PostgreSQL schema operations and data preservation against a real server. - [x] Test PostgreSQL concurrent-index partial failure, explicit repair and safe retry; reject other nontransactional SQL. ## History and execution - [x] Retain format-1 fixtures byte-for-byte and verify append-only format upgrades. - [x] Resolve cross-app version dependencies deterministically; reject missing dependencies, cycles and branch conflicts. - [x] Test explicit merge migrations and historical state independently of current Go models. - [x] Test squash/replacement from fresh and every partially applied replaced history. - [x] Expose inspection, SQL preview, execution plans, target application and rollback. - [x] Test locking, concurrent runners, checksum mismatches, missing applied files, failures, retries and irreversible/data-loss guards. - [x] Support explicit data SQL and handwritten schema transitions with declared historical states. - [x] Verify baseline/adoption against actual schema; detect drift without rewriting history or pretending SQL ran. ## Delivery - [x] Supply runnable lifecycle example with initial generation/application, rename, backfill, data migration, cross-app dependency, rollback and recovery. - [x] Integrate generated project/app workflow without changing runtime ORM or invoking AutoMigrate. - [x] Run nested-module unit, integration, race and PostgreSQL conformance tests explicitly in CI. - [x] Verify independent consumer installation and document exact tested versions and upgrade limitations. ## Evidence and scope The generated separate consumer verifies local module/tool installation, split model packages, related models, embedded history, initial and upgraded prefixes, rename/backfill, status and retained rows after registration removal. The lifecycle example additionally verifies cross-app dependencies, rollback, data SQL and transactional/nontransactional recovery. Both run against PostgreSQL in CI. See [the verification record](https://cicadel.fauzaanu.com/en/dev/sources/docs/automated-migrations-progress.md) for the final checks. Installation uses local replacements; no public release/tag is claimed. Supported storage/operation boundaries are documented in the README. --- Source: `docs/architecture.md` Markdown: https://cicadel.fauzaanu.com/en/dev/internals/architecture/index.md # Architecture decisions These decisions are owned by the implementation, as delegated in PLAN.md. ## Runtime and packages Use Go 1.26.10 or newer in the 1.26 line initially, with PostgreSQL 18 as the only supported database. The module is `github.com/fauzaanu/cicadel`. Framework packages are small and public; CLI generation internals stay under `internal/`. Applications are ordinary Go modules with `manage.go`, `project/settings`, `project/urls.go`, and explicitly registered `apps/` packages. SQLite, MySQL and MariaDB are excluded; there is no multi-provider roadmap. ## ORM and migrations Use GORM v1.31.2 with its PostgreSQL driver. Applications receive `*gorm.DB` directly and attach request contexts with `WithContext`. GORM's [documented relationships, transactions and context support](https://gorm.io/docs/) fit model-centered applications without requiring a new query abstraction. It uses an MIT license. Dependencies are pinned in go.mod/go.sum; upgrades require the integration suite and vulnerability checks. Alternatives considered: [Ent](https://entgo.io/docs/getting-started/) provides generated types and a schema/code-generation workflow (Apache-2.0); [Bun](https://bun.uptrace.dev/guide/) offers a SQL-first interface (BSD-2-Clause). Both are credible choices. GORM is selected because plain model structs, associations, hooks, and direct queries most closely fit this project's initial Django-familiar workflow. This is a design judgment, not a claim that GORM is universally faster or better. Dependency releases and licenses are inspectable through the pinned modules; popularity is not treated as a correctness guarantee. Use the first-party recorded-history migration engine through management commands. It generates reviewable SQL from registered model state, validates version dependencies, and executes under a shared PostgreSQL advisory lock. SQL changes, compatible version records and checksums commit together. There is no automatic migration at startup. Supported concurrent-index operations use explicit recovery; separate migrations are not one atomic deployment. ## Routing and application composition Use `net/http.ServeMux` with method/path patterns. `urls.Route` adds names and single-segment parameter reversal. `urls.Include` adds a path prefix and namespace. Duplicate names, overlapping patterns, and invalid parameter forms fail construction. Terminal slash routes match exactly. No regex converters or catch-all reversal in the initial API. Apps register explicitly and declare dependencies; a stable topological sort rejects unknown dependencies and cycles. Middleware arguments run in the order supplied, outermost first. Host checks, body limits, response security headers, and panic recovery wrap application middleware. Settings are defaults → project assignments → environment overrides, validated before startup. ## Component UI and development Use a component-first UI engine inspired by React and Django Cotton. Props, children, named slots and isolated composition are the public model. Django template syntax, inheritance and implicit context are not the foundation. [The component UI specification](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md) defines the implemented initial scope and acceptance evidence. The server engine uses templ v0.3.1100's parser/IR and Go generator, with Cicadel contracts and AST instrumentation. Typed definitions, explicit slots, registry overrides, private request buffers and source-aware bounded render frames belong to Cicadel. The starter, articles and admin use compiled components. React/Node and hydration are excluded. Use `go tool cicadel dev` for automatic component/CSS compilation and safe executable rebuild/restart. Failed builds preserve the working server; successful builds drain and reap the old process before replacement. Manual `ui build`, `ui check` and `runserver` remain supported. See [the foundation contract](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md). Keep production assets embedded or explicitly configured; never serve the repository root. ## Sessions and authentication Use SCS with PostgreSQL-backed opaque sessions, hashed stored tokens, HttpOnly cookies, SameSite=Lax, secure cookies in production, absolute and idle expiry, token rotation at login, and destruction at logout. SCS owns session encoding and storage. Standard projects compose `contrib/accounts` through the public installable contract. Its browser bridge stores account tokens only in the server-side session and resolves the account on every request; its JSON API uses bearer headers. Applications own object permission policy. See [authentication](https://cicadel.fauzaanu.com/en/dev/topics/authentication/index.md). Use bcrypt with explicit byte-length validation; accept passwords of 12–72 bytes. Cookie-authenticated writes require a random synchronizer CSRF token stored in the session, submitted via form or header and compared in constant time. Login forms are protected too. Trust no forwarded host/protocol headers by default; terminate TLS at a configured reverse proxy and keep secure cookies enabled. ## Performance and threat model Measure standard mux versus named-router dispatch, template rendering, database reads/writes, and full HTTP requests. Include allocations, throughput, latency percentiles, and error counts. Database data, connection limits, concurrency, and hardware must be recorded. No Django speedup claim is justified by language choice alone. Primary threats: hostile Host headers; oversized inputs; SQL injection through raw query interpolation; HTML injection; open redirects; stolen/fixed sessions; cross-site writes; object-level authorization bypass; filesystem traversal; secret leakage through logs/errors; migration races and partial failures. Boundaries require targeted tests. This document is not an independent security audit. ## Battery scope revision [batteries.md](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md) supersedes any earlier implication that these integration decisions complete a Django-equivalent battery. PostgreSQL is the only supported and planned backend. SQLite, MySQL and MariaDB are excluded. Model-driven migration generation requires historical schema state, a version-level dependency graph and provider capabilities, not just GORM schema inspection or Goose SQL execution. Management commands use the first-party migration module for those contracts and its documented PostgreSQL operation subset. Native i18n/l10n and GIS are excluded from first-party support. The experimental locale package has been removed. Third-party localization must be possible through public package/middleware/template contracts. Go modules handle distribution; the initial Cicadel lifecycle and compatibility contract is now implemented; component integration is verified; model integration and module extraction remain separately tracked. ## Installable app foundation The first extension API uses explicit `App` descriptors with manifests, half-open dependency version ranges and a separately versioned app API. Go modules remain the dependency resolver. Registration happens in `project/apps.go`; imports never activate apps. Commands/checks/resources are namespaced, middleware is route-scoped, and lifecycle hooks acquire per-host state only after checks. PostgreSQL migration commands do not start runtime hooks. See [the full contract and evidence](https://cicadel.fauzaanu.com/en/dev/topics/installable-apps/index.md). Batteries should be developed against this public package boundary first. Promotion to first-party maintenance preserves app labels/migration identity and makes the capability a core default through the same public contracts. ## First-party default styling Tailwind CSS v4 is the default component styling workflow, with a pinned standalone compiler and checksum-verified explicit installation. Generated projects ship CSS input/config, compiled CSS, a styled component, and an embedded asset route. The compiler is development/CI tooling, never a production process. `ui build/check` cover configured CSS and markup together. Applications may explicitly opt out and retain another CSS system. See [Tailwind](https://cicadel.fauzaanu.com/en/dev/howto/tailwind/index.md) and the tested [React-style authoring guide](https://cicadel.fauzaanu.com/en/dev/howto/component-authoring/index.md). ## Browser starter and operations `startproject` composes the core accounts and formsets modules, PostgreSQL SCS store, compiled HTML screens and application-owned recovery delivery. The default project and account pages share a green-and-black Tailwind design. [Email](https://cicadel.fauzaanu.com/en/dev/topics/email/index.md) and [logging](https://cicadel.fauzaanu.com/en/dev/topics/logging/index.md) define transport, configuration, redaction, cancellation and output-lifecycle contracts. --- Source: `docs/automated-migrations-progress.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/automated-migrations-progress.md # Automated migrations: verification and handoff record **Resumed and locally verified on 2026-10-31.** The original pause checkpoint below is retained as historical evidence. The resumed verification section supersedes its outstanding local checks. Delivery is recorded by the final Git commit and GitHub workflow results; a local check is not a claim of remote success. ## Scope and standing constraints - PostgreSQL only. SQLite, MySQL and MariaDB are excluded, not pending work. This correction is recorded in `AGENTS.md`, `PLAN.md`, `batteries.md` and the architecture document. Do not reintroduce a multi-provider roadmap. - GORM remains the runtime ORM. Never replace recorded SQL with AutoMigrate. - Keep `contrib/migrations` and `contrib/querygen` independently installable. - No computer use, GUI automation or browser automation. - Preserve unrelated testing-framework and component/UI work. Stage explicit migration/query-generation paths only; do not use `git add .`. - Do not ask for implementation decisions. Keep unfinished items unchecked and report unsupported behavior and skipped verification honestly. ## Implemented and previously pushed The original foundation was commit `60a1b66`. Subsequent migration work includes: | Commit | Increment | | --- | --- | | `f204ac4` | PostgreSQL-only scope and concrete migration acceptance checklist | | `785b7fa` | Deterministic model discovery and first-party GORM GEN integration | | `b2912c5` | Explicit schema-change declarations and recorded data SQL | | `2c1e056` | Planning, execution checksums, schema verification and adoption | | `39df357` | Composite keys, inverse relationships and check constraints | | `3a523df` | Historical SQL transitions and audited initial baselines | | `73d4c0b` | Explicit branches, merges and verified replacement bundles | | `593a54a` | PostgreSQL renderer contract and concurrent-index recovery | | `f28cc72` | Cross-app FKs pinned to historical dependency snapshots | | `b869664` | Offline tooling scaffold and runnable lifecycle example | | `1ae0134` | Reviewed handwritten Goose history import without SQL rewrites | Other intervening commits belong to other threads; do not assume the above is the entire repository history. ### Discovery and query generation - Go package/type analysis discovers explicitly marked `//cicadel:model` structs. It respects build constraints, excludes test files/unmarked helpers, and emits deterministic explicit registries. `--check` catches stale registries. - Explicit model registration remains available; generation needs no database. - `contrib/querygen` uses authored structs with GEN `v0.3.29`, GORM `v1.31.2` and dbresolver `v1.6.2`. GEN's default dbresolver `v1.5.3` failed to compile against this GORM version; the override is deliberate. - Committed generated queries have reproducibility and PostgreSQL runtime tests. Separate consumer tests use local module replacements, not a published release. - Upstream GEN transitively includes other vendor packages. This does not add another supported database to Cicadel. ### Schema and history - Explicit table/column renames, removals, type conversions, null/default changes, backfills, index/FK/check replacement and authored schema/data SQL. - Destructive renames are never inferred. Conversions require authored expressions; removals require reasons. Irreversible migrations refuse Down. - Single/composite PKs and FKs, unique-key references, has-one/has-many/belongs-to relationships, check constraints and explicitly modeled join tables. - Cross-app references pin recorded schemas and add version dependencies. - Format 3 records explicit parent hashes. Formats 1 and 2 remain readable without rewriting files; format-1 validation/diff has a frozen adapter. - Deterministic dependency ordering, cycle/missing-parent detection, branch conflict detection and explicit compatible merges. Conflicting schema edits are rejected. - Replacement bundles consolidate SQL without deleting originals. Fresh installs can execute a bundle atomically; older prefixes run remaining originals. Bundle execution is audited, and missing/edited executed bundles are detected. ### Execution, adoption and recovery - PostgreSQL runner shares Goose's advisory lock and records transactionally executed SQL, Goose history and checksums together. - Applied/pending inspection, execution plans, SQL previews, targets and rollback. - Schema verification before execution and inside transactional migrations before commit. Scratch schemas are rolled back/dropped and require database CREATE privilege. Verification includes managed columns/defaults, identities and sequence properties, indexes, constraints, user-trigger presence and RLS flags. - Verified adoption of existing generated Goose histories; explicit initial baselines audit adoption separately from execution and preserve existing rows. - Handwritten history import requires a reviewed schema snapshot for every old version. A sidecar manifest binds metadata and unchanged source SQL. Existing applied prefixes must pass schema verification before checksum adoption. - Explicit concurrent-index migrations use durable dirty markers. Failures block automatic retry. `Recover(..., "retry")` verifies the pre-state after manual repair; `"complete"` verifies the post-state after interrupted completion. Both are audited. Other nontransactional operations are rejected. ## Work included in this pause checkpoint These changes were added after the last increment above and are being committed with this handoff: - Read-only `fs.FS` histories for package-owned/embedded migrations. Writing tools reject embedded sources. The separate consumer now tests embedded application. - Stricter missing-source diagnostics; unexpected managed tables outside applied state and identity-sequence name/property drift are checked. - Frozen format-2 fixtures plus a real PostgreSQL upgrade from an already-applied format-2 prefix to format 3, without rewriting old SQL. - Explicit versioned custom-field storage metadata (`CustomType`, `SnapshotWithOptions`, `Definition.CustomTypes`) mapped to supported built-in PostgreSQL types. UUID, JSON serializer and numeric precision changes have a real GORM read/write and migration test. No custom field code is needed to replay old files. Native user-defined enum/domain types are not automatically managed. - `Runner.Status`, CLI `status` and familiar `migrate`, `showmigrations`, `sqlmigrate` aliases. The small example host now uses the checksum-aware runner for migrate/showmigrations. - GEN rejects unexported/generic model names that generated imports cannot name. - Nested-module dependency files were refreshed for the independently committed framework UI dependency. No unrelated core/UI source edits are part of this checkpoint. ## Entry points and useful files - `contrib/migrations/ACCEPTANCE.md`: concrete acceptance checklist. - `contrib/migrations/README.md`: detailed API and workflow notes; needs the consistency cleanup listed below. - `docs/migrations.md`: installation, Go tool directives, scaffold and examples. - `contrib/migrations/cmd/cicadel-models`: registry generation/check. - `contrib/migrations/cmd/cicadel-migrations-init`: optional project initializer. - `contrib/migrations/cmd/cicadel-migrate`: inspection/execution/history commands. - `contrib/migrations/example/workflow`: disposable lifecycle walkthrough. - `contrib/querygen/README.md`: GEN compatibility and usage. - `.github/workflows/migration-installables.yml`: explicit nested-module CI. Install command packages with `go get -tool` in consumers. Ordinary `go mod tidy` can remove command-only dependencies when commands are not registered as tools; the separate consumer test caught and now covers this issue. The walkthrough creates a unique disposable schema, generates initial migrations, applies a cross-app FK, renames/reverses/reapplies a column, converts/backfills, records/reverses data SQL, retries a failed transaction and explicitly repairs a failed concurrent unique index. It retains artifact files and removes its schema. ## Verification actually performed - Repeated migration-module unit/integration/race suites and `go vet ./...` passed during the verified increments, against local **PostgreSQL 18.4**. - The full migration suite passed after handwritten import, embedded-source support and tighter schema verification. Later changes were tested with focused runs; the exact final aggregate checkpoint has **not** had a fresh full run. - Focused format-2 applied-prefix upgrade test passed with the race detector. - Focused custom-field PostgreSQL/GORM tests passed with the race detector. - Querygen's full race suite, vet, deterministic regeneration, PostgreSQL queries and separate consumer passed before its latest exported-name validation change. That latest change still needs the final full querygen run. - Separate migration consumer passed actual local `go get`, tool registration, scaffold, discovery/check, offline generation and embedded PostgreSQL execution. - The lifecycle example's PostgreSQL integration test passed. - Root-wide tests/vet and remote CI for the final checkpoint were **not verified** by this thread. Other threads were editing core/UI and scaffolding concurrently. Local test database created for this work: `cicadel_migration_work` on the local PostgreSQL Unix socket. It was not dropped at pause. Typical test DSN: `postgres:///cicadel_migration_work?host=/tmp`. Tests use their own fixture tables or schemas; use a disposable database, not application data. ## Resume checklist — resolved locally - [x] Read `AGENTS.md`, this handoff, the installable skill/references and current Git status/history before changing anything. - [x] Run gofmt and final unit/integration/race/vet checks in both nested modules against the exact resumed checkout. Inspect any new root dependency changes. - [x] Run appropriate root checks without taking over another thread's work. - [x] Review the latest custom-type, embedded-source, status/CLI-alias and schema verification changes together. Add missing regression coverage where needed. - [x] Reconcile `batteries.md`, `PLAN.md` and `ACCEPTANCE.md` with actual evidence. Implemented items now link to evidence; broader parent batteries remain Partial. - [x] Rewrite/consolidate `contrib/migrations/README.md`: appended sections describe the new workflow; removed the stale early claim that graphs, merges, squash, baselines and drift checks were unimplemented. Explain custom types and the new status aliases, and align legacy examples with the checksum-aware runner. Avoid contradictory support claims. - [x] Update relevant installable-app documentation/skill references now that core UI work is separately committed; preserve other threads' documentation edits. - [x] Confirm CI explicitly runs all nested-module tests and registry checks; inspect remote CI results rather than assuming a push passed. The prior head `239afaf` passed both workflows; the new commit must also pass before completion. - [x] Review the eight capability areas preserved in this handoff against implementation, document any remaining scope gaps, prepare the verified final increment for commit/push (delivery is recorded in Git). Suggested final commands, run separately in the relevant directories: ```sh # contrib/migrations go mod tidy CICADEL_TEST_DATABASE_URL='postgres:///cicadel_migration_work?host=/tmp' go test -race ./... go vet ./... go run ./cmd/cicadel-models --check --out example/modelregistry/models.gen.go ./example/models # contrib/querygen go mod tidy CICADEL_TEST_DATABASE_URL='postgres:///cicadel_migration_work?host=/tmp' go test -race ./... go vet ./... ``` ## Boundaries that must remain explicit - No published installable release/tag was created. Local replacement tests are not verification of remote versioned distribution. - Advanced/expression/partial indexes, implicit many-to-many join generation, native PostgreSQL enum/domain lifecycle and arbitrary custom SQL storage types are not inferred. Explicit join models and registered built-in storage mappings are supported. Document unsupported objects instead of claiming universal GORM migration parity. - Schema verification is not row-content verification, a backup, a permission audit or proof that arbitrary authored data SQL commutes across branches. - Imported histories reject unsupported Goose directives (including environment substitution and NO TRANSACTION), transaction control and CRLF source files. They require deliberate conversion instead of silently changing execution. - Squashing retains originals and consolidates SQL; it does not optimize SQL away or support deleting histories still needed by older deployments. Concurrent DDL cannot be placed in a transactional replacement bundle. - Cross-app destructive changes require an explicit dependency sequence, such as removing a dependent FK before renaming its referenced table and then adding the FK against the new pinned snapshot. - Superseded by default-workflow consolidation: management commands now use the checksum-aware runner; the legacy core executor has been removed. ## Resumed verification — 2026-10-31 Reviewed the custom-field metadata, read-only source handling, status/aliases and catalog verification together. Added a missing generated-consumer upgrade test: split model packages and related models, embedded initial history, rename and non-null backfill with existing rows, pending/applied status, then removal of registration without deleting rows. This runs through the generated offline entrypoint and checksum-aware runtime runner against PostgreSQL. Reconciled the README, acceptance checklist, batteries, plan, installable-app guide and repository skill reference. Parent batteries retain experimental/Partial status; no public release, universal GORM parity or unsupported PostgreSQL objects are claimed. `go mod tidy` only corrected the PostgreSQL test driver's direct requirement classification; versions did not change. Formatting and diff checks passed. Local verification used Go 1.26.10 and PostgreSQL 18.4: - Both nested modules: tidy, full race suites with the PostgreSQL DSN, and vet. Migration registry `--check` passed. Suites include deterministic GEN output, separate consumers, frozen format upgrades and the lifecycle walkthrough. - Root: Tailwind installation check, `ui check --json`, strict required-integration test runner with race/coverage, vet and build. - Component-library module: generated UI check, race tests and vet. - All six CI fuzz targets: Compile, TextBoundary, Attributes, Reverse, Settings and ClientPath, each for the required five seconds. - Root and migration govulncheck: no reachable vulnerabilities. Root reported one module-level advisory outside imported vulnerable packages/called symbols. - Both push workflows explicitly cover the nested modules; registry verification is in `migration-installables.yml`. `release.yml` is dispatch-only; no release or tag is part of this change. Eight capability areas are covered by concrete evidence: | Area | Evidence | | --- | --- | | Model discovery | `discovery` tests and generated-consumer registry checks | | Optional typed queries | querygen compatibility, regeneration and consumer tests | | Model state and schema changes | changes, relationships, custom-types and provider tests | | Historical data and compatibility | historical, format compatibility and import tests | | Dependencies and merging | graph and pinned cross-app reference tests | | Execution and recovery | runner, lock, baseline and concurrent-index recovery tests | | Replacement and upgrades | every-prefix squash tests and generated-consumer upgrade | | Installation and workflow | scaffold consumer, lifecycle walkthrough, root package lifecycle tests | The supported operation boundary remains the one stated above and in the README; advanced indexes, implicit join generation, native enum/domain lifecycle and remote versioned distribution are not silently included by checklist completion. --- Source: `docs/component-authoring-verification.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/component-authoring-verification.md # Component authoring and Tailwind verification Verified locally on 2026-10-29 using Go 1.26.10, macOS arm64, PostgreSQL 18.4, and the SHA256-verified Tailwind v4.3.3 standalone executable. Browser/desktop automation was not used. This adds to the [original component verification](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md). ## Executed checks ```sh go run ./cmd/cicadel ui css install go run ./cmd/cicadel ui check --json go vet ./... go build ./... # CICADEL_TEST_DATABASE_URL pointed at a fresh temporary local PostgreSQL cluster. go run ./cmd/cicadel test --strict --require-integration \ --report /tmp/cicadel-authoring-tests.json -- -race ./... # Independently versioned component library, run separately. cd examples/component-library go run github.com/fauzaanu/cicadel/cmd/cicadel ui check --json go test -race ./... ``` All passed. The root strict report records **137 passing named test/subtest outcomes and zero named skips/failures**. It includes database-backed articles and catalog security/persistence tests, original component tests, and the new CSS/docs checks. Preserve the [machine-readable report](https://github.com/fauzaanu/cicadel/blob/main/docs/component-authoring-test-results.json). The temporary PostgreSQL cluster was stopped after verification. No migration or query-generator work from other threads was included. The skill passed the bundled `skill-creator/scripts/quick_validate.py` validator using an isolated `uv run --no-project --with pyyaml` environment. Both its repository copy and its installed Codex copy validated. All relative Markdown file links in the new authoring guide, Tailwind guide and skill resolve. Metadata and file validation do not establish that every possible agent will use the skill correctly; the executable guide supplies behavioral evidence instead. ## What the tests establish - `TestComponentAuthoringGuide` reads the actual file-marked code fences from the guide, copies them into a freshly generated application, compiles `.templ`, builds Tailwind, checks expected utilities from markup and Go variant strings, and runs source checks, race-enabled Go/HTTP tests, and host configuration checks. Its copied tests exercise malicious text, required slots, variant validation, empty collections, named footer composition, default props and stylesheet links. - `TestStarterTailwind` compares the stylesheet shipped in every starter with fresh output from the actual pinned compiler. No handwritten approximation of Tailwind utilities is used. - `TestGeneratedProject` exercises the default home HTML and embedded stylesheet route, including real generated Tailwind selectors. - `TestRealCompiler` verifies responsive/hover selectors, deterministic freshness, source invalidation, check-mode nonmutation and preservation of the previous stylesheet after a failed CSS compile. - `TestIntegrity` rejects changed executable bytes; config tests reject unsupported versions/paths, unknown fields, input/output collisions and trailing JSON. - `TestPackageSources` resolves explicit Go package source directories and rejects missing packages. `TestExternalComponentLibrary` goes further: it installs a library through a local Go proxy into a generated application, discovers a class from its module-cache source, and checks the embedded CSS route while executing compiled HTTP tests outside the repository tree. - `TestStylesheetURL` checks URL sanitization and verifies that a layout with no explicit stylesheet does not silently impose Tailwind on existing applications. The component parser/render engine was not redesigned. Existing fuzz seed tests ran in the root suite; the earlier timed fuzz evidence remains in the original verification record. No new timed fuzz run or performance improvement is claimed. ## Scope boundaries The automatic standalone pins include macOS arm64/x64, Linux glibc arm64/x64 and Windows x64. Local execution evidence is macOS arm64; Linux CI is configured but is not represented here as already passed. The tool is explicitly installed once; server startup never downloads or compiles CSS. There is no Node/npm runtime, HMR, general asset-hashing/collection pipeline, or guarantee of arbitrary npm plugin compatibility. Other CSS systems can replace the default without changing the component runtime. These limits are documented in [the Tailwind guide](https://cicadel.fauzaanu.com/en/dev/howto/tailwind/index.md). --- Source: `docs/component-verification.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md # Component verification record Verified locally on 2026-10-29, Go 1.26.10, macOS arm64 / Apple M4 (10 logical CPUs), PostgreSQL 18.4 (Homebrew). The database was a fresh temporary local cluster; the existing test fixtures created isolated databases. No production data or GUI was used. Migration-module work in the shared checkout was not edited or claimed. ## Commands and results ```sh # Root module: no server or Go initialization executes during ui check. go run ./cmd/cicadel ui check --json go vet ./... go build ./... # Set CICADEL_TEST_DATABASE_URL to a dedicated test PostgreSQL administrator URL. go run ./cmd/cicadel test --strict --require-integration \ --report /tmp/cicadel-ui-test-results.json -- -race ./... go test ./uic -run '^$' -fuzz '^FuzzCompile$' -fuzztime 10s go test ./ui -run '^$' -fuzz '^FuzzTextBoundary$' -fuzztime 10s go test ./ui -run '^$' -fuzz '^FuzzAttributes$' -fuzztime 10s # Separate module; root ./... intentionally excludes it. cd examples/component-library go run github.com/fauzaanu/cicadel/cmd/cicadel ui check --json go test -race ./... go vet ./... ``` All commands passed. The root strict report records **130 passing named test / subtest outcomes, zero failed or skipped named tests**, and 24 passing test packages. Twelve additional package events say `skip` because those packages have no test files; these are not skipped named tests. Nested consumer tests launched by the scaffold tests are additional subprocess checks, not separate records in this count. The independent library module passed its race-enabled HTTP/render test. Preserved results: [root JSON report](https://github.com/fauzaanu/cicadel/blob/main/docs/component-test-results.json), [fuzz output](https://github.com/fauzaanu/cicadel/blob/main/docs/component-fuzz.txt), [benchmark output](https://github.com/fauzaanu/cicadel/blob/main/docs/component-benchmarks.txt). The final bounded fuzz runs performed 211,184 compiler executions, 486,064 text boundary executions, and 1,987,512 attribute executions without a failure. Fuzz counts vary with cache/corpus, hardware and concurrent load; this is sampled boundary testing, not proof that every input is safe. CI includes these checks with five-second fuzz runs and the independent module explicitly listed. ## Behavioral evidence - [`ui/ui_test.go`](https://github.com/fauzaanu/cicadel/blob/main/ui/ui_test.go): typed composition, children/named slots, zero/default behavior, required values/slots, escaping, malicious URLs, forwarding rules, compatible/incompatible overrides, namespace conflicts, nil body rejection, nested failures, error attribution, recursion/output bounds, cancellation before/during rendering, precommit atomicity, committed write failure, concurrent success/failure, and separate request buffers. - [`uic/compiler_test.go`](https://github.com/fauzaanu/cicadel/blob/main/uic/compiler_test.go): malformed nesting/context, script/style/event rejection (including uppercase elements), deterministic output, source invalidation, missing/stale/orphan outputs, Go failures for missing/unknown/incompatible props/components/slots, mapped machine diagnostics, and a panic-in-init regression proving offline check does not execute Go code. - [`component_registry_test.go`](https://github.com/fauzaanu/cicadel/blob/main/component_registry_test.go): host integration, required embedded assets, missing resources and project-only override ownership. - [`TestExternalComponentLibrary`](https://github.com/fauzaanu/cicadel/blob/main/internal/scaffold/components_test.go): a fresh generated project installs a unique version through the Go proxy protocol, explicitly registers the independent library, resolves a typed project override, passes required props/children/footer, verifies HTML/security/concurrent requests and CSS, and builds the server/test executable. The compiled HTTP tests and the production `check` command run from an empty directory. `TEMPL_DEV_MODE=true` deliberately verifies that compiled literals do not fall back to upstream disk discovery. The library is installed with actual `go get`, not a consumer replace; only the framework points to the checkout. No public module publication is claimed. - Existing generated-project/package tests and real PostgreSQL articles/catalog HTTP tests passed under race detection. They retain authorization, ownership, validation, CSRF, session and persistence assertions after the UI conversion. - [`examples/component-library`](https://github.com/fauzaanu/cicadel/blob/main/examples/component-library): independent module with explicit exports, embedded source/CSS, required assets and normal app metadata. The source/host validation commands serve different purposes: source `ui check` does not execute app factories, while host construction/`manage.go check` validates actual registered components, assets, and dependency versions before serving. ## Performance measurements ```sh go test ./ui ./uic ./templates -run '^$' \ -bench 'Benchmark(Render|Compile|PrototypeCompile)$' -benchmem -count=3 ``` Three local samples after the final implementation, using Go's adaptive benchmark loop and no network/database. Both render benchmarks output `

Hello

`. The new render includes an instrumented compiled component and the buffered renderer; the legacy benchmark uses the existing immutable template engine. | Operation | Observed range | Allocation observation | | --- | --- | --- | | Component render | 477.7–514.1 ns/op | 4,655 B/op; 15 allocs/op | | Legacy template render | 322.6–330.6 ns/op | 352 B/op; 9 allocs/op | | Component source-to-Go compile | 175.7–187.5 µs/op | 83.4–83.5 kB/op; 1,736 allocs/op | | Legacy template parse/load | 1.74–2.06 µs/op | 4,728 B/op; 65 allocs/op | The new path costs more for this small render, notably its request-owned 4 KiB buffer and stack/context instrumentation. It deliberately avoids sharing a pool that retains request writers. Compilation is a build-time parser/generator/AST/ formatting pipeline; the old operation parses a runtime template, so those timings are not equivalent phases. Component compilation excludes the subsequent Go compiler/linker. No throughput, production capacity, Django comparison, universal speedup, or regression threshold is inferred from these microbenchmarks. Other work on the development machine and normal scheduling may affect results. See the [earlier performance methodology](https://cicadel.fauzaanu.com/en/dev/howto/performance/index.md) for existing baselines. ## Remaining boundaries This completes the documented initial TPL-01/02/04/05 server component scope. The APIs are experimental, and no independent security review is claimed. Broader forms/admin/package batteries stay open. Streaming, hydration, client reactivity, active script/style/foreign-content support, arbitrary trusted HTML strings, automatic development watching/hot replacement, and sandboxing package Go code are not implemented. Development uses explicit regeneration and server restart. Legacy `templates` remains available for compatibility and email callers. Type errors navigate to a source component declaration and retain their exact generated position; they are not claimed to have expression-perfect source maps. --- Source: `docs/contributing.md` Markdown: https://cicadel.fauzaanu.com/en/dev/internals/contributing/index.md # Contributing Cicadel is experimental. Start with a focused issue or change and describe the behavior you want to improve. ## Work locally Use the Go version declared in `go.mod` and PostgreSQL 18 for integration tests. Read the repository's `AGENTS.md` for project scope and contribution requirements. PostgreSQL is the only supported database. The [architecture guide](https://cicadel.fauzaanu.com/en/dev/internals/architecture/index.md) describes package boundaries. The [testing guide](https://cicadel.fauzaanu.com/en/dev/topics/testing/index.md) explains application fixtures and database-backed tests. ## Documentation Edit the Markdown guides in `docs/` or the relevant module README. The documentation website imports these files during its Hugo build, so fixes stay shared between GitHub and the published site. See the [website authoring instructions](https://cicadel.fauzaanu.com/en/dev/sources/website/README.md) for local builds, navigation and release snapshots. ## Verify changes Run the checks in all applicable `.github/workflows/` workflows before pushing. Include nested Go modules and real PostgreSQL integration tests. UI changes require the matching Cicadel CLI's `ui build` and `ui check --json`; commit authored and generated files together. Keep changes focused. Do not stage unrelated work in a shared checkout. Report validation results and known limitations with your change. ## Update the documentation site Edit source guides in `docs/`; write for developers building applications, with short explanations, working code and useful agent prompts. Put framework design and implementation history in the separate framework section. Follow [the website authoring guide](https://cicadel.fauzaanu.com/en/dev/sources/website/README.md) for navigation, LLM exports, version snapshots and local checks. GitHub Actions builds and validates all static assets on pull requests, then publishes the verified site automatically when changes reach `main`. Do not edit generated `website/public/` files or deploy from a personal machine as part of the normal authoring workflow. --- Source: `docs/foundation.md` Markdown: https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md # Application foundation The application foundation covers DEV-01, DEV-02, DEV-03, DEV-05, DEV-06 and DEV-07: project/app scaffolding, settings, registration and lifecycle, routing, management commands, checks and local rebuild/restart. Its public APIs remain experimental. The separate reusable-package battery (DEV-04), database inspection/shell tools (DEV-08), and independent release validation retain their own acceptance criteria in [the inventory](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md). ## Projects and upgrades `cicadel startproject DIRECTORY example.com/project` creates an ordinary Go module, `manage.go`, typed project settings, explicit `project/apps.go`, root routes, compiled components, embedded CSS and request tests. `startapp NAME [DIRECTORY]` creates model, view, route, migration and test files. Names and module paths are validated before writing. Existing destinations are never intentionally replaced. `startpackage` is the independently distributable-app scaffold. Keep models in `apps/notes/models.go`, split them into multiple files in that Go package, or move them to `apps/notes/models/` with `package models` and import that package explicitly. Do not keep duplicate model declarations in both layouts. There is no runtime discovery. Register owned models with `ModelOf` in the app's `Models()` list. `makemigrations` and `generatequeries` consume that same registry. Handwritten SQL also belongs to recorded history with reviewed historical metadata. Neither startup nor reload calls AutoMigrate or applies migrations. For upgrades, pin the intended framework version with `go get`, run `go mod tidy`, read release notes, and generate a reference project in a new directory. Compare it with your project and merge deliberate changes. Generation does not rewrite existing settings, models, components or migration history. Run the matching `go tool cicadel ui build`, `ui check --json` and project tests before deployment. See [the upgrade policy](https://cicadel.fauzaanu.com/en/dev/releases/releases/index.md) and [model migrations](https://cicadel.fauzaanu.com/en/dev/topics/migrations/index.md). ## Configuration and registration Settings precedence is defaults, typed project assignments, then explicit environment overrides. Every operational field has a documented override in [operations](https://cicadel.fauzaanu.com/en/dev/howto/operations/index.md). Invalid values fail without printing their contents. `settings.LoadWith` accepts an injected lookup for tests; it never changes the process environment. Loaded and constructed applications own their allowed-host slices. Settings formatting and structured logging redact DatabaseURL; directly logging that field or serializing arbitrary application secrets bypasses this protection. Package settings are ordinary typed constructor options, passed explicitly from `project/apps.go`. Validate them in the constructor or a registered check; do not introduce a shared untyped registry or mutate another app's settings. A new factory call must allocate fresh lifecycle state for each test or application. App descriptors are copied at construction. Registration rejects duplicate labels, missing dependencies, cycles, incompatible manifest versions and contribution collisions. Dependency ordering is stable. Startup runs checks before acquiring resources. Successful hooks and a failing hook's returned cleanup run in reverse order on failure. Successful startup is idempotent; closed applications cannot restart. Close follows HTTP drain and attempts every cleanup even when one fails. Hooks must honor context deadlines and must not recursively call Start or Close. Routes use typed `urls.Route` values and standard HTTP handlers. `urls.Include` applies namespaces and prefixes; reversal validates parameters. App middleware wraps only that app's routes, in declaration order. See [the application API](https://cicadel.fauzaanu.com/en/dev/ref/api/index.md) and [installable lifecycle contracts](https://cicadel.fauzaanu.com/en/dev/topics/installable-apps/index.md). ## Management commands `go run manage.go help` lists built-in, project and namespaced app commands in sorted order. `help COMMAND` or `COMMAND --help` shows its description without running checks, startup hooks or the command. Add descriptions through `App.CommandHelp` or `Manager.CommandHelp`; descriptions must reference registered commands. Project names are lowercase identifiers with optional hyphens and underscores; app commands remain `app:command`. Collisions are errors. Runtime commands execute after checks/startup and receive cleanup on success or failure. Explicit `App.BuildCommands` run without database validation or runtime hooks. Constructors and the generated project's Build function still run before Manager.Run; a project that opens a database during construction needs its configuration even for help. Offline tools should use a separate construction path when that distinction matters. Custom commands receive an unmodified argument slice and context. Use Go's `flag.NewFlagSet(name, flag.ContinueOnError)`, choose an explicit output writer, and return `management.UsageError{Err: err}` for invalid flags or arguments. Handle `flag.ErrHelp` as success. Return ordinary errors for execution failures. Do not call os.Exit inside commands, because it bypasses lifecycle cleanup. `management.ExitCode(err)` defines 0 for success/help, 2 for usage errors, 130 for context cancellation, and 1 for execution/configuration failure. Generated manage.go and the framework CLI use it. Existing entry points can adopt the same helper. The exit status of `go run` itself is Go's launcher status; build an executable to observe the application's exact status directly. ## Structured system and deployment checks Legacy `App.Checks` continue to return errors. New `App.SystemChecks` register `SystemCheck{Deployment: bool, Run: func(context.Context) []CheckMessage}`. Each message has a local ID, severity (`info`, `warning`, `error`), concise Message and optional Hint. IDs must be lowercase contribution identifiers and unique within one check invocation. The framework qualifies them as `app:check:id` and rejects invalid results. Diagnostics are ordered by app dependencies, sorted check names, and the check's returned message order. Keep messages and hints free of secrets. Ordinary startup fails on error diagnostics; warnings and information do not block startup. Deployment-only checks run only on explicit request. Checks must be read-only, must honor cancellation, and must not start background services. ``` go run manage.go check go run manage.go check --deploy --fail-level warning go run manage.go check --deploy --json ``` `--deploy` additionally checks debug mode, secure cookies and explicit allowed hosts, and runs package deployment checks. `--json` emits a diagnostic array, including on check failure. `--fail-level` selects the minimum failing severity; it defaults to error. Database provider requirements are included in management checks. These checks cannot certify a reverse proxy, external TLS, backups or production infrastructure; those remain deployment responsibilities. ## Development rebuild and restart Install the matching CLI and the pinned CSS compiler once, then run: ``` go tool cicadel ui css install CICADEL_DEBUG=true CICADEL_SECURE_COOKIES=false go tool cicadel dev ``` `dev --dir DIRECTORY --interval 300ms --shutdown-timeout 10s` watches a project containing go.mod and manage.go. It compiles components and configured CSS, builds an executable outside the project, and runs it with `runserver`. The same project configuration and environment apply to every generation. It does not install build tools implicitly. Applications using another CSS system retain their own build process when no ui.css.json is configured. Content hashes detect creation, deletion and same-size changes, including embedded assets. Two stable observations debounce edits. A source change during a successful build causes another build before that binary is served. A failed build reports compiler/source diagnostics and leaves the working server alive. Fixing the source triggers a new build. The old server receives an interrupt only after a replacement build succeeds; it is reaped before the replacement starts. Shutdown escalates to kill after the configured timeout. Interrupt and SIGTERM stop the supervisor and its child. A server that exits, including on a port conflict, returns an error with its output instead of repeatedly spawning failing processes. Hidden files/directories, bin, dist, vendor, node_modules and nested Go modules are excluded. The project root is resolved to its real path; symlinks within the source tree are rejected with a diagnostic. Put generated runtime logs and artifacts in an excluded output directory. Changes to another module or environment require restarting the supervisor. This is an executable restart workflow; it does not preserve process memory, inject browser refresh scripts or provide in-process hot replacement. Production remains `go build` and ordinary process supervision. ## Acceptance evidence - `settings`: every operational override, malformed-value secrecy, copied host configuration, redacted formatted/structured diagnostics and fuzz boundaries. - Root application tests: route composition, dependency ordering, descriptor isolation, partial-start cleanup, cancellation, readiness, HTTP shutdown and structured check validation/deployment selection. - `management`: command collisions, offline/runtime lifecycle, deterministic help, check flags, severity thresholds, usage status and cancellation status. - `internal/devserver`: real executable rebuild, continued HTTP service after a compiler failure, recovery after fixing source, content-hash boundaries and forced shutdown/reaping of an unresponsive child. - `internal/scaffold`: generated project/app tests and an outside-source-tree executable exercise help, JSON checks, deployment rejection and exact exit codes; existing generated-consumer tests verify component and package integration. The applicable repository workflows verify generated files, PostgreSQL integration, race checks, vet, fuzz targets, vulnerability scans and builds, including nested modules. External security review and beta adoption are not claimed by these tests. Local verification on 2026-11-02 used Go 1.26.10 and PostgreSQL 18.4. The required commands from `ci.yml`, `accounts.yml`, `formsets.yml` and `migration-installables.yml` passed, including strict PostgreSQL/race coverage, all eight configured fuzz runs, generated-source checks, nested-module vet and vulnerability scans. Release CLI builds passed for Linux and macOS on amd64 and arm64. The root suite was rerun after the final watcher fixes. These results cover local checks; they do not claim an external review or a published release. --- Source: `docs/internals/authentication-implementation.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/authentication-implementation.md # Browser authentication and the accounts starter Cicadel has one core accounts service and two explicit HTTP adapters. Browser applications use server-rendered HTML, server-side SCS sessions and CSRF checks. API clients can use the JSON bearer adapter. Both adapters consult the same PostgreSQL users, account sessions, recovery tokens, groups and permissions. Disabling an account, resetting its password or revoking its sessions affects both adapters. A browser never receives the account bearer token in HTML or JSON. ## Create the starter From the framework checkout: ```sh go build -o bin/cicadel ./cmd/cicadel ./bin/cicadel startproject /tmp/myapp example.com/myapp cd /tmp/myapp go mod edit -replace=github.com/fauzaanu/cicadel=/absolute/path/to/Cicadel go mod edit -replace=github.com/fauzaanu/cicadel/contrib/accounts=/absolute/path/to/Cicadel/contrib/accounts go mod edit -replace=github.com/fauzaanu/cicadel/contrib/formsets=/absolute/path/to/Cicadel/contrib/formsets go mod edit -replace=github.com/fauzaanu/cicadel/contrib/migrations=/absolute/path/to/Cicadel/contrib/migrations go mod edit -replace=github.com/fauzaanu/cicadel/contrib/querygen=/absolute/path/to/Cicadel/contrib/querygen go mod tidy export DATABASE_URL='postgres://USER:PASSWORD@localhost/myapp?sslmode=disable' export CICADEL_DEBUG=true export CICADEL_SECURE_COOKIES=false go run manage.go migrate CICADEL_USER_PASSWORD='a local account password' go run manage.go createuser owner@example.com go run manage.go runserver ``` Use an email address whose ownership you have verified before provisioning the account. This starter treats the stored username as that verified recovery address. Requests cannot supply a separate delivery address. There is no public registration endpoint or administrator panel. The service's `Create` API remains available for application-owned provisioning and invitation workflows. The framework and accounts module are private experimental sources without a published accounts release. Local replacements are needed for checkout development; pin actual published versions before distributing an application. No runtime module fetching or automatic registration occurs. `startproject` always includes accounts, formsets and the standard migration workflow; runtime commands require PostgreSQL. ## Screens and actions The default prefix is `/accounts`; `accounts.Pages.Prefix` can change it. | Route | GET | POST | | --- | --- | --- | | `/accounts` | Signed-in account and session actions | — | | `/accounts/login` | Login form | Rotate session and sign in | | `/accounts/recover` | Recovery form | Deliver a reset link to the verified destination | | `/accounts/reset` | Reset form with token | Consume the token once and replace the password | | `/accounts/change-password` | Current/new password form | Replace password and revoke all sessions | | `/accounts/logout` | — | Revoke current account session and destroy its cookie session | | `/accounts/revoke` | — | Revoke all account sessions and sign out | | `/accounts/style.css` | Embedded compiled stylesheet | — | The default components are in `contrib/accounts/accountui`. Typed props and slots, CSS, generated Go and the embedded stylesheet are delivered together. Layout uses dark surfaces, lime controls and a green lighting panel, with a narrow-screen layout, visible keyboard focus, explicit labels and error/status announcements. Applications can customize the component source or compose their own handlers using `accountui.Page`. This package has no JavaScript or CDN dependency. ## Integrate an existing application Construct `accounts.New(accounts.Options{DB: db, DeliverRecovery: deliver})`, then `service.Browser(security.NewSessions(store, secureCookies))`. Handle each error. `browser.HTMLApp(accounts.Pages{Brand: "My application", Logger: logger})` returns the installable app with its embedded resources, components, recorded migrations and protected routes. Register it once and run `migrate` before serving. `HTMLApp` owns LoadAndSave → CSRF → account-resolution middleware for its routes. Do not wrap those routes with those same middleware again. For another app's protected routes, apply `browser.Middleware` then `browser.RequireLogin`, and use `accounts.UserFromContext` inside handlers. `RequireLogin` checks a freshly resolved account, rather than only a stored SCS user ID. Object permissions still require explicit application policy and scoped database queries. The starter uses PostgreSQL `accounts_browser_sessions` through SCS's configurable table name. Migration 002 adds the table without rewriting the existing accounts history. A custom store may also be supplied. Sessions are HttpOnly, SameSite=Lax, secure by default, rotated on login and cleared at logout. Account expiry and revocation are checked on every browser request. SCS expiry can end a session before the associated account token expires; `accounts:cleanup` removes expired tokens. Browser forms are bounded to 8 KiB and all unsafe methods require CSRF. For API-only clients use `service.HTTPApp(prefix)` and `service.Middleware` with explicit `Authorization: Bearer …`. Register either adapter once under the `accounts` app name. If a host needs both, combine their routes into that one app and scope cookie middleware to the HTML routes; never apply cookie CSRF middleware to a bearer-only API by accident. ## Recovery delivery and deployment Configure these starter environment variables: | Variable | Purpose | | --- | --- | | `CICADEL_PUBLIC_URL` | HTTPS origin used to construct reset links | | `CICADEL_MAIL_FROM` | Sender mailbox | | `CICADEL_SMTP_ADDRESS` | SMTP `host:port` with STARTTLS | | `CICADEL_SMTP_USERNAME`, `CICADEL_SMTP_PASSWORD` | Optional SMTP credentials | | `CICADEL_LOG_FORMAT`, `CICADEL_LOG_LEVEL` | JSON/text format and log threshold | `project.DeliverRecovery` is the application-owned callback. It sends to the stored verified address, constructs a local reset route using the configured origin and passes the token only to the mail transport. Known and unknown users receive the same recovery response. Delivery errors are logged without tokens, addresses or server response text. Missing delivery configuration is handled without revealing whether a username exists. Passwords must contain 12–72 bytes; applications may add their own password policy. Use HTTPS and secure cookies, configure allowed hosts, apply gateway rate limits to login/recovery endpoints and schedule `manage.go accounts:cleanup`. Never log query strings on reset routes at the proxy. Reset pages send `no-referrer`, `no-store` and a restrictive content security policy. See [email](https://cicadel.fauzaanu.com/en/dev/topics/email/index.md), [logging](https://cicadel.fauzaanu.com/en/dev/topics/logging/index.md) and [operations](https://cicadel.fauzaanu.com/en/dev/howto/operations/index.md) for configuration details. ## Verification `contrib/accounts/pages_test.go` exercises the compiled pages and real PostgreSQL account store with a cookie-aware HTTP client. It covers CSRF rejection, session rotation, login/logout, recovery uniformity, single-use reset tokens, disabled users, escaping and embedded assets. `TestGeneratedAccountsStarter` creates a separate module, applies migrations, provisions an account, exercises login and password changes, builds/checks generated markup/CSS and builds the executable. The existing accounts service tests cover permission and concurrency behavior. --- Source: `docs/internals/cache-implementation.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/cache-implementation.md # Cache backend contract `cache.Backend` is the context-aware integration boundary for replaceable byte caches. A miss returns `(nil, false, nil)`; an outage returns an error. Callers must explicitly choose whether to fall back to their authoritative data source. Errors remain discoverable with `errors.Is`. Do not use cache contents for session revocation, authorization decisions or distributed locking. `NewMemoryBackend(capacity, maxValueBytes)` supplies a concurrent, bounded local implementation. It copies values, expires entries at the TTL boundary, and evicts the oldest written entry when full. The existing `Memory` and `Store` APIs remain compatible. Local instances do not coordinate across application processes. ```go backend, err := cache.NewMemoryBackend(1000, 64*1024) if err != nil { return err } registry, err := cache.NewRegistry(map[string]cache.Alias{ "articles": {Backend: backend, Namespace: "production:blog", Version: "v1"}, }) if err != nil { return err } articles, err := registry.Lookup("articles") if err != nil { return err } err = articles.Set(ctx, "public:42", []byte("cached payload"), time.Minute) ``` Construct a registry at startup and inject clients into applications. Alias maps are copied. Each alias includes its name, deployment/application namespace and version in a length-framed SHA-256 key. Raw keys are not sent to the backend; keys must contain 1–1024 bytes and TTLs must be positive. Hashing does not encrypt values. Explicitly include every tenant, locale, permission or representation variation in the logical key where applicable. `Delete` invalidates one logical key; deleting a missing key succeeds. Changing Version selects a fresh key space, leaving old entries to expire. All processes must adopt that version to agree on the active generation. In-flight readers or writers can race with deletion, so invalidation does not provide transactional consistency. There is deliberately no global flush operation. Backends must be concurrent, preserve byte ownership, implement positive TTLs, and report operational errors. Cancellation can race with a completed mutation; an error is not evidence of rollback. The built-in adapter checks cancellation before entering its short in-memory operation. Network adapters should pass the context through to their transport. Verified coverage includes namespace/alias/version isolation, mutation isolation, expiry boundaries, rejected writes preserving existing data, cancellation, operational error identity and concurrent client use under the race detector. Shared network providers, provider conformance, atomic operations and HTTP or fragment caching remain open; SVC-01 and SVC-02 are not marked complete. ## Coalescing expensive loads Create a reusable `cache.NewLoader(client)` and call `loader.Get(ctx, key, ttl, load)`, where `load` accepts a context and returns `([]byte, error)`. Hits bypass the function. Concurrent misses for the same key share the first caller's function and TTL; different keys proceed independently. The cache is rechecked before loading to close the miss/join race. Successful loads populate the cache; load and backend failures propagate and can be retried. Each result is copied independently. Caller cancellation stops only that caller's wait. The load retains the first caller's context values, but its lifetime ends when all waiters cancel or the operation finishes. Load functions must honor cancellation and must not recurse into the same loader/key. Use keys that include all authorization and tenant variations, and use one consistent load policy per loader. Coordination is local to a loader instance, not across processes. Deletion and concurrent writes still have the ordinary best-effort cache consistency semantics described above. ## Bounded load execution For request-serving applications, use `cache.NewBoundedLoader(client, 32, 5*time.Second)` to cap concurrent distinct loads and give each shared operation a deadline. Both limits must be positive. Hits remain available at capacity; callers joining an existing flight share its slot. New misses receive `cache.ErrLoaderBusy` immediately, discoverable through `errors.Is`; choose an application-specific retry or fallback policy. The deadline covers backend rechecking, loading and writing. Functions and backends must cooperate with cancellation. An abandoned operation retains its execution slot until it actually returns, preventing repeated canceled requests from creating unlimited replacement goroutines. A noncooperative function can therefore exhaust capacity; Go cannot forcibly terminate it. Existing `NewLoader` behavior remains compatible and unbounded. Neither constructor provides distributed admission control or transactional invalidation. Race-tested evidence: `TestBoundedLoaderAdmissionAndAbandonedExecution` verifies capacity rejection, abandoned-write prevention and slot reuse; `TestBoundedLoaderDeadline` verifies deadline propagation and limit validation. --- Source: `docs/internals/component-ui-implementation.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/component-ui-implementation.md # Composable component UI Cicadel renders components on the Go server. `.templ` markup is parsed and compiled with **templ v0.3.1100**, then compiled/type-checked by Go. Cicadel owns the public props/slots/library contracts, compiler policy and instrumentation, overrides, HTTP buffering, limits, diagnostics, and verification commands. There is no Node, React dependency, hydration, client reactivity, runtime source discovery, or Django template language. This implements the component-first direction inspired by React composition and Django Cotton. We chose a mature [typed markup compiler](https://templ.guide/) instead of inventing a parser or substituting strings around `html/template`. See templ's [syntax](https://templ.guide/syntax-and-usage/basic-syntax/) and [escaping rules](https://templ.guide/syntax-and-usage/attributes/); Cicadel's narrower supported contract below takes precedence. Generated files use the Cicadel CLI, not upstream `templ generate`, because Cicadel adds policy checks and render frames. For the shortest path to writing UI, start with the tested [React-style authoring walkthrough](https://cicadel.fauzaanu.com/en/dev/howto/component-authoring/index.md) and the [component authoring skill](https://cicadel.fauzaanu.com/en/dev/sources/skills/cicadel-components/SKILL.md). Tailwind CSS is now the [first-party default styling workflow](https://cicadel.fauzaanu.com/en/dev/howto/tailwind/index.md) for generated apps; other stylesheet systems remain supported. ## Authoring and public contracts Keep `props.go` and `card.templ` together in a Go package, commonly beneath an app's `templates/cards/` directory. Private bodies and reusable page composition may also live alongside the owning handlers, as in the articles example. Imports are ordinary Go module imports and aliases; no filesystem-based name resolution or global registry occurs. Exported contracts have `appname:component` names. ```go package cards import "github.com/fauzaanu/cicadel/ui" type Props struct { Title string Compact bool } type Slots struct { Children ui.Content Footer ui.Content } var Card = ui.Definition[Props, Slots]{ Name: "cards:card", Source: "templates/cards/card.templ", Validate: func(p Props, s Slots) error { if err := ui.Required("Title", p.Title); err != nil { return err } if s.Children.Empty() { return ui.Required("Children slot", "") } return nil }, Body: card, } ``` ```templ package cards templ card(p Props, s Slots) {

{ p.Title }

@s.Children if !s.Footer.Empty() {
@s.Footer
}
} ``` ```go content := cards.Card.Call( cards.Props{Title: "Welcome"}, cards.Slots{Children: ui.Text("Hello"), Footer: ui.Text("Thanks")}, ) err := (ui.Renderer{}).HTML(r.Context(), w, 200, content) if err != nil && !ui.Committed(err) { response.Error(w, 500) } // Log errors privately; do not send diagnostic details to public clients. ``` `ui.Content` is an opaque **HTML fragment**, never a string or attribute value. `ui.Text` escapes strings; `ui.Group` composes fragments; `ui.Fragment` adapts a trusted compiled component. `Content{}` is empty; `ui.Text("")` is a supplied empty text value, so `Empty()` reports presence rather than rendered text length. Use a named `Children` field for default child content, with other fields for named slots. `ui.NoSlots` declares no slots. There is one model: explicit fields, not templ's implicit `{ children... }` context transport (rejected by the compiler). Use `@someContent` or `@Definition.Call(props, slots)` in markup. Go checks field names, types, function arguments, imports, and slot compatibility. Omitted struct fields have Go zero values. `Validate` declares required values and slot presence; it runs before that component's body and before HTTP commitment. Required does not mean every zero value is invalid: the author specifies the semantic rule. `Defaults`, if provided, runs first on a local props copy. Use pointer/option fields when omitted and explicitly zero/false must differ; do not silently treat all zero values as missing. Both hooks must be pure and must not mutate referenced caller data. Override bodies retain the original default and validation hooks. Exported definition variables are configuration values: treat them as immutable; copy before customizing. Dependencies and request data are explicit typed props, function parameters, or factory arguments. There are no context processors or implicit request maps. A nested body sees only its Go lexical scope and declared inputs. Request `context.Context` carries cancellation and private render bookkeeping; business services should be explicit typed inputs. Ordinary Go `if`, `switch`, `for`, and helpers support variants and collections. All generated markup functions, including private bodies and recursive calls, receive render frames. ## Safety and rendering boundary - Text expressions and string attributes are escaped by templ across nested components. Fragment slots are HTML-body values. `title` and `textarea` permit only text expressions/text, not component insertion. Markup mismatched closing tags and unsupported context composition are compile errors. - Dynamic URL attributes use templ's contextual URL sanitization; unsafe values become `about:invalid#TemplFailedSanitizationURL`. Use `ui.URL` when the caller needs an error instead. It allows relative URLs and `http`, `https`, `mailto`, and `tel`; rejects control characters, backslashes, whitespace padding, protocol-relative URLs, and other schemes. This is not an origin allowlist. - `ui.Merge` is the forwarding boundary. Pass ordered `ui.Attributes` groups; names must be lowercase. Later values win, except classes merge unique tokens in first-seen order. Known boolean attributes require bools (false omits them). Text, `aria-*`, and `data-*` values require strings; use `"false"` for ARIA false. URL-like attributes also pass `ui.URL`. Output attribute order is deterministic. Merge before spreading and do not duplicate those keys as literal attributes. - Forwarding is allowlisted. Events, inline style, `srcdoc`, `srcset`, namespaces, arbitrary custom behavior attributes such as `hx-get`, and unknown standard attributes are rejected. Explicit attributes in trusted markup are a separate authoring decision; contextual URL escaping still applies. Applications may extend a typed component's declared API rather than blindly forward everything. - Inline script/CSS templates, script/style elements, event-handler attributes, dynamic attribute names, and active foreign/embedded content (`svg`, `math`, `iframe`, `object`, `embed`, and obsolete raw-text elements) are outside the initial source contract and rejected. Use explicit static stylesheet links. Client enhancement adapters and active content support are future capabilities, not implied by composition. - Cicadel supplies no string-to-trusted-HTML/URL/JS conversion. `ui.Fragment` is a narrow adapter for **trusted Go implementations**, which must preserve HTML safety. Do not call upstream `templ.Raw`, `SafeURL`, or write untrusted strings directly. Components/packages execute trusted Go code, not a sandbox; they can bypass any framework contract deliberately. Review them like other dependencies. `Renderer.Render` returns bytes only after success. `Renderer.HTML` renders first, then sets content type/status and writes. A render error leaves the HTTP writer untouched. A write failure after commitment is `*ui.CommitError`; `ui.Committed(err)` distinguishes it. Log that error, never try a second response. The caller must supply an uncommitted response writer. No streaming/flush API is supported through `Renderer`; direct low-level component `Render` calls do not provide HTTP atomicity. Go panics remain panics and are handled by the host's existing recovery middleware, not converted into validation failures. Defaults are **64 render frames** and **4 MiB output**; override with `Renderer{MaxDepth: ..., MaxBytes: ...}`. Frames include contract calls and markup bodies. Cancellation is checked at component boundaries and buffered writes. Arbitrary Go helpers must cooperate with context; the engine cannot preempt an infinite Go computation. The output bound excludes caller-owned props and intermediate Go expressions. No shared compile/render cache owns request values, children, context, or output. Generated literal writes ignore upstream development-mode environment variables and never consult source files. Generated code/literals are immutable; Cicadel uses request-owned buffers, deliberately bypassing templ's global buffer pool, which retains an underlying writer. Definitions/registries may be shared; the caller must not mutate props, slices, maps, or closures while a render uses them. ## Installable libraries and overrides `App.Components []ui.Export` explicitly registers `Definition.Export(version)`. The app owns the namespace, and duplicate names, invalid exports, or nil bodies fail construction. `Manifest` / `Requires` provide app API and dependency-version checks; Go modules select actual code. Component contract versions are positive integers, independent of module versions. Nothing is activated by importing a package or embedding source alone. `App.ComponentAssets` lists required files in `App.Resources`; construction checks they exist and are files. Serving is still an explicit route/static-host choice. Compiled Go embeds markup; `go:embed` packages static resources and may package sources for inspection. Runtime does not read `.templ` files or the working directory. The **local `project` app** may supply `ComponentOverrides`. No package or manifest app can override another package implicitly. One override wins over the original; duplicate overrides fail. It must retain the exact named Go props/slots types and contract version. The replacement supplies only the body/source: original default and validation behavior remains authoritative. This prevents silent required-prop or required-slot weakening. Semantic HTML behavior still requires application tests. Build a registry with `cicadel.ComponentRegistry(apps)`, resolve a definition with `ui.Resolve(registry, cards.Card)`, and pass that resolved value into page/route factories. `cicadel.New` also validates and exposes `Application.Components`. Calling an imported definition directly deliberately uses that definition; there is no hidden lookup that changes its meaning. This explicit injection makes project overrides reviewable and separate hosts independent. The [independent cards module](https://github.com/fauzaanu/cicadel/blob/main/examples/component-library) includes a compiled body, required child slot, optional footer, forwarded attributes, embedded source and CSS, app manifest, and HTTP tests. It has no mandatory design-system dependency. The [generated consumer test](https://github.com/fauzaanu/cicadel/blob/main/internal/scaffold/components_test.go) publishes a unique test version through a local Go proxy, performs real `go get`, installs it into a fresh starter, explicitly overrides it, checks escaping and concurrency, and runs compiled HTTP tests plus a production executable outside the source tree. This is verified module installation, not a claim that the example is publicly published. The local module's framework `replace` is development-only. ## Exact authoring and verification loop Generated projects pin the CLI through a Go `tool` directive. After `go mod tidy`: ```sh go doc example.com/your-library.Props # Edit the props/slots types and .templ body. go tool cicadel ui css install # once, when using Tailwind go tool cicadel ui build go tool cicadel ui check --json go test -run '^TestMyPage$' ./apps/myapp go test -race ./... go run manage.go check go build -trimpath -o bin/server . ``` In the framework checkout use `go run ./cmd/cicadel ui build` and `go run ./cmd/cicadel ui check`. For an existing project add the matching CLI with `go get -tool github.com/fauzaanu/cicadel/cmd/cicadel@VERSION`. The tool's compiler and runtime must be from the same framework dependency graph. `generate` parses all module sources before writing outputs. It writes deterministic `*_templ.go` files atomically per file, including a source hash and compiler version; commit them. `build` generates markup and builds configured Tailwind CSS; `generate` remains markup-only. `check` leaves generated files unchanged: it detects missing/stale/orphan outputs, checks configured CSS freshness, and compiles all Go packages/tests (`go test -c -o /dev/null ./...`, using the platform null device). It does not execute tests, start a web server, or evaluate arbitrary app factories. `manage.go check` constructs and validates the actual installed registry/resources; host-specific database setup still follows that host's existing construction rules. Production `cicadel.New` validates registered libraries, assets, and overrides before serving. Run both source and host validation in CI. A plain `go build` cannot detect that an ignored `.templ` source changed: stale checking is a required build step. Automatic compilation and executable restart are available through `go tool cicadel dev`; see [the foundation workflow](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md). In-process hot replacement is not supported. Manual build/check and restart of `go run manage.go runserver` remain supported. Failed generation leaves existing outputs intact for syntax failures, and a failed development build keeps the working server running. Concurrent generators in one checkout are unsupported. Nested Go modules need their own invocation; `.git`/hidden directories, `vendor`, and `testdata` are not compiled as application sources. Orphan generated files must be removed explicitly, never silently adopted. Commands exit 0 on success and 1 on failures, including invalid arguments. `--json` emits a JSON array of diagnostics to stdout (empty on success); a human error is also printed to stderr by the CLI. Fields: `code`, `message`, `file`, `line`, `column`, `stack`. Positions are one-based. Stable IDs include `UI_PARSE`, `UI_SYNTAX`, `UI_GENERATE`, `UI_TYPE`, `UI_STALE`, `UI_ORPHAN`, `UI_BUILD`, `UI_NAMESPACE`, `UI_COLLISION`, `UI_UNKNOWN`, `UI_CONTRACT`, `UI_ATTRIBUTE`, `UI_URL`, `UI_RENDER`, `UI_LIMIT`, the [Tailwind `UI_CSS_*` errors](https://cicadel.fauzaanu.com/en/dev/howto/tailwind/index.md), and `UI_WRITE` (committed transport failure). Runtime diagnostics implement `error`/`Unwrap` and can be JSON-encoded. Nested errors retain their deepest component stack. Source parse/render expression locations are precise; Go type errors map to the owning `.templ` declaration and preserve the exact generated Go position/message for detailed diagnosis. Plain Go errors retain their Go source position. Error messages may contain input values; keep them in development tooling/private logs. ## Forms, application integration, and migration `ui/layout.Page` provides an optional minimal document shell with explicit header, children, and footer, plus an optional explicit stylesheet URL. `ui/form.Field` renders associated labels, bound values, required/maxlength, password/text/textarea variants, and error-only `aria-invalid` and `aria-describedby` relationships. `ui/form.CSRF` requires an explicit token from session middleware. Components do not create tokens, validate requests, or bypass CSRF. Binding/validation stays in `forms` and the application. The starter, articles list/detail/login/edit, and catalog/admin pages use these compiled components. Existing authorization, ownership filtering, CSRF, and persistence paths remain; real PostgreSQL HTTP regression tests verify them. FORM-01 is still Partial: richer typed binding, validators, widgets and ModelForms are separate work. Administration's broader battery is also not completed here. Application UI uses compiled `.templ` components. Follow the [component authoring guide](https://cicadel.fauzaanu.com/en/dev/howto/component-authoring/index.md). Template strings, global definitions and `template.HTML` are not component content. ## Acceptance checklist Verified commands, benchmark observations, and evidence are recorded in [component verification](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md). These checks cover the bounded initial server component contract above, not upstream features we exclude. - [x] Specify syntax, layout, Go compiler/runtime API, props, explicit slots, and scope. - [x] Use a parser/compiler IR with deterministic artifacts and source diagnostics; reject unknown components, invalid nesting/context, and incompatible props/slots. - [x] Typed props, required validation, defaults, explicit dependencies, children, named slots, nesting, conditionals, collections, and reusable layouts. - [x] Safe forwarding/merging and contextual escaping, including malicious inputs. - [x] Accessible reusable form components and explicit CSRF integration. - [x] Package namespaces, collision checks, exact compatible overrides, required embedded assets, app dependency versions, and component contract versions. - [x] Deterministic development regeneration/restart workflow, nested render stacks, stale checks, and production registry validation without JavaScript tooling. - [x] Buffered HTTP failure behavior, committed write errors, concurrency, cancellation, recursion bounds, output limits, and request-owned buffers. - [x] Convert starter, articles, and catalog/admin to reusable components. - [x] Publish migration guidance and measure compiler/rendering against the legacy baseline. - [x] Install an independent library into a generated app with typed props, children, named slots, an explicit override, security/isolation tests, and production checks. ## htmx and REST Use the bundled [htmx 4 integration](https://cicadel.fauzaanu.com/en/dev/howto/htmx/index.md) for component HTML requests, or keep REST/JSON handlers for API clients. The standard page layout accepts a `Scripts` slot; pass `htmx.Script()` and mount `htmx.Handler()` to load the embedded runtime. No CDN, npm, or deployment-time asset collection is required. --- Source: `docs/internals/forms-delivery.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/forms-delivery.md # Forms: completed scope The forms delivery includes FORM-01 (standalone typed forms and widgets), FORM-02 (model forms), FORM-03 (formsets), revision-based stale-edit protection, FILE-01 (upload fields/lifecycle), and integration of model forms and inline formsets into administration. No additional feature is required to call this scope complete. General admin search/actions/audit product features remain ADMIN-02–04, not forms completion requirements. The framework remains experimental. ## Standalone forms ```go definition, err := forms.New([]forms.Field{ forms.Text(forms.Options{Name: "email", Label: "Email", Widget: "email", Required: true}, forms.Email), forms.Integer(forms.Options{Name: "age", Label: "Age", Required: true}, forms.Range[int64](18, 120)), forms.Boolean(forms.Options{Name: "accepted", Label: "Accept terms"}, forms.Accepted), forms.Multiple(forms.Options{Name: "topics", Label: "Topics", Choices: []forms.Choice{ {Value: "go", Label: "Go"}, {Value: "sql", Label: "SQL"}, }}), }) // Check configuration errors before serving requests. posted, err := forms.Parse(r) // Handle parse errors and apply request body limits. bound := definition.Bind(posted.Values) if bound.Valid() { age, ok := forms.Value[int64](bound, "age") // Use age after checking ok; values have already passed validators. } ``` `Initial()` supplies initial values without claiming the form was submitted or valid. `Bind` snapshots input and ignores undeclared names. Single-value fields reject repeated values. Multiple-choice fields reject duplicate or unavailable choices. Invalid UTF-8, numeric overflow, non-finite numbers, invalid dates and malformed timestamps are rejected. Strings preserve whitespace; Required checks trimmed emptiness. Optional numeric/boolean fields become zero/false; optional dates/timestamps become zero time. `Date` accepts YYYY-MM-DD; `Timestamp` requires an RFC3339 offset and returns UTC. There is no implicit locale conversion. Built-ins are `Text`, `Integer` (int64), `Number` (float64), `Boolean`, `Date`, `Timestamp`, `Select`, and `Multiple`. `Typed[T]` supports explicit custom parsers and `Validator[T]` functions. Built-in validators cover rune length, ordered ranges, email, HTTP(S) URLs, patterns and required acceptance. Exact decimals and application-specific identifiers should use explicit types/parsers rather than binary floating point. Parser error details are never exposed as display text. Pass cross-field checks to `New`; they run after every field converts successfully and return `forms.Errors`, using an empty key for form-wide messages. `Errors`, `Values` and `Fields` return independent snapshots; `Value[[]string]` also copies choice lists. Custom pointer/map values and callbacks remain application-owned; use immutable values and pure, concurrency-safe parsers/validators. Check `Valid` before acting on cleaned fields. Password/file values are excluded from `Fields` redisplay; raw `Values` intentionally retains the submission and must not be logged. The original `forms.Parse`/`Required` API remains compatible. ## Accessible components Render each `bound.Fields()` entry through `ui/form.Bound(field, uniqueID)` and `ui/form.Field.Call(props, ui.NoSlots{})` in an authored `.templ` component. The shared widget supports text/textarea, password, email, URL, number, select, multiselect, checkbox, radio, date, datetime-local, time, file and hidden controls. Use a custom parser for local datetime/time inputs; the timestamp field deliberately requires an explicit offset. Set `Multiple` for directly authored multiselect props; the bound adapter supplies it automatically. Labels target controls; radio groups use fieldsets/legends; help/error IDs are connected with `aria-describedby`, errors use `aria-invalid` and `role=alert`. Submitted choices and checkboxes preserve state. Text, labels, help, errors and option values are escaped. Password/file widgets never render a submitted value. Applications display form-wide errors from `Errors()[""]` in their page layout. ## Stale edits Add an application-owned `Revision int64` column through a recorded migration, initializing existing rows to 1. Set `model.Config[T].VersionField = "Revision"`; do not make Revision editable. New model-form records start at 1. Render `form.Version(ctx, &record)` as hidden `_version`. Updates compare it while holding the row lock and increment the revision in the same transaction. A missing or malformed revision is a validation error; an old revision returns `model.ErrConflict` and writes nothing. Hooks cannot modify the revision. Formsets use each row's `--_version` for updates and deletions and roll back the complete collection on a stale row. Admin renders revision fields and returns HTTP 409 for conflicts, preserving submitted input. Reload and explicitly reconcile edits; never silently retry using a fresh token. Every writer to versioned data must advance the same revision. Existing unversioned models keep their old behavior until explicitly opted in. Row/collection locking still protects transactional writes; revisions additionally protect against an old browser form. ## File fields and persistence `forms/upload.Parse(w, r, Config)` streams multipart bodies into private temporary files under a mandatory total limit and explicit per-field limits. It bounds text fields and part counts, rejects duplicate/unknown file fields, sanitizes display filenames, checks optional extension and sniffed media-type allowlists, and validates required/clear semantics. The client filename is never a storage key. Use `ValidateContent` for application-specific inspection (image decoding, document parsing or a scanning service) before storing. Content-type sniffing is not malware scanning. Serve untrusted files as attachments with appropriate content headers. Each `upload.Field` defines Name, MaxBytes, Required, AllowClear, MediaTypes, Extensions and a trusted ExistingKey loaded by the authorized handler. An empty file input preserves the existing file. `_clear=on` explicitly removes it; required files cannot be cleared, and replacement plus clear is rejected. File inputs cannot be prefilled after errors; users must select the file again. Always `defer batch.Close()`. `batch.Values` supplies ordinary fields for typed or model binding. `batch.Save(ctx, store, persist)` generates random storage keys, stores incoming files, and calls `persist(map[string]upload.Stored)` with keys and metadata. The callback owns and commits the database transaction (for example, sets the model's file-key field in BeforeSave and uses a revision-checked update). Return an error only when the database save did not commit. On failure, new objects are removed and old ones retained; after success, replaced/cleared old objects are removed. Objects still referenced by another unchanged field are preserved. Storage and PostgreSQL are separate systems: this is compensating cleanup, not a distributed transaction. `*upload.CleanupError` exposes retry keys and whether the database operation committed. Record and retry failed deletions; do not repeat a committed database save. For process crashes or an uncertain database commit, applications need durable outbox/reconciliation appropriate to their store. These operational realities are explicit, not a claim of cross-system atomic commit. Batch Save is one-use. Cleanup uses a bounded context independent of request cancellation. Temporary files are removed by Close or failed-parse cleanup. For browser multipart POSTs with session CSRF, use the middleware order: ```text authentication -> upload.Middleware(config) -> sessions.CSRF -> handler ``` Keep the session LoadAndSave wrapper outside that chain. The upload middleware parses once, makes text values available to CSRF, and closes the batch after the handler chain. Use `upload.FromRequest(r)` in the handler. Alternatively a direct Parse handler can sit behind CSRF when the client supplies `X-CSRF-Token`. ## Admin integration `admin.Config[T].Model` supplies model-form fields, validators/checks, hooks and VersionField. Display field order must match the explicit model field order when both are supplied. Otherwise fields are derived from the existing admin allowlist. `admin.Field.Widget`/Choices choose the shared widgets; listed choices are checked server-side. `Seed` supplies trusted defaults. Permissions are checked on the current locked record and the proposed model. Existing routes retain deny-by-default permissions, scoped lookup and the external authentication/CSRF middleware contract. The first-party `formsets.AdminInline[P,T](https://github.com/fauzaanu/cicadel/blob/main/docs/AdminConfig[P,T])` adapter goes in `admin.Config[P].Inlines`. Configure child Set, ForeignKey (Go field name), Label, Extra, ParentScope and optional field Widgets. Extra rows render ordinary controls; entirely empty new rows are ignored, and partially filled rows validate normally. The parent key is derived from the authorized parent model, never POST. Scope, identity, version, min/max, deletion and protected-field rules remain those of the formset API. Child errors redisplay beside their row controls. Parent creation/update and all inline saves share one outer transaction. Any child error rolls back the parent, its revision and every child mutation. The adapter uses only public admin/model-form integration contracts; core does not import the first-party module. Parent deletion follows authored foreign-key/cascade policies. No implicit related-record cascade is added by the framework. ## Acceptance evidence - `forms/typed_test.go`: typed conversion, validators, cross-field checks, multiplicity, immutable snapshots, password redaction, Unicode and fuzzing. - `ui/form/form_test.go`: escaped output, labels, groups, selected state and help/error relationships for the widget types. - `forms/model/version_test.go`: revision initialization/increment and stale or missing-token rejection against PostgreSQL. - `forms/upload/upload_test.go`: validation, storage replacement/removal, rollback compensation, explicit cleanup failures, multipart CSRF and temp cleanup. - `contrib/formsets/admin_test.go`: rendered inline editor, atomic parent/child saves, stale row/deletion protection, field errors and unauthorized identities. - `internal/scaffold/forms_complete_test.go`: a newly generated consumer combines typed forms, widgets, revisions and uploaded files with real PostgreSQL; failed stale/unique saves leave the record intact and no additional stored objects. All authored and generated component files are committed together. Root and module workflows check generation, race/integration tests, fuzzing, vet, vulnerability scans and builds. Browser/desktop automation is not used. Local verification on 2026-11-01 used Go 1.26.10 and PostgreSQL 18.4. All 35 applicable CI commands passed across the root, component-library, migrations, querygen, formsets and accounts modules, including the accounts generated host. The strict root integration report recorded zero skipped tests. Vulnerability checks passed with no reachable vulnerabilities reported. --- Source: `docs/internals/installable-app-design.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/installable-app-design.md # Installable applications Installable apps are Cicadel's first extension mechanism. A battery can begin as an independently versioned Go module, be exercised in real applications, and later become first-party maintained without acquiring a special registration path. First-party status does not automatically mean mandatory inclusion in every project. This first implementation supports app manifests, dependency/compatibility checks, explicit registration, commands, configuration checks, route-scoped middleware, resource filesystems, PostgreSQL SQL migrations, and startup/cleanup. It also supports typed component libraries; model-generated migration contracts are separately versioned work. ## Install and register an app Go modules own distribution and version selection. In your project, install a published module with an explicit version: ```sh go get example.com/your-org/greetings@v0.1.0 ``` This is an illustrative module path, not a package published by Cicadel. Add its factory to the generated `project/apps.go`: ```go package project import ( "os" "github.com/fauzaanu/cicadel" greetings "example.com/your-org/greetings" "gorm.io/gorm" ) func InstalledApps(db *gorm.DB) ([]cicadel.App, error) { return []cicadel.App{ greetings.New(greetings.Options{ Greeting: "Welcome", Output: os.Stdout, }), }, nil } ``` `db` is supplied by the generated host for apps that need it; factories can accept explicit typed options/dependencies. They must not mutate global settings or start services during import/construction. The host calls `cicadel.New` with the returned list. `go get` alone does not activate code, routes or migrations. ```sh go run manage.go apps go run manage.go check go run manage.go migrate # only when a database is configured/needed go run manage.go greetings:hello go run manage.go runserver ``` Each command is normally a separate process with a fresh host. Apps with runtime hooks are started and closed around custom commands. Do not share the same live Application between a web server and a lifecycle-owning management command. Legacy local apps without manifests or startup hooks retain repeatable in-process command behavior. The `apps` command prints manifest-declared versions, not a second dependency resolution result. Inspect the actual selected module graph with `go list -m all`; commit `go.mod` and `go.sum`. Use Go's documented `GOPRIVATE` and repository credentials for private modules. Local `replace` directives support development; review/remove machine-specific replacements before deployment. See the [Go module reference](https://go.dev/ref/mod). ## Create a separately distributable app From the Cicadel checkout: ```sh go run ./cmd/cicadel startpackage /tmp/greetings example.com/your-org/greetings greetings cd /tmp/greetings go mod edit -replace=github.com/fauzaanu/cicadel=/absolute/path/to/Cicadel go mod tidy go test ./... ``` The scaffold contains a module, typed options, manifest, named route, command, configuration check, lifecycle example, embedded resources and an `apptest.Check` test. Add `.templ` components using the [component contract](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md); embedding files alone does not register them. To consume it locally, run `go mod edit -replace=example.com/your-org/greetings=/tmp/greetings` in the host and then `go get example.com/your-org/greetings@v0.1.0`, followed by explicit registration. Publish/tag your own module before expecting remote installations to work. `startapp` remains available for project-local app directories. `startpackage` creates a new module for independent distribution. Existing projects can add `project/apps.go` manually and append its returned descriptors to their current `cicadel.New` call; regeneration is not required. ## Manifest and compatibility An app's stable `Name` is a lowercase identifier, at most 40 characters. It owns namespaces and migration history. Do not change it merely because a package moves repository or becomes first-party maintained. ```go Manifest: &cicadel.Manifest{ Module: "example.com/your-org/comments", Version: "v0.3.0", API: cicadel.AppAPIVersion, Requires: []cicadel.Requirement{ { Name: "accounts", Version: cicadel.VersionRange{Min: "v1.0.0", Before: "v2.0.0"}, }, }, Providers: []string{"postgres"}, }, ``` `AppAPIVersion` is currently 1 and versions the experimental app integration contract separately from Cicadel's release number. An app declares the API it targets. Dependency ranges have explicit inclusive `Min` and exclusive `Before` semantic versions; prereleases follow semantic-version ordering. This intentionally avoids a second range language/resolver. A required app must be explicitly installed and have a compatible manifest. Both `Manifest.Requires` and local `DependsOn` edges determine startup order; cycles and absent dependencies fail construction. An exported app release must keep its manifest accurate. Go module checksums verify downloaded code; declared metadata is not a security signature. `Manifest` may be omitted only for project-local/legacy apps, which then cannot satisfy a versioned dependency requirement. A nonempty `Providers` list means the app requires a database. Packaged migrations require that declaration. Management commands check every installed app's provider requirements before executing migrations or starting runtime work. Only PostgreSQL is currently integrated; metadata does not implement another provider. Library callers bypassing `management.Manager` must explicitly call `CheckDatabase` with the provider they supply before starting database-dependent apps. ## Contributions and ownership | Contribution | Contract | | --- | --- | | Routes | Standard `urls.Route`; manifest apps must use `appname:route` names. Conflicting routes fail construction. Factories choose/configure paths; no automatic prefix rewrite. | | Commands | `App.Commands` maps local command names to `cicadel.Command`; invoke as `appname:command`. Project commands cannot replace package commands or builtins. | | Settings | Typed factory options owned by the app. No ambient global settings mutation or shared string-key configuration registry. | | Checks | `App.Checks` maps local IDs to read-only configuration checks. Errors include `appname:check`; execution is sorted within dependency order. | | Middleware | `App.Middleware` wraps that app's routes only, first declared outermost. Host middleware wraps all routes and remains an explicit host decision. | | Components | `App.Components` exports typed definitions under the app namespace. `ComponentAssets` names required files within `Resources`; the local project alone supplies compatible overrides. See [components](https://cicadel.fauzaanu.com/en/dev/topics/component-ui/index.md). | | Resources | `App.Resources` is an app-owned `fs.FS`, accessible through `Application.Resources(appname)`. No automatic serving, implicit overrides or renderer assumptions. | | Migrations | `App.Migrations` is a Goose SQL filesystem. The app label owns its history table. Migration commands do not start runtime services. | | Lifecycle | `App.Start` receives context and returns `Cleanup`; dependencies start first and clean up last. | `InstalledApps()` returns descriptor copies. Configuration containers are copied at construction so mutating the source maps/slices cannot rewrite a running host's registry. Filesystems and function closures are shared references and remain the author's concurrency responsibility. Treat Application settings/router fields as immutable after construction. There is no runtime hot install/uninstall. Typed components register through `App.Components`; required assets use `App.ComponentAssets` with `Resources`. The local project owns explicit compatible `ComponentOverrides`. Resolve definitions through `ComponentRegistry` and inject them into pages. Model metadata and historical migration operations remain separately versioned contracts. New batteries should use this same public boundary instead of editing core to register themselves. ## Startup and cleanup `New` validates and builds the registry without running startup hooks. Apps with manifests, checks or hooks must be started before serving requests; otherwise they return 503. Call `Start` explicitly when mounting the application in your own HTTP server or `httptest` setup. `Run`/`Serve` handle startup and cleanup automatically, and drain active requests before releasing app resources. `Start` runs all configuration checks before acquiring resources, then starts apps in dependency order. A failing hook should return both its error and any cleanup needed for partially acquired resources. That cleanup runs first, followed by already-started dependencies in reverse order. Cleanup uses a fresh bounded context, not the cancelled startup/request context. Errors are joined rather than losing the original failure. Successful repeated `Start` and repeated `Close` calls do not repeat hooks. Closed instances and failed runtime startups cannot restart; create a new host with fresh factories. Validation failures before acquisition can be corrected and retried. Hooks and checks must honor cancellation, return errors rather than panic, and never recursively call `Start`/`Close`. Go cannot forcibly terminate an uncooperative hook; deadlines are cooperative. When integrating your own HTTP server, drain requests before `Close`. Middleware, handlers and commands must not retain resources beyond the owning host's lifetime. Factories must construct instance-local state, not package-global singletons. `apptest.Check` exercises two independent constructions and idempotent start/close; it is a smoke test, not certification of the package's complete behavior. ## Migrations and app composition Ship immutable, ordered SQL migrations within the module and embed them. Apply through the host's `migrate` command before runtime startup. Provider validation happens before any installed app's migration is applied. Migration/check/list commands do not start background workers or acquire app runtime resources. Configuration checks must not assume that migration-created tables already exist. Runtime manifests do not select module versions automatically. Management commands use `contrib/migrations` for version dependencies, checksums, model-driven generation and recovery. Disable an app by removing its registration. Remove its dependency/imports and run `go mod tidy` when no longer needed. Neither operation drops tables, reverses migrations or deletes stored data. Data cleanup is an explicit project operation. Renaming an app creates a different migration-history identity and requires a deliberate migration plan. Maturing a package into a first-party `contrib` offering changes maintenance/support responsibility, not these contracts. Keep stable app identity, migration history, public configuration and namespace behavior; provide a migration guide if module paths change. First-party modules are core defaults. Module boundaries describe composition and distribution; they do not create opt-in alternatives. Django's [reusable-app model](https://docs.djangoproject.com/en/6.1/intro/reusable-apps/) is a useful precedent for self-contained distribution, not evidence that every third-party app is eventually merged into Django. ## Verification and remaining scope The repository's external-package test generates a separate package module and a separate consumer project. A temporary file-backed Go module proxy supplies two published test versions. The consumer runs actual `go get`, version selection, compilation, package tests and HTTP tests; only the framework checkout uses a local replacement. With `CICADEL_TEST_DATABASE_URL`, the same test applies initial/upgrade migrations in PostgreSQL, preserves a data row and verifies removal leaves its data/history usable. Other tests cover incompatible/missing dependencies, cycles, route/command ownership, registry snapshots, check failures, exactly-once startup, partial failure rollback, cleanup errors, request draining and socket-binding failure. The fixture proxy exists only for tests, not as a new Cicadel package registry. The complete DEV-04 battery stays Partial: external localization demonstrations, model metadata, a comprehensive provider conformance harness and extraction of the existing first-party modules remain open. Installed packages are trusted Go code running with the application's privileges; they are not sandboxed. Pin/review dependencies and use the project's security/release process when changing them. ### Offline build commands `App.BuildCommands` contributes namespaced developer tools that must run without runtime startup, database-provider validation or global runtime checks. A name cannot appear in both `Commands` and `BuildCommands`. Each build command validates its own inputs and must not mutate the database. This is an execution contract, not a sandbox against malicious plugin code. The host must use `Application.IsBuildCommand(name)` **before** connecting to a database or starting resources. The manager cannot undo work a host constructor already performed. See [the migrations installable](https://cicadel.fauzaanu.com/en/dev/ref/migrations/index.md) and its executable example for offline generation followed by explicit migration application. Normal `Commands` retain runtime validation and startup/shutdown. The repository's [installable-development skill](https://cicadel.fauzaanu.com/en/dev/sources/skills/cicadel-installables/SKILL.md) provides a detailed authoring, compatibility, testing and release workflow. ### Recorded model migrations The first-party [migration installable](https://cicadel.fauzaanu.com/en/dev/ref/migrations/index.md) provides build-time model discovery, immutable PostgreSQL history and a checksum-aware runner. Follow [the project workflow](https://cicadel.fauzaanu.com/en/dev/topics/migrations/index.md) to register commands as Go tools and generate an offline entrypoint. Package runtimes can load embedded histories through `Definition.Source`; generate changes in the package checkout. Use the standard management commands for generation, execution and verification. Verify module installation in a generated project without local replacements. Cicadel has no published releases. ### Explicit runtime model catalog Packages may contribute `App.Models` with `cicadel.ModelOf[Book]("book", "library_books")`. The generic argument must be a named struct, not a pointer. `ModelRegistry(apps)` validates these contributions offline; `Application.Models()` returns the installed catalog in dependency order. Each entry carries its owning app, local name, explicit table and immutable `reflect.Type`. Consumers can use `reflect.New(entry.Type).Interface()` when they need a fresh GORM model value. Names are app scoped. Tables and Go types have exactly one owner across the application; aliases and competing registrations fail construction. Tables are explicit lowercase, unqualified PostgreSQL identifiers (at most 63 bytes). Configure GORM model table names consistently with these declarations: this catalog does not invoke `TableName`, inspect GORM tags or infer naming strategies. Returned slices and input descriptors cannot mutate the installed catalog. Registration never opens a database, starts services, creates tables or runs AutoMigrate. Recorded SQL migrations remain authoritative. This runtime catalog is not a historical migration snapshot, and does not automatically feed the separately versioned migration generator. Models without catalog declarations remain usable directly through GORM. Tests in `models_test.go` cover ownership, invalid declarations, dependency order and descriptor isolation. --- Source: `docs/internals/model-forms-implementation.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/model-forms-implementation.md # Model forms `forms/model` implements the FORM-02 model binding and persistence contract for PostgreSQL and GORM. It is experimental, like the framework's other public APIs. It does not create tables or change migrations. Declare constraints in recorded migrations before using a form. ## Definition and binding ```go import ( "github.com/fauzaanu/cicadel/forms" modelform "github.com/fauzaanu/cicadel/forms/model" "gorm.io/gorm" ) // Define once with an ordinary, unscoped PostgreSQL *gorm.DB. articleForm, err := modelform.New[Article](db, modelform.Config[Article]{ Fields: []modelform.Field{ {Name: "Title", Required: true, MaxRunes: 200}, {Name: "Published"}, {Name: "CategoryID", Required: true, Check: modelform.Related[Category]("category_id", func(tx *gorm.DB) *gorm.DB { return tx.Where("tenant_id = ?", tenantID) })}, }, }) // Handle err during application setup (or request setup for tenant-specific forms). // In a handler, after authentication, body limiting and CSRF middleware: posted, err := forms.Parse(r) // Handle parse failure before accessing posted. bound := articleForm.Bind(posted.Values) if errors := bound.Errors(); len(errors) != 0 { // Redisplay fields with these errors and bound.Values(). return } // New records receive trusted server values separately from submitted input. created, err := bound.Create(r.Context(), Article{TenantID: tenantID, OwnerID: userID}) // Editing loads and locks the authorized record. ID is parsed from the route. updated, err := bound.Update(r.Context(), articleID, func(tx *gorm.DB) *gorm.DB { return tx.Where("tenant_id = ? AND owner_id = ?", tenantID, userID) }) ``` The create and update calls above are alternative handler paths. Check every returned error. Use `errors.As(err, &validation)` with `var validation modelform.Errors` for safe display messages. The empty key is a form-wide error; `gorm.ErrRecordNotFound` means the target is missing or outside the authorized scope. Other errors belong in server-side handling, not response bodies. A save returns a model only on success. Database work follows the request context. `Name` is the Go model field name. `Input` defaults to GORM's database column name, respecting column tags and the configured naming strategy. There is no implicit “all model fields” mode. Unknown submitted keys are ignored, allowing CSRF fields and submit buttons without permitting mass assignment. Duplicate values for an editable field are rejected rather than choosing one arbitrarily. The binder copies submitted input, and `Values()` returns a copy. Definitions can be shared; parser/check/hook closures must themselves be concurrency-safe. Tenant-specific closures must not be shared across tenants. ## Supported conversion - Strings preserve whitespace and Unicode. Required tests trimmed emptiness; maximum length counts Unicode code points. Invalid UTF-8 is rejected. - Signed and unsigned integers, including named types, use decimal conversion with the destination type's overflow limits. Negative unsigned input fails. - Floating point values reject NaN, infinity and overflow. Use a custom parser and a decimal model type for exact money; floats do not provide decimal precision. - Booleans accept `true`, `1`, `on`, `false`, `0` and empty. A missing checkbox is false. Required means a nonempty submission, not “must be true”; use a check for consent requirements. - `time.Time` accepts RFC3339 timestamps with explicit offsets and normalizes to UTC. Locale-specific dates and naive timestamps are not inferred. - A single pointer to a supported type maps empty input to nil. Empty nonpointer numeric/bool fields map to zero; empty nonpointer timestamps are invalid. - `Field.Parse` supports custom column types and normalization. Return exactly the field's Go type, including its pointer or named type. Parser failures are displayed as a generic conversion error; parser internals never become UI copy. Binding is a full form submission, not PATCH: missing editable fields become zero/nil or fail Required. Binding errors prevent any transaction or hook from running. `Errors()` checks conversion only; database checks run at save time. Parsing may run more than once, so parsers must be pure. Primary keys, associations, read-only columns and automatic timestamps cannot be input fields. Models require a single primary key. Unsupported column types require an explicit parser. No automatic widget generation or schema-derived validation policy is claimed: define Required/MaxRunes and business checks explicitly. ## Relationships, constraints and hooks `Related[R](inputName, scope)` is a `Field.Check` for a scalar foreign key or nullable scalar key. Its required scope expresses the caller's permitted choices. It takes a PostgreSQL share lock on the matching related record for the duration of the transaction, preventing deletion or changes while the form is saved. An unavailable or unauthorized choice produces the same field error. A nullable key accepts empty input unless Required is set. Foreign-key constraints remain necessary even when using this helper. Custom field checks receive `(context.Context, *gorm.DB, any)`; custom cross-field validation belongs in `BeforeSave(context.Context, *gorm.DB, *T)`. Return `modelform.Errors` for safe messages, or an operational error to abort. Checks run in definition order and stop at the first error. BeforeSave can set trusted server-owned fields but cannot change the primary key. AfterSave can write audit records or explicit join-table changes using the same transaction. Both framework hooks and normal GORM model hooks participate in rollback. Automatic association saving is disabled. Inline editing and formsets are now available in the first-party [FORM-03 module](https://cicadel.fauzaanu.com/en/dev/ref/formsets/index.md). Automatic relationship inference remains excluded. Explicit join changes can be made in AfterSave; authorization and validation for those changes belong to that hook. No relationship policy is inferred from GORM tags. PostgreSQL constraints are the final authority for uniqueness, including simultaneous submissions. Duplicate keys become a safe form-wide error; foreign key, check and not-null violations have generic messages. This deliberately avoids leaking constraint names or values and supports composite uniqueness without a misleading preflight query. Custom friendly field messages can be implemented in checks, but must not replace database constraints. ## Transaction and authorization contract Updates use `SELECT ... FOR UPDATE` on the scoped target and reload its current state before binding. Concurrent saves serialize on the target row; server-owned fields cannot be overwritten by a stale caller copy. All mutable scalar columns on the freshly loaded model are persisted, including trusted hook changes and zero values. Updates never fall back to inserts. GORM's normal soft-delete and field-permission behavior applies. Create uses GORM's normal model/database default semantics; custom primary-key assignment can use a trusted GORM create hook. The supplied create seed itself must have a zero primary key. Use a plain database handle, not an existing transaction, when defining a form. Scope functions are trusted query filters; keep them on the supplied transaction and model, without changing table, selection, connection or context. In hooks, use only the supplied transaction for dependent writes. A failure in binding, validation, persistence, hooks or commit returns no saved model. Do not perform external side effects in hooks: database rollback cannot undo sent mail. Publish external effects after success or use a transactional outbox. Hook code must also avoid mutating caller-owned reference values in create seeds. Authorization, CSRF, request size limits, rendering, retries and idempotency remain explicit application concerns. A Bound is not a one-use token: repeated Create calls represent separate attempts. PostgreSQL deadlocks, serialization failures, connection failures and cancellation remain operational errors for the caller. Use a consistent relationship-check order across forms to reduce lock conflicts. ## Acceptance evidence [Tests](https://github.com/fauzaanu/cicadel/blob/main/forms/model/model_test.go) cover definition errors, immutable input, parameter pollution, Unicode, overflow, nullable fields, custom parsers, mass-assignment rejection, authorized create/update, missing rows, zero-value persistence, scoped foreign keys, related-row locks, concurrent unique creation, concurrent updates, hook identity protection, create/update/audit rollback, invalid-input short circuiting and cancellation. The [generated consumer test](https://github.com/fauzaanu/cicadel/blob/main/internal/scaffold/model_forms_test.go) creates a fresh project and exercises the public API through HTTP form submission, including query/body isolation, duplicate input, uniqueness and protected owner fields. The binding fuzz target checks arbitrary strings and deterministic conversion. Integration tests use explicit SQL in a dedicated test database, never AutoMigrate. ```sh CICADEL_TEST_DATABASE_URL='postgres:///cicadel_forms_test?host=/tmp&sslmode=disable' \ go test -race ./forms/... go test ./forms/model -run '^$' -fuzz FuzzBinding -fuzztime 5s ``` Verified locally with Go 1.26.10 and PostgreSQL 18.4: the full root-module `go test -race ./...`, `go vet ./...` and `go build ./...` passed. The final model-form race suite passed with 88.5% statement coverage; the generated-consumer race test passed separately after it was added. A five-second fuzz run passed 126,641 executions. This completes the bounded FORM-02 contract above. FORM-01's standalone widgets and validators are now complete; [FORM-03 formsets](https://cicadel.fauzaanu.com/en/dev/ref/formsets/index.md) now use this contract. For explicit multi-form transactions, `Form.InTransaction(tx)` returns a definition using an existing PostgreSQL transaction. Its save results remain provisional until the outer transaction commits. The caller must use the same database and naming configuration and owns the outer commit/rollback. Set `Config.VersionField` to an application-owned int64 revision column to reject stale edits. Render `Form.Version` as `_version`; conflicts return `ErrConflict` and no writes. See [complete forms](https://cicadel.fauzaanu.com/en/dev/topics/forms-completion/index.md) for adoption and admin integration. --- Source: `docs/internals/operations-implementation.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/operations-implementation.md # Operations, security, and compatibility Cicadel is an experimental implementation. Passing its tests is not a claim of independent security review or production adoption. ## Configuration and deployment Settings precedence is typed defaults, project assignments, then environment overrides. Supported environment keys: `DATABASE_URL`, `CICADEL_ADDRESS`, `CICADEL_DEBUG`, `CICADEL_ALLOWED_HOSTS` (comma-separated exact hosts without ports), and `CICADEL_SECURE_COOKIES`. Request and pool limits also accept `CICADEL_MAX_BODY_BYTES`, `CICADEL_MAX_OPEN_CONNS`, and `CICADEL_MAX_IDLE_CONNS` as decimal integers. `CICADEL_READ_TIMEOUT`, `CICADEL_WRITE_TIMEOUT`, `CICADEL_IDLE_TIMEOUT`, `CICADEL_SHUTDOWN_TIMEOUT`, and `CICADEL_CONN_MAX_LIFETIME` accept Go durations such as `15s` or `30m`. Invalid values fail validation without printing their contents. `settings.LoadWith` supports isolated test overrides and copies the allowed-host slice. Production requires debug off, allowed hosts, and secure cookies. Debug does not expose exception details to clients. Default HTTP limits: 1 MiB body, 15-second header/read timeout, 30-second write timeout, 60-second idle timeout, 10-second shutdown deadline. Database pool: 10 open, 5 idle, 30-minute connection lifetime. Tune these explicitly for workload and database capacity. Handlers must honor request cancellation; the shutdown deadline closes remaining HTTP connections. The application owner closes its database after serving stops. Build `go build -trimpath -o bin/articles ./examples/articles`. Templates and migrations are embedded. Run migrations as a separate deployment step, then run `bin/articles runserver`. The example Dockerfile builds a non-root executable image. Set its configuration through your deployment's secret management, and terminate TLS at a reverse proxy. The framework does not trust `Forwarded` or `X-Forwarded-*`. Keep the original allowed Host and configure the proxy's own header sanitization. Enable HSTS at the HTTPS edge after verifying the domain's HTTPS behavior. The articles example uses its `sessions` table; the accounts starter uses the package-owned `accounts_browser_sessions` table from migration 002. Sessions are shared across instances, rotate at login, expire after 12 hours or 30 minutes idle, and are invalidated at logout. The accounts browser bridge checks revocation and account availability on each request. Custom user stores must implement their own revocation policy; a session ID alone is not an object permission policy. Run `manage.go check --deploy --json` for structured deployment diagnostics. See [the foundation guide](https://cicadel.fauzaanu.com/en/dev/internals/foundation/index.md) for custom checks, command flags/statuses and the development rebuild/restart workflow. ## Migration safety Each app retains its version history table, with checksums in the shared migration ledger. Recorded version dependencies determine ordering; the canonical runner uses a shared PostgreSQL advisory lock. Use a direct/session-pooled database connection for migration commands, not transaction-mode PgBouncer. A failed transactional migration rolls back its schema/data changes and does not become applied. Nontransactional migrations can leave partial changes: inspect them and write an explicit repair; never blindly rerun destructive statements. Take and test database backups before destructive migrations. Prefer expand/backfill/contract changes compatible with the old and new app versions. Goose down migrations may be destructive. Management commands use the checksum-aware runner and provide explicit target rollback with reviewed history and data-loss acknowledgement. Restore a tested backup or apply a reviewed forward repair when necessary. Migration history is not a backup. The shared migration lock serializes execution; separate migrations do not make an entire deployment atomic. ## Application security responsibilities Use parameterized GORM values. SQL fragments, ordering, table names, and raw queries are not made safe by passing arbitrary user strings into them. Select columns explicitly for JSON responses; never serialize password hashes or entire user models. Apply middleware in this order: session LoadAndSave, CSRF, application authorization. Session-based unsafe requests require `csrf_token` form fields or `X-CSRF-Token` headers, including JSON writes. Session pages are `Cache-Control: no-store`. Authentication rotates the session and CSRF token. Secure cookies require HTTPS except in explicit local development. Add gateway/application rate limits to login and other expensive endpoints before exposing them publicly. Every object mutation requires a current permission check; the articles example restricts changes by author ID both before rendering and in the SQL update condition. The low-level `security.RequireLogin` only checks session presence. Accounts-backed routes use `browser.RequireLogin` with `browser.Middleware`, which resolves current account availability and revocation. The package supplies reset/change and revocation; verified recovery destinations, invitation policy and MFA integration remain application choices. The body limit also applies to forms. Multipart handlers must explicitly parse bounded input, remove temporary files, validate content, and use the storage API rather than user-supplied paths. HTML templates escape ordinary strings. Trusted template types bypass escaping and belong only around developer-controlled content. Redirect helpers accept local absolute paths only. ## Verification and supported versions The initial test target is Go 1.26.10+ and PostgreSQL 18. CI starts a disposable PostgreSQL service and runs database tests, race checks, vet, generated-project verification, targeted fuzzing, vulnerability checks, and build checks. Other database backends are excluded from the framework scope. No stable API guarantee is made before 1.0. Run locally against a dedicated disposable database: ```sh CICADEL_TEST_DATABASE_URL='postgres://USER:PASSWORD@localhost/cicadel_test?sslmode=disable' go test -race ./... go vet ./... go test ./urls -run '^$' -fuzz FuzzReverse -fuzztime 5s go test ./urls ./templates -run '^$' -bench . -benchmem go run golang.org/x/vuln/cmd/govulncheck@latest ./... ``` Integration tests drop their own test tables. Never point `CICADEL_TEST_DATABASE_URL` at a database with valuable data. Without this variable, database tests explicitly skip; that is not a full integration pass. ## Structured logging configuration `observability.NewLogger(observability.Logging{Output: os.Stderr, Format: "json"})` constructs a standard `slog.Logger`. Choose `text` for local development, pass a `slog.LevelVar` for runtime level changes, and use `AddSource` for caller locations. Credential attributes are redacted by key before optional `ReplaceAttr` processing. Use `observability.Logger(ctx, logger)` for request correlation and pass the same logger to request middleware. Free-form messages and errors must never contain credentials; key redaction cannot sanitize arbitrary message text. ## SMTP delivery `mail.Sender{Transport: mail.SMTP{Address: "smtp.example.com:587"}}` provides SMTP delivery with mandatory STARTTLS, certificate verification, context cancellation and a default 30-second deadline. Supply credentials through secret configuration. Plain text and HTML bodies are encoded as MIME alternatives when both are present. Delivery errors propagate to the caller; retries must account for uncertain delivery after an SMTP connection failure. The application owns verified recovery destinations. SMTP is not invoked by constructing a sender. The full supported configuration and output lifecycle are documented in [logging](https://cicadel.fauzaanu.com/en/dev/topics/logging/index.md), [email](https://cicadel.fauzaanu.com/en/dev/topics/email/index.md) and [authentication](https://cicadel.fauzaanu.com/en/dev/topics/authentication/index.md). Use those guides for named handlers, error alerts, attachment/envelope behavior, batch counts and generated-starter configuration. --- Source: `docs/internals/performance-baseline.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/performance-baseline.md # Performance baseline Results are in [benchmarks.json](https://github.com/fauzaanu/cicadel/blob/main/docs/benchmarks.json) and [microbenchmarks.txt](https://github.com/fauzaanu/cicadel/blob/main/docs/microbenchmarks.txt), and [ORM allocation benchmarks](https://github.com/fauzaanu/cicadel/blob/main/docs/orm-benchmarks.txt). Reproduce with: ```sh CICADEL_TEST_DATABASE_URL='postgres://USER:PASSWORD@localhost/cicadel_test?sslmode=disable' go run ./benchmarks -n 2000 -c 16 go test ./urls ./templates -run '^$' -bench . -benchmem CICADEL_TEST_DATABASE_URL='postgres://USER:PASSWORD@localhost/cicadel_test?sslmode=disable' go test ./benchmarks -run '^$' -bench BenchmarkORM -benchmem ``` The test ran on an Apple M4, macOS arm64, 10 logical CPUs, Go 1.26.10, and local PostgreSQL 18.4. The recorded PostgreSQL build string and runtime metadata are in the JSON. Each HTTP workload used 2,000 requests, 16 concurrent clients, keepalive, a loopback HTTP server, and no TLS. Client, server and database shared the machine. Database pooling used 10 open / 5 idle connections. The read workload selected 20 rows from 100 seeded records and rendered escaped HTML. The write workload performed one insert transaction per request. Its GET-based mutation handler is benchmark-only and must never be deployed as an application endpoint. Each run reports throughput, p50/p95/p99 latency and errors. The recorded runs had zero errors. The direct-dispatch microbenchmark measured roughly 124 ns/op for named routing versus 120 ns/op for the standard mux, both with 224 B/op and 5 allocations/op, including the test recorder. A simple escaped template rendered at about 323 ns/op, 352 B/op and 9 allocations/op. These are single-run observations, not regression thresholds. The HTTP baseline ordering is noisy: additional middleware appeared faster in this short run due to startup/warm-cache/scheduling effects. Do not infer that middleware improves performance. Use longer repeated runs, randomized workload order, separate load generators, stable database datasets, and statistical comparison before making capacity or speedup claims. Sessions, authenticated writes, TLS, tracing exporters, network delay, and a Django comparison are not part of this baseline. A Django comparison is deferred until equivalent application and deployment configurations can be maintained fairly. The measurements support keeping the standard mux and a thin naming layer. The database and template path deserves application-specific profiling before optimizing routing. No universal acceptable overhead target is set from this development-machine sample. ## Compiled component measurements The component implementation has a separate [verification and performance record](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-verification.md#performance-measurements) with raw three-run output. It compares the same minimal rendered HTML against the existing template benchmark and records source-to-Go compilation separately from runtime template parsing. Request-owned buffers and diagnostic frames add measured cost; no speedup or production throughput claim is made. --- Source: `docs/internals/release-policy.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/release-policy.md # Development policy Cicadel is in active development. No framework or first-party module release has been published. Documentation describes the current implementation. Unreleased APIs and designs can change directly: remove superseded approaches rather than maintaining compatibility shims, deprecation periods or upgrade guides. First-party capabilities are core defaults composed through installable modules. Each capability has one implementation and one standard workflow, integrated into project scaffolding, commands and documentation. Module boundaries describe composition and distribution. The supported development environment is Go 1.26.10+ in the 1.26 series and PostgreSQL 18. GORM handles runtime queries; recorded migrations handle schema changes. Application UI uses typed `.templ` components and Tailwind CSS. Run the applicable local CI checks before pushing. Verify independent module installation and generated applications as well as the workspace. Publish no release or support guarantee until the project explicitly establishes one. The manually dispatched release workflow is tooling for future publication. Its presence does not establish a release, a supported historical version or an upgrade policy. Current scope is tracked in [batteries.md](https://cicadel.fauzaanu.com/en/dev/sources/batteries.md). --- Source: `docs/internals/tailwind-implementation.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/docs/internals/tailwind-implementation.md # First-party Tailwind CSS **Tailwind CSS is Cicadel's default styling workflow.** Generated projects include Tailwind v4 input, a styled component page, compiled CSS, and an embedded static route. The framework owns installation, version pinning, source discovery, build and freshness checks. The server has no Tailwind/Node process or CDN dependency. Other CSS systems remain supported: see the opt-out instructions below. The current toolchain pins Tailwind **v4.3.3**. Cicadel uses the upstream [standalone CLI](https://tailwindcss.com/docs/installation/tailwind-cli), not npm, PostCSS, a custom CSS compiler, or a browser-time Tailwind script. ## Default authoring loop From a generated application, after `go mod tidy`: ```sh # Once per development/CI machine; explicit network download. go tool cicadel ui css install # After editing .templ, Go class variants, or CSS input. go tool cicadel ui build go tool cicadel ui check --json go test -race ./... go build -trimpath -o bin/server . ``` In the framework checkout substitute `go run ./cmd/cicadel` for `go tool cicadel`. The starter includes genuine compiler-generated CSS, so its initial server works without downloading any CSS tool. Tests that compile CSS (including the framework's scaffold/docs tests) need the explicitly installed compiler. CI installs it first. | Command | Responsibility | | --- | --- | | `ui css install` | Download the pinned executable, verify SHA256, install in the OS user cache. An already valid installation does not download again. | | `ui build` | Generate `.templ` Go, then build CSS if `ui.css.json` exists. | | `ui generate` | Generate markup only; use for component-only libraries. | | `ui css build` | Build/minify CSS only, atomically replacing output after success. | | `ui check --json` | Check markup and configured CSS freshness, then compile Go/tests without executing them. | | `ui css check` | Recompile/compare CSS without changing the committed output. | The Go/CSS toolchains still need their normal local caches; install Go dependencies with Go tooling before an offline build. Build/check never download the Tailwind executable or add a Go dependency. Package resolution uses read-only `go list`. Check uses temporary files/caches but leaves generated source and CSS unchanged. A missing tool fails with `UI_CSS_TOOL`; stale output fails with `UI_CSS_STALE`. All failed commands have nonzero exit status. Use top-level `ui check --json` for machine diagnostics; `ui css ...` commands print human-readable errors. ## Files and configuration Generated `ui.css.json`: ```json { "version": "v4.3.3", "input": "project/styles/input.css", "output": "project/static/app.css", "packages": [] } ``` Paths are relative to the project/module directory where you run the command. Input/output must be different local `.css` paths. Unknown config fields, unsupported versions and invalid paths fail explicitly. Commands do not search parent directories. The pinned framework and config version must agree; upgrading Tailwind is a reviewed framework/toolchain upgrade, not an implicit `latest` fetch. `project/styles/input.css` imports Tailwind with automatic detection disabled and lists the project's `.templ` and ordinary Go source patterns explicitly. Generated `*_templ.go` and tests are excluded, preventing stale generated classes and test payloads from influencing normal CSS. Source paths are relative to the input file, not the caller's current directory. See upstream [source detection](https://tailwindcss.com/docs/detecting-classes-in-source-files). Customize with CSS-first Tailwind v4, for example: ```css @theme { --color-brand-600: #4f46e5; } ``` Then write `class="bg-brand-600 text-white"` in `.templ`. Keep the existing `@import` and `@source` declarations. Local CSS imports resolve relative to the input file. Do not use old v3 `@tailwind base` directives or assume a `tailwind.config.js` is auto-loaded. The standalone build is not a promise that arbitrary npm plugins are bundled; those require their own explicitly maintained build integration. CSS remains trusted authored source, not request input. ## Classes and variants Use familiar complete utilities and responsive/state variants: ```templ ``` For dynamic variants, choose between complete literal strings in Go. Do not construct utility names from request values (`"bg-" + color + "-600"`), because Tailwind scans text rather than evaluating Go. For intentional finite classes that cannot appear literally in scanned source, use an explicit CSS `@source inline(...)` declaration. Never safelist an unbounded set derived from user input. `ui.Merge` combines distinct class tokens. It does **not** implement tailwind-merge or decide which conflicting utilities win: the generated CSS cascade governs that. Prefer a typed variant that chooses one spacing/color utility per state. ## Independently installed component packages Register an app through Go imports/manifests as usual. Separately add the **exact Go import path** of a package containing Tailwind classes: ```json { "version": "v4.3.3", "input": "project/styles/input.css", "output": "project/static/app.css", "packages": ["example.com/your-library/cards"] } ``` That path is illustrative. Cicadel resolves each entry using the host's selected Go module graph, then adds an explicit Tailwind source directory for the build. It works with installed module-cache sources and local replacements; no paths into a particular user's module cache are committed. Directory scans include descendants, so point at the narrow component package. The `packages` setting does not install modules, activate apps, or establish permissions. Missing packages fail with `UI_CSS_PACKAGE`; install them via normal Go tooling first. Library releases must include their class-bearing source or literal candidates; Tailwind cannot infer utilities hidden in runtime-only data. Library authors remain responsible for sensible source-directory contents and dependency declarations. ## Serving and production The starter embeds `project/static/app.css` in Go and serves `/static/app.css` using `static.Handler`. `layout.Page` accepts an optional `Props.Stylesheet` URL; it emits a contextual-escaped ``. The generated home page supplies the default asset path. The minimal renderer/layout never silently inserts CSS into other applications, so existing pages keep their current stylesheet choice. Commit CSS input/config and generated CSS together with the generated component Go. Run `ui check` before the production build. After UI changes, run `ui build` and restart/rebuild the Go server to refresh embedded assets. There is no HMR/watch server or production runtime CSS compilation. You can serve the output through your existing static host/CDN instead by setting the page's stylesheet URL explicitly; asset hashing/CDN cache policies are separate from this compiler integration. Tailwind v4 targets modern browsers; use upstream [compatibility guidance](https://tailwindcss.com/docs/compatibility) when choosing browser support. This integration verifies generated CSS/HTTP delivery, not visual pixel equivalence across browser engines. ## Another stylesheet system or an existing project To opt out, remove `ui.css.json`, replace `project/static/app.css` with your own stylesheet/build output, and keep or change the explicit link/static route. `ui build/check` then handles markup only. Do not leave a Tailwind config pointing at output maintained by a different compiler. To adopt Tailwind in an existing app, add the config, an input importing Tailwind with explicit source directories, and an output location owned by your static pipeline. Add the stylesheet link, install the tool, build/check, and verify the asset route. Existing apps are not automatically restyled by upgrading Cicadel. ## Integrity, platforms and evidence SHA256 digests are pinned in framework source from the official v4.3.3 release. Every build/check verifies the cached executable before executing it; damaged copies fail with `UI_CSS_INTEGRITY`. Only `install` replaces/downloads it. The cache is `/cicadel/tailwind/v4.3.3/`; no executable is committed to a project. Config/build/version/package failures use distinct `UI_CSS_*` diagnostic codes. Release pins cover macOS arm64/x64, Linux glibc arm64/x64 and Windows x64. The implementation was exercised locally on macOS arm64; Linux CI is configured. Other platforms, including Linux musl and Windows arm64, are not claimed verified or supported by the automatic installer. Use a separately managed CSS build and opt out of this pipeline when its platform/tooling requirements don't fit. `internal/tailwind` tests real compilation, responsive/hover utilities, freshness, invalid input preservation, package sources, and checksum tampering. Scaffold tests compare shipped CSS with a fresh compiler result and execute the documentation walkthrough. The independent module consumer test includes installed-package class detection and embedded CSS HTTP delivery from outside the source tree. See [authoring verification](https://cicadel.fauzaanu.com/en/dev/sources/docs/component-authoring-verification.md) for recorded runs. --- Source: `docs/philosophy.md` Markdown: https://cicadel.fauzaanu.com/en/dev/internals/philosophy/index.md # Framework philosophy Cicadel aims to bring Django's structure and development speed to Go, with an AI-first workflow, modern components and Go's compiled runtime. ## Predictable application structure Projects own settings and app registration. Apps group routes, handlers, models and components. Explicit Go values make the application understandable to both developers and coding agents. ## AI-first authoring Application guides should show working code, concise explanations, and prompts that an agent can act on. Versioned Markdown and `llms.txt` provide the same application guidance without requiring an agent to extract it from a webpage. ## Reusable applications Official and third-party installable apps use the same public contracts. First-party capabilities form Cicadel's core defaults, composed through those installable contracts. Separate Go modules describe packaging and distribution; they do not make the framework's capabilities optional extras. Each capability has one canonical implementation and workflow, integrated into standard project scaffolding, commands, documentation and checks. Superseded implementations must be consolidated with a migration path that preserves application data and recorded history. An unused implementation in core or a competing installable workflow is an integration gap, not a supported architectural choice. The standard project composes accounts and formsets, and its management commands provide model migrations and typed query generation. Migration execution, verification and recovery share the recorded-history runner. ## Typed, server-rendered UI Components use typed Go props and explicit slots, authored in `.templ`. Tailwind is the default stylesheet workflow. Applications can choose another CSS system. ## Clear boundaries PostgreSQL is the supported database. GORM handles runtime queries; recorded migrations own schema history. Public APIs remain experimental until a stable release. This page explains framework choices. To build an application, start with [the tutorial](https://cicadel.fauzaanu.com/en/dev/intro/tutorial/index.md) or [the application LLM index](https://cicadel.fauzaanu.com/en/dev/llms.txt). --- Source: `docs/security-review.md` Markdown: https://cicadel.fauzaanu.com/en/dev/internals/security-review/index.md # Implementation security review This is the implementation's own review, not an independent audit. - Toolchain: initial scanning identified reachable standard-library issues in Go 1.26.2. The minimum version was raised to 1.26.10 and scanning rerun; no reachable vulnerabilities remained. - Filesystem writes: upload temporary files were changed to creation through `os.Root`, retaining the rooted-directory boundary throughout creation and rename. Path traversal and failed oversized replacements are tested. - Model administration: editable fields must be explicitly listed. Primary keys and associations cannot be mass-assigned. Required authorization/scope callbacks and post-edit permission checks prevent an implicit allow-all policy; role-denial cases are integration-tested. - Session transitions: login rotates tokens and clears prior session state; logout destroys the session. Old tokens and pre-login CSRF tokens are rejected in tests. - CSRF: all unsafe cookie-authenticated methods, including JSON, require the session token. Token comparison is constant-time; token pages are not cacheable. - Data output: ordinary template strings are escaped; the article API projects only ID/title. Authentication hashes are excluded. Template errors are buffered before headers are written. - Database: values are parameterized; application request contexts reach GORM. Explicit SQL migration tests cover contention, rollback, version history, constraints, and cancellation. Raw SQL identifiers remain developer-controlled. - HTTP: explicit allowed hosts, body limits, timeouts, local-only redirects, and generic error responses provide a baseline. No forwarded-header trust is inferred. - Jobs: rollback/commit behavior is tested. Worker idempotency and external side-effect retry policy remain application responsibilities. Before public deployment, apply login/expensive-endpoint rate limits at the gateway or application, use the accounts browser bridge or integrate revocation with a custom user store, apply explicit object permissions, use HTTPS and verified database TLS, validate the object-storage signer, and review the complete application. These are deployment boundaries, not capabilities proved by this repository. External review and beta adoption remain release gates in PLAN.md. - Browser account integration: cookie sessions retain account tokens server-side, resolve disablement/revocation on each request, and enforce bounded CSRF-protected forms. Recovery responses are uniform and single-use tokens are covered by PostgreSQL tests. - Email: required verified TLS by default, no credentials over plaintext, MIME/header validation and envelope-only Bcc are tested against local SMTP fixtures. - Logging: structured credential fields/groups are redacted before handlers; default requests omit private URL/body/header data, and panic values/query arguments are excluded. Free-form text and application-provided custom objects remain the caller's responsibility. --- Source: `website/README.md` Markdown: https://cicadel.fauzaanu.com/en/dev/sources/website/README.md # Documentation website Hugo builds this site into static HTML, CSS and JavaScript. Cloudflare Workers Static Assets serves the output at https://cicadel.fauzaanu.com. There is no Cicadel application server, database or paid search service. ## Build and verify Install **Hugo 0.169.0**, Go (the version in the root `go.mod`), Python 3 and Node.js 22 or later. From this directory: ```sh npm ci npm run build npm run check node --check static/app.js node scripts/test-search.cjs python3 scripts/test-versions.py python3 scripts/test-examples.py npx wrangler deploy --dry-run ``` `HUGO=/path/to/hugo npm run build` selects a specific binary. Build output is `public/`; never edit or commit generated content. Open the generated HTML using your preferred local static hosting tool for manual visual review. ## Authoring Edit the original Markdown in `docs/` and module READMEs. `data/navigation.json` maps source files to Django-style first steps, topic guides, how-to guides, reference, releases and internals sections. Add a source entry there to publish a guide. Internal Markdown links are rewritten to the correct version; repository-only files link to their matching Git source. Page headings produce the table of contents. Search is built locally into `index.json` and filtered by selected version. The theme lives in `layouts/` and `static/`. The UI supports keyboard search (Ctrl/Command K), light/dark themes and mobile navigation. Roboto and Fira Mono are self-hosted copies of the fonts used by Django documentation. Their licenses and provenance are in `static/fonts/`. No third-party scripts or remote font requests are used. ## LLM-readable documentation The build generates these public endpoints automatically: - `/llms.txt`: the development documentation index, plus links to every version. - `/llms-full.txt`: the complete development documentation in one text file. - `/en/VERSION/llms.txt` and `/en/VERSION/llms-full.txt`: version-specific indexes and full bundles. - `/en/VERSION/GROUP/PAGE/index.md`: clean Markdown for each published guide. Section and overview pages also have `index.md` copies. - `/en/VERSION/sources/PATH.md`: supplemental documents outside the website navigation. The application index includes the application navigation and sources listed in `data/application-sources.json`. Framework philosophy, contributor guides, roadmaps and implementation evidence have a separate `/en/VERSION/framework/llms.txt` index and `llms-full.txt` bundle. Keep application guides short and task-oriented, with working code and copyable agent prompts; put framework decisions in the framework section. Absolute documentation URLs in prompts follow the selected version automatically. Together the two corpora include all Markdown in `docs/`, `contrib/`, `examples/` and `skills/`, plus the project README, changelog, roadmap, security policy, battery inventory and this authoring guide. Repository agent instructions and build artifacts are excluded. A version's `llms-manifest.json` records each source and Markdown URL so completeness can be checked. Relative documentation links point to Markdown in the same version; code examples remain unchanged. Each HTML documentation page advertises its Markdown copy with `rel="alternate" type="text/markdown"` and its version's index with `rel="describedby"`. The HTTP `Link` header advertises the root index too. Markdown and text exports have explicit content types and require no JavaScript. Exports read the same working tree or frozen release commit as the HTML build. Release snapshots include supplemental documents and authoring skills, not just the main navigation. The version test modifies both ordinary and supplemental guides after a simulated release to verify isolation. ## Versions and releases `versions.json` initially contains only `dev`, built from the current checkout. After publishing a release tag: ```sh python3 scripts/add-version.py v0.1.0 npm run build npm run check ``` Commit and push the updated manifest to `main`; GitHub Actions builds and publishes the complete site. The helper resolves the tag to an immutable commit SHA. Release content **and navigation** are read from that commit; subsequent changes to `dev` cannot rewrite them. Releases must include the website navigation manifest. Fetch full Git history when building; CI uses `fetch-depth: 0`. Each version is served at `/en/VERSION/`. The root redirects to `/en/dev/` until a stable release policy changes it. Existing versions are always rebuilt alongside dev, so a deployment preserves their URLs. Do not remove published versions from the manifest. ## Deploy The tracked `wrangler.jsonc` targets the personal account and the `cicadel-docs` Worker, with the custom domain `cicadel.fauzaanu.com`. Set `CLOUDFLARE_API_TOKEN` securely in the process environment and `CLOUDFLARE_ACCOUNT_ID` to the configured account. Never commit credentials. ```sh npm run build npm run check npm run deploy python3 scripts/check-live.py ``` The `Documentation` GitHub Actions workflow builds static assets, HTML, search and both LLM corpora on every push and pull request. It tests links, frozen versions, executable documentation examples and JavaScript, then archives the verified `public/` directory. On pushes to `main`, a separate publish job downloads that exact artifact and deploys it to Cloudflare. Pull requests never receive deployment credentials or publish. Manual `workflow_dispatch` on `main` can republish a checked build. The GitHub `documentation` environment holds the `CLOUDFLARE_API_TOKEN` secret. The account and Worker are explicit in the workflow/config. Deployment jobs are serialized and never cancelled mid-upload. The post-deploy check compares live exports and fonts with the artifact, checks page discovery, the root redirect and a missing-page 404. A failing check makes the Actions run fail. Review the run before considering a docs update delivered. Future agents only edit source Markdown, navigation or theme files, run the required local checks, then commit and push. They need no local Cloudflare credentials. Never commit `public/` or tokens. Run all repository-required CI checks locally before any push. Static asset requests are served without Worker code execution. ### Non-browser access on Cloudflare The zone-level custom rule in `cloudflare/browser-integrity-rule.json` skips only Browser Integrity Check for `GET` and `HEAD` on `cicadel.fauzaanu.com`. This prevents Cloudflare error 1010 for ordinary HTTP clients fetching public documentation. Other hostnames, methods, managed firewall rules and rate limits are unaffected. The rule is applied separately through the Cloudflare Rulesets API; Wrangler does not manage it. Its stable rule reference is `cicadel_docs_machine_readable`. `check-live.py` deliberately uses Python's default HTTP client without browser impersonation, cookies or JavaScript. It compares every documentation export and font with the local build and checks the root redirect and 404 response. Run it after deployment to detect content drift or an edge security setting that blocks LLM readers.