110 lines
5.7 KiB
Markdown
110 lines
5.7 KiB
Markdown
# PR#132: tools/draft-review Drafts a Review for a Human, with a Local Config and an HTML Report
|
|
|
|
Version: minor
|
|
|
|
> **WARNING:** This document describes only the change applied in this PR.
|
|
> It may already be outdated once the next PR is merged.
|
|
> Historic PR documentation is not maintained along with new PRs; treat it as a snapshot.
|
|
|
|
## Related Links
|
|
|
|
- [PR#129](2026-10-20-PR#129-hs-review-diagrams.md): the diagrams next to the draft.
|
|
- [PR#130](2026-10-21-PR#130-hs-review-attach.md): `--attach` posts the checked draft.
|
|
|
|
## Problem
|
|
|
|
`hs-review` drafts a review by werkrevisor and Codex for PRs that a human reviews, e.g. on dev.hostsharing.net.
|
|
It is a script in `~/bin` of one workstation, without version control and without review,
|
|
and it holds the server, the repository, the config and the names of the tokens of one host.
|
|
|
|
The draft is Markdown; a browser shows it only after a conversion by hand,
|
|
and its diagrams are images that open in no size of their own.
|
|
|
|
## Non-Goals
|
|
|
|
- No change of the review itself.
|
|
|
|
## Specification
|
|
|
|
### Feature: a draft review for a human, from a local config
|
|
|
|
#### Scenario#132.01: the local config names the host
|
|
|
|
… so that the repository holds no server, repository or token name of a user.
|
|
|
|
- **Given** a local config with server, default repository, werkrevisor config, secrets file and token names
|
|
- **When** the human runs `tools/draft-review 343`
|
|
- **Then** it reviews PR 343 of the default repository with the read token,
|
|
and prints the verdict with its strongest finding and the paths of the report
|
|
|
|
##### Verified by
|
|
|
|
- [test_draftreview.SettingsTest.test_the_local_config_names_server_repository_config_and_tokens](../../tests/test_draftreview.py)
|
|
- [test_draftreview.ResolveTest.test_a_number_means_a_pr_of_the_default_repository](../../tests/test_draftreview.py)
|
|
- [test_draftreview.MainTest.test_a_review_reads_with_the_read_token_and_prints_the_verdict](../../tests/test_draftreview.py)
|
|
- [test_draftreview.LinkTest.test_a_link_to_the_tool_finds_the_package_of_the_checkout](../../tests/test_draftreview.py);
|
|
red/green: with `abspath` instead of `realpath` the link did not find the package.
|
|
|
|
#### Scenario#132.02: a PR on another server gets no token
|
|
|
|
… so that the tokens of the configured server never go to another one.
|
|
|
|
- **Given** the local config of one server
|
|
- **When** the human runs `tools/draft-review` with the URL of a PR on another server
|
|
- **Then** it stops before any request and names the expected form of the URL
|
|
|
|
##### Verified by
|
|
|
|
- [test_draftreview.ResolveTest.test_a_pr_on_another_server_is_refused](../../tests/test_draftreview.py)
|
|
- [test_draftreview.MainTest.test_a_pr_on_another_server_gets_no_token](../../tests/test_draftreview.py)
|
|
|
|
#### Scenario#132.03: the report opens in a browser, with diagrams to zoom
|
|
|
|
… so that the human reads the draft in a browser and looks at each diagram at full size.
|
|
|
|
- **Given** a draft with diagrams, and pandoc on the workstation
|
|
- **When** `tools/draft-review` has written the draft
|
|
- **Then** `report.html` stands next to `report.md`, and a click on a diagram opens its SVG on its own
|
|
|
|
##### Verified by
|
|
|
|
- [test_draftreview.HtmlTest.test_the_report_gets_an_html_page_with_clickable_diagrams](../../tests/test_draftreview.py)
|
|
- [test_draftreview.HtmlTest.test_without_pandoc_there_is_no_html](../../tests/test_draftreview.py)
|
|
|
|
#### Scenario#132.04: the page runs no script of the draft
|
|
|
|
… so that a PR cannot place a script in a finding that runs when the human opens the report.
|
|
|
|
- **Given** a draft whose finding quotes `<script>` or a `javascript:` link, as a model may copy it from the PR
|
|
- **When** `tools/draft-review` writes `report.html` and the human opens it
|
|
- **Then** the script shows as text and runs not, and the page allows no script at all
|
|
|
|
##### Verified by
|
|
|
|
- [test_draftreview.HtmlTest.test_the_page_runs_no_script_of_the_draft](../../tests/test_draftreview.py);
|
|
red/green with pandoc 3: before the fix `report.html` held the `<script>` of the finding and no policy,
|
|
after it the `<script>` is text and the page has `Content-Security-Policy: default-src 'none'; …`.
|
|
- [test_draftreview.HtmlTest.test_a_draft_cannot_inject_a_script_with_pandoc](../../tests/test_draftreview.py),
|
|
where pandoc is installed; red/green with pandoc 3: with `markdown-raw_html` and pandoc's template,
|
|
a YAML block and raw attributes in a finding put 3 scripts into the page, 2 of them into the head before the policy;
|
|
`gfm-raw_html` and `commonmark-raw_html` still kept the inline `<script>`;
|
|
with `markdown_strict-raw_html+pipe_tables` and the own template none.
|
|
|
|
## Solution
|
|
|
|
- `tools/draft-review` and `werkrevisor/draftreview.py` replace `~/bin/hs-review` of one workstation:
|
|
they read `~/.config/werkrevisor/draft-review.toml`, resolve a PR number or URL against its server,
|
|
read the secrets file, pass the read token, or the write token for `--attach`, to `tools/review-report`,
|
|
print the summary line and write `report.html` with pandoc.
|
|
- `report.html` is strict Markdown without raw HTML, plus tables (`--from markdown_strict-raw_html+pipe_tables`):
|
|
no raw HTML, no YAML metadata block, no raw attribute;
|
|
an own template puts a Content Security Policy without scripts first into the head
|
|
and takes only the body and our title from pandoc;
|
|
a link with `javascript:`, `vbscript:` or `data:` leads to `#blocked-…`, also where a browser ignores the policy.
|
|
The Codex reviews of `61b5b80` and `cf1f13c` found the holes.
|
|
- `werkrevisor/reviewreport.py` links each diagram to its SVG: `[](name)`;
|
|
`--attach` points both to the attachment.
|
|
- `README.md`, "Draft review": the local config, with example values.
|
|
- On the workstation, `~/bin/hs-review` becomes a link to `tools/draft-review`,
|
|
and `~/.config/werkrevisor/draft-review.toml` holds the values of dev.hostsharing.net.
|