SDK Delivery & SRI
Two different SDKs reach your game, and both are integrity-pinned:
- The build-time platform package — the npm tarball your game project
npm installs. It providesgame-kit,iframe-sdk, the bundler, and the validators. - The runtime bridge SDK —
sdk-v1.<hash>.js(~22 KB), loaded by your exported bundle cross-origin at run time, pinned by Subresource Integrity (SRI). You do not vendor it; the export pins its hash and the host injects the origin.
Almost every "my game white-screens" or "npm install fails with
EINTEGRITY" report traces back to one of the pins below disagreeing with
the bytes it points at.
1. The runtime SDK: hashed, immutable, per release
Each SDK release is published as a content-addressed, immutable file:
sdk-v<MAJOR>.<sri8>.js e.g. sdk-v1.9OMyC9x6.js
<sri8> is the first 8 alphanumeric characters of the artifact's base64
sha384 SRI digest — the filename is a function of the bytes, so the bytes
under a hashed name can never change. Old hashed files stay live on the
origin forever: a game that pinned sdk-v1.9OMyC9x6.js keeps loading
exactly those bytes after later SDK releases ship alongside it. Releases
coexist; nothing is clobbered.
Two supporting objects:
sdk-manifest.json— the one mutable, short-TTL pointer. Itsfilefield names the current release's hashed file;majorandintegrityidentify it. The export/preflight tooling reads it; it is never SRI-pinned itself.- Legacy
sdk-v1.js— the unhashed transitional name, still served for already-published games. Its bytes move on each release, which is exactly the clobber the hashed scheme retires; new builds pin the hashed path.
Your exported bundle's loader carries the pinned path + SRI:
<script src="<origin>/sdk/sdk-v1.<sri8>.js" integrity="sha384-…" crossorigin="anonymous"></script>
The <origin> is never baked into your bundle — the host injects it via a
query parameter on your iframe URL. Only the path, integrity, and global are
pinned at export.
2. The three places that must agree
A cloud-delivered game project pins the platform in three files, and all three must describe the same bytes:
| Where | What it pins |
|---|---|
package.json |
the bodylink-platform dependency spec — the hosted tarball URL (…/bodylink-platform-<version>.tgz) |
package-lock.json |
npm's resolved URL and integrity hash for that tarball, captured at install time |
bodylink.cloud.json |
the verified hosted-SDK identity: tarballUrl, sdkOrigin, sdkMajor, sdkPath (the hashed runtime file), sdkIntegrity, runtimeRange |
How they drift, and what it looks like:
package.jsonURL vspackage-lock.json— if the tarball behind the URL is ever republished with different bytes (or you hand-edit the URL to a new version without reinstalling),npm install/npm cifails withEINTEGRITY. Fix: update the dependency spec, delete the stale lock entry (or the lock), and reinstall soresolved+integrityare recaptured together.bodylink.cloud.jsonvs the hosted SDK — the export preflight fetches the hostedsdk-manifest.jsonand hard-fails on skew: the locally-built SDK's SRI must equal the hosted manifest's, the hosted major must equal the local major, and yourruntimeRangemust include it. A skew failure before zipping is the system working — never override it.
3. What an SRI mismatch means
An SRI mismatch — the browser refusing the SDK <script>, or the preflight
reporting integrity skew — means exactly one thing: the bytes at the pinned
URL are not the bytes your pin was computed from. The browser fails the
load closed (a blank game) rather than execute unverified code.
Remediation:
npm run build:sdk-artifact # rebuild the SDK artifact + sdk-manifest.json (platform checkout)
npm run export:zip # re-export your game so the lock re-pins the current SRI
Re-exporting re-reads sdk-manifest.json, so the bundle's pinned path and
integrity move together. If the mismatch is on the hosted side (the served
file disagrees with the served manifest), stop and report it — that is a
platform publishing fault, not something to patch around in a game.
4. core.autocrlf false — and why
The SDK artifact is byte-pinned over LF line endings: the builder
normalizes to LF and computes the sha384 over those exact bytes. On Windows,
git's core.autocrlf can silently rewrite LF to CRLF on checkout or commit —
and a CRLF rewrite of the artifact (or the sources it is built from) changes
the hash, which breaks the integrity pin of every game that pinned it.
In any checkout that builds or stages SDK artifacts:
git config core.autocrlf false
Do this before touching files, and if a repo ships a .gitattributes
pinning LF, do not fight it. If you see a diff where every line of an
artifact changed, that is a line-ending rewrite — do not commit it.