ps5-browser-builder (0.1.0)

Published 2026-08-15 19:22:34 -05:00 by miles

Installation

pip install --index-url  ps5-browser-builder

About 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 category to game or media.
  • Use a 512×512 or 660×660 PNG for artwork.icon0.
  • Remove offlineCache for an online-only tile.
  • excludePaths can 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 set updatePolicy to replaceOlder.

--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.

Requirements

Requires Python: >=3.11
Details
PyPI
2026-08-15 19:22:34 -05:00
3
PS5 Browser Builder contributors
5.5 MiB
Assets (2)
Versions (1) View all
0.1.0 2026-08-15