SideloadedIPA is a fail-closed pipeline for selecting, inspecting, provisioning, signing, verifying, and publishing iOS IPA releases. It handles nested apps and extensions as one bundle graph, assigns a distinct profile and entitlement policy to every profile-bearing bundle, and publishes only independently verified output.
The repository also contains the Next.js download application in web/. The
application reads one validated apps.json registry from Cloudflare R2 and serves
the corresponding OTA installation manifests.
- GitHub release selection must resolve to exactly one asset. Direct IPA URLs must be HTTPS and pinned to a reviewed SHA-256 digest.
- Downloads are bounded, streamed, digest checked, and rejected before inventory or side effects when their identity changes.
- Every stage consumes a canonical predecessor manifest bound to the run, task, source, graph, and file digest. Signed output is still reopened and inspected independently.
- Unknown profile-bearing bundles, missing bundle rules, entitlement/profile mismatches, invalid signatures, and tampered cache entries stop publication.
- Apple changes are additive and explicitly gated. Publication is ordered as verified output, immutable upload, atomic registry update, revalidation, then stale-object cleanup.
Use the repository-pinned Python version and the exact uv version required by
pyproject.toml:
uv sync --frozen
cp configs/tasks.toml.example configs/tasks.local.tomlEdit the local task file using the configuration reference.
Export credentials only for stages that require them; .env.example lists the
supported names. Never commit credential values.
Run a task through the visible production stages with one unique run ID:
run_id="local-$(date +%Y%m%d%H%M%S)"
uv run sideloadedipa inspect --config configs/tasks.local.toml \
--run-id "$run_id" --task MyApp
uv run sideloadedipa plan --config configs/tasks.local.toml \
--run-id "$run_id" --task MyApp
uv run sideloadedipa sync --config configs/tasks.local.toml \
--run-id "$run_id" --task MyApp --apply
uv run sideloadedipa sign --config configs/tasks.local.toml \
--run-id "$run_id" --task MyApp
uv run sideloadedipa verify --config configs/tasks.local.toml \
--run-id "$run_id" --task MyAppinspect is read-only. Review plan before adding --apply to sync.
Publication additionally requires publication_enabled = true, a verification
run with --publish, and the R2/revalidation environment described in the
operator runbook. sideloadedipa run --apply is the
non-publishing convenience composition; add --publish only for an intentional
production publication.
Use --json for canonical machine-readable output and --help on the root or any
subcommand for the supported CLI contract.
Run the locked Python checks from the repository root:
uv run --frozen pytest
uv run --frozen black --check src tests scripts
uv run --frozen isort --check-only src tests scripts
uv run --frozen mypy src/sideloadedipa scriptsHTML coverage is an opt-in diagnostic:
uv run --frozen pytest --cov-report=term-missing --cov-report=htmlValidate the download application using its explicit fixture mode:
cd web
npm ci
npm test
APPS_DATA_MODE=fixture npm run buildProduction web deployments use APPS_DATA_MODE=origin, an HTTPS
R2_APPS_JSON_URL, REVALIDATE_SECRET, and SITE_PUBLIC_BASE_URL. Fixture mode
is rejected when VERCEL_ENV=production.
- Configuration — task, source, signing, publication, environment, and web settings.
- Architecture — stage ownership, evidence chain, trust boundaries, cache, publication, and registry behavior.
- Operator runbook — planning, applying, publishing, backend qualification, retry, rollback, and device acceptance.
- Security — archive, credential, CI, dependency, and Apple mutation controls.
- Troubleshooting — typed failure diagnosis for bundle, entitlement, profile, and signature problems.
- Migration — only the currently supported configuration and CLI migrations.
The supported repository-local OpenSpec instructions live only in .codex/skills.
Historical implementation plans belong in Git history and archived OpenSpec
changes, not in the operational documentation set.