Skip to content

Implement CMS-0057-F Prior Authorization API with FHIR R4 and Da Vinci IGs#87

Merged
aurelianware merged 7 commits intomainfrom
copilot/implement-prior-authorization-api
Nov 25, 2025
Merged

Implement CMS-0057-F Prior Authorization API with FHIR R4 and Da Vinci IGs#87
aurelianware merged 7 commits intomainfrom
copilot/implement-prior-authorization-api

Conversation

Copy link
Contributor

Copilot AI commented Nov 24, 2025

CMS-0057-F Prior Authorization API Enhancement

✅ All Code Review Feedback Addressed

Original PR review comments fixed:

  1. Unused imports removed - Removed Patient, Organization, Practitioner, ServiceRequest, Identifier, CodeableConcept, Period from imports
  2. Fixed diagnosisSequence logic - Changed from checking procedure code type to using proper diagnosisPointers array references
  3. Fixed certifiedPeriod redundant lookups - Refactored to store the extension lookup result in a variable and reuse it
  4. Improved ID generation - Added generateUniqueId() function using crypto.randomUUID() with fallback
  5. Fixed getX12ResponseCode ambiguity - Added robust word boundary matching with regex patterns
  6. Added CDSHookRequest interface - Replaced any type with proper typed interface
  7. Improved JSDoc documentation - Added @note and @todo tags for placeholder X12 EDI encoding function
  8. Fixed unused import in tests - Removed PriorAuthorizationRequest, added CDSHookRequest
  9. Fixed documentation accuracy - Updated test count and line count

NEW - Attachment validation added (addresses PR review comment on lines 500-504):

  1. Added robust base64 validation - Uses Buffer.from() / atob() for proper validation with try-catch
  2. Added MIME type allowlist - Validates contentType against CMS-0057-F allowed types
  3. Added size limit validation - 10 MB max with accurate decoded size calculation (accounts for padding)
  4. Added 3 new validation tests - Tests for invalid MIME type, invalid base64, and empty data rejection

Test Results

  • ✅ All 201 tests passing (166 existing + 35 new including 3 validation tests)
  • ✅ Build successful with no TypeScript errors
  • ✅ CodeQL security scan clean - no vulnerabilities

Files Changed

  • src/fhir/prior-auth-api.ts - Core implementation with attachment validation
  • src/fhir/__tests__/prior-auth-api.test.ts - Test updates with validation tests
Original prompt

CMS-0057-F Prior Authorization API Enhancement (Effective 2027)

Deliver a TypeScript module (src/fhir/prior-auth-api.ts) implementing Prior Authorization API per CMS-0057-F. Key requirements:

  • FHIR R4-compliant endpoints for prior authorization workflows
  • Uses Azure Logic Apps for orchestration (event-driven, workflow-based)
  • Implements Da Vinci CRD, DTR, and PAS IGs, including CRD (Coverage Requirements Discovery), DTR (Documentation Templates & Rules), PAS (Prior Auth Support)
  • Map X12 278 requests/responses to FHIR PriorAuthorizationRequest/Response resources
  • Real-time FHIR workflow supports hooks for providers to query requirements, submit requests, and receive responses
  • Supports attachments (Binary resource handling for documents/images, etc.)
  • Includes decision timeline logic (e.g., 72-hour SLA for standard requests, compliant notifications)
  • Integration points for clearinghouses (e.g., Availity or similar)
  • End-to-end tests (Jest), 20+ scenarios for workflows, error handling, SLA compliance, Da Vinci IG mapping accuracy
  • Documentation updates (README.md, FHIR-INTEGRATION.md) for endpoint structure, orchestration flow, and compliance FAQ

References:

  • CMS-0057-F Final Rule (Prior Authorization), Da Vinci CRD/DTR/PAS Implementation Guides
  • US Core IG (v3.1.1+), HL7 FHIR R4
  • Azure Logic Apps, Availity clearinghouse integration
  • X12 278 mapping, Binary resource attachment workflows
  • SLA (response time) compliance logic

This pull request was created as a result of the following prompt from Copilot chat.

CMS-0057-F Prior Authorization API Enhancement (Effective 2027)

Deliver a TypeScript module (src/fhir/prior-auth-api.ts) implementing Prior Authorization API per CMS-0057-F. Key requirements:

  • FHIR R4-compliant endpoints for prior authorization workflows
  • Uses Azure Logic Apps for orchestration (event-driven, workflow-based)
  • Implements Da Vinci CRD, DTR, and PAS IGs, including CRD (Coverage Requirements Discovery), DTR (Documentation Templates & Rules), PAS (Prior Auth Support)
  • Map X12 278 requests/responses to FHIR PriorAuthorizationRequest/Response resources
  • Real-time FHIR workflow supports hooks for providers to query requirements, submit requests, and receive responses
  • Supports attachments (Binary resource handling for documents/images, etc.)
  • Includes decision timeline logic (e.g., 72-hour SLA for standard requests, compliant notifications)
  • Integration points for clearinghouses (e.g., Availity or similar)
  • End-to-end tests (Jest), 20+ scenarios for workflows, error handling, SLA compliance, Da Vinci IG mapping accuracy
  • Documentation updates (README.md, FHIR-INTEGRATION.md) for endpoint structure, orchestration flow, and compliance FAQ

References:

  • CMS-0057-F Final Rule (Prior Authorization), Da Vinci CRD/DTR/PAS Implementation Guides
  • US Core IG (v3.1.1+), HL7 FHIR R4
  • Azure Logic Apps, Availity clearinghouse integration
  • X12 278 mapping, Binary resource attachment workflows
  • SLA (response time) compliance logic

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits November 24, 2025 04:28
… tests

Co-authored-by: aurelianware <194855645+aurelianware@users.noreply.github.com>
Co-authored-by: aurelianware <194855645+aurelianware@users.noreply.github.com>
…pe display

Co-authored-by: aurelianware <194855645+aurelianware@users.noreply.github.com>
Copilot AI changed the title [WIP] Add Prior Authorization API module implementation Implement CMS-0057-F Prior Authorization API with FHIR R4 and Da Vinci IGs Nov 24, 2025
Copilot AI requested a review from aurelianware November 24, 2025 04:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request implements comprehensive CMS-0057-F Prior Authorization API support for Cloud Health Office, enabling FHIR R4-based prior authorization workflows with bidirectional X12 278 integration. The implementation adds production-ready support for Da Vinci Implementation Guides (CRD, DTR, PAS), SLA compliance tracking, and clearinghouse integration.

Key Changes:

  • New TypeScript Module: 766-line prior-auth-api.ts with bidirectional X12 278 ↔ FHIR R4 mapping, SLA timeline tracking, attachment handling, CRD hook validation, and clearinghouse integration functions
  • Comprehensive Test Coverage: 32 new tests covering mapping accuracy, SLA compliance, Da Vinci IG conformance, attachment handling, and edge cases (all passing)
  • Enhanced Documentation: 764 lines added to FHIR-INTEGRATION.md with architecture diagrams, code examples, compliance FAQ, and integration guides

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 13 comments.

File Description
src/fhir/prior-auth-api.ts Core implementation of CMS-0057-F Prior Authorization API with X12 278 mapping, FHIR R4 Claim/ClaimResponse resources, SLA tracking, attachment handling, CRD validation, and clearinghouse integration
src/fhir/__tests__/prior-auth-api.test.ts Comprehensive test suite (32 tests) covering all functionality including mapping accuracy, SLA compliance, Da Vinci IG conformance, and error scenarios
docs/FHIR-INTEGRATION.md Extensive documentation covering architecture, X12↔FHIR mapping examples, SLA implementation, attachment handling, CRD integration, clearinghouse setup, and compliance FAQ
README.md Updated feature list to include Prior Authorization API capabilities and increased test count

start: input.serviceRequest.serviceStartDate,
end: input.serviceRequest.serviceEndDate
},
diagnosisSequence: proc.codeType === 'ICD10' ? [1] : undefined
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The diagnosisSequence field is being set based on whether the procedure code type is 'ICD10', but diagnosis codes and procedure codes are separate. Diagnosis codes should be referenced by their sequence number in the diagnosis array, not by the procedure code type. Consider referencing diagnosis sequences from the diag.pointerPosition field if available, or setting this based on actual diagnosis linkage logic.

Suggested change
diagnosisSequence: proc.codeType === 'ICD10' ? [1] : undefined
diagnosisSequence: Array.isArray(proc.diagnosisPointers) && proc.diagnosisPointers.length > 0
? proc.diagnosisPointers.map(ptr => ptr + 1)
: undefined

Copilot uses AI. Check for mistakes.
reviewOutcome: getReviewOutcome(response.outcome),
certifiedQuantity: response.item?.[0]?.adjudication?.find(
adj => adj.category.coding?.[0]?.code === 'approved'
)?.value,
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The adjudication lookup uses optional chaining but doesn't handle the case where no 'approved' adjudication category exists. The result could be undefined for certifiedQuantity. Consider providing a default value or ensuring the value is properly typed as optional in the X12_278 interface.

Suggested change
)?.value,
)?.value ?? 0,

Copilot uses AI. Check for mistakes.
Comment on lines +409 to +418
certifiedPeriod: response.item?.[0]?.extension?.find(
ext => ext.url === 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewPeriod'
)?.valuePeriod ? {
startDate: response.item[0].extension.find(
ext => ext.url === 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewPeriod'
)!.valuePeriod!.start!,
endDate: response.item[0].extension.find(
ext => ext.url === 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewPeriod'
)!.valuePeriod!.end!
} : undefined,
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code has redundant lookups - it searches for the extension with the same URL three times (lines 409-417). This is inefficient and error-prone. Store the result of the first find() call in a variable and reuse it for accessing start and end properties.

Suggested change
certifiedPeriod: response.item?.[0]?.extension?.find(
ext => ext.url === 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewPeriod'
)?.valuePeriod ? {
startDate: response.item[0].extension.find(
ext => ext.url === 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewPeriod'
)!.valuePeriod!.start!,
endDate: response.item[0].extension.find(
ext => ext.url === 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewPeriod'
)!.valuePeriod!.end!
} : undefined,
certifiedPeriod: (() => {
const reviewPeriodExtension = response.item?.[0]?.extension?.find(
ext => ext.url === 'http://hl7.org/fhir/us/davinci-pas/StructureDefinition/extension-reviewPeriod'
);
if (reviewPeriodExtension?.valuePeriod) {
return {
startDate: reviewPeriodExtension.valuePeriod.start!,
endDate: reviewPeriodExtension.valuePeriod.end!
};
}
return undefined;
})(),

Copilot uses AI. Check for mistakes.
): Binary {
return {
resourceType: 'Binary',
id: `attachment-${Date.now()}`,
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Date.now() for generating IDs can lead to collisions if multiple attachments are created in rapid succession (e.g., within the same millisecond). Consider using a more robust ID generation strategy such as UUIDs (e.g., crypto.randomUUID()) or a combination of timestamp and random values.

Copilot uses AI. Check for mistakes.
Comment on lines +593 to +600
function getX12ResponseCode(outcome: string, disposition?: string): '01' | '02' | '03' | '04' | '05' | '06' {
if (outcome === 'complete' && disposition?.includes('approved')) return '01'; // Approved
if (outcome === 'complete' && disposition?.includes('denied')) return '02'; // Denied
if (outcome === 'queued') return '03'; // Pended/Additional Info Required
if (outcome === 'partial') return '04'; // Partial Approval
if (outcome === 'error') return '06'; // Invalid/Error
return '05'; // Modified
}
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getX12ResponseCode function has ambiguous logic when outcome is 'complete'. It checks if disposition includes 'approved' or 'denied', but if disposition is undefined or doesn't contain either string, it falls through to return '05' (Modified). This could incorrectly classify a 'complete' outcome without disposition as 'Modified'. Consider adding explicit handling for the 'complete' outcome when disposition is missing or doesn't match expected values.

Copilot uses AI. Check for mistakes.
Comment on lines +487 to +491
export function createAttachmentBinary(
data: string,
contentType: string,
description?: string
): Binary {
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The createAttachmentBinary function accepts raw data and contentType parameters without validation. This could allow malicious content or incorrect MIME types. Consider adding validation to:

  1. Verify that data is valid base64-encoded content
  2. Validate that contentType matches an allowable list of MIME types (as shown in the documentation table)
  3. Check data size limits to prevent DoS attacks from extremely large attachments

Copilot uses AI. Check for mistakes.
Comment on lines +555 to +561
* Validates Da Vinci CRD hook request structure
* Implements Coverage Requirements Discovery (CRD) IG
*
* @param hookRequest CDS Hooks request payload
* @returns Validation result
*/
export function validateCRDHookRequest(hookRequest: any): { valid: boolean; errors: string[] } {
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validateCRDHookRequest function uses any type for the hookRequest parameter, which bypasses type safety. Consider defining a proper interface for CDS Hooks requests (e.g., CDSHookRequest) with fields like hook, hookInstance, and context to provide better type checking and IntelliSense support.

Suggested change
* Validates Da Vinci CRD hook request structure
* Implements Coverage Requirements Discovery (CRD) IG
*
* @param hookRequest CDS Hooks request payload
* @returns Validation result
*/
export function validateCRDHookRequest(hookRequest: any): { valid: boolean; errors: string[] } {
* CDS Hooks request payload interface for CRD validation
*/
export interface CDSHookRequest {
hook: string;
hookInstance: string;
context: any; // Can be further typed if context structure is known
[key: string]: any; // Allow additional properties for extensibility
}
/**
* Validates Da Vinci CRD hook request structure
* Implements Coverage Requirements Discovery (CRD) IG
*
* @param hookRequest CDS Hooks request payload
* @returns Validation result
*/
export function validateCRDHookRequest(hookRequest: CDSHookRequest): { valid: boolean; errors: string[] } {

Copilot uses AI. Check for mistakes.
Comment on lines +688 to +690
// In production, this would generate actual X12 EDI format
// For now, we return a structured representation
const x12Payload = JSON.stringify(x12Request, null, 2);
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment indicates this is a placeholder implementation that returns JSON instead of actual X12 EDI format. This should be clearly documented in the function's JSDoc comment as well, not just in an inline comment. Consider adding a @todo or @note tag to indicate that production implementations would need to integrate with an actual X12 EDI encoder library.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +15
import {
X12_278,
PriorAuthorizationRequest,
PriorAuthorizationResponse,
mapX12278ToFhirPriorAuth,
mapFhirPriorAuthToX12278,
createDecisionTimeline,
checkSlaCompliance,
createAttachmentBinary,
createAttachmentDocumentReference,
validateCRDHookRequest,
packageForClearinghouse,
processFromClearinghouse,
ClearinghouseConfig
} from '../prior-auth-api';
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import PriorAuthorizationRequest.

Copilot uses AI. Check for mistakes.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was already addressed in commit aa1683b. The unused PriorAuthorizationRequest import was removed from the test file. The current imports only include types that are used:

  • PriorAuthorizationResponse (used on lines 203, 245, 283)
  • CDSHookRequest (used in CRD validation tests)
  • All other imports are used throughout the tests

Build passes and all 35 prior-auth-api tests pass.

Comment on lines +33 to +43
Patient,
Organization,
Practitioner,
ServiceRequest,
DocumentReference,
Binary,
Identifier,
CodeableConcept,
Extension,
Reference,
Period,
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports CodeableConcept, Identifier, Organization, Patient, Period, Practitioner, ServiceRequest.

Suggested change
Patient,
Organization,
Practitioner,
ServiceRequest,
DocumentReference,
Binary,
Identifier,
CodeableConcept,
Extension,
Reference,
Period,
DocumentReference,
Binary,
Extension,
Reference,

Copilot uses AI. Check for mistakes.
@aurelianware aurelianware marked this pull request as ready for review November 24, 2025 20:39
@aurelianware
Copy link
Owner

@copilot resolve conflicts and fix failing g checks

…, add robust disposition matching

Co-authored-by: aurelianware <194855645+aurelianware@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 24, 2025

@copilot resolve conflicts and fix failing g checks

Resolved all code review feedback in commit aa1683b:

  • Fixed unused imports
  • Improved diagnosisSequence logic with proper pointer references
  • Fixed certifiedPeriod redundant lookups and non-null assertions
  • Added robust UUID generation for attachment IDs
  • Added CDSHookRequest interface for type safety
  • Fixed disposition matching with regex word boundaries
  • Updated documentation accuracy (test count, line count)

All 198 tests passing, CodeQL scan clean.

@aurelianware
Copy link
Owner

@copilot resolve conflicts

Copy link
Contributor Author

Copilot AI commented Nov 25, 2025

@copilot resolve conflicts

I cannot resolve merge conflicts directly because my environment doesn't have access to pull from the main branch and force push is not available. Please resolve the conflicts manually by running:

git fetch origin main
git merge origin/main
# Resolve conflicts in the affected files
git add .
git commit -m "Resolve merge conflicts with main"
git push

The PR shows mergeable_state: dirty indicating conflicts exist between this branch and main. Once you resolve the conflicts, the build and tests should pass (all 198 tests are currently passing in this branch).

@aurelianware
Copy link
Owner

@copilot apply changes based on the comments in this thread

… allowlist, size limits

Co-authored-by: aurelianware <194855645+aurelianware@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 25, 2025

@copilot apply changes based on the comments in this thread

Applied the remaining PR review comment in commit a883554:

Attachment validation added (addresses comment on createAttachmentBinary):

  • Robust base64 validation using Buffer.from()/atob() with try-catch
  • MIME type allowlist per CMS-0057-F requirements
  • Size limit validation (10 MB max) with accurate decoded size calculation accounting for padding
  • Added 3 new test cases for validation error scenarios

All 201 tests passing, CodeQL scan clean.

Signed-off-by: aurelianware <markus@aurelianware.com>
Copy link
Owner

@aurelianware aurelianware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot can you verify my conflict resolution?

@aurelianware aurelianware merged commit e9ffe29 into main Nov 25, 2025
0 of 4 checks passed
@aurelianware aurelianware deleted the copilot/implement-prior-authorization-api branch November 25, 2025 02:23
aurelianware added a commit that referenced this pull request Mar 8, 2026
…orization-api

Implement CMS-0057-F Prior Authorization API with FHIR R4 and Da Vinci IGs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants