Commit graph

10 commits

Author SHA1 Message Date
Snider
e27006de30 fix(pr#2): address CodeRabbit round 3 review findings
- cache: fix LRU race — check expiry before MoveToFront within same lock
  critical section; previously a stale entry could be promoted before
  expiry was verified
- cache: drop stale ETag/Content-Md5/Digest headers when body is
  rewritten by refreshCachedResponseMeta to avoid misrepresenting the
  new body to clients
- ratelimit: cap buckets map at 100k entries with stale-eviction fallback
  and shared overflow bucket to prevent unbounded memory growth under
  high-cardinality traffic
- ratelimit: fix clientRateLimitKey comment — credentials are tried
  second (before IP), not as a "last resort"

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-07 09:29:03 +01:00
Snider
372326297e fix(pr#2): address CodeRabbit round 2 review findings
Go:
- cache: fix TOCTOU race in get() — re-verify entry pointer under lock before
  evicting to prevent corrupting s.currentBytes and removing a newly-set entry
- bridge: fix writeErrorResponse recorder out of sync — buffer into w.body/
  w.headers and call commit() so Status(), Header(), Size() reflect error response
- bridge: fix ValidateResponse number precision — use json.Decoder+UseNumber for
  initial envelope decode to preserve large integers (matches Validate path)
- ratelimit: fix unreachable credential branches — move X-API-Key and
  Authorization hashing before IP fallback so NAT'd clients are bucketed by key
- openapi: gate cacheSuccessHeaders on sb.CacheEnabled flag, not just method==get
- openapi: use isNilRouteGroup in prepareRouteGroups to catch typed-nil RouteGroup

PHP:
- RateLimitExceededException: remove ad-hoc CORS handling — let framework CORS
  middleware apply correct headers for all responses including errors
- SeoReportService.extractCharset: parse charset token from Content-Type value
  instead of returning the full "text/html; charset=utf-8" string
- SeoReportService: validate IP literals directly with filter_var before DNS
  lookup so ::ffff:127.0.0.1-style hosts don't bypass private-IP checks
- SeoReportService.isPrivateIp: extract isPrivateIpv4 helper; handle
  IPv4-mapped IPv6 (::ffff::/96) by checking embedded IPv4 against private
  ranges; add 0.0.0.0/8 to private range list

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-07 09:11:05 +01:00
Snider
e54dd2e370 fix(pr#2): address CodeRabbit major/critical review findings
Go:
- codegen: pass trimmed specPath to buildArgs instead of raw g.SpecPath
- cmd/sdk: use local resolvedSpecFile to avoid mutating flag variable per-invocation
- export: write to temp file + atomic rename to prevent destination truncation on failure
- openapi: gate effectiveGraphQLPath/SwaggerPath/WSPath/SSEPath on enable flags; use effectiveSwaggerPath in effectiveAuthentikPublicPaths
- cache: reject oversized replacement before mutating LRU state for existing keys
- ratelimit: move setRateLimitHeaders before c.Next() so headers are sent; hash credential headers with SHA-256 to avoid storing raw secrets; prefer validated principal from context
- response_meta: track size separately from body buffer so Size() is accurate after body rewrites and in passthrough mode
- bridge: limit request body reads with http.MaxBytesReader (10 MiB); allow missing data key in ValidateResponse for nil/zero success responses; update recorder status in writeErrorResponse
- pkg/provider/proxy: validate target scheme and host after url.Parse to catch hostless inputs
- cmd_test: snapshot/restore global spec registry in TestAPISpecCmd_Good_RegisteredSpecGroups

PHP:
- HasApiResponses.php, config.php: add declare(strict_types=1)
- RateLimitExceededException: validate Origin against cors.allowed_origins before reflecting in CORS header
- ApiUsageService: import and use Core\Api\Models\ApiKey instead of fully-qualified Mod\ path
- SeoReportService: add SSRF protection (scheme check, private-IP rejection); add .throw() for HTTP error handling; disable automatic redirects

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-07 08:38:41 +01:00
Virgil
085c57a06d feat(cache): add byte-bounded eviction
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-02 01:49:36 +00:00
Virgil
ad751fc974 fix(api): preserve multi-value cached headers
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-02 00:07:01 +00:00
Virgil
c4cbd018ac feat(api): auto-attach request metadata
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-01 14:00:04 +00:00
Virgil
37b7fd21ae feat(cache): refresh request meta on cache hits
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-01 13:53:37 +00:00
Virgil
2d8bb12311 fix(api): preserve request id on cache hits
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-01 13:37:38 +00:00
Virgil
837a910148 feat(cache): add LRU eviction limit
Add an optional maxEntries cap to WithCache so the in-memory cache can evict old entries instead of growing without bound.\n\nCo-Authored-By: Virgil <virgil@lethean.io>
2026-04-01 09:27:22 +00:00
Snider
753812ad57 feat(api): merge go-api + php-api into polyglot repo
Go source at root level (Option B), PHP under src/php/.
Module path: forge.lthn.ai/core/api
Package name: lthn/api

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-14 10:03:29 +00:00