The Powers We Deliberately Did Not Take
A tool that governs a research study's schema could be given a great deal of authority. It could hold an API token and read the project directly. It could reconcile your model to the latest upload automatically. It could push corrected instruments back into REDCap. Each of those would demo well.
The Powers We Deliberately Did Not Take
A tool that governs a research study's schema could be given a great deal of authority. It could hold an API token and read the project directly. It could reconcile your model to the latest upload automatically. It could push corrected instruments back into REDCap. Each of those would demo well.
We built the REDCap integration to have none of them, and the reasons are worth stating plainly, because in governance the interesting question is never what a system can do — it is what it is structurally unable to do.
An import can add. It cannot overwrite.
When you import a data dictionary, the import adds what is new and enriches what it recognizes. Instruments already present in the governed model are skipped, and the response says how many were skipped alongside how many were added, how many fields were added, and how many nodes were enriched. Nothing you previously reviewed is rewritten to match the file.
That asymmetry is deliberate. An import is a machine act, and a machine act must not be able to change what your organization has agreed things mean. If import converged the model onto the latest upload, then your governance would be, in practice, whatever the last person happened to download — and the most recent CSV would always win an argument it was never party to.
The one thing an import does refresh is vendor bookkeeping: the metadata that records what the estate currently looks like. That is not governed meaning. The distinction between the two is the line the whole design is drawn along.
Read-only is a role, not a promise
Audit, re-audit, generate, status, history, and badge all run at viewer level and write no governed meaning. Import requires an administrator. Those are enforced per project, on every call, not documented as etiquette.
Even the bookkeeping is opt-in. The audit verb does not record its run into the history unless you
ask it to — recordHistory defaults to false, so a check stays a check. The one exception is
re-audit, which always records: it exists to answer "the model changed; does the last-known estate
still conform?", and that question is only ever asked after a human made a governance decision. A
run that follows a decision is exactly what a trail should contain.
The practical consequence is that nobody audits their way into a model change by accident, and handing an analyst — or an AI agent — the ability to check the estate costs you nothing, because checking cannot alter anything.
Every loss is declared
Any translation between representations loses something. A tool that never mentions it is not lossless; it is quiet. We report success and lossiness as separate channels: success means it ran, and the lossiness list says what was approximated or left behind.
For REDCap, concretely. descriptive rows are display text rather than data, so they are skipped —
and counted, so the number is a visible fact rather than a mystery. If a dictionary contains the
same variable name twice, the later row is ignored and a record says so by name. The snapshot that
makes re-audit possible has a size cap of roughly one and a half megabytes encoded; above it, the
import reports that no snapshot was stored, with a lossiness record, instead of silently truncating
your estate. Fresh-artifact audits still work in that case — you simply cannot re-audit against a
snapshot that was honestly refused. And when generating a dictionary back out, a governed reference
between instruments has no column in the REDCap format, so it lands as plain text rather than as
something invented to fill the slot.
None of these are edge cases we were forced to admit. They are the output of a design rule: the system is allowed to approximate, and it is not allowed to approximate quietly.
Drift arrives as evidence
A drift claim you cannot act on is gossip. Every finding carries a section — coverage, drift, or
conformance — a severity, a stable machine-readable code, the instrument or field it names, and the
detail that makes it checkable. field-type-drift states the governed type and the artifact type.
enum-narrowed and enum-widened distinguish a value set that lost options from one that gained
them. duplicate-choice-codes names the field whose exports will be ambiguous. phi-fields lists
the identifier fields per instrument.
Each audited artifact is fingerprinted, so a finding is bound to a specific version of a specific file rather than to "the dictionary." Recorded runs accumulate with the trigger that caused them, so a build gate, a person, and a post-decision re-audit are distinguishable in the trail. Even the badge participates: it renders gray, not green, when no run has been recorded, because absence of evidence is not a passing grade.
Review, then deploy — in both directions
Put together, the loop mirrors the discipline software teams already trust, and it runs both ways.
Inbound, a proposed dictionary is audited before it ships. Teams that keep their dictionary in version control can wire this into continuous integration on the machine-to-machine surface, where an error count above zero fails the build and the human-readable report lands in the review. People then deliberate over named findings. If the decision is to change governed meaning, someone with the authority makes that change explicitly, and a re-audit confirms where the estate now stands.
Outbound, the generated data dictionary is a proposal, not a deployment. We produce the CSV; a human reviews it and uploads it to REDCap. There is no path by which CoreModels modifies your project, because there is no connection to your project — the only input is the file you exported yourself, and your API token never reaches us. A live connection is a declared-but-deferred capability, which is a more useful thing to tell you than a vague reassurance.
The short version
The machine parses, compares, reports, and remembers. It does not decide what your study means, and it cannot. That constraint is not a limitation we are apologizing for — it is the product.
The verbs and the guarantees behind each of them are documented in the REDCap quickstart in the CoreModels integration docs.