sirius-press/docs/upstream-merges.md

134 lines
4.2 KiB
Markdown
Raw Normal View History

feat(sirius-press): a WordPress where the account is a key, not a mailbox WordPress makes two assumptions this project cannot accept: that identity comes from an email address, and that a site lives at one server. Both are things somebody else can take away — a mailbox is rented from a provider who can close it or be compelled to open it, and a server is one seizure from being gone. Sirius Press replaces the first and hedges the second. Signing in means signing a challenge with the key that controls a CashAddress. The address is recovered from the signature, so nothing is typed but the signature itself, and the result is an ordinary WordPress session cookie — roles, capabilities, nonces and the REST API never learn the login was different. Three ways to produce one: a wallet the browser already exposes, a phrase used once in the page and wiped, or a signature pasted in from any BIP-137 wallet, which needs no JavaScript and lets the key stay on a machine that never touches the web. There is no password reset, and the recovery page says so plainly rather than offering a form that cannot work. A reset mechanism is by construction a way to take an account from its owner, and it is always easier to attack than the cryptography it bypasses. Publishing a post also exports it as static HTML to the name's storage on Sia, signed by the key that owns the name, so the site keeps answering when the server does not. Email as a feature is untouched. wp_mail() still works, SMTP still sends, and contact forms still deliver to addresses real people typed. Only mail to the site's own unroutable placeholder addresses is diverted to an in-app inbox. The objection was to email as identity, not to email. Core is pinned and patched rather than vendored. WordPress 7.1.1 is 149 MB and 5,008 files; the fork's entire core diff is 75 lines in wp-admin/install.php. Carrying the former to express the latter would bury the patch where nobody reviews it and make every clone of the monorepo pay for it. Upstream releases still merge through tools/update-wordpress.sh, which reapplies the series and says exactly which hunk needs a human. The cryptography is implemented twice — PHP on the server, JavaScript in the page — because the server must verify and the browser must sign. Both are pinned against libauth, the library the Sirius portal wallet and the BNS gateway already use, so a disagreement of one byte fails the test suite rather than presenting as a rejected login at three in the morning. 132 checks, no framework, about a second.
2026-09-21 01:39:38 +02:00
# Keeping up with WordPress
WordPress ships security releases, and a fork that cannot take them quickly is
a liability rather than a project. This page is how Sirius Press takes them.
---
## The arrangement
WordPress is not in this repository. Instead:
- `tools/wordpress.lock` pins an exact version, its download URL and its
SHA-256.
- `patches/` holds the fork's core diff as a patch series.
- `tools/build.sh` and the Docker image each download the pinned tarball,
verify the hash, and apply the series.
The entire core diff is currently **one file, 75 lines**: the setup wizard, at
`wp-admin/install.php`. Everything else the fork does is plugins and hooks.
### Why not a vendored subtree
The original plan was to vendor core as a `git subtree`, which is the standard
way to run a fork with a substantial diff. Two numbers argued against it.
WordPress 7.1.1 is **149 MB and 5,008 files**. The fork's core diff is **75
lines**. Carrying the first to express the second means every clone, every
`git status`, every `git subtree split` in the parent monorepo pays for a patch
you can read in a minute — and it buries that patch in a haystack where nobody
will ever review it again.
A patch series makes the opposite trade. The core change is a file you can read
in one sitting, review in a pull request, and re-read whenever it stops
applying. The cost is that upstream merges are `patch` rather than a three-way
git merge — which, for 75 lines in one file, is not much of a cost.
This holds as long as the diff stays small. If the fork ever needs to change
core substantially, vendor it properly: see "Switching to a subtree" below.
---
## Taking a new release
```bash
tools/update-wordpress.sh 7.1.2
```
It fetches the release, verifies its SHA-1 against what wordpress.org
publishes, records a SHA-256, applies the patch series to the new tree, and
reports what happened.
Three possible outcomes:
**Clean.** The series applied. `tools/wordpress.lock` is updated, the tests
run, and you commit the lock change. Usually thirty seconds of work.
**Applied with fuzz.** Upstream moved code near a hunk but not the hunk itself.
The script says which hunk and by how many lines. Look at the result, then
refresh the series so the next release starts from a clean base:
```bash
tools/update-wordpress.sh 7.1.2 --refresh
```
**Failed.** Upstream rewrote the code the patch touches. This is the case that
needs a person: open the new `wp-admin/install.php`, redo the change by hand,
and regenerate the patch. The script leaves the unpacked tree in
`dist/.upstream/` so there is something to work in.
In every case the fork is **not broken while you work** — the lock file still
points at the last known-good version, and builds keep producing that until you
change it.
---
## Reviewing a release before taking it
Security releases are usually small, and it is worth knowing what changed near
the code the fork patches:
```bash
tools/update-wordpress.sh 7.1.2 --diff wp-admin/install.php
```
prints upstream's own diff for that file between the pinned version and the new
one. If it is empty — which it usually is — the patch will apply and there is
nothing to think about.
---
## After any bump
```bash
tests/run.sh
```
The suite does not test core, but it does test every assumption the fork makes
about it. Then build and try an actual install:
```bash
tools/build.sh
cd docker && docker compose build && docker compose up -d
```
and walk through `wp-admin/install.php` once. The setup wizard is the only
patched file, so it is the only thing an upstream change can break in a way
the tests would miss.
---
## Switching to a subtree
If the diff ever grows past what a patch series is comfortable with, the
mechanics are:
```bash
git remote add wordpress https://github.com/WordPress/WordPress.git
git fetch --depth=1 wordpress 7.1.1
git subtree add --prefix=wordpress FETCH_HEAD --squash
```
and then, per release:
```bash
git fetch --depth=1 wordpress 7.1.2
git subtree merge --prefix=wordpress FETCH_HEAD --squash
```
with `patches/` becoming the record of what was changed rather than the
mechanism that changes it. The build script would then copy `wordpress/`
instead of downloading and patching.
Worth doing when the core diff reaches, say, a dozen files. Not before.