ps5-browser-builder (0.1.0)
Installation
pip install --index-url ps5-browser-builderAbout this package
Build deterministic online and offline PS5 browser-tile installers
PS5 Browser Builder
PS5 Browser Builder creates deterministic ELF installers for custom PS5 browser tiles. A tile can open an online homepage or pre-cache a bundled site in WebKit ApplicationCache for offline use.
The repository includes one complete project,
examples/slopkit, whose site is pinned to SlopKit's
curated public main branch with a Git submodule.
Installation and toolchain
The Python package requires Python 3.11 or newer. Building an ELF directly on
the host also requires the PS5 Payload SDK revision and fingerprint listed in
toolchain-lock.json.
The SDK must be supplied separately and is never copied into this repository. Set the standard SDK environment variable before building:
export PS5_PAYLOAD_SDK=/path/to/ps5-payload-sdk
You can also pass --sdk /path/to/ps5-payload-sdk to a build command.
Offline builds use the bundled, hash-locked SQLite amalgamation.
The seed format, transaction ordering, managed-update authorization, and
physical-qualification boundary are documented in
docs/OFFLINE_CACHE.md.
Tagged releases publish a wheel, source distribution, and an amd64 OCI image.
The image contains the exact validated SDK and compiler, so its build command
does not depend on host toolchain state. Pin the name@sha256:digest value from
the release's container-reference.txt, not the moving latest tag:
docker run --rm --read-only --tmpfs /tmp:rw,exec \
-v "$PWD/project:/project:ro" -v "$PWD/out:/out" \
git.richey.dev/miles/ps5-browser-builder@sha256:... \
build /project --output /out/browser.elf
The image consumes only the required SDK directories from the SHA-256-pinned
PacBrew v0.39 release archive. It does not follow PacBrew or SDK main. Exact
base-image, package, SDK source, archive, and fingerprint provenance is recorded
in
toolchain-provenance.json.
The image and release payload also carry the SDK's GPL-3.0-or-later license
text alongside the builder's AGPL license and third-party notice.
Clone the complete project with its public SlopKit dependency:
git clone --recurse-submodules \
git@forgejo:miles/ps5-browser-builder.git
For an existing checkout, initialize the site with
git submodule update --init. Generated source archives do not include the
submodule site. Run the builder from a checkout, or install the Python package
with:
python3 -m pip install .
Configure a project
Copy examples/slopkit and edit its browser.json:
{
"schema": 1,
"titleId": "SLOP00001",
"url": "https://slop00001.ps5.invalid/",
"title": "SlopKit",
"language": "en-US",
"version": "01.00",
"category": "media",
"artwork": {"icon0": "icon0.png"},
"offlineCache": {
"sourceDirectory": "site",
"document": "index.html",
"manifestPath": "slopkit.appcache",
"excludePaths": [
".git",
"slopkit.appcache",
"slopkit.manifest"
],
"networkWildcard": true,
"revision": 4,
"updatePolicy": "replaceOlder",
"fallbacks": [
{"namespace": "notify.html", "resource": "notify.html"}
]
}
}
- Use a unique title ID: four uppercase letters followed by five digits. For an offline project, also give it a unique HTTPS origin so independent tiles do not share an ApplicationCache group.
- Set
categorytogameormedia. - Use a 512×512 or 660×660 PNG for
artwork.icon0. - Remove
offlineCachefor an online-only tile. excludePathscan omit normalized relative files or complete directory subtrees. Exclusions may be absent, but cannot overlap or remove the cached document or a fallback resource.- For an offline update, keep the same identity, increment
revision, and setupdatePolicytoreplaceOlder.
--force-cache-overwrite is for controlled testing only. It bypasses revision
ordering, but still rejects caches that are unsafe, malformed, shared,
browser-created, unknown, or owned by another title.
Build the example
The included example tracks SlopKit public release ordinal 4. Its
replaceOlder policy can replace only a strictly older canonical cache managed
by this builder for the same title and manifest URL.
python3 -m ps5_browser_builder validate examples/slopkit
python3 -m ps5_browser_builder build examples/slopkit \
--output /tmp/slopkit.elf
python3 -m ps5_browser_builder inspect /tmp/slopkit.elf --json
Builds are create-only and compile twice to confirm deterministic output. These commands do not connect to a PS5.
To build a force-enabled testing artifact:
python3 -m ps5_browser_builder build examples/slopkit \
--force-cache-overwrite \
--output /tmp/slopkit-force.elf
Specialize an online carrier
specialize is the narrow integration surface for consumers that need to
embed a prebuilt installer in another binary. It needs no SDK and replaces only
the carrier's fixed 4096-byte metadata record:
python3 -m ps5_browser_builder specialize /tmp/carrier.elf project \
--output /tmp/product.elf
The command fully validates the carrier and result, rejects offline projects,
requires the project's icon0.png to match the carrier, and verifies that all
bytes outside the metadata record remain identical. A legacy game tile whose
param.json omitted applicationCategoryType can be reproduced explicitly:
python3 -m ps5_browser_builder specialize /tmp/carrier.elf project \
--implicit-game-category --output /tmp/legacy-game.elf
inspect --json has schema 1 and reports whether the category encoding is
explicit or implicit. The public compatibility boundary is the CLI and its
JSON output; internal Python modules are not a stable API.
Audit firmware inputs
The read-only firmware preflight moved with the installer implementation. It audits caller-supplied decrypted libraries for the WebKit AppCache schema, mount markers, runtime exports, euid path, and pre-12/12.00 AppInst routes:
ps5-browser-builder firmware-audit \
--root /path/to/ps5_sys_libs \
--firmware 08.60 \
--json
The audit never copies or modifies its inputs. A pass is static structural evidence only: directory names are caller-supplied labels, and the result does not qualify live database ownership, AppInst semantics, browser concurrency, profile selection, cache consumption, or reboot persistence.
Verification
Run the package checks from a recursive checkout:
python3 -m ruff format --check .
python3 -m ruff check .
python3 -m unittest discover -s tests -v
python3 tools/update_slopkit_example.py check
python3 tools/check_toolchain_provenance.py
Forgejo CI repeats these checks, builds and installs the wheel, then performs a clean build/specialize/inspect cycle inside the locked toolchain image. Release tags must match the Python package version before the workflow publishes any package or image.
The release workflow expects CONTAINER_REGISTRY_USERNAME and
CONTAINER_REGISTRY_TOKEN for both the OCI and Forgejo Python registries. Use
scoped service credentials or a personal access token with only the required
package permission. Release asset upload uses Forgejo's short-lived automatic
workflow token, so it does not require a stored repository token. After the
workflow for v0.1.0 succeeds, use its container-reference.txt manifest
digest to finalize the consuming WebKitty lock; never copy the digest of a
local image or of the moving latest tag.