Skip to content

Self-managed bundle rejects a consumer's wrapper Pi launcher before spawn #142

Description

@frankekn

Summary

The operator-managed self-managed bundle refuses to start when a consumer sets PI_BIN to its own wrapper script, failing before Pi is spawned with a 54-byte stderr:

Managed Needlefish rejected an unapproved Pi launcher

This blocks the pi runner lane for SaiensCreditSystemRails and currently has no in-consumer workaround.

Where the check lives

The rejection string is not in this repository at any ref, and not in the consumer repository:

  • git grep unapproved over all local/remote refs of this repo: no match.
  • Same search over frankekn/SaiensCreditSystemRails at origin/main: no match.
  • Upstream launcher resolution is src/shared/codex.ts:1198 -> command: process.env.PI_BIN ?? "pi", with no launcher-identity or allowlist check. RUNNER_ENV_ALLOWLIST.pi (src/shared/codex.ts:83-100) already passes PI_BIN through.

So the check is introduced by the operator-provided self-managed.patch that ships inside the installed release, which is provisioned by hand per README ("Provision the tested self-managed bundle as the runner service account under ~/.local/share/needlefish-self/releases/<self_version>"). Because installation is managed outside CI, the authoritative bytes exist only on the runner and are not under version control.

Reproduction

Consumer: frankekn/SaiensCreditSystemRails, runner label saiens-needlefish-local-proxy (ubuntu-saiens-deploy-x64-1).

Failing gate: the review job step Verify read-only repository evidence contract, which runs node --test policy/.github/scripts/needlefish-repo-integration.test.mjs. That test spawns the installed reviewer binary with PI_BIN pointing at the consumer's wrapper.

Exact runs:

Run Head Result
34806706871 ad9f736a90e19a54356e2c819befa2f8fcae83d2 (PR #1188) Reviewer failed; stderr bytes 54
34810534625 6eea75ed9cfd1c05fa73724e15612c5716d9a2b9 (PR #1210) Reviewer failed; stderr bytes 54; stderr="Managed Needlefish rejected an unapproved Pi launcher\n"

Why the consumer wraps the launcher

The consumer's .github/scripts/needlefish-pi wrapper exists to pin the review policy: it rejects unexpected argv, requires its own runner session before credentials are reachable, caps temp file size, and strips NODE_OPTIONS/NODE_PATH. Pointing PI_BIN at the raw pi CLI would drop those guarantees.

Attempted in-consumer fixes (all insufficient)

PR #1210 tried adding PI_BIN to NEEDLEFISH_RUNNER_ENV_PASSTHROUGH, a setsid --wait session preflight, and wrapping the reviewer in setsid --wait. The rejection is unchanged, because it happens inside the bundle before spawn.

Ask

Define and document the approved-launcher contract for the self-managed tier:

  1. State what makes a launcher approved (path, digest, ownership, or an explicit opt-in env/flag).
  2. Let a consumer supply a wrapper that satisfies it, without weakening approved-launcher bytes, session ownership, credential boundaries, or fail-closed evidence.
  3. Ship a regression that covers a wrapper PI_BIN, and publish a verifiable release/base SHA plus the matching release.json digests so operators can roll it out.

Please keep the failure fail-closed; the current behaviour is correct in spirit, it just has no approved path for a consumer wrapper.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions