M3-04 Velocity Credential Agent Integration (Issuance)¶
Milestone: M3 — Issuing Functionality SOW Reference: FR1, INT1 Requirement Clarity: ✅ Clear Dev Status: 🟢 Prototyped in POC — verified live against Velocity staging
Overview¶
Integration to the VCL-supplied Velocity Credential Agent so the platform can actually issue EmploymentPastV1.1 credentials, rather than just modelling them locally.
Backend Tasks¶
- Confirm
CihApiService/CihApiTypes(app/backend/src/shared/services/cih/cih-api.service.ts) covers all required Credential Agent operations (issue, status check, error handling, retry) - Confirm tenant/key setup for each organisation (
admin/services/velocity-tenant.service.ts) is solid — this underlies every credential issued - Verify the co-located AWS infrastructure requirement (Appendix 6 — Credential Agent co-located with the platform) is satisfied once the AWS hosting decision (see M4-01) is made
Frontend Tasks¶
- N/A — this is a backend integration task.
Dependencies¶
- M2-02 Velocity Registrar — organisation must exist on the Network before it can issue.
- Appendix 5 assumptions A3/A4/A5 (VNF API/service availability).
Acceptance Criteria¶
- Credential is successfully issued via Velocity Credential Agent (per SOW Appendix 3, FR1 acceptance criteria; also INT1 "successful credential issuance, status retrieval, error handling, retry handling verified")
Existing Reference Material¶
docs/requirements/tasks/POC/13-verified-integration-log.md(kept in place — records actual verified Velocity staging calls from 2026-04-15)docs/requirements/tasks/POC/01-setup-configuration.md(kept in place — VNF SDK setup)
Blockers & Risks¶
None currently — this is the most verified integration in the platform.
Update 2026-09-02 — how our approach to Velocity's data requirements changed¶
Where we started. The credential issuance form and the underlying template (what actually gets sent to Velocity) were originally built from Velocity's own written documentation of "mandatory fields" for an EmploymentPastV1.1 credential — a plain-language field list, not the machine-checkable definition Velocity's own systems validate against. That's a reasonable starting point (it's what any integration doc gives you first), but it only tells you which fields are required, not the exact shape, format, or constraints each one has to satisfy.
What that cost us. Every one of the following was only discovered by issuing a real credential against Velocity's staging system and reading the rejection it sent back — none of these were things the written field list would have told us in advance:
- employmentType has to be sent as an array, even for one selection — a plain string is rejected outright.
- addressRegion must be a real ISO 3166-2 subdivision code (e.g. GB-LND), capped at 6 characters — a freely-typed region name is rejected.
- Velocity only has one free-text field on this credential (description) — our form was originally collecting two ("Department" and "Role description") assuming both had a home on the credential; they had to be combined into one before sending.
- The employment location (place) and the employer's own registered address (legalEmployer.place) are two separate blocks on the credential, not one — treating them as the same thing was silently dropping one.
- Velocity's schema rejects any field it doesn't recognise (additionalProperties: false) — anything we sent that wasn't on their list didn't just get ignored, it failed the whole submission.
Each of these surfaced as a live rejection during testing, on a case-by-case basis, over several rounds — not as a single upfront gap list. That's the "intermittent, hard to explain" pattern behind more than one of the bugs fixed this project.
Where we are now. For every Velocity-facing piece of data — credential content, and later the disclosure/verification request shape when that work starts — we now fetch Velocity's actual current machine-readable schema directly from their own published source (stagingregistrar.velocitynetwork.foundation/schemas/..., their live CIH API documentation) and build against that, not against a written summary of it. This is slower up front but has caught every one of the issues above at build time instead of in front of a live rejection, and it's the only way to know Velocity hasn't quietly changed something — which they have: a field their depot schema exposed as recently as July 2026 has since been removed from the version we're integrated against today (see M3-06's update on webhook support). A written doc doesn't tell you when the vendor's own platform has moved out from under it; only checking the live schema does.
Standing practice going forward: before building against any new Velocity endpoint or credential type, pull the live schema first and treat it as the only source of truth — the written documentation is a starting orientation, not a spec.