Repository navigation
Ed-Fi API Publisher Release Notes - Version 1.4.0
Overview
Version 1.4.0 of the Ed-Fi API Publisher adds support for Ed-Fi API v8, faster reads from large sources through cursor paging, resumable runs, and exit codes that report whether a run lost documents. It moves the publisher to .NET 10 and includes reliability, memory and bug fixes. This release contains breaking changes; see Compatibility before upgrading.
New Features
- Publishing from and to Ed-Fi API v8, with Ed-Fi API v8 or the ODS/API on the other side. The publisher now reads each API's Discovery document to find where it serves its resources and its token endpoint. New optional connection settings:
authUrl,dataManagementUrlSegment,changeQueriesUrlSegment - Partitioned cursor paging for ODS/API 7.3 and later sources, on by default, with
disableCursorPagingandcursorPagingPartitionCountoptions. An Ed-Fi API v8.0 source has no partitions and is read with offset paging - Resuming a run that failed partway through, for sources read with cursor paging, with
resumeLastRunandrunStatePathoptions - Deletes and key changes on a full publish, with the
processDeletesAndKeyChangesOnFullPublishoption - Run summary table and specific exit codes, with the
toleratedItemErrorCountoption 429 Too Many Requestsresponses from the source are retried honoringRetry-After, and concurrent source requests can be capped, withtooManyRequestsRetryAttemptsandmaxConcurrentSourceRequestsoptions
Improvements
- Lower memory growth on long runs through bounded processing buffers and streamed page reads, with the
processingBlockBoundedCapacityoption - Bearer token refresh is retried before the token expires, and a
401response triggers a new token and a replay of the request
Bug Fixes
- Fixed a run that lost documents exiting with code 0, except for writes that time out on every retry (see Known Issues)
- Fixed an expired bearer token silently voiding the rest of a run
- Fixed key changes published to Ed-Fi API v8 failing with
400 - Fixed publishing from a Data Standard 5.x source failing with
KeyNotFoundExceptionusing the shipped configuration - Fixed an exception when
lastChangeVersionProcessedis set andincludeOnlycontains a single resource - Fixed a non-concurrent collection error with a remediation script and POST parallelism greater than 1
- A source document with an invalid
idis reported as a controlled error instead of an unhandled exception
Security
- Adopted the 2026-10-15 .NET security release (.NET 10.0.13) in the packages and the Docker base image
- Removed vulnerable packages from the Docker runtime images
Documentation
- Documented the new options, exit codes, Ed-Fi API v8 setup and known issues
Engineering Updates
- Runtime: Solution, Docker images and GitHub Actions workflows moved to .NET 10
- Dependency Management: Central Package Management (
Directory.Packages.props), monthly Dependabot schedule, and pull request checks that build dependency changes - Repository: Line endings normalized to LF, GitHub Actions pins updated, code scanning alerts triaged
- Testing: Scripted regression harness under
eng/regression, run against ODS/API and Ed-Fi API v8; unit tests moved to NUnit 5
Changes in This Release
| Commit | Author | Pull Request | Description |
|---|---|---|---|
| 99a1712 | brian-pazos | #106 | Fix exception when exactly one resource is processed for key changes |
| 2b3523f | Stephen Fuqua | #139 | Product Requirements Document |
| c5d4bbd | Ana Gutierrez | #140 | Make unremediated request tracking thread-safe |
| 569be25 | Ana Gutierrez | #141 | Add processDeletesAndKeyChangesOnFullPublish option |
| 09f8cef | Ana Gutierrez | #142 | Upgrade solution to .NET 10 |
| cc48e31 | Ana Gutierrez | #145 | Recover from an expired bearer token mid-run |
| 791ac2f | Ana Gutierrez | #157 | Remove unused package reference |
| dc503ee | adiaz-msdf | #143 | Reduce memory growth |
| a64dea5 | adiaz-msdf | #152 | Reduce memory growth: bounded retry pass and streamed page reads |
| 9a3b1e9 | adiaz-msdf | #156 | Handle an invalid or missing source item id as a controlled error |
| fd1318a | adiaz-msdf | #163 | Extract the page-request strategy from the source read handler |
| 919a00c | Steven Arnold | #164 | Update GitHub Actions pins |
| 78236a6 | Ana Gutierrez | #168 | Use fuzzy version pins for openssl and icu in Dockerfiles |
| 9de693f | Ana Gutierrez | #165 | Report the run outcome through the exit code |
| 63e2583 | adiaz-msdf | #166 | Cursor paging |
| de74066 | Ana Gutierrez | #167 | Honor 429 Retry-After on source reads and cap concurrent source requests |
| dbd3647 | Ana Gutierrez | #173 | Resumable cursor-paging runs |
| 14d6276 | adiaz-msdf | #178 | Validate cursor-paging parity |
| 1f6ba8b | Ana Gutierrez | #181 | Move the Dependabot NuGet schedule to monthly |
| f816e4a | Ana Gutierrez | #174 | Take the API's served paths from its Discovery document |
| 4f99797 | Ana Gutierrez | #186 | Centralise package versions with Directory.Packages.props |
| 43499e4 | Ana Gutierrez | #188 | Close the gaps left by the package-version conversion |
| f6deb50 | Copilot | #180 | Remove vulnerable Alpine unzip package from runtime images |
| 518971c | Ana Gutierrez | #190 | Build the files that decide the build in pull request checks |
| c42275f | Ana Gutierrez | #191 | Install gettext-envsubst instead of gettext in the images |
| 37136f5 | Ana Gutierrez | #179 | Take the token endpoint from the API's Discovery document |
| 0176103 | adiaz-msdf | #197 | Force LF line endings |
| a9616f1 | Ana Gutierrez | #199 | Keep id in the key-change PUT body so Ed-Fi API v8 accepts it |
| dabdd14 | Ana Gutierrez | #200 | Upgrade NUnit from 4.6.1 to 5.0.0 |
| 9d189dc | adiaz-msdf | #192 | Add the scripted regression harness under eng/regression |
| 1ab0c63 | Ana Gutierrez | #198 | Run the regression harness against Ed-Fi API v8 in all three directions |
| 656c331 | Ana Gutierrez | #201 | Update the README for v1.4 |
| 3d4de93 | Ana Gutierrez | #203 | Adopt the 2026-10-15 .NET security release in packages and the Docker base image |
| 947c914 | Steven Arnold | #193 | Add a version-specific PRD for v1.4 |
| dependabot[bot] | #144, #149, #154, #159, #160, #161, #162, #171, #189, #194, #195 | Dependency updates |
Supported Versions
Version 1.4.0 was tested with the Ed-Fi versions supported for the 2026-2027 school year, Ed-Fi ODS/API 7.3 and Ed-Fi API v8.0, on Data Standard 5.2 and 6.1, in all four directions:
- ODS/API to ODS/API
- ODS/API to Ed-Fi API v8
- Ed-Fi API v8 to Ed-Fi API v8
- Ed-Fi API v8 to ODS/API
Earlier ODS/API versions are out of support (see Ed-Fi Technology Suite Supported Versions). Ed-Fi API v8.0 has two behaviors to plan for, described under Known Issues: its default rate limit, and the lack of snapshot isolation when it is the source.
Compatibility
This release contains breaking changes. Review each item before upgrading.
- .NET 10 required. The publisher now runs on .NET 10. Install the .NET 10 runtime before upgrading a binary deployment.
- Exit codes changed. A run that lost documents no longer exits with code 0, and failures no longer share a single code of
-1(255on Linux and macOS). The new codes are 0 (success), 1 (documents rejected beyond the tolerance), 2 (run incomplete), 3 (authentication failure) and 4 (invalid configuration). Automation that tests for255or-1must be updated. Best-effort behavior is available with--toleratedItemErrorCount=-1. - Ed-Fi API v8 behind a rewriting proxy. The publisher now asks Ed-Fi API v8 for
datadirectly. A proxy that only routes/data/v3/*will answer404to every request. Remove the rewrite, or set--sourceDataManagementUrlSegment=data/v3or--targetDataManagementUrlSegment=data/v3to keep the previous address. An ODS/API is unaffected. - Token endpoint taken from Discovery. A connection without
authUrlnow requests its token from theoauthURL the API declares, instead ofoauth/tokenunder the connection URL. For an API reached at the address its callers use, nothing changes. If the API declares an address its callers cannot reach, setauthUrlon the connection. A tenant-qualified API must be addressed with the tenant in its connection URL.
Other behavior changes:
- Cursor paging is on by default against ODS/API 7.3 and later sources.
--disableCursorPaging=truerestores offset paging. - Processing buffers are bounded by default.
--processingBlockBoundedCapacity=-1restores the previous behavior. - A source read rejected with
429is now waited out and retried, so a run against a busy source can take longer.--tooManyRequestsRetryAttempts=0reports the rejection immediately. - A run that can no longer obtain a bearer token ends with exit code 3 instead of continuing.
- Every run that publishes writes a run state file, in the working directory unless
--runStatePathis set. It is removed when a run finishes without losing a document. - An
authUrlstated on a connection is used exactly as written; a trailing slash is no longer appended. - The shipped
authorizationFailureHandlingdefault uses/ed-fi/contacts(Data Standard 5.x and later) instead of/ed-fi/parents.
Installation and Upgrade
From Version 1.3.0
- Install the .NET 10 runtime.
- Review the Compatibility section, in particular the exit codes and any proxy in front of Ed-Fi API v8.
- For containerized runs that should be resumable, mount a volume and point
--runStatePathat it.
New Installations
Follow the standard installation procedures as documented in the Ed-Fi API Publisher documentation.
Known Issues
Ed-Fi API v8 has setup prerequisites as a target (see Considerations for API Hosts). Ed-Fi API v8.0 rejects requests above its default rate limit (turn on --enableRateLimit when publishing into it), does not provide snapshot isolation when it is the source (publish from it while it is not being changed), a few data values differ between the two APIs, and writes that time out on every retry are not reported as failed in this release. See Known Issues Details.
Support
For support with the API Publisher, please use Ed-Fi Community Hub to open a support case and/or feature request.