@cliwant/mcp-sam-gov 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +22 -9
- package/README.ko.md +22 -9
- package/README.md +70 -12
- package/dist/bea.d.ts +105 -0
- package/dist/bea.d.ts.map +1 -0
- package/dist/bea.js +303 -0
- package/dist/bea.js.map +1 -0
- package/dist/census-economic.d.ts +1 -1
- package/dist/census-economic.d.ts.map +1 -1
- package/dist/census-economic.js +12 -6
- package/dist/census-economic.js.map +1 -1
- package/dist/cms-facility.d.ts +112 -0
- package/dist/cms-facility.d.ts.map +1 -0
- package/dist/cms-facility.js +311 -0
- package/dist/cms-facility.js.map +1 -0
- package/dist/cms-hospital.d.ts +105 -0
- package/dist/cms-hospital.d.ts.map +1 -0
- package/dist/cms-hospital.js +290 -0
- package/dist/cms-hospital.js.map +1 -0
- package/dist/cms-supplier.d.ts +133 -0
- package/dist/cms-supplier.d.ts.map +1 -0
- package/dist/cms-supplier.js +414 -0
- package/dist/cms-supplier.js.map +1 -0
- package/dist/cms-utilization.d.ts +113 -0
- package/dist/cms-utilization.d.ts.map +1 -0
- package/dist/cms-utilization.js +328 -0
- package/dist/cms-utilization.js.map +1 -0
- package/dist/courtlistener.d.ts +115 -0
- package/dist/courtlistener.d.ts.map +1 -0
- package/dist/courtlistener.js +398 -0
- package/dist/courtlistener.js.map +1 -0
- package/dist/cpsc.d.ts +81 -0
- package/dist/cpsc.d.ts.map +1 -0
- package/dist/cpsc.js +283 -0
- package/dist/cpsc.js.map +1 -0
- package/dist/dol.d.ts +118 -0
- package/dist/dol.d.ts.map +1 -0
- package/dist/dol.js +421 -0
- package/dist/dol.js.map +1 -0
- package/dist/epa-envirofacts.d.ts +97 -0
- package/dist/epa-envirofacts.d.ts.map +1 -0
- package/dist/epa-envirofacts.js +292 -0
- package/dist/epa-envirofacts.js.map +1 -0
- package/dist/fred.d.ts +1 -1
- package/dist/fred.js +1 -1
- package/dist/keys.d.ts +11 -8
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +55 -8
- package/dist/keys.js.map +1 -1
- package/dist/lda.d.ts +105 -0
- package/dist/lda.d.ts.map +1 -0
- package/dist/lda.js +317 -0
- package/dist/lda.js.map +1 -0
- package/dist/nhtsa.d.ts +91 -0
- package/dist/nhtsa.d.ts.map +1 -0
- package/dist/nhtsa.js +263 -0
- package/dist/nhtsa.js.map +1 -0
- package/dist/nonprofit.d.ts +116 -0
- package/dist/nonprofit.d.ts.map +1 -0
- package/dist/nonprofit.js +342 -0
- package/dist/nonprofit.js.map +1 -0
- package/dist/openfda-device.d.ts +85 -0
- package/dist/openfda-device.d.ts.map +1 -0
- package/dist/openfda-device.js +277 -0
- package/dist/openfda-device.js.map +1 -0
- package/dist/openfda.d.ts +133 -0
- package/dist/openfda.d.ts.map +1 -0
- package/dist/openfda.js +402 -0
- package/dist/openfda.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +872 -6
- package/dist/server.js.map +1 -1
- package/package.json +2 -1
- package/src/bea.ts +372 -0
- package/src/census-economic.ts +12 -6
- package/src/cms-facility.ts +379 -0
- package/src/cms-hospital.ts +344 -0
- package/src/cms-supplier.ts +527 -0
- package/src/cms-utilization.ts +389 -0
- package/src/courtlistener.ts +465 -0
- package/src/cpsc.ts +333 -0
- package/src/dol.ts +515 -0
- package/src/epa-envirofacts.ts +342 -0
- package/src/fred.ts +1 -1
- package/src/keys.ts +60 -8
- package/src/lda.ts +385 -0
- package/src/nhtsa.ts +352 -0
- package/src/nonprofit.ts +460 -0
- package/src/openfda-device.ts +356 -0
- package/src/openfda.ts +495 -0
- package/src/server.ts +995 -6
package/dist/nhtsa.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nhtsa.ts — NHTSA VEHICLE SAFETY (api.nhtsa.gov) — the vehicle / parts /
|
|
3
|
+
* fleet supplier PRODUCT-SAFETY vetting lane (ADR-0057). Two keyless tools:
|
|
4
|
+
* • nhtsa_recalls — /recalls/recallsByVehicle?make=&model=&modelYear=
|
|
5
|
+
* • nhtsa_complaints — /complaints/complaintsByVehicle?make=&model=&modelYear=
|
|
6
|
+
* The cross-agency product-safety family alongside openFDA (medical) / CPSC
|
|
7
|
+
* (consumer goods): a manufacturer/component/safety-signal history for B2G
|
|
8
|
+
* supplier vetting.
|
|
9
|
+
*
|
|
10
|
+
* ★ KEYLESS — there is NO API key at all (no parameter, no header). This module
|
|
11
|
+
* touches NO key seam (no KEY_REGISTRY / keys.ts / API_KEYS.md). It REUSES the
|
|
12
|
+
* shared `getJson` (redirect:"error") / `driftError` fetch envelope, the `num`/
|
|
13
|
+
* `str` coercions (null-never-empty-string; a genuine 0 stays 0), and
|
|
14
|
+
* `withMeta`/`buildMeta` — and mirrors datagov-catalog.ts's fixed-host SSRF
|
|
15
|
+
* idiom + schema_drift catch-ladder verbatim.
|
|
16
|
+
*
|
|
17
|
+
* ★ PII — the complaints upstream response carries a `vin` field (an individual
|
|
18
|
+
* vehicle identifier). It is DELIBERATELY OMITTED from the curated output
|
|
19
|
+
* entirely — never surfaced, logged, or stored. The B2G value is the
|
|
20
|
+
* manufacturer / component / safety signal, NOT the VIN.
|
|
21
|
+
*
|
|
22
|
+
* ★ THE HONESTY PILLARS (P1-P4, live-verified 2026-07-15):
|
|
23
|
+
* P1: totalAvailable = `Count` (recalls) / `count` (complaints) — the REAL total.
|
|
24
|
+
* NHTSA returns the COMPLETE filtered set (no pagination), so in the normal
|
|
25
|
+
* case Count === results.length ⇒ complete:true. totalAvailable is NEVER
|
|
26
|
+
* fabricated: a PRESENT numeric Count is trusted verbatim; a MISSING Count
|
|
27
|
+
* falls back to results.length WITH an honest note (never invented).
|
|
28
|
+
* P2: results:[] (Count 0) ⇒ an HONEST EMPTY (returned:0, complete:true) — a bad
|
|
29
|
+
* make/model that returns 200+Count 0 is an honest no-match, NOT an error. A
|
|
30
|
+
* 4xx ⇒ invalid_input; a 5xx/timeout ⇒ THROW (never a fake empty); a 200
|
|
31
|
+
* non-JSON body ⇒ schema_drift.
|
|
32
|
+
* P3: booleans (crash/fire/parkIt/parkOutSide/overTheAirUpdate) preserved AS
|
|
33
|
+
* booleans (a non-boolean ⇒ null, never a fabricated false); counts
|
|
34
|
+
* (numberOfInjuries/numberOfDeaths) via `num` (a genuine 0 stays 0, NEVER
|
|
35
|
+
* null-for-0); dates as strings via `str`; Count/count via `num`.
|
|
36
|
+
* P4: `results` non-array ⇒ driftError; a Count/count that is PRESENT but a
|
|
37
|
+
* non-number ⇒ driftError (a broken total contract, never a fabricated empty).
|
|
38
|
+
* SSRF: fixed host `api.nhtsa.gov` (compile-time literal) + post-construction
|
|
39
|
+
* hostname/protocol assertion + redirect:"error"; make/model ride
|
|
40
|
+
* URLSearchParams (module-built, no raw passthrough); modelYear is
|
|
41
|
+
* ^\d{4}$; make/model are charclass-validated (letters/digits/space/hyphen,
|
|
42
|
+
* so a `../` or `%` can never reach the fixed path).
|
|
43
|
+
*/
|
|
44
|
+
import { ToolErrorCarrier } from "./errors.js";
|
|
45
|
+
import { getJson, driftError } from "./datasource.js";
|
|
46
|
+
import { num, str } from "./coerce.js";
|
|
47
|
+
import { withMeta } from "./meta.js";
|
|
48
|
+
// ─── Fixed endpoint (SSRF core — compile-time CONSTANTS) ──────────
|
|
49
|
+
export const NHTSA_HOST = "api.nhtsa.gov";
|
|
50
|
+
const RECALLS_PATH = "/recalls/recallsByVehicle";
|
|
51
|
+
const COMPLAINTS_PATH = "/complaints/complaintsByVehicle";
|
|
52
|
+
// HOST+path-only labels (→ ToolError.upstreamEndpoint). Keyless ⇒ no token can
|
|
53
|
+
// ever appear here regardless, but the labels stay host+path for consistency.
|
|
54
|
+
const RECALLS_LABEL = "nhtsa:/recalls/recallsByVehicle";
|
|
55
|
+
const COMPLAINTS_LABEL = "nhtsa:/complaints/complaintsByVehicle";
|
|
56
|
+
// ─── Input validation grammar (SSRF + injection guard) ────────────
|
|
57
|
+
// modelYear: exactly 4 digits. make/model: letters/digits/space/hyphen only —
|
|
58
|
+
// rejects `../`, `%`, `/`, `.`, quotes, so a value can never break out of the
|
|
59
|
+
// URLSearchParams-encoded query onto the fixed host/path.
|
|
60
|
+
export const NHTSA_MODEL_YEAR_RE = /^\d{4}$/;
|
|
61
|
+
export const NHTSA_MAKE_MODEL_RE = /^[A-Za-z0-9 -]+$/;
|
|
62
|
+
const KEYLESS_NOTE = "NHTSA is a keyless public API (api.nhtsa.gov) — no API key is required or accepted.";
|
|
63
|
+
const COMPLETE_SET_NOTE = "NHTSA returns the COMPLETE set of matching records for this make/model/modelYear (no pagination) — totalAvailable is the upstream Count, and returned should equal it.";
|
|
64
|
+
// ─── Shared coercions ─────────────────────────────────────────────
|
|
65
|
+
/** A genuine boolean preserved; anything else ⇒ null (never a fabricated false). */
|
|
66
|
+
function bool(x) {
|
|
67
|
+
return typeof x === "boolean" ? x : null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validate the shared make/model/modelYear inputs (belt-and-suspenders behind the
|
|
71
|
+
* server Zod; a DIRECT handler call bypasses Zod). Rejects a bad value PRE-fetch
|
|
72
|
+
* (0 network call) so a `../`/`%` can never reach the fixed host/path.
|
|
73
|
+
*/
|
|
74
|
+
function validateVehicleArgs(args, label) {
|
|
75
|
+
const checks = [
|
|
76
|
+
["make", args.make, NHTSA_MAKE_MODEL_RE],
|
|
77
|
+
["model", args.model, NHTSA_MAKE_MODEL_RE],
|
|
78
|
+
["modelYear", args.modelYear, NHTSA_MODEL_YEAR_RE],
|
|
79
|
+
];
|
|
80
|
+
for (const [name, value, re] of checks) {
|
|
81
|
+
if (typeof value !== "string" || !re.test(value)) {
|
|
82
|
+
throw new ToolErrorCarrier({
|
|
83
|
+
kind: "invalid_input",
|
|
84
|
+
retryable: false,
|
|
85
|
+
message: name === "modelYear"
|
|
86
|
+
? `Invalid modelYear ${JSON.stringify(value)} — expected a 4-digit year (^\\d{4}$), e.g. "2020".`
|
|
87
|
+
: `Invalid ${name} ${JSON.stringify(value)} — expected letters/digits/space/hyphen only (^[A-Za-z0-9 -]+$), e.g. "honda".`,
|
|
88
|
+
upstreamEndpoint: label,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// ─── SSRF-guarded fetch (fixed host + hostname assertion + redirect) ──
|
|
94
|
+
/**
|
|
95
|
+
* GET one NHTSA JSON resource on the FIXED host. Builds
|
|
96
|
+
* `https://api.nhtsa.gov${path}?${params}`, asserts the CONSTRUCTED URL's
|
|
97
|
+
* hostname === the fixed host over https (belt-and-suspenders), and sets
|
|
98
|
+
* `redirect:"error"` (fail closed on any off-host 3xx). Keyless — no header/token.
|
|
99
|
+
*/
|
|
100
|
+
async function getNhtsa(path, label, params) {
|
|
101
|
+
const url = `https://${NHTSA_HOST}${path}?${params.toString()}`;
|
|
102
|
+
const built = new URL(url);
|
|
103
|
+
if (built.hostname !== NHTSA_HOST || built.protocol !== "https:") {
|
|
104
|
+
throw new ToolErrorCarrier({
|
|
105
|
+
kind: "invalid_input",
|
|
106
|
+
retryable: false,
|
|
107
|
+
message: `Constructed NHTSA URL host ${JSON.stringify(built.hostname)} (${built.protocol}) does not match the fixed host ${JSON.stringify(NHTSA_HOST)} over https — refusing to fetch (SSRF safety).`,
|
|
108
|
+
upstreamEndpoint: label,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return getJson(url, { label, redirect: "error" });
|
|
112
|
+
}
|
|
113
|
+
/** Build the shared make/model/modelYear query (module-built; no raw passthrough). */
|
|
114
|
+
function vehicleParams(args) {
|
|
115
|
+
const params = new URLSearchParams();
|
|
116
|
+
params.set("make", args.make);
|
|
117
|
+
params.set("model", args.model);
|
|
118
|
+
params.set("modelYear", args.modelYear);
|
|
119
|
+
return params;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Fetch + parse a NHTSA resource, mirroring datagov-catalog's catch-ladder: a
|
|
123
|
+
* ToolErrorCarrier (host-assert / 4xx-5xx taxonomy) rethrows FIRST (preserving its
|
|
124
|
+
* kind); a 200 non-JSON `.json()` SyntaxError reclassifies to schema_drift; a bare
|
|
125
|
+
* error rethrows LAST.
|
|
126
|
+
*/
|
|
127
|
+
async function fetchNhtsa(path, label, args) {
|
|
128
|
+
try {
|
|
129
|
+
return await getNhtsa(path, label, vehicleParams(args));
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
if (e instanceof ToolErrorCarrier)
|
|
133
|
+
throw e;
|
|
134
|
+
if (e instanceof SyntaxError)
|
|
135
|
+
throw driftError(label, `NHTSA ${label} returned a non-JSON body at HTTP 200 — schema drift (never read as an empty result).`);
|
|
136
|
+
throw e;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Resolve the total from a Count/count field (P1/P4). A PRESENT numeric value is
|
|
141
|
+
* trusted verbatim; a MISSING (undefined/null) value falls back to results.length
|
|
142
|
+
* WITH an honest note (never fabricated); a PRESENT non-number ⇒ driftError (a
|
|
143
|
+
* broken total contract). Returns the total + the fallback flag.
|
|
144
|
+
*/
|
|
145
|
+
function resolveTotal(rawCount, returned, label) {
|
|
146
|
+
if (rawCount === undefined || rawCount === null) {
|
|
147
|
+
// P1 fallback — missing Count ⇒ results.length + an honest note.
|
|
148
|
+
return { total: returned, fellBack: true };
|
|
149
|
+
}
|
|
150
|
+
const n = num(rawCount);
|
|
151
|
+
if (n === null) {
|
|
152
|
+
// P4 — a PRESENT non-number Count is a broken contract, never a fake empty.
|
|
153
|
+
throw driftError(label, `NHTSA ${label} shape drift — the total count field is present but non-numeric.`);
|
|
154
|
+
}
|
|
155
|
+
return { total: n, fellBack: false };
|
|
156
|
+
}
|
|
157
|
+
/** Map ONE /recallsByVehicle row → the curated recall shape. Booleans via `bool`. */
|
|
158
|
+
function mapRecall(row) {
|
|
159
|
+
const r = (row ?? {});
|
|
160
|
+
return {
|
|
161
|
+
campaignNumber: str(r.NHTSACampaignNumber),
|
|
162
|
+
manufacturer: str(r.Manufacturer),
|
|
163
|
+
component: str(r.Component),
|
|
164
|
+
summary: str(r.Summary),
|
|
165
|
+
consequence: str(r.Consequence),
|
|
166
|
+
remedy: str(r.Remedy),
|
|
167
|
+
reportReceivedDate: str(r.ReportReceivedDate),
|
|
168
|
+
parkIt: bool(r.parkIt),
|
|
169
|
+
parkOutside: bool(r.parkOutSide),
|
|
170
|
+
overTheAirUpdate: bool(r.overTheAirUpdate),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Map ONE /complaintsByVehicle row → the curated complaint shape. ★The `vin` field
|
|
175
|
+
* is DELIBERATELY OMITTED (PII — never read into the output). Counts via `num` (a
|
|
176
|
+
* genuine 0 stays 0); booleans via `bool`.
|
|
177
|
+
*/
|
|
178
|
+
function mapComplaint(row) {
|
|
179
|
+
const r = (row ?? {});
|
|
180
|
+
return {
|
|
181
|
+
odiNumber: str(r.odiNumber),
|
|
182
|
+
manufacturer: str(r.manufacturer),
|
|
183
|
+
component: str(r.components),
|
|
184
|
+
summary: str(r.summary),
|
|
185
|
+
crash: bool(r.crash),
|
|
186
|
+
fire: bool(r.fire),
|
|
187
|
+
numberOfInjuries: num(r.numberOfInjuries),
|
|
188
|
+
numberOfDeaths: num(r.numberOfDeaths),
|
|
189
|
+
dateOfIncident: str(r.dateOfIncident),
|
|
190
|
+
dateComplaintFiled: str(r.dateComplaintFiled),
|
|
191
|
+
// ★ NO vin — the PII field is never surfaced, logged, or stored.
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
const FILTERS_APPLIED = ["make", "model", "modelYear"];
|
|
195
|
+
// ─── Tool: nhtsa_recalls ──────────────────────────────────────────
|
|
196
|
+
/**
|
|
197
|
+
* Fetch NHTSA safety RECALLS for a make/model/modelYear → curated recall rows +
|
|
198
|
+
* honest `_meta`. KEYLESS. totalAvailable = the upstream `Count` (the REAL total —
|
|
199
|
+
* NHTSA returns the complete set, no pagination). A no-match (Count 0) ⇒ an honest
|
|
200
|
+
* empty; a 4xx ⇒ invalid_input; a 5xx/timeout ⇒ THROW; a 200 non-JSON ⇒ drift.
|
|
201
|
+
*/
|
|
202
|
+
export async function recalls(args) {
|
|
203
|
+
validateVehicleArgs(args, RECALLS_LABEL);
|
|
204
|
+
const body = await fetchNhtsa(RECALLS_PATH, RECALLS_LABEL, args);
|
|
205
|
+
const b = (body ?? {});
|
|
206
|
+
// P4 — results MUST be an array (a missing/string/null results is drift).
|
|
207
|
+
if (!Array.isArray(b.results)) {
|
|
208
|
+
throw driftError(RECALLS_LABEL, `NHTSA ${RECALLS_LABEL} shape drift — results must be an array.`);
|
|
209
|
+
}
|
|
210
|
+
const recalls = b.results.map(mapRecall);
|
|
211
|
+
const returned = recalls.length;
|
|
212
|
+
const { total, fellBack } = resolveTotal(b.Count, returned, RECALLS_LABEL);
|
|
213
|
+
const notes = [KEYLESS_NOTE, COMPLETE_SET_NOTE];
|
|
214
|
+
if (fellBack)
|
|
215
|
+
notes.push("NHTSA did not report a Count field — totalAvailable falls back to the number of returned rows (results.length); the true total may differ.");
|
|
216
|
+
return withMeta({ recalls }, {
|
|
217
|
+
source: `${NHTSA_HOST} /recalls/recallsByVehicle (NHTSA vehicle safety recalls; keyless)`,
|
|
218
|
+
keylessMode: true,
|
|
219
|
+
returned,
|
|
220
|
+
totalAvailable: total,
|
|
221
|
+
filtersApplied: FILTERS_APPLIED,
|
|
222
|
+
filtersDropped: [],
|
|
223
|
+
fieldsUnavailable: [],
|
|
224
|
+
notes,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
// ─── Tool: nhtsa_complaints ───────────────────────────────────────
|
|
228
|
+
/**
|
|
229
|
+
* Fetch NHTSA consumer COMPLAINTS for a make/model/modelYear → curated complaint
|
|
230
|
+
* rows (★NO vin — PII omitted) + honest `_meta`. KEYLESS. totalAvailable = the
|
|
231
|
+
* upstream `count` (the REAL total). A no-match ⇒ honest empty; a 4xx ⇒
|
|
232
|
+
* invalid_input; a 5xx/timeout ⇒ THROW; a 200 non-JSON ⇒ drift.
|
|
233
|
+
*/
|
|
234
|
+
export async function complaints(args) {
|
|
235
|
+
validateVehicleArgs(args, COMPLAINTS_LABEL);
|
|
236
|
+
const body = await fetchNhtsa(COMPLAINTS_PATH, COMPLAINTS_LABEL, args);
|
|
237
|
+
const b = (body ?? {});
|
|
238
|
+
// P4 — results MUST be an array (a missing/string/null results is drift).
|
|
239
|
+
if (!Array.isArray(b.results)) {
|
|
240
|
+
throw driftError(COMPLAINTS_LABEL, `NHTSA ${COMPLAINTS_LABEL} shape drift — results must be an array.`);
|
|
241
|
+
}
|
|
242
|
+
const complaints = b.results.map(mapComplaint);
|
|
243
|
+
const returned = complaints.length;
|
|
244
|
+
const { total, fellBack } = resolveTotal(b.count, returned, COMPLAINTS_LABEL);
|
|
245
|
+
const notes = [
|
|
246
|
+
KEYLESS_NOTE,
|
|
247
|
+
COMPLETE_SET_NOTE,
|
|
248
|
+
"The NHTSA complaint VIN (an individual vehicle identifier) is intentionally EXCLUDED from this output (PII). The B2G signal is the manufacturer/component/crash/fire/injury/death safety history.",
|
|
249
|
+
];
|
|
250
|
+
if (fellBack)
|
|
251
|
+
notes.push("NHTSA did not report a count field — totalAvailable falls back to the number of returned rows (results.length); the true total may differ.");
|
|
252
|
+
return withMeta({ complaints }, {
|
|
253
|
+
source: `${NHTSA_HOST} /complaints/complaintsByVehicle (NHTSA vehicle safety complaints; keyless)`,
|
|
254
|
+
keylessMode: true,
|
|
255
|
+
returned,
|
|
256
|
+
totalAvailable: total,
|
|
257
|
+
filtersApplied: FILTERS_APPLIED,
|
|
258
|
+
filtersDropped: [],
|
|
259
|
+
fieldsUnavailable: [],
|
|
260
|
+
notes,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=nhtsa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nhtsa.js","sourceRoot":"","sources":["../src/nhtsa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nonprofit.ts — US TAX-EXEMPT NONPROFITS (IRS Form 990) — the nonprofit /
|
|
3
|
+
* grantee / subcontractor vetting lane (ADR-0060). Who a tax-exempt organization
|
|
4
|
+
* IS (EIN, NTEE code, subsection, ruling date, status) and what its Form 990
|
|
5
|
+
* FINANCIALS look like (revenue, expenses, assets, liabilities by tax year) —
|
|
6
|
+
* the 501(c) signal no contract/spending/grant/lobbying source carries.
|
|
7
|
+
*
|
|
8
|
+
* ★ PROVENANCE — THIS IS NOT A .gov API (must be disclosed). The DATA is IRS Form
|
|
9
|
+
* 990 filings — FEDERAL tax-exempt PUBLIC RECORDS — but the API is **ProPublica
|
|
10
|
+
* Nonprofit Explorer**, operated by **ProPublica** (a non-profit newsroom) which
|
|
11
|
+
* republishes those records KEYLESS. The IRS itself offers NO clean query API
|
|
12
|
+
* (only bulk downloads / a web UI). So every response's `_meta.source` AND a note
|
|
13
|
+
* name "IRS Form 990 data via ProPublica Nonprofit Explorer" — the tool NEVER
|
|
14
|
+
* presents itself as a government API.
|
|
15
|
+
*
|
|
16
|
+
* ★ KEYLESS — no key of any kind. Anonymous GETs return HTTP 200. There is NO
|
|
17
|
+
* KEY_REGISTRY / keys.ts / API_KEYS.md entry for this source.
|
|
18
|
+
*
|
|
19
|
+
* The module writes ZERO fetch/coercion/error/meta code of its own: it REUSES
|
|
20
|
+
* `getJson` (the shared fetch envelope, redirect:"error") / `driftError` /
|
|
21
|
+
* `num`·`str` (coerce.ts, null-never-0/empty) / `withMeta`·`buildMeta`.
|
|
22
|
+
*
|
|
23
|
+
* SEARCH GET https://projects.propublica.org/nonprofits/api/v2/search.json
|
|
24
|
+
* ?q=&state[id]=&ntee[id]=&page=
|
|
25
|
+
* → { total_results, organizations:[{ ein, name, sub_name, city, state,
|
|
26
|
+
* ntee_code, subseccd, score }], num_pages, cur_page, per_page,
|
|
27
|
+
* page_offset }
|
|
28
|
+
* DETAIL GET https://projects.propublica.org/nonprofits/api/v2/organizations/{ein}.json
|
|
29
|
+
* → { organization:{ ein, name, address, city, state, zipcode, ntee_code,
|
|
30
|
+
* subsection_code, ruling_date, exempt_organization_status_code,
|
|
31
|
+
* foundation_code }, filings_with_data:[{ tax_prd_yr, formtype, pdf_url,
|
|
32
|
+
* totrevenue, totfuncexpns, totassetsend, totliabend }] }
|
|
33
|
+
*
|
|
34
|
+
* ★ HONESTY (ADR-0060 P1–P5):
|
|
35
|
+
* [P1] SEARCH totalAvailable = `total_results` (the API's REAL total for the
|
|
36
|
+
* query) — NEVER organizations.length. Page pagination (page is 0-based):
|
|
37
|
+
* hasMore = (cur_page+1) < num_pages; the next page number is surfaced in
|
|
38
|
+
* a note. DETAIL totalAvailable = filings.length (the COMPLETE filing set
|
|
39
|
+
* from the one detail doc — no pagination). Reverting the search total to
|
|
40
|
+
* organizations.length must go RED.
|
|
41
|
+
* [P2] SEARCH a genuine no-match (organizations:[]) ⇒ honest empty (returned:0,
|
|
42
|
+
* complete:true). DETAIL an unknown EIN (HTTP 404) ⇒ not_found (NEVER a
|
|
43
|
+
* fabricated empty org). A 4xx ⇒ invalid_input; a 5xx/timeout ⇒
|
|
44
|
+
* upstream_unavailable THROW; a 200 non-JSON ⇒ schema_drift.
|
|
45
|
+
* [P3] The four Form 990 figures (totrevenue/totfuncexpns/totassetsend/
|
|
46
|
+
* totliabend) ride `num()` — a genuine 0 STAYS 0, an absent figure ⇒ null
|
|
47
|
+
* (NEVER 0-faked). EIN + the codes are strings; ruling_date is a string.
|
|
48
|
+
* [P4] SEARCH `organizations` non-array OR `total_results` non-number ⇒
|
|
49
|
+
* driftError. DETAIL `organization` non-object OR `filings_with_data`
|
|
50
|
+
* non-array ⇒ driftError (never a fabricated empty/total).
|
|
51
|
+
* [SSRF] fixed host `projects.propublica.org`; a post-construction hostname/
|
|
52
|
+
* protocol assert + `redirect:"error"`; the query VALUES ride
|
|
53
|
+
* URLSearchParams (incl. the `state[id]`/`ntee[id]` bracket keys);
|
|
54
|
+
* `ein` charclass `^\d{1,9}$` (path segment); `state` `^[A-Za-z]{2}$`;
|
|
55
|
+
* `ntee` an integer 1..10.
|
|
56
|
+
*/
|
|
57
|
+
import { num } from "./coerce.js";
|
|
58
|
+
import { type MetaBundle } from "./meta.js";
|
|
59
|
+
export { num };
|
|
60
|
+
export declare const NONPROFIT_HOST = "projects.propublica.org";
|
|
61
|
+
export type NonprofitOrgSummary = {
|
|
62
|
+
ein: string | null;
|
|
63
|
+
name: string | null;
|
|
64
|
+
city: string | null;
|
|
65
|
+
state: string | null;
|
|
66
|
+
nteeCode: string | null;
|
|
67
|
+
subsectionCode: string | null;
|
|
68
|
+
};
|
|
69
|
+
export type NonprofitOrganization = {
|
|
70
|
+
ein: string | null;
|
|
71
|
+
name: string | null;
|
|
72
|
+
address: string | null;
|
|
73
|
+
city: string | null;
|
|
74
|
+
state: string | null;
|
|
75
|
+
zip: string | null;
|
|
76
|
+
nteeCode: string | null;
|
|
77
|
+
subsectionCode: string | null;
|
|
78
|
+
rulingDate: string | null;
|
|
79
|
+
statusCode: string | null;
|
|
80
|
+
};
|
|
81
|
+
export type NonprofitFiling = {
|
|
82
|
+
taxYear: number | null;
|
|
83
|
+
formType: string | null;
|
|
84
|
+
revenueUsd: number | null;
|
|
85
|
+
expensesUsd: number | null;
|
|
86
|
+
assetsUsd: number | null;
|
|
87
|
+
liabilitiesUsd: number | null;
|
|
88
|
+
pdfUrl: string | null;
|
|
89
|
+
};
|
|
90
|
+
export type NonprofitSearchArgs = {
|
|
91
|
+
query?: string;
|
|
92
|
+
state?: string;
|
|
93
|
+
ntee?: number;
|
|
94
|
+
page?: number;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Search US tax-exempt nonprofits (IRS Form 990) via ProPublica Nonprofit Explorer
|
|
98
|
+
* (`/nonprofits/api/v2/search.json`) → curated org summaries + honest `_meta`.
|
|
99
|
+
* KEYLESS. ★PROVENANCE: this is ProPublica (a non-profit newsroom) republishing
|
|
100
|
+
* IRS Form 990 public records — NOT a .gov API. ★totalAvailable is the API's REAL
|
|
101
|
+
* `total_results` — never organizations.length; page-based (0-indexed) pagination.
|
|
102
|
+
*/
|
|
103
|
+
export declare function search(args: NonprofitSearchArgs): Promise<MetaBundle>;
|
|
104
|
+
export type NonprofitFinancialsArgs = {
|
|
105
|
+
ein: string;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Fetch ONE nonprofit's IRS Form 990 profile + financials via ProPublica Nonprofit
|
|
109
|
+
* Explorer (`/nonprofits/api/v2/organizations/{ein}.json`) → curated organization +
|
|
110
|
+
* filings + honest `_meta`. KEYLESS. ★PROVENANCE: ProPublica (a non-profit newsroom)
|
|
111
|
+
* republishing IRS Form 990 public records — NOT a .gov API. An unknown EIN (HTTP
|
|
112
|
+
* 404) ⇒ not_found (never a fabricated empty org). The four Form 990 figures ride
|
|
113
|
+
* num() (null-never-0). totalAvailable = filings.length (the COMPLETE set).
|
|
114
|
+
*/
|
|
115
|
+
export declare function financials(args: NonprofitFinancialsArgs): Promise<MetaBundle>;
|
|
116
|
+
//# sourceMappingURL=nonprofit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonprofit.d.ts","sourceRoot":"","sources":["../src/nonprofit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAIH,OAAO,EAAE,GAAG,EAAO,MAAM,aAAa,CAAC;AACvC,OAAO,EAAY,KAAK,UAAU,EAAqB,MAAM,WAAW,CAAC;AAIzE,OAAO,EAAE,GAAG,EAAE,CAAC;AAGf,eAAO,MAAM,cAAc,4BAA4B,CAAC;AAiCxD,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAiBF,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAmCF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CA4H3E;AAGD,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,UAAU,CAAC,CAoGrB"}
|