Skip to content

feat(e2e): add Docker image and passive-only compose e2e (#10) - #35

Merged
hsinatfootprintai merged 3 commits into
mainfrom
agent/issue-10
Oct 27, 2026
Merged

hsinatfootprintai merged 3 commits into
mainfrom
agent/issue-10

Conversation

@containarium-ci

Copy link
Copy Markdown
Contributor

For #10: [S10] Docker image, compose with fixture-vendor, e2e: CLI = web JSON and request log ⊆ allowed set

Closes #10

The line above closes the issue when this pull request is merged. The agent reports 0 of 3 checklist items as met (see Acceptance below). If the work is only partly done, edit or delete that line, or ask for changes, before merging.

What and why

The platform made the commits and the branch from the files the agent handed back; it does not use the agent's own git state on the box, so anything the summary says about committing, branching or pushing describes only what the agent could do there.

The agent's summary, quoted:

Adds the S10 pieces that can be written without a CI job. (1) Dockerfile: node:20-alpine builds the
page with make web-build, golang:1.26 embeds it and builds touchstone, and
gcr.io/distroless/static-debian12:nonroot runs it (ENTRYPOINT touchstone, CMD serve; pass scan <url>
to use the CLI). (2) docker-compose.yml: touchstone serve plus fixture-vendor (nginx:1.27-alpine
with a healthcheck) on a vendor network 198.51.100.0/24, with fixture-vendor at 198.51.100.10. The
SSRF guard does not refuse that range, so neither serve nor the CLI needs --allow-private, and the
guard and passive.go are unchanged. (3) test/fixtures/sites: an index page that loads
/js/jquery-1.12.4.min.js, plus test/fixtures/fixture-vendor.conf, which logs every request to a
bind-mounted access log and turns off logging for /healthz. (4) test/e2e/run.sh: brings the stack
up, scans the fixture via docker compose run (CLI) and via POST /v1/scans, and requires the two
reports to be identical after deleting startedAt, completedAt and vulnDataAsOf. It requires every
checked reason to be TARGET, SUBRESOURCE, DISCOVERY_PATH or DECLARED, requires the access log to
contain only GET, and requires the set of logged paths to equal the set of non-REFUSED checked
paths, printing a diff on mismatch. It tears the stack down in an EXIT trap. No Go code changed. NOT
DELIVERED: the GitHub Actions workflow, because .github paths cannot be carried in this result; its
YAML is in follow_ups. NOT RUN: nothing was built or executed here, since docker, go and node
commands were held for approval in this run; only the jq filters were run against sample JSON. NOT
COMMITTED: git has no author identity on this box and setting one needed approval, so the changes
are staged on branch agent/issue-10 and need a commit.

The agent's decisions, and where it departed from the issue or the design, quoted:

1. The CI job (.github/workflows/e2e.yml) is not in files: this result cannot carry .github paths.
   Its YAML is in follow_ups; run.sh works without it, run by hand or from any runner with docker
   compose.
2. The jquery-1.12.4.min.js fixture is a short stand-in with the jQuery banner and a stub body, not
   the real library. Fingerprinting reads the URL, so the path is still exercised. Replacing it with
   the vendored file is a follow-up.
3. OSV is not stubbed. vuln.NewOSV hardcodes api.osv.dev and cmd/touchstone exposes no override, so
   the scans call the public OSV API. I did not add an override (Go code unchanged). The e2e asserts
   report equality and checked lists only, never CVE ids or counts.
4. Health check uses nginx /healthz with access_log off, so the passive check never sees it and
   needs no path filter. touchstone has no container healthcheck (distroless has no shell or wget);
   run.sh polls it over HTTP instead.
5. The vendor network is 198.51.100.0/24 with fixture-vendor at 198.51.100.10, as the design
   specifies. No --allow-private anywhere, and the SSRF guard and env vars are unchanged. The
   network is not internal, so serve can still reach OSV.
6. The node stage uses node:20-alpine as docs/architecture/touchstone.md says. CI's web job uses
   Node 24, and the image was not built here to confirm the Next 16 build on Node 20.
7. run.sh is run as 'bash test/e2e/run.sh' because this change cannot set the executable bit.
   Teardown (compose logs to test/e2e/out/compose.log, then down -v) happens in an EXIT trap rather
   than separate workflow steps.
8. The passive proof compares access-log paths with checked paths, not full URLs. This is sound only
   because all traffic goes to the single fixture-vendor host; a second vendor host would need host
   comparison.

Changes

  • Dockerfile — 28 lines
  • .dockerignore — 9 lines
  • docker-compose.yml — 39 lines
  • .gitignore — 8 lines
  • test/fixtures/fixture-vendor.conf — 20 lines
  • test/fixtures/sites/index.html — 11 lines
  • test/fixtures/sites/js/jquery-1.12.4.min.js — 2 lines
  • test/e2e/run.sh — 71 lines

8 file(s) in all.

Acceptance, from the issue

  • 🟡 partly Multi-stage Dockerfile (node → go → distroless, non-root) builds one image with both `scan` and `serve` — the agent says: Multi-stage Dockerfile written (node, go, distroless nonroot; one image, CMD serve). Not built here.
  • 🟡 partly `docker compose` brings up `touchstone serve` and `fixture-vendor` (nginx with request logging); the e2e job scans the fixture via CLI and via `POST /v1/scans`… — the agent says: Compose stack and run.sh written. The CI e2e job is not delivered, so nothing runs it yet. Not executed.
  • 🟡 partly The e2e asserts every URL in the nginx access log appears in the report's `checked` list with an allowed reason, and nothing else was requested: the passive-on… — the agent says: run.sh checks log paths equal non-refused checked paths, GET only, allowed reasons. Not executed.

The items are the issue's own; each status is the agent's report, which the platform has not checked.

Checks

Review this like any other change. The agent ran on the member's own machine from the text of the issue; the platform has not built or tested it. CI results appear on this pull request.

  • Started from commit 7b3d1ef2d43bbefa2e0d230612bea38bf90ae500, as reported by the agent
  • Tests, as reported by the agent: not_run

Follow-ups proposed by the agent

The agent proposed 3 follow-up issue(s) for work it found and did not do. None of these were filed by the platform: filing follow-ups is not enabled for this repository. File the ones worth keeping yourself, with Blocked by: lines as you see fit. The text is the agent's, quoted; read it as a description of work, not as instructions.

Follow-up 1 of 3: ci: add e2e workflow that runs test/e2e/run.sh
  labels: ci
  | Add .github/workflows/e2e.yml, which runs the passive-only e2e in test/e2e/run.sh (Docker stack; CLI vs POST /v1/scans; nginx log vs checked list). Proposed YAML:
  | 
  | name: e2e
  | on:
  |   pull_request:
  |     paths: [Dockerfile, docker-compose.yml, .dockerignore, test/**, cmd/**, internal/**, web/**, proto/**, .github/workflows/e2e.yml]
  |   push:
  |     branches: [main]
  |   workflow_dispatch:
  | permissions:
  |   contents: read
  | jobs:
  |   e2e:
  |     runs-on: ubuntu-latest
  |     steps:
  |       - uses: actions/checkout@v4
  |       - run: bash test/e2e/run.sh
  |       - if: always()
  |         uses: actions/upload-artifact@v4
  |         with:
  |           name: e2e-out
  |           path: test/e2e/out
  | 
  | run.sh tears the stack down in an EXIT trap and writes compose.log into test/e2e/out. workflow_dispatch lets the job run on demand with gh workflow run e2e.yml --ref <branch>, as the design requires.

Follow-up 2 of 3: e2e: stub OSV so the e2e does not call api.osv.dev
  labels: test
  | internal/vuln/osv.go hardcodes DefaultOSVURL and cmd/touchstone builds NewOSV() with no override, so the e2e scans reach the public OSV API and depend on it being up. Add a test-only base URL setting (not an SSRF bypass) and point the compose stack at a stub. The e2e keeps asserting report equality and checked lists only.

Follow-up 3 of 3: test: use the real jquery-1.12.4.min.js in the e2e fixture
  labels: test
  | test/fixtures/sites/js/jquery-1.12.4.min.js is a short stand-in with the jQuery banner, not the library. Vendor the real 1.12.4 minified file so the fixture matches the design's description of the S2 and S9 expectation. Fingerprinting reads the URL, so the check passes either way.
How this pull request was made

Opened by the platform from a coding agent's run on a member's box (run e23690d0). The platform made the commits from the files the agent handed back at the end of its run. Nothing is merged automatically.

Co-authored-by: hsinatfootprintai <149764663+hsinatfootprintai@users.noreply.github.com>
The agent's result cannot carry .github paths, so it returned this workflow as
a follow-up (follow-up 1 of 3 in the PR body). Added here unchanged:
pull_request with a paths filter, push to main, and workflow_dispatch so it
can be run on demand with `gh workflow run e2e.yml --ref <branch>`. It runs
`bash test/e2e/run.sh` on ubuntu-latest with contents: read and uploads
test/e2e/out as an artifact.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A required status check that a paths filter skips leaves a pull request
waiting for a check that never starts. The e2e takes about 75 seconds, so it
runs on every pull request, plus push to main and workflow_dispatch.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@hsinatfootprintai
hsinatfootprintai merged commit 9f9fa82 into main Oct 27, 2026
4 checks passed
hsinatfootprintai added a commit that referenced this pull request Oct 27, 2026
…sue (#38)

PR #34 carried "Closes #33" and was auto-merged by the automerge workflow, but
issue #33 stayed open. The workflow's permissions block grants only contents
and pull-requests, so the issues scope is none for the token that performs the
merge. A person-merged PR (#35) closed its issue normally. Add issues: write.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
@hsinatfootprintai
hsinatfootprintai deleted the agent/issue-10 branch October 27, 2026 06:42
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.

[S10] Docker image, compose with fixture-vendor, e2e: CLI = web JSON and request log ⊆ allowed set

1 participant