Learner Records — Service Reference
Module: backends/learner-records · REST: 8086 (real business API) · gRPC: 50055,
mTLS required · Schema: learner (isolated from catalog because this data is regulated PII)
See Master Data Registry §4/§6 for why this is a separate service (independent encryption master key, independent retention clock) rather than folded into Program Catalog.
LearnerController exposes a real /api/v1/learners/* REST API on port 8086, for
direct/future student-management-system integration. Core Engine’s issuance flow still calls the
gRPC service directly, not this REST API — both transports share the same
LearnerRecordsService business-logic class so they can’t diverge.
Purpose
Learner Records holds learner identity, national identifiers (USI, NSN, …), enrolments, and
outcomes — the facts a credential ultimately certifies. Smallest master-data service by RPC
surface, most sensitive by data classification: learner.legal_name and learner.dob are
encrypted at rest, and learner_identifier.identifier_value_ciphertext uses its own AES-256-GCM
master key (LEARNER_REGISTRY_KMS_MASTER_KEY), independent of Issuer Registry’s signing-key and
SSO-secret keys — a compromise of one does not expose the others.
Data model (learner schema)
| Entity | Table | Notes |
|---|---|---|
| Learner | learner | learner_id (UUID PK), legal_name, dob — both encrypted at rest |
| Learner identifier | learner_identifier | identifier_type (USI, NSN, …), ciphertext + nonce (AES-256-GCM), verification_status (UNVERIFIED/VERIFIED/FAILED) |
| Enrolment | enrolment | learner × issuer × catalog entry version over a period; delivery_mode/funding_source are jurisdiction-scoped code_set values, never hardcoded enums |
| Outcome | outcome | result of an enrolment — result_code (code_set FK), is_rpl (recognition of prior learning), assessor_ref |
Identifier verification — format-only, not a registry lookup
LearnerIdentifierVerificationClient is a pluggable interface; the only implementation today,
UsiFormatVerificationClient, validates an Australian USI’s structural well-formedness (10
characters from a 32-symbol ambiguous-character-free alphabet, weighted check-digit —
computeCheckCharacter). This is explicitly not a call to the real TGA/USI Registry web
service — a VERIFIED result means “well-formed,” not “confirmed against the national
registry.” Any identifier type other than USI (e.g. NZ’s NSN) is left UNVERIFIED. Swap in a
real HTTP client behind LearnerIdentifierVerificationClient before treating VERIFIED as more
than a data-entry sanity check.
REST API (/api/v1/learners)
| Method | Path | Purpose |
|---|---|---|
POST | /verify-identifier | Verify (or create, if unseen) a learner by national identifier |
GET | /{learnerId} | Fetch a learner record |
POST | /enrolments | Record an enrolment |
GET | /enrolments?issuerId=&fromDate=&toDate= | List an issuer’s enrolments (with outcome, if recorded) — source data for regulatory export jobs |
POST | /outcomes | Record an outcome for an enrolment |
gRPC surface (learner.proto)
Implemented in LearnerRecordsServiceImpl, delegating to the same LearnerRecordsService class
the REST controller uses.
| RPC | Purpose |
|---|---|
VerifyLearnerIdentifier | Verify/create a learner by national identifier — the RPC Core Engine calls at issuance time when learner identity is supplied |
GetLearner | Fetch a learner record |
RecordEnrolment, RecordOutcome | For direct/future SMS integration — not called from Core Engine’s issuance flow (recording an enrolment/outcome is a distinct workflow from issuing the credential that later cites it) |
ListEnrolments | For an issuer’s regulatory reporting job (e.g. AVETMISS NAT-file export) |
Who calls this service
LearnerRecordsGrpcClient (Core Engine) is used by exactly two callers: IssuanceOrchestrator
(VerifyLearnerIdentifier at issuance time) and AvetmissExportService (ListEnrolments for the
AU VET regulatory export) — a narrower integration surface than Program Catalog’s. Learner Records
is not involved in custodian intake, catalog administration, or semantic search.
Implementation status
Fully implemented against the learner schema and the full learner.proto surface. The one
explicitly-flagged gap: identifier verification depth is format-only (a self-contained checksum
algorithm), not a live registry call — the same documented pilot-stopgap pattern used elsewhere
(e.g. Issuer Registry’s application-layer key encryption ahead of a real HSM/KMS).