Skip to content

Release 3.0.0

See GitHub Release.

Viaduct 3.0.0 is a major release. The headline work is schema scopes declared in scopes.yaml and validated at build time, one ctx.ref(...) entry point for node and root-field references, a soft-by-default GraphQL Representational Type (GRT) getters, a Java Tenant API (beta release), and Java 25 support. It also includes early work on a new execution engine and @defer incremental delivery, both off by default.

Three changes affect every consumer's build regardless of what else they use:

  • the Viaduct Gradle plugins now require Kotlin 2.2 or 2.3;
  • tenant modules must be rebuilt with the 3.0 plugins;
  • GRT getters getX() now returns null on a data failure instead of throwing.

Start with Requirements and Breaking Changes below.

Requirements

  • Java: 17 is the new minimum (support for Java 11 has been dropped), and the published bytecode still targets Java 17. Viaduct 3.0 is built and tested on Java 17, 21 and 25.
  • Kotlin: the Viaduct Gradle plugins require Kotlin 2.2 or 2.3. Building for Java 25 needs Kotlin 2.3. Use a KSP2 release that matches your Kotlin version (KSP 2.3 uses standalone versions such as 2.3.7).
  • Gradle: 8.11 or newer; CI tests builds on 8.11 and 9.1. Java 25 needs Gradle 9.1 or newer.

Breaking Changes

Build and bootstrap — affects every consumer

  • The Viaduct Gradle plugins require Kotlin 2.2 or 2.3 (16653620b) by @gokhan-ozgozen — Viaduct itself now builds with Kotlin 2.3.21, KSP 2.3.7 and Gradle 9.1. This commit carries no !, but it is the change most likely to break a consumer build. See Requirements.
  • Rebuild every tenant module with the 3.0 plugins. Module configs generated by 2.0 fail at startup:
  • every field and node entry must now carry tenantMetadata (1a50aec92, 9b686122c) by @pclowes;
  • every config must declare an apiName, and two configs with the same <tenantName, apiName> are rejected (9ffd1fd5c) by @kristileka;
  • a config file whose version is not 1 is rejected (0ea77aa07) by @kristileka.
  • Schema scopes are declared in src/main/viaduct/scopes.yaml; the viaductApplication { declareScoping { } } DSL is removed (ad8aa6c09) by @geovannefduarte — move the DSL contents into scopes.yaml with version: 1. Multi-document YAML, YAML aliases and empty named scope sets are rejected. SchemaScopingBuilder and the SCHEMA_SCOPES_DECLARED_TWICE / SCHEMA_SCOPING_DECLARED_TWICE error codes are gone.
  • Schema files and module configs are loaded from build-generated resource indexes (7e8bd1805, 9e18ace23) by @pclowes — the application plugin writes META-INF/viaduct/indexes/*.index, and the runtime loads only the resources listed there. Each indexed resource must appear exactly once on the classpath, and duplicate module-config contributors fail the build. Standard plugin layouts need no change. .graphqls files or module JSON added to the classpath outside the build must move into it. A missing index fails startup with an actionable error; there is no classpath-scan fallback. Supply schemas and module configs through the generated indexes, or pass them explicitly.

Stricter build-time validation

Each of these fails a build that 2.0 accepted:

  • Type-level @resolver on an object type that doesn't implement Node (RESOLVER_ON_NON_NODE_OBJECT) (20eee5ecb) by @gokhan-ozgozen;
  • @namespaceType on a type that also declares @connection or @edge (NAMESPACE_TYPE_HAS_CONFLICTING_DIRECTIVE) (a169f2bb1) by @alexanderuv;
  • Two fields whose generated accessors collide, such as foo and fooOrThrow (527bad796) by @geovannefduarte;
  • A @Resolver class that doesn't extend exactly one generated resolver base. Indirect inheritance through an intermediate class is now allowed (85d2e3e15) by @catacraciun;
  • Required selection sets are disallowed on mutation resolvers (9755643c5) by @alexanderuv — mutation resolvers on the mutation root or on a reachable @namespaceType can't declare objectValueFragment or queryValueFragment. Call ctx.query() or ctx.mutation() inside resolve instead;
  • A variable used inside a nested named fragment of a required selection set must be bound; otherwise bootstrap fails with UnboundVariablesException (9a8e6f522) by @catacraciun;
  • A required selection set can't use a from-field variable in a @skip or @include condition (980b8b895) by @alexanderuv — a variable bound with fromObjectField or fromQueryField in the if argument fails bootstrap with InvalidVariableException. Select the value in the fragment and fetch the conditional data with ctx.query() instead. Variables bound with fromArgument or a variables provider still work;
  • A required selection set that applies a directive to a @parent field, or to an inline fragment or fragment spread that directly contains one, or that uses a variable anywhere beneath a @parent field (49a9cab0b) by @alexanderuv;
  • With scopes.yaml, an @scope(to:) name that isn't declared, or a declared scope set that produces an invalid schema (a324dedab) by @geovannefduarte;
  • Invalid @scope on type extensions that add no fields (922c023ef) by @geovannefduarte.

Generated types (GRTs) — Kotlin and Java

  • The bare accessor getX() now returns null instead of throwing (f137387b2) by @geovannefduarte — getX() is now the soft accessor, and getXOrThrow() is the strict one. Non-null Boolean!/Int!/Float! fields now return the nullable boxed type, so Kotlin call sites that use the value in arithmetic or boolean contexts stop compiling, and code compiled against 2.0 fails with NoSuchMethodError. Call sites that need the old behavior must switch to getXOrThrow(). Call sites on already-nullable schema fields keep compiling but change behavior silently, so audit them by hand. Java GRTs follow the same model: getAmount() returns Double, and getAmountOrThrow() returns double.
  • The getXOrNull() accessor form is removed from Kotlin GRTs (ba1a21601) by @geovannefduarte — rename call sites to getX(), which has the same soft behavior in 3.0. The API dump doesn't show this, because schema-specific generated classes aren't in it.
  • Java GRT reads now match Kotlin semantics (9d5b9ab42) by @catacraciun — reading an unselected or unset field raises UnsetFieldException instead of returning null. A null on a non-null field, and malformed list or object values, raise TenantUsageException.
  • Java GRT builders validate values (f4d90838a, 480a7663c) by @catacraciun:
  • a setter that receives a wrong scalar class, an invalid enum value, a GlobalID for the wrong type, or a null for a non-null field throws TenantUsageException;
  • build() throws for missing required fields and @oneOf violations;
  • list values are stored as unmodifiable copies.
  • Java resolvers for @idOf and Node ID fields return GlobalID<T> instead of String (d940dd53f) by @catacraciun
  • Java object GRTs no longer generate a Fields.<field> constant for @backingData fields (930382ac8) by @catacraciun — read backing data with ObjectBase.get("field", Backing.class).

Tenant API — resolver context

  • nodeRef is now ref (e128ccc48, 4ec3666ff) by @alexanderuv — ResolverExecutionContext.nodeRef(GlobalID) and the Kotlin nodeRef(localId: String) extension are removed in both the Kotlin and Java APIs. Call ctx.ref(...) with the same arguments.
  • rootFieldRef is replaced by ctx.ref with a generated root field call (bc4a879d9, 6ca3d04b9) by @alexanderuv — for example, Kotlin ctx.rootFieldRef(Query.Fields.product, args) becomes ctx.ref(Query.product { ... }). RootFieldCall.resolve is replaced by field() and arguments(context), so hand-written RootFieldCall implementations must be updated.
  • The string-based query(String, …) and mutation(String, …) overloads are removed from the Kotlin API (bcbf4a12e) by @kristileka — use query(QueryFromAnnotation, …) and mutation(MutationFromAnnotation, …).
  • Mutation contexts no longer expose query or object values:
  • Kotlin mutation contexts lose getQueryValue() (a46dc0792) by @alexanderuv;
  • the Java MutationFieldExecutionContext no longer extends FieldExecutionContext (e6dcb1e14) by @alexanderuv.

Read data with ctx.query(...) inside resolve. - In the Java API, ctx.mutation() works only in mutation field resolvers (a7787b34e) by @catacraciun — calling it from a query, node or object-field resolver throws TenantUsageException. - ResolverExecutionContext.selectionsFor(type, selections, variables) is removed (9139e4ed4) by @amity177 — declare reads as resolver dependencies, or use named operations. - The selection-construction surface of SelectionSet is removed (a6c0aaa2a, 4116a184d, de300569b, 8f2ce9602, c69d773c7) by @amity177: - removed: SelectionSet.type, isEmpty(), selectionSetFor(Type) and toFragment(), plus the OutputSelectionFragment class; - a custom SelectionSet passed to framework batching must implement InternalSelectionSet. - New abstract members for code that implements tenant API interfaces itself, such as test fakes: - SelectionSet.selectedFieldCoordinates() (c3f681279) by @alexanderuv; - SelectiveNodeExecutionContext.ownedSelections() (afe33183d) by @fireboy1919. - isPresent(field) is now true for an omitted input field that has a schema default (2731f3c88) by @catacraciun — Java input getters also return the schema default. Code that used isPresent to tell a client-sent value from an applied default must compare against the default instead. - Input getters and argument wrappers return programmatic defaults (cdfc33bbd) by @catacraciun — in 2.0 they threw or dropped the default. - viaduct.api.fetchOrNull and fetchOrDefault are now @InternalApi (b28ba31e1) by @catacraciun — Kotlin callers get an opt-in warning, which -Werror turns into an error. - Selective resolvers are temporarily disabled in the Java tenant API (8d6e7c90b) by @catacraciun — @resolver(isSelective: true) on a Java-resolved field or node fails codegen and bootstrap. Remove it, or keep those resolvers in Kotlin.

Service API

  • ViaductBuilder.withScopedSchemasFromSdl is removed (c6b0ba2fe) by @gokhan-ozgozen — 2.0's notes introduced it as the replacement for withSchemaConfiguration. Use withScopedSchemas(...), with SchemaScopeInfo.fromResources() to read the scoped schemas declared in scopes.yaml.
  • withScopedSchemas rejects an empty list, and the scope-definition types move (93ac16f77) by @geovannefduarte — registering no views used to build successfully and then answer every request with Schema not found. SchemaScoping, SchemaScopingValidator and ScopingErrorCodes move from viaduct.service.api.scoping to viaduct.scoping.
  • New FlagManager.Flags entries (ba3865e57) by @rstata — a custom FlagManager that returns true for every flag now fails engine construction, because ENGINE2_ENABLED and ENGINE2_BATCHING must be off on the default engine. ENABLE_CACHE_KEY_LOOKUP_PARTITIONING is deprecated, and partitioning is always on (81f0c0512) by @njlynch.
  • Resolver error reporters receive ResolverOutputMissingFieldException (aaa998ebf) by @fireboy1919 — this happens whenever a requested field is missing from a resolver's output. The new ENABLE_RESOLVER_OUTPUT_MISSING_FIELD_ERRORS flag also turns it into a GraphQL error (VIADUCT_RESOLVER_OUTPUT_MISSING_FIELD).

Test fixtures (com.airbnb.viaduct:test-fixtures)

  • RootFieldRefStub and the rootFieldRefValues / rootFieldRefResults inputs are removed (f1f62aab6, e5906d370) by @alexanderuv — assert the references a resolver creates with ReferenceSpy.
  • The mock execution contexts' constructors gain a referenceSpy parameter before ownedSelectionsValue and caller (e5906d370) by @alexanderuv — pass trailing arguments by name.
  • Mutation mocks and specs no longer accept queryValue (2acd5b6c9) by @alexanderuv — supply query results through contextQueryValues.
  • Classpath resolver scanning is removed (d2dcb1c6f) by @pclowes — ClassGraphScanner, TenantResolverClassFinder, TenantPackageInfo and findResourcePathsMatching are gone. The feature-app test contracts no longer validate resolver completeness by scanning.
  • The jar no longer bundles JUnit or ClassGraph (5d73441bd, 9e18ace23) by @geovannefduarte, @pclowes — 3.0.0-rc.1 bundled JUnit Jupiter API 5.11.3, which 2.0.0 did not. Declare junit-jupiter-api in your test dependencies, as 2.0.0 already required.

Engine SPI — affects advanced integrators

  • The TenantAPIBootstrapper lane is removed (a73e3ac81, cf9919915) by @kristileka — StandardViaduct.Builder.withTenantAPIBootstrapperBuilder(s) and withNoTenantAPIBootstrapper are gone. Provide tenants through module configs and withTenantModuleInjectorFactory.
  • The Java classpath-scanning bootstrapper is removed (db0dcf71d) by @catacraciun — ModuleBootstrapper, DefaultResolverClassFinder, JavaTenantAPIBootstrapper and ResolverClassFinder are gone. Java resolvers load from the registry the module-java plugin generates at build time.
  • TenantModule is removed (7f7bde034) by @pclowes — resolver attribution comes from the generated tenantMetadata.
  • The engine schema type ViaductSchema is renamed EngineSchema (b5444c026) by @gokhan-ozgozen — this changes the deprecated ViaductBuilder.withCheckerExecutorFactoryCreator and the CheckerExecutorFactory / ExecutorFactory SPIs.
  • Other engine-API removals and moves:
  • ObjectEngineResult and ResolveSelectionSetOptions.targetResult are removed (93f54eeaa) by @rstata;
  • the execution-registry config types move to viaduct.bootstrap (c19ab6a6f) by @kristileka;
  • SelectionsParser.parse loses knownFragments (300e99eeb) by @kristileka;
  • Engine.completeSelectionSet is removed (609a6a728) by @rstata.

Experimental — x/remoteresolvers, not covered by the API stability contract

  • The remote-resolver wire encoding is now versioned (7fc43a5b0) by @cetinsahin — build the RRS and the RRP from the same Viaduct version.

Features

Schema scopes

  • Scopes are declared in scopes.yaml, and every declared scoped schema is built and validated during the build, with all failures reported at once (ad8aa6c09, a324dedab) by @geovannefduarte.
  • The build hands the declared scopes to the runtime as a manifest, and SchemaScopeInfo.fromResources() returns them (93ac16f77) by @geovannefduarte.

Java tenant API

  • Stability annotations: every public Java API type carries @StableApi, @ExperimentalApi or @InternalApi (c8a0913bf) by @catacraciun, and the stable surface is checked for binary compatibility (#436) by @geovannefduarte.
  • Location: the implementation moved from core/x/javaapi to core/javaapi (70423b54b) by @catacraciun. Packages and published coordinates are unchanged. The API reference moved from /apis/x-javaapi-api/ to /apis/javaapi-api/.
  • Generated types now match Kotlin: Java GRTs generate the same accessors as Kotlin (9d5b9ab42), toBuilder() on object and input GRTs (cd4028da2), and dynamic @backingData reads (930382ac8). Code generation honors custom root type names (8f45c84e3). All by @catacraciun.
  • Resolver features:
  • field batch resolvers can return a per-item value, null or error through batchResolveWithErrors (87f886c8e);
  • typed GlobalID<T> for ID fields (d940dd53f);
  • @TenantBootstrapper support (97025acd1);
  • non-blocking fetchOrNull / fetchOrDefault helpers (b28ba31e1).

All by @catacraciun. - Gradle: the module-java plugin runs the Java registry annotation processor and packages the module config, so Java modules bootstrap without classpath scanning (6345cc115) by @kristileka. - Demo: a standalone Java demo application, demoapps/starwars-java (4e05cd91b) by @catacraciun.

Resolver context and references

  • ctx.ref(...) is the single entry point for lazy references to nodes and root fields:
  • ctx.ref(GlobalID) and ctx.ref(localNodeId) (d9828a499) by @alexanderuv;
  • generated RootFieldCall factories on the root query type and every eligible namespace field (4ca5b19ae, 23b0a3d14) by @alexanderuv.
  • Field resolver contexts expose the calling resolver as caller. It is informational and must not be used for authorization (ba07c27e2) by @alexanderuv.
  • Generated types add getXOrThrow() next to getX() (527bad796) by @geovannefduarte.
  • ReferenceSpy asserts the references a resolver creates (e5906d370) by @alexanderuv, and the mock harness supports @GraphQLOperation queries and mutations (ae6da2a78) by @kristileka.

Selective resolvers

  • Selective resolvers can read the selections they own with ownedSelections() (afe33183d) by @fireboy1919.
  • Experimental batching helpers in viaduct.api.batch, and SelectionSet.selectedFieldCoordinates() (c3f681279) by @alexanderuv.
  • A FieldSelectivityProvider SPI (75641a72f) by @jbellenger.
  • Documentation and a Star Wars demo of selective field and node resolvers (b7b444b15, 74f0782db) by @jbellenger.

Build and Gradle plugins

  • Java 25 support: Viaduct is tested on Java 17, 21 and 25, and the demoapps run on all three (#437) by @geovannefduarte.
  • Viaduct builds with Kotlin 2.3.21, KSP 2.3.7 and Gradle 9.1 (16653620b, 00230ca63) by @gokhan-ozgozen.
  • Schema and module-config loading is owned by the build (7e8bd1805, 9e18ace23) by @pclowes.
  • New com.airbnb.viaduct.gradle:metamodule library, applied by the module plugins (b5b5115b7, a94251ea3) by @gokhan-ozgozen:
  • it validates that each module is declared in the application topology;
  • it lets module-extension plugins contribute schemabase definitions;
  • identical contributions are deduplicated, and conflicting ones are reported with their sources.
  • Generated interfaces carry both native JVM default methods and the legacy DefaultImpls, so consumers link with either layout (1fa7c7da9) by @fireboy1919.
  • Routine KSP processor messages moved to verbose logging (f238f49eb) by @njlynch.

Schema and engine

  • @parent accepts several compatible producer fields (c0032ed7f).
  • A temporary field-level shadow-execution hook for internal use (85ca12785) by @andimarek, and callers can fork isolated shadow execution state (c8e62db8e) by @amity177.
  • DataLoader subclasses can customize internal loader creation (18a660296) by @bhavanapallempati.
  • memoize accepts non-concurrent caches (a855babbb) by @gummybug.

New execution engine and @defer — early work in progress

Both are off by default and are not ready for production use.

Remote resolvers (experimental)


Bug Fixes

Execution and engine correctness

  • Allow sibling progress during composite list traversal (03e7b3cc5) by @skevy
  • A selective resolver that reads its own object while it is still loading no longer deadlocks (e59bd3b7b) by @jbellenger
  • Root field references resolve in the same object tree, and node resolvers that return them no longer hang (c57084bbf, 92b8a28c4) by @gummybug, @jbellenger
  • A selective node reference selected only by id / __typename now always resolves (e3b1c4165) by @alexanderuv
  • Respect parent-supplied values during selective resolution (d6f6d6a0a) by @alexanderuv
  • Preserve field argument values during rematerialization (c32ea44e1) by @alexanderuv
  • Bind operation variables in materialization plans (abb60562a) by @alexanderuv
  • Stop dropping ... on Type fragments when a resolver is re-run (3a55747e0) by @alexanderuv
  • Unwrap parent-managed values selected from materialized lists (76c5647aa) by @gummybug
  • Keep filtered field ASTs aligned with query plans (f5a17d851) by @gummybug
  • Attribute conditional exclusions to the types a selection reached (80f5b9c96) by @geovannefduarte
  • Preserve parent traversal in selective refills (4d081cb46) by @alexanderuv
  • Preserve tenant materialization errors (0b8b1c294) by @jbellenger
  • Misc selective field fixes (29d36102b) by @jbellenger
  • Fix selective node materialization interop (5218c1dd7) by @jbellenger
  • Fix materialization variable resolution (6d8e2aacb) by @jbellenger
  • With materialization on, an error from a selective node resolver is stored on the result instead of failing the request with InternalEngineException, matching the behavior without materialization (d5c8e840e) by @gummybug
  • Convert Classic resolver backing objects during materialization (3f1be62c5) by @gummybug
  • Follow named fragments when extracting checker variables (17823aa85) by @andimarek
  • Fail the batch instead of hanging when the schedule callback throws (d391f4799) by @vickeyyeh
  • Populate field variable definitions during bootstrap (5af014fa6) by @kristileka
  • Wire tenant module metadata into Modern resolver metadata (18fbb4157) by @vickeyyeh
  • Reuse immutable execution registry config snapshots (b324765ea) by @pclowes

Java tenant API

  • Preserve nested list shape in specialized Java GRT conversions (778e62a97) by @catacraciun
  • Make GlobalID equality and hashing structural (6945bffbb) by @catacraciun
  • Restore batch invocation attribution (02ffb4a98) by @catacraciun
  • Use resolver coordinates for VariablesProvider arguments (fa9b0163d) by @catacraciun
  • Allow resolvers to inherit generated resolver bases indirectly (85d2e3e15) by @catacraciun

Service and GraphiQL

  • GraphiQL loads again (45692c718) by @geovannefduarte — since 2.0.0 the bundled page imported a JavaScript file that was never shipped, so it stayed on "Loading…", and the Global ID plugin couldn't load. Babel is now pinned to 8.0.7 with an integrity check.

Schema, codegen and build plugins

  • Support enum values that are language keywords (475c976f1) by @alexanderuv
  • Preserve descriptions when converting schemas to GraphQL Java (f482e4ed4) by @pclowes
  • Preserve runtime schema metadata (93f45a5e2) by @pclowes
  • Make file source names platform-independent (4428ada91) by @geovannefduarte
  • Schema validation rules match module partition paths on Windows (ce689a694) by @geovannefduarte
  • Hide @bypassPolicyCheck from client-facing schema views (12f0c2b83) by @andimarek

Remote resolvers (experimental)

  • Support unary remote resolver callbacks across processes (5cd9fbfe8) by @cetinsahin
  • Preserve unary callback execution errors (019d02f10) by @cetinsahin
  • Carry nested object type identity over the wire (7fc43a5b0) by @cetinsahin

Performance Improvements

  • Prevent a single deeply nested polymorphic query from exhausting the heap while mat constructs its field-coverage KeyTree (5a5e7561a) by @gummybug
  • Avoid repeated copying when merging selection sets (ba73f44e6) by @gummybug
  • Avoid including multiple occurrences of duplicated selections in CollectedField (40cc0f49a) by @gummybug
  • Avoid traversing selection trees when hashing selectors (ac33dd577) by @gummybug
  • Parent completableDeferred directly to the request supervisor (9895e1bbf) by @viaduct-maintainers
  • Partition data loader custom cache-key matching, and make the partitioning unconditional (4d25b4d0d, 29731b19b, 81f0c0512) by @njlynch
  • New engine: compact parent demand, reuse materialization templates and selection forests, reduce cycle-check work, consume compliant resolver outputs directly, improve demand closure scaling, reduce selection merging and demand transformation overhead, remove hot-path invariant validation, and reuse normalized selections (56ac359eb, 5edbd7eab, 9e80ec47f, 3866ea733, 4cff74838, e38d04431, 0c11c65b3, 2c597944a, 5f0a222d8, 2d91c4273) by @rstata

Documentation

  • Document object GRT toBuilder() (8dfd66c91) by @gummybug
  • Document selective resolvers (b7b444b15) by @jbellenger
  • Document ctx.ref for root field references and node references (cbd046ea9, 3ab51ecc5, 63f2c732e) by @alexanderuv
  • Document directly returning GRTs from required selection sets (811fc83d2) by @gummybug
  • Document that from-field variables can't be @skip/@include conditions (2253d7790) by @alexanderuv
  • Add Java developer documentation: quickstart, foundations, setup and Star Wars tutorials, advanced guides, and service integration (91e8e5113, c482c47e7, 0b76c91e9, 73427e38a, 5f7d20d03) by @catacraciun
  • Update the supported Java, Kotlin and Gradle versions (#438) by @geovannefduarte
  • Update the roadmap for 3.0 (#442) by @geovannefduarte
  • Record the Java mapping domain deferral (3e4e85ef8) by @catacraciun
  • Clarify new engine names and source references (2dbebb5d7) by @viaduct-maintainers
  • Update AGENTS.md for bootstrapping (ed8e26cf8) by @kristileka
  • KDoc updates (9ce0849f7) by @andimarek
  • Add 2.0.0 release notes post (#406) by @geovannefduarte

Testing

  • Verify mixed Kotlin and Java Viaduct Gradle modules in one application topology (a31022dc0) by @catacraciun
  • Cover selective node, selective field and parent field interactions (50dcf6c54, dfaa3235b) by @alexanderuv
  • Add coroutine context contract (d2282c258) by @rstata
  • Share feature test harness through StandardViaduct (e716e6495) by @rstata
  • Support tenant provider variables in numbered resolver families (ec641cecb) by @rstata
  • Reset Resolution overhead baseline and feature coverage (a7d5b215d) by @rstata
  • Isolate large-schema round-trip tests (327f3b113) by @rstata
  • Use explicit values in mock field fixtures (7ef2f402f) by @rstata
  • Add a StandardViaduct engine comparison benchmark (560fe7a76) by @rstata
  • Derive reproducible schema seeds from content hashes and a seed variant (12e9aa865) by @kristileka
  • Generate the classdiff test schema from the arbitrary schema generator, with a pinned seed and case-only name dedupe (58a726186, c39ca87bb, 71981a6e9) by @kristileka, @jbellenger, @geovannefduarte
  • Layer Viaduct directive shapes onto the arbitrary schema generator (fc6d94726) by @kristileka
  • Replay generated resolver contract witnesses, list-deepening and mutations, and store property-test suites (bf53d82ac, 2a7833598, 3cba206ea) by @kristileka
  • Generate namespace types, root field references and a coordinate index in the arbitrary schema generator (dfc8e8e79, d15f297c0, c9e325b75) by @jbellenger
  • Add an isolated Java resolver test fixture (62fed5e31) by @catacraciun
  • Move GraphQL-independent arbitrary helpers to viaduct.arbitrary.common (019b12a34) by @kristileka
  • Measure maybeDelay with virtual time (d5f538c81) by @geovannefduarte
  • Bound the async fetch, not mockk setup (#422) by @geovannefduarte
  • Resolve TestKit fixture jars from a synced repo (#417) by @geovannefduarte
  • Stop testParallelMap failing under CI contention (3f93f0f94) by @geovannefduarte
  • Make mixed unions assertions order-independent (5c0c110ca) by @geovannefduarte
  • Compare runtime2 source paths with forward slashes (#434) by @geovannefduarte
  • Make runtime2 tests pass on Windows (#440) by @geovannefduarte
  • Register the scoping manifest task without the deprecated create API (46a828450) by @geovannefduarte
  • Stabilize type-checker coverage in CI (6c58a9e29) by @rstata
  • Observe fresh-thread failures with FutureTask, limit invalid-schema diagnostics to exceptions, and catch expected concurrent-write failures (f02ac2df9, c86d78496, 0fabde072) by @viaduct-maintainers

Refactoring

  • Move Java API implementation to core/javaapi (70423b54b) by @catacraciun
  • Share Kotlin and Java input type construction, required selection set dependencies, annotated operation preparation and node batch execution (fbb6f91bc, 9a8e6f522, 8b7f5cead, cc0e63d46) by @catacraciun
  • Introduce FullSchema for the complete engine schema while keeping scoped views as EngineSchema (872ac4897) by @gokhan-ozgozen
  • Rename the engine ViaductSchema to EngineSchema (b5444c026) by @gokhan-ozgozen
  • Build the RRS schema and executors as an instance-owned runtime (38af9473a) by @njlynch
  • Remove remote resolver proxy factory registry side effects (5bbe8838d) by @njlynch
  • Read materialized paths and coverage through the field reader, and make materialized field reads configurable (a675bd66f, 3676d91c4) by @alexanderuv
  • Share data fetcher result transformation (6225ba54f) by @alexanderuv
  • Collapse fetchObject/fetchObjectSerially into one serially-flagged method (43b4c7081) by @alexanderuv
  • Rename nodeRef call sites to ref (862a289d1) by @alexanderuv
  • Introduce ExecutionMode, CollectFields.Result and other CollectFields refactorings (012a2284e, fdc18c39f, 8258a42c1, bba534179) by @jbellenger
  • Introduce incremental variable definition plumbing (c002edb18) by @rstata
  • Add tenant-local fields to internal scoped schema construction (37a643da9) by @gummybug
  • Store FieldCompleter in Constants (79ddf0dc1) by @jbellenger
  • Preserve empty KeyTree branches (ed6f40bfa) by @jbellenger
  • Encapsulate schema metadata with typed holders, and add a programmatic schema builder with filtered copies and type roles (4b81f93fe, a788f0497, 457b15861, a798d09a7) by @rstata
  • Add neverHasArgs field metadata to the internal schema model (abd53f56c) by @rstata
  • Internalize ObjectEngineResult and checker result completion (93f54eeaa, 609a6a728) by @rstata
  • Separate resolver capability from dispatch policy (92a40bec0) by @viaduct-maintainers
  • Create shared/bootstrap for the execution-registry config model (c19ab6a6f) by @kristileka
  • Remove knownFragments from SelectionsParser (300e99eeb) by @kristileka
  • Give every execution registry configuration an explicit <tenantName, apiName> identity (9ffd1fd5c) by @kristileka
  • Move callers onto the file-based bootstrap path, then delete the second bootstrap lane (aa130706f, cf9919915, a73e3ac81) by @kristileka
  • Generalize the file-based classic tenant-module-config to all classic resolver directives (6b1eda4d0) by @kristileka
  • Rename the internal GRT accessor entry points (40041ea6a) by @geovannefduarte
  • Use getFooOrThrow in engine tests, tutorials and the starwars demoapp (4cce8bf9f) by @geovannefduarte
  • Move tenantFromLocation to ModulePartitionPaths (#426) by @geovannefduarte
  • Remove unused internal schema tenant-path helpers (2044ee871) by @geovannefduarte
  • Remove unused ViaductModernInstrumentation interface (62c1f63a6) by @andimarek
  • Separate VSchema and ViaductSchema generators (c716d9264) by @jbellenger
  • Add input and output value type aliases (bfbc03bb0) by @gokhan-ozgozen

Build System

  • Test on Java 25 alongside 17 and 21 (#437) by @geovannefduarte
  • Validate the Java API's binary compatibility (#436) by @geovannefduarte
  • Upgrade Viaduct OSS to Kotlin 2.3.21, KSP 2.3.7 and Gradle 9.1 (16653620b) by @gokhan-ozgozen
  • Prepare Gradle build and tests for Gradle 9 and Kotlin 2.x (00230ca63) by @gokhan-ozgozen
  • Run tests on the matrix JDK (#432) by @geovannefduarte
  • Apply static analysis to four unlinted modules (#429) by @geovannefduarte
  • Add the Java linting stack (f58d9d643) by @catacraciun
  • Normalize bytecode comparisons across Kotlin compiler versions (38a650bfd) by @freetheinterns
  • Replace subprojects{} scanning with BuildService self-registration and configuration sharing (302618eb8, bb9cc4193, f55a9f04d, ac3a74d75) by @gokhan-ozgozen
  • Run standalone checks after included builds (1b2aa7966) by @fireboy1919
  • Add Artifactory mirror to root plugin settings (0857f6bad) by @gokhan-ozgozen
  • Restore stock Gradle 9.1.0 wrapper jar and scripts (#435) by @geovannefduarte
  • Pin Spotless line endings to LF (#410) by @geovannefduarte
  • Delete the orphaned bom module (#423) by @geovannefduarte
  • Index Java and Kotlin golden resources to remove an unnecessary ClassGraph dependency (6d91d5eb5, 1fbae1553) by @pclowes
  • Check that the test-fixtures jar never bundles JUnit (5d73441bd) by @geovannefduarte
  • Use one djlint ignore list for every docs check (#441) by @geovannefduarte

Continuous Integration

  • Drop the Java 11 matrix leg (#431) by @geovannefduarte
  • Introduce a CodeArtifact mirror for build artifacts (#424) by @gokhan-ozgozen
  • Derive the artifact probe list from the build (#419) by @geovannefduarte
  • Validate every demo app's pinned Viaduct version (1e10d004e) by @geovannefduarte
  • Render BREAKING CHANGE text in release notes (#433) by @geovannefduarte
  • Label retry alerts with the failure cause (#427) by @geovannefduarte
  • Accept only Gradle task paths in CI alerts (#428) by @geovannefduarte
  • Retry a failed nightly once before alerting (#425) by @geovannefduarte
  • Retry a failed run once before alerting (#415) by @geovannefduarte
  • Run coverage only on schedule and dispatch (#418) by @geovannefduarte
  • Run Copybara on Java 25 (#416) by @geovannefduarte
  • Report every matrix leg, key concurrency per entry point (#413) by @geovannefduarte
  • Stop discarding matrix and task failure evidence (#411) by @geovannefduarte
  • Stop discarding Windows nightly failure evidence (#409) by @geovannefduarte
  • Make demoappsStandaloneTest work on Windows (#408) by @geovannefduarte
  • Cache demo app Gradle distributions to stop repeat downloads (#407) by @geovannefduarte
  • Never cancel main CI runs to protect the shared Gradle cache (#402) by @geovannefduarte

Chores

  • Mark the materialized field reader as for Airbnb use only (5bce92343) by @alexanderuv
  • Add a comment documenting materialization behavior (c52294b94) by @gummybug
  • Fail module config assembly on selections of forbidden-directive fields, behind an opt-in CLI flag (c72b78625) by @viaduct-maintainers
  • Pin the seed used for some arbitrary schema generations (c39ca87bb) by @jbellenger
  • Dumpable field references (a9eca264c) by @jbellenger
  • Fix nullable reference field generation (b94df0308) by @jbellenger
  • Classify long-running central-schema reflection tests correctly (00c3638b8) by @pclowes