feat(safeoutputs): add dynamic tags with allowed-tags to create/update work item#420
Conversation
…e work item Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/35468e9f-e355-404b-bfdf-b5f8b34d9d85 Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
|
@copilot does this align with GitHub/gh-aw approach for issues? |
Yes — this follows the same pattern gh-aw uses for
One small extension beyond the gh-aw baseline: ado-aw supports prefix wildcards in The same |
|
/rust-review |
|
@copilot What is gh-aw's allowed default labels? Does it allow all agent provided labels by default? |
|
✅ Rust PR Reviewer completed successfully! |
Yes — from AllowedLabels []string `yaml:"allowed-labels,omitempty"` // Optional list of allowed labels. If omitted, any labels are allowed (including creating new ones).When Our |
🔍 Rust PR ReviewSummary: Mostly solid — one correctness bug in the allowlist implementation, plus a DRY concern for a security-critical path. Findings🐛 Bugs / Logic Issues
|
|
@copilot create_work_item.rs:312 / update_work_item.rs:476 — prefix wildcard matching is case-sensitive, exact matching is not Both files share this same pattern: if let Some(prefix) = pattern.strip_suffix('') { Fix: if let Some(prefix) = pattern.strip_suffix('*') { |
…ensitive prefix matching - Add shared `pub(crate) fn tag_matches_pattern(tag, pattern)` to src/safeoutputs/mod.rs; both prefix-wildcard and exact branches are now fully case-insensitive (fixes the bug where `allowed-tags: ["Agent-*"]` silently failed to match `"agent-created"`) - Replace the duplicated inline closures in create_work_item.rs and update_work_item.rs with calls to the shared helper - Add unit tests covering case-insensitive prefix wildcard matching in mod.rs, create_work_item.rs, and update_work_item.rs Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/82fb0a02-078e-4c88-bf92-f4b0b0464462 Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
…iles Agent-Logs-Url: https://github.com/githubnext/ado-aw/sessions/82fb0a02-078e-4c88-bf92-f4b0b0464462 Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Fixed in commit Both issues are addressed: Bug fix — prefix wildcard matching is now case-insensitive, consistent with exact matching: // Before (case-sensitive prefix, case-insensitive exact — inconsistent)
if let Some(prefix) = pattern.strip_suffix('*') {
tag.starts_with(prefix)
} else {
pattern.eq_ignore_ascii_case(tag)
}
// After — both branches case-insensitive
tag.to_ascii_lowercase().starts_with(&prefix.to_ascii_lowercase())Refactor — the shared Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
create-work-itemonly accepted agent-suppliedtitleanddescription; tags were static operator config only.update-work-itemhad no tag allowlist. Both tools now follow the same allow-list pattern used bycreate-pull-request(labels) andadd-build-tag— and mirrors thecreate-issuepattern in gh-aw.Summary
create-work-itemtags— agents can now supply tags dynamically; each tag is validated to reject semicolons (ADO's tag separator)allowed-tags— restricts which agent-supplied tags are accepted; empty = any (default, same as gh-aw'sallowed-labels). Supports prefix wildcards ("agent-*")tagsfrom config always applied; agent tags appended after allowlist check (case-insensitive dedup)update-work-itemallowed-tags— whentags: true, restricts which tags the agent may set; same prefix wildcard semantics; empty = any (default)This aligns with the gh-aw
create-issuepattern:labels(static, always applied) +allowed-labels(allowlist for agent-provided labels, empty = any labels allowed, including creating new ones). The only ADO-specific extension is prefix wildcard support (e.g."agent-*"), consistent with the existingadd-build-tagbehaviour.Allowlist matching (
tag_matches_pattern)tag.starts_with(prefix)) while exact matching was case-insensitive (eq_ignore_ascii_case). An operator writingallowed-tags: ["Agent-*"]would silently fail to match an agent-provided tag"agent-created". Both branches are now fully case-insensitive.create_work_item.rsandupdate_work_item.rshas been extracted into a sharedpub(crate) fn tag_matches_pattern(tag: &str, pattern: &str) -> boolinsrc/safeoutputs/mod.rs, so future fixes only need to be made in one place.Example front matter
Test plan
cargo test— unit tests cover: semicolon rejection, allowlist enforcement, case-insensitive prefix wildcard matching (including mixed-case patterns), exact case-insensitive matching,*-only wildcard, config deserialization defaults, and tag merging. Thetag_matches_patternhelper tests live insrc/safeoutputs/mod.rs.