Skip to content

fix: improve DIFC error messages and replace issue:#0 sentinel#2202

Merged
lpcox merged 7 commits intomainfrom
fix/difc-error-messages
Mar 20, 2026
Merged

fix: improve DIFC error messages and replace issue:#0 sentinel#2202
lpcox merged 7 commits intomainfrom
fix/difc-error-messages

Conversation

@lpcox
Copy link
Collaborator

@lpcox lpcox commented Mar 20, 2026

Summary

Improves DIFC error messaging for non-expert users and fixes the synthetic issue:#0 resource descriptions reported in gh-aw#21866 (recommendation 5).

Addresses gh-aw#21824 — confusing "Agent would need to drop integrity tags" messages.

Changes

Guard (Rust) — Replace #0 sentinel with #unknown

  • New extract_resource_number() helper in helpers.rs returns "unknown" (with log_warn) when the number field is missing or invalid
  • Replaces unwrap_or(0) in both response_items.rs and response_paths.rs for issues and PRs
  • Before: issue:github/gh-aw#0After: issue:github/gh-aw#unknown

DIFC Evaluator (Go) — Human-readable error messages

Context Before After
Read denied (integrity) "Agent would need to drop integrity tags [unapproved:all approved:all] to trust this resource" "The agent cannot read data with integrity below "approved""
Read denied (secrecy) "Agent would need to add secrecy tags [private:org/repo] to read this resource" "The agent is not authorized to access private (org/repo)-scoped data"
Write denied (integrity) "Resource requires integrity tags [production] that agent doesn't have" "The agent's integrity level is insufficient; it needs "production" integrity"
Write denied (secrecy) "Resource would need these secrecy requirements to accept the write" "The agent carries sensitive data that the target resource is not authorized to receive"

New helper functions

  • formatIntegrityLevel() — converts tag lists to named levels (e.g., [unapproved:all approved:all]"approved")
  • formatSecrecyLevel() — converts tags to scope descriptions (e.g., [private:org/repo]"private (org/repo)")

Test Results

  • All 70 Rust guard tests pass ✅
  • All Go unit tests pass (including updated assertion expectations) ✅
  • 0 lint issues ✅

Guard improvements (Rust):
- Replace unwrap_or(0) with extract_resource_number() helper that
  returns "unknown" instead of "0" for missing/invalid number fields
- Log warnings when number field is missing (helps diagnose synthetic
  issue:#0 entries reported in DIFC analysis discussions)
- Applies to both issue and PR number extraction in response_items.rs
  and response_paths.rs

Error message improvements (Go):
- Replace technical "Agent would need to drop integrity tags [X]"
  with human-readable "The agent cannot read data with integrity
  below X"
- Replace "Agent would need to add secrecy tags" with "The agent
  is not authorized to access private-scoped data"
- Add formatIntegrityLevel() that converts tag lists to named levels
  (e.g., [unapproved:all approved:all] → "approved")
- Add formatSecrecyLevel() that converts tags to scope descriptions
  (e.g., [private:org/repo] → "private (org/repo)")
- Update ViolationError.Error() with consistent plain-language messages
- Remove verbose "Remediation:" hints from user-facing errors

Addresses: github/gh-aw#21824, github/gh-aw#21866 (recommendation 5)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 20, 2026 03:18
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves DIFC denial/violation messages to be more human-readable and replaces the synthetic #0 sentinel in GitHub guard resource descriptions with #unknown when an issue/PR number is missing or invalid.

Changes:

  • Added DIFC formatting helpers to render integrity/secrecy tag sets as simplified “levels”/scopes and updated evaluator + ViolationError messages accordingly.
  • Updated Go unit tests to assert against the new error wording.
  • Added a Rust helper to extract issue/PR numbers safely and updated response labeling to use #unknown instead of #0.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
internal/difc/evaluator.go Adds formatting helpers and updates read/write denial Reason strings to be more user-friendly.
internal/difc/labels.go Updates ViolationError.Error() to use the new human-readable formatting.
internal/difc/labels_test.go Updates expectations to match new error messages.
guards/github-guard/rust-guard/src/labels/helpers.rs Introduces extract_resource_number() that returns "unknown" with a warning on missing/invalid numbers.
guards/github-guard/rust-guard/src/labels/response_items.rs Switches PR/issue number extraction to the new helper for item-based labeling.
guards/github-guard/rust-guard/src/labels/response_paths.rs Switches PR/issue number extraction to the new helper for path-based labeling.

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

Comment on lines 356 to 358
result.Reason = fmt.Sprintf("Agent has secrecy tags %v that cannot flow to '%s'. "+
"Resource would need these secrecy requirements to accept the write.",
"The agent carries sensitive data that the target resource is not authorized to receive.",
extraTags, resource.Description)
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

This denial reason still includes the low-level tag list and the target resource in the same sentence ("Agent has secrecy tags %v that cannot flow..."). In the PR description, the intended user-facing message for this case appears to be the simplified sentence only. If the goal is to avoid confusing non-experts, consider dropping the tag list from Reason (or moving detailed tags to debug logs / the detailed error output).

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

lpcox and others added 4 commits March 19, 2026 21:18
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Mar 20, 2026

@lpcox I've opened a new pull request, #2205, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 2 commits March 20, 2026 04:25
…2205)

The write-secrecy denial `Reason` exposed raw internal tag slices (e.g.
`[private:owner/repo]`) in the user-facing message, inconsistent with
read-denial messages which already use
`formatSecrecyLevel`/`formatIntegrityLevel`.

## Changes

- **`internal/difc/evaluator.go`:** Replace `%v extraTags` with
`formatSecrecyLevel(extraTags)` in the write-secrecy denial `Reason`,
producing e.g. `"private (owner/repo)"` instead of
`[private:owner/repo]`.

**Before:**
```
Agent has secrecy tags [private:owner/repo] that cannot flow to 'public-repo'.
The agent carries sensitive data that the target resource is not authorized to receive.
```

**After:**
```
Agent carries private (owner/repo)-scoped data that cannot be written to 'public-repo' due to secrecy constraints.
The target resource is not authorized to receive this sensitive data.
```

Raw tag details remain available in the debug log (`extraTags=%v`) and
in `FormatViolationError`'s "Current Agent Labels" output.

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)
@lpcox lpcox merged commit 3a94637 into main Mar 20, 2026
16 checks passed
@lpcox lpcox deleted the fix/difc-error-messages branch March 20, 2026 04:36
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