Skip to content

feat: tag swamp-originated lab issues with source="swamp"#1140

Merged
stack72 merged 1 commit intomainfrom
feat/lab-issue-source-swamp
Apr 8, 2026
Merged

feat: tag swamp-originated lab issues with source="swamp"#1140
stack72 merged 1 commit intomainfrom
feat/lab-issue-source-swamp

Conversation

@stack72
Copy link
Copy Markdown
Contributor

@stack72 stack72 commented Apr 8, 2026

Summary

swamp-club#375 added a source field on lab issues so each one is attributed to its origin (swamp-club, swamp, extensions, UAT). Both paths in this repo that create lab issues defaulted to swamp-club, which is wrong. Tag both with source: "swamp" so the Lab UI shows the correct chip and filter bucket.

  • CLISwampClubClient.submitIssue (used by swamp issue bug | feature | security) now sends source: "swamp" as a top-level field on the JSON payload alongside type, title, and body.
  • GitHub auto-responder.github/workflows/auto-response.yml switches from the admin-only /api/v1/lab/issues/ensure endpoint (which doesn't accept source) to the public /api/v1/lab/issues endpoint, and tags submissions with source: "swamp". The footer is expanded to include the full GitHub issue URL (issue.html_url) so the back-link survives the loss of the structured githubRepoFullName / githubIssueNumber fields that the public endpoint doesn't accept.

The extension lifecycle client (extensions/models/_lib/swamp_club.ts) was refactored in #1139 to operate only on existing issues by number — it no longer creates lab issues, so nothing to update there.

Notes

  • The /issues endpoint accepts the same Bearer ${SWAMP_CLUB_API_KEY} header as /ensure, confirmed via swamp-club's routes/_middleware.ts which recognizes Bearer swamp_… API keys for any /api/* route.
  • /issues is not idempotent on (repo, issueNumber) like /ensure was, but auto-response.yml only fires on issues.opened (one-shot per GitHub issue), so dedup behavior is unchanged in practice.
  • swamp-club's MAX_TITLE_LENGTH is 256 chars; GitHub titles can exceed this. The current workflow doesn't truncate — same as before. Failures keep the GitHub issue open via core.setFailed.

Test plan

  • deno fmt — clean
  • deno lint — clean
  • deno check — clean
  • deno run test4204 passed, 0 failed (includes 2 new submitIssue tests that capture the actual HTTP request body and assert capturedBody.source === "swamp")
  • deno run compile — recompiled
  • Manual: swamp issue bug --title "source smoke" --body "verify source=swamp" --json, then open the resulting issue in the swamp.club UI and confirm the "Swamp CLI" chip appears
  • Post-merge: open a throwaway issue on systeminit/swamp and verify the auto-responder produces a lab issue with the "Swamp CLI" chip and a footer linking back to the GitHub URL

🤖 Generated with Claude Code

swamp-club#375 added a `source` field to lab issues so each one can be
attributed to its origin (web app, CLI, extensions, UAT). Both paths in
this repo that create lab issues — the CLI's `swamp issue` command and
the GitHub auto-responder workflow — were defaulting to "swamp-club".
Tag both with `source: "swamp"`.

The auto-responder also switches from `/api/v1/lab/issues/ensure` to the
public `/api/v1/lab/issues` endpoint, since `/ensure` doesn't accept the
`source` field. The footer is expanded to include the full GitHub issue
URL so the back-link survives the loss of the structured
githubRepoFullName/githubIssueNumber fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Code Review

Clean, well-scoped PR. The source: "swamp" field is correctly added in both paths (CLI client and GitHub workflow), and the explicit field listing in submitIssue prevents any unexpected properties from leaking into the payload.

Blocking Issues

None.

Suggestions

None — the tests cover both success and failure paths, the workflow changes are consistent, and the handler type widening (Response | Promise<Response>) in the test helper is a nice touch to support the async mock.

Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

CI Security Review

Critical / High

None.

Medium

None.

Low

None.

Analysis

Prompt Injection — Not applicable. No LLM is invoked in this workflow.

Expression Injection — Safe. The workflow uses actions/github-script where issue data (issue.title, issue.body, issue.html_url) is accessed via JavaScript variables and serialized through JSON.stringify(). No ${{ }} interpolation of untrusted data in run: blocks or YAML contexts.

Dangerous Triggersissues: [opened] is triggered by external users, but the workflow only reads issue metadata and forwards it to an external API via properly serialized JSON. No code checkout, no code execution from issue content.

Supply Chainactions/github-script@v7 is a GitHub-owned action, acceptable with tag-only pin per policy.

Permissionsissues: write and contents: read at workflow level. Single-job workflow, so workflow-level scoping is equivalent to job-level. Permissions are minimal for the task (comment, close issue, read content).

Secret ExposureSWAMP_CLUB_API_KEY is accessed via process.env, used only in the Authorization header of a fetch call. Not logged or interpolated into shell commands. Error messages do not leak the secret.

Auto-merge — Not applicable; this workflow does not merge anything.

Verdict

PASS — The changes are security-neutral. The endpoint switch from /ensure to /issues, the addition of source: "swamp", and the footer format change introduce no new attack surface. All untrusted issue data continues to flow through JSON.stringify() serialization.

Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Adversarial Review

Critical / High

None.

Medium

  1. .github/workflows/auto-response.yml:43-57 — Loss of idempotency creates duplicate risk on workflow re-runs.
    The old /ensure endpoint was idempotent on (repo, issueNumber). The new /issues endpoint is not. If the workflow succeeds at creating the lab issue (line 43) but then fails at createComment (line 93) or issues.update (line 102) — e.g. due to a transient GitHub API error — and an admin manually re-runs the workflow, a second lab issue will be created. The PR notes acknowledge this and argue that issues.opened is one-shot, which is true for automatic triggers, but manual re-runs bypass that.
    Breaking example: Lab issue created → createComment times out → admin clicks "Re-run all jobs" → duplicate lab issue with duplicate footer.
    Suggested fix: Accept as-is if duplicates are tolerable, or add a comment in the workflow warning maintainers not to re-run the job (since the lab issue may already exist). Alternatively, check for an existing comment from the bot before creating a new lab issue.

Low

  1. .github/workflows/auto-response.yml:54type is hardcoded to "feature" for all GitHub issues. Bug reports opened on GitHub will be tagged as features in the Lab. This is pre-existing behavior (not introduced by this PR), but worth noting since the PR is already touching this payload — it would be a one-line fix to attempt to infer the type from GitHub labels.

  2. src/infrastructure/http/swamp_club_client.ts:180-185 — Explicit field enumeration is good but brittle if the input type grows. If a new field is added to the input parameter type in the future, a developer could add it to the TypeScript type but forget to add it to the JSON.stringify object literal. The old JSON.stringify(input) pattern would have forwarded it automatically. This is a minor maintainability concern, not a bug — the explicit enumeration is arguably safer since it prevents accidental field leakage.

Verdict

PASS — Clean, well-scoped change. The idempotency trade-off is acknowledged and acceptable given the one-shot trigger semantics. Tests cover the new behavior. No security, correctness, or resource management issues found.

@stack72 stack72 merged commit 06888df into main Apr 8, 2026
11 checks passed
@stack72 stack72 deleted the feat/lab-issue-source-swamp branch April 8, 2026 01:39
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