Skip to content

FEAT-024 Phase 4D Report and Export Compatibility

Delivery boundary

This slice proves that existing exports retain source-record semantics. It adds no production adapter: the current export writers do not consume any materialized statistics family. This implements the disposition in the Phase 0 catalogue, consumer inventory and D7. It does not assert that all Phase 5 statistics consumers have migrated or that export permissions have been verified. The separate authorization gap below prevents that latter acceptance claim.

Inspection baseline: 0583018ce507acf2592083bfc5ffc928bb262714. Paths below are repository-relative.

Current report and export inventory

Surface Actual input and output FEAT-024 disposition
DataExportController.CreateDataExportJob Request options stored as a DataExportJob Operational job creation; no family adapter
DataExportController.GetDataExport Source Study cursor plus its all/included count, streamed through StudyDataService.GetDataExport Keep authoritative paging count; no family adapter
StudyDataService.GetBibliographicDto Source all/included studies and search names; one bibliographic DTO per study Source-row helper; no production caller found at this baseline, no statistical adapter
BibliographicDataFormatRowWriter Bibliographic fields and search identity of each source study Preserve row values, quoting, and provenance
LongScreeningDataFormatRowWriter, WideScreeningDataFormatRowWriter Individual screening decisions, dates, identities and the study's screening status These are screening records, not project/reviewer screening totals
LongDataFormatRowWriter, WideDataFormatRowWriter Individual annotation answers, questions, sessions, reconciliation and configured blinding Preserve existing row schemas; no aggregate answer-count substitution
OutcomeDataFormatRowWriter Outcome measurements, cohort/experiment/time-point relationships and annotations Preserve existing outcome export; no aggregate family dependency
CsvDataExportWriter, OptimizedDataExportProgressReporter Processed source-study count, errors and job completion Operational progress, excluded from statistics history and projection freshness
BulkPdfUploadReportWriter, BulkPdfUploadController.GetBulkPdfUploadReport Stored CSV of uploaded-file matching outcomes (file_path, normalized_path, outcome, study_id, study_title, detail) Import diagnostics artifact, no family adapter
RobDbProgressReporter Risk-of-bias job progress and messages Operational progress, no family adapter

The export controller selects paged or ordinary source cursors using the 25,000-study threshold and requested format. Included-only export uses the repository's included-study filter. Neither that count nor progress is the imported-reference population. SystematicSearch.NumberOfStudies is the sum of reference-file import metadata and can remain 17 when only two source studies survive. Replacing the cursor count with that total would misrepresent job progress; replacing the study cursor with aggregate rows would lose the exported records.

Approved statistics surfaces still requiring consumer disposition

These are statistics consumers, not existing report file writers. Their adapters belong to their respective family/consumer slices and must preserve permissions and coherent revision selection.

Surface Approved families / derived values Required disposition
ProjectController.GetFullStats, ReviewController.GetFullStats Project screening, stage annotation, membership screening and membership-stage annotation Migrate the approved complete response only when all selected families are supported; otherwise coherent authoritative response
ReviewController.GetReviewerStatsForProject, GetReviewerStatsForStage Reviewer screening and reviewer annotation Preserve acting-reviewer scope and stage/project policy; no export writer change
AnnotationQuestionDto.AnsweredAnnotationCount on project details / pushes Question-answer study and annotation counts Question-family adapter, including current versus retained historical question identity
SearchController.GetProjectSearches, SearchResolver and client studyCount sum Imported reference-file population Search-family adapter; never substitute surviving-study or export cursor counts
Overview/stage/screening/review-completed views and design/assign stores The above API values, ratios and availability summaries Phase 5 migration inventory; retain existing visible values until the complete required response is supported
Phase 4C derived summary composer Screening percentage, verification, stage totals and insufficiently completed candidate sessions Compose one authorized bundle or one resolved checkpoint; it creates no CSV/report endpoint

No cross-study statistics report/export endpoint was found at this baseline. Any future report that embeds aggregate statistics must select one authorized revision/checkpoint and retain its provenance. A catalogue entry or generic family decoder alone does not establish an existing report consumer or justify rewriting a row writer. Historical annotation summaries that require retained stage configuration remain a separate dependency of 4C, not a reason to change exports.

Compatibility evidence

SyRF.ProjectManagement.Core.Tests/DataExport/StudyDataServiceTests.cs exercises the real StudyDataService, row writers and CsvHelper serialization with 17 imported reference records and two surviving source studies. Bibliographic, long/wide screening and long annotation fixtures assert surviving study IDs, search name, escaped title round-trip, individual decisions/answers, and progress 1, 2; job size remains 2, never 17. Repositories supply fixture data at the service boundary; no statistics reader or synthetic projection adapter is mocked.

The existing DataExport suite covers wide annotation and outcome row/header consistency, comments, blinding and pipeline errors. This slice does not claim a snapshot guarantee for the legacy export cursor, historical export support, controller authorization coverage, or a database import/removal integration test. Search-family integration coverage owns import population calculation; this fixture verifies the consumer's different source-record contract.

Separate permission correction required

The catalogue's generic “per-endpoint export policies” statement is not supported by this baseline. Program.cs installs an authenticated-user MVC filter, but DataExportController has no explicit project policy; job creation trusts the request project and download loads a job by ID without binding it to the route project. This existing authorization gap needs a separate bounded security fix and endpoint tests before claiming report/export permission acceptance. It is independent of materialized family implementation and must not be hidden by a no-adapter disposition.