Review 886 on #517, both findings. Finding 1 - getrawdata validates three inputs, and the mock only had the third. getrawdata.sas aborts, in this order and all with mac=&_program..sas, before it streams anything: table shape -> "Invalid table" filter integer -> "Invalid filter" type list -> "Invalid type" The mock now reproduces all three, from the rules of the macros the service calls: %mpe_validatecol(...,LIBDS,...) strips a trailing -FC and applies %mp_validatecol's /^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i, and %mp_validatecol(...,ISINT,...) is input(??best32.) with mod 1 = 0, so 7.0 and 1e3 are integers and abc and 1.5 are not. Each answer was recorded from the synthetic estate first: {table:'NOT_A_LIBDS'} -> Invalid table {filter:'abc'} -> Invalid filter no table at all -> Invalid table (was a ReferenceError before) {type:'FOOBAR',table:'NOT_A_LIBDS',filter:'abc'} -> Invalid table Finding 2 - the tests waited 100ms for a fire-and-forget write. The cause was the writers, not the tests: getddl, getrawdata and exportdb used the async fs.writeFile for the headers file, while %mfs_httpheader (fopen/fput/fclose) and dcMockUtils.mpStreamfile are synchronous. Those three now use fs.writeFileSync, so the file is complete when the program returns; the waits are gone, the positive assertions read the file directly, and the absence assertions mean "never written" rather than "not written yet". No polling remains in the file. Also: mock-settings.test.js renamed the control library to DC7QATEST to prove getrawdata follows the settings file - nine characters, which the estate rejects as "Invalid table" for a LIBREF. The fixture is now DC7QATST. That was a test defect the new validation exposed, not a product one. Tests: download-headers.test.js is 11 tests, and the two new ones were run against the old code first - dropping either check fails its own test. Whole mock suite: 144 tests, 144 pass. parity/check.js unchanged.