Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/commands/check-ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ Run all CI checks locally, in order. Stop and report if any step fails.
5. `cd crates/trusted-server-js/lib && npx vitest run`
6. `cd crates/trusted-server-js/lib && npm run format`
7. `cd docs && npm run format`
8. `cargo run --manifest-path crates/trusted-server-cli/Cargo.toml --target "$(rustc -vV | sed -n 's/host: //p')" --bin ts -- dev lint domains --changed-vs origin/main` (use the PR's base branch in place of `main` when it targets another branch)

Report a summary of all results when done.
39 changes: 39 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,45 @@ jobs:
cargo test --manifest-path crates/trusted-server-cli/Cargo.toml --target "$TARGET" \
--test proxy_trust_linux -- --ignored

lint-domains:
# Server-side counterpart to the `ts dev install-hooks` pre-commit hook,
# which `--no-verify` skips and fresh clones never install: fail the PR
# when an added line introduces a non-allowlisted URL host. PR-only, so
# direct pushes to main are not linted.
name: ts dev lint domains (changed lines)
Comment thread
dhruv8sh marked this conversation as resolved.
Comment thread
dhruv8sh marked this conversation as resolved.
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
# A PR checkout is GitHub's merge commit; depth 2 also fetches its
# parents, so `HEAD^1` is the exact base commit the PR merges into.
- uses: actions/checkout@v4
with:
fetch-depth: 2
Comment thread
dhruv8sh marked this conversation as resolved.

- name: Set up Rust toolchain
uses: ./.github/actions/setup-rust
with:
# Restore `test-cli`'s cache read-only. The action only saves on
# main and this job only runs on PRs; `save-cache` keeps it
# restore-only if either changes.
cache-key: cargo-cli
save-cache: "false"

# Building `ts` compiles trusted-server-core, whose trusted-server-js
# build script runs the TSJS build with the `npm` on PATH, so pin Node
# first (see #1204).
- name: Use Node.js for the TSJS build
uses: actions/setup-node@v4
with:
node-version-file: .tool-versions

# The `ts` CLI is host-target only; the workspace default is wasm32-wasip1.
Comment thread
dhruv8sh marked this conversation as resolved.
- name: Lint URL hosts on lines added by this PR
run: |
cargo run --manifest-path crates/trusted-server-cli/Cargo.toml \
--target "$(rustc -vV | sed -n 's/host: //p')" --bin ts -- \
dev lint domains --changed-vs HEAD^1 --verbose

test-typescript:
name: vitest
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ Every PR must pass:
9. Native core build-digest test and lint (`cargo test -p trusted-server-core --test template_build_digest` and `cargo clippy -p trusted-server-core --test template_build_digest -- -D warnings`)
10. Wasm clock lint: `scripts/lint-wasm-clock.sh` (crates built into the Cloudflare Worker must use `web_time`, not the `std::time::{Instant,SystemTime}` `now`/`elapsed` methods, which panic there)
11. Documentation proposal scripts: `shellcheck scripts/docs-proposal/*.sh && node --test scripts/docs-proposal/hunks.test.mjs && scripts/docs-proposal/test.sh`
12. URL-host linter on lines the PR adds (`lint-domains` job, PRs only); run it locally with `cargo run --manifest-path crates/trusted-server-cli/Cargo.toml --target <host-triple> --bin ts -- dev lint domains --changed-vs origin/main`, using the PR's base branch in place of `main` when it targets another branch

CI also runs these HTML EOF checks. Run them locally only when changing EOF
finalization, publisher or HTML-processor code:
Expand Down
11 changes: 10 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,18 @@ To scan on demand, `ts dev lint domains` audits the whole working tree and
`--changed-vs <ref>` limits it to lines added against a ref. The full audit
reports pre-existing violations, so a non-zero exit is expected today.

CI runs the same check on every pull request: the `lint-domains` job scans the
lines the PR adds against its base branch, so `--no-verify` or a missing hook
does not let a host through. Editing or moving a line that already contains a
non-allowlisted host counts as adding it. Reproduce the job locally with
`ts dev lint domains --changed-vs origin/main`, using the PR's base branch in
place of `main` when it targets another branch.

To allow a new host, add it to the allowlist constants in
`crates/trusted-server-cli/src/commands/dev/lint/domains.rs`. To suppress a
single line, append `// allow-domain: <host>` in a comment.
single line, append `allow-domain: <host>` in the file's comment syntax:
`// allow-domain: <host>`, `# allow-domain: <host>`,
`<!-- allow-domain: <host> -->`, or `* allow-domain: <host>`.

## Commits

Expand Down
8 changes: 8 additions & 0 deletions docs/superpowers/specs/2026-05-18-check-domains-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,14 @@ delta-only enforcement, unbypassable. Requirements:
- Reuse the host-target CI lane introduced by PR #669 (since `ts`
binary is host-target only).

As implemented in #1254, Stage 2 differs from the plan above. It is
its own `lint-domains` job rather than a step in the host-target lane,
so branch protection can require it by name. It runs
`--changed-vs HEAD^1` on a `fetch-depth: 2` checkout rather than
`$GITHUB_BASE_REF` on a full clone: a PR checkout is GitHub's merge
commit, so its first parent is the exact base commit, and depth 1
fails closed (exit 2).

**Stage 3 (optional, deferred):** Either (a) clean existing violations
and add full-repo audit as a CI gate, or (b) snapshot a baseline file
and run full-repo audit with baseline subtraction. Choice deferred
Expand Down
Loading