Designing a Blog Publisher That Can Prove What It Shipped
Designing a Blog Publisher That Can Prove What It Shipped
Unattended publishing looks simple until the requirement changes from “send some content” to “publish exactly this reviewed content, and prove that the intended page is live.” That second version is an engineering problem. It needs bounded inputs, explicit evidence, deterministic processing, and a recovery path for failures that happen after a database write.
This week, BlueDot built and hardened a weekly blog publication pipeline around those constraints. The useful lesson is broader than blogging: any automation that changes public state should be able to identify its inputs, verify its exact output, and stop cleanly when the proof is incomplete.
Start with an evidence packet
The pipeline does not treat a draft as sufficient authority to publish. Each run begins with a source packet that names the publication slot, date, canonical URL, article path, claims, uncertainties, and source artifacts. Every artifact is paired with a lowercase SHA-256 digest.
That structure creates a narrow chain of custody. The article can be traced to a dated packet, and the packet can be traced to immutable evidence files. It also makes missing evidence a normal stop condition. If there is not enough verified work for a useful article, the correct output is no publication.
This is a practical pattern for other automations. A deployment summary, compliance report, or customer-facing status update should not be assembled from ambient context. Give the run a bounded packet that says what it may claim and where the supporting evidence lives.
Rebuild before mutation
Staging validates the packet, reads the article, checks artifact hashes, derives the slug from the official canonical URL, and writes a staged representation. Publication then receives the same original packet and article paths. Before touching the database, it rebuilds the staged object and requires a byte-for-byte match.
That second build closes an important gap. Without it, someone—or simply another process—could alter the article after review while leaving the staged file unchanged. Requiring the original inputs at publish time turns staging into a reproducible build rather than a loose handoff.
The canonical URL is constrained too. It must use HTTPS on the official BlueDot domain, point beneath the blog path, and contain a safe slug without query parameters or fragments. The publisher does not get to improvise its destination.
Verify the exact page, not merely a 200
A successful write is not proof that readers can see the intended article. Caches, routing errors, stale application processes, and redirects can all produce misleading success signals.
The hardened verifier requests the exact canonical URL without following redirects. It requires a successful response from the expected origin and path, then searches the returned page for a marker derived from the source packet ID and combined source hash. A generic healthy homepage, stale article, redirect, or unrelated 200 response cannot satisfy that check.
This distinction matters anywhere automation crosses a delivery boundary. “The API accepted the mutation” and “the intended public artifact is observable” are different claims. Verification should test the second one.
Treat partial success as failure
The most dangerous moment is after the post has been written but before verification and receipts are complete. The pipeline handles that interval with compensating rollback. If exact-page verification fails, or either durable receipt cannot be written, it restores the previous post state—or deletes a newly created post—and clears the incomplete run records.
If cleanup itself fails, the run reports that reconciliation is required. It does not label the publication successful or hand the content to another channel.
Retries also reuse identical inputs. The post is upserted by slug, while the run record is keyed by its source packet ID. That makes a bounded retry idempotent instead of creating duplicate posts or inventing a new chain of evidence midway through recovery.
Test the failure paths
The repository tests cover more than the happy path. They check invalid canonical destinations, unhashed artifacts, unsafe slugs, short content, redirects, stale pages without the publication marker, changed staged fields, receipt failures, rollback ordering, and cleanup failures. The full test run completed with 20 passing tests and no failures before this publication run.
Tests do not eliminate operational uncertainty, but they make the contract executable. The important behaviors are no longer comments that operators must remember; they are conditions the publisher enforces.
The operational rule
Reliable automation should leave behind enough evidence to answer four questions:
- What exact inputs authorized this change?
- Did the system publish those inputs without substitution?
- Is the intended artifact observable at the exact destination?
- If anything failed, was public state restored or clearly marked for reconciliation?
If a pipeline cannot answer those questions, it is still relying on hope at the boundary. Hope is cheap. Receipts are better.