@frihet/mcp-server 1.16.6 → 1.17.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.md +92 -31
- package/dist/agent-onboarding.d.ts +98 -0
- package/dist/agent-onboarding.js +275 -0
- package/dist/api-origin.d.ts +9 -0
- package/dist/api-origin.js +41 -0
- package/dist/canary/mcp-harness.d.ts +77 -0
- package/dist/canary/mcp-harness.js +549 -0
- package/dist/capability-truth.d.ts +29 -0
- package/dist/capability-truth.js +254 -0
- package/dist/client-interface.d.ts +22 -14
- package/dist/client.d.ts +114 -18
- package/dist/client.js +488 -56
- package/dist/demo-client.d.ts +16 -13
- package/dist/demo-client.js +171 -17
- package/dist/demo-fixtures.d.ts +3 -3
- package/dist/demo-fixtures.js +7 -7
- package/dist/fiscal-aliases.d.ts +44 -0
- package/dist/fiscal-aliases.js +62 -0
- package/dist/index.js +41 -56
- package/dist/logger.d.ts +2 -2
- package/dist/logger.js +140 -8
- package/dist/observability.d.ts +18 -29
- package/dist/observability.js +192 -105
- package/dist/openai-profile.d.ts +25 -21
- package/dist/openai-profile.js +1166 -156
- package/dist/openai-review-contract.d.ts +15 -6
- package/dist/openai-review-contract.js +715 -41
- package/dist/openai-review-oauth.d.ts +47 -0
- package/dist/openai-review-oauth.js +73 -3
- package/dist/prompts/register-all.d.ts +2 -0
- package/dist/prompts/register-all.js +2 -0
- package/dist/public-capability-contract.d.ts +39 -0
- package/dist/public-capability-contract.js +186 -0
- package/dist/redaction.d.ts +10 -0
- package/dist/redaction.js +74 -0
- package/dist/resources/register-all.js +6 -12
- package/dist/server-composition.d.ts +16 -0
- package/dist/server-composition.js +44 -0
- package/dist/tool-exposure.d.ts +25 -22
- package/dist/tool-exposure.js +199 -77
- package/dist/tools/accountingClose.d.ts +14 -5
- package/dist/tools/accountingClose.js +41 -23
- package/dist/tools/backend-availability.d.ts +3 -3
- package/dist/tools/backend-availability.js +3 -3
- package/dist/tools/clients.js +9 -9
- package/dist/tools/crm.js +22 -21
- package/dist/tools/deposits.js +30 -11
- package/dist/tools/einvoice.d.ts +1 -1
- package/dist/tools/expenses.d.ts +16 -0
- package/dist/tools/expenses.js +47 -27
- package/dist/tools/hr.d.ts +2 -3
- package/dist/tools/hr.js +8 -9
- package/dist/tools/intelligence.js +2 -2
- package/dist/tools/invoices.js +150 -47
- package/dist/tools/payroll.d.ts +5 -8
- package/dist/tools/payroll.js +19 -32
- package/dist/tools/permissions.d.ts +4 -7
- package/dist/tools/permissions.js +11 -14
- package/dist/tools/products.js +6 -6
- package/dist/tools/quotes.js +109 -24
- package/dist/tools/shared.d.ts +1431 -75
- package/dist/tools/shared.js +386 -76
- package/dist/tools/team.js +18 -14
- package/dist/tools/vendors.js +9 -9
- package/dist/tools/webhooks.js +35 -30
- package/dist/types.d.ts +28 -4
- package/docs/agent-onboarding.json +381 -0
- package/package.json +30 -7
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public capability truth for the full Frihet MCP surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Registration proves only that a tool name and handler exist. It does not
|
|
5
|
+
* prove that the backing API family is deployed, enabled for a workspace, or
|
|
6
|
+
* authorized for the caller. This profile adds a conservative, machine-readable
|
|
7
|
+
* fact to tools/list and corrects action annotations on the non-OpenAI surface.
|
|
8
|
+
*
|
|
9
|
+
* The OpenAI review profile reuses the same annotation corrections so every
|
|
10
|
+
* public surface reports side effects consistently.
|
|
11
|
+
*/
|
|
12
|
+
import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
13
|
+
export declare const CAPABILITY_META_KEY = "io.frihet/capability";
|
|
14
|
+
export type CapabilityCallability = "api_dependent" | "runtime_checked" | "deferred" | "unavailable" | "local";
|
|
15
|
+
export type ExternalSideEffect = "email_or_invitation" | "webhook_delivery_or_configuration" | "fiscal_or_einvoice_submission" | "external_provider_read" | "external_provider_configuration" | "money_movement" | "channel_sync";
|
|
16
|
+
export interface PublicCapabilityTruth {
|
|
17
|
+
readonly registered: true;
|
|
18
|
+
readonly callability: CapabilityCallability;
|
|
19
|
+
readonly canonicalOperation: string;
|
|
20
|
+
readonly writesFrihet: boolean;
|
|
21
|
+
readonly externalInteraction: boolean;
|
|
22
|
+
readonly externalSideEffects: readonly ExternalSideEffect[];
|
|
23
|
+
}
|
|
24
|
+
export declare function correctToolAnnotations(name: string, annotations: ToolAnnotations | undefined): ToolAnnotations;
|
|
25
|
+
export declare function buildPublicCapabilityTruth(name: string, annotations: ToolAnnotations | undefined): PublicCapabilityTruth;
|
|
26
|
+
export declare function buildLocalDiscoveryCapability(name: string): PublicCapabilityTruth;
|
|
27
|
+
/** Must run after grouped exposure (when grouped) and before registration. */
|
|
28
|
+
export declare function applyPublicCapabilityTruth(server: any): void;
|
|
29
|
+
//# sourceMappingURL=capability-truth.d.ts.map
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public capability truth for the full Frihet MCP surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Registration proves only that a tool name and handler exist. It does not
|
|
5
|
+
* prove that the backing API family is deployed, enabled for a workspace, or
|
|
6
|
+
* authorized for the caller. This profile adds a conservative, machine-readable
|
|
7
|
+
* fact to tools/list and corrects action annotations on the non-OpenAI surface.
|
|
8
|
+
*
|
|
9
|
+
* The OpenAI review profile reuses the same annotation corrections so every
|
|
10
|
+
* public surface reports side effects consistently.
|
|
11
|
+
*/
|
|
12
|
+
export const CAPABILITY_META_KEY = "io.frihet/capability";
|
|
13
|
+
const RUNTIME_CHECKED = new Set([
|
|
14
|
+
"anomaly_list",
|
|
15
|
+
"attendance_clock_in",
|
|
16
|
+
"attendance_clock_out",
|
|
17
|
+
"frihet_aiem_calculate",
|
|
18
|
+
"frihet_bank_rule_create",
|
|
19
|
+
"frihet_bank_rules_list",
|
|
20
|
+
"frihet_gl_entry_approve",
|
|
21
|
+
"frihet_gl_entry_audit_log",
|
|
22
|
+
"frihet_gl_entry_reject",
|
|
23
|
+
"frihet_modelo_200_summary",
|
|
24
|
+
"frihet_modelo_202_summary",
|
|
25
|
+
"frihet_modelo_415_summary",
|
|
26
|
+
"frihet_modelo_418_summary",
|
|
27
|
+
"frihet_modelo_425_summary",
|
|
28
|
+
"frihet_portal_domain_add",
|
|
29
|
+
"frihet_portal_domain_remove",
|
|
30
|
+
"frihet_portal_domain_verify",
|
|
31
|
+
"frihet_portal_onboard_link_generate",
|
|
32
|
+
"frihet_tax_id_vies_lookup",
|
|
33
|
+
"gestoria_template_create",
|
|
34
|
+
"get_modelo_130_summary",
|
|
35
|
+
"get_modelo_180_summary",
|
|
36
|
+
"get_modelo_303_summary",
|
|
37
|
+
"get_modelo_347_summary",
|
|
38
|
+
"get_modelo_390_summary",
|
|
39
|
+
"leave_approve",
|
|
40
|
+
"leave_cancel",
|
|
41
|
+
"leave_list",
|
|
42
|
+
"leave_reject",
|
|
43
|
+
"leave_request_create",
|
|
44
|
+
"onboarding_persona_set",
|
|
45
|
+
"onboarding_status",
|
|
46
|
+
"overtime_report",
|
|
47
|
+
"payroll_checklist",
|
|
48
|
+
"payroll_export",
|
|
49
|
+
"period_close_status",
|
|
50
|
+
"permissions_matrix",
|
|
51
|
+
"permissions_me",
|
|
52
|
+
"verifactu_resubmit",
|
|
53
|
+
"verifactu_status",
|
|
54
|
+
"send_einvoice",
|
|
55
|
+
"get_einvoice_status",
|
|
56
|
+
"validate_einvoice_xml",
|
|
57
|
+
"export_datev",
|
|
58
|
+
"einvoice_export",
|
|
59
|
+
"face_submit",
|
|
60
|
+
"face_status",
|
|
61
|
+
"ticketbai_submit",
|
|
62
|
+
"ticketbai_status",
|
|
63
|
+
]);
|
|
64
|
+
const DEFERRED = new Set([
|
|
65
|
+
"period_close",
|
|
66
|
+
"period_reopen",
|
|
67
|
+
"gestoria_message_send",
|
|
68
|
+
"gestoria_messages_list",
|
|
69
|
+
"gestoria_template_bulk_send",
|
|
70
|
+
"gestoria_aging_consolidated",
|
|
71
|
+
"create_reservation",
|
|
72
|
+
"sync_channel",
|
|
73
|
+
]);
|
|
74
|
+
const UNAVAILABLE = new Set(["ksef_submit"]);
|
|
75
|
+
const DESTRUCTIVE_UPDATES = new Set([
|
|
76
|
+
// These writes can synchronously enqueue delivery to workspace webhooks.
|
|
77
|
+
// Once an external endpoint receives the event, that disclosure cannot be
|
|
78
|
+
// recalled even if the Frihet record itself remains editable.
|
|
79
|
+
"create_invoice",
|
|
80
|
+
"duplicate_invoice",
|
|
81
|
+
"create_credit_note",
|
|
82
|
+
"create_expense",
|
|
83
|
+
"create_quote",
|
|
84
|
+
"create_client",
|
|
85
|
+
"log_client_activity",
|
|
86
|
+
"create_product",
|
|
87
|
+
"frihet_gl_entry_approve",
|
|
88
|
+
"frihet_gl_entry_reject",
|
|
89
|
+
"send_einvoice",
|
|
90
|
+
"categorize_transaction",
|
|
91
|
+
"update_client",
|
|
92
|
+
"update_deposit",
|
|
93
|
+
"apply_deposit",
|
|
94
|
+
"refund_deposit",
|
|
95
|
+
"update_expense",
|
|
96
|
+
"leave_approve",
|
|
97
|
+
"leave_reject",
|
|
98
|
+
"leave_cancel",
|
|
99
|
+
"attendance_clock_out",
|
|
100
|
+
"update_invoice",
|
|
101
|
+
"send_invoice",
|
|
102
|
+
"mark_invoice_paid",
|
|
103
|
+
"update_kitchen_ticket",
|
|
104
|
+
"onboarding_persona_set",
|
|
105
|
+
"update_product",
|
|
106
|
+
"update_quote",
|
|
107
|
+
"send_quote",
|
|
108
|
+
"update_recurring_invoice",
|
|
109
|
+
"sync_channel",
|
|
110
|
+
"update_team_member_role",
|
|
111
|
+
"update_time_entry",
|
|
112
|
+
"update_vendor",
|
|
113
|
+
"update_webhook",
|
|
114
|
+
"match_transaction_to_invoice",
|
|
115
|
+
"verifactu_resubmit",
|
|
116
|
+
"pause_recurring_invoice",
|
|
117
|
+
"resume_recurring_invoice",
|
|
118
|
+
"run_recurring_now",
|
|
119
|
+
"frihet_portal_domain_verify",
|
|
120
|
+
"face_submit",
|
|
121
|
+
"ticketbai_submit",
|
|
122
|
+
"frihet_portal_domain_add",
|
|
123
|
+
]);
|
|
124
|
+
const NON_IDEMPOTENT = new Set([
|
|
125
|
+
"create_invoice",
|
|
126
|
+
"duplicate_invoice",
|
|
127
|
+
"create_credit_note",
|
|
128
|
+
"update_invoice",
|
|
129
|
+
"mark_invoice_paid",
|
|
130
|
+
"delete_invoice",
|
|
131
|
+
"create_expense",
|
|
132
|
+
"update_expense",
|
|
133
|
+
"create_quote",
|
|
134
|
+
"update_quote",
|
|
135
|
+
"delete_quote",
|
|
136
|
+
"create_client",
|
|
137
|
+
"log_client_activity",
|
|
138
|
+
"update_client",
|
|
139
|
+
"create_product",
|
|
140
|
+
"update_product",
|
|
141
|
+
"update_vendor",
|
|
142
|
+
"send_invoice",
|
|
143
|
+
"send_quote",
|
|
144
|
+
"sync_channel",
|
|
145
|
+
"verifactu_resubmit",
|
|
146
|
+
"frihet_portal_domain_verify",
|
|
147
|
+
"pause_recurring_invoice",
|
|
148
|
+
"resume_recurring_invoice",
|
|
149
|
+
]);
|
|
150
|
+
const WRITE_OVERRIDES = new Set(["frihet_portal_domain_verify"]);
|
|
151
|
+
const EXTERNAL_SIDE_EFFECTS = {
|
|
152
|
+
create_invoice: ["webhook_delivery_or_configuration", "fiscal_or_einvoice_submission"],
|
|
153
|
+
duplicate_invoice: ["webhook_delivery_or_configuration"],
|
|
154
|
+
create_credit_note: ["webhook_delivery_or_configuration"],
|
|
155
|
+
update_invoice: ["webhook_delivery_or_configuration", "fiscal_or_einvoice_submission"],
|
|
156
|
+
mark_invoice_paid: ["webhook_delivery_or_configuration", "fiscal_or_einvoice_submission"],
|
|
157
|
+
delete_invoice: ["webhook_delivery_or_configuration", "fiscal_or_einvoice_submission"],
|
|
158
|
+
create_expense: ["webhook_delivery_or_configuration"],
|
|
159
|
+
update_expense: ["webhook_delivery_or_configuration"],
|
|
160
|
+
create_quote: ["webhook_delivery_or_configuration"],
|
|
161
|
+
update_quote: ["webhook_delivery_or_configuration"],
|
|
162
|
+
delete_quote: ["webhook_delivery_or_configuration"],
|
|
163
|
+
create_client: ["webhook_delivery_or_configuration"],
|
|
164
|
+
log_client_activity: ["webhook_delivery_or_configuration"],
|
|
165
|
+
update_client: ["webhook_delivery_or_configuration"],
|
|
166
|
+
create_product: ["webhook_delivery_or_configuration"],
|
|
167
|
+
update_product: ["webhook_delivery_or_configuration"],
|
|
168
|
+
send_invoice: [
|
|
169
|
+
"email_or_invitation",
|
|
170
|
+
"webhook_delivery_or_configuration",
|
|
171
|
+
"fiscal_or_einvoice_submission",
|
|
172
|
+
],
|
|
173
|
+
send_quote: ["email_or_invitation", "webhook_delivery_or_configuration"],
|
|
174
|
+
invite_team_member: ["email_or_invitation"],
|
|
175
|
+
create_webhook: ["webhook_delivery_or_configuration"],
|
|
176
|
+
update_webhook: ["webhook_delivery_or_configuration"],
|
|
177
|
+
delete_webhook: ["webhook_delivery_or_configuration"],
|
|
178
|
+
test_webhook: ["webhook_delivery_or_configuration"],
|
|
179
|
+
send_einvoice: ["fiscal_or_einvoice_submission"],
|
|
180
|
+
face_submit: ["fiscal_or_einvoice_submission"],
|
|
181
|
+
face_status: ["external_provider_read"],
|
|
182
|
+
ticketbai_submit: ["fiscal_or_einvoice_submission"],
|
|
183
|
+
verifactu_resubmit: ["fiscal_or_einvoice_submission"],
|
|
184
|
+
gestoria_message_send: ["email_or_invitation"],
|
|
185
|
+
gestoria_template_bulk_send: ["email_or_invitation"],
|
|
186
|
+
frihet_tax_id_vies_lookup: ["external_provider_read"],
|
|
187
|
+
frihet_portal_domain_add: ["external_provider_configuration"],
|
|
188
|
+
frihet_portal_domain_verify: [
|
|
189
|
+
"external_provider_read",
|
|
190
|
+
"external_provider_configuration",
|
|
191
|
+
],
|
|
192
|
+
frihet_portal_domain_remove: ["external_provider_configuration"],
|
|
193
|
+
refund_sale: ["money_movement"],
|
|
194
|
+
sync_channel: ["channel_sync"],
|
|
195
|
+
};
|
|
196
|
+
function callabilityFor(name) {
|
|
197
|
+
if (UNAVAILABLE.has(name))
|
|
198
|
+
return "unavailable";
|
|
199
|
+
if (DEFERRED.has(name))
|
|
200
|
+
return "deferred";
|
|
201
|
+
if (RUNTIME_CHECKED.has(name))
|
|
202
|
+
return "runtime_checked";
|
|
203
|
+
return "api_dependent";
|
|
204
|
+
}
|
|
205
|
+
export function correctToolAnnotations(name, annotations) {
|
|
206
|
+
const externalInteraction = Object.hasOwn(EXTERNAL_SIDE_EFFECTS, name);
|
|
207
|
+
return {
|
|
208
|
+
...annotations,
|
|
209
|
+
...(WRITE_OVERRIDES.has(name) ? { readOnlyHint: false } : {}),
|
|
210
|
+
...(DESTRUCTIVE_UPDATES.has(name) ? { destructiveHint: true } : {}),
|
|
211
|
+
...(NON_IDEMPOTENT.has(name) ? { idempotentHint: false } : {}),
|
|
212
|
+
...(externalInteraction ? { openWorldHint: true } : {}),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export function buildPublicCapabilityTruth(name, annotations) {
|
|
216
|
+
const effects = Object.hasOwn(EXTERNAL_SIDE_EFFECTS, name)
|
|
217
|
+
? EXTERNAL_SIDE_EFFECTS[name]
|
|
218
|
+
: [];
|
|
219
|
+
return {
|
|
220
|
+
registered: true,
|
|
221
|
+
callability: callabilityFor(name),
|
|
222
|
+
canonicalOperation: name,
|
|
223
|
+
writesFrihet: annotations?.readOnlyHint !== true,
|
|
224
|
+
externalInteraction: effects.length > 0,
|
|
225
|
+
externalSideEffects: effects,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
export function buildLocalDiscoveryCapability(name) {
|
|
229
|
+
return {
|
|
230
|
+
registered: true,
|
|
231
|
+
callability: "local",
|
|
232
|
+
canonicalOperation: name,
|
|
233
|
+
writesFrihet: false,
|
|
234
|
+
externalInteraction: false,
|
|
235
|
+
externalSideEffects: [],
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/** Must run after grouped exposure (when grouped) and before registration. */
|
|
239
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
240
|
+
export function applyPublicCapabilityTruth(server) {
|
|
241
|
+
const originalRegisterTool = server.registerTool.bind(server);
|
|
242
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
243
|
+
server.registerTool = (name, config, handler) => {
|
|
244
|
+
const annotations = correctToolAnnotations(name, config?.annotations);
|
|
245
|
+
const capability = buildPublicCapabilityTruth(name, annotations);
|
|
246
|
+
config.annotations = annotations;
|
|
247
|
+
config._meta = {
|
|
248
|
+
...(config?._meta ?? {}),
|
|
249
|
+
[CAPABILITY_META_KEY]: capability,
|
|
250
|
+
};
|
|
251
|
+
return originalRegisterTool(name, config, handler);
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=capability-truth.js.map
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* classes satisfy this interface via structural typing. Tool registration
|
|
6
6
|
* functions depend on this interface so they can work with either client.
|
|
7
7
|
*/
|
|
8
|
-
import type { PaginatedResponse } from "./types.js";
|
|
8
|
+
import type { CreateWebhookInput, CreateWebhookResult, PaginatedResponse, UpdateWebhookInput, Webhook } from "./types.js";
|
|
9
9
|
export interface IFrihetClient {
|
|
10
10
|
listInvoices(params?: {
|
|
11
11
|
limit?: number;
|
|
@@ -21,7 +21,12 @@ export interface IFrihetClient {
|
|
|
21
21
|
getInvoice(id: string): Promise<Record<string, unknown>>;
|
|
22
22
|
createInvoice(data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
23
23
|
updateInvoice(id: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Resolves to the soft-cancel payload when the backend answered 200 (non-draft
|
|
26
|
+
* invoice CANCELLED, not destroyed — VeriFactu hash chain), or void/undefined
|
|
27
|
+
* when it answered 204 (draft really removed). See `FrihetClient.deleteInvoice`.
|
|
28
|
+
*/
|
|
29
|
+
deleteInvoice(id: string): Promise<Record<string, unknown> | void>;
|
|
25
30
|
searchInvoices(query: string, params?: {
|
|
26
31
|
limit?: number;
|
|
27
32
|
offset?: number;
|
|
@@ -83,7 +88,8 @@ export interface IFrihetClient {
|
|
|
83
88
|
getQuote(id: string): Promise<Record<string, unknown>>;
|
|
84
89
|
createQuote(data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
85
90
|
updateQuote(id: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
86
|
-
|
|
91
|
+
/** Same 200-cancel / 204-destroy contract as {@link IFrihetClient.deleteInvoice}. */
|
|
92
|
+
deleteQuote(id: string): Promise<Record<string, unknown> | void>;
|
|
87
93
|
listVendors(params?: {
|
|
88
94
|
q?: string;
|
|
89
95
|
limit?: number;
|
|
@@ -97,8 +103,8 @@ export interface IFrihetClient {
|
|
|
97
103
|
deleteVendor(id: string): Promise<void>;
|
|
98
104
|
sendInvoice(id: string, to?: string): Promise<Record<string, unknown>>;
|
|
99
105
|
markInvoicePaid(id: string, paidDate?: string): Promise<Record<string, unknown>>;
|
|
100
|
-
getInvoicePdf(id: string): Promise<
|
|
101
|
-
getInvoiceEInvoice(invoiceId: string): Promise<
|
|
106
|
+
getInvoicePdf(id: string): Promise<import("./client.js").BinaryDocument>;
|
|
107
|
+
getInvoiceEInvoice(invoiceId: string): Promise<import("./client.js").EInvoiceDocument>;
|
|
102
108
|
createCreditNote(invoiceId: string, data: {
|
|
103
109
|
reason: string;
|
|
104
110
|
reasonDescription?: string;
|
|
@@ -110,13 +116,15 @@ export interface IFrihetClient {
|
|
|
110
116
|
daysOverdue?: number;
|
|
111
117
|
}): Promise<any>;
|
|
112
118
|
sendQuote(id: string, to?: string): Promise<Record<string, unknown>>;
|
|
113
|
-
listWebhooks(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
listWebhooks(): Promise<{
|
|
120
|
+
data: Webhook[];
|
|
121
|
+
total: number;
|
|
122
|
+
_demo?: true;
|
|
123
|
+
_demoNotice?: string;
|
|
124
|
+
}>;
|
|
125
|
+
getWebhook(id: string): Promise<Webhook>;
|
|
126
|
+
createWebhook(data: CreateWebhookInput): Promise<CreateWebhookResult>;
|
|
127
|
+
updateWebhook(id: string, data: UpdateWebhookInput): Promise<Webhook>;
|
|
120
128
|
deleteWebhook(id: string): Promise<void>;
|
|
121
129
|
listClientContacts(clientId: string, params?: {
|
|
122
130
|
limit?: number;
|
|
@@ -519,7 +527,7 @@ export interface IFrihetClient {
|
|
|
519
527
|
eventType?: string;
|
|
520
528
|
}): Promise<Record<string, unknown>>;
|
|
521
529
|
exportPayroll(params: {
|
|
522
|
-
format: "a3" | "contasol" | "sage" | "
|
|
530
|
+
format: "a3" | "contasol" | "sage" | "siltra";
|
|
523
531
|
month: string;
|
|
524
532
|
}): Promise<Record<string, unknown>>;
|
|
525
533
|
getPayrollChecklist(params: {
|
|
@@ -532,7 +540,7 @@ export interface IFrihetClient {
|
|
|
532
540
|
getPermissionsMatrix(): Promise<Record<string, unknown>>;
|
|
533
541
|
getMyPermissions(): Promise<Record<string, unknown>>;
|
|
534
542
|
getCurrentPeriod(params?: {
|
|
535
|
-
|
|
543
|
+
fiscalYear?: string;
|
|
536
544
|
}): Promise<Record<string, unknown>>;
|
|
537
545
|
closePeriod(data: {
|
|
538
546
|
type: "monthly" | "quarterly";
|
package/dist/client.d.ts
CHANGED
|
@@ -11,11 +11,63 @@
|
|
|
11
11
|
* (`req.query.cursor`, functions/src/publicApi.ts in Frihet-ERP). `after`
|
|
12
12
|
* is never sent on the wire. See src/__tests__/pagination-cursor-param.test.ts.
|
|
13
13
|
*/
|
|
14
|
-
import type { PaginatedResponse } from "./types.js";
|
|
14
|
+
import type { CreateWebhookInput, CreateWebhookResult, PaginatedResponse, UpdateWebhookInput, Webhook } from "./types.js";
|
|
15
|
+
/**
|
|
16
|
+
* Hard size caps for document responses. Enforced TWICE: precheck on
|
|
17
|
+
* `Content-Length` (so an honest server doesn't waste bandwidth) and after
|
|
18
|
+
* streaming (so a missing/lying `Content-Length` still can't trigger an
|
|
19
|
+
* unbounded allocation).
|
|
20
|
+
*
|
|
21
|
+
* - PDF: 25 MiB — generous for any ERP-issued invoice PDF, including
|
|
22
|
+
* embedded logos, Facturae XML attachments, and stamp signatures.
|
|
23
|
+
* - XML: 5 MiB — UBL / Facturae / PEPPOL documents stay well under 1 MiB
|
|
24
|
+
* in practice; 5 MiB absorbs any historical / annex-laden outlier.
|
|
25
|
+
*
|
|
26
|
+
* Anything larger is rejected with `413 payload_too_large` BEFORE we allocate
|
|
27
|
+
* — the user sees a clean error, the worker doesn't OOM.
|
|
28
|
+
*/
|
|
29
|
+
export declare const MAX_PDF_BYTES: number;
|
|
30
|
+
export declare const MAX_XML_BYTES: number;
|
|
31
|
+
/**
|
|
32
|
+
* Bounded binary document response. Always base64-encoded because MCP
|
|
33
|
+
* `structuredContent` is JSON-only — raw `Uint8Array` would coerce to a
|
|
34
|
+
* sparse object on the wire.
|
|
35
|
+
*/
|
|
36
|
+
export interface BinaryDocument {
|
|
37
|
+
/** Echoed id from the request (invoice id), so callers can correlate. */
|
|
38
|
+
id: string;
|
|
39
|
+
/** Verbatim `Content-Type` from the response (e.g. `application/pdf`). */
|
|
40
|
+
contentType: string;
|
|
41
|
+
/** Byte length of the decoded body. Equal to the decoded base64 byte length. */
|
|
42
|
+
sizeBytes: number;
|
|
43
|
+
/** Base64-encoded bytes. */
|
|
44
|
+
base64: string;
|
|
45
|
+
/** Filename hint parsed from `Content-Disposition`, when present. */
|
|
46
|
+
filename?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Bounded XML document response (UBL / CII / Facturae / PEPPOL / FatturaPA /
|
|
50
|
+
* XRechnung — anything declared `application/xml` or `text/xml`).
|
|
51
|
+
*/
|
|
52
|
+
export interface XmlDocument {
|
|
53
|
+
/** Echoed id from the request (invoice id). */
|
|
54
|
+
id: string;
|
|
55
|
+
/** Strictly decoded UTF-8 XML text. */
|
|
56
|
+
xml: string;
|
|
57
|
+
/** Verbatim `Content-Type` from the response. */
|
|
58
|
+
contentType: string;
|
|
59
|
+
/** Byte length of the decoded UTF-8 body. */
|
|
60
|
+
sizeBytes: number;
|
|
61
|
+
/** Filename hint parsed from `Content-Disposition`, when present. */
|
|
62
|
+
filename?: string;
|
|
63
|
+
}
|
|
64
|
+
/** `/invoices/:id/xml` serves XML or a Factur-X PDF, depending on storage MIME. */
|
|
65
|
+
export type EInvoiceDocument = XmlDocument | BinaryDocument;
|
|
15
66
|
export declare class FrihetApiError extends Error {
|
|
16
67
|
readonly statusCode: number;
|
|
17
68
|
readonly errorCode: string;
|
|
18
|
-
|
|
69
|
+
readonly detail?: string | undefined;
|
|
70
|
+
constructor(statusCode: number, errorCode: string, message?: string, detail?: string | undefined);
|
|
19
71
|
}
|
|
20
72
|
export interface FrihetClientOptions {
|
|
21
73
|
/**
|
|
@@ -23,13 +75,32 @@ export interface FrihetClientOptions {
|
|
|
23
75
|
* Cloudflare Workers should pass ≤25000 to leave margin under the ~30s limit.
|
|
24
76
|
*/
|
|
25
77
|
timeoutMs?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Internal second factor for API keys provisioned by Frihet OAuth Workers.
|
|
80
|
+
* Ordinary dashboard/API keys must omit it. The value is sent only to the
|
|
81
|
+
* already-normalized API origin and is never included in logs or errors.
|
|
82
|
+
*/
|
|
83
|
+
oauthServiceSecret?: string;
|
|
26
84
|
}
|
|
27
85
|
export declare class FrihetClient {
|
|
28
86
|
private readonly apiKey;
|
|
29
87
|
private readonly baseUrl;
|
|
30
88
|
private readonly timeoutMs;
|
|
89
|
+
private readonly oauthServiceSecret?;
|
|
31
90
|
constructor(apiKey: string, baseUrl?: string, options?: FrihetClientOptions);
|
|
32
91
|
private request;
|
|
92
|
+
/** Fetch a raw response. The caller owns timeout and body consumption. */
|
|
93
|
+
private fetchRaw;
|
|
94
|
+
/** Consume one response body without ever retaining more than `maxBytes`. */
|
|
95
|
+
private readBoundedBody;
|
|
96
|
+
/**
|
|
97
|
+
* Bounded document fetch — ONE call, ONE Response, dispatch on Content-Type.
|
|
98
|
+
*
|
|
99
|
+
* Success and error bodies use the same bounded reader. The abort timer stays
|
|
100
|
+
* active until the body is complete, and a normal success performs one GET.
|
|
101
|
+
* A 429 may retry, matching the generic JSON client path.
|
|
102
|
+
*/
|
|
103
|
+
private requestDocument;
|
|
33
104
|
private sleep;
|
|
34
105
|
/**
|
|
35
106
|
* Wrapper for endpoints whose backend wraps the payload in a `{ data, meta }`
|
|
@@ -46,10 +117,15 @@ export declare class FrihetClient {
|
|
|
46
117
|
* output schema (id/clientName/items/success all read as `undefined`). This
|
|
47
118
|
* unwraps to `body.data`. Every create/update/action mutation routes through
|
|
48
119
|
* here for exactly this reason; single-object reads (`getInvoice`/…) have since
|
|
49
|
-
* #64. `deleteX` methods
|
|
50
|
-
*
|
|
51
|
-
*
|
|
120
|
+
* #64. Most `deleteX` methods keep `request` (they return `void` — the tool
|
|
121
|
+
* discards the body and synthesizes `{ success, id }`, so there is nothing to
|
|
122
|
+
* unwrap). `deleteInvoice`/`deleteQuote` are the EXCEPTION and route through
|
|
123
|
+
* here: their backend answers 204 for a real delete but 200 + `{ data, meta }`
|
|
124
|
+
* when it soft-CANCELS a non-draft document instead (see those methods).
|
|
125
|
+
* Only unwraps a non-array-object `data` (see guard below), so an
|
|
52
126
|
* array-`data` list envelope and any non-enveloped body pass through unchanged.
|
|
127
|
+
* A 204 yields `undefined` from `request`, which falls through untouched — that
|
|
128
|
+
* `undefined` is what tells the delete tools "destroyed, not cancelled".
|
|
53
129
|
*
|
|
54
130
|
* Only unwraps when the body is an object carrying a `data` property that is
|
|
55
131
|
* itself a (non-array) object — i.e. a genuine single-object envelope. It is
|
|
@@ -75,7 +151,21 @@ export declare class FrihetClient {
|
|
|
75
151
|
getInvoice(id: string): Promise<Record<string, unknown>>;
|
|
76
152
|
createInvoice(data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
77
153
|
updateInvoice(id: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
78
|
-
|
|
154
|
+
/**
|
|
155
|
+
* DELETE /invoices/{id} — NOT an unconditional destroy.
|
|
156
|
+
*
|
|
157
|
+
* The backend refuses to destroy a non-draft invoice (VeriFactu hash-chain
|
|
158
|
+
* integrity) and soft-CANCELS it instead, and it distinguishes the two
|
|
159
|
+
* outcomes on the wire (`publicApi.ts` DELETE branch):
|
|
160
|
+
* - 204 No Content → the draft row was really removed
|
|
161
|
+
* - 200 + `{ data: { id, status: 'cancelled', previousStatus,
|
|
162
|
+
* cancelledVia }, meta }` → the document still exists, now cancelled
|
|
163
|
+
*
|
|
164
|
+
* This used to be typed `Promise<void>` and the body was thrown away, so the
|
|
165
|
+
* tool reported "deleted successfully" for a document that was still there.
|
|
166
|
+
* Resolves to the unwrapped soft-cancel payload on 200, `undefined` on 204.
|
|
167
|
+
*/
|
|
168
|
+
deleteInvoice(id: string): Promise<Record<string, unknown> | undefined>;
|
|
79
169
|
searchInvoices(query: string, params?: {
|
|
80
170
|
limit?: number;
|
|
81
171
|
offset?: number;
|
|
@@ -137,7 +227,13 @@ export declare class FrihetClient {
|
|
|
137
227
|
getQuote(id: string): Promise<Record<string, unknown>>;
|
|
138
228
|
createQuote(data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
139
229
|
updateQuote(id: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
140
|
-
|
|
230
|
+
/**
|
|
231
|
+
* DELETE /quotes/{id} — same two-outcome contract as {@link deleteInvoice}:
|
|
232
|
+
* the backend soft-CANCELS a non-draft quote (200 + body), destroys only a
|
|
233
|
+
* clean draft with no delivery/response/attachment/conversion evidence (204),
|
|
234
|
+
* and refuses a protected draft with 409.
|
|
235
|
+
*/
|
|
236
|
+
deleteQuote(id: string): Promise<Record<string, unknown> | undefined>;
|
|
141
237
|
listVendors(params?: {
|
|
142
238
|
q?: string;
|
|
143
239
|
limit?: number;
|
|
@@ -151,8 +247,8 @@ export declare class FrihetClient {
|
|
|
151
247
|
deleteVendor(id: string): Promise<void>;
|
|
152
248
|
sendInvoice(id: string, to?: string): Promise<Record<string, unknown>>;
|
|
153
249
|
markInvoicePaid(id: string, paidDate?: string): Promise<Record<string, unknown>>;
|
|
154
|
-
getInvoicePdf(id: string): Promise<
|
|
155
|
-
getInvoiceEInvoice(invoiceId: string): Promise<
|
|
250
|
+
getInvoicePdf(id: string): Promise<BinaryDocument>;
|
|
251
|
+
getInvoiceEInvoice(invoiceId: string): Promise<EInvoiceDocument>;
|
|
156
252
|
/**
|
|
157
253
|
* `POST /v1/invoices/:id/credit-note` — creates a rectificativa DRAFT.
|
|
158
254
|
*
|
|
@@ -176,13 +272,13 @@ export declare class FrihetClient {
|
|
|
176
272
|
daysOverdue?: number;
|
|
177
273
|
}): Promise<any>;
|
|
178
274
|
sendQuote(id: string, to?: string): Promise<Record<string, unknown>>;
|
|
179
|
-
listWebhooks(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
getWebhook(id: string): Promise<
|
|
184
|
-
createWebhook(data:
|
|
185
|
-
updateWebhook(id: string, data:
|
|
275
|
+
listWebhooks(): Promise<{
|
|
276
|
+
data: Webhook[];
|
|
277
|
+
total: number;
|
|
278
|
+
}>;
|
|
279
|
+
getWebhook(id: string): Promise<Webhook>;
|
|
280
|
+
createWebhook(data: CreateWebhookInput): Promise<CreateWebhookResult>;
|
|
281
|
+
updateWebhook(id: string, data: UpdateWebhookInput): Promise<Webhook>;
|
|
186
282
|
deleteWebhook(id: string): Promise<void>;
|
|
187
283
|
listClientContacts(clientId: string, params?: {
|
|
188
284
|
limit?: number;
|
|
@@ -585,7 +681,7 @@ export declare class FrihetClient {
|
|
|
585
681
|
eventType?: string;
|
|
586
682
|
}): Promise<Record<string, unknown>>;
|
|
587
683
|
exportPayroll(params: {
|
|
588
|
-
format: "a3" | "contasol" | "sage" | "
|
|
684
|
+
format: "a3" | "contasol" | "sage" | "siltra";
|
|
589
685
|
month: string;
|
|
590
686
|
}): Promise<Record<string, unknown>>;
|
|
591
687
|
getPayrollChecklist(params: {
|
|
@@ -598,7 +694,7 @@ export declare class FrihetClient {
|
|
|
598
694
|
getPermissionsMatrix(): Promise<Record<string, unknown>>;
|
|
599
695
|
getMyPermissions(): Promise<Record<string, unknown>>;
|
|
600
696
|
getCurrentPeriod(params?: {
|
|
601
|
-
|
|
697
|
+
fiscalYear?: string;
|
|
602
698
|
}): Promise<Record<string, unknown>>;
|
|
603
699
|
closePeriod(data: {
|
|
604
700
|
type: "monthly" | "quarterly";
|