Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 179 additions & 0 deletions apps/web/__tests__/receipt-route.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/**
* /api/receipt/[npi] — end-to-end verifier flow.
*
* The load-bearing property of this endpoint is that an external
* verifier with NO privileged access can:
*
* 1. fetch the receipt at /api/receipt/<npi>
* 2. fetch the JWKS at /.well-known/jwks.json
* 3. cryptographically validate the receipt against the JWKS
*
* The tests below execute exactly that flow in-process against mocked
* backend data, plus pin the shape contract (ES256 + kid + replay
* fields) and the `?format=download` content-disposition.
*/
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { jwtVerify, createLocalJWKSet, decodeJwt, decodeProtectedHeader } from 'jose';

function buildPassport(overrides: Record<string, unknown> = {}) {
return {
entityId: 'entity-1',
npi: '1346053246',
identity: {
displayName: 'Macie Miller',
entityType: 'PERSON',
specialty: 'PA-C',
status: 'ACTIVE',
},
readiness: { score: 50, level: 'L1', status: 'PARTIAL' },
trustPosture: { band: 'YELLOW' },
lastCheckedAt: '2026-04-01T15:00:00.000Z',
replay: {
lineageKey: 'lin_v1_aaaabbbbccccdddd',
runId: 'run_v1_1111222233334444',
schemeVersion: 'v1' as const,
},
...overrides,
};
}

function jsonResponse(body: unknown, status = 200) {
return new Response(JSON.stringify(body), {
status,
headers: { 'Content-Type': 'application/json' },
});
}

beforeEach(() => {
vi.resetModules();
vi.unstubAllGlobals();
process.env.VITALCV_ISSUER_ORIGIN = 'https://issuer.test.vitalcv.com';
process.env.BACKEND_URL = 'http://backend.test';
});

async function callReceiptRoute(npi: string, search = '') {
const mod = await import('../app/api/receipt/[npi]/route');
const req = new Request(`http://localhost/api/receipt/${npi}${search}`) as never;
return mod.GET(req, { params: Promise.resolve({ npi }) });
}

describe('/api/receipt/[npi]', () => {
it('returns 400 on a non-10-digit NPI', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(buildPassport())));
const res = await callReceiptRoute('not-a-npi');
expect(res.status).toBe(400);
});

it('returns 502 when the upstream passport is malformed', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse({ nope: true })));
const res = await callReceiptRoute('1346053246');
expect(res.status).toBe(502);
});

it('returns the backend status code when the upstream is not ok', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response('not found', { status: 404 })));
const res = await callReceiptRoute('1346053246');
expect(res.status).toBe(404);
});

it('returns 200 with application/jwt and the active kid on success', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(buildPassport())));
const res = await callReceiptRoute('1346053246');
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toMatch(/application\/jwt/);
expect(res.headers.get('x-receipt-kid')).toBeTruthy();
expect(res.headers.get('x-receipt-issuer')).toBe('did:web:issuer.test.vitalcv.com');

const jwt = await res.text();
const header = decodeProtectedHeader(jwt);
expect(header.alg).toBe('ES256');
expect(header.typ).toBe('vc+jwt');
expect(header.kid).toBeTruthy();
});

it('produces a JWT whose payload carries the W3C VC 2.0 + VitalCV claim blocks', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(buildPassport())));
const res = await callReceiptRoute('1346053246');
const jwt = await res.text();
const payload = decodeJwt(jwt) as Record<string, unknown> & {
vc: Record<string, unknown>;
vcv: Record<string, unknown>;
};

expect(payload.iss).toBe('did:web:issuer.test.vitalcv.com');
expect(payload.sub).toBe('npi:1346053246');
expect(typeof payload.jti).toBe('string');
expect((payload.jti as string).startsWith('receipt:')).toBe(true);

// VC 2.0
expect(payload.vc).toMatchObject({
type: ['VerifiableCredential', 'VitalCVTrustReceipt'],
issuer: 'did:web:issuer.test.vitalcv.com',
});

// VitalCV claim block with replay identity
expect(payload.vcv.replay).toMatchObject({
lineageKey: 'lin_v1_aaaabbbbccccdddd',
runId: 'run_v1_1111222233334444',
schemeVersion: 'v1',
});
expect(payload.vcv.checkedAt).toBe('2026-04-01T15:00:00.000Z');
expect(payload.vcv.jwksUri).toBe('https://issuer.test.vitalcv.com/.well-known/jwks.json');
expect(payload.vcv.didDocumentUri).toBe('https://issuer.test.vitalcv.com/.well-known/did.json');
});

it('produces a deterministic jti derived from replay.runId', async () => {
vi.stubGlobal('fetch', vi.fn().mockImplementation(async () => jsonResponse(buildPassport())));
const a = decodeJwt(await (await callReceiptRoute('1346053246')).text()) as { jti: string };
const b = decodeJwt(await (await callReceiptRoute('1346053246')).text()) as { jti: string };
expect(a.jti).toBe('receipt:run_v1_1111222233334444');
expect(a.jti).toBe(b.jti);
});

it('pins iat to lastCheckedAt seconds so the payload is stable across re-issuance', async () => {
vi.stubGlobal('fetch', vi.fn().mockImplementation(async () => jsonResponse(buildPassport())));
const a = decodeJwt(await (await callReceiptRoute('1346053246')).text()) as { iat: number; exp: number };
const b = decodeJwt(await (await callReceiptRoute('1346053246')).text()) as { iat: number; exp: number };
expect(a.iat).toBe(Math.floor(new Date('2026-04-01T15:00:00.000Z').getTime() / 1000));
expect(a.iat).toBe(b.iat);
expect(a.exp - a.iat).toBe(90 * 24 * 60 * 60);
});

it('end-to-end: an external verifier can validate the receipt against the published JWKS', async () => {
// 1. Receipt
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(buildPassport())));
const receiptRes = await callReceiptRoute('1346053246');
const jwt = await receiptRes.text();

// 2. JWKS (same handler the well-known route exposes)
const jwksMod = await import('../app/.well-known/jwks.json/route');
const jwksRes = await jwksMod.GET();
const jwks = (await jwksRes.json()) as { keys: Array<Record<string, unknown>> };

// 3. Verifier flow — validate signature against the JWKS
const jwkSet = createLocalJWKSet(jwks as never);
const verified = await jwtVerify(jwt, jwkSet, { algorithms: ['ES256'] });
expect(verified.payload.iss).toBe('did:web:issuer.test.vitalcv.com');
expect(verified.payload.sub).toBe('npi:1346053246');
expect(verified.protectedHeader.alg).toBe('ES256');
expect(verified.protectedHeader.kid).toBe(jwks.keys[0].kid);
});

it('?format=download adds Content-Disposition: attachment', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(buildPassport())));
const res = await callReceiptRoute('1346053246', '?format=download');
expect(res.status).toBe(200);
expect(res.headers.get('content-disposition')).toMatch(/attachment; filename="vitalcv-receipt-1346053246\.jwt"/);
});

it('omits the replay block gracefully when the backend response has no replay field', async () => {
const noReplay = buildPassport({ replay: undefined });
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(noReplay)));
const res = await callReceiptRoute('1346053246');
expect(res.status).toBe(200);
const payload = decodeJwt(await res.text()) as { vcv: Record<string, unknown>; jti: string };
expect(payload.vcv.replay).toBeNull();
// jti falls back to npi-derived form
expect(payload.jti).toBe('receipt:npi:1346053246');
});
});
171 changes: 171 additions & 0 deletions apps/web/__tests__/well-known-surfaces.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/**
* Wave 9 — four well-known surfaces pinned at RFC-correct paths.
*
* /.well-known/jwks.json (RFC 8615 + RFC 7517)
* /.well-known/did.json (W3C DID Core, did:web method)
* /.well-known/openid-credential-issuer (OID4VCI)
* /.well-known/trust-register (VitalCV institutional manifest)
*
* The tests pin:
* - HTTP 200 + the canonical content-type for each surface
* - RFC-valid shape (top-level required fields per spec)
* - Cross-surface coherence: same DID, same kid, same JWKS URI
*
* Cross-surface coherence is the load-bearing invariant — any change
* that lets the four surfaces disagree on issuer identity breaks
* external verifier resolution.
*/
import { beforeEach, describe, expect, it, vi } from 'vitest';

beforeEach(() => {
vi.resetModules();
vi.unstubAllGlobals();
process.env.VITALCV_ISSUER_ORIGIN = 'https://issuer.test.vitalcv.com';
process.env.VITALCV_RUNTIME_CHANNEL = 'staging';
});

describe('/.well-known/jwks.json (root, RFC-correct)', () => {
it('returns 200 with application/jwk-set+json and a `keys` array', async () => {
const mod = await import('../app/.well-known/jwks.json/route');
const res = await mod.GET();
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toMatch(/application\/jwk-set\+json/);
const body = await res.json();
expect(Array.isArray(body.keys)).toBe(true);
expect(body.keys.length).toBeGreaterThan(0);
const key = body.keys[0];
expect(key.kty).toBeDefined();
expect(key.alg).toBe('ES256');
expect(key.use).toBe('sig');
expect(typeof key.kid).toBe('string');
expect(key.kid.length).toBeGreaterThan(0);
// Private component must NOT be present.
expect(key.d).toBeUndefined();
});
});

describe('/.well-known/did.json (W3C DID Core, did:web)', () => {
it('returns 200 with application/did+json and a valid DID document', async () => {
const mod = await import('../app/.well-known/did.json/route');
const res = await mod.GET();
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toMatch(/application\/did\+json/);

const doc = await res.json();
expect(Array.isArray(doc['@context'])).toBe(true);
expect(doc['@context']).toContain('https://www.w3.org/ns/did/v1');
expect(typeof doc.id).toBe('string');
expect(doc.id.startsWith('did:web:')).toBe(true);
expect(Array.isArray(doc.verificationMethod)).toBe(true);
expect(doc.verificationMethod.length).toBeGreaterThan(0);

const vm = doc.verificationMethod[0];
expect(vm.id.startsWith(doc.id + '#')).toBe(true);
expect(vm.type).toBe('JsonWebKey2020');
expect(vm.controller).toBe(doc.id);
expect(vm.publicKeyJwk).toBeDefined();
expect(vm.publicKeyJwk.d).toBeUndefined();

expect(doc.assertionMethod).toContain(vm.id);
expect(doc.authentication).toContain(vm.id);

// Sibling well-known endpoints discoverable from the document.
const services = doc.service as Array<{ id: string; type: string; serviceEndpoint: string }>;
expect(services.some((s) => s.type === 'JsonWebKeySet')).toBe(true);
expect(services.some((s) => s.type === 'OID4VCIIssuer')).toBe(true);
expect(services.some((s) => s.type === 'VitalCVTrustRegister')).toBe(true);
});
});

describe('/.well-known/openid-credential-issuer (OID4VCI)', () => {
it('returns 200 with application/json and minimum required fields', async () => {
const mod = await import('../app/.well-known/openid-credential-issuer/route');
const res = await mod.GET();
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toMatch(/application\/json/);

const meta = await res.json();
expect(typeof meta.credential_issuer).toBe('string');
expect(typeof meta.credential_endpoint).toBe('string');
expect(typeof meta.jwks_uri).toBe('string');
expect(meta.jwks_uri.endsWith('/.well-known/jwks.json')).toBe(true);

// draft-13+ shape
expect(meta.credential_configurations_supported).toBeDefined();
expect(typeof meta.credential_configurations_supported).toBe('object');

// draft-11 back-compat shape
expect(Array.isArray(meta.credentials_supported)).toBe(true);
expect(meta.credentials_supported.length).toBeGreaterThan(0);

// Display block carries an issuer name.
expect(Array.isArray(meta.display)).toBe(true);
expect(meta.display[0].name).toBe('VitalCV');
});
});

describe('/.well-known/trust-register (VitalCV manifest)', () => {
it('returns 200 with application/json and schema_version pinned', async () => {
const mod = await import('../app/.well-known/trust-register/route');
const res = await mod.GET();
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toMatch(/application\/json/);

const manifest = await res.json();
expect(manifest.schema_version).toBe(1);
expect(manifest.issuer.did.startsWith('did:web:')).toBe(true);
expect(typeof manifest.issuer.origin).toBe('string');

expect(typeof manifest.signing.active_kid).toBe('string');
expect(manifest.signing.algorithm).toBe('ES256');
expect(manifest.signing.jwks_uri).toMatch(/\/\.well-known\/jwks\.json$/);
expect(manifest.signing.did_document_uri).toMatch(/\/\.well-known\/did\.json$/);

expect(manifest.runtime.channel).toBe('staging');
expect(typeof manifest.runtime.deploy_commit).toBe('string');
expect(typeof manifest.runtime.published_at).toBe('string');

expect(Array.isArray(manifest.launch_spine)).toBe(true);
expect(manifest.launch_spine.length).toBe(4);
const ids = manifest.launch_spine.map((s: { id: string }) => s.id).sort();
expect(ids).toEqual(['NPPES_API', 'OIG_LEIE', 'PECOS_PUBLIC', 'STATE_BOARD']);

expect(Array.isArray(manifest.credentials)).toBe(true);
expect(manifest.credentials.length).toBeGreaterThan(0);

// Disclaimers must be present and non-empty.
expect(Array.isArray(manifest.disclaimers)).toBe(true);
expect(manifest.disclaimers.length).toBeGreaterThan(0);
});
});

describe('cross-surface coherence (load-bearing institutional invariant)', () => {
it('all four surfaces agree on issuer DID, JWKS URI, and kid', async () => {
const [jwks, did, oidc, trust] = await Promise.all([
import('../app/.well-known/jwks.json/route').then((m) => m.GET()).then((r) => r.json()),
import('../app/.well-known/did.json/route').then((m) => m.GET()).then((r) => r.json()),
import('../app/.well-known/openid-credential-issuer/route').then((m) => m.GET()).then((r) => r.json()),
import('../app/.well-known/trust-register/route').then((m) => m.GET()).then((r) => r.json()),
]);

const kid = jwks.keys[0].kid;
expect(typeof kid).toBe('string');

// DID document's verification-method id includes the same kid.
const vm = did.verificationMethod[0];
expect(vm.id).toBe(`${did.id}#${kid}`);
expect(vm.publicKeyJwk.kid).toBe(kid);

// OID4VCI metadata points at the same JWKS.
expect(oidc.jwks_uri).toBe(trust.signing.jwks_uri);

// Trust register agrees on DID + kid.
expect(trust.issuer.did).toBe(did.id);
expect(trust.signing.active_kid).toBe(kid);
expect(trust.signing.did_document_uri).toBe(`${trust.issuer.origin}/.well-known/did.json`);

// No private key leakage in any surface.
expect(jwks.keys[0].d).toBeUndefined();
expect(did.verificationMethod[0].publicKeyJwk.d).toBeUndefined();
});
});
Loading
Loading