steid

@jamesgill /

docs: record the first real deployment

Steid is live at https://jpgill.dev on Lightsail, hosting its own source. What
the deployment taught, written down while it is fresh:

A domain transfer moves the registrar, not the nameservers — the transfer had
completed and the Route 53 zone was correct, yet every public resolver returned
nothing, because the .dev registry still delegated to the old provider. dig
+trace shows the delegation the world follows rather than the zone you happen to
be looking at.

The domain was jpgill.dev, not jpgilldev.com. It was inferred from an email
address and never confirmed, and by the time that surfaced it was baked into the
release URL and the systemd unit.

The uniform 401 from 0007 cost more than the ADR predicted. Pushing to a
mistyped handle reported "Authentication failed" rather than "no such
repository". That was recorded as costing a prompt on a typo; in practice it
cost ten minutes and a confident wrong diagnosis, with someone watching who knew
the design. current.md now carries the question of whether an absent public
repository can 404 while private ones still 401.

Renaming a handle was exercised for real, jpgilldev to jamesgill on the live
instance: one UPDATE and one mv, because everything else keys off ids. So the
feature is two writes; what makes it more than that is that every existing clone
URL breaks and nothing redirects from the old handle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JZwc7URWKVhkAuRTWiDmjA
JamesPatrickGill authored 21 hours agoparentcadde5cBrowse files4414bba19ed3c96adbac447e85a4840105da9921

2 files changed+62 −0

plans/current.md+17 −0View file
@@ -94,6 +94,23 @@ instance, and Steid's own source is pushed to it and browsable there.
9494 - **A domain.** Caddy needs a real hostname to obtain a certificate. This is the one
9595 blocker that is DNS rather than code.
9696
97+### Open
98+
99+- **Whether an absent *public* repository can 404 while private ones still 401.** The
100+ uniform 401 from [0007](decisions/0007-tokens-over-http-basic.md) is what makes a
101+ private repository indistinguishable from one that does not exist — but it also turns
102+ every mistyped URL into "Authentication failed", which cost real time on the first
103+ deployment. The leak being prevented concerns *private* names only, so answering 404 for
104+ a repository that would be public if it existed may cost nothing. Needs thought about
105+ whether that is actually true.
106+- **No scheduled backups.** `/var/lib/steid` is the whole of the state and copies of it
107+ exist only because they were taken by hand. This is the largest gap now that the
108+ instance is live.
109+- **Releases are not served from the instance yet.** The Caddy blocks are written and
110+ commented in `deploy/Caddyfile`, and `install.sh`'s `RELEASE_BASE_URL` points at
111+ `/jamesgill/repos/steid/releases`, but nothing has been rsynced there — so the
112+ one-command install a stranger would run does not work yet.
113+
97114 ### Carried over — small, unblocked
98115
99116 - **A client that disappears mid-request leaves the body-copy task waiting.** The copy
plans/progress.md+45 −0View file
@@ -618,6 +618,51 @@ added without them would simply not have them and nothing would fail.
618618 - No dependency audit (`cargo audit` was not run), and no review of the deployment
619619 scripts beyond the earlier container dry-run.
620620
621+### Deployed · jpgill.dev, 2026-09-04
622+
623+Steid runs on the public internet at **https://jpgill.dev**, on AWS Lightsail (Debian 13,
624+x86_64, 1 GB), behind Caddy with a Let's Encrypt certificate, hosting its own source.
625+Installed with `install.sh --tarball`, since the instance that will serve the releases is
626+the one being installed.
627+
628+#### What the first real deployment taught
629+
630+- **A domain transfer moves the registrar, not the nameservers.** The transfer to Amazon
631+ Registrar completed, the Route 53 zone held the right records, and every public resolver
632+ returned nothing — because the `.dev` registry still delegated to the old provider's
633+ nameservers. Diagnosed with `dig +trace`, which shows the delegation the world actually
634+ follows rather than the zone you are looking at.
635+- **The domain was `jpgill.dev`, not `jpgilldev.com`.** Inferred from an email address and
636+ never confirmed, and by then it was baked into `install.sh`'s release URL and the
637+ systemd unit. Ask what the domain is.
638+- **`.dev` is HSTS-preloaded.** Browsers refuse plain HTTP with no click-through, so the
639+ certificate is not optional — until Caddy has one the site is simply unreachable.
640+- **The uniform 401 cost real time.** Pushing to a mistyped handle answered
641+ `Authentication failed` rather than "no such repository", because
642+ [0007](decisions/0007-tokens-over-http-basic.md) deliberately makes an absent repository
643+ indistinguishable from a private one. That trade was recorded as costing "a prompt on a
644+ typo"; in practice it cost ten minutes and a confident wrong diagnosis, with someone
645+ watching who knew the design. A stranger has nobody to ask.
646+- **An upgrade silently discarded the operator's Caddyfile.** `install.sh` kept
647+ `steid.env` across a re-run but rewrote the Caddyfile unconditionally, so a hand-added
648+ `www` redirect vanished on the next upgrade and took the hostname with it. Now written
649+ on first install only, with `--force-caddyfile` and `--www`. Found by testing the
650+ upgrade path rather than waiting for it to happen.
651+- **The upgrade path works and is verified**: claim, database, repositories, `steid.env`
652+ and Caddyfile all survive `install.sh` re-run against a newer tarball.
653+
654+#### Renaming a handle, done by hand
655+
656+`current.md` recorded a rename as "a directory move, not a row update". That was exercised
657+for real, renaming `jpgilldev` to `jamesgill` on the live instance: **one `UPDATE orgs SET
658+name` and one `mv` of `{data_dir}/{handle}/`**. Everything else — users, repositories,
659+tokens, sessions — keys off ids, so nothing else moved, and the account, password and
660+access token all survived.
661+
662+So a rename feature is genuinely two writes. What makes it more than that is the
663+consequence: every existing clone URL breaks, and there is no redirect from the old
664+handle. That is the part to design, not the mechanics.
665+
621666 ---
622667
623668 ## Reference: what attempt #2 proved