Skip to content

feat(triage-security): add runner-side mutation authorization opt-in - #356

Merged
mrizzi merged 2 commits into
mainfrom
TC-6934
Oct 26, 2026
Merged

mrizzi merged 2 commits into
mainfrom
TC-6934

Conversation

@mrizzi

@mrizzi mrizzi commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • pre_triage_security.py collect now reads the runner-only opt-in FULLSEND_TRIAGE_MUTATION_AUTHORIZED and passes it to collect_bundle → build_bundle → authorization.mutation_authorized, replacing the hardcoded False.
    • exact true → true; unset or false → false (unchanged report-only default); any other value → ERROR: on stderr, exit 1, no bundle written (fail closed).
    • The variable is read from the runner environment only (same trusted-host pattern as FULLSEND_RELEASE_DECISIONS); it is not added to the harness env.sandbox and never reaches the sandbox.
  • No executor or schema change: execute_plan already accepts mutation-authorized results only when the bundle is authorized (covered by the existing test_authorized_actions_execute_in_order_with_footnoted_comments / test_unauthorized_mutating_plan_fails_without_jira_calls).
  • fullsend.md "Triage-security release orchestration" documents the opt-in and that enabling it in CI is gated on TC-6191.
  • Second commit re-pins .fullsend/harness/triage-security.yaml base: to 8f17cfaf (sha256 441a08b5…) and re-locks triage-security only via fullsend lock triage-security; the verify-pr harness and lock entry are byte-identical. The re-pin also carries TC-7141's bare built-in vertex-ai provider into the triage-security pin, so running it from this repo needs fullsend ≥ v0.45.0 (already the documented prerequisite).

Merge with a merge commit (no rebase/squash): the base: URL pins 8f17cfaf from this PR.

Replaces #355 (same commits, reopened from an upstream branch so fullsend lock can fetch the pinned commit).

Tests

  • New: test_mutation_authorization_opt_in_reaches_collector (unset/false/true), test_invalid_mutation_authorization_fails_closed (7 malformed values), test_authorized_bundle_satisfies_input_contract.
  • python3 -m pytest plugins/sdlc-workflow/scripts/ -q → 740 passed, 3 skipped; uvx skillsaw 0 errors; claude plugin validate plugins/sdlc-workflow passed.

Implements TC-6934

🤖 Generated with Claude Code

Summary by Sourcery

Enable controlled runner-side authorization of triage-security mutations while maintaining fail-closed report-only defaults and updating the pinned harness.

New Features:

  • Add a runner-only opt-in for authorizing triage-security mutation bundles while preserving report-only behavior by default.

Bug Fixes:

  • Reject malformed mutation authorization values before collection and fail closed without writing a bundle.

Enhancements:

  • Propagate trusted mutation authorization through bundle creation so the existing executor can distinguish authorized mutation plans.
  • Document the mutation authorization opt-in, sandbox isolation, and CI gating requirements.

Build:

  • Re-pin the triage-security harness and refresh its lock metadata to the updated upstream revision.

Documentation:

  • Document runner-side mutation authorization behavior and prerequisites for enabling it in CI.

Tests:

  • Add coverage for authorization opt-in states, malformed values, and validation of authorized bundles.

mrizzi and others added 2 commits October 26, 2026 16:22
The pre-script sets authorization.mutation_authorized from the runner-only
FULLSEND_TRIAGE_MUTATION_AUTHORIZED variable: exact 'true' authorizes,
unset or 'false' stays report-only, any other value fails closed (exit 1,
no bundle). The variable is never exposed to the sandbox. Enabling it in
CI is gated on TC-6191.

Implements TC-6934

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-pin the triage-security child base to the commit carrying the
mutation-authorization opt-in and re-lock triage-security only; the
verify-pr harness and lock entry are unchanged.

Implements TC-6934

Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Introduces a trusted runner-side mutation-authorization opt-in for triage-security collection while preserving report-only defaults and fail-closed handling, documents the security and rollout model, and refreshes the pinned triage-security harness/lock to the requested upstream revision.

Sequence diagram for runner-side triage mutation authorization

sequenceDiagram
    participant Runner
    participant PreScript as pre_triage_security.py
    participant Collector as collect_bundle
    participant Bundle as Bundle
    participant Executor as execute_plan
    participant Jira

    Runner->>PreScript: collect
    PreScript->>PreScript: parse_mutation_authorization
    alt FULLSEND_TRIAGE_MUTATION_AUTHORIZED is true
        PreScript->>Collector: collect_bundle(mutation_authorized=true)
        Collector->>Bundle: authorization.mutation_authorized=true
        Bundle-->>Executor: authorized result
        Executor->>Jira: execute mutation actions
    else unset or false
        PreScript->>Collector: collect_bundle(mutation_authorized=false)
        Collector->>Bundle: authorization.mutation_authorized=false
        Bundle-->>Executor: report-only result
    else invalid value
        PreScript-->>Runner: EvidenceError on stderr, exit 1
        PreScript-->>Runner: no bundle written
    end
Loading

File-Level Changes

Change Details Files
Adds a runner-only, fail-closed opt-in that propagates mutation authorization into collected triage bundles.
  • Parse FULLSEND_TRIAGE_MUTATION_AUTHORIZED with exact true/false semantics.
  • Thread the resulting flag through collection into authorization.mutation_authorized.
  • Keep the variable out of sandbox inputs and reject malformed values before collection or bundle output.
plugins/sdlc-workflow/scripts/pre_triage_security.py
Expands coverage for authorization propagation, rejection behavior, and bundle contract compatibility.
  • Test unset, false, and true runner settings.
  • Test malformed values produce stderr errors, exit 1, and no collector invocation or stdout.
  • Validate that an authorized bundle satisfies the existing input contract.
plugins/sdlc-workflow/scripts/test_pre_triage_security.py
Documents the mutation opt-in, security boundary, executor behavior, and CI rollout gate.
  • Describe exact environment-variable semantics and report-only defaults.
  • Document runner-only visibility and TC-6191 gating for CI enablement.
fullsend.md
Re-pins the triage-security harness and refreshes its lock metadata to the specified upstream commit.
  • Update the harness base URL and digest to commit 8f17cfaf.
  • Re-lock triage-security resources and hashes, including the upstream built-in Vertex AI provider changes.
  • Retain the verify-pr harness and its lock entry unchanged.
.fullsend/harness/triage-security.yaml
.fullsend/lock.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai 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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Needs a human reviewer. If the runner has FULLSEND_TRIAGE_MUTATION_AUTHORIZED=true, collection records the bundle as authorized and the executor can perform Jira mutations; those writes may remain after reverting this change.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@fullsend-ai-review

fullsend-ai-review Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

🤖 Finished Verify Pr · ✅ Success · Started 4:02 PM UTC · Completed 4:11 PM UTC

Commit: 6e16027 · View workflow run →

Runtime: claude · Model: claude-opus-4-8 · Effort: high · Cost: $4.58

@fullsend-ai-review

Copy link
Copy Markdown

[sdlc-workflow/verify-pr] Re: @sourcery-ai[bot] review — Classified as suggestion — the comment flags the by-design behavior that a runner with FULLSEND_TRIAGE_MUTATION_AUTHORIZED=true records an authorized bundle so the executor may perform Jira mutations that persist after a revert. This is the intended, fail-closed, default-report-only opt-in this task (TC-6934) adds — not a defect — and it is not backed by a documented CONVENTIONS.md convention or a counted codebase pattern, so it is not upgraded to a code change request. No sub-task created.

@fullsend-ai-review

Copy link
Copy Markdown

Verification Report for TC-6934 (commit 6e16027)

Check Result Details
Review Feedback PASS 1 review-body observation from sourcery-ai[bot], classified as suggestion (by-design security note); no code change requests; no sub-tasks created.
Root-Cause Investigation N/A No sub-tasks were created; nothing to investigate.
Scope Containment PASS PR changes exactly the 5 files named in the task spec; no out-of-scope or unimplemented files.
Diff Size PASS 5 files, +143/-65; proportionate once the mechanical lock.yaml re-lock churn is accounted for.
Commit Traceability PASS Both commits reference TC-6934 (Implements TC-6934 trailer).
Sensitive Patterns PASS No secrets, credentials, keys, or sensitive values in any added line (lock.yaml hashes/SHAs and the boolean env-var flag are not secrets).
CI Status PASS All head-SHA check runs completed with conclusion success (Script Unit Tests 3.11-3.14, Plugin Validation, Skill Lint, Sourcery).
Acceptance Criteria PASS 6 of 6 criteria met: default false, exact 'true' true, invalid value fail-closed exit 1, never sandbox-exposed, harness re-pinned/re-locked (verify-pr untouched), fullsend.md documents opt-in + TC-6191 gating.
Test Quality PASS Repetitive Test Detection: PASS; Test Documentation: PASS (all added tests have docstrings); Eval Quality: N/A (no eval reviews).
Test Change Classification ADDITIVE +3 test functions, +10 parameterized cases, one existing test strengthened; no coverage removed or weakened.
Verification Commands PASS pytest validated via CI Script Unit Tests success (3.11-3.14); env var confirmed absent from any sandbox-exposed harness section.

Overall: PASS

All verification checks pass or are N/A. The PR implements the runner-side mutation-authorization opt-in exactly as specified: fail-closed parsing (exact true authorizes, unset/false stays report-only, any other value exits 1 with no bundle), the opt-in is never exposed to the sandbox, the triage-security harness was re-pinned and re-locked with verify-pr left untouched, and fullsend.md documents the opt-in and its TC-6191 CI gating. Tests cover all three value cases plus the executor/input-contract direction, and all CI checks are green. The single sourcery review observation describes intended by-design behavior and requires no code change. Informational rows (Root-Cause Investigation, Test Quality, Test Change Classification) do not affect the overall result. A human reviewer decides whether to merge.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.10.

@mrizzi
mrizzi merged commit 0bcdff9 into main Oct 26, 2026
27 checks passed
@mrizzi
mrizzi deleted the TC-6934 branch October 26, 2026 16:33
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.

1 participant