diff --git a/specs/medh/nsc/README.md b/specs/medh/nsc/README.md index 5be8d1e..33c6ea7 100644 --- a/specs/medh/nsc/README.md +++ b/specs/medh/nsc/README.md @@ -33,16 +33,17 @@ Current scope: ├── package.json ├── openapi.yml ├── paths/ -└── schemas/ +├── schemas/ +└── scripts/ ``` * `README.md`: Service-level guidance for the MEDH NSC specification workspace. * `package.json`: Local package metadata, validation scripts, and tooling dependencies. -* `openapi.yml`: OpenAPI entrypoint for the MEDH NSC service. It is currently a - placeholder for linter development. +* `openapi.yml`: OpenAPI entrypoint for the MEDH NSC service. * `paths/`: Operation path fragments referenced by `openapi.yml`. * `schemas/`: JSON Schema source files used by the service specification. +* `scripts/`: Local helper scripts used by service-level validation commands. ## Source of Truth and Generated Artifacts diff --git a/specs/medh/nsc/openapi.yml b/specs/medh/nsc/openapi.yml index cbeac50..9ac4dde 100644 --- a/specs/medh/nsc/openapi.yml +++ b/specs/medh/nsc/openapi.yml @@ -1,20 +1,65 @@ openapi: 3.1.0 info: - title: MEDH NSC Service API - summary: Placeholder OpenAPI document for linter development. + title: MEDH National Student Clearinghouse Service API + summary: Postsecondary enrollment verification through MESH. description: | - This is a minimal hello-world OpenAPI document for developing and testing - specification linting rules before the full MEDH NSC contract is authored. + The MEDH National Student Clearinghouse (NSC) service enables authorized + requesters to submit a single synchronous JSON request through the Medicaid + Eligibility Services Hub (MESH) to verify postsecondary enrollment + information reported to NSC. + + The service returns enrollment verification information only. It does not + determine Medicaid eligibility, determine whether a person satisfies a + community engagement requirement, verify high school enrollment, verify GED + or high school equivalency participation, or provide a complete academic + history. Requesters remain responsible for applying Medicaid eligibility + policy, community engagement policy, and state business rules to the + response. + + Requesters must obtain and maintain FERPA-compliant written or electronic + consent from the eligible student or another FERPA-authorized individual + before submitting a query. MESH does not collect, validate, or retain FERPA + consent artifacts in the NSC payload. The `termsAcceptedIndicator` value + confirms acceptance of applicable Clearinghouse terms and conditions; it is + not a FERPA consent indicator. license: name: CC0-1.0 identifier: CC0-1.0 - version: 0.0.1 + version: 0.1.0 servers: - - url: https://example.invalid - description: Placeholder server for local specification tooling. + - url: https://{meshHost} + description: MESH requester-facing endpoint assigned during onboarding. + variables: + meshHost: + default: mesh.example.invalid + description: Environment-specific MESH host name. tags: - - name: health - description: Placeholder operations for tooling validation. + - name: enrollment-verification + description: Postsecondary enrollment verification operations. +x-fdsh: + productGroup: medh + product: education + service: national-student-clearinghouse + serviceId: MH1 + gateway: MESH + trustedDataSource: NSC paths: - /hello: - $ref: "./paths/hello.yml" + /enrollment-verifications: + $ref: "./paths/verify-enrollment.yml" +components: + securitySchemes: + MeshClientCredentials: + type: oauth2 + description: | + OAuth 2.0 client credentials authentication issued through MESH + onboarding. Clients must support JWT-based authentication. + flows: + clientCredentials: + tokenUrl: /oauth2/token + scopes: {} + MeshMutualTLS: + type: mutualTLS + description: | + Two-way TLS is required for requester-to-MESH connections. Client + certificates must be signed by a trusted certificate authority, use + 2048-bit keys, and use SHA-2 digest strength of 256, 384, or 512. diff --git a/specs/medh/nsc/package.json b/specs/medh/nsc/package.json index 5327448..9ab2739 100644 --- a/specs/medh/nsc/package.json +++ b/specs/medh/nsc/package.json @@ -9,7 +9,7 @@ "lint:openapi": "REDOCLY_TELEMETRY=off REDOCLY_SUPPRESS_UPDATE_NOTICE=true redocly lint openapi.yml", "bundle": "REDOCLY_TELEMETRY=off REDOCLY_SUPPRESS_UPDATE_NOTICE=true redocly bundle openapi.yml --output openapi.bundled.yml", "validate": "pnpm run validate:schemas", - "validate:schemas": "sh -c 'set -- schemas/*.schema.json; if [ -e \"$1\" ]; then for schema in \"$@\"; do ajv compile --spec=draft2020 -s \"$schema\"; done; else echo \"No JSON Schema files found\"; fi'", + "validate:schemas": "sh -c 'set -- schemas/*.schema.json; if [ -e \"$1\" ]; then for schema in \"$@\"; do ajv compile --spec=draft2020 -c ./scripts/ajv-formats.cjs -s \"$schema\"; done; else echo \"No JSON Schema files found\"; fi'", "test": "pnpm run lint" }, "devDependencies": { diff --git a/specs/medh/nsc/paths/hello.yml b/specs/medh/nsc/paths/hello.yml deleted file mode 100644 index d919c66..0000000 --- a/specs/medh/nsc/paths/hello.yml +++ /dev/null @@ -1,21 +0,0 @@ -get: - tags: - - health - summary: Return a hello-world message. - description: Returns a static response that can be used to test OpenAPI tooling. - operationId: getHello - security: [] - responses: - "200": - description: A hello-world response. - content: - application/json: - schema: - $ref: "../schemas/hello-world-response.schema.json" - examples: - default: - summary: Default hello-world response. - value: - message: hello world - "400": - description: Invalid request. diff --git a/specs/medh/nsc/paths/verify-enrollment.yml b/specs/medh/nsc/paths/verify-enrollment.yml new file mode 100644 index 0000000..4dea0e4 --- /dev/null +++ b/specs/medh/nsc/paths/verify-enrollment.yml @@ -0,0 +1,251 @@ +post: + tags: + - enrollment-verification + summary: Verify postsecondary enrollment with NSC. + description: | + Submits one synchronous enrollment verification request through MESH to NSC + for a single applicant or beneficiary. The request must use either the + Name/DOB verification path or the SSN-only verification path. + + The Name/DOB path requires first name, last name, birth date, as-of date, + and `termsAcceptedIndicator`. It may include a full SSN, last four SSN + digits, middle name, and up to five previous names. The SSN-only path + requires a full nine-digit SSN, as-of date, and `termsAcceptedIndicator`, + and does not permit other request fields. + + `asOfDate` filters enrollment records as if the request was submitted on + that date. The service returns a business response for successful + transactions, including no-match results, and an error response containing + `responseMetadata` when validation or upstream processing fails. + operationId: verifyNscEnrollment + security: + - MeshClientCredentials: [] + MeshMutualTLS: [] + parameters: + - name: messageID + in: header + required: true + description: | + Unique request tracing identifier. Requesters are expected to send a + UUID value that is unique for each request. + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + requestBody: + required: true + content: + application/json: + schema: + $ref: "../schemas/nsc-enrollment-verification-request.schema.json" + examples: + minimalNameDob: + summary: Minimal Name/DOB verification request. + value: + nscRequest: + personGivenName: Mason + personSurName: Brooks + personBirthDate: "1984-02-21" + asOfDate: "2026-05-22" + termsAcceptedIndicator: true + nameDobWithPreviousNames: + summary: Name/DOB request with optional identifiers. + value: + nscRequest: + personSocialSecurityNumber: "1234" + personGivenName: Mason + personMiddleName: Lee + personSurName: Brooks + previousNames: + - personGivenName: John + personMiddleName: Jacob + personSurName: Smith + personBirthDate: "1984-02-21" + asOfDate: "2026-05-22" + termsAcceptedIndicator: true + ssnOnly: + summary: SSN-only verification request. + value: + nscRequest: + personSocialSecurityNumber: "555551234" + asOfDate: "2026-05-22" + termsAcceptedIndicator: true + responses: + "200": + description: | + Successful NSC transaction. A successful response can contain matched + enrollment details or a no-match result with `nscHitIndicator` set to + `false`. + headers: + messageID: + description: Request tracing identifier associated with the response. + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + content: + application/json: + schema: + $ref: "../schemas/nsc-enrollment-verification-response.schema.json" + examples: + matched: + summary: Successful matched response. + value: + nscResponse: + transactionDetails: + transactionId: "200000001" + orderId: "100000001" + transactionStatusCode: CNF + transactionFee: "0.00" + salesTax: "0.00" + transactionTotal: "0.00" + requestedByText: MESH TEST USER + requestedDateTimeText: "2026-05-03 09:06:00.0" + notifiedDateTimeText: "2026-05-03 09:11:05.0" + nscHitIndicator: true + studentInfoProvided: + personGivenName: Mason + personMiddleName: Lee + personSurName: Brooks + personBirthDate: "1984-02-21" + previousNames: + - personGivenName: John + personMiddleName: Jacob + personSurName: Smith + enrollmentDetails: + - officialSchoolName: Example School Name + schoolCode: "000001" + branchCode: "00" + currentEnrollmentStatusCode: CC + enrollmentData: + - enrollmentStatusCode: Y + termBeginDate: "2025-01-10" + termEndDate: "2025-05-04" + schoolCertifiedOnDate: "2025-02-04" + anticipatedGraduationDate: "2026-05-04" + responseMetadata: + responseCode: MS000000 + responseText: Successful + noMatch: + summary: Successful no-match response. + value: + nscResponse: + transactionDetails: + transactionId: "200000002" + orderId: "100000002" + transactionStatusCode: CNF + transactionFee: "0.00" + salesTax: "0.00" + transactionTotal: "0.00" + requestedByText: MESH TEST USER + requestedDateTimeText: "2026-05-03 09:06:00.0" + nscHitIndicator: false + responseMetadata: + responseCode: MS000000 + responseText: Successful + "400": + description: | + Request validation, authorization, or submitted-data failure reported by + MESH. The response body contains a MESH response code and text. + headers: + messageID: + description: Request tracing identifier associated with the response. + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + content: + application/json: + schema: + $ref: "../schemas/nsc-enrollment-verification-response.schema.json" + examples: + schemaValidationFailure: + summary: Schema validation failure. + value: + nscResponse: + responseMetadata: + responseCode: ME007000 + responseText: Schema Validation Failure + invalidSsn: + summary: Invalid SSN value. + value: + nscResponse: + responseMetadata: + responseCode: ME110020 + responseText: personSocialSecurityNumber is invalid + "401": + description: Authentication failed before the enrollment verification request could be processed. + headers: + messageID: + description: Request tracing identifier associated with the response. + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + content: + application/json: + schema: + $ref: "../schemas/nsc-enrollment-verification-response.schema.json" + examples: + authenticationFailure: + summary: Authentication or authorization failure. + value: + nscResponse: + responseMetadata: + responseCode: ME110010 + responseText: Authentication or authorization failure + "429": + description: The trusted data source reported a rate-limit condition. + headers: + messageID: + description: Request tracing identifier associated with the response. + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + content: + application/json: + schema: + $ref: "../schemas/nsc-enrollment-verification-response.schema.json" + examples: + trustedDataSourceRateLimit: + summary: Trusted data source rate limit. + value: + nscResponse: + responseMetadata: + responseCode: MX005001 + responseText: Unexpected Exception Occurred at Trusted Data Source + "500": + description: System error or unexpected upstream failure. + headers: + messageID: + description: Request tracing identifier associated with the response. + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + content: + application/json: + schema: + $ref: "../schemas/nsc-enrollment-verification-response.schema.json" + examples: + trustedDataSourceFailure: + summary: Trusted data source failure. + value: + nscResponse: + responseMetadata: + responseCode: MX005001 + responseText: Unexpected Exception Occurred at Trusted Data Source + unexpectedSystemException: + summary: Unexpected system exception. + value: + nscResponse: + responseMetadata: + responseCode: MX009000 + responseText: Unexpected System Exception diff --git a/specs/medh/nsc/schemas/hello-world-response.schema.json b/specs/medh/nsc/schemas/hello-world-response.schema.json deleted file mode 100644 index 0da8610..0000000 --- a/specs/medh/nsc/schemas/hello-world-response.schema.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://dsacms.github.io/fdsh-utils/schema/hello-world-response.schema.json", - "title": "HelloWorldResponse", - "description": "A minimal response schema used to validate local OpenAPI and JSON Schema linting.", - "type": "object", - "required": ["message"], - "additionalProperties": false, - "properties": { - "message": { - "type": "string", - "const": "hello world" - } - } -} diff --git a/specs/medh/nsc/schemas/nsc-enrollment-verification-request.schema.json b/specs/medh/nsc/schemas/nsc-enrollment-verification-request.schema.json new file mode 100644 index 0000000..233ca2e --- /dev/null +++ b/specs/medh/nsc/schemas/nsc-enrollment-verification-request.schema.json @@ -0,0 +1,159 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://dsacms.github.io/fdsh-utils/schema/medh/nsc/nsc-enrollment-verification-request.schema.json", + "title": "NscEnrollmentVerificationRequest", + "description": "Request payload for the MEDH National Student Clearinghouse enrollment verification service. The request must use either the SSN-only verification path or the Name/DOB verification path.", + "type": "object", + "required": ["nscRequest"], + "additionalProperties": false, + "properties": { + "nscRequest": { + "oneOf": [ + { + "$ref": "#/$defs/NscSsnOnlyVerificationRequest" + }, + { + "$ref": "#/$defs/NscNameDobVerificationRequest" + } + ] + } + }, + "$defs": { + "NscSsnOnlyVerificationRequest": { + "description": "SSN-only verification path. This path requires the full nine-digit SSN and does not permit name or birth-date fields.", + "type": "object", + "required": [ + "personSocialSecurityNumber", + "asOfDate", + "termsAcceptedIndicator" + ], + "additionalProperties": false, + "properties": { + "personSocialSecurityNumber": { + "$ref": "#/$defs/FullSocialSecurityNumber" + }, + "asOfDate": { + "$ref": "#/$defs/AsOfDate" + }, + "termsAcceptedIndicator": { + "$ref": "#/$defs/TermsAcceptedIndicator" + } + } + }, + "NscNameDobVerificationRequest": { + "description": "Name/DOB verification path. This path requires first name, last name, birth date, as-of date, and accepted terms. Optional fields can improve matching.", + "type": "object", + "required": [ + "personGivenName", + "personSurName", + "personBirthDate", + "asOfDate", + "termsAcceptedIndicator" + ], + "additionalProperties": false, + "properties": { + "personSocialSecurityNumber": { + "$ref": "#/$defs/OptionalSocialSecurityNumber" + }, + "personGivenName": { + "$ref": "#/$defs/PersonGivenName" + }, + "personMiddleName": { + "$ref": "#/$defs/PersonMiddleName" + }, + "personSurName": { + "$ref": "#/$defs/PersonSurName" + }, + "previousNames": { + "description": "Previous names used by the individual. If present, the array must contain at least one and no more than five names.", + "type": "array", + "minItems": 1, + "maxItems": 5, + "items": { + "$ref": "#/$defs/NscPreviousName" + } + }, + "personBirthDate": { + "description": "Birth date of the individual.", + "type": "string", + "format": "date" + }, + "asOfDate": { + "$ref": "#/$defs/AsOfDate" + }, + "termsAcceptedIndicator": { + "$ref": "#/$defs/TermsAcceptedIndicator" + } + } + }, + "NscPreviousName": { + "description": "A previous name used by the individual.", + "type": "object", + "required": [ + "personGivenName", + "personSurName" + ], + "additionalProperties": false, + "properties": { + "personGivenName": { + "$ref": "#/$defs/PersonGivenName" + }, + "personMiddleName": { + "$ref": "#/$defs/PersonMiddleName" + }, + "personSurName": { + "$ref": "#/$defs/PersonSurName" + } + } + }, + "FullSocialSecurityNumber": { + "description": "Full nine-digit Social Security Number.", + "type": "string", + "minLength": 9, + "maxLength": 9, + "pattern": "^([1-57-8][0-9]{2}|0([1-9][0-9]|[0-9][1-9])|6([0-57-9][0-9]|[0-9][0-57-9]))([1-9][0-9]|[0-9][1-9])([1-9]\\d{3}|\\d[1-9]\\d{2}|\\d{2}[1-9]\\d|\\d{3}[1-9])$" + }, + "OptionalSocialSecurityNumber": { + "description": "Either a full nine-digit Social Security Number or the last four digits. Last-four values cannot be 0000.", + "type": "string", + "minLength": 4, + "maxLength": 9, + "anyOf": [ + { + "$ref": "#/$defs/FullSocialSecurityNumber" + }, + { + "pattern": "^(?!0000)\\d{4}$" + } + ] + }, + "PersonGivenName": { + "description": "First name of the individual. Use FNU or NFN when no first name is available.", + "type": "string", + "minLength": 1, + "maxLength": 30 + }, + "PersonMiddleName": { + "description": "Middle name or middle initial of the individual.", + "type": "string", + "minLength": 1, + "maxLength": 30 + }, + "PersonSurName": { + "description": "Last name of the individual.", + "type": "string", + "minLength": 1, + "maxLength": 30 + }, + "AsOfDate": { + "description": "Date used to filter enrollment records as if the request was submitted on that date.", + "type": "string", + "format": "date" + }, + "TermsAcceptedIndicator": { + "description": "Indicates that the requester has accepted the applicable Clearinghouse terms and conditions for the query. This is not a FERPA consent indicator.", + "type": "boolean", + "const": true + } + } +} diff --git a/specs/medh/nsc/schemas/nsc-enrollment-verification-response.schema.json b/specs/medh/nsc/schemas/nsc-enrollment-verification-response.schema.json new file mode 100644 index 0000000..cf65d09 --- /dev/null +++ b/specs/medh/nsc/schemas/nsc-enrollment-verification-response.schema.json @@ -0,0 +1,358 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://dsacms.github.io/fdsh-utils/schema/medh/nsc/nsc-enrollment-verification-response.schema.json", + "title": "NscEnrollmentVerificationResponse", + "description": "Response payload for the MEDH National Student Clearinghouse enrollment verification service. Responses contain either business details and response metadata, or an error response with response metadata only.", + "type": "object", + "required": ["nscResponse"], + "additionalProperties": false, + "properties": { + "nscResponse": { + "oneOf": [ + { + "$ref": "#/$defs/NscBusinessResponse" + }, + { + "$ref": "#/$defs/NscErrorResponse" + } + ] + } + }, + "$defs": { + "NscBusinessResponse": { + "description": "Business response from an NSC enrollment verification transaction.", + "type": "object", + "required": [ + "transactionDetails", + "responseMetadata" + ], + "additionalProperties": false, + "properties": { + "transactionDetails": { + "$ref": "#/$defs/NscTransactionDetails" + }, + "studentInfoProvided": { + "$ref": "#/$defs/NscStudentInfoProvided" + }, + "enrollmentDetails": { + "description": "Enrollment details returned by NSC when records are available. This array is omitted for no-match responses.", + "type": "array", + "minItems": 1, + "maxItems": 99, + "items": { + "$ref": "#/$defs/NscEnrollmentDetails" + } + }, + "responseMetadata": { + "$ref": "#/$defs/MeshResponseMetadata" + } + } + }, + "NscErrorResponse": { + "description": "Error response containing MESH response metadata only.", + "type": "object", + "required": ["responseMetadata"], + "additionalProperties": false, + "properties": { + "responseMetadata": { + "$ref": "#/$defs/MeshResponseMetadata" + } + } + }, + "NscTransactionDetails": { + "description": "Transaction metadata returned by NSC and MESH for tracing, status, and cost reporting.", + "type": "object", + "required": [ + "transactionId", + "orderId", + "transactionStatusCode", + "transactionFee", + "salesTax", + "transactionTotal", + "requestedByText", + "requestedDateTimeText", + "nscHitIndicator" + ], + "additionalProperties": false, + "properties": { + "transactionId": { + "description": "Unique NSC transaction identifier.", + "type": "string", + "pattern": "^[0-9]{9,15}$" + }, + "orderId": { + "description": "Unique NSC order identifier.", + "type": "string", + "pattern": "^[0-9]{9,15}$" + }, + "transactionStatusCode": { + "$ref": "#/$defs/NscTransactionStatusCode" + }, + "transactionFee": { + "$ref": "#/$defs/NscCurrencyAmount" + }, + "salesTax": { + "$ref": "#/$defs/NscCurrencyAmount" + }, + "transactionTotal": { + "$ref": "#/$defs/NscCurrencyAmount" + }, + "requestedByText": { + "description": "Name associated with the MESH user account that requested the transaction.", + "type": "string", + "minLength": 1, + "maxLength": 60 + }, + "requestedDateTimeText": { + "$ref": "#/$defs/NscDateTimeText" + }, + "notifiedDateTimeText": { + "$ref": "#/$defs/NscDateTimeText" + }, + "nscHitIndicator": { + "description": "Indicates whether NSC found a matching student record. A false value means no matching NSC record was found.", + "type": "boolean" + } + } + }, + "NscStudentInfoProvided": { + "description": "Student information echoed from the request when available.", + "type": "object", + "required": [ + "personGivenName", + "personSurName", + "personBirthDate" + ], + "additionalProperties": false, + "properties": { + "personGivenName": { + "$ref": "#/$defs/NscResponsePersonGivenName" + }, + "personMiddleName": { + "$ref": "#/$defs/NscResponsePersonMiddleName" + }, + "personSurName": { + "$ref": "#/$defs/NscResponsePersonSurName" + }, + "previousNames": { + "description": "Previous names used by the individual. If present, the array must contain at least one and no more than five names.", + "type": "array", + "minItems": 1, + "maxItems": 5, + "items": { + "$ref": "#/$defs/NscResponsePreviousName" + } + }, + "personBirthDate": { + "description": "Birth date of the individual.", + "type": "string", + "format": "date" + } + } + }, + "NscResponsePreviousName": { + "description": "A previous name used by the individual.", + "type": "object", + "required": [ + "personGivenName", + "personSurName" + ], + "additionalProperties": false, + "properties": { + "personGivenName": { + "$ref": "#/$defs/NscResponsePersonGivenName" + }, + "personMiddleName": { + "$ref": "#/$defs/NscResponsePersonMiddleName" + }, + "personSurName": { + "$ref": "#/$defs/NscResponsePersonSurName" + } + } + }, + "NscEnrollmentDetails": { + "description": "Enrollment information for one school.", + "type": "object", + "required": [ + "officialSchoolName", + "schoolCode", + "branchCode", + "currentEnrollmentStatusCode", + "enrollmentData" + ], + "additionalProperties": false, + "properties": { + "officialSchoolName": { + "description": "Official school name.", + "type": "string", + "minLength": 1, + "maxLength": 100 + }, + "schoolCode": { + "description": "Six-digit Department of Education school identifier.", + "type": "string", + "pattern": "^[0-9]{6}$" + }, + "branchCode": { + "description": "Two-digit school branch identifier.", + "type": "string", + "pattern": "^[0-9]{2}$" + }, + "currentEnrollmentStatusCode": { + "$ref": "#/$defs/NscCurrentEnrollmentStatusCode" + }, + "enrollmentData": { + "description": "Enrollment term details for the school.", + "type": "array", + "minItems": 1, + "maxItems": 99, + "items": { + "$ref": "#/$defs/NscEnrollmentTerm" + } + } + } + }, + "NscEnrollmentTerm": { + "description": "Enrollment details for one school term.", + "type": "object", + "required": [ + "enrollmentStatusCode", + "termBeginDate", + "termEndDate", + "schoolCertifiedOnDate" + ], + "additionalProperties": false, + "properties": { + "enrollmentStatusCode": { + "$ref": "#/$defs/NscEnrollmentStatusCode" + }, + "termBeginDate": { + "description": "Start date of the enrollment term.", + "type": "string", + "format": "date" + }, + "termEndDate": { + "description": "End date of the enrollment term.", + "type": "string", + "format": "date" + }, + "schoolCertifiedOnDate": { + "description": "Date the school certified the enrollment record.", + "type": "string", + "format": "date" + }, + "anticipatedGraduationDate": { + "description": "Anticipated graduation date provided by the school.", + "type": "string", + "format": "date" + } + } + }, + "MeshResponseMetadata": { + "description": "MESH response code and response text for a successful or unsuccessful service response.", + "type": "object", + "required": [ + "responseCode", + "responseText" + ], + "additionalProperties": false, + "properties": { + "responseCode": { + "$ref": "#/$defs/MeshResponseCode" + }, + "responseText": { + "description": "Description of the response code.", + "type": "string" + }, + "tdsResponseText": { + "description": "Optional response text returned by the trusted data source.", + "type": "string" + } + } + }, + "MeshResponseCode": { + "description": "MESH response code. Known NSC codes include success, request validation failures, upstream failures, and unexpected system conditions.", + "type": "string", + "pattern": "^(ME|MS|MX)[0-9]{6}$", + "enum": [ + "MS000000", + "ME110010", + "ME100005", + "ME110020", + "ME110030", + "ME110040", + "ME110050", + "ME110060", + "ME110075", + "ME120030", + "ME120040", + "ME120045", + "ME007000", + "MX005001", + "MX009000", + "MX009999" + ] + }, + "NscTransactionStatusCode": { + "description": "NSC transaction status: CNF is confirmed; UCF is unable to respond.", + "type": "string", + "enum": [ + "CNF", + "UCF" + ] + }, + "NscCurrentEnrollmentStatusCode": { + "description": "Current enrollment status: CC is currently enrolled; CN is currently not enrolled. CC can be returned when an active enrollment term has an end date within 18 months of the request. CN can be returned when the most recent enrollment term end date is more than 18 months before the request.", + "type": "string", + "enum": [ + "CC", + "CN" + ] + }, + "NscEnrollmentStatusCode": { + "description": "Enrollment status code: F full-time, Q three-quarter-time, H half-time, L less-than-half-time, Y status not released by school, A leave of absence, W withdrawn, S Clearinghouse generated withdrawn, G graduated, D deceased. When Y is returned, only the enrollment status classification is withheld; other available enrollment data may still be returned.", + "type": "string", + "enum": [ + "F", + "Q", + "H", + "L", + "Y", + "A", + "W", + "S", + "G", + "D" + ] + }, + "NscCurrencyAmount": { + "description": "Currency amount formatted as X.XX. The value is typically 0.00.", + "type": "string", + "pattern": "^[0-9]\\.[0-9]{2}$" + }, + "NscDateTimeText": { + "description": "Date and time text in YYYY-MM-DD HH:MM:SS.X format without timezone.", + "type": "string", + "minLength": 21, + "maxLength": 24 + }, + "NscResponsePersonGivenName": { + "description": "First name of the individual.", + "type": "string", + "minLength": 1, + "maxLength": 30 + }, + "NscResponsePersonMiddleName": { + "description": "Middle name or middle initial of the individual.", + "type": "string", + "minLength": 1, + "maxLength": 30 + }, + "NscResponsePersonSurName": { + "description": "Last name of the individual.", + "type": "string", + "minLength": 1, + "maxLength": 30 + } + } +} diff --git a/specs/medh/nsc/scripts/ajv-formats.cjs b/specs/medh/nsc/scripts/ajv-formats.cjs new file mode 100644 index 0000000..8ec2fd1 --- /dev/null +++ b/specs/medh/nsc/scripts/ajv-formats.cjs @@ -0,0 +1,21 @@ +function isValidDate(value) { + if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) { + return false; + } + + const [year, month, day] = value.split("-").map(Number); + const date = new Date(Date.UTC(year, month - 1, day)); + + return ( + date.getUTCFullYear() === year && + date.getUTCMonth() === month - 1 && + date.getUTCDate() === day + ); +} + +module.exports = function addAjvFormats(ajv) { + ajv.addFormat("date", { + type: "string", + validate: isValidDate + }); +};