108 Commits

Author SHA1 Message Date
5716f0f757
fix(monorel): guard against nested go.mod in binary paths
Any directory on the path from the module root to a binary that
contains its own go.mod is a separate module; monorel should not try
to manage it.  Two cases are now caught with distinct errors:

  ../other              → "outside the module directory"
  ./cmd/go.mod          → "has its own go.mod" (intermediate dir)
  ./cmd/foo/go.mod      → "has its own go.mod" (binary dir itself)

Both suggest the correct fix: cd into that directory and run monorel
from there.
2026-03-01 19:13:49 -07:00
12c025e5e2
feat(monorel): require binary-path args; support multi-binary modules
The tool now requires at least one positional argument — the path(s) to
the Go main package(s) to build — and must be run from the module root
(the directory containing go.mod).

  # single binary (module root is the main package)
  monorel .

  # multiple binaries under one module
  monorel ./cmd/gsheet2csv ./cmd/gsheet2tsv ./cmd/gsheet2env

Changes:
- Add `binary` struct {name, mainPath} and `parseBinaries()`
  - "." is special-cased: binary name is taken from the CWD, not "."
  - filepath.Clean's "./"-stripping is undone so goreleaser sees an
    explicit relative path (./cmd/foo not cmd/foo)
- `goreleaserYAML` now takes `projectName + []binary`
  - Each binary gets its own `builds` entry (with `id:` and `main:`)
    and its own `archives` entry (with `ids:` to link it to the build)
  - `main:` is omitted when mainPath is "." (goreleaser default)
  - Checksum is named <projectName>_VERSION_checksums.txt
- `printScript` takes `projectName + []binary`
  - Summary line says "Binaries:" (plural) when more than one
  - Upload step globs tar.gz + zip for every binary, then the checksum
- Require go.mod in CWD; error out with usage message when no args given

Also regenerates cmd/tcpfwd/.goreleaser.yaml via the new code path
(adds `id: tcpfwd` to builds/archives; no functional change otherwise).
2026-03-01 19:13:45 -07:00
3676ef0f47
feat: add tools/monorel for monorepo submodule releases
Adds a standalone Go CLI tool (tools/monorel) that automates the
goreleaser + gh release workflow for modules living in a subdirectory
of a monorepo where goreleaser Pro is not available.

Run from any module subdirectory (e.g. cmd/tcpfwd):
  monorel          # writes .goreleaser.yaml + prints release script
  monorel --help   # (flag defaults)

What the tool does:
- Detects module path and binary name from git prefix
- Lists and semver-sorts tags matching <prefix>/v* (e.g. cmd/tcpfwd/v*)
- Computes version: exact tag → stable release; commits/dirty → pre-release
- Writes (or updates) .goreleaser.yaml with the binary name hard-coded,
  {{.Env.VERSION}} used for filenames instead of the prefixed tag,
  and release.disable: true (gh handles the GitHub Release)
- Prints a numbered bash script covering env vars, optional git tag,
  goreleaser build, release notes, and gh release create/upload/publish

Also updates cmd/tcpfwd/.goreleaser.yaml (first output from monorel):
- Fixes stray trailing quote in ldflags
- Sets release.disable: true (was release.footer)
- Adds generated-by header comment
2026-03-01 19:13:39 -07:00
968b375221
chore(io/transform/gsheet2csv): update .goreleaser.yaml with more builds io/transform/gsheet2csv/v1.0.5 2026-03-01 02:11:00 -07:00
ae0e02b5aa
chore(io/transform/gsheet2csv): add .goreleaser.yaml io/transform/gsheet2csv/v1.0.4 2026-03-01 01:20:48 -07:00
6e4f25ff5e
chore(release): add .goreleaser.yaml for auth-proxy 2026-03-01 01:20:48 -07:00
18eec1f5cb
chore(release): update .goreleaser.yaml for cmd/tcpfwd cmd/tcpfwd/v1.1.1 2026-03-01 00:29:33 -07:00
fc9f070285
chore(cmd/tcpfwd): update .goreleaser.yaml for monorepo 2026-03-01 00:22:44 -07:00
115efc0afb
chore(cmd/tcpfwd): goreleaser init 2026-03-01 00:18:32 -07:00
698137576a
chore: add 'dist/' to .gitignore 2026-03-01 00:18:32 -07:00
0762e64857
chore(cmd/tcpfwd): add go.mod (for git-tag-based releases) cmd/tcpfwd/v1.1.0 2026-02-27 23:50:37 -07:00
d30ceb004d
chore(cmd/tcpfwd): minor cleanup, add license, lint 2026-02-27 23:35:00 -07:00
3e4ce3ac91
ref(cmd/tcpfwd): extract waitWithTimeout to simplify shutdown block
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:52:07 -07:00
0d356c0b26
feat(cmd/tcpfwd): add description to version/help output
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:16:49 -07:00
f9e06f131b
ref(cmd/tcpfwd): simplify parseForward with strings.Cut
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:13:10 -07:00
3f16e89f5c
ref(cmd/tcpfwd): remove implicit time.Now() for testability
- connEntry.isIdle(now, threshold): caller supplies now instead of time.Since
- connRegistry.closeIdle(now, threshold): passes now through to isIdle
- trackingConn gains a clock func() time.Time field used in Read/Write
- handleConn takes clock func() time.Time; uses it to init lastRead/lastWrite
  and passes it to trackingConn
- Call sites in main pass time.Now or time.Now() explicitly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:08:56 -07:00
89f6e04516
feat(cmd/tcpfwd): add graceful shutdown with idle connection tracking
On SIGINT/SIGTERM:
- Stop accepting new connections
- Close connections idle longer than --idle-timeout (default 5s),
  determined by LastRead/LastWrite timestamps tracked per connection pair
- Wait for active connections to drain up to --shutdown-timeout (default 30s)
- Force-close any remaining connections if the timeout is exceeded

Also switches isClosedConn to use errors.Is(err, net.ErrClosed) and
exits the accept loop cleanly when a listener is closed during shutdown.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:05:04 -07:00
b08525b024
feat(cmd/tcpfwd): add multi-forward positional args and version/help
Accept any number of local-port:remote-host:remote-port forwards as
positional arguments. Backward-compatible with existing --port/--target
flags. Adds --version/-V/version and --help/help handling matching the
auth-proxy pattern, including printVersion printed to stderr at startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 21:54:51 -07:00
ec64afe390
feat: add tcpfwd to pipe connections 2026-02-27 21:25:33 -07:00
a56f8601f0
chore: add cmd binaries to .gitignore 2026-02-27 02:56:28 -07:00
af6b0eb5a2
feat: add cmd/smsgwhookstocsv for smsapid (android sms gateway) jsonl to tsv 2026-02-27 02:48:13 -07:00
71eceb809f
feat: add cmd/smsapid for use with android-sms-gateway 2026-02-27 02:48:13 -07:00
4176923dd8
ref(cmd/sendsms): separate http/androidsmsgateway into own package 2026-02-27 02:42:50 -07:00
6db9bd805d
chore: remove empty go.sum 2026-02-27 02:42:50 -07:00
c6b55feb78
chore: add .DS_Store to .gitignore 2026-02-27 01:55:24 -07:00
c08f7e342a
feat(cmd/sendsms): add back curl script for testing 2026-02-27 01:52:19 -07:00
de8630c136
fix(cmd/sendsms): send messages again (but not on dry-run), check ENVs 2026-02-27 01:52:19 -07:00
4e5277d133
fix(cmd/sendsms): randomize-csv now keeps header and adds back extension 2026-02-27 01:52:19 -07:00
7b40097396
fix(cmd/auth-proxy): show all working credentials, not just the first one cmd/auth-proxy/v1.0.1 2026-02-27 00:26:43 -07:00
cbacf9ffc9
chore: add credentials.tsv to .gitignore 2026-02-27 00:17:31 -07:00
7a93b333ba
doc(cmd/auth-proxy): add README.md with examples and install instructions 2026-02-27 00:06:58 -07:00
13eeb6793b
feat: add cmd/auth-proxy to add Basic, Bearer, X-API-Key, or access_token auth to routes 2026-02-27 00:06:58 -07:00
8ef2f73cb0
fix(auth/csvauth): oops, should have added as auth.BasicAuthenticator, done auth/csvauth/v1.2.2 2026-02-26 21:12:29 -07:00
ff8cdec1d7
feat(auth): add BasicVerifier, BasicAuthenticator, and BasicPrinciple for interfaces without implementation dependency auth/v1.0.0 2026-02-26 20:03:43 -07:00
d756f205b0
ref(auth/csvauth): create and adhere to Principle interface for verified credential 2026-02-26 16:44:54 -07:00
737f3b0057
fix(auth/csvauth): make username lookups timing safe 2026-02-26 02:23:31 -07:00
1789c92815
fix(auth/csvauth): don't allow BOTH username and password to be empty 2026-02-26 02:23:31 -07:00
3465e9e232
doc(auth/csvauth): update examples 2026-02-26 02:23:31 -07:00
01a4cdda8a
feat(auth/csvauth): add Authenticate(user, pass string) to get verified Credential 2026-02-26 02:23:31 -07:00
7d35551fa7
ref(auth/csvauth): separate Login, Token, and ServiceAccount files 2026-02-26 02:23:31 -07:00
85c7b78ca6
ref(auth/csvauth): enable token use with Verify(dummy, token) auth/csvauth/v1.1.1 2026-02-21 15:41:02 -07:00
85d42550bf
feat(auth/csvauth): add token support,make secrets non-printing auth/csvauth/v1.1.0 2026-02-21 05:49:11 -07:00
dd48b2420b
feat(auth/csvauth): make secrets non-printing 2026-02-21 05:49:11 -07:00
af634f2175
doc+fix(cmd/csvauth): cleanup help, print with bare '--help' 2026-02-21 05:49:11 -07:00
6e0c91feb4
fix(cmd/csvauth): use errors.Is(err, ErrInQuestion) correctly 2026-02-21 05:49:11 -07:00
b4886aa710
feat: add crypto/passphrase encoding/base2048/v1.0.0 crypto/passphrase/v1.0.0 2026-02-12 00:38:04 -07:00
a68cac6529
feat: add encoding/base2048 2026-02-12 00:38:04 -07:00
d2f362ae50
chore: bump go.mod to 1.26.0 2026-02-12 00:38:04 -07:00
21ea2d0613
chore(cmd/sql-migrate): bump v2.0.3 cmd/sql-migrate/v2.0.3 2026-01-31 21:22:42 -07:00
b6ffacd0a6
fix(cmd/sql-migrate): spell 'postgres' correctly 2026-01-31 21:21:53 -07:00