Skip to content

feat(jira): include Jira attachments and recent comments in task context (#577)#619

Open
ayushtr-aws wants to merge 3 commits into
aws-samples:mainfrom
ayushtr-aws:feat/577-jira-attachments-comments
Open

feat(jira): include Jira attachments and recent comments in task context (#577)#619
ayushtr-aws wants to merge 3 commits into
aws-samples:mainfrom
ayushtr-aws:feat/577-jira-attachments-comments

Conversation

@ayushtr-aws

Copy link
Copy Markdown
Contributor

What

Closes #577. Jira-origin tasks now receive the same practical issue context Linear-origin tasks can use — attached files and recent comments, not just the summary/description. Because the Atlassian Remote MCP can't run headlessly (see the parent tracker #580 design note), the context is fetched authenticated at task-admission time in the webhook processor rather than on demand by the agent.

How

  • cdk/src/handlers/shared/jira-attachments.ts (new) —
    • downloadScreenAndStoreJiraAttachments: resolves Jira media attachments via the gateway attachment-content endpoint (api.atlassian.com/ex/jira/{cloudId}/rest/api/3/attachment/content/{id} — the only host the 3LO token is valid against), refresh-and-retry-once on 401/403, enforces the size cap while streaming, validates magic bytes, screens each through the existing Bedrock Guardrail pipeline, uploads cleaned bytes to S3, and returns passed AttachmentRecords. Fail-closed: a selected attachment that can't be safely fetched/screened throws and the task is rejected with a Jira comment. Unsupported/oversized/over-cap attachments are silently skipped. Filenames sanitized + ids validated to prevent S3-key / on-disk path traversal.
    • fetchRecentHumanComments: recent human (accountType: atlassian) comments, ADF→markdown, oldest-first. Fail-open: any failure proceeds without them.
  • cdk/src/handlers/shared/jira-adf.ts (new) — extracted the ADF→markdown walker so the processor and comment helper share it without a circular import (behavior-preserving).
  • cdk/src/handlers/shared/create-task-core.tsTaskCreationContext gains optional taskId (so processor-uploaded S3 keys match the eventual record) and preScreenedAttachments (merged verbatim, never re-screened; a non-passed record fails closed).
  • cdk/src/handlers/jira-webhook-processor.ts — wires both in; comments fold under a ## Recent comments heading, bounded so they never push task_description past the 10k limit (advisory context must not become a hard gate).
  • cdk/src/constructs/jira-integration.ts + agent.ts — pass the attachments bucket to the processor, grant ReadWrite + ATTACHMENTS_BUCKET_NAME, bump the async processor timeout to 60s for serial download+screen. No new OAuth scopes (read:jira-work covers reading attachments + comments).
  • cdk/src/constructs/task-api.ts — exempt /v1/jira/webhook from the WAF SizeRestrictions_BODY managed rule (mirrors the existing Linear/GitHub webhook exemptions). Jira issue payloads carrying attachment metadata exceed the 8 KB body limit and were being blocked at the edge (403) before the receiver Lambda ran — so this is required for feat(jira): include Jira attachments and recent comments in task context #577 to function. The receiver still HMAC-verifies the raw body and the rate-limit rule still applies.

Docs

docs/guides/JIRA_SETUP_GUIDE.md gets an "Issue context: attachments and comments" section (supported types, limits, skip-vs-reject behavior, comment behavior) + regenerated Starlight mirror.

Tests

  • jira-attachments.test.ts (new): download/filter/screen/upload, filename sanitization + unsafe-id rejection, 401 refresh-and-retry, size cap, magic-byte reject, screen-blocked → throw, comment human/app filtering + ADF→markdown + fail-open.
  • jira-webhook-processor.test.ts: comment folding + truncation, fail-closed attachment rejection, remaining-slots math, no-attachments path.
  • create-task-core.test.ts: preScreenedAttachments merge without re-screening, caller-supplied taskId, non-passed fail-closed.
  • task-api.test.ts: WAF exemption present in both the exclusion scope-down and the full-CRS scope-down.

mise run build green (cdk 2357 tests, cli 605, agent + docs pass, synth clean).

Validated end-to-end

Deployed to a dev stack and triggered from a real Jira Cloud tenant: a SCRUM issue with 2 image attachments + a comment triggered a task → comments fetched → both attachments authenticated-downloaded, Bedrock-screened, and stored to S3 → agent hydrated them → committed the images → opened a PR. Confirmed the full path works.

Out of scope

Atlassian Remote MCP support; Confluence/project documents; fetching full historical comment threads; new attachment limits or file types beyond what ABCA already screens.

…ext (aws-samples#577)

Jira-origin tasks previously saw only the issue summary + description (ADF→
markdown) plus embedded HTTPS image URLs. Jira-hosted `media` file attachments
and issue comments were invisible to the agent, so a ticket that says "see the
attached log" or carries acceptance clarifications in comments would run
under-informed. Bring Jira to parity with Linear's on-demand context reads by
fetching the context authenticated at task-admission time in the webhook
processor (the Atlassian Remote MCP can't run headlessly — see aws-samples#580).

- agent-admission download path (cdk/src/handlers/shared/jira-attachments.ts):
  * downloadScreenAndStoreJiraAttachments — resolve Jira `media` attachments via
    the gateway attachment-content endpoint (api.atlassian.com/ex/jira/{cloudId},
    the only host the 3LO token is valid against), refresh-and-retry-once on
    401/403, enforce the size cap while streaming, validate magic bytes, screen
    through the existing Bedrock Guardrail, upload cleaned bytes to S3, and
    return `passed` AttachmentRecords. Fail-closed: a selected attachment that
    can't be safely fetched/screened throws JiraAttachmentError and the task is
    rejected with a Jira comment. Unsupported/oversized/over-cap attachments are
    silently skipped. Filenames are sanitized and ids validated to a safe token
    so neither can traverse the S3 key / agent on-disk path.
  * fetchRecentHumanComments — recent human (accountType `atlassian`) comments,
    ADF→markdown, oldest-first. Fail-open: any failure proceeds without them.
- create-task-core: TaskCreationContext gains optional `taskId` (so processor-
  uploaded S3 keys match the eventual record) and `preScreenedAttachments`
  (merged verbatim, never re-screened; a non-`passed` record fails closed).
- jira-webhook-processor: wire both in; comments fold under a "## Recent
  comments" heading, bounded so they never push task_description past the 10k
  limit (advisory context must not become a hard gate).
- jira-adf.ts: extract the ADF→markdown walker so the processor and the comment
  helper share it without a circular import (behavior-preserving).
- CDK: pass the attachments bucket to JiraIntegration; grant the processor
  ReadWrite + ATTACHMENTS_BUCKET_NAME env; bump the async processor timeout to
  60s for serial download+screen. No new OAuth scopes (read:jira-work covers it).
- docs: JIRA_SETUP_GUIDE "Issue context: attachments and comments" (supported
  types, limits, skip vs fail-closed reject, comment behavior) + Starlight mirror.

Tests: new jira-attachments.test.ts (download/filter/screen/upload, sanitize,
401 retry, size cap, comment human/app filter + fail-open); processor tests for
comment folding + truncation and fail-closed attachment rejection; create-task-
core tests for preScreenedAttachments merge + taskId. `mise run build` green.
…s-samples#577)

Jira issue webhook payloads that carry attachment metadata exceed the AWS
managed `SizeRestrictions_BODY` 8 KB limit, so WAF returned 403 at the edge and
the webhook receiver Lambda never ran — the delivery vanished before ABCA saw
it. This is exactly the case aws-samples#577 depends on (an issue with file attachments),
so without this exemption the feature can't work in any WAF-protected deploy.

Mirror the existing `/v1/linear/webhook` and `/v1/github/webhook` handling —
both rules must be updated together:
- AWSManagedRulesCommonRuleSet-TaskPaths (excludes SizeRestrictions_BODY): add
  `/v1/jira/webhook` to the orStatement scope-down so large Jira bodies pass.
- AWSManagedRulesCommonRuleSet (full CRS for other paths): add a NOT
  `/v1/jira/webhook` clause so the path isn't re-covered by the strict rule.

The receiver still HMAC-verifies the raw body and the priority-4 rate-limit
rule still applies, so relaxing the body-size check on this path is safe.

Test: task-api.test.ts asserts the exclusion scope-down contains the Jira path
and the full-CRS scope-down excludes it. 42 pass.
…amples#577)

The Jira attachment-content endpoint
(`/rest/api/3/attachment/content/{id}`) serves the file's own media type and
responds 406 Not Acceptable to a narrow `Accept: application/octet-stream`.
That made every attachment download fail with HTTP 406, and the fail-closed
path then rejected the whole task ("could not be downloaded (HTTP 406)").
Send `Accept: */*` so the gateway serves the real content type.

Verified against the live endpoint: octet-stream → 406, */* → 200.
Test asserts the download request sets Accept: */*.
@ayushtr-aws ayushtr-aws requested review from a team as code owners July 16, 2026 02:15
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 95.61224% with 43 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@22705e8). Learn more about missing BASE report.

Files with missing lines Patch % Lines
cdk/src/handlers/shared/jira-attachments.ts 95.54% 26 Missing ⚠️
cdk/src/handlers/shared/jira-adf.ts 89.80% 16 Missing ⚠️
cdk/src/handlers/jira-webhook-processor.ts 99.25% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #619   +/-   ##
=======================================
  Coverage        ?   89.44%           
=======================================
  Files           ?      226           
  Lines           ?    55205           
  Branches        ?     5587           
=======================================
  Hits            ?    49376           
  Misses          ?     5829           
  Partials        ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

feat(jira): include Jira attachments and recent comments in task context

2 participants