What we write down when we decide something
A decision that only exists in a conversation gets re-argued every few months. Writing it down is cheaper than remembering it.
Removing the server removes most of the classic vulnerabilities and moves the remainder into the build, the bucket, and the third parties you embed.
1 min read
Written by
Seratlas Team
Engineering and delivery
1 min read
We build and operate assessment software. We write here about the parts that are harder than they look.
There is no database behind this site, no session, no request handler, and no runtime dependency install. A long list of familiar problems does not apply: injection into a query, a deserialisation bug in a request body, an authorisation check on the wrong branch.
What is left is worth naming, because "it's just static files" is where people stop thinking about it.
Everything that has credentials happens at build time. Anything interpolated into
a page during next build is in the output permanently, and any NEXT_PUBLIC_
variable is inlined into JavaScript that ships to every visitor. A secret in one
of those is not hidden by obscurity — it is published, then cached at the edge.
So the rule here is blunt: if it must stay private, it cannot participate in this build, because there is no runtime to hold it instead.
With a private origin and an access control policy, the interesting failures are configuration ones. A bucket policy scoped too broadly, an error response left unmapped so every bad URL returns a bare 403, a stale object that the last deploy failed to prune while the HTML that referenced it was replaced.
None of those are code defects, which is why they survive code review.
Every embedded script is a dependency that can change after you deploy. This site posts its forms to one external endpoint and embeds nothing else — no tag manager, no chat widget, no font CDN. That is not austerity; it is the only version of "we know what runs on this page" that stays true next week.
A content security policy, delivered as a response header from the distribution rather than a meta tag, and subresource integrity on anything we ever do embed. Both are edge configuration, and neither is in the repository yet.
A decision that only exists in a conversation gets re-argued every few months. Writing it down is cheaper than remembering it.
What this site is for, what is still missing from it, and why we would rather publish it in that state than wait.
A consent checkbox that starts checked is not consent. A few small decisions separate a form that asks from one that assumes.
A reading-time estimate is a guess presented as a fact. That is fine, as long as the guess is not wrong in a way the reader will notice.
We would rather answer a direct question than write a follow-up post nobody asked for.