Proving sdocs.dev is running the public code
SDocs renders Markdown files, and the Markdown files we or our agents produce contain some of the most sensitive information we have (about codebases, unresolved bugs, production logs, etc.). For this reason client-side focused privacy (privacy that leave our server as blind as can be) is an essential component of SDocs.
In public/sdocs-app.js (which your browser - not our server - compiles and runs) we handle the use of the url fragment for our 100% our client-side default links and the encryption and client-side decryption key isolation for our short-links. You can use SDocs confidently because all the computation touching the content of your Markdown files is done in your browser and not on our server (i.e. we cannot see the content of your files).
SDocs is open-source, which means anyone can inspect our code to prove it does what we say (another layer of trust). However that leaves one broken link in the chain: Just because our open-source code does what we say, it doesn't mean that the sdocs.dev website is actually serving that same code.
This page explains how we do our best to prove that it is.
How we demonstrate trust
Because our client-side (browser run) files are the only ones that touch your sensitive data, the main thing to prove, and only thing we (and you) can prove, is that the files your browser is receiving to serve our website match the publicly available ones in our GitHub repo.
Our proof works like this:
- Our GitHub repo has a publicly available list of commits for our
mainbranch: https://github.com/espressoplease/SDocs/commits/main - At each commit, the files that make up our code are in a particular state.
-
Any file (or string) can be run through a function called a hash function, which produces a fixed-length string of
characters. That string is the file's fingerprint. If the file changes in any way, even a single byte, the fingerprint
changes completely. The same file will always produce the same hash.
"hello world" -> b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 "hello world!" -> 7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9 "hello world" -> b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
- We have a custom GitHub Action (a script which runs on GitHub after a specified action) every time a commit is merged to our main branch. It goes through all of our
publicfiles (the files your browser receives when it renders sdocs.dev) and calculates their hashes using the SHA-256 hashing algorithm. - This data is saved on an isolated branch in the public SDocs codebase: https://github.com/espressoplease/SDocs/tree/trust-manifests
- For example, for commit
043623163f2bcd6b25eb2ff71f378e716b9552d3, the list of hashes looks like:{ "commit": "043623163f2bcd6b25eb2ff71f378e716b9552d3", "builtAt": "2026-04-19T07:15:35Z", "repo": "https://github.com/espressoplease/SDocs", "files": [ { "path": "/brotli_wasm_bg.wasm", "sha256": "9ef0a025046bf7d87b7cdb8eac3f73a5c8fea2f1adb848cc9768345573fcd8a9", "bytes": 1056860 }, { "path": "/brotli-wasm-v1.js", "sha256": "08b8126c78feff5b7a2a3349bd34fe6359b1829e2c1a59af59c1611e885882ae", "bytes": 14890 }, ... { "path": "/sdocs-app.js", "sha256": "1a4adf7845f201a51563ca76f127d3b647335d15b39ea4a14583bb7f7e1f4b2a", "bytes": 42229 }, ...See the exact list. - When you render a page at SDocs we send a custom
X-Sdocs-Commitheader which says which commit the sdocs.dev server is pointing too. For example, if the sdocs.dev server was pointing to043623163f2bcd6b25eb2ff71f378e716b9552d3, in the request headers section of the inspector you'd see:X-Sdocs-Commit 043623163f2bcd6b25eb2ff71f378e716b9552d3
- Every time we deploy to production, and every 10 minutes via a different GitHub action, we fetch the current code from sdocs.dev and compare the SHA-256 hashes from the code sdocs.dev returns, with the hashes from the corresponding commit in the public isolated branch discussed above. The final step of this second GitHub action is to update a publicly available JSON file hosted on GitHub with the latest trust status. You can read the latest status here: https://raw.githubusercontent.com/espressoplease/SDocs/trust-manifests/checks/latest.json
-
On success, this endpoint returns:
{ "checkedAt": "2026-04-19T07:03:45.361Z", "base": "https://sdocs.dev", "commit": "043623163f2bcd6b25eb2ff71f378e716b9552d3", "commitShort": "e158bea", "result": "ok", "totalFiles": 28, "matched": 28, "mismatches": [], "manifestUrl": "http://localhost:4099/fake/043623163f2bcd6b25eb2ff71f378e716b9552d3.json" }And on failure it returns:{ "checkedAt": "2026-04-19T08:14:34.140Z", "base": "https://sdocs.dev", "result": "error", "error": "Could not read /trust/manifest from server: HTTP 404 for https://sdocs.dev/trust/manifest" } -
The status returned by this JSON file powers the result and timestamp in the footer. E.g.
✓ verified 5m agowould correspond to a successful run five minutes ago.
You can also run the check here yourself (this will not update the timestamp):
Or paste this code into the console on a sdoc.dev page rendering one of your Markdown files:
(async () => {
const srv = await fetch('/trust/manifest').then(r => r.json());
const url = 'https://raw.githubusercontent.com/espressoplease/SDocs'
+ '/trust-manifests/' + srv.commit + '.json';
const gh = await fetch(url).then(r => r.json());
const hex = b => [...new Uint8Array(b)].map(x => x.toString(16).padStart(2, '0')).join('');
let ok = 0, fail = 0;
for (const f of gh.files) {
const buf = await fetch('/public' + f.path).then(r => r.arrayBuffer());
const got = hex(await crypto.subtle.digest('SHA-256', buf));
const pass = got === f.sha256;
console.log((pass ? '\u2713' : '\u2717') + ' ' + f.path);
pass ? ok++ : fail++;
}
console.log(ok + '/' + (ok + fail) + ' match, commit ' + srv.commit.slice(0, 7));
})();
You will see a tick or a cross logged per frontend file and a final line with the pass count and the short commit hash the server reported. The fetches happen from whichever origin you're currently on, so the script verifies this page's bytes, not the /trust page's.