This document expands the request lifecycle in docs/architecture.md.
cmd/lipstd is the standard distribution entrypoint. Its startup path is intentionally explicit and matches the converged ownership model in architecture.md: one process runtime / ProcessServices, one generation runtime (GenerationRuntime), one private-field host (runtimebundle.Host from runtimebundle.BuildHost; Host.Close owns shutdown; Manager-owned retirement drains superseded generations), and one reload contract (pkg/lipsdk/configreload, explicit triggers only). Candidate assembly stays package-private and temporary (not a runtime API). ValidateDistribution / check-config is true unpublished validation (compile + rollback; never publish).
runtimebundle.BuildHost owns the whole sequence as one transaction and returns a complete Host or rolls back and returns nil; cmd/lipstd serve and public lipruntime.Build are its only production callers. Public lipruntime.Build normalizes descriptor-bound registrations on lipruntime.Options, then calls canonical registration-only Host construction through runtimebundle.BuildHost. Field migration: legacy-options-migration.md. Supported public Runtime methods: Build, ExecutorView, Ready, Capabilities, MeteringQuerier, ReadinessReport, RefreshSnapshots, Reload, ReloadStatus, ReloadControl, Close.
- The strict effective loader (
LoadBootstrapEffectiveWithSource, the sole config-load owner) reads YAML into typed config exactly once and runsrouting.ValidateModelAliasesConfig. BuildHostevaluates the serve-only--multi-userCLI gate against that same accepted snapshot before acquiring any expensive resource.tracing.Initandlogging.NewLoggercreate process infrastructure.pluginreg.NewRegistrycreates an isolated registry for this process.standardplugins.ResolveUpstreamAPIKeysFromEnvreads fallback hosted-provider keys.standardplugins.InstallStandardBundleOninstalls official backend, frontend, feature, and auth-renderer factories.config.RegistrationsFromConfigselects configured plugin instances.featurebundle.MergeFeatureSurfacebuilds hook and extension chains from configured feature plugins.runtimebundleconstructs the process runtime and publishes request-plane generation 1 as aGenerationRuntime(executor, stores, model catalog, metrics, tracing, health, diagnostics, handler graph) — all still insideBuildHost.BuildHostbinds the startup-fixed config source, effective loader, generation compiler, and reload coordinator onto that same generation and returns the completeHost;stdhttpserves through a generation dispatcher until context cancellation. Optional management reload HTTP starts only whenLIP_RELOAD_MANAGEMENT_ADDRESSis set; UnixSIGHUPinvokes the same coordinator. CLI and public facade shutdown delegate toHost.Close.
Custom tests and future alternate distributions should follow the same shape: construct an explicit registry or bundle, publish an immutable generation, then serve. Operator reload contract: runtime-config-reload.md (pkg/lipsdk/configreload).
A bundled frontend owns wire-level details: route path, request body shape, streaming flags, protocol-specific validation, and protocol-specific error rendering. It decodes to lipapi.Call and calls the runtime executor. It must not call backend plugins directly.
HTTP auth is a transport concern in internal/stdhttp. Stable identity crosses into runtime through pkg/lipsdk/transport/httpauth and pkg/lipsdk/execview, not through *http.Request or middleware-specific types.
The executor validates lipapi.Call before orchestration. When present, extensions.RequestRuntimeSnapshot is attached to the context. A snapshot is immutable for the request lifetime; runtime config reload publishes a new generation (and snapshot) for new admissions instead of mutating objects reachable by in-flight work.
Secure-session preparation is core-owned. The runtime resolves workspace metadata, opens or resumes the authoritative proxy session, maps denials to stable public errors, and fetches the B2BUA A-leg. Client-provided session hints are hints only; they do not authorize resume or A-leg selection.
Before route planning, the runtime runs configured feature stages in the legal order:
session_openfor first-turn labels and bootstrap metadata;submit_requestfor brownfield submit hooks;traffic_observationfor canonical client-to-proxy snapshots where configured;tool_catalog_filterfor outbound tool definition policy;request_wide_shapingfor whole-call transforms;route_hintingfor advisory route preferences.
Mutation stages must leave the canonical call valid. Stage runners validate after mutation where they own canonical changes.
The executor parses the route selector, applies aliases and default backend resolution, expands weighted/failover candidates, applies candidate health, and honors route hints as advisory preferences. For each candidate, capability negotiation and model-catalog eligibility run before backend open. A candidate can be rejected, downgraded attempt-locally, or opened.
For an eligible candidate, the executor allocates the next B-leg, runs request-part hooks, merges route query parameters into generation options, emits proxy-to-backend traffic observations when configured, and calls the selected backend's Open method.
Backends return lipapi.EventStream. They translate provider SDK or wire events into canonical events and classify recoverable pre-output failures with enough metadata for routing and diagnostics.
The returned stream wrapper preserves the no-retry-after-output invariant. Before first output, recoverable open or recv failures may consume additional B-legs and try another candidate. After first output, failures are terminal for that stream.
On received events, the stream path applies response-part hooks, tool reactors, completion gates, secure-session recording, traffic observation, and attempt outcome recording where those handlers are configured. Frontend encoders then render canonical events into legal streaming or collected protocol responses.
Frontend adapters translate protocol-specific cancel operations into lipapi.ALegCancelRequest; core cancellation remains A-leg based. OpenAI Responses cancel accepts the proxy response id from /v1/responses/{response_id}/cancel as the primary correlation carrier for normal clients; proxy-issued response ids carry the A-leg and authoritative session binding needed for core authorization. X-LIP-A-Leg-Id remains a LIP-private fallback for internal/test clients and older responses. Frontends must not require a private LIP header when the public protocol already carries an opaque response id issued by this proxy.
- Bad client input fails at frontend decode or canonical validation.
- Unsupported required capabilities fail before upstream I/O for the selected candidate.
- Recoverable upstream failures can be swallowed only before output starts.
- Post-output failures surface as terminal stream errors.
- Extension failures follow stage-specific failure policy; fail-open stages log and continue, fail-closed stages reject.
- Panics at extension/backend boundaries are isolated and mapped to structured errors or fail-open skips according to the boundary and stage.
Reload is operator-triggered only (SIGHUP and/or management POST /admin/config/reload). File edits alone do nothing. The coordinator re-reads the fixed startup path under a 2 MiB strict YAML bound, requires atomic path replacement for changed content, classifies restart-required vs reloadable fields, compiles a candidate generation, and atomically swaps the active pointer. Failures keep last-good; correction requires another explicit trigger. Details, status fields, retention (default budget 8), and management opt-in live in runtime-config-reload.md.
- Change frontend wire decoding or encoding in
internal/plugins/frontends/<id>. - Change backend provider mapping in
internal/plugins/backends/<id>. - Change shared canonical semantics in
pkg/lipapionly when multiple protocols need the concept. - Change plugin author contracts in
pkg/lipsdk. - Change route planning, B2BUA, secure-session, or no-retry semantics in
internal/core. - Change standard wiring in
cmd/lipstd,internal/pluginreg,internal/infra/runtimebundle, orinternal/stdhttp. - Change reload policy/triggers in
internal/core/configreload,internal/infra/runtimehost,internal/infra/configsource, andinternal/stdhttp/admin/configreload(see ADR 0008).