Repository navigation
fix: enforce the release policy end to end and serialise overseer decisions - #39
Merged
Merged
Conversation
…isions Disclosure control - projects.yaml sets a per-project min_cell_size floor (5). A request may ask for a larger k, never a smaller one; the adapters and the server disclosure check both apply the floor. - A variable observed in fewer than k rows releases nothing. - Regression inputs with missing values are rejected on every backend instead of being fitted on a silent subset. The SQL adapter counts complete rows in the same aggregate query. - Every Newton-Raphson round goes through one release helper (shape, finiteness, n >= max(k, p + 2)) and is audited whether it is accepted or rejected, on the direct API path and in the FLARE executor. - The dominance rule also covers per-variable counts, Gram sample counts and every released round, and every released round needs two sites. - Logistic fits take sites_reported, n and n_per_site from the sites that contributed an accepted round, on both the API and FLARE paths. - fed_stats results need observed values for every requested variable. - Released results name each suppressed location without the count that caused the suppression; result.json keeps the detail for overseers. Release lifecycle - One re-entrant lock in server/overseer_queue.py covers disclosure check -> record and every approve/reject decision. Queue and released.json writes are atomic. - A new run of a spec replaces the earlier run's release or queue entry, and a rejected result leaves nothing released. - Run status reports overseer decisions (APPROVED / REJECTED, status "rejected"), including a decision that lands between record and the run update. The UI reloads the open run after a decision. - The FLARE FedAvg controller no longer records its zero start vector as a fit when no training round completes. - Two processes writing one SERVER_OUT stay unsupported; the docs say so. Operations and CI - scripts/limit_server_jobs.py makes a provisioned server kit run one job at a time (max_jobs 1, full copy of resources.json.default); provision.sh and local_federation.sh call it. - CI adds a merge-conflict-marker check and a frontend job (Node 24: npm ci, npm test, npm run build). Frontend dependencies are pinned and the UI proxy defaults to the API on :8500. Tests: 149 fast and 4 FLARE simulator tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes gaps where aggregates could leave the server without passing the full release policy, and makes the overseer release lifecycle consistent: one lock, atomic writes, and run status that follows overseer decisions.
Changes
Disclosure control
projects.yamlsets a per-projectmin_cell_sizefloor of 5. Requests may raise k but never lower it; the adapters andserver/disclosure_check.pyboth apply the floor.safe_output.release_irls_step, which checks shape, finiteness andn >= max(k, p + 2). Each round is audited whether accepted or rejected.fed_statsresults need observed values for every requested variable.result.jsonkeeps the full detail for overseers.Release lifecycle
overseer_queue.RELEASE_LOCKis re-entrant. It covers check → record and every approve/reject.released.jsonwrites are atomic.released.jsonexists only while the latest run is OK or approved.Operations and CI
scripts/limit_server_jobs.pymakes a provisioned server kit run one job at a time (max_jobs: 1). It writes a full copy ofresources.json.default, which NVFlare uses in place of the default.provision.shandlocal_federation.shcall it.npm ci,npm test,npm run build).Behaviour changes to note
n, which gave a wrong fit with no warning. The pandas-based backends produced NaN statistics.sites_reported,nandn_per_siteonly from sites that contributed an accepted round, on both the API and FLARE paths. A site that joined and then failed is now reported as missing.RunStatusgains statusrejectedand decisionsAPPROVED/REJECTED.docs/schemas/has been regenerated.:8080to:8500, the documented API port.frontend/.env.examplematches.Verification
python -m pytest -q -m "not slow"python -m pytest -q -m slow(FLARE simulator: allele_freq, straggler, FedAvg linreg, Newton-Raphson logreg)npm test,npm run buildmax_jobs: 1, rest of the config preserved, NVFlare selects the overridegit diff --check, conflict-marker grep, CI YAML parse, shell syntaxAn independent review of the final tree found nothing new to fix and reran both Python suites. Not run on this branch: the Docker stack, or a live
local_federation.shjob against a kit limited tomax_jobs: 1.Accepted limitations
/overseer,/overseer/{hash}/approve|reject,/audit) are open, and/overseerand/auditshow exact pre-suppression counts. Authentication and authorization for these endpoints are mandatory before any shared deployment.SERVER_OUT. The lock is in-process only. The API, a FLARE server and the overseer CLI writing the same directory at the same time are not coordinated.min/maxare released as exact values.n, including sites that later miss rounds.max_jobs: 4) until they are re-provisioned orscripts/limit_server_jobs.pyis run on them. Deployed kits have not been inspected.