256 Commits

Author SHA1 Message Date
1ecdc9a7cf
feat: add cmd/ssechat as ServerSentEvents demo 2026-08-17 17:28:12 -06:00
d752988808
feat: add cmd/cullbak for culling backup directories 2026-08-17 17:28:12 -06:00
d64070dc60
f: net/formmailer 2026-08-17 17:28:12 -06:00
7bfb638af4
wip: feat: add net/formmailer for web forms with bot protection 2026-08-17 17:28:12 -06:00
061c45d188
feat: add cmd/smtp-test for debugging smtp auth and delivery 2026-08-17 17:28:12 -06:00
8e6174330f
wip: add more middleware examples 2026-08-17 17:28:12 -06:00
6ecfc31498
feat(calendar): parse reminder durations 2026-08-17 17:28:12 -06:00
8aa0799562
wip(calendar): rework field access 2026-08-17 17:28:12 -06:00
3d533338bf
f: feat(calendar): calculate fixed and floating yearl and monthly events 2026-08-17 17:28:12 -06:00
3fa8e4b71b
f: feat(calendar): calculate fixed and floating yearl and monthly events 2026-08-17 17:28:12 -06:00
719905ff26
wip: feat(calendar): calculate fixed and floating yearl and monthly events 2026-08-17 17:28:11 -06:00
7946099f72
f(ai): add WithFormat to change format without changing Generate signature 2026-08-17 17:28:11 -06:00
4e60fc6597
f(ai): add WithModel to change model on-the-fly 2026-08-17 17:28:11 -06:00
a84cf639ed
f(ai): fix interface / add type guard 2026-08-17 17:28:11 -06:00
613cdfa312
feat(ai): add Ollama and OpenAI helpers 2026-08-17 17:28:11 -06:00
1f2e264712
feat: add cmd/smbtest for debugging smb connection issues 2026-08-17 17:28:11 -06:00
89281ece5a
ref(cmd/monorelease): fix tag and version output, start flagset 2026-08-17 17:28:11 -06:00
e315659aec
WIP: feat(cmd/monorelease): fix versioning 2026-08-17 17:28:11 -06:00
90d519cc3a
WIP: feat(cmd/monorelease): better table 2026-08-17 17:28:11 -06:00
039e56cd25
WIP: feat(cmd/monorelease): show table 2026-08-17 17:28:11 -06:00
232b12372e
WIP: feat(cmd/monorelease): show bins 2026-08-17 17:28:11 -06:00
bd04c811e3
WIP: feat: add cmd/monorelease for checking version info 2026-08-17 17:28:11 -06:00
f7d30e4dcf
feat: add tools/gitver for monorepo versioning 2026-08-17 17:28:11 -06:00
d80c4ffab8
feat: add ./scripts/concat-for-context.sh to reduce total file count 2026-08-17 17:28:11 -06:00
27e3b05a10
doc: add PROMPT.md for Ai context 2026-08-17 17:28:11 -06:00
6dbe89ff02
feat: add cmd/api-example as server boilerplate 2026-08-17 17:28:11 -06:00
e178c86945
f: cmd/cli-example 2026-08-17 17:28:11 -06:00
2c99785ec3
feat: add cmd/cli-example for reference, and Ai context 2026-08-17 17:28:11 -06:00
5f2d7a9c9a
fix(sqlmigrate): address high-severity review findings
- Collect: replace WalkDir with ReadDir to avoid subdirectory recursion
  and the risk of duplicate filenames silently overwriting each other
- shmigrate: check scanner.Err() after reading migrations log
- shmigrate: shell-quote all paths in generated scripts to prevent
  shell injection via migration filenames
- shmigrate: wrap errors with ErrQueryApplied sentinel for consistency
  with DB backends
- mustInit: remove stale err check that could never fire
- mustInit: fix swapped error messages (read vs create)
2026-08-17 17:28:11 -06:00
484b6bc11a
fix(io/transform/gsheet2csv): use safe defaults for http client io/transform/gsheet2csv/v1.0.6 2026-08-17 17:25:45 -06:00
c66c4a8de4
ref!(https): rewrite with latest best practices, for publish https/v0.9.0 2026-08-17 15:15:09 -06:00
71671b7852
fix(sql-migrate): add missing period 'basename+".up.sql"' 2026-07-07 16:40:37 -06:00
bc3fb945af
chore(sql-migrate): lint 2026-07-07 16:30:13 -06:00
3e2b055c88
fix(sql-migrate): strip id\t prefix when parsing migrations.log
parseAndFixupBatches treated every line as a migration name, but the
new log format uses id\tname (tab-separated). This caused fixupMigration
to look for non-existent files like '05aba66a\t2026-06-03-003000_team-create.up.sql'.

Align with shmigrate.Applied() which already handles both formats.
cmd/sql-migrate/v2.2.5
2026-06-04 22:08:22 -06:00
a408dc890b
feat(sync/dataset): generic hot-swap refresh with atomic.Pointer
Coordinates a Set of Fetchers (each producing a typed dataset) so a
running server can swap to fresh data without locks on the read path.
Readers go through atomic.Pointer; Load/Close are mutex-serialized so
concurrent reloads can't race. Add and AddInitial register fetchers
before the first Load.
sync/dataset/v0.5.0
2026-05-26 22:46:04 -06:00
584061744b
feat(geoip-update): CLI for downloading GeoLite2 databases via conditional HTTP GET
- Downloads all editions listed in a GeoIP.conf
  - Flags: -config, -dir, -fresh-days, -base-url (override
    DownloadBase for custom mirror/proxy), -V/--version, -help
  - Version output shows name, version, commit, date, copyright and
    license (populated via ldflags at build time)
  - Uses Basic auth with split credential encoding for readability
  - ETag/Last-Modified caching via httpcache
net/geoip/v0.5.0 ‎net/geoip/v0.5.0
2026-05-26 22:04:22 -06:00
2f33b5e430
feat(net/geoip): MaxMind GeoLite2 reader with auto-update
Add a Go package for reading MaxMind GeoLite2 City and ASN databases.

  - ParseConf: parses geoipupdate-style config files (AccountID,
    LicenseKey, EditionIDs, DatabaseDirectory)
  - Databases: holds open City + ASN readers; Open() loads both
    editions from a directory, extracting .mmdb from tar.gz in memory
    without writing to disk
  - FindTarGz: resolves cache paths, preferring *_LATEST.tar.gz
  - Lookup: returns city, region, country, ASN, and AS org for an IP
  - DownloadBase constant, TarGzName helper, DefaultConfPaths and
    DefaultCacheDir conveniences

Integration tests verify download and conditional-get freshness.
2026-05-26 22:04:17 -06:00
ecba24973b
chore: add LOCAL.md and agents/ to .gitignore 2026-05-26 21:59:57 -06:00
04b8bb406d
feat(net/httpcache): ETag/Last-Modified HTTP cache
Conditional GET cache for periodic data sources. Persists ETag and
Last-Modified to a .meta sidecar so 304s survive process restarts.
Two independent rate-limit gates (MaxAge file-mtime, MinInterval
in-memory). Body cap via MaxBytes defends against fill-disk from a
hostile upstream or redirect target. Authorization (and any
caller-supplied) headers stripped on every redirect hop. Userinfo
in URL is redacted from error messages.
net/httpcache/v0.5.0
2026-05-26 01:27:20 -06:00
dddfdd392c
feat(net/ipgate): IP allowlist/blocklist via PrefixSet and DomainSet
PrefixSet: git-backed CIDR files via gitshallow, refreshed every 47 min.
DomainSet: takes pre-parsed (staticPrefixes, domains []string); resolves
hostnames every 5 min, retaining stale IPs on failure. Both use
atomic-swapped ipcohort.Cohort for lock-free reads.

ParseDomainSet(RecordReader) parses rows into prefixes and hostnames;
caller constructs the record reader (e.g. csv.Reader with delimiter,
comment char). RecordReader interface is satisfied by *csv.Reader.

commaify uses plain string concat (integers max ~7 groups).
net/ipgate/v0.5.2
2026-05-22 12:23:35 -04:00
d472c00ef1
feat(net/dnsresolver): parallel DNS resolver with fallback servers
Resolves A, CNAME chain, and SRV records via miekg/dns. Queries all
configured servers in parallel and returns the first success. Falls
back to OpenDNS/Cloudflare/Quad9 when /etc/resolv.conf is absent or empty.
net/dnsresolver/v0.5.0
2026-05-22 11:16:22 -04:00
1db21be047
fix(gitshallow): depth-3 windowed fetch with low-memory GC
- Default depth changed from 1 to 3: enough overlap for delta
  compression even if the remote pushes 2 commits between fetches
- Keep --depth on fetch (not just clone) so shallow stays windowed
- GCInterval default changed: 0 now means every fetch (was disabled)
- GC sequence: reflog expire → prune → gc --prune=now
  Expire makes old shallow entries' objects unreachable, prune removes
  them cheaply (5MB RSS), then gc delta-compresses what remains (~10MB)
- Only GC when HEAD actually changed (skip no-op fetches)
- Dropped GCAggressive (no benefit in shallow clones)
net/gitshallow/v0.9.1
2026-05-11 23:45:10 -06:00
1dacbdd8f7
feat(net/gitshallow): incremental shallow git-repo mirroring
Periodically-updated shallow clone for repos used as a data source.
One Fetch verb (clone-or-pull-or-skip) drives both the Fetcher
interface and per-File handles. MaxAge gates on FETCH_HEAD mtime so
short-lived CLI invocations don't hammer the remote across process
restarts; an in-memory 1s debounce coalesces concurrent Fetches.
Hardens git invocations against argument injection: validates
branch/ref shape, rejects URLs starting with '-', and uses '--'
separators before positional args. Userinfo in URL is redacted from
error output (both args echo and git's own messages).
net/gitshallow/cmd/git-shallow-sync/v0.9.0 net/gitshallow/v0.9.0
2026-05-02 16:15:54 -06:00
bea4c3de0a
feat(net/ipcohort): IP block/allow cohort filter
IPv4 host + CIDR membership testing backed by sorted /32 binary search
and a linear scan of CIDR ranges. CSV/text loader with bounded reads
(maxBytes is required so callers pick a limit appropriate to their
input source — 1 KB allowlists through 100+ MB threat feeds). Returns
errors for unparseable IPs so callers can decide fail-open vs
fail-closed; partial cohorts are returned alongside parse errors.
net/ipcohort/cmd/ipcohort-contains/v0.9.0 net/ipcohort/v0.9.0
2026-05-02 15:41:38 -06:00
c2f5dbeeca
doc(skills): pgmigrate clarificaton 2026-04-19 19:25:52 -06:00
65432d7c29
database/sqlmigrate/pgmigrate: add Schema field for qualified _migrations table
Add Schema string field to Migrator. When set, Applied() constructs a
schema-qualified table name via pgx.Identifier.Sanitize() rather than
the bare "_migrations". New() signature is unchanged.

Usage:
    runner := pgmigrate.New(conn)
    runner.Schema = "authz"
database/sqlmigrate/pgmigrate/v1.0.5
2026-04-17 03:53:32 -06:00
17bbc881a9
database/sqlmigrate: allow optional schema prefix in INSERT INTO _migrations
Update idFromInsert regex to match schema-qualified table references
such as INSERT INTO authz._migrations, in addition to the existing
unqualified INSERT INTO _migrations form.
database/sqlmigrate/v1.0.3
2026-04-17 02:30:41 -06:00
02fef67e53
fix(auth/csvauth): ID() returns Name only, not Name~hashID for tokens
Principal identity is the subject (who), not the credential instance
(which token). The hashID suffix was an internal cache fingerprint that
leaked into the public ID. Callers that need to distinguish individual
token instances must use a separate mechanism.

TSV serialization in ToRecord() still writes Name~hashID when hashID is
set so the credential file round-trips correctly.
auth/csvauth/v1.2.9
2026-04-13 22:57:21 -06:00
fbb4a14620
chore(git): ignore worktrees and vim swap files 2026-04-13 17:14:08 -06:00
4abac2a0df
feat(auth/xhubsig): X-Hub-Signature HMAC webhook verification + HTTP middleware
Verify X-Hub-Signature-256 (and SHA-1) webhook signatures. Middleware
buffers and re-exposes the body for downstream handlers. Errors honor
Accept header: TSV default (text/plain for browsers), JSON, CSV, or
Markdown — three fields (error, description, hint) with pseudocode hints.
auth/xhubsig/v0.9.0
2026-04-13 17:04:45 -06:00