Skip to content
Merged
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
15 changes: 7 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: Download dependencies
run: go mod download
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: Build
run: go build -v ./...
Expand Down Expand Up @@ -104,7 +104,7 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: Build binary
run: go build -o ts-bridge ./cmd/ts-bridge/
Expand All @@ -131,7 +131,7 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: Build for ${{ matrix.goos }}/${{ matrix.goarch }}
env:
Expand All @@ -154,15 +154,15 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: golangci-lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9
with:
# Pinned so local `golangci-lint run` and CI report identical findings.
# Bump deliberately when the project upgrades; do not silently track latest.
# v2.x is required by golangci-lint-action@v9 and uses the v2 config schema.
version: v2.12.2
version: v2.14.0

security:
runs-on: ubuntu-latest
Expand All @@ -173,11 +173,10 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: Run gosec
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
gosec ./...
2 changes: 1 addition & 1 deletion .github/workflows/mutation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: Add GOPATH bin to PATH
run: echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod

- name: Run tests
run: go test -v ./...
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/repo-hygiene.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ jobs:
run: bash scripts/tests/test-check-review-published.sh
- name: Site changes keep their pull-request build gate
run: bash scripts/tests/test-site-pr-workflow.sh
- name: Go workflows follow the module toolchain
run: bash scripts/tests/test-go-toolchain.sh
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.26'
go-version-file: go.mod
- name: Install actionlint
run: go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.12
# ubuntu-latest ships shellcheck preinstalled; actionlint shells out to it to lint
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Portable TCP bridge over Tailscale/Headscale mesh networks using tsnet.

## Tech Stack

- **Language:** Go 1.26+
- **Language:** Go 1.27.1+
- **Key dependency:** `tailscale.com/tsnet` (userspace networking) — version pinned in `go.mod`
- **Architecture:** Single binary, multi-package — `cmd/ts-bridge/main.go` (~40 lines, thin entry point) delegates to the `cmd/cli` Cobra tree (ADR-010) over eight `internal/` packages (ADR-007).
- **Config:** Flags, environment variables, and YAML config files, in that precedence order, plus named profiles (ADR-011/012). `.env.example` documents the env-var surface; `init` writes either format.
Expand Down Expand Up @@ -44,7 +44,7 @@ go build -o ts-bridge ./cmd/ts-bridge/
go test -race -v ./...

# Lint (CI pins this version via golangci-lint-action@v9 — match it to avoid drift)
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.14.0
golangci-lint run

# Security scan
Expand Down
1 change: 1 addition & 0 deletions docs/lessons/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ tags: [ts-bridge, lessons, index]
| 034 | 2026-10-02 | A writer must not accept what its own reader rejects, the differential round-trip test that catches it, and why "refuses" must also write nothing | [lesson-034-2026-10-02.md](lesson-034-2026-10-02.md) | `config`, `cli`, `validation`, `testing`, `sdd` |
| 035 | 2026-10-03 | A prefix is a namespace not a type, validate the resolved config, listener collisions on normalized endpoints, tests own their goroutines, never assert on a bindable port range, and trusted gate code from the base branch | [lesson-035-2026-10-03.md](lesson-035-2026-10-03.md) | `credentials`, `config`, `testing`, `ci`, `security`, `windows` |
| 036 | 2026-10-06 | A guard over a text format must parse the unit it protects, a command matcher enumerates invocations, and mutate before the reviewer does | [lesson-036-2026-10-06.md](lesson-036-2026-10-06.md) | `testing`, `ci`, `sdd` |
| 037 | 2026-10-09 | Do not "fix" a module checksum mismatch by changing `go.sum` | [lesson-037-2026-10-09.md](lesson-037-2026-10-09.md) | `go`, `dependencies`, `supply-chain` |
21 changes: 21 additions & 0 deletions docs/lessons/lesson-037-2026-10-09.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
id: "lesson-037-2026-10-09"
type: lesson
status: active
title: "2026-10-09"
created: "2026-10-09"
owner: manu
tags: [ts-bridge, lesson, go, dependencies, supply-chain]
---

# 2026-10-09

**Do not "fix" a module checksum mismatch by changing `go.sum`.** During the
Tailscale v1.104.0 upgrade (#435), `go mod tidy` with the workstation's default
direct-first `GOPROXY` fetched `golang.zx2c4.com/wireguard/windows@v1.0.1`
with bytes that did not match the committed checksum. The public Go checksum
database confirmed the committed value; a fresh download through
`https://proxy.golang.org` matched it, and `go mod verify` succeeded. The
direct-origin discrepancy was not explained, so do not treat it as proof of a
compromise or silently accept its bytes. Keep `GOSUMDB` enabled and verify an
immutable proxy download against the public checksum before proceeding.
56 changes: 28 additions & 28 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
module ts-bridge

go 1.26.6
go 1.27.1

require (
github.com/spf13/cobra v1.10.2
golang.org/x/term v0.46.0
gopkg.in/yaml.v3 v3.0.1
tailscale.com v1.102.5
tailscale.com v1.104.0
tailscale.com/client/tailscale/v2 v2.11.0
)

require (
filippo.io/edwards25519 v1.2.0 // indirect
github.com/akutz/memconn v0.1.0 // indirect
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
github.com/coder/websocket v1.8.14 // indirect
github.com/creachadair/msync v0.8.1 // indirect
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/gaissmai/bart v0.26.1 // indirect
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e // indirect
github.com/coder/websocket v1.8.15 // indirect
github.com/creachadair/msync v0.10.1 // indirect
github.com/dblohm7/wingoes v0.0.0-20260526185140-fb298caac7ca // indirect
github.com/fxamacker/cbor/v2 v2.9.3 // indirect
github.com/gaissmai/bart v0.29.0 // indirect
github.com/go-json-experiment/json v0.0.0-20260820222146-c27c302e5fc3 // indirect
github.com/godbus/dbus/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jsimonetti/rtnetlink v1.4.1 // indirect
github.com/klauspost/compress v1.19.1 // indirect
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
github.com/mdlayher/socket v0.5.0 // indirect
github.com/jsimonetti/rtnetlink v1.4.2 // indirect
github.com/klauspost/compress v1.20.0 // indirect
github.com/mdlayher/netlink v1.11.2 // indirect
github.com/mdlayher/socket v0.7.0 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/pires/go-proxyproto v0.8.1 // indirect
github.com/safchain/ethtool v0.3.0 // indirect
github.com/pires/go-proxyproto v0.15.0 // indirect
github.com/safchain/ethtool v0.7.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d // indirect
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd // indirect
github.com/tailscale/hujson v0.0.0-20260727124030-b80ff77dac4f // indirect
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect
github.com/tailscale/wireguard-go v0.0.0-20260715223240-2e01ba5b00f0 // indirect
github.com/tailscale/web-client-prebuilt v0.0.0-20260917222731-e0ed2d0d0fea // indirect
github.com/tailscale/wireguard-go v0.0.0-20260928213032-417aef361226 // indirect
github.com/x448/float16 v0.8.4 // indirect
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/crypto v0.54.0 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/net v0.56.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.22.0 // indirect
go4.org/netipx v0.0.0-20260823151212-3075585bcbeb // indirect
golang.org/x/crypto v0.57.0 // indirect
golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba // indirect
golang.org/x/net v0.59.0 // indirect
golang.org/x/oauth2 v0.37.0 // indirect
golang.org/x/sync v0.23.0 // indirect
golang.org/x/sys v0.48.0 // indirect
golang.org/x/text v0.40.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/text v0.42.0 // indirect
golang.org/x/time v0.16.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
gvisor.dev/gvisor v0.0.0-20260224225140-573d5e7127a8 // indirect
golang.zx2c4.com/wireguard/windows v1.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20260915211658-a6f909f08a72 // indirect
)
Loading
Loading