@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/cpsc.js
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cpsc.ts — CPSC CONSUMER-PRODUCT RECALLS (www.saferproducts.gov) — the consumer
|
|
3
|
+
* goods / import product-safety vetting lane (ADR-0058). ONE keyless tool:
|
|
4
|
+
* • cpsc_recalls — /RestWebServices/Recall?format=json + date/product/manufacturer/
|
|
5
|
+
* recallNumber filters.
|
|
6
|
+
* The third leg of the cross-agency product-safety family alongside NHTSA (vehicles)
|
|
7
|
+
* and openFDA (medical/food): a manufacturer / product / hazard recall history for
|
|
8
|
+
* B2G supplier and import 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 `str`
|
|
13
|
+
* coercion (null-never-empty-string), and `withMeta`/`buildMeta` — and mirrors
|
|
14
|
+
* nhtsa.ts / datagov-catalog.ts's fixed-host SSRF idiom + schema_drift
|
|
15
|
+
* catch-ladder verbatim.
|
|
16
|
+
*
|
|
17
|
+
* ★ THE HONESTY PILLARS (P1-P5, live-verified 2026-07-15):
|
|
18
|
+
* P1: the /Recall response is a BARE JSON ARRAY with NO count field and NO server
|
|
19
|
+
* pagination — it returns the COMPLETE set matching the filter. So
|
|
20
|
+
* totalAvailable = results.length and complete:true, WITH a disclosing note
|
|
21
|
+
* that CPSC reports no total-count field / no pagination. A total is NEVER
|
|
22
|
+
* fabricated (there is no upstream total to trust; the honest total is the
|
|
23
|
+
* length of the complete set).
|
|
24
|
+
* P2: an empty array `[]` ⇒ an HONEST EMPTY (returned:0, complete:true) — a filter
|
|
25
|
+
* that matches nothing is an honest no-match, NOT an error. A 4xx ⇒
|
|
26
|
+
* invalid_input; a 5xx/timeout ⇒ THROW (never a fake empty); a 200 non-JSON
|
|
27
|
+
* body OR a non-array body ⇒ schema_drift (never a fabricated empty).
|
|
28
|
+
* P3: dates stay STRINGS (via `str`); NumberOfUnits is free text ("About 6,500")
|
|
29
|
+
* kept as a STRING; nested arrays (Products/Manufacturers/Retailers/Hazards/
|
|
30
|
+
* Remedies/Injuries/ManufacturerCountries) are flattened to string arrays by
|
|
31
|
+
* extracting each object's `.Name` (★ManufacturerCountries uses `.Country`,
|
|
32
|
+
* NOT `.Name`), SKIPPING an empty `{}` object (never a fabricated entry); a
|
|
33
|
+
* genuinely-absent nested array ⇒ []; null-never-empty-string throughout.
|
|
34
|
+
* P4: the top-level body MUST be an array — a non-array (object/string/null) ⇒
|
|
35
|
+
* driftError (a broken response contract, never a fabricated empty).
|
|
36
|
+
* DEFAULT-WINDOW: with NO filter given, the unfiltered result is huge, so the tool
|
|
37
|
+
* defaults RecallDateStart to ~90 days ago and DISCLOSES the default in a note
|
|
38
|
+
* — it NEVER silently fetches the whole dataset.
|
|
39
|
+
* SSRF: fixed host `www.saferproducts.gov` (compile-time literal) + post-construction
|
|
40
|
+
* hostname/protocol assertion + redirect:"error"; every filter rides a
|
|
41
|
+
* module-built URLSearchParams (no raw passthrough); dates are ^\d{4}-\d{2}-\d{2}$;
|
|
42
|
+
* recallNumber is charclass-validated (letters/digits/hyphen only), so a
|
|
43
|
+
* `../` or `%` can never reach the fixed path.
|
|
44
|
+
*/
|
|
45
|
+
import { ToolErrorCarrier } from "./errors.js";
|
|
46
|
+
import { getJson, driftError } from "./datasource.js";
|
|
47
|
+
import { str } from "./coerce.js";
|
|
48
|
+
import { withMeta } from "./meta.js";
|
|
49
|
+
// ─── Fixed endpoint (SSRF core — compile-time CONSTANTS) ──────────
|
|
50
|
+
export const CPSC_HOST = "www.saferproducts.gov";
|
|
51
|
+
const CPSC_RECALL_PATH = "/RestWebServices/Recall";
|
|
52
|
+
// HOST+path-only label (→ ToolError.upstreamEndpoint). Keyless ⇒ no token can ever
|
|
53
|
+
// appear here regardless, but the label stays host+path for consistency.
|
|
54
|
+
const CPSC_RECALL_LABEL = "cpsc:/RestWebServices/Recall";
|
|
55
|
+
// ─── Input validation grammar (SSRF + injection guard) ────────────
|
|
56
|
+
// dates: strict YYYY-MM-DD. recallNumber: letters/digits/hyphen only — rejects
|
|
57
|
+
// `../`, `%`, `/`, `.`, spaces, quotes, so a value can never break out of the
|
|
58
|
+
// URLSearchParams-encoded query onto the fixed host/path.
|
|
59
|
+
export const CPSC_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
60
|
+
export const CPSC_RECALL_NUMBER_RE = /^[A-Za-z0-9-]+$/;
|
|
61
|
+
// The default recent-window span (days) applied when NO filter is given, so an
|
|
62
|
+
// unbounded whole-dataset fetch never happens silently.
|
|
63
|
+
const CPSC_DEFAULT_WINDOW_DAYS = 90;
|
|
64
|
+
const KEYLESS_NOTE = "CPSC SaferProducts is a keyless public API (www.saferproducts.gov) — no API key is required or accepted.";
|
|
65
|
+
// The P1 load-bearing honesty caveat carried on EVERY response.
|
|
66
|
+
const CPSC_NO_PAGINATION_NOTE = "CPSC returns the complete matching set (no server pagination or total-count field) — totalAvailable is the number of returned recalls (the size of the complete set), not an upstream-reported total.";
|
|
67
|
+
// ─── Nested-array flatteners (P3) ─────────────────────────────────
|
|
68
|
+
/**
|
|
69
|
+
* Flatten a CPSC nested array (Products/Manufacturers/Retailers/Hazards/Remedies/
|
|
70
|
+
* Injuries/ManufacturerCountries) to a string[] by extracting `field` from each
|
|
71
|
+
* object via `str` (null-never-empty-string). An empty `{}` object (or one whose
|
|
72
|
+
* `field` is absent/blank) is SKIPPED — never a fabricated entry. A non-array
|
|
73
|
+
* (absent nested array) ⇒ [].
|
|
74
|
+
*/
|
|
75
|
+
function extractField(x, field) {
|
|
76
|
+
if (!Array.isArray(x))
|
|
77
|
+
return [];
|
|
78
|
+
const out = [];
|
|
79
|
+
for (const el of x) {
|
|
80
|
+
if (el === null || typeof el !== "object")
|
|
81
|
+
continue;
|
|
82
|
+
const v = str(el[field]);
|
|
83
|
+
if (v !== null)
|
|
84
|
+
out.push(v);
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The recall-level numberOfUnits (P3): CPSC carries NumberOfUnits per PRODUCT as
|
|
90
|
+
* FREE TEXT ("About 6,500"), so this returns the FIRST product's non-blank
|
|
91
|
+
* NumberOfUnits as a STRING (never numerically coerced), or null when none is
|
|
92
|
+
* present (null-never-empty-string).
|
|
93
|
+
*/
|
|
94
|
+
function firstNumberOfUnits(products) {
|
|
95
|
+
if (!Array.isArray(products))
|
|
96
|
+
return null;
|
|
97
|
+
for (const p of products) {
|
|
98
|
+
if (p === null || typeof p !== "object")
|
|
99
|
+
continue;
|
|
100
|
+
const v = str(p.NumberOfUnits);
|
|
101
|
+
if (v !== null)
|
|
102
|
+
return v;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Map ONE /Recall row → the curated recall shape. Scalars via `str`
|
|
108
|
+
* (null-never-empty-string; dates stay strings). Nested arrays flattened via
|
|
109
|
+
* `extractField` on `.Name` — EXCEPT ManufacturerCountries, which carries `.Country`.
|
|
110
|
+
*/
|
|
111
|
+
function mapRecall(row) {
|
|
112
|
+
const r = (row ?? {});
|
|
113
|
+
return {
|
|
114
|
+
recallNumber: str(r.RecallNumber),
|
|
115
|
+
recallDate: str(r.RecallDate),
|
|
116
|
+
title: str(r.Title),
|
|
117
|
+
description: str(r.Description),
|
|
118
|
+
url: str(r.URL),
|
|
119
|
+
products: extractField(r.Products, "Name"),
|
|
120
|
+
numberOfUnits: firstNumberOfUnits(r.Products),
|
|
121
|
+
manufacturers: extractField(r.Manufacturers, "Name"),
|
|
122
|
+
retailers: extractField(r.Retailers, "Name"),
|
|
123
|
+
hazards: extractField(r.Hazards, "Name"),
|
|
124
|
+
remedies: extractField(r.Remedies, "Name"),
|
|
125
|
+
injuries: extractField(r.Injuries, "Name"),
|
|
126
|
+
// ★ ManufacturerCountries objects carry `Country`, not `Name` (live-verified).
|
|
127
|
+
manufacturerCountries: extractField(r.ManufacturerCountries, "Country"),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Validate the optional inputs PRE-fetch (0 network call). A DIRECT handler call
|
|
132
|
+
* bypasses the server Zod, so re-guard the SSRF-relevant grammars here: dates are
|
|
133
|
+
* ^\d{4}-\d{2}-\d{2}$; recallNumber is letters/digits/hyphen only. productName /
|
|
134
|
+
* manufacturer are free text (they ride URLSearchParams-encoded, so injection is
|
|
135
|
+
* neutralized by encoding — no charclass needed, but they are validated as strings).
|
|
136
|
+
*/
|
|
137
|
+
function validateArgs(args) {
|
|
138
|
+
const dateChecks = [
|
|
139
|
+
["dateStart", args.dateStart],
|
|
140
|
+
["dateEnd", args.dateEnd],
|
|
141
|
+
];
|
|
142
|
+
for (const [name, value] of dateChecks) {
|
|
143
|
+
if (value !== undefined && (typeof value !== "string" || !CPSC_DATE_RE.test(value))) {
|
|
144
|
+
throw new ToolErrorCarrier({
|
|
145
|
+
kind: "invalid_input",
|
|
146
|
+
retryable: false,
|
|
147
|
+
message: `Invalid ${name} ${JSON.stringify(value)} — expected a YYYY-MM-DD date (^\\d{4}-\\d{2}-\\d{2}$), e.g. "2025-01-01".`,
|
|
148
|
+
upstreamEndpoint: CPSC_RECALL_LABEL,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (args.recallNumber !== undefined &&
|
|
153
|
+
(typeof args.recallNumber !== "string" || !CPSC_RECALL_NUMBER_RE.test(args.recallNumber))) {
|
|
154
|
+
throw new ToolErrorCarrier({
|
|
155
|
+
kind: "invalid_input",
|
|
156
|
+
retryable: false,
|
|
157
|
+
message: `Invalid recallNumber ${JSON.stringify(args.recallNumber)} — expected letters/digits/hyphen only (^[A-Za-z0-9-]+$), e.g. "25088".`,
|
|
158
|
+
upstreamEndpoint: CPSC_RECALL_LABEL,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
for (const [name, value] of [
|
|
162
|
+
["productName", args.productName],
|
|
163
|
+
["manufacturer", args.manufacturer],
|
|
164
|
+
]) {
|
|
165
|
+
if (value !== undefined && typeof value !== "string") {
|
|
166
|
+
throw new ToolErrorCarrier({
|
|
167
|
+
kind: "invalid_input",
|
|
168
|
+
retryable: false,
|
|
169
|
+
message: `Invalid ${name} — expected a string.`,
|
|
170
|
+
upstreamEndpoint: CPSC_RECALL_LABEL,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ─── SSRF-guarded fetch (fixed host + hostname assertion + redirect) ──
|
|
176
|
+
/**
|
|
177
|
+
* GET the CPSC /Recall JSON on the FIXED host. Builds
|
|
178
|
+
* `https://www.saferproducts.gov/RestWebServices/Recall?${params}`, asserts the
|
|
179
|
+
* CONSTRUCTED URL's hostname === the fixed host over https (belt-and-suspenders),
|
|
180
|
+
* and sets `redirect:"error"` (fail closed on any off-host 3xx). Keyless — no
|
|
181
|
+
* header/token.
|
|
182
|
+
*/
|
|
183
|
+
async function getCpsc(params) {
|
|
184
|
+
const url = `https://${CPSC_HOST}${CPSC_RECALL_PATH}?${params.toString()}`;
|
|
185
|
+
const built = new URL(url);
|
|
186
|
+
if (built.hostname !== CPSC_HOST || built.protocol !== "https:") {
|
|
187
|
+
throw new ToolErrorCarrier({
|
|
188
|
+
kind: "invalid_input",
|
|
189
|
+
retryable: false,
|
|
190
|
+
message: `Constructed CPSC URL host ${JSON.stringify(built.hostname)} (${built.protocol}) does not match the fixed host ${JSON.stringify(CPSC_HOST)} over https — refusing to fetch (SSRF safety).`,
|
|
191
|
+
upstreamEndpoint: CPSC_RECALL_LABEL,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return getJson(url, { label: CPSC_RECALL_LABEL, redirect: "error" });
|
|
195
|
+
}
|
|
196
|
+
/** Compute an ISO YYYY-MM-DD `days` days before now (the default-window start). */
|
|
197
|
+
function daysAgoIso(days) {
|
|
198
|
+
return new Date(Date.now() - days * 86_400_000).toISOString().slice(0, 10);
|
|
199
|
+
}
|
|
200
|
+
// ─── Tool: cpsc_recalls ───────────────────────────────────────────
|
|
201
|
+
/**
|
|
202
|
+
* Fetch CPSC consumer-product RECALLS → curated recall rows + honest `_meta`.
|
|
203
|
+
* KEYLESS. All filters are optional; with NO filter given, RecallDateStart defaults
|
|
204
|
+
* to ~90 days ago (disclosed in a note) so the whole dataset is never silently
|
|
205
|
+
* fetched. The response is a bare array with no total-count field / no pagination
|
|
206
|
+
* ⇒ totalAvailable = the number of returned recalls, complete:true. An empty array
|
|
207
|
+
* ⇒ an honest empty; a 4xx ⇒ invalid_input; a 5xx/timeout ⇒ THROW; a 200 non-JSON
|
|
208
|
+
* OR a non-array body ⇒ schema_drift.
|
|
209
|
+
*/
|
|
210
|
+
export async function recalls(args) {
|
|
211
|
+
validateArgs(args);
|
|
212
|
+
// ── Build the query from VALIDATED typed args, key-by-key (SSRF: no raw
|
|
213
|
+
// passthrough). format=json is ALWAYS appended. ──
|
|
214
|
+
const params = new URLSearchParams();
|
|
215
|
+
params.set("format", "json");
|
|
216
|
+
const filtersApplied = [];
|
|
217
|
+
if (args.dateStart !== undefined) {
|
|
218
|
+
params.set("RecallDateStart", args.dateStart);
|
|
219
|
+
filtersApplied.push("dateStart");
|
|
220
|
+
}
|
|
221
|
+
if (args.dateEnd !== undefined) {
|
|
222
|
+
params.set("RecallDateEnd", args.dateEnd);
|
|
223
|
+
filtersApplied.push("dateEnd");
|
|
224
|
+
}
|
|
225
|
+
if (args.productName !== undefined) {
|
|
226
|
+
params.set("ProductName", args.productName);
|
|
227
|
+
filtersApplied.push("productName");
|
|
228
|
+
}
|
|
229
|
+
if (args.manufacturer !== undefined) {
|
|
230
|
+
params.set("Manufacturer", args.manufacturer);
|
|
231
|
+
filtersApplied.push("manufacturer");
|
|
232
|
+
}
|
|
233
|
+
if (args.recallNumber !== undefined) {
|
|
234
|
+
params.set("RecallNumber", args.recallNumber);
|
|
235
|
+
filtersApplied.push("recallNumber");
|
|
236
|
+
}
|
|
237
|
+
// ── DEFAULT-WINDOW: with NO filter, an unbounded fetch would return the WHOLE
|
|
238
|
+
// dataset. Bound it to a ~90-day recent window (RecallDateStart) and DISCLOSE
|
|
239
|
+
// the default — never silently fetch everything. ──
|
|
240
|
+
const notes = [KEYLESS_NOTE, CPSC_NO_PAGINATION_NOTE];
|
|
241
|
+
let defaultWindowApplied = false;
|
|
242
|
+
if (filtersApplied.length === 0) {
|
|
243
|
+
const defaultStart = daysAgoIso(CPSC_DEFAULT_WINDOW_DAYS);
|
|
244
|
+
params.set("RecallDateStart", defaultStart);
|
|
245
|
+
defaultWindowApplied = true;
|
|
246
|
+
notes.push(`No filter was provided — to avoid silently fetching the ENTIRE recall dataset, results are bounded to a default recent window: RecallDateStart=${defaultStart} (~${CPSC_DEFAULT_WINDOW_DAYS} days ago). Pass dateStart/dateEnd, productName, manufacturer, or recallNumber for a scoped query.`);
|
|
247
|
+
}
|
|
248
|
+
// ── The typed catch-ladder (nhtsa.ts / datagov-catalog.ts shape, VERBATIM):
|
|
249
|
+
// a ToolErrorCarrier (host-assert / 4xx-5xx taxonomy) rethrows FIRST
|
|
250
|
+
// (preserving its kind); a 200 non-JSON `.json()` SyntaxError reclassifies to
|
|
251
|
+
// schema_drift; a bare error rethrows LAST. ──
|
|
252
|
+
let body;
|
|
253
|
+
try {
|
|
254
|
+
body = await getCpsc(params);
|
|
255
|
+
}
|
|
256
|
+
catch (e) {
|
|
257
|
+
if (e instanceof ToolErrorCarrier)
|
|
258
|
+
throw e;
|
|
259
|
+
if (e instanceof SyntaxError)
|
|
260
|
+
throw driftError(CPSC_RECALL_LABEL, "CPSC /RestWebServices/Recall returned a non-JSON body at HTTP 200 — schema drift (never read as an empty result).");
|
|
261
|
+
throw e;
|
|
262
|
+
}
|
|
263
|
+
// ── P4: the top-level body MUST be an array (a non-array object/string/null is
|
|
264
|
+
// drift, never a fabricated empty). ──
|
|
265
|
+
if (!Array.isArray(body)) {
|
|
266
|
+
throw driftError(CPSC_RECALL_LABEL, "CPSC /RestWebServices/Recall shape drift — the response must be a bare JSON array.");
|
|
267
|
+
}
|
|
268
|
+
const recalls = body.map(mapRecall);
|
|
269
|
+
const returned = recalls.length;
|
|
270
|
+
return withMeta({ recalls }, {
|
|
271
|
+
source: `${CPSC_HOST} /RestWebServices/Recall (CPSC consumer-product recalls; keyless)`,
|
|
272
|
+
keylessMode: true,
|
|
273
|
+
returned,
|
|
274
|
+
// P1 — no upstream total-count field / no pagination: the complete set IS the
|
|
275
|
+
// returned rows, so totalAvailable = returned and complete:true (derived).
|
|
276
|
+
totalAvailable: returned,
|
|
277
|
+
filtersApplied: defaultWindowApplied ? ["dateStart(default)"] : filtersApplied,
|
|
278
|
+
filtersDropped: [],
|
|
279
|
+
fieldsUnavailable: [],
|
|
280
|
+
notes,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=cpsc.js.map
|
package/dist/cpsc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpsc.js","sourceRoot":"","sources":["../src/cpsc.ts"],"names":[],"mappings":"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"}
|
package/dist/dol.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dol.ts — US Department of Labor Data API v4 (apiprod.dol.gov) — the LABOR
|
|
3
|
+
* ENFORCEMENT lane (ADR-0053). WHD wage/hour violations, OSHA inspections, ILAB
|
|
4
|
+
* child/forced-labor reports, MSHA mine safety … — the compliance/enforcement
|
|
5
|
+
* signal no contract/spending/market source carries.
|
|
6
|
+
*
|
|
7
|
+
* TWO tools with a DELIBERATE key split (the honest reflection of the live API):
|
|
8
|
+
* • `dol_list_datasets` (KEYLESS) — GET /v4/datasets. The dataset CATALOG (and
|
|
9
|
+
* /v4/agencies) is keyless; this tool needs NO key. It returns the machine
|
|
10
|
+
* inventory (name / tablename / api_url / agency / …) you page + filter to find
|
|
11
|
+
* an endpoint, then feed its `apiUrl` into dol_get_dataset.
|
|
12
|
+
* • `dol_get_dataset` (KEY-REQUIRED, DOL_API_KEY) — GET
|
|
13
|
+
* /v4/get/{agency}/{endpoint}/json?… . The DATA endpoint has NO keyless tier, so
|
|
14
|
+
* with NO `DOL_API_KEY` this tool THROWS an invalid_input config error BEFORE any
|
|
15
|
+
* fetch (0 network call; the message names DOL_API_KEY + dataportal.dol.gov/registration).
|
|
16
|
+
* So DOL is the 4th REQUIRED key — but ONLY for the data tool; the catalog tool
|
|
17
|
+
* (and every other tool on the server) stays keyless.
|
|
18
|
+
*
|
|
19
|
+
* ★LIVE-VERIFIED WIRE FACTS (2026-07-15):
|
|
20
|
+
* - Host `apiprod.dol.gov` (AWS API Gateway) + base `/v4`.
|
|
21
|
+
* - /v4/datasets is KEYLESS 200 → `{ datasets:[…], meta:{ current_page, next_page,
|
|
22
|
+
* prev_page, total_pages, total_count } }`. `limit` is the PER-PAGE size (limit=1000
|
|
23
|
+
* returns the whole 42-row catalog in one page, total_pages:1); server-side agency
|
|
24
|
+
* filtering is NOT honored (verified: ?agency=ILAB still returned the full 42) — so
|
|
25
|
+
* agency/query filtering is CLIENT-SIDE over the fetched catalog.
|
|
26
|
+
* - The DATA route is the QUERY-STYLE form `/v4/get/{agency}/{endpoint}/{format}?…`
|
|
27
|
+
* (NOT the path-style `/…/limit/N/offset/O/format/json`): the query-style URL
|
|
28
|
+
* reached the DOL app and returned a proper `401 {"…key…missing…"}` on a bad key,
|
|
29
|
+
* whereas the path-style URL only ever hit the AWS gateway's generic
|
|
30
|
+
* `403 {"message":"Missing Authentication Token"}` (an unmatched route). The DOL
|
|
31
|
+
* API User Guide (dataportal.dol.gov/pdf/dol-api-user-guide.pdf) confirms the
|
|
32
|
+
* `/get/<agency>/<api_url>/<format>?limit=&offset=&filter_object=&…` template and
|
|
33
|
+
* that `<endpoint>` is the dataset's **api_url** (NOT its tablename).
|
|
34
|
+
*
|
|
35
|
+
* ★UNVERIFIED (key-gated — coded DEFENSIVELY, honestly disclosed): the DATA response
|
|
36
|
+
* body shape could not be observed live (every /v4/get call is 401 without a real
|
|
37
|
+
* key, and the User Guide shows no body example). So `dol_get_dataset` accepts EITHER
|
|
38
|
+
* a bare row array `[…]` OR `{ data:[…] }` OR `{ results:[…] }`; a top-level count
|
|
39
|
+
* (`total_count`/`total`/`count`, or `meta.total_count`) is used for totalAvailable
|
|
40
|
+
* ONLY if actually present, else `totalAvailable = null` (an HONEST unknown — never
|
|
41
|
+
* `returned` passed off as the total). Records are surfaced VERBATIM (each dataset
|
|
42
|
+
* has its own enforcement schema; blind coercion would distort compliance data — a
|
|
43
|
+
* JSON `0` stays `0`, a JSON `null` stays `null`, field names are preserved as-is).
|
|
44
|
+
*
|
|
45
|
+
* ★HONESTY (ADR-0053 P1–P4 + KEY + SSRF):
|
|
46
|
+
* [KEY] dol_get_dataset with NO DOL_API_KEY ⇒ invalid_input THROW pre-fetch (0
|
|
47
|
+
* fetch); the message names DOL_API_KEY + dataportal.dol.gov/registration. The key rides the
|
|
48
|
+
* `X-API-KEY` HEADER ONLY — NEVER the URL / label / _meta / notes / a log (the
|
|
49
|
+
* K-test). dol_list_datasets is keyless (no key read, no header).
|
|
50
|
+
* [P1] catalog: totalAvailable = meta.total_count (the API's real catalog total)
|
|
51
|
+
* for an unfiltered scan; when a CLIENT-SIDE filter is applied it is the
|
|
52
|
+
* filtered-set size (exact — the whole catalog is fetched in one page). data:
|
|
53
|
+
* totalAvailable = a real count field when present, else null; offset/limit
|
|
54
|
+
* pagination in both.
|
|
55
|
+
* [P2] data: 401/403 (missing/invalid key) ⇒ invalid_input reclassified with the
|
|
56
|
+
* DOL_API_KEY guidance (the AWS "Missing Authentication Token" is a key problem
|
|
57
|
+
* here) — never empty. 400 ⇒ invalid_input. empty rows ⇒ honest empty
|
|
58
|
+
* (returned:0). 429 ⇒ rate_limited THROW (Retry-After honored). 5xx/timeout ⇒
|
|
59
|
+
* upstream_unavailable THROW. 200 non-JSON ⇒ schema_drift.
|
|
60
|
+
* [P3] records verbatim (null-never-0 comes for free — JSON preserves 0/null and
|
|
61
|
+
* every original field name; the tool never introduces a fabricated 0).
|
|
62
|
+
* [P4] the expected array (catalog `datasets`; data's row array) absent/non-array
|
|
63
|
+
* ⇒ driftError. A ToolErrorCarrier (401/5xx/…) is a P2 outcome, rethrown
|
|
64
|
+
* BEFORE the drift check.
|
|
65
|
+
* [SSRF] fixed host `apiprod.dol.gov` + a post-construction hostname/https assert +
|
|
66
|
+
* `redirect:"error"`; agency/endpoint charclass `^[A-Za-z0-9_]+$` (they ride
|
|
67
|
+
* in the PATH); limit/offset integers; filterValue/fields ride URLSearchParams;
|
|
68
|
+
* the key rides the X-API-KEY header only.
|
|
69
|
+
*/
|
|
70
|
+
import { num } from "./coerce.js";
|
|
71
|
+
import { type MetaBundle } from "./meta.js";
|
|
72
|
+
export { num };
|
|
73
|
+
export declare const DOL_HOST = "apiprod.dol.gov";
|
|
74
|
+
/** Read DOL_API_KEY from env; trim; return the value or undefined (unset/blank). */
|
|
75
|
+
export declare function dolApiKey(): string | undefined;
|
|
76
|
+
export type DolListDatasetsArgs = {
|
|
77
|
+
agency?: string;
|
|
78
|
+
query?: string;
|
|
79
|
+
limit?: number;
|
|
80
|
+
offset?: number;
|
|
81
|
+
};
|
|
82
|
+
export type DolDataset = {
|
|
83
|
+
name: string | null;
|
|
84
|
+
tablename: string | null;
|
|
85
|
+
apiUrl: string | null;
|
|
86
|
+
agency: string | null;
|
|
87
|
+
agencyAbbr: string | null;
|
|
88
|
+
description: string | null;
|
|
89
|
+
frequency: string | null;
|
|
90
|
+
datasetType: number | null;
|
|
91
|
+
category: string | null;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* List the DOL Data API v4 dataset catalog (KEYLESS). Fetches the WHOLE catalog in
|
|
95
|
+
* one page, applies optional CLIENT-SIDE `agency` (abbr/name) + `query` (substring over
|
|
96
|
+
* name/description/tags) filters, then offset/limit-slices the filtered set. Honest
|
|
97
|
+
* `_meta`: totalAvailable = the catalog's real total (unfiltered) or the filtered-set
|
|
98
|
+
* size (exact — the whole catalog is in hand); offset pagination over the filtered set.
|
|
99
|
+
*/
|
|
100
|
+
export declare function listDatasets(args: DolListDatasetsArgs): Promise<MetaBundle>;
|
|
101
|
+
export type DolGetDatasetArgs = {
|
|
102
|
+
agency?: string;
|
|
103
|
+
table?: string;
|
|
104
|
+
limit?: number;
|
|
105
|
+
offset?: number;
|
|
106
|
+
filterField?: string;
|
|
107
|
+
filterValue?: string;
|
|
108
|
+
fields?: string[];
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Fetch records from one DOL dataset (KEY-REQUIRED). `agency` (abbr) + `table` (the
|
|
112
|
+
* dataset's api_url endpoint) ride the request PATH; limit/offset/filter ride the query;
|
|
113
|
+
* the DOL_API_KEY rides the X-API-KEY header ONLY. Records are surfaced VERBATIM. Honest
|
|
114
|
+
* `_meta`: totalAvailable is a real count field when present, else null (offset
|
|
115
|
+
* pagination). Unset key ⇒ invalid_input THROW pre-fetch (0 fetch).
|
|
116
|
+
*/
|
|
117
|
+
export declare function getDataset(args: DolGetDatasetArgs): Promise<MetaBundle>;
|
|
118
|
+
//# sourceMappingURL=dol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dol.d.ts","sourceRoot":"","sources":["../src/dol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;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,QAAQ,oBAAoB,CAAC;AAkC1C,oFAAoF;AACpF,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAI9C;AAyBD,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAoBF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiGjF;AAGD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAyK7E"}
|