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.