Trust centre
Last reviewed: 22 September 2026
Overview
Foundry is a shared base Bootstrap/SCSS theme and component catalogue, built and maintained by Michael Shreeves as an individual, not a company. It ships to every Symfony/Bootstrap project that copies a partial or a template out of it — which is why the security and accessibility floor set here matters beyond this one repository, even though the repository itself holds no accounts and almost no personal data of its own.
Data protection
There is no user entity, no password, and no security firewall in
this application at all — not a restricted one, an absent
one (checked directly: composer.json has no
security-bundle package, and there is no
config/packages/security.yaml). A real database now
exists (MySQL), holding exactly one kind of row: a Web Push
subscription, kept for at most 30 days. Visits are also recorded
in server access logs and in self-hosted, cookieless analytics, and
demo edits live in the visitor's session. Every one of these, with
its lawful basis and retention period, is in the
privacy notice rather than
repeated here. Michael Shreeves, as an individual, is the
controller; data is held in the UK.
Security controls
- Authentication and authorisation. Not applicable — there is nothing to sign in to, so there is no password hasher and no per-object voter to describe. What this showcase does demonstrate is the pattern for documenting a real access-control policy once a project has one: /settings/mfa and /settings/password-policy (Phase 11) show mandatory admin MFA rendered as unmistakable fixed text rather than a togglable checkbox, and a length-over-complexity password policy defaulting to a 12-character minimum with no forced special character, per NCSC's current guidance. Copy that pattern, not this paragraph, into a consuming app's own trust centre once real accounts exist.
-
Response security headers, sent on every
response outside local debugging
(
SecurityHeadersSubscriber): a Content Security Policy withscript-srcandstyle-srcboth restricted to'self'plus a per-request nonce for script — no'unsafe-inline'anywhere —X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Referrer-Policy: strict-origin-when-cross-origin, a locked-downPermissions-Policy, andStrict-Transport-Securityon every HTTPS response. -
CSRF protection. Every state-changing route
(the two forms, the demo delete confirmation in
/components/overlays, every settings form added in Phase 11) is a genuine Symfony CSRF token, not a visual mock-up. - Rate limiting. The posts that could be used to flood someone or make the server call out are limited per IP address: the support form to 5 per 15 minutes, push subscriptions to 10 an hour, test pushes to 5 per 15 minutes. The demo forms (calendar, kanban, settings) only change the visitor's own session, so they aren't limited.
- Outbound requests. The push demo is the only thing that makes the server call out. It accepts only the browser vendors' own push services, refuses redirects, times out after 5 seconds, and checks the address it actually connects to, so a subscription can't be used to reach an internal address.
- No third-party script or font. IBM Plex Sans and Space Grotesk are self-hosted; every icon is vendored as inline SVG; Chart.js and Leaflet are served from this site via AssetMapper, not a CDN. See Subprocessors below.
- Encryption in transit. HTTPS everywhere, with HSTS sent for a year including subdomains. Cloudflare terminates TLS at its edge and requires TLS 1.3 as the minimum.
-
Encryption at rest. The one row this
application stores — a Web Push subscription's endpoint
and two keys — sits in an ordinary MySQL column with no
application-level encryption added on top; the keys are
already meaningless without the server's own VAPID private key
(kept in the server's untracked
.env.local, never committed). Whether the host's underlying disk is encrypted at rest hasn't been separately confirmed, so it isn't claimed. - Retention. A push subscription is deleted after 30 days, when its browser turns notifications off, or the moment the push service says it's gone. Access logs rotate out after 14 days.
-
Secrets. Never committed —
.envin this repository ships with every value blank or a non-secret default, and there is no mail, database or third-party API credential configured in a tracked file anywhere to leak.
Development practices
- Static analysis at PHPStan level 8, no baseline suppressions used to get a green run (checked:
phpstan.dist.neonhas noignoreErrors/baseline entry). - Coding standards enforced by ECS (PER-CS 2.0) on every change.
- An automated PHPUnit test suite, run before every change ships — covering the security headers (present, and CSP genuinely absent while debug is on), every shell and themed error page actually rendering, the theme-cookie behaviour, direct-GET 403/POST-only enforcement across the Settings area, and the accessibility/contrast assertions described below.
- All three (
composer qa) run in Bitbucket Pipelines on every pull request and again before every deploy; a red run stops the deploy. composer auditrun directly against this page's own "last reviewed" date: no known security vulnerability advisories in any dependency.scripts/verify-contrast.pyindependently re-verifies every colour pair in the token/theme files against the WCAG relative-luminance formula, rather than the pairs being eyeballed.
Subprocessors
Every third party that sees anything about a visitor, found by checking the templates, the JavaScript controllers and the outbound HTTP code rather than from memory:
| Who | What for | What they see | Where |
|---|---|---|---|
| Vultr | Hosting the server | Everything stored on it | Manchester, UK |
| Cloudflare | Proxy, TLS and DNS in front of every request | IP address, browser, the page requested | Global edge network; US company |
| The visitor's browser push service (Google, Mozilla, Apple or Microsoft) | Delivering a test push, only if the visitor asks for one | That a message was sent to that device; the content is encrypted | The vendor's own network |
| OpenStreetMap Foundation | Map tiles on /components/map only, fetched by the visitor's browser |
IP address, browser, which tiles were viewed | OSMF's tile servers |
Analytics aren't in this table because they aren't a third party:
Matomo runs on the same server, sets no cookie, and nothing is sent
anywhere else. No mail transport is configured, so the support and
feedback forms don't send anywhere. The API reference at
/api-reference is a page of this site, with no
third-party script or CDN.
Availability and resilience
Foundry runs on a Vultr VPS in Vultr's Manchester, UK data centre, shared with other projects by the same maintainer. Releases are atomic: each one is built in a fresh directory, health-checked against a route that queries the database, and only then switched live, so a failed release never replaces a working one. The server is backed up by Vultr's backup service, and a restore, including to a specific point in time, was tested and confirmed working on 10 September 2026. There's no uptime commitment; this is a showcase, not a service anyone depends on.
Incident response
Report a security concern to hello@mashreeves.com. As a sole individual maintainer there is no formal incident-response SLA published. Very little personal data is at stake here (see the privacy notice), so the realistic incident is a defect in this reference app that a consuming project shouldn't copy. A breach involving personal data would be assessed against the ICO's 72-hour reporting rule.
Certifications and frameworks
Foundry itself holds none. It's a personal project, not run under an organisation's certification. The host does: Vultr's Manchester data centre holds ISO 27001, SOC 2, SOC 1 and PCI DSS attestations, as listed in the hosting account's own compliance dashboard. Those are the host's certifications, not a claim that this service has been audited.
PCI DSS. Not applicable. Foundry takes no payments of any kind — there is no card, billing or payment concept anywhere in this codebase.
SOC 2. No SOC 2 report exists, and none has been requested. Nothing here is sold to an organisation whose procurement process would ask for one.
Accessibility
Built to WCAG 2.2 AA as the floor — every colour pair contrast-checked (not eyeballed) against light, dark and high-contrast themes, and every interactive component keyboard- operable from the start, because this catalogue becomes the accessibility baseline every consuming app inherits. See the published accessibility statement for what's actually been tested, rather than a summary here that could drift from it.
Reporting a vulnerability
Email hello@mashreeves.com
with what you found and how to reproduce it. Good-faith security
research that doesn't access, modify or destroy other people's data
won't be treated as an attack. The same contact is published in
machine-readable form at
/.well-known/security.txt
(RFC 9116).
Supplier and procurement questionnaire mapping
Most of a bespoke security questionnaire is one of a small number of standard question sets, reworded. This table maps the common ones onto the sections above, so a specific answer is a link rather than a rewrite.
| Common question area | Where it's answered here |
|---|---|
| Where is data hosted, and is it encrypted at rest? | Data protection; Security controls |
| Is MFA enforced for privileged access? | Security controls |
| How are subcontractors/subprocessors managed? | Subprocessors |
| What is your patch/vulnerability management process? | Development practices |
| Do you have a documented incident response process, and a breach notification commitment? | Incident response |
| Are backups tested? | Availability and resilience |
| Do you hold ISO 27001 / Cyber Essentials / SOC 2 / DSPT? | Certifications and frameworks |
| How do we report a security concern to you? | Reporting a vulnerability; /.well-known/security.txt |
| DSPT-specific: are all systems on supported software, and is staff security training current? | Development practices (software support); staff training is organisational, not code-verifiable, and doesn't apply to a sole individual with no staff |
Contact
hello@mashreeves.com for anything on this page, the privacy notice, or a security concern. For a problem with this showcase itself, use support instead.