Implements gaps between RFC.md spec and code:
- Export canonical webhook event identifiers (RFC §6) as Go constants:
WebhookEventWorkspaceCreated, WebhookEventLinkClicked, etc. Plus
WebhookEvents() and IsKnownWebhookEvent(name) helpers for SDK consumers
and middleware validation.
- Surface the chat completions endpoint (RFC §11.1) through TransportConfig
(ChatCompletionsEnabled + ChatCompletionsPath) and the OpenAPI spec
extensions (x-chat-completions-enabled, x-chat-completions-path) so
clients can auto-discover the local OpenAI-compatible endpoint.
- Add internal test coverage for chat completions sampling defaults
(Gemma 4 calibrated temp=1.0, top_p=0.95, top_k=64, max_tokens=2048)
and the ThinkingExtractor channel routing (RFC §11.6).
Co-Authored-By: Virgil <virgil@lethean.io>
- options.go: new WithChatCompletions(resolver) and
WithChatCompletionsPath(path); api.New(...) now auto-mounts at
/v1/chat/completions when a resolver is configured (previously the
resolver could be attached but never mounted, which would have
panicked Gin)
- chat_completions.go: fixed missing net/http import, dropped
ModelType during discovery, Retry-After header set after c.JSON
silently lost, swapped OpenAI error type/code fields, swapped
validate call site, redundant nil check, builder length read before
nil-receiver check
- openapi.go: effective*Path helpers surface an explicit path even
when the corresponding Enabled flag is false so CLI callers still
get x-*-path extensions; /swagger always in authentik public paths
- chat_completions_test.go: Good/Bad/Ugly coverage for new options,
validation, no-resolver behaviour
- openapi_test.go: fix stale assertion for CacheEnabled-gated X-Cache
- go.mod: bump dappco.re/go/core/cli to v0.5.2
- Removed local go-io / go-log stubs — replace points to outer
modules for single source of truth
- Migrated forge.lthn.ai/core/cli imports to dappco.re/go/core/cli
across cmd/api/*.go + docs
Co-Authored-By: Virgil <virgil@lethean.io>
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>
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>
Treat enabled built-in transports as having their default paths when callers omit an explicit override. This keeps manual SpecBuilder usage aligned with the engine defaults and prevents Swagger, GraphQL, WebSocket, and SSE metadata from disappearing from generated documents.\n\nCo-Authored-By: Virgil <virgil@lethean.io>
Preserve the Swagger UI mount path in generated OpenAPI output and expose it through the spec and sdk CLI builders.\n\nCo-Authored-By: Virgil <virgil@lethean.io>
Adds GraphQL Playground coverage to the generated OpenAPI spec when the GraphQL playground option is enabled, and wires the engine metadata through so runtime docs match the mounted route.
Co-Authored-By: Virgil <virgil@lethean.io>
Simplifies route-group preparation by dropping dead metadata that was no longer used by the OpenAPI builder.
Co-Authored-By: Virgil <virgil@lethean.io>