Skip to content

fix: make runner refresh exchange work (Stage 1) - #8

Open
eyevinn-developer[bot] wants to merge 1 commit into
mainfrom
stage1-runner-refresh-exchange
Open

eyevinn-developer[bot] wants to merge 1 commit into
mainfrom
stage1-runner-refresh-exchange

Conversation

@eyevinn-developer

Copy link
Copy Markdown

Stage 1 of the decision on #6 (comment) (parent: python-runner#39).

Closes #6

What changed

  • scripts/docker-entrypoint.sh: the runner-token exchange now POSTs {"token": ...} as application/json (body from a mode-600 temp file, --connect-timeout 5 --max-time 10). The response is parsed with node, because jq is not installed in this image; an empty token counts as failure.
  • The fresh 1h PAT is passed inline to the config-to-env command only.
  • The job gains OSC_REFRESH_TOKEN (original token; a parameter store key of the same name still overrides it).
  • || true is replaced by a [CONFIG] WARNING: runner token exchange failed (HTTP <status>, code=<code>); using the original token on stderr (no token or body printed, never exits).
  • README documents OSC_REFRESH_TOKEN.
  • tests/test-entrypoint-runner-refresh.sh: extracts the config-load block and runs it under set -e with stub curl/npx. Success case asserts the config load used the NEW token, the job's OSC_ACCESS_TOKEN is unchanged and OSC_REFRESH_TOKEN is the original. Failure cases: 401 expired/invalid/revoked, 500, empty and garbled body, missing token key, curl exit 22 and 28. Parser-unavailable case: node stub exits 127, config load falls back to the original token (not empty). Run locally: ALL PASSED (the repo has no PR CI).

Contract

Stage 1 keeps the job-visible OSC_ACCESS_TOKEN unchanged. The Stage 2 swap is out of scope (gated on the REJECT_RUNNER_REFRESH_TOKENS rollout).

What a human does next

Nothing.

Notes

The build check is red on this repo regardless (Dockerfile.osc was removed upstream); not part of this change. Open PRs #3 and #5 touch the same lines; whichever merges second needs a rebase.

Lessons

set -e makes the original config-load error branch unreachable, so every new step in this block is guarded with ||/if and the npx line is left untouched. A missing jq would have turned the body-only fix into a silent tokenless config load; the parser-unavailable test pins that.

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

POST JSON body, parse with node (no jq in image), use fresh PAT for
config load only, add OSC_REFRESH_TOKEN, warn instead of || true.

Co-Authored-By: Claude <noreply@anthropic.com>

@eyevinn-pr-reviewer eyevinn-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Research Review

Verified

  • Endpoint contract: POST /runner-token/refresh in osaas-token-service src/api_service_token.ts:549 takes body { token } (destructured at :568), replies 200 { token, expiresIn: 3600 }, 401 { reason, code } with code in refresh_token_expired | refresh_token_invalid | refresh_token_revoked, 500 { reason } with no code. The PR's body, parsing of .token and .code, and the code=none fallback match this exactly.
  • jq absent / node present: the repo Dockerfile on main (python:3.12-slim, apt list without jq, nodesource Node install) confirms birme's decision comment, so parsing with node is correct.
  • Decision match: birme's Stage 1 decision on issue #6 (job-visible OSC_ACCESS_TOKEN unchanged, fresh PAT only for config-to-env, OSC_REFRESH_TOKEN added, || true replaced by a [CONFIG] warning, node-based parse, success test asserting the NEW token is used) is implemented point by point.
  • Token handling: body goes via mode-600 temp file (--data @file), not argv; warning prints status and code only; the fresh PAT is passed inline to the npx command and not assigned to the shell variable.

Needs Verification

  • None blocking. The test stubs curl/npx and extracts the block between markers, so the real @osaas/cli honouring OSC_ACCESS_TOKEN from env is assumed (that is the existing behaviour of the unchanged npx line).

CI status

  • The build check is failing. I read the log: failed to read dockerfile: open Dockerfile.osc: no such file or directory. The repo's Dockerfile on main is Dockerfile, and the workflow still points at Dockerfile.osc. This is a pre-existing workflow/file mismatch unrelated to this diff (the PR changes only README, the entrypoint and a test), and the PR body says so. It is not a blocker for this review, but the repo has no real test CI, so the new test only runs locally.

Adjacent Stubs Detected

  • Swept scripts/docker-entrypoint.sh: the only stub-pattern hit is || true at line 105, inside json_field, which is intentional (empty output is treated as failure). Nothing else.

Orphaned Files Detected

  • None. tests/test-entrypoint-runner-refresh.sh is a standalone script; the entrypoint is the container entry point. The # BEGIN/END CONFIG LOAD markers are consumed by the test.

Escape Hatch Coverage

  • No new terminal-rejection branch. The failure path explicitly never exits, and the test covers 401 x3, 500, empty/garbled/missing-token body, curl exit 22 and 28, and parser-unavailable, all continuing with the original token.

Object Shape Verification

  • No fetched ORM or SDK object is spread. N/A.

Contract diff

  • No HTTP request handler changed. Container entrypoint behaviour: job-visible OSC_ACCESS_TOKEN unchanged; one additive env var OSC_REFRESH_TOKEN (optional addition, parameter-store key of the same name still overrides; consumer audit is on issue #6); startup adds one call to the token service bounded by --connect-timeout 5 --max-time 10 (the architect cites measured max 133 ms), and a timeout keeps the original token instead of failing (outcome-unknown is not treated as terminal). No new failure modes. Stage 2 swap is explicitly out of scope and birme-gated.

Impact Analysis

  • Blast radius: My Jobs runs of this image with CONFIG_SVC set.
  • Downstream consumers: jobs reading OSC_ACCESS_TOKEN see no change.
  • Coordinated changes needed: none. Open PRs #3 and #5 touch the same lines; the second to merge needs a rebase (stated in the PR).
  • Breaking change risk: low.

Risks Not Tested

  • Live exchange against the real token service with a real runner refresh token was not exercised; verified from the handler source only.
  • Behaviour of the real @osaas/cli with the inline env token was not run.

Research Suggestions

  • Separately fix the Dockerfile.osc reference in the docker workflow so the repo gets a green build.

Verdict

No blocking issues found.


Reviewed by PR Research Validator. This review checks whether code is based on verified sources rather than assumptions.

@eyevinn-developer

Copy link
Copy Markdown
Author
CI-fix agent started for the failing checks (one cycle per PR). _daily-review Step 4.6_

@eyevinn-developer

Copy link
Copy Markdown
Author

CI failures addressed

  • build: not fixed, push blocked. The failure is inherited from main (main's last two runs fail the same way): .github/workflows/docker.yml builds file: Dockerfile.osc, but commit 47cb5af on main deliberately removed that file ("Dockerfile.osc is added in the eyevinn-osaas fork as part of OSC catalog ingestion"). The workflow is the wrong side; the correct fix is the one-line change file: Dockerfile.osc -> file: Dockerfile. I committed it locally, but the push was rejected: the eyevinn-developer GitHub App lacks the workflows permission, so it cannot modify workflow files.

A human can apply the one-line change in .github/workflows/docker.yml (or fix it on main in a separate PR, after which this PR just needs to merge main).

@eyevinn-developer

Copy link
Copy Markdown
Author

CI-fix cycle already ran on this PR (marker 2026-11-08T13:20Z) and the head did not change (last commit 2026-11-08T12:17Z), while the build check is still failing (run 42479570081). No further fix agent is spawned (one cycle per PR). The linked issue #6 was declassified from Human Needed earlier today, so no label is written; this comment is the escalation.

Needed now: look at why the build job fails on this PR (log shows only checkout and a Node 20 deprecation warning in the failed-step output) and either fix the branch or tell the architect triage what to change.
Cause category: tooling/CI failure
Prevent next time: have the CI-fix agent post a ## CI failure needs a human comment when it cannot push, so the escalation names the cause; owner of the change is the daily-review skill (Step 4.6 step 3b prompt).
Owner of that change: birme
daily-review Step 4.6

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.

Runner refresh exchange always fails (see python-runner#39)

2 participants