Skip to content

Demos: keyless OIDC CI/CD for on-platform example apps#428

Open
MajorTal wants to merge 2 commits into
mainfrom
add-demos-keyless-cicd
Open

Demos: keyless OIDC CI/CD for on-platform example apps#428
MajorTal wants to merge 2 commits into
mainfrom
add-demos-keyless-cicd

Conversation

@MajorTal

@MajorTal MajorTal commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

What

Adds demos/ — example run402 apps that auto-deploy to their own run402 projects on push to main, via keyless GitHub OIDC: each push exchanges the GitHub Actions OIDC token for a short-lived, deploy-scoped run402 CI session (run402's own CI-binding / OIDC-federation feature), then deploys through /content/v1 + /apply/v1. No run402 credential is stored in CI.

This is also peak dogfood — the run402 demos deploy to run402 using exactly the keyless flow we tell customers to use.

Layout

demos/
  _deploy/            # shared toolkit (registry, change-detection, the
                      # /content+/apply engine, the dispatcher, OIDC exchange,
                      # a registry gate) — no demo of its own
  <name>/
    app.json          # checked-in, NON-SECRET deploy target (project_id, binding_id, …)
    public/           # static site (the generic deploy ships this)
    deploy.ts         # OPTIONAL — only demos with functions/DB need a custom spec

.github/workflows/deploy-demos.yml is the change-detected matrix workflow (environment: demos scopes the OIDC subject the run402 bindings pin). A change under demos/<name>/** deploys that demo; a change under demos/_deploy/** redeploys all. Only provisioned demos (a real project_id in app.json) are ever in the matrix — so this is a safe no-op for the source-only demos until they're onboarded.

Status

Demo URL Status
test-video https://test-vid.run402.com ✅ provisioned + live (static)
passkeys https://passkeys.run402.com ✅ provisioned + live (static)
cosmicforge / evilme / social-todo source-only — need onboarding (functions / DB / secrets)
mpp-test local dual-rail payment server, not deployable

The two provisioned demos reuse system projects (non-billable/transferable/freezeable, deploy-tier-exempt) with CI bindings scoped to repo:kychee-com/run402:environment:demos.

Safety

  • demos/_deploy/check-registry.mjs fails the build if any app.json carries a secret-bearing key. Verified no secret values are committed (the app.json binding_id is a revocable handle; the anon token is public by design).
  • Merging this activates the demos' CI; the workflow no-ops for everything except the two provisioned demos.

🤖 Generated with Claude Code

Adds demos/ — example run402 apps that auto-deploy to their own run402 projects on push to main via keyless GitHub OIDC (no run402 credential in CI; each push exchanges the OIDC token for a short-lived run402 CI session). demos/_deploy/ is the shared toolkit (registry, change-detection, the /content+/apply engine, the dispatcher, the OIDC exchange, a registry gate); .github/workflows/deploy-demos.yml is the change-detected matrix workflow (environment: demos).

test-video + passkeys are provisioned + live (test-vid.run402.com, passkeys.run402.com), reusing system projects + bindings scoped to repo:kychee-com/run402:environment:demos. cosmicforge/evilme/social-todo are source-only pending onboarding (functions/DB/secrets); mpp-test is a local server, not deployable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread demos/test-video/public/index.html Fixed
Comment thread demos/test-video/public/index.html Fixed
Both assigned a static, author-controlled data-* attribute into innerHTML. data-text (showScene): the innerHTML pre-seed was dead code — initTypewriters already rebuilds the .visible/.hidden spans via createElement + textContent; removed it. data-code (initCodeLines): values are entity-encoded text, not markup — decode the few entities used and assign via textContent. No behavioral change; no remaining DOM-text→HTML flow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MajorTal added a commit that referenced this pull request Jun 17, 2026
…ept keys

The gateway deleted POST /projects/v1/admin/:id/functions (live on main), so
r.functions.deploy() 404s in prod. Re-point it onto the unified apply engine
(a one-function functions.patch.set ReleaseSpec) — the same path the rest of
the SDK uses. Auth shifts from the service-key bearer to the standard apply
credential (SIWX wallet, or the v3.1.0 project.deploy operator-approval gate).
Public signature + FunctionDeployResult shape unchanged; runtime_version and
deps_resolved are null on the deploy result (apply returns release-level data —
they live on the functions-list record).

Wire `deps` end-to-end through the apply engine (capability
apply-v1-function-deps, verified on origin/main): public FunctionSpec.deps, the
validateSpec field allowlist, normalizeFunction, and functionToWire. Without all
four, functions.deploy({ deps }) would silently drop deps at the wire.

transfer-accept (#428): AcceptTransferResult gains anon_key/service_key, and
accept() persists them via saveProject + setActiveProject (mirroring provision)
so the new owner can operate the inherited project with no extra provisioning.

Tests: rewrote the SDK + MCP deploy tests onto the apply flow (plan+commit;
empty missing_content skips upload, terminal ready skips poll); added
transfer-accept persistence tests. Corrected the now-false docs (unified deploy
does accept deps; the deploy result no longer surfaces runtime_version /
deps_resolved). npm test green (0 fail), build clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants