Repository navigation
fix(triggers): run.secrets refuses every steering name the pinned sources read (#511) - #513
Merged
Merged
Conversation
edgehero
force-pushed
the
fix/511-steering-scan
branch
3 times, most recently
from
October 2, 2026 08:07
a88f574 to
1e75ed0
Compare
…rces read (#511) The steering set was derived from pi-ai and the SDKs it imports, one hop deep, with capital-only names and four accessor spellings. That left bindable: the lowercase twins google-auth-library reads beside the uppercase forms (google_application_credentials, measured planting a credential file), GOOGLE_CLOUD_QUOTA_PROJECT, every variable pi reads for its own configuration (PI_CODING_AGENT_DIR first), and every name read through a form the spelling list did not have. The derivation now: - reads both copies of pi-ai: the hoisted one and the one nested under pi-coding-agent that the runner dispatches through; - follows each SDK's imports that its package.json also declares in dependencies, one hop further (google-auth-library, @smithy/core, the AWS credential chain, debug, ws); - counts, after stripping comments with a small tokenizer (checked against esbuild's parser on every scanned file), every occurrence that can reach the environment instead of matching accessor spellings (worker/test/helpers/env-reads.mjs): every env token (process.env, ctx.env, a parameter named env, { env: e } = process), every process["env"], every use of an alias of one (const v = env(), const e = process.env), every call of a helper (derived: any named function one of whose own parameters is the key of a read). Each occurrence names a variable or is a site, and every file's sites are pinned with a count (worker/test/fixtures/provider-steering-sites.json), so a new occurrence anywhere names something or changes a count; - adds pi's own PI_* reads from pi-coding-agent's dist (not dist/bundle/) and the pi packages it declares, evaluating the agent and session directory keys through pi's config.js, minus CONTAINER_ENV_NAMES and the names the runner assigns before pi runs (PI_OFFLINE, PI_TELEMETRY, derived from image/runner/src). Every name found is reserved and matching stays exact, so the twins are literal members and openai_base_url stays bindable. The hand-written residuals shrink from nine to four. HOMEDRIVE and HOMEPATH join the runtime subtractions (the same home-directory helper as HOME). A job queued before the set widened, a stored scheduler template, or a receiver older than the worker can still carry such a name, and the container env would write it. The processor now asks the same RESERVED_ENV_NAMES of the job at the call site, before the secrets resolver is called (so no wiring of the resolver can skip it), and refuses it pre-spend as secret-name-reserved, naming the key. Specs: INT-TRIGGERS-FILE-CONTRACT AMENDED (the steering family, the pre-spend re-check), INT-CONTAINER-RUNTIME-CONTRACT AMENDED (the stale PI_CODING_AGENT_DIR claim, the steering-table note), REQ-TRIGGER-SECRETS AMENDED (load and pre-spend clauses), DES-TRIGGERS-UNIFIED-FILE AMENDED (#511 is another narrowing, the release notes must name it), CONST-PI-VERSION-PINNED evidence amended (the second upgrade gate covers pi's own reads). docs/secrets.md names the new families and the PI_FORWARD_ENV route. Checked unchanged: the per-provider pre-spend reservation, the key-variable bound, the closed container env map, admin/build.mjs inlining (the bundle carries the new members). Signed-off-by: Rob Boerman <robboerman@live.nl>
edgehero
force-pushed
the
fix/511-steering-scan
branch
from
October 2, 2026 08:22
1e75ed0 to
2ddc704
Compare
edgehero
added a commit
that referenced
this pull request
Oct 2, 2026
…egress and endpoint changes (#529) The three CLI transcripts were stale after the #508 and #503 round. init now also writes model-endpoints.json and model-endpoints.conf. up starts the egress proxy with a third mount for model-endpoints.conf and with --add-host host.docker.internal:host-gateway. doctor has a third egress probe, the plain HTTP refusal off port 80 (#508), and a Valkey listener line. Each transcript is real output of this tree's CLI, run on a Linux Docker Engine 29.1.3 host as a throwaway account (uid 1000), in an empty folder, with the home of that account shown as ~ (the sed is in launch/demo.md), so the folder reads ~/pi-work. The key is a dummy and gh is not logged in, so doctor shows the gh warning in place of the old scopes warning. In up the 25 doctor checks fold into one counted line (23 ok, 2 warnings, no failures), as before. The renderer that drew the old images was lost with a scratch folder. It now lives in launch/transcript-svg.mjs. Fed the text of the 2.0.0 images it gives them back byte for byte. launch/demo.md says how to capture and render each image. cli-service-windows.svg is unchanged: the nssm render did not change in this round. The panel images are unchanged too: no admin renderer changed in #513 to #527. The README cache busters for the three images move to 2026-10-02, and the up and doctor alt texts name what the images now show. No spec change: docs and maintainer tooling only. Spec IDs UNCHANGED, checked: REQ-DEPLOYMENT-BOOTSTRAP and INT-EGRESS-POLICY-CONTRACT, which these transcripts show, are not touched. Signed-off-by: Rob Boerman <robboerman@live.nl>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #511.
What changes
run.secretsrefuses every provider steering name the pinned sources read. The set is still derived from the sources, never hand-typed, and a test compares it both ways.The scan now:
package.jsondeclares independencies. That reaches google-auth-library, @smithy/core, the AWS credential chain, debug and ws. It does not follow undici, which is only an optional peer of openai.envtoken (process.env,ctx.env, a parameter namedenv,{ env: e } = process), everyprocess["env"], every use of an alias of one (const v = env(),const e = process.env), and every call of a helper. Helpers are derived, not listed: any named function one of whose own parameters is the key of an environment read (resolveEnvConfigValue(name, env)), so a new call of an existing helper is counted like a read.intest, a destructure, or a selector argument, with keys resolved through string constants) or is a site. Every file's sites are pinned with a count inworker/test/fixtures/provider-steering-sites.json. So a new occurrence anywhere either names something the equality sees or changes a count, and the failure prints the entries to review. The names pi reads outside itsPI_*namespace are pinned too. Forms with noenvtoken at all (Reflect.get(process, "env"),process["e" + "nv"]) are a stated limit; none occurs at the pin.PI_*reads from pi-coding-agent'sdist/(notdist/bundle/) and from the pi packages it declares. It subtracts the names the worker writes and the ones the runner assigns before pi runs (PI_OFFLINE,PI_TELEMETRY).Matching stays exact, so
google_application_credentialsis refused whileopenai_base_urlstays bindable. The set grows from 68 to 132 names: 64 added, none removed. The hand-written residuals drop from nine to four.A job queued before the set widened, a stored cron schedule, or an older receiver can still carry such a name. The worker now checks the same reserved set against the job at the call site, before the secrets resolver is called, and refuses it before anything spends as
secret-name-reserved, naming the key.Operator impact (release notes must say this)
A triggers file that binds any newly reserved name stops loading, and a queued job that binds one is refused. Some of these are ordinary names, such as
DEBUG,HOSTNAME,K_CONFIGURATION,AWS_EXECUTION_ENVandPI_TUI_DEBUG. Put those onPI_FORWARD_ENVinstead.Tests
provider-steering.test.mjsgoes from 9 to 16 tests, including a fixture test of every access form.triggers.test.mjsgains a refusal test and a still-bindable test.processor.test.mjsgains a test for the pre-spend re-check, with a resolver that fails if it is ever reached.config.jsevaluation, no assignment check, no runner subtraction, scanningdist/bundle/, no alias receivers, counting onlyprocess.env, no selector form, no destructure form, no comment stripping, noenv()result follow, noprocess["env"]count, no helper derivation, case-insensitive matching, a deleted name, and no pre-spend re-check. Added to the pinned sources:const { X } = process.env, an alias,process.env?.X,ctx.env("X"),env[CONST], a template key and a runtime key inopenai/client.mjs, a newprocess.env[name]helper in pi-ai,const v = env(); v.Xin @google/genai,process["env"]["X"],import { env as E } from "node:process", and two new calls of the existingresolveEnvConfigValuehelper.google_application_credentials, and again withPI_CODING_AGENT_DIR, inrun.secrets:pi-dispatch doctorprints✗ triggers file is refused at load;pi-dispatch workerexits 2 with the same "is reserved" error.