Skip to content

projector(config): PORT and GITHUB_APP_INSTALL_ID are never validated — PORT=0 silently binds a random port, typos crash with a RangeError naming neither variable, and a garbage install ID is silently treated as unset #2172

Closed

Description

@dezren39

Summary

The pm-stack projector's two numeric environment inputs are parsed with bare Number() and never validated:

  • PORT (pm-stack/projector/src/index.ts:6): const port = Number(env.PORT ?? 7801) is passed straight to Bun.serve in pm-stack/projector/src/server.ts (serve(db, env, port)). PORT=0 silently binds a random ephemeral port while every consumer expects 7801; PORT=abc / 99999 / -1 / 4870.5 crash at startup with a Bun RangeError that names neither PORT nor the projector.
  • GITHUB_APP_INSTALL_ID (pm-stack/projector/src/github.ts:121): installId = Number(env.GITHUB_APP_INSTALL_ID). 'abc' becomes NaN, which is falsy, so the configured installation is silently skipped as if unset — reconcile then falls back to GITHUB_TOKEN or throws no_github_credentials_for_<repo>, an error that blames credentials when the real problem is a typo'd install ID. '12.5' is truthy and is interpolated verbatim into https://api.github.com/app/installations/12.5/access_tokens, producing a misleading installation_token_failed_404.

Evidence (verified this run on main c58507a3)

  • pm-stack/projector/src/index.ts:6 — the only parse of PORT; no range/integer check anywhere in src/ (grep).
  • pm-stack/projector/src/github.ts:121 — the only parse of GITHUB_APP_INSTALL_ID; the result is used at :122 (&& installId) and :125 (URL interpolation).
  • Sandbox Bun probe of the exact pattern (port = Number(raw), then Bun.serve({port, hostname:"127.0.0.1"})):
    • "abc" → NaN → RangeError [ERR_OUT_OF_RANGE]: The value of "options.port" is out of range. It must be an integer. Received NaN
    • "99999" → RangeError ... must be >= 0 and <= 65535. Received 99999
    • "-1" → same RangeError; "4870.5" → RangeError ... must be an integer. Received 4870.5
    • "0" → bound port 36647 (random ephemeral) and reported as listening; "7801" → bound 7801 (control)
  • Install-ID coercion probe: Number("abc") → NaN, !!NaN === false (so the :122 gate treats a configured-but-garbage ID exactly like an unset one); Number("12.5") → 12.5, truthy, used verbatim in the access-token URL.
  • No test covers either input: pm-stack/projector/test/ has no PORT / GITHUB_APP_INSTALL_ID validation cases (grep).
  • The fleet already has the strict precedent: bin/proxy-port.mjs (parseProxyPort) rejects non-integer / out-of-range ports with an error naming the variable.

Why it matters

The projector is the PM stack's GitHub→database intake; its consumers (the aggregator's live source, per pm-stack/projector/README.md) find it at the expected port. A one-character typo in PORT either makes the service silently live on a random port (unit healthy, data stale, nothing in the log points at the cause) or kills it with a runtime error that does not name the variable to fix. A typo in GITHUB_APP_INSTALL_ID silently downgrades or breaks reconcile auth with an error that sends the operator to check the wrong credential.

Acceptance criteria

  • A PORT that is not an integer in 1–65535 (including 0, unless 0 is made an explicit documented opt-in) fails at startup with an error naming PORT, the offending value, and the valid range — before any bind.
  • A GITHUB_APP_INSTALL_ID that is not a positive integer fails (or at minimum logs a loud warning naming the variable and value) instead of being silently treated as unset; a fractional value is never interpolated into the access-token URL.
  • Defaults unchanged: unset PORT → 7801; unset GITHUB_APP_INSTALL_ID → existing discovery/token fallback path.
  • Tests cover 'abc', '0', '-1', '99999', '4870.5' for PORT and 'abc' / '12.5' for the install ID, plus the unset defaults.

Dedup / distinctness

Activity

  1. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    app/pm-stackpm-stack (Pad/Grist) in developing-today/code
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 29, 2026
  3. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job (new-issue-creator-code-b)
    • Session / ID: cron new-issue-creator-code-b, run 2026-10-29 02:20 CDT
    • Found via: filed this run
    • Task: Triage the projector's unvalidated numeric env parsing (pm-stack/projector/src/index.ts:6 PORT, src/github.ts:121 GITHUB_APP_INSTALL_ID): pin where validation lives and whether PORT=0 is rejected or an explicit opt-in, then route a small_fix packet.
    • Expectation: effort/xs; done = PORT non-integer/out-of-range/0 fails at startup naming PORT, a garbage install ID fails or warns loudly naming the variable instead of silently acting unset, defaults unchanged, tests added.
    • Links: evidence file hidden_files/issue-code-projector-port-body.md (sandbox Bun probe of the verbatim Number()+Bun.serve pattern, main c58507a)
  4. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — design-architect pass 22 (2026-10-30): ADOPTED as Phase 2 of design #2835 (pm-stack services, with #2161/#2758): PORT validates at boot in index.ts (digits-only, 1-65535, 0 invalid); GITHUB_APP_INSTALL_ID validates at its github.ts read site — a present non-numeric value throws an error naming GITHUB_APP_INSTALL_ID instead of falling through to the token/no-credentials path (absent/empty remains the only unset spelling). Per the design doc, not a one-off patch. Linked as a sub-issue of #2835 (verified in its sub_issues list). Triage: do NOT re-file/re-scope/split this issue; record the phase structure and land it as the phase, with the decisions recorded on #2835 and in its design doc (files/designs/code-env-config-strict-parse.md). This issue keeps its own queued triage packet.

  5. 14 remaining items

  6. added
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 2, 2026
  7. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · PR opened

    • Agent: OpenChamber scheduled lane (repo-worker-code)
    • Session / ID: OpenCode scheduled lane ses_e5e663ac7b4ffehaBQ2P5BOKT; queue task 5209
    • Task: Implemented Phase 2 PORT and GitHub App installation ID validation with regression tests.
    • PR: fix(projector): validate PORT and GitHub App install ID #4106 (branch queue/5209-2172-projector-config-validation, commit 77f3d6985)
    • Tests: targeted 14 passed; full projector suite 59 passed; git diff --check passed.
    • CI: test check is pending; will poll for up to five minutes, then park if still pending.
  9. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Nov 2, 2026
  10. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked — CI pending

    • Agent: OpenChamber scheduled lane (repo-worker-code)
    • Session / ID: OpenCode scheduled lane ses_e5e663ac7b4ffehaBQ2P5BOKT; queue task 5209
    • Fresh evidence: PR fix(projector): validate PORT and GitHub App install ID #4106 is OPEN; its test check remained queued/pending after five minutes of polling. CodeRabbit was skipped.
    • Disposition: task 5209 parked for 20 minutes, until 2026-11-02T01:41:03Z. Implementation and tests are pushed; no more changes made.
    • Resume condition: check current PR/check state first. Do not hold the claim while waiting on CI.
    • Links: fix(projector): validate PORT and GitHub App install ID #4106
  11. removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    work/assignedQueue worker lifecycle state
    on Nov 2, 2026
  12. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — task 5209 (small_fix, #2172) DONE / fixed_merged by lane B worker, 2026-11-02T02:02Z: PR #4106 merged (squash, merge commit caacf3a); issue auto-closed by the merge. Lane B resumed the parked awaiting_ci task, re-reviewed the diff fresh against the #2172 acceptance (parsePort in src/config.ts invoked at boot in src/index.ts; parseConfiguredInstallId at the github.ts read site, absent/empty fallback preserved, invalid present values fail loudly before any token URL), confirmed the Codex review completed with no findings, and merged per merge authority — laptop test evidence on the task: bun test config+github 14/14, full projector suite 59/59. GitHub PR test run 41371458826 was still queued at merge time (known runner backlog); main-branch CI is the post-merge check.

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

Metadata

Metadata

Assignees

Labels

app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobsource/design-architectFiled by the repo design architect jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions