Public course previewThis is not your assigned passport. No identity, answers, or completion progress are stored here.How to start your passport
Handbook / maintainers

maintainers

Four-Repository Passport Deployment

This runbook is for the IDEAL Lab IT administrator. The active 2026 service uses IDEALLab/onboarding-IT as source and soheylm-passport-sandbox for the three runtime repositories. For compatible releases, use the routine-update matrix below. Initial provisioning and first-cutover gates remain as reference; do not recreate working Apps, secrets, learner forks or control records.

Repository Actions are disabled on IDEALLab/onboarding-IT. Do not re-enable them or add a source-side workflow. Source validation is dispatched to the private sandbox control repository described below.

Routine Compatible Update#

Change Artifacts Required verification
Lesson copy/navigation Website and compatible launcher; generated exercise/controller exports when changed Full source checks, desktop/mobile and three-engine journeys, contract comparison, release assets and synthetic reopen
Controller behavior Reviewed private control export Accepted/rejected agreement, protected-state diff and trusted status behavior
Required assessment meaning Versioned curriculum, website, launcher, exercises and controller Owner-reviewed contract/migration and old complete/draft/pending/new learner cases

Build from one exact reviewed source. Preserve protected assignments, history, enrollments and registry; keep the previous compatible release available. Publish only after qualification, then compare the live website with the reviewed build and verify the downloaded launcher. Provisioning below is for a new service.

1. Build From One Reviewed Revision#

From a clean reviewed onboarding-IT commit:

python3 scripts/export_exercises_repo.py /tmp/passport-exercises
python3 scripts/export_gh_passport.py /tmp/gh-passport
git clone git@github.com:soheylm-passport-sandbox/onboarding-control.git /tmp/onboarding-control
python3 scripts/export_onboarding_control.py --update-existing /tmp/onboarding-control
python3 scripts/render_deployment_assets.py --check

Diff each export before pushing. Exercises and launcher are public; onboarding-control is private. The initial overhaul branch cutover is historical. For a routine update, embed the exact reviewed source and publish the qualified main tree; do not reinterpret or replace existing learner assessment records.

Never replace the control repository with a fresh directory or use an unqualified rsync --delete: assignments, enrollments, registry events, and completion records are append-only operational state. --update-existing refuses a dirty clone, a branch other than main, or an origin other than the configured control repository. It preserves trusted state while replacing generated code and rebuilding the operational views.

Generated Public Browser Qualification#

Each launcher export now includes qualification/ and a local reusable WebKit workflow. Run the export from one clean reviewed source; --skip-web-build requires the matching current and compatibility build proofs. Missing proofs, modified or extra assets, and mismatched source revisions stop the export. Rebuild rather than relabelling an old bundle. Dirty preview exports remain available locally, but cannot pass the public qualification verifier.

The exporter copies the unchanged tracked browser cases and only their public fixtures. It serves the launcher's actual embedded pages. A public-repository preflight runs before allocating a Mac; tag builds require the complete WebKit result and native tests. Keep other final source/controller/browser gates. No learner version, existing progress or production permissions change here.

Local reusable workflows run from the caller's commit and context; a public callee does not make a private caller's runner usage free. See GitHub reusable workflow rules. Use the generated README for local verification; never upload the private checkout or protected records. Only ordinary standard public runners are used.

2. Publish The Static First Contact#

Build the stateless browser product locally from the reviewed revision:

PNPM=pnpm python3 scripts/build_web.py \
  --source-ref "$(git rev-parse HEAD)" \
  --site-url https://ideal-passport.pages.dev
cd platform/cloudflare-worker
pnpm install --frozen-lockfile
pnpm exec wrangler pages deploy ../../web/dist --project-name ideal-passport

Expected: Cloudflare prints the deployed HTTPS URL. Open /getting-started/ without GitHub login and verify all internal links. This Pages project stores no learner identity or progress and needs no GitHub repository access or secret.

3. Protect Public Exercises#

Protect passport-exercises:main: require PRs and conversation resolution, disable force pushes and deletion, and require the trusted controller Check Run once live. Keep the repository free of privileged workflows and secrets.

4. Configure Two GitHub Apps#

Controller App#

Install only on passport-exercises:

Permission Level
Metadata read
Contents read
Checks read/write
Issues read/write
Pull requests read/write

Subscribe only to Pull request. Configure the deployed Cloudflare Worker as Webhook URL and a new random webhook secret. Store this App's client ID and private key only in private onboarding-control as CONTROLLER_APP_CLIENT_ID and CONTROLLER_APP_PRIVATE_KEY. The immutable App ID must match platform/deployment.json and the launcher release.

Dispatch App#

Install only on private onboarding-control:

Permission Level
Metadata read
Actions write

Do not subscribe it to public events. Put its App ID, installation ID, and PKCS#8 private key only in Cloudflare Worker secrets.

5. Deploy The Signed Worker#

Follow platform/cloudflare-worker/README.md. Review wrangler.toml, run the local Worker tests, enter six secrets through hidden Wrangler prompts, deploy, and update the Controller App webhook URL. Never broaden either App installation as a debugging shortcut.

A successful webhook forwards only delivery ID, exercise repository, PR number, and head SHA. GitHub's delivery log must show 202 controller_dispatched.

6. Route Source CI To The Sandbox#

Export platform/onboarding-control so that source-ci.yml, validate_source_ci_event.py, and classify_source_ci.py exist on the control repository's main branch. Configure these two credentials:

  1. Create one dedicated Ed25519 deploy key. Add only its public key to IDEALLab/onboarding-IT as a read-only deploy key.
  2. Store only its private key in the private control repository as SOURCE_REPOSITORY_DEPLOY_KEY.
  3. Generate a new random webhook secret and store it in Cloudflare as SOURCE_WEBHOOK_SECRET.
  4. Add a repository webhook to IDEALLab/onboarding-IT with the Worker URL ending in /source-ci, the same source secret, JSON content type, SSL verification, and only Pull requests selected.

Keep Actions disabled at repository level on IDEALLab/onboarding-IT. A push to a same-repository PR must create one fast run in soheylm-passport-sandbox/onboarding-control and zero runs in IDEALLab. The automatic suite is one Ubuntu job and cancels obsolete revisions. Run the release suite manually only before a release; it expands to exactly three OS jobs and three browser jobs (Chromium/Firefox on Linux, WebKit on macOS); Chromium also packages the launcher. Finish local checks before dispatch, and rerun only failed jobs for the same exact source SHA during diagnosis.

The sandbox run does not become an IDEALLab-hosted Check Run. Review its exact PR number and head SHA in the private Actions run before merging source. Do not replace the read-only deploy key with a personal access token or give it write access.

7. Lock Cost#

The private workflow has one serial assessment per changed learner SHA, bounded job timeouts, and workflow concurrency. A recovery cron runs only four times per day. No large runner is allowed.

Before enabling a cohort:

  1. confirm the sandbox organization has no payment method, so usage stops at included quota; or
  2. if a payment method exists, set a GitHub Actions product budget with Stop usage when budget limit is reached.

Keep usage alerts enabled. Measure minutes after five synthetic learners and project the full cohort. A notification is not a spending lock. The owner confirmed a 50 USD monthly Actions budget on 2026-10-15. Read metered usage before paid qualification, keep the stop-usage setting enabled, and stop discretionary CI at 75% of the budget to retain student capacity.

8. Publish The Launcher#

The release workflow tests and emits Windows x64, macOS x64/arm64, and Linux x64/arm64 binaries. It generates release compatibility metadata from SOURCE.json. Tag the reviewed matching release, then test:

gh extension install soheylm-passport-sandbox/gh-passport --force --pin v0.12.1
gh passport version

For an existing compatible Passport, also open the older launcher, press Update and reopen, and verify that the new launcher reopens the same current mission. Force one update-verification failure in a disposable qualification fixture and confirm the previous launcher is restored. Do not publish a release whose compatibility marker names a different curriculum.

On Apple Silicon, verify both boundaries: the downloaded release asset must match GitHub's raw SHA-256 before installation, and the installed executable must match the deterministic ad-hoc signing transformation performed by GitHub CLI. A raw post-install checksum comparison is invalid because that signature changes the file.

The update API returns a saved success or rollback only when its recorded launcher version matches the launcher serving the dashboard. Keep this check on both the local API and browser renderer so a later manual installation does not present a stale rollback as a current failure.

Do not ask learners to bypass Gatekeeper, SmartScreen, antivirus, or execution policy.

9. Enroll Learners#

Enroll GitHub usernames and one operational reviewer asynchronously in private onboarding-control. Do not store operating system, answers, credentials, or research context in enrollment. The learner starts from the public first-contact page and does not join the sandbox organization.

Registration derives one exact editable allowlist from the frozen mission route: each assigned submission receipt plus only that mission's declared artifacts. Re-registering an active assignment repairs an older allowlist without changing its identity, route, branch, PR, baseline, attempts, or history. When a repair occurs, a private manifest_reassessment_required marker queues the same public commit again without clearing its recorded SHA or counting another attempt. The controller removes the marker only after it publishes the replacement assessment. Never replace this migration with a broad workspace/** rule or ask the learner to purge their Passport.

10. Production Transaction#

Before invitation, use a non-admin synthetic learner to prove:

  1. no public artifact exists before browser consent;
  2. start creates exactly one personal fork and central draft transport PR;
  3. a mission submission causes one signed Worker dispatch;
  4. the controller assesses the exact SHA without credentials or network;
  5. the expected trusted App publishes one Check Run and sanitized feedback;
  6. wrong signature/repository/App/branch/SHA inputs cause no assessment;
  7. an unchanged redelivery does not increase attempts or duplicate records;
  8. completion writes one private record, closes without merging, and resumes;
  9. public help works asynchronously without a secret or private log.

11. Cutover And Rollback#

After qualification, merge the reviewed onboarding branch, change handbook_ref to main, rebuild all four products from the same commit, and publish the first-contact URL. Rollback pins a previously reviewed matching curriculum, launcher, exercises, controller, Worker, and static build. Never delete public records or private completion history.

Production Gates#

  • Static first contact is public and tested without authentication.
  • passport-exercises is public and protected.
  • gh-passport is tagged and installable on clean Windows, macOS, and Linux.
  • onboarding-control is private with controller credentials configured.
  • Controller App is limited to passport-exercises.
  • Dispatch App is limited to onboarding-control.
  • Cloudflare Worker signature and real webhook transaction pass.
  • Owner confirmed a 50 USD/month Actions limit on 2026-10-15; metered usage is checked before manual paid runs.
  • Source PR webhook dispatched one sandbox CI run and zero IDEALLab runs on 2026-09-06.
  • Scheduled recovery and exact-SHA assessment succeeded in the sandbox on 2026-09-02.
  • One synthetic non-admin learner completes the full public-record loop.
  • Real Euler CPU, NAS, Blade, and Windows SSH pilots pass where claimed.
  • No privileged key appears in public code, workflow, artifact, or log.
  • The overhaul PR is reviewed and remains unmerged until cutover approval.