Skip to content

Improve Copilot 403 auth guidance for copilot-requests mode#40052

Merged
pelikhan merged 6 commits into
mainfrom
copilot/update-copilot-403-error-message
Jun 18, 2026
Merged

Improve Copilot 403 auth guidance for copilot-requests mode#40052
pelikhan merged 6 commits into
mainfrom
copilot/update-copilot-403-error-message

Conversation

Copilot AI commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Copilot CLI failures in copilot-requests: write mode were surfacing BYOK provider-token guidance even when the real problem was org-billing authorization. This updates the 403 path to point users at Copilot requests permissions and centralized billing docs instead.

  • 403 diagnostics for Copilot requests

    • Detect gh-aw API proxy auth failures returning HTTP 403 during Copilot requests flow.
    • Replace COPILOT_PROVIDER_API_KEY / COPILOT_PROVIDER_BEARER_TOKEN guidance with messaging tailored to:
      • permissions.copilot-requests: write
      • org-level Copilot billing enablement
      • the billing reference docs
  • Mode detection hardening

    • Normalize S2STOKENS as a truthy env flag instead of requiring an exact "true" match.
    • Keeps the diagnostic path stable across equivalent flag values.
  • Regression coverage

    • Add focused harness coverage for:
      • proxy-backed 403 failures in Copilot requests mode
      • truthy S2STOKENS variants
      • preservation of existing 401 behavior

Example of the new guidance path:

Copilot requests authentication failed through the gh-aw API proxy (HTTP 403, model=claude-sonnet-4.5, stage=starting the Copilot CLI request). This workflow is using permissions.copilot-requests: write, so Copilot requests must be allowed through your organization's centralized Copilot billing configuration. Verify that copilot-requests: write is granted to the workflow or job and that Copilot org billing is enabled for your organization. See https://github.github.com/gh-aw/reference/billing/ for details.

Copilot AI and others added 2 commits June 18, 2026 12:40
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title Improve Copilot 403 org-billing auth guidance Improve Copilot 403 auth guidance for copilot-requests mode Jun 18, 2026
Copilot AI requested a review from pelikhan June 18, 2026 12:45
Comment thread actions/setup/js/copilot_harness.cjs Outdated
const stage = detectCopilotAuthFailureStage(output);
if (authFailure.statusCode === "403" && envFlagEnabled(env.S2STOKENS)) {
return (
`Copilot requests authentication failed through the gh-aw API proxy (HTTP 403, model=${selectedModel}, stage=${stage}). ` +

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot refactor to template file in actions/setup/md use renderTemplate

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in ef58ece by moving the 403 copilot-requests guidance into an actions/setup/md template and rendering it with renderTemplateFromFile.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan June 18, 2026 13:02
@pelikhan pelikhan marked this pull request as ready for review June 18, 2026 13:05
Copilot AI review requested due to automatic review settings June 18, 2026 13:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Ready to approve

The changes are narrowly scoped to diagnostics, include targeted regression tests, and align with the stated 403/Copilot-requests requirements without introducing risky behavioral changes.

Note: this review does not count toward required approvals for merging.

Pull request overview

This PR updates gh-aw’s Copilot CLI harness diagnostics so HTTP 403 failures that occur specifically in permissions.copilot-requests: write (Copilot requests / centralized billing) mode no longer show BYOK provider-token guidance, and instead direct users to org billing enablement and the billing reference docs.

Changes:

  • Added a dedicated 403 diagnostic message for Copilot requests mode when the failure is coming from the local gh-aw API proxy.
  • Hardened Copilot requests mode detection by treating S2STOKENS as a truthy env flag (not only an exact "true" match).
  • Added regression tests covering proxy-backed 403 behavior in Copilot requests mode and S2STOKENS truthy variants, while preserving existing 401 behavior.
File summaries
File Description
actions/setup/md/copilot_requests_proxy_auth_403.md New templated diagnostic message for proxy-backed HTTP 403 in Copilot requests mode, linking to billing guidance.
actions/setup/js/copilot_harness.cjs Adds truthy env-flag parsing and a 403-specific diagnostic path gated on S2STOKENS (Copilot requests mode).
actions/setup/js/copilot_harness.test.cjs Adds focused unit coverage for the new 403 rewrite behavior and truthy S2STOKENS handling.
.changeset/patch-copilot-403-org-billing-message.md Records the user-facing patch change in release notes.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 0

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #40052 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold 100).

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions github-actions Bot mentioned this pull request Jun 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 100/100 — Excellent

Analyzed 2 test(s): 2 design, 0 implementation, 0 guideline violation(s).

📊 Metrics & Test Classification (2 tests analyzed)
Metric Value
New/modified tests analyzed 2
✅ Design tests (behavioral contracts) 2 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 2 (100%)
Duplicate test clusters 0
Test inflation detected No (23 test lines / 25 prod lines = 0.92)
🚨 Coding-guideline violations 0
Test File Classification Issues Detected
rewrites local proxy 403 errors in copilot-requests mode to org-billing guidance actions/setup/js/copilot_harness.test.cjs ✅ Design
treats truthy S2STOKENS values as copilot-requests mode for 403 guidance actions/setup/js/copilot_harness.test.cjs ✅ Design Minimal (1 assertion) — see detail below

JavaScript: 2 (*.test.cjs). No Go or other language test files changed.

💡 Optional Improvements (non-blocking)

treats truthy S2STOKENS values as copilot-requests mode for 403 guidance — The single assertion (toContain("Copilot requests authentication failed")) confirms the correct branch is taken for S2STOKENS=" YES " but does not verify the complete output contract (billing URL, permissions guidance, suppression of COPILOT_PROVIDER_API_KEY). Consider extending this test with the same assertions as the first 403 test, or folding it into a table-driven pattern covering multiple truthy values ("true", "1", " YES ").

Verdict

Check passed. 0% implementation tests (threshold: 30%). Both new tests verify observable user-facing output from buildCopilotProxyAuthFailureDiagnostic — the 403 copilot-requests diagnostic content and the truthy env-flag edge case. No mock libraries, no missing build tags, no test inflation.

🧪 Test quality analysis by Test Quality Sentinel ·

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 100/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /tdd and /diagnose — commenting with improvement suggestions, no blocking issues.

📋 Key Themes & Highlights

Key Themes

  • Test coverage gaps: The new branch discriminator (envFlagEnabled(S2STOKENS) guards the 403 path) has no negative-case test. BYOK 403s should return empty, but removing the guard wouldn't be caught by the current suite.
  • envFlagEnabled is untested at the unit level: Falsy variants ("false", "0", "no") are never exercised; only the truthy path is covered integration-style.
  • Second test underspecified: The truthy-normalization test checks a single property, while the first test checks five — worth aligning the coverage depth.

Positive Highlights

  • ✅ Clean guard restructuring — splitting the compound statusCode !== "401" condition into per-branch returns is more readable and extensible.
  • envFlagEnabled is a well-scoped pure function with a clear contract; the "yes" / "1" normalization pre-empts common CI flag variation.
  • ✅ The first regression test is thorough: six expectations lock down the message content, billing URL, and absence of wrong guidance in one shot.
  • ✅ Changeset entry accurately scopes the change as patch with a clear one-sentence description.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

Comment thread actions/setup/js/copilot_harness.test.cjs
Comment thread actions/setup/js/copilot_harness.test.cjs
Comment thread actions/setup/js/copilot_harness.cjs
Comment thread actions/setup/js/copilot_harness.cjs

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

REQUEST_CHANGES — 3 test coverage gaps + 1 throw-safety issue

The diagnostic logic and envFlagEnabled implementation are correct. The issues below are about insufficient test coverage that would let regressions slip through and a silent contract change that turns a no-throw function into one that can crash the harness.

Blocking findings summary
# File Severity Finding
1 copilot_harness.test.cjs:987 medium No assertion verifies {selected_model}/{stage} placeholders are resolved — static-string checks pass even if substitution is broken
2 copilot_harness.test.cjs:996 medium No test for falsy S2STOKENS returning "" and no test for non-proxy 403 + S2STOKENS=true returning "" — both gate conditions are unverified on their off paths
3 copilot_harness.cjs:434 medium buildCopilotProxyAuthFailureDiagnostic gains a filesystem I/O call with no error handling; a missing template file now crashes the harness retry loop instead of returning a fallback string

🔎 Code quality review by PR Code Quality Reviewer

Comment thread actions/setup/js/copilot_harness.test.cjs
});

expect(diagnostic).toContain("Copilot requests authentication failed");
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Falsy S2STOKENS and non-proxy-URL paths are completely untested: the test suite covers only truthy values, leaving two correctness gaps that would hide regressions.

💡 Suggested additions

Gap 1 — falsy S2STOKENS returns empty string (S2STOKENS gate correctness):

it("returns empty string for proxy 403 when S2STOKENS is not set", () => {
  const diagnostic = buildCopilotProxyAuthFailureDiagnostic(
    "Authentication failed with provider at (172.30.0.30/redacted) (HTTP 403).",
    { COPILOT_MODEL: "claude-sonnet-4.5" } // no S2STOKENS
  );
  expect(diagnostic).toBe("");
});

Gap 2 — non-proxy URL with S2STOKENS=true returns empty string (proxy-URL gate correctness):

it("returns empty string for non-proxy 403 even when S2STOKENS is true", () => {
  const diagnostic = buildCopilotProxyAuthFailureDiagnostic(
    "Authentication failed with provider at (api.anthropic.com/redacted) (HTTP 403).",
    { COPILOT_MODEL: "claude-sonnet-4.5", S2STOKENS: "true" }
  );
  expect(diagnostic).toBe("");
});

Without these, accidentally inverting the envFlagEnabled check or removing the isLikelyAWFAPIProxyURL guard would silently pass the entire test suite.

Comment thread actions/setup/js/copilot_harness.cjs
@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

@github-actions

Copy link
Copy Markdown
Contributor

``
@copilot review all comments and address the requested changes in the latest review, especially the missing test coverage and throw-safety issue.

Generated by 👨‍🍳 PR Sous Chef ·

Copilot AI and others added 2 commits June 18, 2026 13:46
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Done. Addressed all open github-actions[bot] review threads:

  • Wrapped renderTemplateFromFile in a try/catch to preserve the no-throw contract (commits Strengthen copilot 403 test coverage... and Fix template literal inconsistency...)
  • Exported envFlagEnabled and added a full describe("envFlagEnabled") suite covering all truthy/falsy/undefined cases
  • Strengthened the proxy-403 test with model=claude-sonnet-4.5 and stage=starting... substitution assertions
  • Strengthened the truthy-S2STOKENS test with billing URL and not.toContain("COPILOT_PROVIDER_API_KEY") assertions
  • Added three new negative tests: 403 without S2STOKENS (BYOK mode), 403 with falsy S2STOKENS, and non-proxy 403 with S2STOKENS=true

Local make fmt, make lint, and the full vitest run are all green. CI must be re-triggered by a maintainer before merge.

Comment thread actions/setup/js/copilot_harness.cjs Outdated
Comment on lines +434 to +441
try {
return renderTemplateFromFile(COPILOT_REQUESTS_PROXY_AUTH_403_TEMPLATE_PATH, {
selected_model: selectedModel,
stage,
});
} catch {
return `Copilot requests authentication failed through the gh-aw API proxy (HTTP 403, model=${selectedModel}, stage=${stage}). Verify that copilot-requests: write is granted and that Copilot org billing is enabled.`;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot remove try/catch. Assume this will not fail

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done — try/catch removed in the latest commit.

…FailureDiagnostic

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan June 18, 2026 14:07
@pelikhan pelikhan merged commit 7dd6030 into main Jun 18, 2026
14 checks passed
@pelikhan pelikhan deleted the copilot/update-copilot-403-error-message branch June 18, 2026 14:17
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.

3 participants