@frihet/mcp-server 1.16.3 → 1.16.5
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.md +1 -1
- package/dist/client-interface.d.ts +1 -1
- package/dist/client.d.ts +13 -1
- package/dist/client.js +70 -6
- package/dist/demo-client.d.ts +1 -1
- package/dist/demo-client.js +23 -3
- package/dist/openai-profile.js +1 -1
- package/dist/tools/invoices.js +24 -11
- package/package.json +11 -5
- package/scripts/postinstall.js +30 -8
- package/dist/__tests__/audit-server-version.test.d.ts +0 -13
- package/dist/__tests__/audit-server-version.test.d.ts.map +0 -1
- package/dist/__tests__/audit-server-version.test.js +0 -96
- package/dist/__tests__/audit-server-version.test.js.map +0 -1
- package/dist/__tests__/banking-client-contract.test.d.ts +0 -20
- package/dist/__tests__/banking-client-contract.test.d.ts.map +0 -1
- package/dist/__tests__/banking-client-contract.test.js +0 -133
- package/dist/__tests__/banking-client-contract.test.js.map +0 -1
- package/dist/__tests__/banking-tools.test.d.ts +0 -18
- package/dist/__tests__/banking-tools.test.d.ts.map +0 -1
- package/dist/__tests__/banking-tools.test.js +0 -252
- package/dist/__tests__/banking-tools.test.js.map +0 -1
- package/dist/__tests__/contract.test.d.ts +0 -33
- package/dist/__tests__/contract.test.d.ts.map +0 -1
- package/dist/__tests__/contract.test.js +0 -208
- package/dist/__tests__/contract.test.js.map +0 -1
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts +0 -13
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts.map +0 -1
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js +0 -420
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js.map +0 -1
- package/dist/__tests__/demo-mode.test.d.ts +0 -11
- package/dist/__tests__/demo-mode.test.d.ts.map +0 -1
- package/dist/__tests__/demo-mode.test.js +0 -119
- package/dist/__tests__/demo-mode.test.js.map +0 -1
- package/dist/__tests__/einvoice-day4-tools.test.d.ts +0 -16
- package/dist/__tests__/einvoice-day4-tools.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-day4-tools.test.js +0 -421
- package/dist/__tests__/einvoice-day4-tools.test.js.map +0 -1
- package/dist/__tests__/einvoice-integration.test.d.ts +0 -24
- package/dist/__tests__/einvoice-integration.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-integration.test.js +0 -142
- package/dist/__tests__/einvoice-integration.test.js.map +0 -1
- package/dist/__tests__/einvoice-tools.test.d.ts +0 -16
- package/dist/__tests__/einvoice-tools.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-tools.test.js +0 -411
- package/dist/__tests__/einvoice-tools.test.js.map +0 -1
- package/dist/__tests__/fiscal-tools.test.d.ts +0 -21
- package/dist/__tests__/fiscal-tools.test.d.ts.map +0 -1
- package/dist/__tests__/fiscal-tools.test.js +0 -271
- package/dist/__tests__/fiscal-tools.test.js.map +0 -1
- package/dist/__tests__/get-envelope-unwrap-regression.test.d.ts +0 -27
- package/dist/__tests__/get-envelope-unwrap-regression.test.d.ts.map +0 -1
- package/dist/__tests__/get-envelope-unwrap-regression.test.js +0 -223
- package/dist/__tests__/get-envelope-unwrap-regression.test.js.map +0 -1
- package/dist/__tests__/intelligence-duplicate-invoice.test.d.ts +0 -14
- package/dist/__tests__/intelligence-duplicate-invoice.test.d.ts.map +0 -1
- package/dist/__tests__/intelligence-duplicate-invoice.test.js +0 -108
- package/dist/__tests__/intelligence-duplicate-invoice.test.js.map +0 -1
- package/dist/__tests__/kitchen-tools.test.d.ts +0 -18
- package/dist/__tests__/kitchen-tools.test.d.ts.map +0 -1
- package/dist/__tests__/kitchen-tools.test.js +0 -399
- package/dist/__tests__/kitchen-tools.test.js.map +0 -1
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.d.ts +0 -30
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.d.ts.map +0 -1
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.js +0 -164
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.js.map +0 -1
- package/dist/__tests__/observability-redaction.test.d.ts +0 -13
- package/dist/__tests__/observability-redaction.test.d.ts.map +0 -1
- package/dist/__tests__/observability-redaction.test.js +0 -94
- package/dist/__tests__/observability-redaction.test.js.map +0 -1
- package/dist/__tests__/openai-grouped-compose.test.d.ts +0 -26
- package/dist/__tests__/openai-grouped-compose.test.d.ts.map +0 -1
- package/dist/__tests__/openai-grouped-compose.test.js +0 -245
- package/dist/__tests__/openai-grouped-compose.test.js.map +0 -1
- package/dist/__tests__/openai-profile.test.d.ts +0 -10
- package/dist/__tests__/openai-profile.test.d.ts.map +0 -1
- package/dist/__tests__/openai-profile.test.js +0 -168
- package/dist/__tests__/openai-profile.test.js.map +0 -1
- package/dist/__tests__/pagination-cursor-param.test.d.ts +0 -27
- package/dist/__tests__/pagination-cursor-param.test.d.ts.map +0 -1
- package/dist/__tests__/pagination-cursor-param.test.js +0 -96
- package/dist/__tests__/pagination-cursor-param.test.js.map +0 -1
- package/dist/__tests__/pos-tools.test.d.ts +0 -16
- package/dist/__tests__/pos-tools.test.d.ts.map +0 -1
- package/dist/__tests__/pos-tools.test.js +0 -244
- package/dist/__tests__/pos-tools.test.js.map +0 -1
- package/dist/__tests__/recurring-tools.test.d.ts +0 -23
- package/dist/__tests__/recurring-tools.test.d.ts.map +0 -1
- package/dist/__tests__/recurring-tools.test.js +0 -352
- package/dist/__tests__/recurring-tools.test.js.map +0 -1
- package/dist/__tests__/schema-envelope-guard.test.d.ts +0 -18
- package/dist/__tests__/schema-envelope-guard.test.d.ts.map +0 -1
- package/dist/__tests__/schema-envelope-guard.test.js +0 -56
- package/dist/__tests__/schema-envelope-guard.test.js.map +0 -1
- package/dist/__tests__/stay-tools.test.d.ts +0 -17
- package/dist/__tests__/stay-tools.test.d.ts.map +0 -1
- package/dist/__tests__/stay-tools.test.js +0 -259
- package/dist/__tests__/stay-tools.test.js.map +0 -1
- package/dist/__tests__/team-tools.test.d.ts +0 -18
- package/dist/__tests__/team-tools.test.d.ts.map +0 -1
- package/dist/__tests__/team-tools.test.js +0 -228
- package/dist/__tests__/team-tools.test.js.map +0 -1
- package/dist/__tests__/time-tools.test.d.ts +0 -19
- package/dist/__tests__/time-tools.test.d.ts.map +0 -1
- package/dist/__tests__/time-tools.test.js +0 -286
- package/dist/__tests__/time-tools.test.js.map +0 -1
- package/dist/__tests__/tool-exposure.test.d.ts +0 -11
- package/dist/__tests__/tool-exposure.test.d.ts.map +0 -1
- package/dist/__tests__/tool-exposure.test.js +0 -264
- package/dist/__tests__/tool-exposure.test.js.map +0 -1
- package/dist/client-interface.d.ts.map +0 -1
- package/dist/client-interface.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/demo-client.d.ts.map +0 -1
- package/dist/demo-client.js.map +0 -1
- package/dist/demo-fixtures.d.ts.map +0 -1
- package/dist/demo-fixtures.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/metrics.d.ts.map +0 -1
- package/dist/metrics.js.map +0 -1
- package/dist/observability.d.ts.map +0 -1
- package/dist/observability.js.map +0 -1
- package/dist/openai-profile.d.ts.map +0 -1
- package/dist/openai-profile.js.map +0 -1
- package/dist/prompts/register-all.d.ts.map +0 -1
- package/dist/prompts/register-all.js.map +0 -1
- package/dist/redaction.d.ts.map +0 -1
- package/dist/redaction.js.map +0 -1
- package/dist/resources/register-all.d.ts.map +0 -1
- package/dist/resources/register-all.js.map +0 -1
- package/dist/tool-exposure.d.ts.map +0 -1
- package/dist/tool-exposure.js.map +0 -1
- package/dist/tools/accountingClose.d.ts.map +0 -1
- package/dist/tools/accountingClose.js.map +0 -1
- package/dist/tools/audit_gl.d.ts.map +0 -1
- package/dist/tools/audit_gl.js.map +0 -1
- package/dist/tools/backend-availability.d.ts.map +0 -1
- package/dist/tools/backend-availability.js.map +0 -1
- package/dist/tools/bank_rules.d.ts.map +0 -1
- package/dist/tools/bank_rules.js.map +0 -1
- package/dist/tools/banking.d.ts.map +0 -1
- package/dist/tools/banking.js.map +0 -1
- package/dist/tools/clients.d.ts.map +0 -1
- package/dist/tools/clients.js.map +0 -1
- package/dist/tools/crm.d.ts.map +0 -1
- package/dist/tools/crm.js.map +0 -1
- package/dist/tools/deposits.d.ts.map +0 -1
- package/dist/tools/deposits.js.map +0 -1
- package/dist/tools/einvoice.d.ts.map +0 -1
- package/dist/tools/einvoice.js.map +0 -1
- package/dist/tools/expenses.d.ts.map +0 -1
- package/dist/tools/expenses.js.map +0 -1
- package/dist/tools/fiscal.d.ts.map +0 -1
- package/dist/tools/fiscal.js.map +0 -1
- package/dist/tools/gestoria.d.ts.map +0 -1
- package/dist/tools/gestoria.js.map +0 -1
- package/dist/tools/hr.d.ts.map +0 -1
- package/dist/tools/hr.js.map +0 -1
- package/dist/tools/igic.d.ts.map +0 -1
- package/dist/tools/igic.js.map +0 -1
- package/dist/tools/impuesto_sociedades.d.ts.map +0 -1
- package/dist/tools/impuesto_sociedades.js.map +0 -1
- package/dist/tools/intelligence.d.ts.map +0 -1
- package/dist/tools/intelligence.js.map +0 -1
- package/dist/tools/invoices.d.ts.map +0 -1
- package/dist/tools/invoices.js.map +0 -1
- package/dist/tools/kitchen.d.ts.map +0 -1
- package/dist/tools/kitchen.js.map +0 -1
- package/dist/tools/onboard_vies.d.ts.map +0 -1
- package/dist/tools/onboard_vies.js.map +0 -1
- package/dist/tools/onboarding.d.ts.map +0 -1
- package/dist/tools/onboarding.js.map +0 -1
- package/dist/tools/payroll.d.ts.map +0 -1
- package/dist/tools/payroll.js.map +0 -1
- package/dist/tools/permissions.d.ts.map +0 -1
- package/dist/tools/permissions.js.map +0 -1
- package/dist/tools/portal_domain.d.ts.map +0 -1
- package/dist/tools/portal_domain.js.map +0 -1
- package/dist/tools/pos.d.ts.map +0 -1
- package/dist/tools/pos.js.map +0 -1
- package/dist/tools/products.d.ts.map +0 -1
- package/dist/tools/products.js.map +0 -1
- package/dist/tools/quotes.d.ts.map +0 -1
- package/dist/tools/quotes.js.map +0 -1
- package/dist/tools/recurring.d.ts.map +0 -1
- package/dist/tools/recurring.js.map +0 -1
- package/dist/tools/register-all.d.ts.map +0 -1
- package/dist/tools/register-all.js.map +0 -1
- package/dist/tools/shared.d.ts.map +0 -1
- package/dist/tools/shared.js.map +0 -1
- package/dist/tools/stay.d.ts.map +0 -1
- package/dist/tools/stay.js.map +0 -1
- package/dist/tools/team.d.ts.map +0 -1
- package/dist/tools/team.js.map +0 -1
- package/dist/tools/time.d.ts.map +0 -1
- package/dist/tools/time.js.map +0 -1
- package/dist/tools/vendors.d.ts.map +0 -1
- package/dist/tools/vendors.js.map +0 -1
- package/dist/tools/webhooks.d.ts.map +0 -1
- package/dist/tools/webhooks.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/scripts/audit-mcp-refs.mjs +0 -402
- package/scripts/no-public-leak.sh +0 -60
- package/scripts/test-openai-grouped-compose.mjs +0 -173
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Regression tests for the "invoices INOPERABLE via MCP" bug set (LANE B1).
|
|
3
|
-
*
|
|
4
|
-
* Two independent bugs made every WRITE path fail MCP output validation while
|
|
5
|
-
* reads (fixed in #64) worked:
|
|
6
|
-
*
|
|
7
|
-
* BUG-1 (envelope leak on mutations): create/update/action client methods
|
|
8
|
-
* called `this.request(...)` (RAW) instead of `this.requestUnwrapped(...)`.
|
|
9
|
-
* The live Frihet `/v1` API wraps EVERY mutation in `{ data, meta }`
|
|
10
|
-
* (publicApi.ts: 201/PUT/PATCH → `{ data: <resource>, meta }`; action POSTs
|
|
11
|
-
* → `actionResponse = { data: actionResult, meta }`). The raw envelope went
|
|
12
|
-
* straight into `structuredContent`, so `id`/`clientName`/`items`/`success`
|
|
13
|
-
* all read as `undefined` and the tool's outputSchema rejected the call.
|
|
14
|
-
*
|
|
15
|
-
* BUG-2 (output schemas too strict): list/search item schemas required fields
|
|
16
|
-
* that `fields=` projections and drafts legitimately omit (`GET
|
|
17
|
-
* /invoices?fields=id,total` → `{ id }`-shaped rows), and `actionResultOutput`
|
|
18
|
-
* required `success`+`id` that action endpoints never return in full.
|
|
19
|
-
*
|
|
20
|
-
* Part A boots a `node:http` mock backend that mimics the LIVE mutation envelope
|
|
21
|
-
* and drives a REAL `FrihetClient` (same pattern as
|
|
22
|
-
* get-envelope-unwrap-regression.test.ts) — it would fail before the BUG-1 fix.
|
|
23
|
-
* Part B pins the relaxed schemas against the real projected/draft/action shapes
|
|
24
|
-
* — it would fail before the BUG-2 fix. The final guard asserts the schemas are
|
|
25
|
-
* still strict enough to REJECT a raw envelope, so removing the unwrap regresses.
|
|
26
|
-
*
|
|
27
|
-
* Run: npm test (after build)
|
|
28
|
-
*/
|
|
29
|
-
import { test, describe, before, after } from "node:test";
|
|
30
|
-
import assert from "node:assert/strict";
|
|
31
|
-
import { createServer } from "node:http";
|
|
32
|
-
import { FrihetClient } from "../client.js";
|
|
33
|
-
import { invoiceItemOutput, paginatedOutput, actionResultOutput, creditNoteResultOutput, } from "../tools/shared.js";
|
|
34
|
-
// ── Mock ERP backend: every mutation wraps its result in { data, meta } ──
|
|
35
|
-
let server;
|
|
36
|
-
let baseUrl;
|
|
37
|
-
function envelope(data, meta = { requestId: "test" }) {
|
|
38
|
-
return { data, meta };
|
|
39
|
-
}
|
|
40
|
-
const FULL_INVOICE = {
|
|
41
|
-
id: "inv_new",
|
|
42
|
-
clientName: "Acme Corp",
|
|
43
|
-
items: [{ description: "Consulting", quantity: 1, unitPrice: 100 }],
|
|
44
|
-
status: "draft",
|
|
45
|
-
taxRate: 21,
|
|
46
|
-
};
|
|
47
|
-
const FULL_CLIENT = { id: "cli_new", name: "Acme Corp", email: "billing@acme.example" };
|
|
48
|
-
async function readBody(req) {
|
|
49
|
-
return new Promise((resolve) => {
|
|
50
|
-
req.on("data", () => { });
|
|
51
|
-
req.on("end", () => resolve());
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
before(async () => {
|
|
55
|
-
server = createServer(async (req, res) => {
|
|
56
|
-
await readBody(req);
|
|
57
|
-
const url = new URL(req.url ?? "/", "http://localhost");
|
|
58
|
-
res.setHeader("Content-Type", "application/json");
|
|
59
|
-
const send = (status, body) => {
|
|
60
|
-
res.statusCode = status;
|
|
61
|
-
res.end(JSON.stringify(body));
|
|
62
|
-
};
|
|
63
|
-
// create invoice (201) — main-resource envelope
|
|
64
|
-
if (url.pathname === "/invoices" && req.method === "POST") {
|
|
65
|
-
return send(201, envelope(FULL_INVOICE));
|
|
66
|
-
}
|
|
67
|
-
// update invoice (PATCH) — main-resource envelope
|
|
68
|
-
if (url.pathname === "/invoices/inv_new" && req.method === "PATCH") {
|
|
69
|
-
return send(200, envelope({ ...FULL_INVOICE, status: "sent" }));
|
|
70
|
-
}
|
|
71
|
-
// mark paid (POST action, 200) — action envelope, NO id, has success/status/paidAt
|
|
72
|
-
if (url.pathname === "/invoices/inv_new/paid" && req.method === "POST") {
|
|
73
|
-
return send(200, envelope({ success: true, status: "paid", paidAt: "2026-07-10" }));
|
|
74
|
-
}
|
|
75
|
-
// credit note (POST action) — action envelope with { success, creditNote }
|
|
76
|
-
if (url.pathname === "/invoices/inv_new/credit-note" && req.method === "POST") {
|
|
77
|
-
return send(201, envelope({
|
|
78
|
-
success: true,
|
|
79
|
-
creditNote: { id: "cn_1", documentNumber: "CN-FRI-0001", originalInvoiceId: "inv_new", reason: "error", fullCredit: true },
|
|
80
|
-
}));
|
|
81
|
-
}
|
|
82
|
-
// create client (201) — sibling-resource envelope (proves the fix is systemic)
|
|
83
|
-
if (url.pathname === "/clients" && req.method === "POST") {
|
|
84
|
-
return send(201, envelope(FULL_CLIENT));
|
|
85
|
-
}
|
|
86
|
-
res.statusCode = 404;
|
|
87
|
-
return send(404, { error: "not_found" });
|
|
88
|
-
});
|
|
89
|
-
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
90
|
-
const { port } = server.address();
|
|
91
|
-
baseUrl = `http://127.0.0.1:${port}`;
|
|
92
|
-
});
|
|
93
|
-
after(async () => {
|
|
94
|
-
await new Promise((resolve) => server.close(() => resolve()));
|
|
95
|
-
});
|
|
96
|
-
function makeClient() {
|
|
97
|
-
return new FrihetClient("fri_test_key", baseUrl);
|
|
98
|
-
}
|
|
99
|
-
function assertNoEnvelopeLeak(result) {
|
|
100
|
-
assert.equal(typeof result, "object");
|
|
101
|
-
assert.ok(result !== null);
|
|
102
|
-
assert.equal("data" in result, false, "envelope 'data' key must NOT leak into the mutation result");
|
|
103
|
-
assert.equal("meta" in result, false, "envelope 'meta' key must NOT leak into the mutation result");
|
|
104
|
-
}
|
|
105
|
-
describe("BUG-1 — mutation client methods unwrap the { data, meta } envelope", () => {
|
|
106
|
-
test("createInvoice unwraps + validates against invoiceItemOutput", async () => {
|
|
107
|
-
const result = await makeClient().createInvoice(FULL_INVOICE);
|
|
108
|
-
assertNoEnvelopeLeak(result);
|
|
109
|
-
assert.equal(result.id, "inv_new");
|
|
110
|
-
assert.equal(invoiceItemOutput.safeParse(result).success, true);
|
|
111
|
-
});
|
|
112
|
-
test("updateInvoice unwraps the envelope", async () => {
|
|
113
|
-
const result = await makeClient().updateInvoice("inv_new", { status: "sent" });
|
|
114
|
-
assertNoEnvelopeLeak(result);
|
|
115
|
-
assert.equal(result.status, "sent");
|
|
116
|
-
});
|
|
117
|
-
test("markInvoicePaid unwraps to the action result (success/status/paidAt)", async () => {
|
|
118
|
-
const result = await makeClient().markInvoicePaid("inv_new");
|
|
119
|
-
assertNoEnvelopeLeak(result);
|
|
120
|
-
assert.equal(result.success, true);
|
|
121
|
-
assert.equal(actionResultOutput.safeParse(result).success, true);
|
|
122
|
-
});
|
|
123
|
-
test("createCreditNote unwraps to { success, creditNote }", async () => {
|
|
124
|
-
const result = await makeClient().createCreditNote("inv_new", { reason: "error" });
|
|
125
|
-
assertNoEnvelopeLeak(result);
|
|
126
|
-
assert.equal(creditNoteResultOutput.safeParse(result).success, true);
|
|
127
|
-
});
|
|
128
|
-
test("createClient unwraps — the fix is systemic across resources", async () => {
|
|
129
|
-
const result = await makeClient().createClient(FULL_CLIENT);
|
|
130
|
-
assertNoEnvelopeLeak(result);
|
|
131
|
-
assert.equal(result.id, "cli_new");
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
describe("BUG-2 — output schemas tolerate projections, drafts, and action shapes", () => {
|
|
135
|
-
const listOf = (rows) => ({ data: rows, total: rows.length, limit: 20, offset: 0 });
|
|
136
|
-
test("list schema accepts a fields=id,total projection ({ id } / { id,total } rows)", () => {
|
|
137
|
-
const schema = paginatedOutput(invoiceItemOutput);
|
|
138
|
-
assert.equal(schema.safeParse(listOf([{ id: "e2e-invoice-4" }])).success, true);
|
|
139
|
-
assert.equal(schema.safeParse(listOf([{ id: "a", total: 5 }, { id: "b" }])).success, true);
|
|
140
|
-
});
|
|
141
|
-
test("invoiceItemOutput accepts a draft (no items) and a null clientName", () => {
|
|
142
|
-
assert.equal(invoiceItemOutput.safeParse({ id: "inv_draft" }).success, true);
|
|
143
|
-
assert.equal(invoiceItemOutput.safeParse({ id: "inv_draft", clientName: null }).success, true);
|
|
144
|
-
});
|
|
145
|
-
test("actionResultOutput accepts the already-paid shape ({ message, status }) and the happy path", () => {
|
|
146
|
-
assert.equal(actionResultOutput.safeParse({ message: "Invoice already marked as paid", status: "paid" }).success, true);
|
|
147
|
-
assert.equal(actionResultOutput.safeParse({ success: true, status: "paid", paidAt: "2026-07-10" }).success, true);
|
|
148
|
-
});
|
|
149
|
-
test("creditNoteResultOutput accepts the { success, creditNote } action shape", () => {
|
|
150
|
-
assert.equal(creditNoteResultOutput.safeParse({
|
|
151
|
-
success: true,
|
|
152
|
-
creditNote: { id: "cn_1", documentNumber: "CN-1" },
|
|
153
|
-
}).success, true);
|
|
154
|
-
});
|
|
155
|
-
test("GUARD: invoiceItemOutput still REJECTS a raw { data, meta } envelope (id stays required)", () => {
|
|
156
|
-
// `id` stays required precisely so create/update/get can't silently surface
|
|
157
|
-
// the envelope if a future edit drops requestUnwrapped — the envelope has no
|
|
158
|
-
// top-level `id`. actionResultOutput is deliberately permissive (all fields
|
|
159
|
-
// optional so already-paid `{ message, status }` validates), so for ACTION
|
|
160
|
-
// paths the unwrap pinned in Part A — not the schema — is the envelope guard.
|
|
161
|
-
assert.equal(invoiceItemOutput.safeParse({ data: FULL_INVOICE, meta: {} }).success, false);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
//# sourceMappingURL=mutation-unwrap-and-schema-regression.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mutation-unwrap-and-schema-regression.test.js","sourceRoot":"","sources":["../../src/__tests__/mutation-unwrap-and-schema-regression.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Trust test — no government ID, credential, or banking identifier may ever
|
|
3
|
-
* reach the external Langfuse observability service.
|
|
4
|
-
*
|
|
5
|
-
* Regression guard for the P0 finding (Codex audit 2026-06-22): the Langfuse
|
|
6
|
-
* tracer captured the RAW tool output BEFORE the OpenAI profile redaction
|
|
7
|
-
* wrapper ran, so taxId/secret/IBAN leaked into traces in every profile mode.
|
|
8
|
-
* The fix moved redaction INTO buildTracePayload, so the trace copy is redacted
|
|
9
|
-
* unconditionally. This test fails if any sensitive value survives into the
|
|
10
|
-
* serialized ingestion batch.
|
|
11
|
-
*/
|
|
12
|
-
export {};
|
|
13
|
-
//# sourceMappingURL=observability-redaction.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observability-redaction.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/observability-redaction.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Trust test — no government ID, credential, or banking identifier may ever
|
|
3
|
-
* reach the external Langfuse observability service.
|
|
4
|
-
*
|
|
5
|
-
* Regression guard for the P0 finding (Codex audit 2026-06-22): the Langfuse
|
|
6
|
-
* tracer captured the RAW tool output BEFORE the OpenAI profile redaction
|
|
7
|
-
* wrapper ran, so taxId/secret/IBAN leaked into traces in every profile mode.
|
|
8
|
-
* The fix moved redaction INTO buildTracePayload, so the trace copy is redacted
|
|
9
|
-
* unconditionally. This test fails if any sensitive value survives into the
|
|
10
|
-
* serialized ingestion batch.
|
|
11
|
-
*/
|
|
12
|
-
import { describe, test } from "node:test";
|
|
13
|
-
import assert from "node:assert/strict";
|
|
14
|
-
import { buildTracePayload } from "../observability.js";
|
|
15
|
-
import { redactClone, SENSITIVE_FIELD_NAMES } from "../redaction.js";
|
|
16
|
-
const SECRETS = {
|
|
17
|
-
taxId: "B12345678",
|
|
18
|
-
nif: "12345678Z",
|
|
19
|
-
secret: "whsec_live_DEADBEEFCAFE",
|
|
20
|
-
iban: "ES9121000418450200051332",
|
|
21
|
-
passport: "PAX9988776",
|
|
22
|
-
apiKey: "fri_live_TOPSECRET",
|
|
23
|
-
accessToken: "ya29.A0ARrdaM-TOKEN",
|
|
24
|
-
password: "hunter2",
|
|
25
|
-
};
|
|
26
|
-
const SECRET_VALUES = Object.values(SECRETS);
|
|
27
|
-
/** A realistic MCP tool result: structuredContent + a serialized JSON text block. */
|
|
28
|
-
function mcpResultWithSecrets() {
|
|
29
|
-
return {
|
|
30
|
-
content: [{ type: "text", text: JSON.stringify({ id: "cli_1", ...SECRETS }) }],
|
|
31
|
-
structuredContent: {
|
|
32
|
-
client: { id: "cli_1", name: "Acme", ...SECRETS },
|
|
33
|
-
webhooks: [{ id: "wh_1", url: "https://x.test", secret: SECRETS.secret }],
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
function assertNoSecrets(serialized) {
|
|
38
|
-
for (const v of SECRET_VALUES) {
|
|
39
|
-
assert.ok(!serialized.includes(v), `sensitive value leaked into trace payload: ${v}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
describe("observability redaction", () => {
|
|
43
|
-
test("buildTracePayload strips PII/credentials from output (success path)", () => {
|
|
44
|
-
const now = new Date("2026-06-22T10:00:00.000Z");
|
|
45
|
-
const batch = buildTracePayload({
|
|
46
|
-
toolName: "get_client",
|
|
47
|
-
input: { id: "cli_1", taxId: SECRETS.taxId },
|
|
48
|
-
output: mcpResultWithSecrets(),
|
|
49
|
-
isError: false,
|
|
50
|
-
startTime: now,
|
|
51
|
-
endTime: now,
|
|
52
|
-
traceId: "trace_1",
|
|
53
|
-
spanId: "span_1",
|
|
54
|
-
stub: null,
|
|
55
|
-
});
|
|
56
|
-
assertNoSecrets(JSON.stringify(batch));
|
|
57
|
-
});
|
|
58
|
-
test("buildTracePayload strips PII from input args even on the error path", () => {
|
|
59
|
-
const now = new Date("2026-06-22T10:00:00.000Z");
|
|
60
|
-
const batch = buildTracePayload({
|
|
61
|
-
toolName: "create_client",
|
|
62
|
-
input: { name: "Acme", ...SECRETS },
|
|
63
|
-
output: undefined,
|
|
64
|
-
isError: true,
|
|
65
|
-
// an error message that echoes the request body must not leak either
|
|
66
|
-
errorMessage: `Backend rejected payload: {"taxId":"${SECRETS.taxId}","secret":"${SECRETS.secret}"}`,
|
|
67
|
-
startTime: now,
|
|
68
|
-
endTime: now,
|
|
69
|
-
traceId: "trace_2",
|
|
70
|
-
spanId: "span_2",
|
|
71
|
-
stub: null,
|
|
72
|
-
});
|
|
73
|
-
assertNoSecrets(JSON.stringify(batch));
|
|
74
|
-
});
|
|
75
|
-
test("redactClone never mutates its argument", () => {
|
|
76
|
-
const original = mcpResultWithSecrets();
|
|
77
|
-
const before = JSON.stringify(original);
|
|
78
|
-
redactClone(original);
|
|
79
|
-
assert.equal(JSON.stringify(original), before, "redactClone must not mutate input");
|
|
80
|
-
});
|
|
81
|
-
test("redactClone preserves non-sensitive fields", () => {
|
|
82
|
-
const cloned = redactClone({ id: "cli_1", name: "Acme", total: 100, taxId: SECRETS.taxId });
|
|
83
|
-
assert.equal(cloned.id, "cli_1");
|
|
84
|
-
assert.equal(cloned.name, "Acme");
|
|
85
|
-
assert.equal(cloned.total, 100);
|
|
86
|
-
assert.notEqual(cloned.taxId, SECRETS.taxId);
|
|
87
|
-
});
|
|
88
|
-
test("the sensitive field set covers the critical Trust fields", () => {
|
|
89
|
-
for (const f of ["taxId", "secret", "iban", "apiKey", "accessToken", "password"]) {
|
|
90
|
-
assert.ok(SENSITIVE_FIELD_NAMES.includes(f), `missing critical sensitive field: ${f}`);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
//# sourceMappingURL=observability-redaction.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"observability-redaction.test.js","sourceRoot":"","sources":["../../src/__tests__/observability-redaction.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the OpenAI × grouped tool-exposure COMPOSITION.
|
|
3
|
-
*
|
|
4
|
-
* openai-mcp.frihet.io now runs BOTH profiles: the OpenAI-safe profile
|
|
5
|
-
* (53 reviewed tools, redaction, openWorldHint justification) AND the grouped
|
|
6
|
-
* progressive-disclosure profile (terse descriptions + 3 discovery meta-tools).
|
|
7
|
-
*
|
|
8
|
-
* This is the Trust-Area-critical surface that the ChatGPT app review covers, so
|
|
9
|
-
* the three invariants below are asserted explicitly:
|
|
10
|
-
*
|
|
11
|
-
* (1) The 3 grouped meta-tools (search_tools, describe_tool, list_tool_groups)
|
|
12
|
-
* are PRESENT in OpenAI mode — they register against the real server and
|
|
13
|
-
* bypass the OpenAI allow-list gate. Live surface = 53 + 3 = 56 tools.
|
|
14
|
-
* (2) Every one of the 53 reviewed tools has a COLLAPSED (terse) description
|
|
15
|
-
* AND still carries the per-tool openWorldHint rationale marker that OpenAI
|
|
16
|
-
* app review requires.
|
|
17
|
-
* (3) The grouped catalog (what search_tools / describe_tool / list_tool_groups
|
|
18
|
-
* surface) contains ONLY the 53 reviewed tools — a tool outside the reviewed
|
|
19
|
-
* set is never returned by search_tools and is rejected by describe_tool.
|
|
20
|
-
*
|
|
21
|
-
* Composition order under test mirrors the worker/stdio init wiring:
|
|
22
|
-
* applyToolExposureProfile(server, { allowlist }) FIRST (innermost),
|
|
23
|
-
* applyOpenAIProfile(server) SECOND (outermost).
|
|
24
|
-
*/
|
|
25
|
-
export {};
|
|
26
|
-
//# sourceMappingURL=openai-grouped-compose.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-grouped-compose.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/openai-grouped-compose.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the OpenAI × grouped tool-exposure COMPOSITION.
|
|
3
|
-
*
|
|
4
|
-
* openai-mcp.frihet.io now runs BOTH profiles: the OpenAI-safe profile
|
|
5
|
-
* (53 reviewed tools, redaction, openWorldHint justification) AND the grouped
|
|
6
|
-
* progressive-disclosure profile (terse descriptions + 3 discovery meta-tools).
|
|
7
|
-
*
|
|
8
|
-
* This is the Trust-Area-critical surface that the ChatGPT app review covers, so
|
|
9
|
-
* the three invariants below are asserted explicitly:
|
|
10
|
-
*
|
|
11
|
-
* (1) The 3 grouped meta-tools (search_tools, describe_tool, list_tool_groups)
|
|
12
|
-
* are PRESENT in OpenAI mode — they register against the real server and
|
|
13
|
-
* bypass the OpenAI allow-list gate. Live surface = 53 + 3 = 56 tools.
|
|
14
|
-
* (2) Every one of the 53 reviewed tools has a COLLAPSED (terse) description
|
|
15
|
-
* AND still carries the per-tool openWorldHint rationale marker that OpenAI
|
|
16
|
-
* app review requires.
|
|
17
|
-
* (3) The grouped catalog (what search_tools / describe_tool / list_tool_groups
|
|
18
|
-
* surface) contains ONLY the 53 reviewed tools — a tool outside the reviewed
|
|
19
|
-
* set is never returned by search_tools and is rejected by describe_tool.
|
|
20
|
-
*
|
|
21
|
-
* Composition order under test mirrors the worker/stdio init wiring:
|
|
22
|
-
* applyToolExposureProfile(server, { allowlist }) FIRST (innermost),
|
|
23
|
-
* applyOpenAIProfile(server) SECOND (outermost).
|
|
24
|
-
*/
|
|
25
|
-
import { describe, test } from "node:test";
|
|
26
|
-
import assert from "node:assert/strict";
|
|
27
|
-
import { applyOpenAIProfile, OPENAI_REVIEWED_TOOL_ALLOWLIST, OPENAI_ALLOWED_TOOL_COUNT, } from "../openai-profile.js";
|
|
28
|
-
import { applyToolExposureProfile, GROUPED_META_TOOL_COUNT } from "../tool-exposure.js";
|
|
29
|
-
import { registerAllTools } from "../tools/register-all.js";
|
|
30
|
-
import { registerAllPrompts } from "../prompts/register-all.js";
|
|
31
|
-
import { registerAllResources } from "../resources/register-all.js";
|
|
32
|
-
class StubMcpServer {
|
|
33
|
-
tools = new Map();
|
|
34
|
-
prompts = [];
|
|
35
|
-
resources = [];
|
|
36
|
-
registerTool(name, config, handler) {
|
|
37
|
-
this.tools.set(name, { name, config, handler });
|
|
38
|
-
}
|
|
39
|
-
registerPrompt(name) {
|
|
40
|
-
this.prompts.push(name);
|
|
41
|
-
}
|
|
42
|
-
registerResource(name) {
|
|
43
|
-
this.resources.push(name);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
/** Client that returns a payload carrying sensitive fields (to test redaction). */
|
|
47
|
-
function makeClient() {
|
|
48
|
-
return new Proxy({}, {
|
|
49
|
-
get: (_target, prop) => async (input) => {
|
|
50
|
-
if (prop === "createClient") {
|
|
51
|
-
return {
|
|
52
|
-
id: "cli_compose",
|
|
53
|
-
name: "Compose Test Corp",
|
|
54
|
-
email: "test@example.com",
|
|
55
|
-
taxId: "B12345678",
|
|
56
|
-
secret: "should-not-leak",
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return { data: [], total: 0, limit: 10, offset: 0, input };
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
const asMcp = (s) => s;
|
|
64
|
-
/**
|
|
65
|
-
* Build a server with BOTH profiles composed in the production order:
|
|
66
|
-
* grouped (allow-list) first, OpenAI second.
|
|
67
|
-
*/
|
|
68
|
-
function makeComposedServer() {
|
|
69
|
-
const server = new StubMcpServer();
|
|
70
|
-
// 1. grouped FIRST (innermost) — meta-tools bypass the OpenAI gate; catalog
|
|
71
|
-
// pinned to the reviewed allow-list.
|
|
72
|
-
applyToolExposureProfile(asMcp(server), {
|
|
73
|
-
allowlist: OPENAI_REVIEWED_TOOL_ALLOWLIST,
|
|
74
|
-
});
|
|
75
|
-
// 2. OpenAI SECOND (outermost) — gate/redact/annotate, then collapse.
|
|
76
|
-
applyOpenAIProfile(asMcp(server));
|
|
77
|
-
registerAllTools(asMcp(server), makeClient());
|
|
78
|
-
registerAllResources(asMcp(server));
|
|
79
|
-
registerAllPrompts(asMcp(server));
|
|
80
|
-
return server;
|
|
81
|
-
}
|
|
82
|
-
const META_TOOLS = ["list_tool_groups", "search_tools", "describe_tool"];
|
|
83
|
-
/** Tools that exist on the full server but must NEVER surface in the composed one. */
|
|
84
|
-
const NON_REVIEWED_TOOLS = [
|
|
85
|
-
"get_quarterly_taxes",
|
|
86
|
-
"get_invoice_einvoice",
|
|
87
|
-
"send_einvoice",
|
|
88
|
-
"validate_einvoice_xml",
|
|
89
|
-
"create_reservation",
|
|
90
|
-
"payroll_export",
|
|
91
|
-
"invite_team_member",
|
|
92
|
-
"get_modelo_303_summary",
|
|
93
|
-
];
|
|
94
|
-
describe("openai × grouped composition: invariant (1) — meta-tools present, 53+3 surface", () => {
|
|
95
|
-
test("registers exactly 53 reviewed tools + 3 meta-tools (56 total)", () => {
|
|
96
|
-
const server = makeComposedServer();
|
|
97
|
-
assert.equal(GROUPED_META_TOOL_COUNT, 3);
|
|
98
|
-
assert.equal(OPENAI_ALLOWED_TOOL_COUNT, 53, "advertised reviewed count stays 53");
|
|
99
|
-
assert.equal(server.tools.size, OPENAI_ALLOWED_TOOL_COUNT + GROUPED_META_TOOL_COUNT, "live surface must be the 53 reviewed tools + 3 meta-tools");
|
|
100
|
-
assert.equal(server.tools.size, 56);
|
|
101
|
-
// Prompts still hidden in OpenAI mode.
|
|
102
|
-
assert.equal(server.prompts.length, 0);
|
|
103
|
-
// Resources are hidden too: full-server static fiscal/compliance resources
|
|
104
|
-
// are outside the reviewed ChatGPT app surface.
|
|
105
|
-
assert.equal(server.resources.length, 0);
|
|
106
|
-
});
|
|
107
|
-
test("all 3 discovery meta-tools materialise by name despite the OpenAI allow-list", () => {
|
|
108
|
-
const server = makeComposedServer();
|
|
109
|
-
for (const meta of META_TOOLS) {
|
|
110
|
-
assert.equal(server.tools.has(meta), true, `${meta} must survive OpenAI filtering in the composed surface`);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
test("non-reviewed tools are dropped entirely (defence: openai gate)", () => {
|
|
114
|
-
const server = makeComposedServer();
|
|
115
|
-
for (const name of NON_REVIEWED_TOOLS) {
|
|
116
|
-
assert.equal(server.tools.has(name), false, `${name} must NOT be exposed in the composed OpenAI surface`);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
test("meta-tools are read-only, closed-world catalog lookups (NOT openWorldHint)", () => {
|
|
120
|
-
const server = makeComposedServer();
|
|
121
|
-
for (const meta of META_TOOLS) {
|
|
122
|
-
const ann = server.tools.get(meta).config.annotations;
|
|
123
|
-
assert.equal(ann?.readOnlyHint, true, `${meta} must be read-only`);
|
|
124
|
-
assert.equal(ann?.openWorldHint, false, `${meta} must be closed-world`);
|
|
125
|
-
// Their descriptions carry an explicit closed-world rationale already (so
|
|
126
|
-
// the OpenAI rationale-injector does not double-append).
|
|
127
|
-
assert.match(server.tools.get(meta).config.description, /openWorldHint: false/, `${meta} description must state the closed-world rationale`);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
describe("openai × grouped composition: invariant (2) — collapsed + openWorldHint on all 53", () => {
|
|
132
|
-
test("every reviewed tool is collapsed AND carries an openWorldHint rationale", () => {
|
|
133
|
-
const server = makeComposedServer();
|
|
134
|
-
let reviewedCount = 0;
|
|
135
|
-
for (const [name, tool] of server.tools) {
|
|
136
|
-
if (META_TOOLS.includes(name))
|
|
137
|
-
continue;
|
|
138
|
-
reviewedCount += 1;
|
|
139
|
-
const desc = tool.config.description;
|
|
140
|
-
// Collapsed: terse "[group] summary — full schema via describe_tool('name')."
|
|
141
|
-
assert.match(desc, /^\[[a-z]+\] /, `${name} description must start with the [group] collapsed prefix`);
|
|
142
|
-
assert.ok(desc.includes(`describe_tool('${name}')`), `${name} description must point to describe_tool`);
|
|
143
|
-
// Terse: collapsed line is short, NOT a multi-paragraph bilingual blob.
|
|
144
|
-
assert.ok(desc.length < 400, `${name} description must be collapsed (terse), got length ${desc.length}`);
|
|
145
|
-
// openWorldHint rationale marker survives the collapse.
|
|
146
|
-
assert.ok(desc.includes("openWorldHint"), `${name} collapsed description must still carry an openWorldHint rationale`);
|
|
147
|
-
// Annotation must be an explicit boolean (never null) per OpenAI review.
|
|
148
|
-
assert.equal(typeof tool.config.annotations?.["openWorldHint"], "boolean", `${name} must have an explicit boolean openWorldHint annotation`);
|
|
149
|
-
}
|
|
150
|
-
assert.equal(reviewedCount, OPENAI_ALLOWED_TOOL_COUNT, "must cover all 53 reviewed tools");
|
|
151
|
-
});
|
|
152
|
-
test("open-world tools keep openWorldHint:true rationale; read tools keep false", () => {
|
|
153
|
-
const server = makeComposedServer();
|
|
154
|
-
// The 4 reviewed open-world tools carry the true rationale (and not false).
|
|
155
|
-
for (const name of ["send_invoice", "send_quote", "create_webhook", "update_webhook"]) {
|
|
156
|
-
const tool = server.tools.get(name);
|
|
157
|
-
assert.equal(tool.config.annotations?.["openWorldHint"], true, `${name} annotation true`);
|
|
158
|
-
assert.match(tool.config.description, /openWorldHint: true/, `${name} collapsed description must state openWorldHint: true`);
|
|
159
|
-
assert.doesNotMatch(tool.config.description, /openWorldHint: false/, `${name} must not also claim false`);
|
|
160
|
-
}
|
|
161
|
-
// A read-only tool carries the false rationale.
|
|
162
|
-
const li = server.tools.get("list_invoices");
|
|
163
|
-
assert.match(li.config.description, /openWorldHint: false/);
|
|
164
|
-
assert.doesNotMatch(li.config.description, /openWorldHint: true/);
|
|
165
|
-
});
|
|
166
|
-
test("collapse does not break OpenAI redaction / input-strip / annotation behavior", async () => {
|
|
167
|
-
const server = makeComposedServer();
|
|
168
|
-
// Government IDs stripped from input schema.
|
|
169
|
-
assert.equal("taxId" in (server.tools.get("create_client").config.inputSchema ?? {}), false);
|
|
170
|
-
assert.equal("to" in (server.tools.get("send_invoice").config.inputSchema ?? {}), false);
|
|
171
|
-
assert.equal("secret" in (server.tools.get("create_webhook").config.inputSchema ?? {}), false);
|
|
172
|
-
// Output redaction wrapper survives the collapse (handler still redacts).
|
|
173
|
-
const result = await server.tools.get("create_client").handler({ name: "Compose Test Corp" });
|
|
174
|
-
const serialized = JSON.stringify(result);
|
|
175
|
-
assert.equal(serialized.includes("taxId"), false);
|
|
176
|
-
assert.equal(serialized.includes("B12345678"), false);
|
|
177
|
-
assert.equal(serialized.includes("should-not-leak"), false);
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
describe("openai × grouped composition: invariant (3) — catalog is allow-list-only", () => {
|
|
181
|
-
test("list_tool_groups counts exactly the 53 reviewed tools", async () => {
|
|
182
|
-
const server = makeComposedServer();
|
|
183
|
-
const res = await server.tools.get("list_tool_groups").handler({});
|
|
184
|
-
const payload = JSON.parse(res.content[0].text);
|
|
185
|
-
assert.equal(payload.totalTools, OPENAI_ALLOWED_TOOL_COUNT);
|
|
186
|
-
const sum = payload.groups.reduce((acc, g) => acc + g.toolCount, 0);
|
|
187
|
-
assert.equal(sum, OPENAI_ALLOWED_TOOL_COUNT, "group counts must sum to 53");
|
|
188
|
-
assert.ok(payload.groups.every((g) => g.toolCount > 0), "no empty groups listed");
|
|
189
|
-
// Reviewed surface has no fiscal/stay/pos/hr tools → those groups must be absent.
|
|
190
|
-
for (const forbidden of ["fiscal", "stay", "pos", "hr", "banking"]) {
|
|
191
|
-
assert.ok(!payload.groups.some((g) => g.group === forbidden), `group ${forbidden} must not appear (no reviewed tools in it)`);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
test("search_tools NEVER returns a tool outside the reviewed allow-list (browse all)", async () => {
|
|
195
|
-
const server = makeComposedServer();
|
|
196
|
-
// Empty query + huge limit = browse the entire catalog.
|
|
197
|
-
const res = await server.tools.get("search_tools").handler({ query: "", limit: 500 });
|
|
198
|
-
const payload = JSON.parse(res.content[0].text);
|
|
199
|
-
assert.equal(payload.count, OPENAI_ALLOWED_TOOL_COUNT, "browse-all returns exactly the 53");
|
|
200
|
-
const leaks = payload.tools.filter((t) => !OPENAI_REVIEWED_TOOL_ALLOWLIST.has(t.name));
|
|
201
|
-
assert.deepEqual(leaks, [], "search_tools must not surface any non-reviewed tool");
|
|
202
|
-
});
|
|
203
|
-
test("search_tools for a fiscal term yields nothing (fiscal tools are not in the catalog)", async () => {
|
|
204
|
-
const server = makeComposedServer();
|
|
205
|
-
// 'modelo 303' would top-rank get_modelo_303_summary on the full grouped
|
|
206
|
-
// server. Here that tool is NOT in the catalog, so it must not appear.
|
|
207
|
-
const res = await server.tools.get("search_tools").handler({ query: "modelo 303 verifactu" });
|
|
208
|
-
const payload = JSON.parse(res.content[0].text);
|
|
209
|
-
const leaks = payload.tools.filter((t) => !OPENAI_REVIEWED_TOOL_ALLOWLIST.has(t.name));
|
|
210
|
-
assert.deepEqual(leaks, [], "no fiscal/non-reviewed tool may be returned");
|
|
211
|
-
assert.ok(!payload.tools.some((t) => t.name === "get_modelo_303_summary"), "get_modelo_303_summary (non-reviewed) must never surface");
|
|
212
|
-
});
|
|
213
|
-
test("search_tools group filter cannot reach a non-reviewed group", async () => {
|
|
214
|
-
const server = makeComposedServer();
|
|
215
|
-
// Even explicitly asking for the fiscal group returns nothing, because no
|
|
216
|
-
// fiscal tool was catalogued.
|
|
217
|
-
const res = await server.tools.get("search_tools").handler({
|
|
218
|
-
query: "",
|
|
219
|
-
group: "fiscal",
|
|
220
|
-
limit: 100,
|
|
221
|
-
});
|
|
222
|
-
const payload = JSON.parse(res.content[0].text);
|
|
223
|
-
assert.equal(payload.tools.length, 0, "fiscal group is empty in the reviewed catalog");
|
|
224
|
-
});
|
|
225
|
-
test("describe_tool serves reviewed tools but REJECTS any tool outside the 53", async () => {
|
|
226
|
-
const server = makeComposedServer();
|
|
227
|
-
// A reviewed tool resolves.
|
|
228
|
-
const ok = await server.tools.get("describe_tool").handler({ name: "list_invoices" });
|
|
229
|
-
const okPayload = JSON.parse(ok.content[0].text);
|
|
230
|
-
assert.equal(ok.isError, undefined);
|
|
231
|
-
assert.equal(okPayload.name, "list_invoices");
|
|
232
|
-
// Every non-reviewed tool is rejected (not in the catalog).
|
|
233
|
-
for (const name of NON_REVIEWED_TOOLS) {
|
|
234
|
-
const res = await server.tools.get("describe_tool").handler({ name });
|
|
235
|
-
assert.equal(res.isError, true, `describe_tool('${name}') must error — not in reviewed catalog`);
|
|
236
|
-
const payload = JSON.parse(res.content[0].text);
|
|
237
|
-
assert.match(payload.error, /No tool named/);
|
|
238
|
-
// Suggestions can only ever be reviewed tools — never a leak.
|
|
239
|
-
for (const s of payload.suggestions) {
|
|
240
|
-
assert.ok(OPENAI_REVIEWED_TOOL_ALLOWLIST.has(s), `describe_tool suggestion '${s}' must be a reviewed tool, not a leak`);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
//# sourceMappingURL=openai-grouped-compose.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-grouped-compose.test.js","sourceRoot":"","sources":["../../src/__tests__/openai-grouped-compose.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the OpenAI-safe MCP profile.
|
|
3
|
-
*
|
|
4
|
-
* The public ChatGPT app intentionally exposes a narrower tool surface than
|
|
5
|
-
* the full MCP server. This prevents regulated or sensitive workflows added
|
|
6
|
-
* to the general MCP server from becoming part of the OpenAI submission by
|
|
7
|
-
* accident.
|
|
8
|
-
*/
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=openai-profile.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-profile.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/openai-profile.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|