Skip to content

fix(server): stop imposing one instance's status workflow - #77

Merged
plusky merged 2 commits into
plusky:mainfrom
mimi1vx:bugz_api_e
Aug 9, 2026
Merged

fix(server): stop imposing one instance's status workflow#77
plusky merged 2 commits into
plusky:mainfrom
mimi1vx:bugz_api_e

Conversation

@mimi1vx

@mimi1vx mimi1vx commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Two self-contained commits, each verified independently (builds/tests/lints
clean on its own).

What

update_bug_status and mark_as_duplicate hard-coded one Bugzilla
instance's status workflow, and bug_fields discarded exactly the data
that would let a client discover it instead of guessing.

  • fix(server): stop imposing one instance's status workflow
    update_bug_status dropped a local CLOSED-requires-resolution
    pre-check (it missed RESOLVED and every custom closed status, and
    fired on instances where CLOSED isn't even the closing status) along
    with a synthesised "resolution": "" on every non-CLOSED/VERIFIED
    target — verified against Bugzilla::Bug::set_bug_status, that empty
    string makes a stock RESOLVED transition fail with
    missing_resolution, an upstream error the tool was causing, not
    avoiding. The payload now sends status always and resolution only
    when the caller gives a non-empty one; Bugzilla enforces the
    resolution requirement itself and clears it automatically on reopen.
    mark_as_duplicate similarly stopped forcing status = CLOSED
    set_dup_id already applies the instance's own
    duplicate_or_move_bug_status (plus resolution DUPLICATE) from
    dupe_of alone.
  • feat(server): report the status workflow in bug_fields
    bug_fields's detail projection reduced legal values to bare names,
    dropping is_open and can_change_to, the exact fields Bugzilla
    attaches to bug_status for this purpose. Each legal value now
    projects to {name} plus is_open/can_change_to (itself
    [{name, comment_required}]) when the upstream value carries them;
    absent keys are omitted, never null, so every other field's values
    stay exactly as cheap as before.

Behavior change

On a stock Bugzilla instance, mark_as_duplicate now leaves a bug in
RESOLVED/DUPLICATE rather than always CLOSED/DUPLICATE, because the
operator's duplicate_or_move_bug_status decides, not this server.
Anyone with a runbook expecting CLOSED/DUPLICATE needs to update it.

Invariants touched

  • I11 — unaffected; the capability checks on bug_id/duplicate_of
    are untouched, only the resulting write payload changed.
  • I15 — unaffected; every routed tool still has an
    audit_refusal_text entry and writes exactly one audit record per
    call (existing tests unmodified).
  • I16 — unaffected; bug_fields's workflow data is still reported
    exactly as Bugzilla gave it, never filtered against the guard policy.

Verification

  • cargo fmt --check
  • cargo clippy --workspace --all-targets --locked -- -D warnings
  • cargo clippy -p bugwarden --features gen --all-targets --locked -- -D warnings
  • cargo test --workspace --all-targets --locked — all green, including:
    • crates/bugwarden/tests/tools_wiremock.rs: update_bug_status
      without a resolution PUTs exactly {"status": ...} (no synthesised
      resolution); with a resolution PUTs both; targeting CLOSED
      without one now reaches upstream instead of being refused locally;
      mark_as_duplicate PUTs exactly dupe_of + comment; the bug_fields
      detail test extended to assert is_open/can_change_to survive the
      projection for bug_status while a plain field (priority) still
      projects to {name}-only.
  • cargo deny check — clean (no new dependencies).
  • Each commit verified standalone in an isolated worktree (fmt, clippy,
    test, deny) — both build and pass on their own, not just as a pair.

mimi1vx added 2 commits August 9, 2026 13:03
update_bug_status hard-coded a workflow no Bugzilla instance is
required to have: a local CLOSED/resolution pre-check that missed
RESOLVED and any custom closed status, and a synthesised
"resolution": "" on every non-CLOSED/VERIFIED target that Bugzilla's
_check_resolution actually rejects (missing_resolution) on a stock
RESOLVED transition. mark_as_duplicate had the same assumption,
hard-coding status=CLOSED alongside dupe_of.

Bug.pm's set_bug_status already clears the resolution itself when the
target status is open, and set_dup_id already applies the instance's
duplicate_or_move_bug_status when dupe_of is set alone — so both local
guesses were dead weight on stock behavior and wrong on customized
workflows. Drop them: update_bug_status sends resolution only when the
caller gives a non-empty one, and mark_as_duplicate sends dupe_of (and
the comment) only, letting Bugzilla decide the resulting status.

Accepted behavior change: mark_as_duplicate now lands a bug in
whatever status the instance's duplicate_or_move_bug_status names
(RESOLVED/DUPLICATE on stock Bugzilla) rather than always CLOSED.
bug_fields' detail projection reduced legal values to bare names,
dropping the is_open and can_change_to data Bugzilla attaches to
bug_status specifically — exactly what a client would need to learn
an instance's status workflow instead of guessing it, which is what
update_bug_status and mark_as_duplicate now defer to Bugzilla for.

Project each legal value to {name}, plus is_open and can_change_to
(itself projected to [{name, comment_required}]) when the upstream
value carries them. Absent keys are omitted, never null, so every
non-workflow field's values stay exactly as cheap as before. The
catalog shape (no field_names) is untouched, and the data is reported
exactly as Bugzilla gave it — I16's guard-policy exemption already
covers it.
@plusky
plusky merged commit 132f89c into plusky:main Aug 9, 2026
11 checks passed
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.

2 participants