kassza 1.0.1 → 1.0.2

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.
Files changed (60) hide show
  1. package/README.md +3 -2
  2. package/agents/api.md +4 -4
  3. package/agents/pitfalls.md +3 -0
  4. package/dist/batch/index.d.cts +2 -2
  5. package/dist/batch/index.d.ts +2 -2
  6. package/dist/cli.cjs +2 -2
  7. package/dist/cli.js +2 -2
  8. package/dist/{client-JZ1M1sZX.js → client-8ElbVwSO.js} +2 -2
  9. package/dist/{client-B00WZ3FK.d.cts → client-CXjvVevB.d.cts} +11 -3
  10. package/dist/{client-I_29IPMh.cjs → client-CYS1_Xaz.cjs} +2 -2
  11. package/dist/{client-BJfeFjCM.d.ts → client-CvojBxd9.d.ts} +11 -3
  12. package/dist/{create-once-zeF7GVVP.cjs → create-once-BKUhF1Ov.cjs} +1 -1
  13. package/dist/{create-once-B6cAXyET.js → create-once-DcEjO8QH.js} +1 -1
  14. package/dist/delegation/index.cjs +1 -1
  15. package/dist/delegation/index.d.cts +1 -1
  16. package/dist/delegation/index.d.ts +1 -1
  17. package/dist/delegation/index.js +1 -1
  18. package/dist/index.cjs +3 -3
  19. package/dist/index.d.cts +3 -3
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +3 -3
  22. package/dist/{issue-Dy9zvRK1.js → issue-CUiDvJhQ.js} +92 -3
  23. package/dist/{issue-DReARZnF.cjs → issue-bLLBTt9j.cjs} +92 -3
  24. package/dist/journal/index.cjs +22 -2
  25. package/dist/journal/index.d.cts +1 -1
  26. package/dist/journal/index.d.ts +1 -1
  27. package/dist/journal/index.js +22 -2
  28. package/dist/{journal-JwiYpBui.d.ts → journal-9pfg0if1.d.ts} +1 -0
  29. package/dist/{journal-D_ypAW50.d.cts → journal-Cp_OMWlI.d.cts} +1 -0
  30. package/dist/mcp/index.cjs +1 -1
  31. package/dist/mcp/index.d.cts +1 -1
  32. package/dist/mcp/index.d.ts +1 -1
  33. package/dist/mcp/index.js +1 -1
  34. package/dist/payments/barion.d.cts +2 -2
  35. package/dist/payments/barion.d.ts +2 -2
  36. package/dist/payments/index.cjs +1 -1
  37. package/dist/payments/index.d.cts +4 -4
  38. package/dist/payments/index.d.ts +4 -4
  39. package/dist/payments/index.js +1 -1
  40. package/dist/payments/paypal.d.cts +2 -2
  41. package/dist/payments/paypal.d.ts +2 -2
  42. package/dist/payments/revolut.d.cts +2 -2
  43. package/dist/payments/revolut.d.ts +2 -2
  44. package/dist/payments/simplepay.d.cts +2 -2
  45. package/dist/payments/simplepay.d.ts +2 -2
  46. package/dist/payments/stripe.cjs +30 -1
  47. package/dist/payments/stripe.d.cts +2 -2
  48. package/dist/payments/stripe.d.ts +2 -2
  49. package/dist/payments/stripe.js +30 -1
  50. package/dist/{server-aSw0DUua.js → server-CZTJ3562.js} +38 -10
  51. package/dist/{server-BbR19Oj6.cjs → server-CrmxXPV-.cjs} +38 -10
  52. package/dist/testing/index.cjs +2 -2
  53. package/dist/testing/index.d.cts +1 -1
  54. package/dist/testing/index.d.ts +1 -1
  55. package/dist/testing/index.js +2 -2
  56. package/dist/{types-DeuUqIvU.d.cts → types-DGJiVNxr.d.cts} +1 -1
  57. package/dist/{types-oiDulesz.d.ts → types-DPnHIwQ_.d.ts} +1 -1
  58. package/dist/{webhook-C9IBUdeT.d.ts → webhook-BY7437wx.d.ts} +1 -1
  59. package/dist/{webhook-DF2p_m2Q.d.cts → webhook-CwDbGvSn.d.cts} +1 -1
  60. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
- import { c as resolveInvoice, l as INVOICE_LANGUAGES } from "./create-once-B6cAXyET.js";
1
+ import { c as resolveInvoice, l as INVOICE_LANGUAGES } from "./create-once-DcEjO8QH.js";
2
2
  import { o as isSzamlazzError, r as SzamlazzError } from "./errors-CGGsW0Y5.js";
3
- import { t as createKassza } from "./client-JZ1M1sZX.js";
3
+ import { t as createKassza } from "./client-8ElbVwSO.js";
4
4
  import { i as resolveRecoveryDelay, n as isUncertainOutcome, r as recoverAfterFailure } from "./once-CMhDPrs7.js";
5
5
  import { r as toBudapestDate } from "./dates-DWsZOdaO.js";
6
6
  import { a as isVatRate } from "./vat-B4J5Q0tu.js";
@@ -207,13 +207,14 @@ function resolveTtl(ttlMs) {
207
207
  function createConfirmations(options) {
208
208
  const secret = options.secret ?? randomSecret();
209
209
  const ttlMs = resolveTtl(options.ttlMs);
210
- const sign = async (action, expiresAt, payload) => {
211
- return (await hmacHex("SHA-256", secret, `${action}\n${expiresAt}\n${canonicalJson(payload)}`)).slice(0, SIGNATURE_LENGTH);
210
+ const sign = async (action, expiresAt, day, payload) => {
211
+ return (await hmacHex("SHA-256", secret, `${action}\n${expiresAt}\n${day}\n${canonicalJson(payload)}`)).slice(0, SIGNATURE_LENGTH);
212
212
  };
213
213
  return {
214
214
  async issue(action, payload) {
215
- const expiresAt = options.now().getTime() + ttlMs;
216
- const signature = await sign(action, expiresAt, payload);
215
+ const now = options.now();
216
+ const expiresAt = now.getTime() + ttlMs;
217
+ const signature = await sign(action, expiresAt, toBudapestDate(now), payload);
217
218
  return {
218
219
  token: `${expiresAt.toString(36)}.${signature}`,
219
220
  expiresAt: new Date(expiresAt).toISOString()
@@ -225,14 +226,20 @@ function createConfirmations(options) {
225
226
  const match = TOKEN_PATTERN.exec(token.trim());
226
227
  const expiresAt = match?.[1] === void 0 ? NaN : Number.parseInt(match[1], 36);
227
228
  if (!match?.[2] || !Number.isSafeInteger(expiresAt)) throw new ToolInputError(`A megerősítő kód formátuma érvénytelen. ${again}`);
228
- if (options.now().getTime() > expiresAt) throw new ToolInputError(`A megerősítő kód lejárt. ${again}`);
229
- const expected = await sign(action, expiresAt, payload);
230
- if (!timingSafeEqual(expected, match[2])) throw new ToolInputError(`A megerősítő kód nem ehhez a kéréshez tartozik (az adatok eltérnek az előnézettől). ${again}`);
229
+ const now = options.now();
230
+ if (now.getTime() > expiresAt) throw new ToolInputError(`A megerősítő kód lejárt. ${again}`);
231
+ const today = toBudapestDate(now);
232
+ const expected = await sign(action, expiresAt, today, payload);
233
+ if (!timingSafeEqual(expected, match[2])) {
234
+ const previewDay = toBudapestDate(new Date(expiresAt - ttlMs));
235
+ if (previewDay !== today && timingSafeEqual(await sign(action, expiresAt, previewDay, payload), match[2])) throw new ToolInputError(`A megerősítő kód egy előző napi (${previewDay}) előnézethez tartozik, budapesti idő szerint éjfél után nem érvényes. ${again}`);
236
+ throw new ToolInputError(`A megerősítő kód nem ehhez a kéréshez tartozik (az adatok eltérnek az előnézettől). ${again}`);
237
+ }
231
238
  }
232
239
  };
233
240
  }
234
241
  // src/core/version.ts
235
- const KASSZA_VERSION = "1.0.0";
242
+ const KASSZA_VERSION = "1.0.1";
236
243
  // src/mcp/tool-kit.ts
237
244
  const LOCAL_READ = {
238
245
  readOnlyHint: true,
@@ -1196,10 +1203,28 @@ function reversalOutput(document, reversedNumber, number, created) {
1196
1203
  }
1197
1204
  };
1198
1205
  }
1206
+ const reversalsInFlight = /* @__PURE__ */ new Map();
1207
+ async function oneReversalAtATime(key, run) {
1208
+ for (;;) {
1209
+ const pending = reversalsInFlight.get(key);
1210
+ if (!pending) break;
1211
+ await pending.catch(() => void 0);
1212
+ }
1213
+ const current = run();
1214
+ reversalsInFlight.set(key, current);
1215
+ try {
1216
+ return await current;
1217
+ } finally {
1218
+ if (reversalsInFlight.get(key) === current) reversalsInFlight.delete(key);
1219
+ }
1220
+ }
1199
1221
  async function reverseInvoice(args, context) {
1200
1222
  assertKnownKeys(args, ["invoiceNumber", "confirmation"], "");
1201
1223
  const invoiceNumber = requiredString(args, "invoiceNumber", "");
1202
1224
  await context.confirmations.verify(REVERSE_INVOICE, { invoiceNumber }, args.confirmation, PREVIEW_REVERSAL);
1225
+ return oneReversalAtATime(`invoice:${invoiceNumber}`, () => reverseInvoiceOnce(invoiceNumber, context));
1226
+ }
1227
+ async function reverseInvoiceOnce(invoiceNumber, context) {
1203
1228
  const kassza = context.client();
1204
1229
  const externalId = `${invoiceNumber}/SS`;
1205
1230
  const lookup = () => kassza.invoices.find({ externalId }, { includePdf: false });
@@ -1225,6 +1250,9 @@ async function reverseReceipt(args, context) {
1225
1250
  assertKnownKeys(args, ["receiptNumber", "confirmation"], "");
1226
1251
  const receiptNumber = requiredString(args, "receiptNumber", "");
1227
1252
  await context.confirmations.verify(REVERSE_RECEIPT, { receiptNumber }, args.confirmation, PREVIEW_REVERSAL);
1253
+ return oneReversalAtATime(`receipt:${receiptNumber}`, () => reverseReceiptOnce(receiptNumber, context));
1254
+ }
1255
+ async function reverseReceiptOnce(receiptNumber, context) {
1228
1256
  const kassza = context.client();
1229
1257
  const original = await kassza.receipts.get({
1230
1258
  receiptNumber,
@@ -1,6 +1,6 @@
1
- const require_create_once = require("./create-once-zeF7GVVP.cjs");
1
+ const require_create_once = require("./create-once-BKUhF1Ov.cjs");
2
2
  const require_errors = require("./errors-Bn6pe6yw.cjs");
3
- const require_client = require("./client-I_29IPMh.cjs");
3
+ const require_client = require("./client-CYS1_Xaz.cjs");
4
4
  const require_once = require("./once-BmXfrNbQ.cjs");
5
5
  const require_dates = require("./dates-oOp3ypPP.cjs");
6
6
  const require_vat = require("./vat-BkoiiKm4.cjs");
@@ -207,13 +207,14 @@ function resolveTtl(ttlMs) {
207
207
  function createConfirmations(options) {
208
208
  const secret = options.secret ?? randomSecret();
209
209
  const ttlMs = resolveTtl(options.ttlMs);
210
- const sign = async (action, expiresAt, payload) => {
211
- return (await require_crypto.hmacHex("SHA-256", secret, `${action}\n${expiresAt}\n${canonicalJson(payload)}`)).slice(0, SIGNATURE_LENGTH);
210
+ const sign = async (action, expiresAt, day, payload) => {
211
+ return (await require_crypto.hmacHex("SHA-256", secret, `${action}\n${expiresAt}\n${day}\n${canonicalJson(payload)}`)).slice(0, SIGNATURE_LENGTH);
212
212
  };
213
213
  return {
214
214
  async issue(action, payload) {
215
- const expiresAt = options.now().getTime() + ttlMs;
216
- const signature = await sign(action, expiresAt, payload);
215
+ const now = options.now();
216
+ const expiresAt = now.getTime() + ttlMs;
217
+ const signature = await sign(action, expiresAt, require_dates.toBudapestDate(now), payload);
217
218
  return {
218
219
  token: `${expiresAt.toString(36)}.${signature}`,
219
220
  expiresAt: new Date(expiresAt).toISOString()
@@ -225,14 +226,20 @@ function createConfirmations(options) {
225
226
  const match = TOKEN_PATTERN.exec(token.trim());
226
227
  const expiresAt = match?.[1] === void 0 ? NaN : Number.parseInt(match[1], 36);
227
228
  if (!match?.[2] || !Number.isSafeInteger(expiresAt)) throw new ToolInputError(`A megerősítő kód formátuma érvénytelen. ${again}`);
228
- if (options.now().getTime() > expiresAt) throw new ToolInputError(`A megerősítő kód lejárt. ${again}`);
229
- const expected = await sign(action, expiresAt, payload);
230
- if (!require_crypto.timingSafeEqual(expected, match[2])) throw new ToolInputError(`A megerősítő kód nem ehhez a kéréshez tartozik (az adatok eltérnek az előnézettől). ${again}`);
229
+ const now = options.now();
230
+ if (now.getTime() > expiresAt) throw new ToolInputError(`A megerősítő kód lejárt. ${again}`);
231
+ const today = require_dates.toBudapestDate(now);
232
+ const expected = await sign(action, expiresAt, today, payload);
233
+ if (!require_crypto.timingSafeEqual(expected, match[2])) {
234
+ const previewDay = require_dates.toBudapestDate(new Date(expiresAt - ttlMs));
235
+ if (previewDay !== today && require_crypto.timingSafeEqual(await sign(action, expiresAt, previewDay, payload), match[2])) throw new ToolInputError(`A megerősítő kód egy előző napi (${previewDay}) előnézethez tartozik, budapesti idő szerint éjfél után nem érvényes. ${again}`);
236
+ throw new ToolInputError(`A megerősítő kód nem ehhez a kéréshez tartozik (az adatok eltérnek az előnézettől). ${again}`);
237
+ }
231
238
  }
232
239
  };
233
240
  }
234
241
  // src/core/version.ts
235
- const KASSZA_VERSION = "1.0.0";
242
+ const KASSZA_VERSION = "1.0.1";
236
243
  // src/mcp/tool-kit.ts
237
244
  const LOCAL_READ = {
238
245
  readOnlyHint: true,
@@ -1196,10 +1203,28 @@ function reversalOutput(document, reversedNumber, number, created) {
1196
1203
  }
1197
1204
  };
1198
1205
  }
1206
+ const reversalsInFlight = /* @__PURE__ */ new Map();
1207
+ async function oneReversalAtATime(key, run) {
1208
+ for (;;) {
1209
+ const pending = reversalsInFlight.get(key);
1210
+ if (!pending) break;
1211
+ await pending.catch(() => void 0);
1212
+ }
1213
+ const current = run();
1214
+ reversalsInFlight.set(key, current);
1215
+ try {
1216
+ return await current;
1217
+ } finally {
1218
+ if (reversalsInFlight.get(key) === current) reversalsInFlight.delete(key);
1219
+ }
1220
+ }
1199
1221
  async function reverseInvoice(args, context) {
1200
1222
  assertKnownKeys(args, ["invoiceNumber", "confirmation"], "");
1201
1223
  const invoiceNumber = requiredString(args, "invoiceNumber", "");
1202
1224
  await context.confirmations.verify(REVERSE_INVOICE, { invoiceNumber }, args.confirmation, PREVIEW_REVERSAL);
1225
+ return oneReversalAtATime(`invoice:${invoiceNumber}`, () => reverseInvoiceOnce(invoiceNumber, context));
1226
+ }
1227
+ async function reverseInvoiceOnce(invoiceNumber, context) {
1203
1228
  const kassza = context.client();
1204
1229
  const externalId = `${invoiceNumber}/SS`;
1205
1230
  const lookup = () => kassza.invoices.find({ externalId }, { includePdf: false });
@@ -1225,6 +1250,9 @@ async function reverseReceipt(args, context) {
1225
1250
  assertKnownKeys(args, ["receiptNumber", "confirmation"], "");
1226
1251
  const receiptNumber = requiredString(args, "receiptNumber", "");
1227
1252
  await context.confirmations.verify(REVERSE_RECEIPT, { receiptNumber }, args.confirmation, PREVIEW_REVERSAL);
1253
+ return oneReversalAtATime(`receipt:${receiptNumber}`, () => reverseReceiptOnce(receiptNumber, context));
1254
+ }
1255
+ async function reverseReceiptOnce(receiptNumber, context) {
1228
1256
  const kassza = context.client();
1229
1257
  const original = await kassza.receipts.get({
1230
1258
  receiptNumber,
@@ -1,9 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_once = require("../create-once-zeF7GVVP.cjs");
2
+ const require_create_once = require("../create-once-BKUhF1Ov.cjs");
3
3
  const require_errors = require("../errors-Bn6pe6yw.cjs");
4
4
  const require_binary = require("../binary-CdpKlNNI.cjs");
5
5
  const require_serialize = require("../serialize-DEU7r6Bk.cjs");
6
- const require_issue = require("../issue-DReARZnF.cjs");
6
+ const require_issue = require("../issue-bLLBTt9j.cjs");
7
7
  const require_dates = require("../dates-oOp3ypPP.cjs");
8
8
  const require_rounding = require("../rounding-CHmSK5Z2.cjs");
9
9
  const require_vat = require("../vat-BkoiiKm4.cjs");
@@ -1,7 +1,7 @@
1
1
  import { a as AgentAction, t as KasszaWarning } from "../warnings-DpuYhn39.cjs";
2
2
  import { G as InvoiceType, M as CreateInvoiceInput, d as DocumentErrorMode, p as DocumentHook, st as SzamlazzError } from "../context-zGthvNo2.cjs";
3
3
  import { r as Receipt } from "../types-_HKTOCuQ.cjs";
4
- import { f as TaxpayerInfo, n as Kassza, r as KasszaDefaults } from "../client-B00WZ3FK.cjs";
4
+ import { f as TaxpayerInfo, n as Kassza, r as KasszaDefaults } from "../client-CXjvVevB.cjs";
5
5
  import { n as InvoiceDetails, o as InvoiceDetailsPayment } from "../get-BL4Fr8-P.cjs";
6
6
  type FakeInvoiceTypeCode = "SZ" | "D" | "ES" | "VS" | "HS" | "SS" | "SL";
7
7
  interface FakeAgentSeller {
@@ -1,7 +1,7 @@
1
1
  import { a as AgentAction, t as KasszaWarning } from "../warnings-DpuYhn39.js";
2
2
  import { G as InvoiceType, M as CreateInvoiceInput, d as DocumentErrorMode, p as DocumentHook, st as SzamlazzError } from "../context-BROX7Krw.js";
3
3
  import { r as Receipt } from "../types-Z6rQoqHn.js";
4
- import { f as TaxpayerInfo, n as Kassza, r as KasszaDefaults } from "../client-BJfeFjCM.js";
4
+ import { f as TaxpayerInfo, n as Kassza, r as KasszaDefaults } from "../client-CvojBxd9.js";
5
5
  import { n as InvoiceDetails, o as InvoiceDetailsPayment } from "../get-BL4Fr8-P.js";
6
6
  type FakeInvoiceTypeCode = "SZ" | "D" | "ES" | "VS" | "HS" | "SS" | "SL";
7
7
  interface FakeAgentSeller {
@@ -1,8 +1,8 @@
1
- import { c as resolveInvoice, g as AGENT_ACTIONS, m as emitDocumentEvent, r as registerPaymentOnce, t as createReceiptOnce } from "../create-once-B6cAXyET.js";
1
+ import { c as resolveInvoice, g as AGENT_ACTIONS, m as emitDocumentEvent, r as registerPaymentOnce, t as createReceiptOnce } from "../create-once-DcEjO8QH.js";
2
2
  import { r as SzamlazzError, t as AGENT_ERROR_CODES } from "../errors-CGGsW0Y5.js";
3
3
  import { i as encodeUtf8, n as bytesToBase64 } from "../binary-DuKBSfH-.js";
4
4
  import { a as optionalEl, c as childNumber, d as findChildren, f as parseXml, i as formatXmlNumber, l as childText, n as buildXmlDocument, r as el, s as childBoolean, u as findChild } from "../serialize-CjymGkJj.js";
5
- import { l as createInvoiceOnce, n as issueForPayment, o as convertReceiptToInvoice } from "../issue-Dy9zvRK1.js";
5
+ import { l as createInvoiceOnce, n as issueForPayment, o as convertReceiptToInvoice } from "../issue-CUiDvJhQ.js";
6
6
  import { n as toAgentDate, r as toBudapestDate } from "../dates-DWsZOdaO.js";
7
7
  import { n as decimalPlaces, r as roundMoney } from "../rounding-CZLj4DbV.js";
8
8
  import { i as isHuf, t as NUMERIC_VAT_RATES } from "../vat-B4J5Q0tu.js";
@@ -1,7 +1,7 @@
1
1
  import { t as KasszaWarning } from "./warnings-DpuYhn39.cjs";
2
2
  import { n as KeyValueStore } from "./store-BkaZ8qkU.cjs";
3
3
  type PaymentProvider = "stripe" | "simplepay" | "barion" | "revolut" | "paypal" | (string & {});
4
- type PaymentEventKind = "paid" | "refunded" | "partially-refunded" | "failed" | "other";
4
+ type PaymentEventKind = "paid" | "refunded" | "partially-refunded" | "refund-failed" | "failed" | "other";
5
5
  interface PaymentAmount {
6
6
  readonly value: number;
7
7
  readonly currency: string;
@@ -1,7 +1,7 @@
1
1
  import { t as KasszaWarning } from "./warnings-DpuYhn39.js";
2
2
  import { n as KeyValueStore } from "./store-BkaZ8qkU.js";
3
3
  type PaymentProvider = "stripe" | "simplepay" | "barion" | "revolut" | "paypal" | (string & {});
4
- type PaymentEventKind = "paid" | "refunded" | "partially-refunded" | "failed" | "other";
4
+ type PaymentEventKind = "paid" | "refunded" | "partially-refunded" | "refund-failed" | "failed" | "other";
5
5
  interface PaymentAmount {
6
6
  readonly value: number;
7
7
  readonly currency: string;
@@ -1,4 +1,4 @@
1
- import { i as PaymentEvent, u as PaymentWebhookBaseOptions } from "./types-oiDulesz.js";
1
+ import { i as PaymentEvent, u as PaymentWebhookBaseOptions } from "./types-DPnHIwQ_.js";
2
2
  declare const WEBHOOK_DEDUPE_KEY_PREFIX = "szamlazz:evt:";
3
3
  declare const DEFAULT_DEDUPE_TTL_SECONDS: number;
4
4
  type WebhookHandler = (request: Request) => Promise<Response>;
@@ -1,4 +1,4 @@
1
- import { i as PaymentEvent, u as PaymentWebhookBaseOptions } from "./types-DeuUqIvU.cjs";
1
+ import { i as PaymentEvent, u as PaymentWebhookBaseOptions } from "./types-DGJiVNxr.cjs";
2
2
  declare const WEBHOOK_DEDUPE_KEY_PREFIX = "szamlazz:evt:";
3
3
  declare const DEFAULT_DEDUPE_TTL_SECONDS: number;
4
4
  type WebhookHandler = (request: Request) => Promise<Response>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kassza",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "author": {
5
5
  "name": "futozs",
6
6
  "url": "https://github.com/futozs",