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 provides game-kit, iframe-sdk, the bundler, and the validators.
  • The runtime bridge SDKsdk-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. Its file field names the current release's hashed file; major and integrity identify 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.json URL vs package-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 ci fails with EINTEGRITY. Fix: update the dependency spec, delete the stale lock entry (or the lock), and reinstall so resolved + integrity are recaptured together.
  • bodylink.cloud.json vs the hosted SDK — the export preflight fetches the hosted sdk-manifest.json and 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 your runtimeRange must 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.