188 Commits

Author SHA1 Message Date
f89b8115dd feat(mymigrate): add MySQL/MariaDB backend for sqlmigrate 2026-04-09 02:35:42 -06:00
a8bc605ebf
fix(pgmigrate): update sqlmigrate dependency to v1.0.1 2026-04-09 02:20:36 -06:00
b5d9c7fab7
feat(pgmigrate): add PostgreSQL backend for sqlmigrate 2026-04-09 02:14:40 -06:00
a3ecf5ac81
ref(sqlmigrate): add subpath to Collect, add Latest/Drop convenience functions
API changes for v1:
- Collect(fsys, subpath) takes a subdirectory path (use "." for root),
  enabling embed.FS with //go:embed sql/migrations/*.sql
- Latest() applies all pending migrations (shorthand for Up with n=-1)
- Drop() rolls back all applied migrations (shorthand for Down with n=-1)
2026-04-09 02:04:37 -06:00
9c672a9d76
fix(shmigrate): use errors.Is for fs.ErrNotExist compatibility
os.IsNotExist does not recognize fs.ErrNotExist when wrapped by an
fs.FS implementation. Switch to errors.Is(err, fs.ErrNotExist) so
the "file not found" check works for both os.Open and fs.FS.Open.
2026-04-08 17:52:53 -06:00
55298ac018
feat(sql-migrate): add ID-in-log for tab-delimited migration tracking
- logMigrationsSelect() returns DB-specific SELECT for id+name output,
  matching psql explicitly and erroring on unrecognized --sql-command
- logMigrationsQueryNote const for the comment header
- maybeUpgradeLogQuery() auto-upgrades old _migrations.sql on first run,
  replacing only the matching SELECT line
- Add UPGRADING help section pointing to sync subcommand
2026-04-08 17:23:50 -06:00
3e51c7b67a
fix(sqlmigrate): make n=0 an error in Up/Down, use -1 for "all"
Passing 0 to Up() or Down() is an easy mistake — it silently means
"all" which could be destructive. Now n=0 returns ErrInvalidN.
Convention: n > 0 for a specific count, n < 0 (typically -1) for all.
v2.2.0
2026-04-08 15:51:25 -06:00
3547b7e409
ref(database/sqlmigrate): extract migration library with shmigrate backend
Factor the inline migration logic from cmd/sql-migrate into reusable
packages: database/sqlmigrate (core types, matching, file collection)
and database/sqlmigrate/shmigrate (shell script generation backend).

No behavior changes — the CLI produces identical output. The shmigrate
package implements the sqlmigrate.Migrator interface so other backends
(pgmigrate, mymigrate, etc.) can follow the same pattern.
2026-04-08 15:37:03 -06:00
c4964a5b65
chore(sql-migrate): remove dead subcmd != "create" checks in status/list cases
Go switch cases don't fall through, so subcmd can never be "create"
when we're inside the "status" or "list" case.
2026-04-08 15:21:04 -06:00
da7f45438c
doc(sql-migrate): add PGOPTIONS multi-tenant schema docs to help text
Document how to use PGOPTIONS="-c search_path=..." for multi-tenant
PostgreSQL migrations. Each schema gets its own _migrations table,
so tenants are migrated independently.
2026-04-08 15:06:41 -06:00
2080ae223d
fix(sql-migrate): reject explicit 'up 0' and 'down 0' as invalid
An explicit 0 argument should error, not silently run all pending (up)
or get handled as a special case (down). Change the guard from < 0 to
< 1 in both subcommands so '0' is treated as invalid input.
2026-04-08 14:57:55 -06:00
03d81a2b76
fix(sql-migrate): reject explicit 'up 0' as invalid
An explicit 0 argument to 'up' should error (like 'down 0' already
does), not silently run all pending migrations. Change the guard
from < 0 to < 1 to match 'down' behavior.
2026-04-08 14:41:09 -06:00
40fa1e876c
fix(sql-migrate): add missing --tuples-only to psql examples in help text
The psql command constant uses -A -t (--no-align --tuples-only) but
the help text and code comments only showed --no-align. Without
--tuples-only, psql prints column headers into migrations.log,
corrupting it.
cmd/sql-migrate/v2.1.6
2026-04-08 13:45:11 -06:00
404079f154
fix(sql-migrate): use goreleaser ldflags for version info
Replace hardcoded version const with var block populated by goreleaser
ldflags (version, commit, date). Add printVersion() matching the pattern
used by sibling commands (tcpfwd, smsapid, auth-proxy). Fix date var
shadowing in main() by renaming local to today.
cmd/sql-migrate/v2.1.5
2026-04-08 02:57:53 -06:00
075cc7b286
fix(sql-migrate): add missing ! to shebang in generated scripts
Generated shell scripts had `#/bin/sh` instead of `#!/bin/sh`,
meaning the shebang was treated as a comment rather than an
interpreter directive.
cmd/sql-migrate/v2.1.4
2026-04-06 00:39:36 -06:00
4a9c331ef9
Fix INSERT INTO _migrations ordering in create and fixup
The create subcommand generated .up.sql files with INSERT INTO
_migrations as the FIRST statement, before the actual DDL. If the
DDL fails, the migration is incorrectly marked as applied. Move the
INSERT to be the LAST statement, matching how .down.sql already puts
DELETE FROM _migrations last.

Also fix the automatic fixup logic to append (not prepend) missing
INSERT statements to existing .up.sql files.

Fixes #86
cmd/sql-migrate/v2.1.3
2026-03-30 15:58:21 -06:00
87b666ffd3
chore(cmd/sql-migrate): add .goreleaser.yaml cmd/sql-migrate/v2.1.2 2026-03-28 17:16:40 -06:00
a4c4deabfa
chore(tools/monorel): re-init .goreleaser.yaml tools/monorel/v0.6.7 2026-03-28 17:15:38 -06:00
9d11500cd6
feat(monorel): separate Windows builds and full goamd64 v1-v4 matrix
Go 1.23+ changed Windows target naming so x86_64 builds now carry a
micro-architecture suffix (e.g. _v2).  Update the goreleaser YAML
generator and monorel's own .goreleaser.yaml to match:

- Remove windows from defaultGoos/almostAllGoos; emit a dedicated
  <name>-windows build entry per binary.  Windows is kept in a separate
  build because it does not support ARM v6/v7, so it cannot share the
  same goarch matrix as non-Windows builds.
- Add defaultWindowsGoarch [amd64, arm64] and almostAllWindowsGoarch
  [386, amd64, arm64] for the Windows-specific architecture lists.
- Promote defaultGoamd64 from [v1, v2] to [v1, v2, v3, v4] so the
  full amd64 micro-architecture matrix is always generated.
- Update the archive name_template to include
  {{ if .Amd64 }}_{{ .Amd64 }}{{ end }} after x86_64.
- Include both <name> and <name>-windows in archive ids.
- Regenerate tools/monorel/.goreleaser.yaml and
  cmd/sql-migrate/.goreleaser.yaml with the new format.
2026-03-28 17:15:33 -06:00
690cf90d67
chore(cmd/sql-migrate): add .goreleaser.yaml 2026-03-23 11:43:08 -06:00
1f61095873
feat(sql-migrate): add sync subcommand
Adds `sql-migrate sync` which outputs a shell script that refreshes
the local migrations.log from the DB by running _migrations.sql.
Uses `|| true` so a fresh DB with no _migrations table yields an
empty log (all migrations pending) rather than an error.

Usage:
  sql-migrate -d ./db/migrations sync | sh
  sql-migrate -d ./db/migrations up | sh
cmd/sql-migrate/v2.1.0
2026-03-23 11:42:23 -06:00
b50696f64d feat(sql-migrate): skip +-prefixed files in migrations directory (refs #68) cmd/sql-migrate/v2.0.4 2026-03-23 11:39:49 -06:00
3487702bf7 fix(sql-migrate): use 6-digit zero-padded number in init migration filename (refs #68) 2026-03-23 11:39:49 -06:00
4895012d67 fix(sql-migrate): use portable SQL in _migrations table (closes #37) 2026-03-23 11:39:49 -06:00
a854fef67e
test(auth/csvauth): regression test for Authenticate token deadlock
Guards against the v1.2.4 bug (fixed in c32acd5) where Authenticate
held a.mux via defer for its full duration, then called
loadAndVerifyToken which also tries to acquire a.mux — deadlock on
every token auth request.

TestAuthenticateTokenNoDeadlock exercises both the bare-token
("", token) and named-username ("api", token) forms with a 1s
timeout, so a regression fails fast rather than hanging the suite.
2026-03-23 00:26:16 -06:00
a4cb1e3bfd
doc: clarify how to create users and tokens
Signed-off-by: AJ ONeal <aj@therootcompany.com>
2026-03-19 21:17:57 -06:00
0d99234914
ref!(auth/jwt): variadic requiredScopes in NewAccessTokenValidator
Distinguishes the two validator constructors by signature:
- NewIDTokenValidator(iss, aud, azp []string) — allowlist semantics
- NewAccessTokenValidator(iss, aud []string, requiredScopes ...string) — requirement semantics

Variadic scopes read naturally at the call site:
  NewAccessTokenValidator(issuers, audiences, "openid", "profile")

Three-state semantics preserved:
  no args        → scope not checked
  []string{}...  → scope must be present (any value)
  "openid", ...  → scope must contain all listed values

Also removes the old gracePeriod parameter from both constructors
(was 0 at all call sites; set GracePeriod on the struct directly
if a non-default value is needed).

Adds TestCov_NewAccessTokenValidator_Scopes covering all three cases.
auth/jwt/v0.9.1
2026-03-17 08:00:45 -06:00
26bdc0a3db
ref!(auth/jwt): full modern rewrite auth/jwt/v0.9.0 2026-03-17 07:49:53 -06:00
117ed8cc9b
feat(auth/jwt): add jwk fetch and jwt verify auth/jwt/v0.6.5 2026-03-17 07:10:25 -06:00
ba674a673d
doc(tools/monorel): move usage summary to doc.go tools/monorel/v0.6.6 2026-03-08 17:21:55 -06:00
f2302d2f24
chore(monorel): add MPL-2.0 license header 2026-03-08 17:21:55 -06:00
eaa3636a35
feat(monorel): add version output with ldflags support 2026-03-08 17:21:55 -06:00
92e1ae9992
docs(monorel): add README tools/monorel/v0.6.5 2026-03-08 15:55:11 -06:00
bd2443cb58
fix(monorel): various path, module root, and --recursive fixes 2026-03-08 15:51:26 -06:00
fd3cb8ba99
feat(monorel): add goarch/goarm/goamd64 to build matrix with --almost-all/--ios/--android-ndk
Default matrix (conservative, CGO_ENABLED=0):
  goos:   darwin freebsd js linux netbsd openbsd wasip1 windows
  goarch: amd64 arm arm64 mips64le mipsle ppc64le riscv64 wasm
  goarm:  6 7  (always included when arm is in goarch)

--almost-all widens to esoteric goos (aix dragonfly illumos plan9
solaris), adds 386/loong64/mips/mips64/ppc64/s390x to goarch, and
emits goamd64: v1 v2 v3 v4.

--ios generates an active iOS build entry (CGO_ENABLED=1, arm64)
instead of the default commented stub.

--android-ndk generates an active Android NDK build entry
(CGO_ENABLED=1, arm64) instead of the default commented stub.

Both --ios and --android-ndk are available on init and release.
The existing -A flag (include hidden dirs) is unchanged.
2026-03-08 15:49:24 -06:00
1cb478b475
fix(http/androidsmsgateway): revert to using observed phoneNumber field rather than the documented recipient,sender ones 2026-03-05 14:00:55 -07:00
516b23eac3
feat+ref(cmd/smsapid): add sms:* endpoints, csvauth, cli flags, etc 2026-03-03 03:11:26 -07:00
4bda5b4580
ref(cmd/auth-proxy): consolidate generic token logic in auth package 2026-03-03 03:08:27 -07:00
c32acd5a74
ref(auth/csvauth): don't hold mutex longer than necessary auth/csvauth/v1.2.5 2026-03-03 03:05:05 -07:00
020b00c353
feat(http/androidsmsgateway): add webhook examples, JSON, CSV, and signature verification 2026-03-03 03:01:56 -07:00
66dde73bd4
chore(auth/csvauth): add .goreleaser.yaml auth/csvauth/v1.2.4 2026-03-03 02:31:36 -07:00
249385c775
fix(auth/csvauth): load tokens into hashmap so that they can be retrieved by CredentialKeys auth/csvauth/v1.2.3 auth/v1.1.1 2026-03-03 02:26:34 -07:00
d415a8c743
fix(auth/csvauth): turn the old CLI-only warnings and errors into returned errors 2026-03-03 01:21:36 -07:00
8842791e34
fix(auth): update test 2026-03-03 00:01:15 -07:00
92f865912a
fix(auth): add missing arg to NewBasicRequestAuthenticator 2026-03-02 23:18:05 -07:00
846d14baf5
feat(auth): add BasicRequestAuthenticator auth/v1.1.0 2026-03-02 12:32:01 -07:00
8056a07d10
chore(tools/monorel): add .goreleaser.yaml tools/monorel/v0.6.4 2026-03-01 19:13:50 -07:00
8405be04ad
feat(monorel): use YAML anchors to DRY up multi-binary build matrices
When a module has more than one binary, the shared build options (env,
ldflags, goos) are defined once via a YAML anchor on the first build and
merged into the rest with <<: *build_defaults.  Single-binary modules use
plain fields with no anchor overhead.

  - id: gsheet2csv          - id: gsheet2csv
    binary: gsheet2csv        binary: gsheet2csv
    env:              →       <<: &build_defaults
      - CGO_ENABLED=0           env:
    goos:                         - CGO_ENABLED=0
      - aix                     goos:
      - ...                       - aix
  - id: gsheet2env               - ...
    binary: gsheet2env      - id: gsheet2env
    env:                      binary: gsheet2env
      - CGO_ENABLED=0           <<: *build_defaults
    goos: ...

The commented-out ios stubs follow the same pattern using a separate
build_defaults_ios anchor so they remain consistent when uncommented.

Also extracts defaultGoos to a package-level var to avoid repetition.
2026-03-01 19:13:50 -07:00
445a6e9c07
feat(monorel): expand default build matrix to all practical CGO_ENABLED=0 targets
Replace linux/windows/darwin with the full CGO_ENABLED=0 goos list:
  aix, darwin, dragonfly, freebsd, illumos, js, linux, netbsd, openbsd,
  plan9, solaris, wasip1, windows

Add commented-out stanzas for each binary for platforms that require extra
tooling:
  - iOS  (CGO_ENABLED=1, Xcode toolchain required)
  - Android (CGO_ENABLED=0 arm64-only; NDK required for full CGO builds)

Archive formats unchanged (tar.gz + tar.zst / zip + tar.gz for Windows).
2026-03-01 19:13:50 -07:00
1289f3e5b6
fix(monorel): guard .goreleaser.yaml overwrite in release; loosen compat check
release subcommand:
- Replace yamlLooksCorrect with yamlIsCompatible: file is considered OK if
  {{ .ProjectName }} is absent AND at least one binary's VERSION string is
  present.  Extra hand-edited binaries (like fixtures) no longer trigger a
  rewrite.
- Before overwriting an existing file, prompt the user [Y/n].  --yes does
  not skip this prompt; --force does.  If stdin is not a terminal and
  --force is not set, the command errors rather than silently clobbering.

init subcommand: unchanged — still uses the strict yamlLooksCorrect check
(all binaries must be present, ldflags must include main.version).
2026-03-01 19:13:50 -07:00