How lazysite is engineered
The software good practices behind lazysite - the measures, gates and controls in place across eight dimensions of quality, as of v0.6.0.
lazysite is a deliberately small engine, but it is built and maintained as a commercial product. It is assessed against an eight-dimension non-functional standard - correctness, code quality, testing, performance, reliability, security, documentation and compliance - under a declared Commercial regime. This page is a factual summary of the measures in place as of v0.6.0.
1. Correctness
- Compile integrity, enforced. Every production Perl file compiles under
perl -c, guaranteed by a committed gate (t/lint/04-compile.t) so a non-compiling file cannot pass the suite. - One capability resolver. Account capabilities resolve through a single source-of-truth reader; the deliberate module-free copy on the render hot path is recorded in an architecture decision record (ADR 0001).
- Path safety. Every filesystem path derived from request input is passed through
realpathand verified to sit inside the document root before any file operation. - Grounded features. Shipped behaviour is exercised by the test suite, and plugin discovery is honest - each discovered script answers a
--describecontract.
2. Code quality
- Static analysis at severity 3, zero violations (
perlcritic), enforced by the suite - plus a separate security-themed pass at the strictest severity 1, also zero. - Formatting gate. A house
.perltidyrcwith a changed-code-only gate: new and edited lines must match the style, without churning the existing tree. - Every deviation documented. Each relaxed rule carries a written rationale in the profile and the architecture docs - deliberate, not silently suppressed.
- Consistent structure.
use strict; use warningseverywhere, with shared logic living once in an eighteen-module library the CGIs consult.
3. Testing
- 2,365 automated tests across 154 files, green at v0.6.0 (up from 2,003 at the last review).
- A five-level taxonomy: unit, integration, journey, smoke and lint - the CGIs are exercised as real subprocesses in a real CGI environment.
- Coverage floors enforced at release: statement 60 and branch 60 (target 75), checked by
coverage.sh --checkinsiderelease.sh, so a coverage breach blocks the release rather than being a hand-run reminder.
4. Performance
- Render-once, serve-cached. Each page is rendered to
.htmlbeside its source and served verbatim thereafter, regenerating only on change - fast by default, nothing recomputed per visit. - Benchmark gate, enforced at release. Three key operations are timed against a provenance-stamped baseline (host, Perl version, date) within a 2x tolerance; the render benchmark is split into cache-hit and render-miss so the figure is honest.
- Measured properties on record - token verification is materially cheaper than password verification; a per-CGI module-load floor of ~50 ms and a cache-hit concurrency speedup are documented and tuned (e.g. three manager calls collapsed into one to cut cold-start).
5. Reliability
- Backup and restore, tested. Pre-upgrade backups with configurable retention; content and full-system snapshots; in-manager restore takes a safety snapshot first and clears affected caches; full-system restore even supports cross-domain migration. The round trip is covered by tests.
- Fail-closed writes. Manager and form writes check for the out-of-space/quota case and remove half-written files on failure - with disk-full injection and concurrent-writer races covered by a dedicated test. WebDAV PUT bodies stream in bounded chunks.
- Concurrency and locking. Theme/layout activation snapshots under an artifact lock (validate -> snapshot -> flip); WebDAV honours a documented 423/429 retry contract.
- Graceful degradation. Unparseable state falls back to safe defaults rather than failing; the audit reader is rotation- and truncation-aware.
- Operational tooling. A health-check "doctor" reports OK/WARN/FAIL with remediation hints, offers safe
--fixrepairs and a DAV-endpoint probe; alogrotatesnippet ships with the installer.
6. Security
Security is structured around a STRIDE threat model with OWASP ASVS L1 verification (docs/SECURITY.md), enumerating the assets and trust boundaries and pairing each threat category with a concrete control:
| Threat category | Control in place |
|---|---|
| Spoofing | Two-signal trust gate with mandatory edge-stripping of client X-Remote-* headers; HMAC-signed session cookie |
| Tampering | Template engine runs with Perl evaluation disabled; layout authoring gated by capability; content-vs-layout capability split |
| Repudiation | Append-only audit trail (who / what / target / origin / outcome, including denied attempts), gated by an audit capability |
| Information disclosure | Secrets server-denied under restrictive modes; analytics aggregated and IP-anonymised; error surface synthesised |
| Denial of service | Per-IP login rate limiting; upload-size gate; bounded-chunk streaming; fail-closed writes; a bad-URL auto-blocker on by default |
| Elevation of privilege | API/MCP token clients confined to a capability subset, never operators; per-file ACLs; manager/remote channel separation |
Alongside the model: a single SSRF guard for outbound fetches (rejects loopback, private, link-local/metadata and CGNAT ranges), groups-only explicit capabilities, a strict SBOM gate (an undeclared dependency fails the release), secrets-lint and security-perlcritic gates all green, and a published coordinated vulnerability disclosure policy.
7. Documentation
- Role-scoped for every audience - user, developer, implementor, operator and policy docs around a canonical feature reference, plus README, upgrade guide and security policy.
- Six architecture decision records and architecture docs for security, code quality and performance.
- Generated, drift-checked references - the capability map, quickstarts and host-dependency list are generated from a single source of truth and golden-tested against drift; CLI tools carry POD that renders to man pages at release.
- Accessibility - a WCAG 2.1 AA self-assessment of the manager UI and default theme.
- Ships inside every install - the reference docs (including AI-agent briefings) travel with the product; a commit-keyed CHANGELOG is the single source of truth for what changed.
8. Compliance and supply chain
- Posture of record - a documented Commercial-regime policy structured around licensing, supply chain, the EU Cyber Resilience Act status, support period and data protection, with the CE-marking date tracked.
- Software bill of materials - a CycloneDX
sbom.jsonin every release with per-component SHA-256 hashes and SPDX licence ids, behind a strict gate so it can never drift from the code. - Security-update mechanism - edge/stable release channels with per-site channel selection, documented in the upgrade guide.
- Install classification and provenance - every shipped file is classified as code (overwritten) or seed (operator content, preserved), with a provenance stamp distinguishing the two.
- MIT licensed, with per-component licence ids recorded in the SBOM.
At a glance (v0.6.0)
| Measure | State |
|---|---|
| Test suite | 154 files, 2,365 tests, green |
| Compile sweep | Enforced over all production files |
| Static analysis | perlcritic severity 3 zero; security theme severity 1 zero |
| Formatting | House profile, changed-code gate |
| Coverage | Statement 60, branch 60 (target 75), enforced at release |
| Benchmark | Three ops within 2x of baseline, enforced at release |
| SBOM | CycloneDX per release, strict gate |
| Decision records | Six ADRs |
| Threat model | STRIDE + ASVS L1 |
| Regime | Commercial, MIT licensed |
These are the disciplines that keep lazysite a small, auditable codebase you can run in production with confidence - and they are the same enforced rules an AI agent publishes through, exactly as a person would.
- See what lazysite does, or how it compares.
- Onboard an AI agent to publish within these same rules.
- Source and licence on GitHub.