Repository navigation
v0.7.0
Review remediation: release pipeline, server sessions, transport hardening & docs truth (spec 021-2 / 021-3)
Includes 021-3 remediation work orders W001–W041 resolving server session concurrency and turn locking, NAT64 metadata defense-in-depth, transport lifecycle safety, and docs truth.
Breaking changes:
-
SDK API rename —
askSeepient/runSeepientServer: The one-shot entry pointsgenerateText/streamTextare replaced by a single unifiedaskSeepient(prompt, options); the server factorycreateServer/startServeris renamedrunSeepientServer. Migration (pre-1.0, no shims):Old (≤ v0.6.x) New (v0.7.0) generateText(prompt, options?)askSeepient(prompt, options?)streamText(prompt, options?)askSeepient(prompt, { ...options, stream: true })createServer(options?)/startServer(options?)runSeepientServer(options?)(uselisten: falsefor an unattachedhttp.Server)GenerateTextOptions/StreamTextOptionsAskSeepientOptionsGenerateTextResultAskSeepientResultStreamTextResultAskSeepientStreamResultServerOptionsRunSeepientServerOptions(now exported only fromseepient/server, next torunSeepientServer)Additional surface changes in the rename:
toResponse()now accepts optional{ headers }; phantom structured-output fields were removed (AskSeepientOptions.output,AskSeepientResult.data/error— structured output remains deferred);Seepient.chatStream()options no longer acceptstream/signal(it is always streaming and owns its abort handle via the returned result);RunSeepientServerOptions.settingsManageris typed by theSettingsManagerLikecontract instead ofany. Update all imports and call sites accordingly — no compatibility aliases are provided in the pre-1.0 phase. -
SDK session ownership binding (tenant isolation):
createSeepientnow stamps the effectiveprincipalId(default"sdk-user") on every persisted session (SessionData.principalId) and fails closed withSESSION_OWNERSHIP_MISMATCHwhen resuming under a different principal — previously a second tenant supplying the samesessionIdand its own stores could restore and continue the first tenant's conversation. Sessions persisted before this change carry no owner stamp and will not resume (delete the stored session or start a newsessionId). CustomPersistenceBackendimplementations must round-trip the newprincipalIdfield; the deprecated messages-onlySessionStoreadapter cannot carry ownership and now fails closed when resuming an existing session. Expanded API key hash digests from 16 to 64 hex characters (full SHA-256). Pre-0.7.0 session files created under 16-hex key ownership will not resume and fail closed with a descriptive error. Server sessions are ephemeral runtime state.
Release pipeline & packaging safety (US1):
- Static publish hook safety: Restored
prepublishOnlytopnpm run build(HEAD semantics); addedpnpm run pack:verifystatic hook assertion preventing clean/delete scripts in publish hooks and verifying native exact-commit helper staging. - Release workflow gate: Added
pack:verifygate to.github/workflows/release.ymlbetween staging and npm publish. - Docker CI health & documentation: Added CI container image build & health check job to release pipeline; updated Dockerfile and standalone usage documentation comments; removed deprecated
SEEPIENT_SHELL_APPROVE. - Artifact hygiene: Removed uncommitted temporary visual check artifacts and stale architecture dumps.
Server sessions & WebSocket integrity (US2):
- Stateless one-shot chat & session adoption (D1):
POST /v1/chatand WebSocket chat requests sent without asessionIdoperate statelessly as one-shot turns — no session files are created on disk, no session capacity limits are consumed, and nosessionIdis returned. Requests providing an explicitsessionIdadopt or create the session and persist full turn history. - Id-preserving session lifecycle:
createSessionadopts client-supplied IDs across memory and persistence backends with strict charset validation and collision refusal.addMessagefails loudly on missing sessions. GET /v1/sessionsendpoint: Added authenticated collection listing returningSessionSummarymetadata for the caller's key only (no message bodies).- REST session resumption:
POST /v1/chataccepts optionalsessionId, resumes conversation history, persists turn messages, and echoes session identity. - WebSocket concurrency guard & lifecycle: Single in-flight chat per connection with
REQUEST_IN_FLIGHTerror frame; abort signals reach active streaming controllers; pipeline identities use UUIDs. - SDK turn mutex durability:
chatStreamfinallyblock guarantees mutexrelease()executes even if session persistence fails.
SDK parity & type truth (US3):
- One-shot option parity: Added
purposeandtieroptions toGenerateTextOptionsandStreamTextOptions, threaded to agent loop resolution. - Declaration type narrowing: Narrowed
TrustedHostToolEffectDeclarationto supported effect kinds (network-egress,secret-use,model-egress), injecting boundary defaults and eliminating untyped casts. - Unified local store predicate: Added
isLocalAuditStorehelper unifying local filesystem store detection across SDK, HTTP server, and lifecycle factory. - Runtime contract extension: Extended
ProviderRuntimeContractwith optional inspection and listener cleanup methods, eliminating(runtime as any)probes.
021-4 remediation work order (W100–W164):
- API rename landed (D1 adopt):
askSeepient/runSeepientServerare the public API; abort reaches media operations again;onErrorparity in non-streaming mode;hooks.onFinishfires in streaming mode; phantom structured-output fields removed;chatStreamoptions narrowed;SettingsManagerLikecontract replacessettingsManager?: any. - Embedding safety (W130/W131):
runSeepientServerregisters signal handlers only when listening and returns adispose()handle; the WebSocket layer is per-instance (independent WSS + registries), so multiple servers can live in one process. - Security parity (W140–W146): WS handlers enforce the REST scope model (
agent:run/agent:read); the effect broker and the transport validator now share byte-level IP classification (hex-mapped, v4-compatible, NAT64, and reserved IPv4 spellings denied); gateway OpenAPI import and REST calls route through the SSRF-validated pinned fetch (gateway_import_openapire-classifiedcommunications); cross-host redirect credential stripping is case-insensitive incl.X-Api-Key;safeSsrfFetchgained a cross-hop deadline; default CORS no longer reflects arbitrary origins; WS messages consume the shared rate limiter, per-key connection caps enforced (SEEPIENT_WS_MAX_CONNECTIONS_PER_KEY), and non-/wsupgrades are 404'd. - Session integrity (W150–W154, D3 option a): send-time history normalization collapses dangling failed-turn user messages on the model-input copy (stored crash-recovery data intact); resolved-error turns persist no empty assistant row and answer 502; the absolute session TTL defers to in-flight turns and
deleteSessionrefuses while a turn is live; denied cross-key probes no longer cache the victim's session; sessionId charset/length aligned (128-char cap). - Transport polish (W160–W164): unified capped body reader (413 on settings/gateway/provider routes);
server.rateLimitRpmre-read per request; shutdown closes keep-alive sockets and flushes the audit outbox before force-exit; sanitized error envelopes with raw detail only in logs;scripts/now typechecked in the test gate with a docs-sync test denying deleted API symbols; strict IPv6 hex validation; media and webhook fetches routed through the validated fetch.
Transport hardening & documentation truth (US4):
- Default CORS no longer reflects arbitrary origins (021-4 W145): with no
server.corsOriginssetting and noSEEPIENT_CORS_ORIGINSenv var, responses carry noAccess-Control-Allow-Originheader — browser cross-origin access is now opt-in. Set the setting or env var to an origin allowlist, or*to reflect any origin. Combined with the default0.0.0.0bind, the previous default made the allowlist feature moot out of the box. - SSRF socket IP pinning: Reused socket lookup override primitive via
pinnedFetchto connect strictly to pre-validated IP addresses, eliminating DNS rebinding TOCTOU windows. Added 5-hop redirect limit and extended private/reserved CIDR blocks. - Transport DoS caps: Enforced 10 MB default body limit on REST requests (
413 PAYLOAD_TOO_LARGE), 1 MiB WebSocket frame size (maxPayload), 300 rpm per-key token bucket rate limiter (429 RATE_LIMITED), and configurable CORS allowlist (SEEPIENT_CORS_ORIGINS). - Structured request logging: Added JSON-line logger with
requestIdcorrelation at transport seams; sanitized 500 error responses to prevent internal detail leaks. - Documentation reorganization: Removed duplicate
docs/embedding/workers.mdin favor of canonicaldocs/sdk/stateless-workers.md, repointed VitePress sidebar and documentation references, and configured.gitignorefordocs/.vitepress/dist. - Documentation truth: Corrected docs license to BUSL-1.1; removed phantom
seepient/reactguide; corrected/sdk/session-persistencelinks and serverpersistoption.