The subtree is in place, so everything that used to fetch and patch core at
build time now just copies it.
tools/build.sh copies wordpress/ — no download, no checksum step,
because there is nothing to fetch and nothing to
trust that is not already in the repository
docker/Dockerfile COPY wordpress/ instead of curl + sha256 + patch;
the build args and the `patch` package are gone
docker-compose.yml no WP_VERSION / WP_URL / WP_SHA256 to keep in step
tools/update-wordpress.sh is rewritten around what the subtree makes
possible. It imports the pristine release onto sirius-press/wordpress-upstream
and then `git subtree merge`s that branch, which three-way merges upstream
against the fork's own commit. A patch either applies with fuzz and hopes or
fails and leaves you re-deriving the change by hand; a merge conflict is
resolved once, in the file, and the next release merges against the
resolution.
patches/ survives as documentation rather than mechanism, and is now
generated: tools/refresh-patches.sh diffs the subtree against the pristine
import and rewrites the directory, with --check for CI. It answers the
question anyone auditing a fork asks first — what exactly did you change
inside WordPress? — in a minute, which `git log wordpress/` cannot, because
that log is mostly upstream imports. Generated documentation stays true; a
hand-maintained record of a core diff drifts, and a stale one is worse than
none because people trust it.
One test change worth noting: the syntax sweep no longer walks all of
wordpress/. It lints the fork's own PHP plus every core file patches/ says
the fork touches, which keeps the suite at seven seconds instead of a minute
while still covering the only core file that can break.
198 lines
8.2 KiB
Markdown
198 lines
8.2 KiB
Markdown
# Sirius Press
|
|
|
|
WordPress, with the mailbox taken out of the middle of it.
|
|
|
|
An account on a Sirius Press site is a Bitcoin Cash address. Signing in means
|
|
signing a challenge with the key that controls it. There is no registration
|
|
email, no confirmation link, no password reset — and no list of your readers'
|
|
email addresses sitting in a database waiting to leak.
|
|
|
|
Everything the site publishes is also mirrored, as plain static HTML, to the
|
|
BCNR name it belongs to. When the server is down, being upgraded, or seized,
|
|
the name keeps serving the last thing it published.
|
|
|
|
It is still WordPress. Yoast, WooCommerce, Contact Form 7 and the rest of the
|
|
ecosystem install and run; roles, capabilities, nonces and the REST API are
|
|
untouched. The fork's diff against upstream core is **one file, 75 lines** —
|
|
everything else is plugins.
|
|
|
|
---
|
|
|
|
## What this is for
|
|
|
|
You own a BCNR name. You want a real site behind it — one with an editor, a
|
|
media library, plugins, a theme you did not have to write — without the two
|
|
things WordPress assumes and this project rejects:
|
|
|
|
1. **That identity comes from email.** It does not. A mailbox is rented from
|
|
somebody who can close it, read it, or be compelled to hand it over. A key
|
|
is not.
|
|
2. **That the site lives at one server.** Sirius Press publishes a static copy
|
|
of every page to your name's storage on Sia, signed by the key that owns the
|
|
name. Readers reach that copy through any BCNR resolver, with no DNS and no
|
|
certificate authority in the path.
|
|
|
|
Email itself still works. `wp_mail()` is not disabled — configure SMTP and your
|
|
contact forms send, your WooCommerce receipts arrive. The objection was never
|
|
to email as a feature. It was to email as an identity.
|
|
|
|
---
|
|
|
|
## Getting it running
|
|
|
|
On a fresh Ubuntu 22.04 or 24.04 server:
|
|
|
|
```bash
|
|
curl -fsSL https://silentmode.st/sirius-press/install.sh | sudo bash
|
|
```
|
|
|
|
That installs Docker if needed, brings up MariaDB + PHP-FPM + nginx, and prints
|
|
the URL to finish setup. It takes about five minutes on a small VPS, most of it
|
|
building the PHP image.
|
|
|
|
For shared hosting, a `.zip` you can upload is on
|
|
[the releases page](https://code.silentmode.st/silentmode/sirius-press/releases).
|
|
|
|
Full instructions, including how to point your name at it:
|
|
**[docs/install.md](docs/install.md)**.
|
|
|
|
---
|
|
|
|
## How it works
|
|
|
|
### Signing in
|
|
|
|
The login page issues a short, single-use challenge. You sign it, the server
|
|
recovers the public key from the signature, derives the address, and looks up
|
|
the account. Nothing is typed but the signature.
|
|
|
|
Three ways to produce it, in order of preference:
|
|
|
|
- **A wallet the browser already has.** Theseus exposes one; the key never
|
|
touches the page.
|
|
- **A recovery phrase typed into the login form.** Used once, in the page, then
|
|
wiped. It is never transmitted — only the signature is.
|
|
- **Any Bitcoin Cash wallet at all.** The challenge is a BIP-137 message, the
|
|
format Electron Cash has had a "Sign message" box for since forever. Copy the
|
|
text, sign it on a machine that never touches the web, paste the result back.
|
|
This path works with JavaScript switched off.
|
|
|
|
The signature becomes an ordinary WordPress session cookie. Everything
|
|
downstream — `current_user_can()`, nonces, REST permissions, every plugin that
|
|
checks a capability — behaves exactly as it does on stock WordPress.
|
|
|
|
**There is no password reset, because there is nothing to reset.** If you lose
|
|
your phrase, the account is gone. An administrator can point an account at a
|
|
new address from the user editor, which makes recovery a decision a human
|
|
makes about a person they recognise — not something an attacker triggers by
|
|
compromising a mailbox. [docs/accounts.md](docs/accounts.md) says this at more
|
|
length, and the fork's "lost password" page says it to your users.
|
|
|
|
### Publishing
|
|
|
|
Publish a post and the affected pages — the post, the home page, the archives
|
|
it belongs to — are queued. Draining the queue renders each page over a
|
|
loopback request, rewrites its links to be document-relative, and PUTs it to
|
|
`/api/site/<name>/<path>` on the BNS gateway, signed by the key that owns the
|
|
name.
|
|
|
|
Signing happens one of two ways, and the choice is yours:
|
|
|
|
| | Where the key lives | Unattended publishing |
|
|
|---|---|---|
|
|
| **Manual** (default) | Nowhere. You type the phrase on the Publishing screen, it signs in your browser and uploads straight to the gateway. | No — the queue waits for you. |
|
|
| **Automatic** | Encrypted in the database, under `SIRIUS_PRESS_KEY` from `wp-config.php`. | Yes — cron drains the queue. |
|
|
|
|
Automatic is genuinely convenient and genuinely risky, and the settings screen
|
|
says so in those words. The gateway only accepts writes signed by the name's
|
|
current on-chain owner, so the key that can publish for your name is the key
|
|
that owns your name and its funds. There is no middle option where the server
|
|
holds something weaker; that is a property of the protocol, not a gap in this
|
|
fork. [docs/publishing.md](docs/publishing.md) has the details.
|
|
|
|
---
|
|
|
|
## Layout
|
|
|
|
```
|
|
plugins/
|
|
sirius-press-core/ wallet crypto, gateway client, settings, the inbox
|
|
sirius-press-auth/ wallet sign-in, registration, the recovery page
|
|
sirius-press-sia-export/ the static export queue and uploader
|
|
sirius-press-compat/ shims for plugins that insist on an admin email
|
|
mu-plugins/ the bits that must load before plugins do
|
|
wordpress/ WordPress itself, vendored as a subtree, patched
|
|
patches/ a generated record of the core diff — one file
|
|
docker/ compose stack: MariaDB, PHP-FPM, nginx
|
|
tools/ build, upstream update, release
|
|
tests/ 138 unit checks plus a live end-to-end suite
|
|
docs/
|
|
```
|
|
|
|
### Where WordPress itself is
|
|
|
|
In `wordpress/`, as a git subtree, already patched. That is what gets built
|
|
and what gets shipped — there is no download step and no checksum to trust at
|
|
build time.
|
|
|
|
Upstream releases arrive through `git subtree merge` against a branch of
|
|
pristine imports, which three-way merges them against the fork's own commit
|
|
on top. `tools/update-wordpress.sh <version>` does the whole thing;
|
|
`patches/` keeps a generated, readable record of the 75 lines that differ
|
|
from stock WordPress, so nobody has to read a 3,800-file log to find out what
|
|
this fork changes in core.
|
|
|
|
The trade is repository size — WordPress is about 149 MB. Worth it for a fork
|
|
that can absorb a security release in a minute.
|
|
[docs/upstream-merges.md](docs/upstream-merges.md) has the procedure.
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
- PHP 7.4+ — 8.2 or newer recommended
|
|
- **GMP or BCMath.** Not optional: the wallet cryptography runs in PHP. GMP is
|
|
about twenty times faster and is what the Docker image uses.
|
|
- 64-bit PHP — address checksums need 40-bit arithmetic
|
|
- OpenSSL, for encrypting a stored publishing key
|
|
- MySQL 5.7+ / MariaDB 10.4+
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
tests/run.sh # 138 checks, no framework, about a second
|
|
node tests/live.mjs # 40 more, against a running instance
|
|
```
|
|
|
|
The suite that matters most is `tests/interop.mjs`, which pins the browser
|
|
wallet against the PHP one. Both implement secp256k1, RFC 6979, BIP-32 and
|
|
BIP-137 independently, and every vector came from libauth — the library the
|
|
Sirius portal wallet and the BNS gateway both use. A signature made in a
|
|
browser verifies on the server and at the gateway, or the suite fails.
|
|
|
|
### What has actually been run
|
|
|
|
On WordPress 7.1.1, against a live instance:
|
|
|
|
- The patched setup wizard asks for a wallet and installs with or without one.
|
|
- Sign-in, registration, replay refusal, wrong-key refusal, altered-text
|
|
refusal and purpose separation — 40 checks, all through real HTTP with real
|
|
session cookies.
|
|
- Yoast SEO 28.6, Contact Form 7 6.1.7 and WooCommerce 11.1.1 install,
|
|
activate, and leave every Sirius Press screen rendering cleanly.
|
|
- Publishing: 29 files signed by the server and accepted by a gateway running
|
|
the real verification logic, read back intact, with a wrong key refused 403.
|
|
- An upstream version bump through `tools/update-wordpress.sh`, reapplying the
|
|
patch series.
|
|
|
|
Not yet run: `install.sh` on a clean Ubuntu box, and an upload to the real
|
|
gateway with a registered name. [docs/testing.md](docs/testing.md) says how to
|
|
do both and what each proves.
|
|
|
|
---
|
|
|
|
## Licence
|
|
|
|
GPL-2.0-or-later, inherited from WordPress.
|