You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
engine: multi-file specs — bounded load-and-bundle and a sources-based entry point #74
Split-file OpenAPI repos — the common real-world layout — don't work at all:
A minimal two-file spec with a correct relative $ref: './child.yaml#/components/schemas/Child' yields error openapi/unresolved-ref and the referencing type degrades to t/prim/any (verified with absolute and relative CWDs).
architecture.md §2.1 phase 1 promises "Load & bundle — read all source files, resolve external references"; the harness comment confirms the gap is known ("the compiler does no file I/O, so the external ref surfaces as an unresolved-ref error").
Document.Sources is hard-coded to exactly one entry (compilers/openapi/openapi.go:58).
engine.Run(ctx, specPath, opts) does its own os.ReadFile and always passes exactly one compilers.Source, although the compiler contract accepts a slice by design ("the caller loads bytes"). Embedders with in-memory specs must write temp files today.
Proposed direction
Two stages, both sized against the docs' own milestones:
The seam (S, now): add engine.RunSources(ctx, []compilers.Source, RunOptions) and make Run a thin file-loading wrapper. Two functions, no behavior change — the multi-file seam stops being a future breaking change to the engine's only entry point.
Load-and-bundle (L): a bounded file loader (root-relative, no network by default, file-count/size budgets per openapi+engine: resource budgets for pathological-but-legal inputs #75) wired into reference resolution; every contributing file recorded in Document.Sources with its hash; provenance Source indices pointing at the right file. Until it lands, make external-ref behavior honest: unresolved-with-diagnostic by default and DisableExternalRefs not a trap.
Note for the cache work (#76): once multiple files contribute, all of them must appear in Sources for cache keys to stay sound — design together.
Acceptance
The two-file repro compiles with the child type resolved, Sources listing both files, and provenance pointing into the correct one.
In-memory compilation via RunSources needs no temp files.
With allow-external-refs=true, cross-document references to parameters and responses resolve today (the fixtures resolve_main_external_valid.yaml and resolve_main_alias_external_valid.yaml cover them), but a cross-document schema reference never does. A one-hop $ref: './components.yaml#/components/schemas/X' is openapi/unresolved-ref whether the target file is a full OpenAPI document or a components-only fragment. The passing tests therefore don't show that multi-file schemas work.
If the implementation reuses the parser's openapi.Bundle, it doesn't rebase discriminator mapping values (they are URI references too), and it doesn't copy a schema that is reachable only through a mapping. Both surface as unresolved-ref on the mapping after bundling.
Activity
OmarAlJarrah commentedon Sep 30, 2026
Two details for the load-and-bundle work:
allow-external-refs=true, cross-document references to parameters and responses resolve today (the fixturesresolve_main_external_valid.yamlandresolve_main_alias_external_valid.yamlcover them), but a cross-document schema reference never does. A one-hop$ref: './components.yaml#/components/schemas/X'isopenapi/unresolved-refwhether the target file is a full OpenAPI document or a components-only fragment. The passing tests therefore don't show that multi-file schemas work.openapi.Bundle, it doesn't rebase discriminator mapping values (they are URI references too), and it doesn't copy a schema that is reachable only through a mapping. Both surface asunresolved-refon the mapping after bundling.OmarAlJarrah commentedon Oct 19, 2026
Two related results at
c387e25c:engine.Runreads the root spec and an overlay withos.ReadFile, with no size bound and no cancellation (engine: the root spec and an overlay are read with no size bound and no way to cancel #969). A FIFO blocks indefinitely, and/dev/zerogrows past 10 GB in 2 s.Runtakes only a path, so a driver cannot hand it sources it already holds, or a persisted IR document. The first emitter's driver will want both (engine: move diagnostic rendering and artifact writing out of the CLI, where emitter-design §2.1 puts them in the engine #958).fix(compilers/openapi): lend a use site only what its type reaches
fix(compilers/openapi): word another document's identifiers truly