FireUX · 3 min

Safe Publishing Must Hash Content, Not Filenames

A reliable publishing plan verifies exact text and image bytes, then uses content-derived image URLs to prevent stale immutable caches.

Safe Publishing Must Hash Content, Not Filenames

Safe Publishing Must Hash Content, Not Filenames

A publishing workflow can display the right filename and still publish the wrong file.

We encountered this while building a reviewed path from local Markdown into the FireUX Blog. The workflow already produced a plan before writing, required explicit approvals and verified the stored post afterwards. But an image filename alone did not identify the exact image being approved.

If the bytes changed while the path stayed the same, the plan needed to change too.

A plan should describe the exact mutation

A useful publication plan includes the target, operation, title, slug, source file and editorial findings. For media, it should also include a cryptographic hash of the exact bytes.

The confirmation hash can then be derived from the complete plan. Editing the article, replacing the image or changing the intended operation produces a different confirmation value. Approval applies to one exact mutation rather than a vague intention to “publish this file.”

This matters most in automated or agent-assisted workflows, where planning and applying may happen in separate steps.

Immutable caching creates a second problem

Long-lived immutable caching is excellent for performance, but only when a changed asset receives a changed URL.

Uploading new bytes to the same path while retaining the same public token can leave browsers and content networks serving the old image. The database may point to a technically valid URL, yet readers still see stale artwork.

A content-derived token solves this cleanly. When the bytes change, the hash changes, the public URL changes and caches fetch the new asset. Unchanged content keeps the stable URL and retains the caching benefit.

Safe publication is more than upload success

Our workflow now separates several decisions:

  1. Create by default; require an explicit mode to update an existing post.
  2. Plan without writing.
  3. Review privacy, factual claims and remaining names.
  4. Hash the exact article plan and image bytes.
  5. Apply only with the matching confirmation.
  6. Verify the public record after the mutation.

Each step answers a different question: Is this new or existing? What will change? Is it safe to publish? Is this the exact reviewed input? Did storage end in the expected state?

What we do at FireUX

FireUX treats the local publisher as a transport into the Blog-owned contract, not as independent publication authority. It has a fixed project and database, uses typed mutation targets, rejects unexpected record state and verifies each published record.

The broader lesson is simple: a filename is a location, not an identity. When an approval or cache depends on exact content, hash the content.

For the editorial half of the process, read how to turn a daily brief into a valuable blog post.