Accounts soon

4 decisions

Decisions worth writing down

Four arguments from building these projects. Each one has a problem, what changed, what it bought, and a number you can check against the repository it names.

Architectureorbis

The website cannot hold the brain

0

copies of the model key in any cloud

The problem
The original plan put the conversation loop in serverless functions. Two facts killed it: a serverless function cannot hold a WebSocket open for the length of a voice turn, and the database was required to stay on a personal machine.
What changed
The split inverted. The hosted site serves the interface; the personal machine runs the brain, the tools and the database, reached over an outbound tunnel that needs no open inbound ports.
The result
Two requirements that looked opposed — host it on Vercel, and keep the database on my own machine — both hold, and the model API key never enters a cloud environment at all.

An archive that reports condition

8 of 8

projects listed, four of them not deployed

The problem
When this register was first drawn up, one of its eight repositories held a single line of README and one commit, and three more had never been deployed. A portfolio showing only the four live projects would have been honest but thin; one implying the rest were finished would have been a fabrication.
What changed
Condition became a first-class field rather than an omission — shipped, built, specced, claimed — set in the same face at the same weight as everything else, and constrained in the database so a fifth value cannot be invented later.
The result
The sparse inventory became the subject instead of the problem. The register shows the real shape of a body of work, which includes the parts that stalled, and nothing on the page needs a disclaimer.

Enabled is not enforced

4

tables verified FORCE, not merely enabled

The problem
Row-level security was switched on for every table, and it did nothing. Postgres exempts a table's owner from its own policies by default, and the application connects as the owner — so every policy reported as enabled while permitting everything.
What changed
Two changes, both required: the role is created NOBYPASSRLS, and every table is set to FORCE ROW LEVEL SECURITY. The setup script then reads both facts back out of the catalogue and refuses to finish if either is missing.
The result
The policies bind to the role that actually connects. The failure mode that mattered here was silent — a security control that reports success while doing nothing — so the check for it is now part of provisioning rather than a thing to remember.

The rate limiter that forgot

15 to 30 min

ladder that now outlives a restart

The problem
The login lockout ladder was ported from a working implementation that kept its state in a module-level map. Its own comment admitted the flaw: on serverless that state is per-instance and resets on every cold start, so an attacker who can force new instances gets far more attempts than the ladder implies.
What changed
The state moved into Postgres — one row per fingerprinted address, with the failure count, the tier and the lockout expiry. The comment had said to do exactly this if it ever became the only gate on something that mattered. Here it was.
The result
The escalating lockout survives a restart, which is the one thing the in-memory version could not do. The addresses themselves are encrypted at rest, because an IP address is personal data and a lockout table is not a reason to keep a plaintext log of who tried.

Reviews

Empty, and honestly so. Nobody has said anything on the record about this work yet, and a testimonial is only worth printing if a real person attached their name to it.

When there is one, it appears here with the name of the person who said it. Until then this section stays as it is.