Rename net/ipgate to net/ippolicy and compose independently refreshed
whitelist and blacklist sources into one IP decision policy.
- rename slog group and error prefixes from ipgate to ippolicy
- delete unused ParseDomainSet and RecordReader from domainsetcsv.go
- rewrite README to match the actual Config API
- document nil-whitelist behavior on New()
- bump iplist dependency to v0.8.5
- go mod tidy: remove stale ipgate and iplist entries
Add net/iplist for shared IP-policy source loading.
- Accept local TSV/CSV file paths or HTTP(S) URLs (including Google Sheets).
- Auto-detect TSV vs CSV format from file content.
- Send Accept: text/tab-separated-values header for content negotiation.
- Parse the first column and ignore comments (#) and optional "network" header.
- Expand nested list URLs up to MaxNestedSources (2) levels.
- Support Basic Auth from URL userinfo without sending credentials in the URL.
- Persist cached URL responses across restarts via httpcache.
- Refresh periodically and preserve the known-good cache on fetch or parse failure.
- Validate entries as IP address, CIDR range, or domain name (Validate()).
- Use golib/https.NewInternalClient() through httpcache.NewWith.
- Add README with usage examples and entry format documentation.
Add non-breaking context-aware and custom-HTTP-client variants of the
existing reader and fetch functions:
- NewReaderFromContext / NewReaderFromContextWith
- NewReaderFromURLContext / NewReaderFromURLWith
- NewReaderFromIDsContext
- GetSheetContext
All existing function signatures are unchanged. The shared response
handling is extracted into newReaderFromResponse, and the legacy GetSheet
path is refactored through getSheetWithGet for clarity.
Ensure cohort is never nil:
- NewDomainSet stores an empty Cohort before rebuildCohort, so a parse
failure leaves an empty (non-nil) cohort instead of nil
- Contains uses CompareAndSwap to lazily self-initialise a zero-value
struct, making nil impossible after first access — no explicit nil
check needed
Extract the cache-validity check into a testable cachedCohortValid()
helper and add filesPresent() to detect when data files exist on disk.
Use strings.Builder in commaify() for efficiency.
Tests:
- TestPrefixSetContainsZeroValue: zero-value self-heals via CAS,
cohort is non-nil after first Contains call
- TestCachedCohortValidRequiresFiles: cache invalidation logic
Add tests for AuthorizationSchemes ["*"] accepting any scheme and
for unaccepted schemes returning ErrNoCredentials without falling
through to cookies. These fill pre-existing test gaps unrelated to
the TokenCookies feature.
Add a TokenCookies []string field checked after query params (step 5).
Each named cookie's value is passed directly to Authenticator.Authenticate
as a token, enabling cookie-based token flows alongside Bearer and query params.
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.