PMO read surface: scoped read keys, visit and form-instance listings, edc:VisitDate designation (ADR-0017) - #118
Merged
Merged
Conversation
…:VisitDate designation (ADR-0017)
E6-05 and E6-12 now describe both API-key classes (write-only RTSM intake, read-only PMO listings) and cite integration.test.ts and visit-date.test.ts, so the validation pack carries evidence for the ADR-0017 surface.
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.
What
A read-only integration surface so a DM PMO portal (dmops-core is the concrete consumer) can compute query turnaround, visit-to-entry lag, and access rosters from edc-core on a schedule. Design and boundaries are in ADR-0017 (merged as the first commit here). Migration 0025.
Until now the only machine credential was the ADR-0010 RTSM key, which reaches one intake POST and by design can never read. Two facts a metrics pipeline needs also had no API field at all: the date a visit happened, and the first save on a form instance.
Key classes that cannot cross
api_keysgains ascopecolumn (rtsm|pmo_read, defaultrtsmso existing keys are untouched). PMO keys mint with anedcpmo_prefix against a per-studysvc-pmo-<studyId>service account holding the newpmo_agentrole, which carriesintegration.readand nothing else. Route guards pin scope: the RTSM intake accepts onlyrtsmkeys, the read listings onlypmo_readkeys. A leaked read key cannot post assignments, and the ADR-0010 property that the RTSM key can never read data holds verbatim. Mint, sha256 storage, revocation, and audit events reuse the ADR-0010 machinery. Key management is API-first under/studies/:id/pmo/keys(study.manage); no UI in this PR.The listings
GET /studies/:id/visits: one row per event instance withvisitDateresolved from the build-designated item under that instance's own pinned metadata version. No designated value isnull. A stored value that is not ISOyyyy-MM-ddfails the request with a 422 naming subject, event, item, and observed value, because interactive capture does not enforce castability on entry and the boundary should validate rather than guess.GET /studies/:id/form-instances: status plusfirstEnteredAt, the earliestitem_value_versions.created_at(machine writes included).subjects,queries, andmembersadditionally accept a PMO key. Query message bodies are omitted on the key path since a thread can quote any captured value; authors and timestamps stay, which is what a response-time metric needs.svc-*account, not justsvc-rtsm-*.Visit date lives in the build
edc:VisitDate="Yes"onItemDef, followingedc:Blindedandedc:CodingDictionary. Which item carries the visit date is CRF design, so it versions with the build and an amendment that removes the item fails at publish instead of leaving a stale mapping behind. Publish validation hard-fails a designation that is notDataType="date", one that is blinded, or an event whose forms reach two designated items.Decision to review: the visit date is the single captured value that crosses the key boundary, and only through a designation the build itself declares. The rejected alternatives (a
visit_datecolumn, anrtsm_configs-style table, widening the RTSM key, a generic item export) are recorded in the ADR.Docs and traceability
New guide page
guide/pmo-integration, a cross-link from the RTSM guide, changelog under Unreleased. Traceability rows E6-05 and E6-12 now describe both key classes and citeintegration.test.tsandvisit-date.test.ts, so the validation pack carries evidence for this surface. No new regulatory citations; the two rows are wording changes against citations that already existed.Verification
pnpm lintandpnpm typecheckclean.packages/odm: 126 passed, including the six newvisit-date.test.tscases (parse, XML/JSON round-trip, the three publish-validation failures, edit plus build diff).apps/api/src/routes/integration.test.ts(8 cases: minting, visits, form instances, session parity, the read listings on a key, scope pinning both directions, cross-study and anonymous rejection, the non-ISO 422) needs Postgres and was skipped locally because Docker was not running. CI provides the database, so these run on this PR; please check that job reports them as passed rather than skipped before merging.