Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pas-lint

A fast, dependency-free linter for FHIR R4 prior-authorization request bundles. You hand it the Bundle you would POST to a payer's Claim/$submit endpoint, and it tells you, in plain English with an IG citation on every finding, which parts of the Da Vinci PAS request contract you are not meeting yet. It exists because most teams building CMS-0057 PAS flows (rule effective January 1, 2027) have a request bundle long before they have a payer to test it against.

It is a linter for common, deterministic failure modes, not a conformance verdict. It checks required elements, fixed values, and intra-bundle reference integrity: the things that are cheap to get wrong and annoying to discover from a 400 with no body. It does not validate terminology bindings against value sets, run FHIRPath invariants, or replace the official HL7 validator. If pas-lint is green, run the real validator before you claim conformance.

Rules were written and verified against HL7 Da Vinci Prior Authorization Support (PAS) STU 2, v2.2.1 (FHIR R4 / 4.0.1). The version is printed by pas-lint --version and included in the JSON output.

Install / usage

Requires Node >= 18.

# one-off, from the published package (once released)
npx pas-lint path/to/bundle.json

# or clone + build locally
git clone <repo> && cd pas-lint
npm install        # builds dist/ via the prepare script
node dist/cli.js examples/valid-request-bundle.json

Options:

pas-lint <bundle.json> [options]

  --json         Emit machine-readable JSON (for CI)
  -q, --quiet    Only show errors; suppress warnings and the summary
  -v, --version  Print pas-lint and IG version
  -h, --help     Show help

Exit codes:  0 = no errors   1 = errors found   2 = usage / parse error

Example against a broken bundle:

$ pas-lint examples/broken-request-bundle.json

✗ error CLM-003  Claim.use is "claim"; the PAS Claim profile fixes it to "preauthorization".
    at Claim.use
    fix Set "use": "preauthorization".
    https://hl7.org/fhir/us/davinci-pas/StructureDefinition-profile-claim.html

✗ error REF-004  Claim.insurance[0].coverage references "Coverage/NotInBundle" but no matching Coverage entry exists in the bundle.
    at Claim.insurance[0].coverage
    fix Include the Coverage resource in the bundle; a missing Coverage is one of the most common PAS submission failures.
    https://hl7.org/fhir/us/davinci-pas/StructureDefinition-profile-pas-request-bundle.html

✗ failed: 2 errors, 0 warnings

Use as a library

import { lint } from "pas-lint";

const result = lint(JSON.parse(bundleJson));
// { ok, igVersion, errorCount, warnCount, findings: [{ id, severity, rule, ig, message, location, hint }] }
if (!result.ok) {
  for (const f of result.findings) console.log(f.id, f.message);
}

lint() never throws on malformed input: bad JSON structure produces findings, not exceptions.

CI usage

pas-lint exits non-zero when it finds errors, so it drops into CI directly:

# .github/workflows/pas.yml
name: PAS bundle lint
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npx pas-lint fixtures/*.json --json

Use --json to capture findings as an artifact, or --quiet to fail only on errors and keep the log short.

What it checks

30 deterministic checks. error = the bundle violates a required element or fixed value in the PAS profiles (or a reference that cannot resolve); warn = valid but likely a mistake or a missing best-practice declaration.

ID Severity Rule IG citation
BDL-001 error The root resource must be a Bundle. PAS Request Bundle profile
BDL-002 error Bundle.type must be "collection" for a PAS request bundle. PAS Request Bundle profile
BDL-003 error Bundle.identifier is required (1..1). PAS Request Bundle profile
BDL-004 error Bundle.timestamp is required (1..1). PAS Request Bundle profile
BDL-005 error Bundle must contain at least one entry (1..*). PAS Request Bundle profile
BDL-006 error Every Bundle.entry must have a fullUrl (1..1). PAS Request Bundle profile
BDL-007 error Bundle.entry.fullUrl values must be unique. PAS Request Bundle profile
BDL-008 error Bundle must contain exactly one PAS Claim entry (1..2 in the profile; one for a new request). PAS Request Bundle profile
BDL-009 warn Bundle.meta.profile should declare the PAS Request Bundle profile. PAS Request Bundle profile
CLM-001 warn Claim should declare the PAS Claim profile in meta.profile. PAS Claim profile
CLM-002 error Claim.status is required (1..1) and must be a valid financial-management status. PAS Claim profile
CLM-003 error Claim.use is required (1..1) and PAS fixes it to "preauthorization". PAS Claim profile
CLM-004 error Claim.type is required (1..1) with a coding. PAS Claim profile
CLM-005 warn Claim.type.coding should use the standard claim-type code system. PAS Claim profile
CLM-006 error Claim.patient is required (1..1). PAS Claim profile
CLM-007 error Claim.created is required (1..1) and must be a valid dateTime. PAS Claim profile
CLM-008 error Claim.insurer is required (1..1). PAS Claim profile
CLM-009 error Claim.provider is required (1..1). PAS Claim profile
CLM-010 error Claim.priority is required (1..1) with a coding. PAS Claim profile
CLM-011 error Claim.identifier is required (1..2), each with system and value. PAS Claim profile
CLM-012 error Claim.insurance is required (1..*); each entry needs focal and a coverage reference. PAS Claim profile
CLM-013 error Claim.item is required (1..*); each item needs productOrService and a category. PAS Claim profile
REF-001 error Claim.patient must resolve to an entry inside the bundle. PAS Request Bundle profile
REF-002 error Claim.insurer must resolve to an entry inside the bundle. PAS Request Bundle profile
REF-003 error Claim.provider must resolve to an entry inside the bundle. PAS Request Bundle profile
REF-004 error Every Claim.insurance.coverage must resolve to a Coverage entry in the bundle. PAS Request Bundle profile
REF-005 error Every Claim.careTeam.provider must resolve to an entry inside the bundle. PAS Request Bundle profile
REF-006 error Claim.supportingInfo.valueReference must resolve to an entry inside the bundle. PAS Request Bundle profile
REF-007 error Each Claim.item.careTeamSequence must point at an existing Claim.careTeam.sequence. PAS Claim profile
SUP-001 error Each Claim.supportingInfo entry must have a sequence and a category coding. PAS Claim profile

Reference resolution accepts the forms real bundles use: absolute fullUrl matches, urn:uuid: matches, and relative ResourceType/id references resolved against each entry's fullUrl or the contained resource's own id. Contained (#local) references are treated as satisfied and left to a full validator.

Scope note

This is a linter for common failure modes, not a conformance verdict. A clean run means the bundle passes 30 cheap structural checks; it does not mean the bundle is PAS-conformant. It does not validate value-set bindings, X12 278 code content, slicing, extension cardinality, or the response side of the exchange. For a conformance verdict, run the official HL7 FHIR validator with the hl7.fhir.us.davinci-pas package.

Development

npm install     # installs devDeps and builds dist/
npm run build   # tsc -> dist/
npm test        # builds, then runs vitest (real IG example bundles + one broken variant per check)

The checks live in src/checks.ts as a registry of { id, severity, rule, ig, run }. Adding a check is a single array entry plus a mutation test in test/pas-lint.test.ts; the test suite asserts that every registered check has a corresponding failing fixture.

License

MIT.


pas-lint is built by the team behind MockPayer, a hosted synthetic payer you can test CRD/DTR/PAS flows against.

About

Lint FHIR R4 Da Vinci PAS prior-auth bundles before the CMS-0057 deadline. 30 IG-cited checks, plain-English errors, CI-friendly.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages