1. Secure development lifecycle
| Phase | What happens |
|---|---|
| Requirements | Each change states what it does and its security impact: new data collected, new supplier, new public endpoint, change to authentication, tenancy or audit. Changes with security impact are noted in the security register. |
| Design | The secure-coding baseline (section 2) applies. New data collection is checked against policy 08 (minimization, classification, retention). |
| Build | Code lives in a private GitHub repository. Secrets are never committed. |
| Test | The full automated test suite passes before every push (section 3). |
| Review | Every change is reviewed as a diff before it is committed (section 4). |
| Deploy | Only through the deploy script (section 6). |
| Operate | Audit log integrity is checked every 10 minutes and at the end of each deploy; problems follow policy 05. |
2. Secure-coding baseline (in place)
These rules are written in the repository's developer guide and enforced by tests:
- Every model with customer data uses the organization scope; a query with no organization set throws instead of returning data.
- Background jobs and commands set the organization explicitly.
- Audit events are written only through the audit service; the table is append-only and hash-chained; secrets never go into event context.
- Allow and deny decisions about AI-agent actions are deterministic; AI may propose, never decide.
- MFA is mandatory; there is no public sign-up.
- Third-party websites are fetched only through the anti-SSRF client (public IPs only, standard ports, redirects re-checked).
- Content Security Policy forbids inline scripts and styles and external assets; database queries are parameterized; HTML output is escaped; every form has CSRF protection.
- Every public route has its own rate limit.
3. Testing and acceptance criteria
- In place: the PHPUnit suite (feature, security regression and tenant-isolation tests) runs against both SQLite and PostgreSQL before every push. A change is not released unless all tests pass.
- Acceptance criteria for a release: all tests green on both databases; new behavior covered by at least one test; any change to authentication, tenancy, audit or public endpoints has a security regression test; translations complete (the localization test passes); database migrations have a working
down()step or a written reason why not. - Tests use synthetic data only (factories and test scenarios). Production data is never copied to development or test environments; if it ever became necessary, it would require a written exception (policy 00) and masking first.
- There is no separate staging environment; development runs on local and cloud development machines with synthetic data.
4. Code review
- Today: the Founder reviews every change as a diff before committing, including changes proposed by AI coding assistants, which are treated as untrusted proposals.
- From the first hire: every change needs approval by a person other than its author, enforced with GitHub branch protection on
main.
5. Dependencies
- PHP dependencies are pinned in
composer.lock; production installs exactly those versions (composer install --no-dev). - Dependencies are updated at least monthly, and within the deadlines of policy 07 when a security advisory applies.
- Commitments: enable GitHub Dependabot alerts and update pull requests for Composer and npm (owner: Founder, target 2026-10-15); add
composer auditto the deploy script and CI (target 2026-11-30); generate a Software Bill of Materials (CycloneDX) for each release (target 2026-12-31).
6. Deployment
- In place: deploys are manual, run by the Founder over SSH with
deploy/deploy.sh: fast-forwardgit pullfrom the private repository (read-only deploy key),composer install --no-dev, database migrations, catalog sync, configuration/route/view caches, worker restart, PHP-FPM reload and an audit-chain integrity check. - Only code that is on the
mainbranch of the repository can be deployed; nobody edits code directly on the server. - Commitment: a CI pipeline (GitHub Actions) running the full test suite on both databases and
composer auditon every push, with deploy allowed only after a green run (owner: Founder, target 2026-11-30).
7. Rollback
- Identify the last good commit (
git logon the server). - If the bad release included migrations, roll them back first with
php artisan migrate:rollback --step=N, only when thedown()steps do not lose data; otherwise restore from backup (policy 06). - Check out the last good commit on the server (
git checkout <commit>), then run the remaining deploy steps (composer install, caches, worker restart, PHP-FPM reload, audit-chain check). - Fix forward on
main, then return the server tomainwith a normal deploy. - Record the rollback in the register. The procedure is exercised at least once a year (first test: owner Founder, target 2026-12-31).
8. Server configuration changes and baseline
The server baseline is: Ubuntu 24.04 LTS with unattended security upgrades; ufw allowing only 22 (SSH), 80 (HTTP, redirected to HTTPS) and 443 (HTTPS); SSH by key only with password authentication disabled; fail2ban on SSH; NTP synchronized; Caddy, PHP 8.4-FPM, PostgreSQL 16 (SSL on) and Redis, whose ports are not open in the firewall. Commitment: confirm that PostgreSQL and Redis listen on the local host only and record it (owner: Founder, target 2026-10-15).
- Manual configuration changes are written in the register before or right after the change (what, why, how to undo).
- The baseline is reviewed at least once a year.
- Commitment: a scheduled check that compares the server against this baseline (SSH, firewall, Caddy, services) and alerts on drift (owner: Founder, target 2027-01-31).
9. Emergency changes
When a fix cannot wait (active exploitation, outage): the change may skip the normal wait but never skips the automated tests, unless the service is down and the change is a rollback. It is recorded as an exception (policy 00) within 2 business days, with a follow-up review.
10. Changes affecting customers
Changes to customer tenants (policies, keys, settings) are made only by the customer, or by the operator at the customer's written request, and are audited. Platform changes that affect how customers use the service are announced before release; security fixes may ship immediately.
11. Asset changes
The security register holds the asset list: servers, domains, databases, supplier accounts, keys (policy 02), endpoints (policy 10) and the code repository, each with its owner, the highest data class it holds (policy 08) and its location. The list is reviewed at least once a year.
- Adding, removing or changing a production asset is approved by the Founder and recorded in the asset list. A new subprocessor also follows policy 09.
- Moving systems or data to another location (new server, datacenter, region or provider) requires written approval by the Founder in the register, a transfer over encrypted channels, deletion at the old location once verified, and notice to customers before their data changes location.
- Customer data is never moved on physical media. If that ever became necessary, the media must be encrypted, carried by hand and logged.