Theory

What you built, the honest caveat, and where next

What you built. An empty main.go became: a Chi server rendering Templ over HTMX; Postgres through goose and sqlc with the schema as one source of truth; registration, login, and password reset over server-side sessions; CSRF you felt the need for before you added it; file upload that streams and hashes in one pass; ownership enforced in SQL; accountless signing where the token is the authorization; a signature that recomputes its hash and never lies about it; an append-only audit trail the database itself protects; and a real deployment that survives its own redeploys. Fifteen lessons, one system, every piece earned.

The caveat, one last time — because it matters most at the end. SignFlow's signature is a typed name, a timestamp, and a SHA-256 of the document at signing. It is tamper-evident and nothing more. It is not PKI. It is not an eIDAS qualified or advanced electronic signature. It does not prove identity — only that whoever held a link typed a name against these exact bytes at this time. The app does evidence, not prevention: it will tell you a document changed; it will not stop the change, and it lets a signer sign past a tamper warning, honestly recording what they saw. Never ship this, or describe it, as more than that. Knowing precisely where the line is — and saying so plainly — is itself a professional skill, and the one this track cared about most.

The upgrade path, if you want to cross that line. Real digital signatures replace "typed name + hash" with public-key cryptography: each signer holds a private key (ideally in hardware — a smart card, a secure element, an HSM) and signs the document's hash with that key. Anyone can verify the signature against the signer's public key, which binds it to a real, vetted identity. To be legally qualified (eIDAS), that identity is asserted by a certificate from a trusted Certificate Authority, often on a government-issued token, under audited processes — with certificate revocation, timestamping authorities, and long-term validation on top. That is a different discipline, deliberately out of scope here. But you now have the exact mental model it extends: SignFlow pins the bytes; qualified signing additionally pins the identity, cryptographically. The hash you already compute is the very thing a real private key would sign.

Where to take your fork. Add roles (an owner who can delegate). Put object storage behind the storage.Store seam and scale to multiple instances. Swap the console mailer for Resend and send real invites. Add the refresh-token flow from last lesson and feel the trade move. Every one of these has a clean seam already waiting — because the whole app was built to be extended, and read, as much as run.

You finished the server-side track, and with it all four. You can build a mobile app and its backend, a browser client in vanilla JS and then TypeScript, structured Go from first principles, and now a full server-rendered web application — deployed, honest about its limits, and yours to grow.