SHA256 and MANIFEST.json Cold-Validation Drill Before Partner Upload - Q3 2026
You fixed partner ZIP naming and your README bullet map finally points at real folders. Q3 2026 intake still returns yellow on dimension two when SHA256SUMS.txt lists a Windows binary your MANIFEST.json calls game.exe but the zip root ships Riftbound.exe, or when your Asia-EU BUILD_RECEIPT cites commit a1b2c3d while the hashed file was built from f4e5d6c.
That failure mode is not cryptography—it is cold validation. Reviewers re-hash on machines that never saw your dev drive. This Process & Workflow guide gives micro-studios a sixty-minute drill for SHA256 sidecars, a minimal MANIFEST.json schema, and receipt parity before you score the seven-dimension mock audit.
Why this matters now (May 2026)
- Portal re-uploads strip metadata — macOS resource forks and cloud-sync conflict copies change bytes without changing your README version string.
- Overnight CI greens lie — A green pipeline on a build agent is not the same artifact you zip by hand at 2 a.m.; handoff receipts exist to catch that gap.
- AI disclosure annexes multiply files — Seven-day disclosure challenges add PDFs and CSV rows that must appear in both hash lists and manifest paths.
- Two-storefront teams duplicate hashes — Under the two-storefront rule, Steam and secondary SKUs need separate manifest roots, not one
SHA256SUMS.txtthat silently omits the Epic build.
Who this is for and what you get
| Audience | You will be able to… |
|---|---|
| Solo dev on first partner packet | Generate SHA256 sidecars and a manifest a reviewer can replay |
| Tech lead with contractors | Require cold validation before anyone uploads to a portal |
| Producer running Friday Block 5 | Add a hash spot-check without expanding ritual past fifteen minutes |
Time: sixty minutes for the first drill; ten minutes on every upload after templates exist.
Prerequisites: A frozen build folder under your release-evidence taxonomy, a second computer or VM, and shell access to sha256sum or PowerShell Get-FileHash.
The failure mode partners actually cite
Partners rarely write “your hash was wrong.” They write:
- “Checksum file does not include all attachments.”
- “Manifest references build not present in archive.”
- “Hash mismatch on resubmission without version bump.”
- “Receipt metadata inconsistent with packaged binary.”
Each maps to a repeatable drill—not a new engine feature.
Cold validation defined
Cold validation means:
- Copy the zip to hardware that did not compile the game.
- Unpack to a clean directory (not your git workspace).
- Recompute hashes from unpacked bytes only.
- Parse
MANIFEST.jsonandBUILD_RECEIPT.jsonwithout opening your issue tracker. - Compare results to
SHA256SUMS.txtand README bullets in that order.
If step five fails, you do not upload. You fix naming or bytes, bump build_id, and re-run.
Sixty-minute drill overview
| Block | Minutes | Output |
|---|---|---|
| A — Freeze file list | 10 | files_to_hash.txt from 01_build/ only |
| B — Write SHA256SUMS | 15 | One line per file, relative paths |
| C — Author MANIFEST.json | 15 | Schema below, matches sums file |
| D — Align BUILD_RECEIPT | 10 | Commit, agent, UTC time, manifest version |
| E — Cold machine replay | 10 | Pass/fail log in 05-operations/ |
Stop at first mismatch. Do not “fix forward” in the portal UI.
Block A — Freeze the file list
Before hashing, list every file partners can execute or open as evidence:
release-evidence/01-build/
game/
symbols/ (optional separate zip later)
steam_appid.txt (if PC Steam build)
known_issues.md
Rules:
- Hash bytes on disk, not git blobs.
- Exclude
.DS_Store,Thumbs.db, and editor swap files—add them to.hashignoreif your OS insists on creating them. - If you ship a separate demo zip, it gets its own
SHA256SUMS.txt—never merge unrelated artifacts.
Export the list:
# Git Bash / Linux / macOS — from 01_build/game/
find . -type f ! -path '*/\.*' | sort > ../../files_to_hash.txt
# Windows PowerShell — from 01_build\game\
Get-ChildItem -Recurse -File |
Where-Object { $_.FullName -notmatch '\\\.' } |
ForEach-Object { $_.FullName.Substring($pwd.Path.Length + 1).Replace('\','/') } |
Sort-Object | Set-Content ..\..\files_to_hash.txt
Success check: two teammates produce identical files_to_hash.txt from the same frozen folder.
Block B — SHA256SUMS.txt format
Use GNU coreutils style unless your partner portal specifies otherwise:
<64-char-lowercase-hex> <relative/path/with/forward/slashes>
Generate:
cd release-evidence/01-build/game
sha256sum $(cat ../../files_to_hash.txt) > ../../SHA256SUMS.txt
Windows without WSL:
cd release-evidence\01-build\game
$lines = Get-Content ..\..\files_to_hash.txt
$out = foreach ($rel in $lines) {
$h = (Get-FileHash -Algorithm SHA256 $rel).Hash.ToLower()
"$h $rel"
}
$out | Set-Content ..\..\SHA256SUMS.txt
Common mistakes:
| Mistake | Symptom | Fix |
|---|---|---|
| Absolute paths in sums | Reviewer hash fails on their drive | Strip to zip-relative paths |
| CRLF vs LF only in text files | Hash drift across OS | Normalize or hash after dos2unix on text manifests |
| Hashing before copy completes | Random mismatch | Wait for sync; verify file size stable |
| Uppercase hex | Parser rejects | Lowercase only |
Block C — MANIFEST.json minimal schema
Keep the manifest boring. Partners parse JSON; they do not want your game design doc.
{
"manifest_version": "1.0",
"build_id": "riftbound_win_20260518_a1b2c3d",
"platform": "win64",
"channel": "steam",
"primary_executable": "Riftbound.exe",
"files": [
{ "path": "Riftbound.exe", "sha256": "abc...def", "role": "game_binary" },
{ "path": "steam_appid.txt", "sha256": "...", "role": "store_metadata" }
],
"hash_sidecar": "SHA256SUMS.txt",
"readme_version": "1.2"
}
Field rules:
build_idmust match your ZIP naming contract.primary_executablemust match README bullet 1 wording.- Every
files[].sha256must equal the line inSHA256SUMS.txtfor the samepath. hash_sidecaris always the filename at zip root—not a subfolder path.
Validate locally:
python3 -c "
import json, hashlib, pathlib
m = json.load(open('MANIFEST.json'))
sums = dict(line.split(None,1) for line in open('SHA256SUMS.txt') if line.strip())
for f in m['files']:
assert sums[f['path']] == f['sha256'], f['path']
print('manifest ok')
"
If you lack Python on the cold machine, use jq plus a twenty-line shell loop—portability beats elegance.
Block D — BUILD_RECEIPT.json alignment
Pair the manifest with a receipt your overnight handoff can audit:
{
"receipt_version": "1.0",
"build_id": "riftbound_win_20260518_a1b2c3d",
"git_commit": "a1b2c3d4e5f6789012345678901234567890abcd",
"ci_job_url": "https://your-ci.example/job/12345",
"built_at_utc": "2026-05-18T14:22:00Z",
"agent": "win-builder-02",
"manifest_sha256": "placeholder_recomputed_after_manifest_write"
}
After you finalize MANIFEST.json, hash it and store that digest in manifest_sha256. The receipt proves which manifest belonged to which CI job—not which marketing slide deck.
Freeze carve-out rule: If you cherry-pick a hotfix into 01_build/ after the receipt was written, increment build_id and regenerate both manifest and sums. Editing in place without a version bump is the fastest way to fail a resubmission diff.
Block E — Cold machine replay script
On the second machine:
- Download or copy the zip via USB—avoid “same folder” cloud sync shortcuts.
unziporExpand-ArchivetoC:\cold-verify\or/tmp/cold-verify/.- Re-run hash generation into
SHA256SUMS.recomputed.txt. diff SHA256SUMS.txt SHA256SUMS.recomputed.txt— output must be empty.- Open
PARTNER_README.mdand click mentally through each bullet path. - Log result in
release-evidence/05-operations/cold_validation_log.csv:
date_utc,build_id,validator_machine,result,notes
2026-05-18T15:00:00Z,riftbound_win_20260518_a1b2c3d,laptop-kitchen,pass,
A fail row with notes beats a silent re-upload.
Pairing with the mock audit tabletop
Map this drill to mock audit dimensions:
| Dimension | What cold validation proves |
|---|---|
| Artifact parity | README, manifest, and bytes agree |
| Build integrity | Hashes cover every executable and annex |
| Ops traceability | BUILD_RECEIPT ties CI to packaged folder |
| AI disclosure | Annex files hashaed and listed under 04_ai/ |
Score yourself: pass only if block E completed on a machine that did not produce the build.
macOS and Linux partner packets
When platform is macos or linux:
- Include
.appbundles as directories—hash each file inside, not the bundle folder as opaque blob unless partners instruct otherwise. - Note quarantine attributes:
xattr -crbefore hashing if you distribute outside App Store notarization workflows. - For Linux, record
glibcor Steam Runtime expectation inKNOWN_ISSUES.md, not in manifest JSON—manifest is for files, not runtime essays.
Symbols and split zips
Large teams ship _symbols.zip separately. Rules:
- Separate
SHA256SUMS.txtper zip. MANIFEST.jsonin the gameplay zip references only files inside that zip.- README bullet 6 names the symbols zip explicitly—see partner naming standard.
Never hash symbols into the gameplay manifest “to save time.”
AI and legal annex hashing
When Steam and Play disclosure adds PDFs:
04_ai/disclosure_matrix.csv
04_ai/tool_attestation.pdf
Each must appear in files_to_hash.txt. If bullet 4 says “see 04_ai/,” cold validation without those files is a self-inflicted red flag.
Integration with Friday Block 5
You do not need a new ritual—extend Friday Block 5 with one line:
- “Spot-check: re-hash
01_build/game/Riftbound.exevsSHA256SUMS.txtline 1.”
If the spot-check fails, Block 5 becomes “fix hashes before any store marketing work.”
Save-game and demo annexes
If you ship a fest demo with save fuzz testing evidence, hash the repro save and the fixed build together only when they live in the same zip. Otherwise split manifests—reviewers treat cross-zip hash claims as broken.
Resubmission hash discipline
When partners request a resubmission:
- Never edit
SHA256SUMS.txtin place on the portal copy—regenerate from bytes. - Append a row to
cold_validation_log.csvwithresult=resubmit. - Add
RESUBMISSION_NOTE.mdat zip root per partner naming guide. - Bump
readme_versionwhen folder names change—even if gameplay bytes are identical.
Partners diff archives. Identical hashes with renamed folders still fail human review.
Security notes (practical, not paranoia)
- SHA256 proves integrity against accidental corruption, not attacker resistance. Still ship HTTPS downloads and signed CI artifacts where available.
- Do not paste secret keys, Steam partner tokens, or API keys into
MANIFEST.json—those belong in vaults, not partner zips. - If you must include credentials for a private beta, use portal-side fields—not README bullets.
Tooling that helps (all optional)
| Tool | Role |
|---|---|
sha256sum / Get-FileHash |
Canonical digest |
jq |
Manifest spot checks |
rsync --checksum |
Detect drift before zipping |
7z t |
Test zip integrity pre-upload |
| Your CI artifact store | Source of truth for BUILD_RECEIPT |
None replace cold machine replay.
Beginner quick start
Never hashed a build before?
- Pick one
.exeor binary. - Run
sha256sum Riftbound.exe(or PowerShell equivalent). - Paste the line into
SHA256SUMS.txt. - Copy the hex into one
MANIFEST.jsonfile entry. - Email the file to yourself, download on your phone’s hotspot laptop, re-hash.
Success check: the hex matches on the second device.
Common mistakes to avoid
- Hashing the zip instead of contents — Partners unpack first.
- Manifest lists files you removed from disk — Stale JSON is worse than no JSON.
- BUILD_RECEIPT from a different branch — Receipt must match the commit that produced bytes.
- Skipping annex PDFs — If README mentions them, hash them.
- Trusting IDE “upload” plugins — Re-hash what the plugin actually sent.
Pro tips for micro-studios
- Store templates in
release-evidence/templates/—copy, don’t reinvent paths weekly. - Pin
manifest_versionuntil partners request a schema change. - Teach artists to drop finals only into numbered folders—hash drift often starts with “quickDesktop/export.exe.”
- Pair this drill with operating review Block 3 so hashes do not rot between Fridays.
Worked example — win64 Steam packet (fictional layout)
Imagine a micro-studio ships northlake_riftbound_steam_a1b2c3d_cert_20260518.zip with this root:
PARTNER_README.md
SHA256SUMS.txt
MANIFEST.json
BUILD_RECEIPT.json
01_build/game/Riftbound.exe
01_build/game/steam_appid.txt
01_build/game/known_issues.md
04_ai/disclosure_matrix.csv
05_ops/upload_log.csv
Step 1 — Freeze: From 01_build/game/, files_to_hash.txt lists three paths (exe, appid, known_issues). Annex 04_ai/disclosure_matrix.csv is hashed separately because README bullet 4 names that folder.
Step 2 — Sums: SHA256SUMS.txt contains four lines—game trio plus CSV. No line uses C:\ prefixes.
Step 3 — Manifest: primary_executable is Riftbound.exe. Each files[].path matches a sums line. channel is steam.
Step 4 — Receipt: git_commit matches the tag your CI job built. manifest_sha256 is the digest of MANIFEST.json after save—recomputed, not copied from an old upload.
Step 5 — Cold: A producer laptop unpacks the zip, reruns PowerShell Get-FileHash, diffs sums, and logs pass in cold_validation_log.csv.
If bullet 2 in README said 01_build/Riftbound.exe but the file lives under 01_build/game/, cold validation fails before portal upload—exactly the cheap failure you want.
RC freeze and hash regeneration
During RC freeze challenges or any carve-out that touches binaries:
| Carve-out type | Hash action |
|---|---|
Copy-only marketing video in 03_media/ |
No gameplay hash regen if 01_build/ untouched |
Hotfix .exe in 01_build/ |
Full regen of sums + manifest + receipt |
| AI disclosure CSV row add | Hash new CSV; bump readme_version |
| README typo only | Bump readme_version; hashes may stay if bytes unchanged |
Document carve-outs in FREEZE_CARVEOUT.md at zip root when partners ask why build_id jumped without a gameplay headline change. Silence reads as hiding churn.
Portal upload vs local zip parity
Some portals recompress or virus-scan uploads. Mitigations:
- Self-download after upload when the portal allows—re-hash downloaded bytes.
- Record portal file size and etag in
upload_log.csv. - If self-download hash fails, open a ticket before reviewers do.
Never assume “upload succeeded” equals “bytes arrived intact.”
Cross-platform hash gotchas (expanded)
Windows:
- Antivirus may quarantine your own
.exeon the cold machine—whitelist the verify folder or hashes will false-fail. - Code signing changes file size but not necessarily hash if you sign before hashing—pick one order and document it in
KNOWN_ISSUES.md.
macOS:
- Gatekeeper quarantine extended attributes change perceived “file identity” for support staff even when SHA256 matches—note
xattrcleanup in internal runbooks, not partner README unless required.
Linux:
- AppImage mounts are not the same as extracted payloads—hash the payload you actually upload.
Parser-friendly MANIFEST.json hygiene
Partners sometimes machine-parse JSON:
- No trailing commas.
- UTF-8 without BOM.
- Keep keys stable—add new keys at the end of objects.
- Use
roleenums you document once:game_binary,store_metadata,disclosure,ops_log.
If you automate manifest generation in CI, pin the generator version in BUILD_RECEIPT.json as manifest_generator: "hash-manifest-v2".
Teaching contractors without leaking authority
Contractors should:
- Drop files only into assigned numbered folders.
- Never edit
SHA256SUMS.txtorMANIFEST.json. - Attach a
CONTRACTOR_DROP_NOTE.mdwith UTC timestamp when they add bytes.
Your designated release owner runs blocks B–E. That separation prevents “helpful” hash edits that desync receipts.
Linking to publisher diligence
Publisher diligence packets often request the same integrity story as platform cert. Reuse one manifest schema for both—do not maintain MANIFEST_publisher.json and MANIFEST_platform.json unless contracts explicitly diverge. Dual schemas drift within a week.
Instrumentation without overbuilding
You do not need a custom dashboard on day one. A CSV log plus weekly review during operating review is enough:
week,uploads,cold_pass,cold_fail,resubmit_after_fail
2026-W20,1,1,0,0
When cold_fail rises, audit whether overnight CI or manual zips caused the drift—not whether your hash algorithm is “wrong.”
When to escalate
Escalate to counsel or platform support when:
- Partners require code signing attestations beyond SHA256.
- Console SKUs need proprietary manifest formats—this post is PC-first.
- You discover tampering—hashes mismatch on cold machine and CI artifact.
Do not band-aid with a README apology.
Key takeaways
- Q3 2026 partner intake treats hash ↔ manifest ↔ README parity as table stakes.
- Cold validation always happens on a second machine that did not build the game.
SHA256SUMS.txtuses lowercase hex and zip-relative forward-slash paths.MANIFEST.jsonstays minimal—executables, roles, and matching digests only.BUILD_RECEIPT.jsonties CI commit and UTC time to the manifest you ship.- Any freeze carve-out that touches
01_build/forcesbuild_idand hash regeneration. - Log every drill in
05-operations/cold_validation_log.csv. - Pair this drill with ZIP naming and the mock audit tabletop before portal upload.
FAQ
Is SHA256 enough for partner cert?
For integrity checks on attached binaries, usually yes. Signing and notarization are separate gates—ask your platform contact when contracts require them.
Can we use MD5 for smaller files?
No. Use SHA256 end-to-end so parsers do not split algorithms.
What if our game has thousands of small files?
Hash every file partners receive. If the list is huge, split artifacts (game vs symbols) rather than sampling.
How does this relate to the Q3 resource templates?
The Q3 submission intake resource roundup supplies folder skeletons; this post is the replayable hash behavior those folders need.
Should contractors run cold validation?
They deliver into numbered folders. One designated human runs blocks B–E so receipts stay authoritative.
What about encrypted or DRM-wrapped builds?
Hash the bytes you upload. If DRM wraps post-upload, document that in KNOWN_ISSUES.md—do not claim hashes cover portal-transformed bytes you never possessed.
Does manifest replace Steam depot manifests?
No. Steam depot metadata lives in Steamworks. This MANIFEST.json is for partner evidence zips aligned with your internal taxonomy.
How often should we rerun the full cold drill?
Before every partner upload and within twenty-four hours of any 01_build/ byte change. Spot-checks on Fridays are enough only when no upload is planned that week.
Can we automate cold validation in CI?
Yes—run the same hash commands on the CI artifact, then still replay once on a laptop that is not the build agent. CI proves repeatability; cold machine proves portability.
Next step after this drill
Schedule the mock audit tabletop the same week you pass cold validation. Dimension scores mean little if hashes were never replayed outside the pipeline that produced them. Bookmark this post beside your partner ZIP naming standard template folder so upload night stays a checklist—not a debate.
Conclusion
SHA256 sidecars and a cold MANIFEST.json drill are how you prove the build in the zip is the build you tested—not the build you meant to zip after coffee. Q3 2026 windows will not wait while you re-learn hashing on a resubmission thread.
Run the sixty-minute drill once this week, log the cold machine result beside your release-evidence tree, and reuse the templates on every upload. Partners will still find gameplay bugs—but they will stop finding that your checksum file describes a game that is not in the archive.