@happyvertical/smrt-commerce 0.60.11 → 0.60.12

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 (39) hide show
  1. package/AGENTS.md +3 -0
  2. package/agents/estimate-conversion.md +42 -0
  3. package/dist/chunks/{ContractLineItemCollection-BFWJ2e6a.js → ContractLineItemCollection-CwGdWgQE.js} +4 -4
  4. package/dist/chunks/{ContractLineItemCollection-BFWJ2e6a.js.map → ContractLineItemCollection-CwGdWgQE.js.map} +1 -1
  5. package/dist/chunks/{DocumentTaxCollection-MFfprLH-.js → DocumentTaxCollection-BfuNqFNm.js} +16 -10
  6. package/dist/chunks/DocumentTaxCollection-BfuNqFNm.js.map +1 -0
  7. package/dist/chunks/{InvoiceCollection-D_8NXuaw.js → InvoiceCollection-Cxz6Z1uv.js} +9 -9
  8. package/dist/chunks/{InvoiceCollection-D_8NXuaw.js.map → InvoiceCollection-Cxz6Z1uv.js.map} +1 -1
  9. package/dist/chunks/{TaxCodeCollection-Bc-Z8alx.js → TaxCodeCollection-CKGI5AzL.js} +2 -2
  10. package/dist/chunks/{TaxCodeCollection-Bc-Z8alx.js.map → TaxCodeCollection-CKGI5AzL.js.map} +1 -1
  11. package/dist/chunks/{TaxComponentCollection-DUY7A2sU.js → TaxComponentCollection-r9ipXMGD.js} +3 -3
  12. package/dist/chunks/{TaxComponentCollection-DUY7A2sU.js.map → TaxComponentCollection-r9ipXMGD.js.map} +1 -1
  13. package/dist/chunks/{allocation-integrity-ri5cUYXB.js → allocation-integrity-Qge856lI.js} +6 -6
  14. package/dist/chunks/{allocation-integrity-ri5cUYXB.js.map → allocation-integrity-Qge856lI.js.map} +1 -1
  15. package/dist/chunks/{contract-money-By1XIzp_.js → contract-money-ByflBBOV.js} +38 -7
  16. package/dist/chunks/contract-money-ByflBBOV.js.map +1 -0
  17. package/dist/chunks/{invoice-posting-BfnOyqBR.js → invoice-posting-DeixlpG-.js} +3 -3
  18. package/dist/chunks/{invoice-posting-BfnOyqBR.js.map → invoice-posting-DeixlpG-.js.map} +1 -1
  19. package/dist/chunks/{retention-accounting-CASwH8OH.js → retention-accounting-DT3N01yc.js} +8 -8
  20. package/dist/chunks/{retention-accounting-CASwH8OH.js.map → retention-accounting-DT3N01yc.js.map} +1 -1
  21. package/dist/chunks/{tenant-money-barrier-BbbInDGP.js → tenant-money-barrier-BtMoMg85.js} +3 -3
  22. package/dist/chunks/{tenant-money-barrier-BbbInDGP.js.map → tenant-money-barrier-BtMoMg85.js.map} +1 -1
  23. package/dist/contract-money.d.ts +2 -0
  24. package/dist/contract-money.d.ts.map +1 -1
  25. package/dist/estimate-conversion.d.ts +29 -0
  26. package/dist/estimate-conversion.d.ts.map +1 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +173 -58
  30. package/dist/index.js.map +1 -1
  31. package/dist/invoices.js +1 -1
  32. package/dist/manifest.json +32 -2
  33. package/dist/models/Contract.d.ts +6 -0
  34. package/dist/models/Contract.d.ts.map +1 -1
  35. package/dist/smrt-knowledge.json +33 -6
  36. package/dist/smrt-knowledge.okf.md +17 -13
  37. package/package.json +13 -13
  38. package/dist/chunks/DocumentTaxCollection-MFfprLH-.js.map +0 -1
  39. package/dist/chunks/contract-money-By1XIzp_.js.map +0 -1
package/dist/invoices.js CHANGED
@@ -1,3 +1,3 @@
1
- import { S as calculateInvoiceMinorLine, _ as reconcileOrdinaryCreditAccounting, a as reconcileRetainedBaseInvoice, b as syncOrdinaryRefundToAccounting, c as syncRetainedCreditToAccounting, d as toRetainedCreditAccountingInput, f as toRetainedInvoiceAccountingInput, g as reconcileOrdinaryBaseInvoice, h as reconcileOrdinaryAccountingStep, i as reconcileRetainedAccountingStep, l as syncRetainedInvoiceToAccounting, m as readOrdinaryInvoiceAccountingState, n as loadRetainedInvoiceAccountingSnapshot, o as reconcileRetainedCreditAccounting, p as loadOrdinaryCreditAccountingSnapshot, r as readRetainedInvoiceAccountingState, s as releaseRetainedInvoiceToAccounting, t as loadRetainedCreditAccountingSnapshot, u as syncRetainedRefundToAccounting, v as syncOrdinaryCreditToAccounting, x as toOrdinaryCreditAccountingInput, y as syncOrdinaryInvoiceToAccounting } from "./chunks/retention-accounting-CASwH8OH.js";
1
+ import { S as calculateInvoiceMinorLine, _ as reconcileOrdinaryCreditAccounting, a as reconcileRetainedBaseInvoice, b as syncOrdinaryRefundToAccounting, c as syncRetainedCreditToAccounting, d as toRetainedCreditAccountingInput, f as toRetainedInvoiceAccountingInput, g as reconcileOrdinaryBaseInvoice, h as reconcileOrdinaryAccountingStep, i as reconcileRetainedAccountingStep, l as syncRetainedInvoiceToAccounting, m as readOrdinaryInvoiceAccountingState, n as loadRetainedInvoiceAccountingSnapshot, o as reconcileRetainedCreditAccounting, p as loadOrdinaryCreditAccountingSnapshot, r as readRetainedInvoiceAccountingState, s as releaseRetainedInvoiceToAccounting, t as loadRetainedCreditAccountingSnapshot, u as syncRetainedRefundToAccounting, v as syncOrdinaryCreditToAccounting, x as toOrdinaryCreditAccountingInput, y as syncOrdinaryInvoiceToAccounting } from "./chunks/retention-accounting-DT3N01yc.js";
2
2
  import { MoneyValidationError } from "./money.js";
3
3
  export { MoneyValidationError, calculateInvoiceMinorLine, loadOrdinaryCreditAccountingSnapshot, loadRetainedCreditAccountingSnapshot, loadRetainedInvoiceAccountingSnapshot, readOrdinaryInvoiceAccountingState, readRetainedInvoiceAccountingState, reconcileOrdinaryAccountingStep, reconcileOrdinaryBaseInvoice, reconcileOrdinaryCreditAccounting, reconcileRetainedAccountingStep, reconcileRetainedBaseInvoice, reconcileRetainedCreditAccounting, releaseRetainedInvoiceToAccounting, syncOrdinaryCreditToAccounting, syncOrdinaryInvoiceToAccounting, syncOrdinaryRefundToAccounting, syncRetainedCreditToAccounting, syncRetainedInvoiceToAccounting, syncRetainedRefundToAccounting, toOrdinaryCreditAccountingInput, toRetainedCreditAccountingInput, toRetainedInvoiceAccountingInput };
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-commerce",
5
- "packageVersion": "0.60.11",
5
+ "packageVersion": "0.60.12",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-commerce:ContractCollection": {
8
8
  "name": "contractcollection",
@@ -10439,6 +10439,36 @@
10439
10439
  "_meta": {
10440
10440
  "required": true
10441
10441
  }
10442
+ },
10443
+ "sourceEstimateId": {
10444
+ "type": "meta",
10445
+ "required": false,
10446
+ "default": "",
10447
+ "description": "The accepted estimate this order was converted from, if any.",
10448
+ "_meta": {
10449
+ "description": "The accepted estimate this order was converted from, if any.",
10450
+ "underlyingType": "text"
10451
+ }
10452
+ },
10453
+ "conversionRequestId": {
10454
+ "type": "meta",
10455
+ "required": false,
10456
+ "default": "",
10457
+ "description": "The request identity of the conversion that created this order.",
10458
+ "_meta": {
10459
+ "description": "The request identity of the conversion that created this order.",
10460
+ "underlyingType": "text"
10461
+ }
10462
+ },
10463
+ "acceptanceEvidenceRef": {
10464
+ "type": "meta",
10465
+ "required": false,
10466
+ "default": "",
10467
+ "description": "Where the proof of the customer accepting the estimate is kept.",
10468
+ "_meta": {
10469
+ "description": "Where the proof of the customer accepting the estimate is kept.",
10470
+ "underlyingType": "text"
10471
+ }
10442
10472
  }
10443
10473
  },
10444
10474
  "methods": {
@@ -29201,7 +29231,7 @@
29201
29231
  }
29202
29232
  },
29203
29233
  "help": {
29204
- "markdown": "## Overview\n\nEstimates are price quotes you send before a customer commits. Each one belongs\nto a customer, lists its line items and shows how long the price is good for.\n\n## Tasks\n\n### Write an estimate\n\n1. Create a new estimate.\n2. Pick the **{field:customerId}** the quote is for.\n3. Add the line items, then check the **{field:totalAmount}**.\n4. Set **{field:expiryDate}** to the last day the price is good for.\n5. Put your conditions in **{field:terms}** and save.\n\n### Follow it up\n\n1. Set **{field:status}** to sent once it goes out.\n2. Move it to accepted or declined when the customer answers.\n",
29234
+ "markdown": "## Overview\n\nEstimates are price quotes you send before a customer commits. Each one belongs\nto a customer, lists its line items and shows how long the price is good for.\n\n## Tasks\n\n### Write an estimate\n\n1. Create a new estimate.\n2. Pick the **{field:customerId}** the quote is for.\n3. Add the line items, then check the **{field:totalAmount}**.\n4. Set **{field:expiryDate}** to the last day the price is good for.\n5. Put your conditions in **{field:terms}** and save.\n\n### Follow it up\n\n1. Set **{field:status}** to sent once it goes out.\n2. Move it to accepted or declined when the customer answers.\n3. Once accepted, convert it to an order so the work can be billed; the order keeps the estimate's lines and totals and a link back to the quote.\n",
29205
29235
  "fieldRefs": [
29206
29236
  "customerId",
29207
29237
  "expiryDate",
@@ -235,6 +235,12 @@ export declare class Estimate extends SalesContract {
235
235
  export declare class Order extends SalesContract {
236
236
  customerId: string | null;
237
237
  contractType: ContractType;
238
+ /** Accepted Estimate this Order was converted from; empty for a direct Order. */
239
+ sourceEstimateId: Meta<string>;
240
+ /** Idempotency identity of the conversion that created this Order. */
241
+ conversionRequestId: Meta<string>;
242
+ /** Host-owned evidence reference for the customer's acceptance of the Estimate. */
243
+ acceptanceEvidenceRef: Meta<string>;
238
244
  constructor(options?: SalesContractOptions);
239
245
  }
240
246
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Contract.d.ts","sourceRoot":"","sources":["../../src/models/Contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Contract.d.ts","sourceRoot":"","sources":["../../src/models/Contract.ts"],"names":[],"mappings":"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"}
@@ -3,13 +3,13 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-commerce",
6
- "packageVersion": "0.60.11",
6
+ "packageVersion": "0.60.12",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "f9423bde5768c27448171290ef7c664bf3d7e457ac68dffd7ecf8ff6e7372f35",
11
- "packageJson": "27bb1b47f692e77f3b7da033e4c012bfc881db1a76bc174f4249cb5992ca9699",
12
- "agents": "8fae989030badeabdb15109fab804aa7910c01570d449046c24a04678fe432a7",
10
+ "manifest": "7b8b4c08f157995f6873292940bb4674374eaf3839a6913f57be48511f0a7383",
11
+ "packageJson": "5208643bbd2aa2ba66c251b03b44cb35ece47726cc736ac3b06c4a690bd4f654",
12
+ "agents": "f9bb1baf74bd8c0f5ecb097fb631daa5fe0a7ab16e14c2a5a4bc4cdfbfe4503e",
13
13
  "moduleDoc:agents/customer-vendor-ui.md": "2b22e519411a16d8c493496fc168da77b9acd25f6077ea8fbac00cfee3a3501c",
14
14
  "moduleDoc:README.md": "beb2fada61d0babc7aa0528b883a9d47d6c827d876ace1cce04a908338fa01f8",
15
15
  "moduleDoc:agents/invoice-quantity.md": "3a5fbb464c8fe63acc021b2259ba36f052bb22c49b29e503639c5316814e2028",
@@ -27,6 +27,7 @@
27
27
  "moduleDoc:agents/purchasing-ui.md": "d2b413009d466f3320934adf1e30ffbb7278138b859df69635e7c1f77efbbd1c",
28
28
  "moduleDoc:agents/cost-billing.md": "eaedcc68bb5c2ad7994bf1fc873175b6b800a6ca87e04ba6a51e041d4b765561",
29
29
  "moduleDoc:agents/contract-billing-schedules.md": "3a6a0a88279f90dcc6d20dc7f0673601784ed78a06741b3d5354f9f1b13077a4",
30
+ "moduleDoc:agents/estimate-conversion.md": "a1256dce640638dbbcac612fa86e205488dad23f59e805a8225d1ea8d0f5e9c5",
30
31
  "moduleDoc:agents/customer-funds.md": "417af24b9de9c41c89917e3c6e50e324a1baa70de9e45a61772b3d84c8bfeda0",
31
32
  "moduleDoc:agents/observed-purchase-prices.md": "e8e68d733b7b9453b4dbd54e1dcf11e1486b70ee855ac629bb4e6888eb90ca9c",
32
33
  "moduleDoc:agents/received-sales-contract-money.md": "675d728c565346e5d808e8299a55f2543a423853be0ce9abc99dc7041af79570",
@@ -5667,6 +5668,27 @@
5667
5668
  "required": true,
5668
5669
  "related": "Customer",
5669
5670
  "columnType": "UUID"
5671
+ },
5672
+ {
5673
+ "name": "sourceEstimateId",
5674
+ "type": "meta",
5675
+ "required": false,
5676
+ "default": "",
5677
+ "description": "The accepted estimate this order was converted from, if any."
5678
+ },
5679
+ {
5680
+ "name": "conversionRequestId",
5681
+ "type": "meta",
5682
+ "required": false,
5683
+ "default": "",
5684
+ "description": "The request identity of the conversion that created this order."
5685
+ },
5686
+ {
5687
+ "name": "acceptanceEvidenceRef",
5688
+ "type": "meta",
5689
+ "required": false,
5690
+ "default": "",
5691
+ "description": "Where the proof of the customer accepting the estimate is kept."
5670
5692
  }
5671
5693
  ],
5672
5694
  "relationships": [
@@ -22301,7 +22323,7 @@
22301
22323
  "polymorphicAssociations": 0,
22302
22324
  "uuidColumns": 276
22303
22325
  },
22304
- "agentDoc": "# @happyvertical/smrt-commerce\n\nE-commerce with Contract STI hierarchy, invoice lifecycle, payment tracking, payout remittance, and optional ledger integration.\n\n## Models\n\n- **Customer** / **Vendor**: linked to Profile via string ID (not FK). `contacts` (JSON) is written via [`savePartyContacts()`](agents/customer-vendor-ui.md#contact-rows-3501). Customer has creditLimit, paymentTerms, customerType (DTC / WHOLESALE / RETAIL). Vendor has leadTimeDays, minimumOrder, and `payoutAddresses: Record<string, string>` — a flat map from payout-rail-qualified currency code (`USDC-base`, `BTC`, `USD-stripe`, ...) to destination string (EVM address, BTC address, Stripe Connect account id, IBAN). Use `getPayoutAddress(currency)` for a `Map.get`-style lookup; missing entries return `undefined` (caller decides skip-vs-error).\n- **Contract**: concrete STI base. Abstract **SalesContract** owns `customerId`; **PurchaseContract** owns `vendorId`. `channelId` is open-ended. Before upgrade, run `preflightCommercePartyLinks(db)` and repair linked base rows, stray parties, and wrong-branch links. See [README](README.md).\n- **WholesaleOrder**: B2B order. Conventional pairing — customer has `customerType: 'wholesale'`, NET-30/60 terms, delivered via wholesale-portal channel.\n- **ProductionOrder**: manufacturing equivalent of a PurchaseOrder — commission your factory to make finished goods. Consumes raw materials per BOM (`@happyvertical/smrt-manufacturing`) and produces SKU stock (`@happyvertical/smrt-inventory`).\n- **Cart**: transient order-in-progress. Same shape as Order; the application promotes the row from `_meta_type: Cart` to `_meta_type: Order` at checkout instead of copying data between tables.\n- **LicenseSale**: industry-neutral licensing primitive. Carries an *immutable* rights snapshot (`rightsMedium`, `rightsDistributionScope`, `rightsExclusivity`, `rightsDuration`, `rightsTerritory`, `rightsSublicensing`, `rightsDerivatives` — typed `Meta<T>` fields), licensee identity (`licenseeEmail`, optional `licenseeLegalEntity` / `licenseeJurisdiction`), and a signed-PDF reference (`pdfUrl`, `pdfHash`, optional `onChainHashRegistryRef`). Once saved at `ContractStatus.ACCEPTED`, the rights snapshot is frozen — mutating any of the seven rights fields and re-saving throws. The only legal transition out of ACCEPTED is `revoke()` (moves to CANCELLED without touching rights). Useful for stock media, music licensing, code-asset marketplaces, license keys, anywhere rights are sold for a fee.\n- **ContractLineItem**: items on contracts.\n- **Invoice**: status machine `DRAFT → SENT → VIEWED → PARTIAL → PAID` (also OVERDUE, CANCELLED, WRITTEN_OFF). `recognizeRevenue()` creates balanced AR journal entry (DR: Accounts Receivable, CR: Revenue, CR: Tax Payable).\n- **InvoiceLineItem**: fractional-quantity line items with safe minor-unit validation/recalculation on save; the existing-column migration is documented in [invoice quantity persistence](agents/invoice-quantity.md).\n- **Payment** / **PaymentAllocation**: tracks payments against invoices (status: see Gotchas). Carries optional backend-adapter fields for PaymentBackend-routed flows: `backendId` (rail adapter id — `base-usdc`, `btc`, `stripe`, distinct from `externalProvider` which names an accounting sync destination), `backendTxRef` (chain tx hash or gateway settlement id), `nativeAmount` / `nativeCurrency` (what actually arrived), `usdAtQuote` / `usdAtConfirmation` (drift accounting for volatile-currency rails). `Payment.usdDrift()` returns the confirmation - quote delta, or `0` when either side is unset.\n- **PaymentInstrument**: reusable saved payment method (\"card on file\"). Stores only provider references and non-sensitive display metadata (`providerCustomerId`, `providerPaymentMethodId`, brand / last4 / expiry), never raw card data. `isDefault` is domain-managed, not API-writable: `PaymentInstrumentCollection.setDefaultForCustomer(customerId, instrumentId)` validates the target and clears the customer's other defaults (one per customer).\n- **PaymentIntent**: short-lived pre-payment commitment with multi-option semantics. Locks a USD price for a fixed window (default 15 minutes) and lists one or more `PaymentOption`s describing different rails (`backendId`, `currency`, `payTo`, `nativeAmount`, optional `chain` / `memo` / `x402Capable` / `expiresAt`). First option to receive payment wins; the others are implicitly retired. State machine `awaiting_payment → paid → (issued | retired)` plus `expired` and `cancelled`. Mutate via dedicated `markPaid` / `markIssued` / `expire` / `cancel` / `retire` helpers — direct status assignment bypasses the invariant checks. Idempotency: see the natural-key Gotcha.\n- **TenantPaymentAccount**: tenant-owned Stripe Connect account; direct charges with an application fee, account→tenant webhook routing, refunds, no platform fallback. Write only through `connected-payments.ts`; see [connected payments](agents/connected-payments.md).\n- **Payout**: operator-to-supplier remittance. Distinct from Payment because direction, status machine, and chain semantics differ. Status machine `pending → sent → confirmed → failed` (failed is terminal but resettable via `resetFromFailed()` after fixing the underlying problem). References source `paymentId` (plain string) and destination `vendorId` (foreign key). Amount invariant `supplierNet === grossAmount - operatorFee` enforced exactly on save (integer minor units, no tolerance — #2401). `PayoutCollection.createFromPayment()` is the typical entry point; it pulls native amount / currency from the source Payment.\n- **Fulfillment** / **FulfillmentLineItem**: shipment/delivery tracking.\n\n## Recipes (#3590)\n\n`src/recipes.ts` declares four minimal `SmrtRecipe`s, emitted into the built\n`manifest.json` and `smrt-knowledge.json` `recipes`: `commerce.customers`\n(Customer), `commerce.vendors` (Vendor), `commerce.sales` (Order, requires\ncustomers), `commerce.purchases` (PurchaseOrder, requires vendors). Headers\nonly; line items, fulfilment, invoices, and payments are later recipes. Each\nhas user-facing help in `src/<name>.recipe.md` (#3591), and the fields those\nrecipes show carry `@field({ description })` text; keep both in plain\nlanguage for end users and update them when a recipe's fields change. See\n[core recipes](../core/agents/recipes.md).\n\nSee [historical issued sales](agents/historical-sales.md) for exact original source\nmoney, immutable source children and combined historical/live customer funds.\nSee [payment allocation integrity](agents/payment-allocations.md) for atomic splits,\nretry identity, parent corrections and supported dialects.\nSee [tax codes](agents/tax-codes.md) for tenant-owned rate components, default codes,\nand the standard codes every tenant gets.\nSee [document money persistence](agents/document-money.md) for the one money\nmodel: tax-code resolution, atomic aggregate writes, issued snapshots, and\nfrozen fields. Every Invoice and Contract money write needs a tenant. Host\nbootstrap is `ensureCommerceTenant(db, tenantId, { cookbook })`, which returns\n`{ tenantId }`. Money data written by an earlier version is refused with\n`COMMERCE_DATA_NEEDS_UPGRADE` until `smrt db:upgrade-commerce-money` converts\nit; see [money data upgrade](agents/money-upgrade.md).\nSee [Contract money persistence](agents/contract-money.md) for the Contract\naggregate and purchase recoverability.\n\n## Ledger Integration\n\n`@happyvertical/smrt-ledgers` is a regular dependency, loaded lazily via dynamic `import()` (never a static import) so the package graph stays a DAG (#1582). Invoice stores `arJournalId` and `revenueJournalId` as string references. `recognizeRevenue()` creates a balanced AR journal entry; `getArJournal()` returns null when no journal has been recognized yet.\n\n## Billing-period close (#3060)\n\n`src/billing/` closes periods from smrt-subscriptions charges; see the README\nfor usage.\n\n- **Port, not provider.** Period close, events, and credit checkout call only\n the `BillingProvider` port (integer minor units). `stripe.ts` adapts\n `@happyvertical/accounting`, which takes currency *major* units; convert with\n `units.ts` and never hand-roll a Stripe call here. `units.ts` exponents are\n an explicit ISO 4217 table matching the SDK's, never `Intl` display digits\n (CLDR differs for IQD, MGA, … and drifts by ICU release). The SDK's\n `*Minor` fields are already ISO minor units. Capabilities a rail may lack\n (`chargeSavedPaymentMethod`, `createSetupCheckout`, `getCheckout`,\n `setDefaultPaymentMethod`, `markInvoiceUncollectible`) are optional port\n methods: detect them by presence, and keep additions optional (#3139).\n `sendAndReconcile` refuses a provider invoice whose subtotal or total\n disagrees with the local invoice.\n- **Replay safety is identity.** Close, invoice, line, payment, allocation,\n and claim ids are `deterministicId()`s; `BillingLineSource` (conflict key\n `source_type, source_id`) is the only double-billing guard, so never bill a\n source without claiming it, and never widen that key. Each close step is\n persisted before the next; `acquireCloseLease()` serializes workers. A\n close that nets to a credit keeps its claims and ends `carried_forward`;\n its subtotal is a `credit_carry_forward` source for the payer's next billed\n close, which marks the carried close `completed`.\n- **Cycles and flat-plan coverage (#3116).** `cycles.ts` is the schedule\n (pure; `BillingAccount.billingAnchorAt`, null = calendar months). A close\n with no period closes each payer's `lastEndedBillingPeriod()`. Flat-plan\n claims are the exception to \"id from the source\": their `sourceId` is\n `<subscriptionId>:seq:<chainSequence>` and their `periodStart/End` is the\n exact time they bill. `claimFlatWindow()` reads the last number, then the\n coverage (claims ending after the window start), claims one gap as number\n n + 1, and retries on conflict; reading in that order is what makes it\n safe. That numbering, not the period, stops overlaps when schedules or\n payers change — never claim a flat plan outside it, and keep both reads\n bounded (no whole-history scans). Each numbered claim is its own invoice\n line keyed `lineKey|periodStart` (a function of the claim alone, so a\n resumed close rebuilds the same line ids). Proration is\n `prorateMinorUnits()` (half up, BigInt) against the period's full cycle.\n- **System tables.** `BillingAccount`, `BillingPeriodClose`, and\n `BillingLineSource` are not tenant-scoped and have no generated surface.\n Collections stay unexported; models are root exports (#3082). Invoices,\n payments, and journals are written in the seller's tenant; payer-owned\n subscriptions and credit grants in a system context, only after\n verification.\n- **Events** use smrt-jobs' delivery inbox under provider\n `<name>-billing:<sellerTenantId>` and a provider-filtered\n `ForgeProjectionRuntime`, so a runtime never claims another seller's\n events; any other runtime sharing the inbox must pass `providers` too. Only\n events this package acts on are stored: foreign checkouts are `ignored`,\n and only `smrt_*` checkout metadata is kept; it is\n HMAC-signed with the webhook secret at creation (empty values are omitted:\n Stripe drops them), so another integration on the same account cannot forge\n a credit purchase or a card setup; credit is granted only when the\n collected total equals it plus provider tax. Checkout amounts come from the\n re-read session (`getCheckout()`), never the Stripe event, whose amounts are\n in Stripe's unit. Rotating the webhook secret strands in-flight checkouts\n (up to 24 h). `observe()` re-reads provider state, so ordering never depends\n on delivery order; the only provider writes in `observe()` are idempotent\n (making a saved card the default). The standing hook runs inside the event\n transaction and must be idempotent.\n- **Card on file and top-ups (#3139).** A saved card is the payer customer's\n default `PaymentInstrument` (seller tenant, id from the provider method).\n `autoChargeInvoices` bills such payers `charge_automatically`, decided once\n and saved as `Invoice.collectionMethod` before the first push, which every\n retry reuses (never recompute it: a lost push response would record a\n method the provider was not asked for, #3190); activation follows `paid`, never send. An auto top-up attempt\n is a `PENDING` `Payment` (`reference` `auto-top-up:<policyId>`, id from the\n policy and `count()` of its attempts) inserted before the charge, so racing\n evaluations derive one id and one charge; the charge key is derived from\n that id. `applyAutoTopUpOutcome()` must run in a transaction and starts with\n a conditional `UPDATE … WHERE status = 'pending'` row lock, so the hook and\n the `payment` webhook settle once; the grant is keyed by the charge key.\n Never settle an attempt outside that function. Taxed accounts are charged\n with provider tax by default (#3194): the attempt row holds the credit\n (the charge subtotal), the tax is journaled to tax payable at settlement,\n and the attempt's tax decision is recorded in its `notes` so a re-drive\n repeats the same charge request (the provider refuses a key reused with\n different tax). `claimAttempt()` is the only place that decides a\n skip and reports it (`onAutoTopUpSkipped`); `cardOnFile()` and period close\n use `defaultCardInstrument()` — never copy that predicate. A provider write-off moves the local invoice to\n `WRITTEN_OFF` (a later payment, by card or on a rail (#3188), is recorded\n and reinstates the payer; the status stays, so \"paid in full\" for a\n written-off invoice is read from its allocations).\n- **Billing invoices are money-model invoices.** The provider taxes them\n (`providerTaxAmount`, server-managed, not API-writable, added to line tax),\n so every billing line is an explicit `taxMode: 'override'` to the seller's\n `out-of-scope` code. Charges are written before credits so the running\n subtotal never goes negative, and provider tax is written in the save that\n issues the invoice. Revenue posting is idempotent. `ledger.bookCurrency` is\n required (ISO 4217, validated by `BillingRuntime`) and must equal the\n billing currency. `toAccountingInput({ mapping })` emits major units.\n- **Payment rails (#3138).** A runtime has one issuing `provider` and any\n number of `paymentProviders` (unique names, one inbox namespace each; a\n provider with `capabilities.issuesInvoices === false` can never issue).\n `observe()` resolves the provider from the delivery namespace, never the\n payload. Crypto rails implement the port over `@happyvertical/payments`'\n `CryptoCheckoutGateway`; never call BTCPay (or any gateway) from here.\n Settlement is decided by the pure `decideAttempt()` from gateway state and\n `paymentPolicy` — the gateway's `settled` is authoritative and nothing here\n counts confirmations. A `BillingPaymentAttempt` (`(provider, checkout_id)`\n deterministic id) records every state and settles once; grants and payments\n are keyed by checkout id. Invoice payments close the issuer's invoice out of\n band in `observe()` (idempotent) before `project()` records the payment, and\n `settlePaidInvoice` skips (records nothing for) a `paidOutOfBand` invoice\n the rail latched with `outOfBandRequestedAt`; other out-of-band closes are\n recorded as `OTHER` payments. Rails never save cards or charge tax: a taxed\n credit purchase on a rail needs an explicit `automaticTax: false`. Exceptions are flags for operators;\n nothing reverses or refunds automatically.\n- **Known limits**: write-offs post no bad-debt journal (AR stays until paid\n or journaled by an operator); discounts still reach Stripe as negative lines (the SDK's\n line `discount` would change the lines a replayed push reconciles, so it\n needs its own migration); `RetailCharge` has no adjustment ledger. Flat\n plans are monthly, in arrears; plan changes are not prorated (#3119).\n\n## Cross-Package References\n\n- `customerId` → `@foreignKey('Customer')` (hard reference within package)\n- `vendorId` → `@foreignKey('Vendor')` on PurchaseContract only\n- `profileId` → plain string to smrt-profiles\n- `arJournalId`, `revenueJournalId` → plain string to smrt-ledgers\n- `skuId` (on `PaymentIntent`, `LicenseSale`) → plain string to smrt-products\n- `paymentId` (on `PaymentIntent`, `Payout`, `LicenseSale`) → plain string to `Payment` (same package, but kept as plain string for cross-model consistency)\n- `vendorId` on `Payout` → `@foreignKey(Vendor)` (hard reference within package)\n- Billing records reference tenants with `@crossPackageRef('@happyvertical/smrt-users:Tenant')` and charges, plan periods, and adjustments by plain `sourceId`\n\n## Gotchas\n\n- **Optional tenancy**: all models `@TenantScoped({ mode: 'optional' })` + nullable tenantId\n- **Money units and arithmetic**: money fields use signed integer minor units; rates and quantities remain decimal where their contracts require them. Exact rounding, tax-code resolution, safe-integer validation, and journal units are defined in the [commercial money model](agents/money-model.md) and [money calculator](agents/money-calculator.md). Do not reintroduce floating-point tolerances on money paths.\n- **Money documents need a tenant**: models are optionally tenant-scoped, but every Invoice and Contract money write requires one (`MoneyValidationError` `INVALID_MONEY_INPUT`, `Commerce money documents require a tenant`).\n- **Earlier-version money data is refused**: never add a read or conversion path for it. Detection and the one-shot upgrade are in [money data upgrade](agents/money-upgrade.md).\n- **Book currency is required**: `recognizeRevenue()` and `cancelWithRevenueReversal()` take a required `bookCurrency`, which must equal the invoice currency.\n- **Asset-native amounts stay outside line rescales**: `Payment.nativeAmount` and `PaymentIntent.paymentOptions[].nativeAmount` are per-asset values identified by `nativeCurrency`; normalize each asset to its own minor unit before any type conversion, and never apply the commerce ×100 line-money rescale to them.\n- **Invoice controls payment status**: not the Payment model — use `Invoice.updatePaymentStatus()`\n- **Tax comes from tax codes**: the server resolves each line's code and computes line tax and header totals; client totals and a line's stored `taxRate` are never inputs\n- **Profile linking**: separate `ProfileCollection.create()` needed to fetch actual Profile object\n- **PaymentIntent natural key**: `conflictColumns: ['tenant_id', 'offering_ref', 'licensee_email', 'idempotency_key']` — a retried `create` with the same tuple upserts the existing row. Use `PaymentIntentCollection.getOrCreateByIdempotencyKey()` to branch on `{ intent, created }`. Empty natural-key inputs (e.g. blank `idempotencyKey`) disable dedup by design.\n- **Payout state-machine guards**: `markSent` requires a non-empty `backendTxRef`; `markConfirmed` only valid from `SENT`; `markFailed` only valid from `PENDING` / `SENT` (a confirmed payout can't fail — that path is a refund). `resetFromFailed()` is the dedicated escape hatch from `FAILED` back to `PENDING` after an operator fixes the underlying problem; it clears `backendTxRef` so the next attempt picks up a fresh one.\n- **LicenseSale immutability**: rights snapshot freezes on save-with-status-ACCEPTED. The captured snapshot lives in a module-scoped `WeakMap<LicenseSale, string>` so it doesn't interact with the schema or round-trip through `_meta_data`. Drafts (status != ACCEPTED) remain mutable. To \"change\" an issued license: `revoke()` it, then issue a new `LicenseSale` row.\n- **Vendor.payoutAddresses normalization**: the constructor accepts either a `Record<string, string>` or a pre-serialized JSON string. `initialize()` re-normalizes after the framework's option-override pass; `save()` re-normalizes defensively against direct field assignment. Non-string values inside the input map are silently dropped to preserve the typed invariant downstream.\n\n## Commercial UI\n\n`CustomerSelect`/`VendorSelect` are the registered selectors for Customer and\nVendor (`selects` in `src/ui.ts`); models carry `ui.widget` / `ui.format` hints. See\n[customer/vendor UI](agents/customer-vendor-ui.md#selectors-3602).\n\nSee [commercial UI composition](agents/commercial-ui.md) for native form recovery, amount compatibility and backend ownership. Package-owned guides under `agents/` ship with the package.\n\n## Quote and estimate UI\n\n`src/svelte/quote-types.ts` separates unparsed draft strings from explicit\nminor-unit revision DTOs. Native row submitters, caller-owned retry identity and\nextension conventions are documented in [agents/quote-ui.md](agents/quote-ui.md).\n\n## Purchasing UI\n\n`PurchaseOrderEditor` preserves allocation IDs and explicit zeroes, including\nretained reduction rows; the server validates review fingerprints before recording.\nSee [agents/purchasing-ui.md](agents/purchasing-ui.md) for caller responsibilities.\n\n## Exact cost billing\n\nPure signed cost billing and explicit tax rounding are available through the\nindependent `cost-billing` subpath; see [contract](agents/cost-billing.md).\n\nSee [contract billing schedules](agents/contract-billing-schedules.md) for exact\napproved milestone capacity, immutable amendments and atomic canonical invoice issue.\n\n## Customer funds (#4079)\n\nSee [customer advances](agents/customer-funds.md) for explicitly configured\nunapplied-AR/deposit-liability receipts, conserved application/refund capacity,\nreal liability reclassification, final-invoice attestation and mutation guards.\nUse the public commands; `Payment.customerFundsJson` is command-owned.\n\nSee [observed purchase prices](agents/observed-purchase-prices.md) for incomplete\noriginal supplier prices, explicit unknown totals and reviewed completion.\nSee [received sales agreement money](agents/received-sales-contract-money.md) for\nexact complete source Order/Agreement evidence without synthetic lines or tax recognition.\n\nSee [ordinary invoice accounting adjustments](agents/ordinary-accounting.md) for\nnon-retained provider credit applications, recorded refunds and durable recovery.\n",
22326
+ "agentDoc": "# @happyvertical/smrt-commerce\n\nE-commerce with Contract STI hierarchy, invoice lifecycle, payment tracking, payout remittance, and optional ledger integration.\n\n## Models\n\n- **Customer** / **Vendor**: linked to Profile via string ID (not FK). `contacts` (JSON) is written via [`savePartyContacts()`](agents/customer-vendor-ui.md#contact-rows-3501). Customer has creditLimit, paymentTerms, customerType (DTC / WHOLESALE / RETAIL). Vendor has leadTimeDays, minimumOrder, and `payoutAddresses: Record<string, string>` — a flat map from payout-rail-qualified currency code (`USDC-base`, `BTC`, `USD-stripe`, ...) to destination string (EVM address, BTC address, Stripe Connect account id, IBAN). Use `getPayoutAddress(currency)` for a `Map.get`-style lookup; missing entries return `undefined` (caller decides skip-vs-error).\n- **Contract**: concrete STI base. Abstract **SalesContract** owns `customerId`; **PurchaseContract** owns `vendorId`. `channelId` is open-ended. Before upgrade, run `preflightCommercePartyLinks(db)` and repair linked base rows, stray parties, and wrong-branch links. See [README](README.md).\n- **WholesaleOrder**: B2B order. Conventional pairing — customer has `customerType: 'wholesale'`, NET-30/60 terms, delivered via wholesale-portal channel.\n- **ProductionOrder**: manufacturing equivalent of a PurchaseOrder — commission your factory to make finished goods. Consumes raw materials per BOM (`@happyvertical/smrt-manufacturing`) and produces SKU stock (`@happyvertical/smrt-inventory`).\n- **Cart**: transient order-in-progress. Same shape as Order; the application promotes the row from `_meta_type: Cart` to `_meta_type: Order` at checkout instead of copying data between tables.\n- **LicenseSale**: industry-neutral licensing primitive. Carries an *immutable* rights snapshot (`rightsMedium`, `rightsDistributionScope`, `rightsExclusivity`, `rightsDuration`, `rightsTerritory`, `rightsSublicensing`, `rightsDerivatives` — typed `Meta<T>` fields), licensee identity (`licenseeEmail`, optional `licenseeLegalEntity` / `licenseeJurisdiction`), and a signed-PDF reference (`pdfUrl`, `pdfHash`, optional `onChainHashRegistryRef`). Once saved at `ContractStatus.ACCEPTED`, the rights snapshot is frozen — mutating any of the seven rights fields and re-saving throws. The only legal transition out of ACCEPTED is `revoke()` (moves to CANCELLED without touching rights). Useful for stock media, music licensing, code-asset marketplaces, license keys, anywhere rights are sold for a fee.\n- **ContractLineItem**: items on contracts.\n- **Invoice**: status machine `DRAFT → SENT → VIEWED → PARTIAL → PAID` (also OVERDUE, CANCELLED, WRITTEN_OFF). `recognizeRevenue()` creates balanced AR journal entry (DR: Accounts Receivable, CR: Revenue, CR: Tax Payable).\n- **InvoiceLineItem**: fractional-quantity line items with safe minor-unit validation/recalculation on save; the existing-column migration is documented in [invoice quantity persistence](agents/invoice-quantity.md).\n- **Payment** / **PaymentAllocation**: tracks payments against invoices (status: see Gotchas). Carries optional backend-adapter fields for PaymentBackend-routed flows: `backendId` (rail adapter id — `base-usdc`, `btc`, `stripe`, distinct from `externalProvider` which names an accounting sync destination), `backendTxRef` (chain tx hash or gateway settlement id), `nativeAmount` / `nativeCurrency` (what actually arrived), `usdAtQuote` / `usdAtConfirmation` (drift accounting for volatile-currency rails). `Payment.usdDrift()` returns the confirmation - quote delta, or `0` when either side is unset.\n- **PaymentInstrument**: reusable saved payment method (\"card on file\"). Stores only provider references and non-sensitive display metadata (`providerCustomerId`, `providerPaymentMethodId`, brand / last4 / expiry), never raw card data. `isDefault` is domain-managed, not API-writable: `PaymentInstrumentCollection.setDefaultForCustomer(customerId, instrumentId)` validates the target and clears the customer's other defaults (one per customer).\n- **PaymentIntent**: short-lived pre-payment commitment with multi-option semantics. Locks a USD price for a fixed window (default 15 minutes) and lists one or more `PaymentOption`s describing different rails (`backendId`, `currency`, `payTo`, `nativeAmount`, optional `chain` / `memo` / `x402Capable` / `expiresAt`). First option to receive payment wins; the others are implicitly retired. State machine `awaiting_payment → paid → (issued | retired)` plus `expired` and `cancelled`. Mutate via dedicated `markPaid` / `markIssued` / `expire` / `cancel` / `retire` helpers — direct status assignment bypasses the invariant checks. Idempotency: see the natural-key Gotcha.\n- **TenantPaymentAccount**: tenant-owned Stripe Connect account; direct charges with an application fee, account→tenant webhook routing, refunds, no platform fallback. Write only through `connected-payments.ts`; see [connected payments](agents/connected-payments.md).\n- **Payout**: operator-to-supplier remittance. Distinct from Payment because direction, status machine, and chain semantics differ. Status machine `pending → sent → confirmed → failed` (failed is terminal but resettable via `resetFromFailed()` after fixing the underlying problem). References source `paymentId` (plain string) and destination `vendorId` (foreign key). Amount invariant `supplierNet === grossAmount - operatorFee` enforced exactly on save (integer minor units, no tolerance — #2401). `PayoutCollection.createFromPayment()` is the typical entry point; it pulls native amount / currency from the source Payment.\n- **Fulfillment** / **FulfillmentLineItem**: shipment/delivery tracking.\n\n## Recipes (#3590)\n\n`src/recipes.ts` declares four minimal `SmrtRecipe`s, emitted into the built\n`manifest.json` and `smrt-knowledge.json` `recipes`: `commerce.customers`\n(Customer), `commerce.vendors` (Vendor), `commerce.sales` (Order, requires\ncustomers), `commerce.purchases` (PurchaseOrder, requires vendors). Headers\nonly; line items, fulfilment, invoices, and payments are later recipes. Each\nhas user-facing help in `src/<name>.recipe.md` (#3591), and the fields those\nrecipes show carry `@field({ description })` text; keep both in plain\nlanguage for end users and update them when a recipe's fields change. See\n[core recipes](../core/agents/recipes.md).\n\nSee [historical issued sales](agents/historical-sales.md) for exact original source\nmoney, immutable source children and combined historical/live customer funds.\nSee [payment allocation integrity](agents/payment-allocations.md) for atomic splits,\nretry identity, parent corrections and supported dialects.\nSee [tax codes](agents/tax-codes.md) for tenant-owned rate components, default codes,\nand the standard codes every tenant gets.\nSee [document money persistence](agents/document-money.md) for the one money\nmodel: tax-code resolution, atomic aggregate writes, issued snapshots, and\nfrozen fields. Every Invoice and Contract money write needs a tenant. Host\nbootstrap is `ensureCommerceTenant(db, tenantId, { cookbook })`, which returns\n`{ tenantId }`. Money data written by an earlier version is refused with\n`COMMERCE_DATA_NEEDS_UPGRADE` until `smrt db:upgrade-commerce-money` converts\nit; see [money data upgrade](agents/money-upgrade.md).\nSee [Contract money persistence](agents/contract-money.md) for the Contract\naggregate and purchase recoverability.\n\n## Ledger Integration\n\n`@happyvertical/smrt-ledgers` is a regular dependency, loaded lazily via dynamic `import()` (never a static import) so the package graph stays a DAG (#1582). Invoice stores `arJournalId` and `revenueJournalId` as string references. `recognizeRevenue()` creates a balanced AR journal entry; `getArJournal()` returns null when no journal has been recognized yet.\n\n## Billing-period close (#3060)\n\n`src/billing/` closes periods from smrt-subscriptions charges; see the README\nfor usage.\n\n- **Port, not provider.** Period close, events, and credit checkout call only\n the `BillingProvider` port (integer minor units). `stripe.ts` adapts\n `@happyvertical/accounting`, which takes currency *major* units; convert with\n `units.ts` and never hand-roll a Stripe call here. `units.ts` exponents are\n an explicit ISO 4217 table matching the SDK's, never `Intl` display digits\n (CLDR differs for IQD, MGA, … and drifts by ICU release). The SDK's\n `*Minor` fields are already ISO minor units. Capabilities a rail may lack\n (`chargeSavedPaymentMethod`, `createSetupCheckout`, `getCheckout`,\n `setDefaultPaymentMethod`, `markInvoiceUncollectible`) are optional port\n methods: detect them by presence, and keep additions optional (#3139).\n `sendAndReconcile` refuses a provider invoice whose subtotal or total\n disagrees with the local invoice.\n- **Replay safety is identity.** Close, invoice, line, payment, allocation,\n and claim ids are `deterministicId()`s; `BillingLineSource` (conflict key\n `source_type, source_id`) is the only double-billing guard, so never bill a\n source without claiming it, and never widen that key. Each close step is\n persisted before the next; `acquireCloseLease()` serializes workers. A\n close that nets to a credit keeps its claims and ends `carried_forward`;\n its subtotal is a `credit_carry_forward` source for the payer's next billed\n close, which marks the carried close `completed`.\n- **Cycles and flat-plan coverage (#3116).** `cycles.ts` is the schedule\n (pure; `BillingAccount.billingAnchorAt`, null = calendar months). A close\n with no period closes each payer's `lastEndedBillingPeriod()`. Flat-plan\n claims are the exception to \"id from the source\": their `sourceId` is\n `<subscriptionId>:seq:<chainSequence>` and their `periodStart/End` is the\n exact time they bill. `claimFlatWindow()` reads the last number, then the\n coverage (claims ending after the window start), claims one gap as number\n n + 1, and retries on conflict; reading in that order is what makes it\n safe. That numbering, not the period, stops overlaps when schedules or\n payers change — never claim a flat plan outside it, and keep both reads\n bounded (no whole-history scans). Each numbered claim is its own invoice\n line keyed `lineKey|periodStart` (a function of the claim alone, so a\n resumed close rebuilds the same line ids). Proration is\n `prorateMinorUnits()` (half up, BigInt) against the period's full cycle.\n- **System tables.** `BillingAccount`, `BillingPeriodClose`, and\n `BillingLineSource` are not tenant-scoped and have no generated surface.\n Collections stay unexported; models are root exports (#3082). Invoices,\n payments, and journals are written in the seller's tenant; payer-owned\n subscriptions and credit grants in a system context, only after\n verification.\n- **Events** use smrt-jobs' delivery inbox under provider\n `<name>-billing:<sellerTenantId>` and a provider-filtered\n `ForgeProjectionRuntime`, so a runtime never claims another seller's\n events; any other runtime sharing the inbox must pass `providers` too. Only\n events this package acts on are stored: foreign checkouts are `ignored`,\n and only `smrt_*` checkout metadata is kept; it is\n HMAC-signed with the webhook secret at creation (empty values are omitted:\n Stripe drops them), so another integration on the same account cannot forge\n a credit purchase or a card setup; credit is granted only when the\n collected total equals it plus provider tax. Checkout amounts come from the\n re-read session (`getCheckout()`), never the Stripe event, whose amounts are\n in Stripe's unit. Rotating the webhook secret strands in-flight checkouts\n (up to 24 h). `observe()` re-reads provider state, so ordering never depends\n on delivery order; the only provider writes in `observe()` are idempotent\n (making a saved card the default). The standing hook runs inside the event\n transaction and must be idempotent.\n- **Card on file and top-ups (#3139).** A saved card is the payer customer's\n default `PaymentInstrument` (seller tenant, id from the provider method).\n `autoChargeInvoices` bills such payers `charge_automatically`, decided once\n and saved as `Invoice.collectionMethod` before the first push, which every\n retry reuses (never recompute it: a lost push response would record a\n method the provider was not asked for, #3190); activation follows `paid`, never send. An auto top-up attempt\n is a `PENDING` `Payment` (`reference` `auto-top-up:<policyId>`, id from the\n policy and `count()` of its attempts) inserted before the charge, so racing\n evaluations derive one id and one charge; the charge key is derived from\n that id. `applyAutoTopUpOutcome()` must run in a transaction and starts with\n a conditional `UPDATE … WHERE status = 'pending'` row lock, so the hook and\n the `payment` webhook settle once; the grant is keyed by the charge key.\n Never settle an attempt outside that function. Taxed accounts are charged\n with provider tax by default (#3194): the attempt row holds the credit\n (the charge subtotal), the tax is journaled to tax payable at settlement,\n and the attempt's tax decision is recorded in its `notes` so a re-drive\n repeats the same charge request (the provider refuses a key reused with\n different tax). `claimAttempt()` is the only place that decides a\n skip and reports it (`onAutoTopUpSkipped`); `cardOnFile()` and period close\n use `defaultCardInstrument()` — never copy that predicate. A provider write-off moves the local invoice to\n `WRITTEN_OFF` (a later payment, by card or on a rail (#3188), is recorded\n and reinstates the payer; the status stays, so \"paid in full\" for a\n written-off invoice is read from its allocations).\n- **Billing invoices are money-model invoices.** The provider taxes them\n (`providerTaxAmount`, server-managed, not API-writable, added to line tax),\n so every billing line is an explicit `taxMode: 'override'` to the seller's\n `out-of-scope` code. Charges are written before credits so the running\n subtotal never goes negative, and provider tax is written in the save that\n issues the invoice. Revenue posting is idempotent. `ledger.bookCurrency` is\n required (ISO 4217, validated by `BillingRuntime`) and must equal the\n billing currency. `toAccountingInput({ mapping })` emits major units.\n- **Payment rails (#3138).** A runtime has one issuing `provider` and any\n number of `paymentProviders` (unique names, one inbox namespace each; a\n provider with `capabilities.issuesInvoices === false` can never issue).\n `observe()` resolves the provider from the delivery namespace, never the\n payload. Crypto rails implement the port over `@happyvertical/payments`'\n `CryptoCheckoutGateway`; never call BTCPay (or any gateway) from here.\n Settlement is decided by the pure `decideAttempt()` from gateway state and\n `paymentPolicy` — the gateway's `settled` is authoritative and nothing here\n counts confirmations. A `BillingPaymentAttempt` (`(provider, checkout_id)`\n deterministic id) records every state and settles once; grants and payments\n are keyed by checkout id. Invoice payments close the issuer's invoice out of\n band in `observe()` (idempotent) before `project()` records the payment, and\n `settlePaidInvoice` skips (records nothing for) a `paidOutOfBand` invoice\n the rail latched with `outOfBandRequestedAt`; other out-of-band closes are\n recorded as `OTHER` payments. Rails never save cards or charge tax: a taxed\n credit purchase on a rail needs an explicit `automaticTax: false`. Exceptions are flags for operators;\n nothing reverses or refunds automatically.\n- **Known limits**: write-offs post no bad-debt journal (AR stays until paid\n or journaled by an operator); discounts still reach Stripe as negative lines (the SDK's\n line `discount` would change the lines a replayed push reconciles, so it\n needs its own migration); `RetailCharge` has no adjustment ledger. Flat\n plans are monthly, in arrears; plan changes are not prorated (#3119).\n\n## Cross-Package References\n\n- `customerId` → `@foreignKey('Customer')` (hard reference within package)\n- `vendorId` → `@foreignKey('Vendor')` on PurchaseContract only\n- `profileId` → plain string to smrt-profiles\n- `arJournalId`, `revenueJournalId` → plain string to smrt-ledgers\n- `skuId` (on `PaymentIntent`, `LicenseSale`) → plain string to smrt-products\n- `paymentId` (on `PaymentIntent`, `Payout`, `LicenseSale`) → plain string to `Payment` (same package, but kept as plain string for cross-model consistency)\n- `vendorId` on `Payout` → `@foreignKey(Vendor)` (hard reference within package)\n- Billing records reference tenants with `@crossPackageRef('@happyvertical/smrt-users:Tenant')` and charges, plan periods, and adjustments by plain `sourceId`\n\n## Gotchas\n\n- **Optional tenancy**: all models `@TenantScoped({ mode: 'optional' })` + nullable tenantId\n- **Money units and arithmetic**: money fields use signed integer minor units; rates and quantities remain decimal where their contracts require them. Exact rounding, tax-code resolution, safe-integer validation, and journal units are defined in the [commercial money model](agents/money-model.md) and [money calculator](agents/money-calculator.md). Do not reintroduce floating-point tolerances on money paths.\n- **Money documents need a tenant**: models are optionally tenant-scoped, but every Invoice and Contract money write requires one (`MoneyValidationError` `INVALID_MONEY_INPUT`, `Commerce money documents require a tenant`).\n- **Earlier-version money data is refused**: never add a read or conversion path for it. Detection and the one-shot upgrade are in [money data upgrade](agents/money-upgrade.md).\n- **Book currency is required**: `recognizeRevenue()` and `cancelWithRevenueReversal()` take a required `bookCurrency`, which must equal the invoice currency.\n- **Asset-native amounts stay outside line rescales**: `Payment.nativeAmount` and `PaymentIntent.paymentOptions[].nativeAmount` are per-asset values identified by `nativeCurrency`; normalize each asset to its own minor unit before any type conversion, and never apply the commerce ×100 line-money rescale to them.\n- **Invoice controls payment status**: not the Payment model — use `Invoice.updatePaymentStatus()`\n- **Tax comes from tax codes**: the server resolves each line's code and computes line tax and header totals; client totals and a line's stored `taxRate` are never inputs\n- **Profile linking**: separate `ProfileCollection.create()` needed to fetch actual Profile object\n- **PaymentIntent natural key**: `conflictColumns: ['tenant_id', 'offering_ref', 'licensee_email', 'idempotency_key']` — a retried `create` with the same tuple upserts the existing row. Use `PaymentIntentCollection.getOrCreateByIdempotencyKey()` to branch on `{ intent, created }`. Empty natural-key inputs (e.g. blank `idempotencyKey`) disable dedup by design.\n- **Payout state-machine guards**: `markSent` requires a non-empty `backendTxRef`; `markConfirmed` only valid from `SENT`; `markFailed` only valid from `PENDING` / `SENT` (a confirmed payout can't fail — that path is a refund). `resetFromFailed()` is the dedicated escape hatch from `FAILED` back to `PENDING` after an operator fixes the underlying problem; it clears `backendTxRef` so the next attempt picks up a fresh one.\n- **LicenseSale immutability**: rights snapshot freezes on save-with-status-ACCEPTED. The captured snapshot lives in a module-scoped `WeakMap<LicenseSale, string>` so it doesn't interact with the schema or round-trip through `_meta_data`. Drafts (status != ACCEPTED) remain mutable. To \"change\" an issued license: `revoke()` it, then issue a new `LicenseSale` row.\n- **Vendor.payoutAddresses normalization**: the constructor accepts either a `Record<string, string>` or a pre-serialized JSON string. `initialize()` re-normalizes after the framework's option-override pass; `save()` re-normalizes defensively against direct field assignment. Non-string values inside the input map are silently dropped to preserve the typed invariant downstream.\n\n## Commercial UI\n\n`CustomerSelect`/`VendorSelect` are the registered selectors for Customer and\nVendor (`selects` in `src/ui.ts`); models carry `ui.widget` / `ui.format` hints. See\n[customer/vendor UI](agents/customer-vendor-ui.md#selectors-3602).\n\nSee [commercial UI composition](agents/commercial-ui.md) for native form recovery, amount compatibility and backend ownership. Package-owned guides under `agents/` ship with the package.\n\n## Quote and estimate UI\n\n`src/svelte/quote-types.ts` separates unparsed draft strings from explicit\nminor-unit revision DTOs. Native row submitters, caller-owned retry identity and\nextension conventions are documented in [agents/quote-ui.md](agents/quote-ui.md).\n\n## Purchasing UI\n\n`PurchaseOrderEditor` preserves allocation IDs and explicit zeroes, including\nretained reduction rows; the server validates review fingerprints before recording.\nSee [agents/purchasing-ui.md](agents/purchasing-ui.md) for caller responsibilities.\n\n## Exact cost billing\n\nPure signed cost billing and explicit tax rounding are available through the\nindependent `cost-billing` subpath; see [contract](agents/cost-billing.md).\n\nSee [contract billing schedules](agents/contract-billing-schedules.md) for exact\napproved milestone capacity, immutable amendments and atomic canonical invoice issue.\n\nSee [estimate conversion](agents/estimate-conversion.md) for turning an accepted\nEstimate into an idempotent Order with copied lines and lineage.\n\n## Customer funds (#4079)\n\nSee [customer advances](agents/customer-funds.md) for explicitly configured\nunapplied-AR/deposit-liability receipts, conserved application/refund capacity,\nreal liability reclassification, final-invoice attestation and mutation guards.\nUse the public commands; `Payment.customerFundsJson` is command-owned.\n\nSee [observed purchase prices](agents/observed-purchase-prices.md) for incomplete\noriginal supplier prices, explicit unknown totals and reviewed completion.\nSee [received sales agreement money](agents/received-sales-contract-money.md) for\nexact complete source Order/Agreement evidence without synthetic lines or tax recognition.\n\nSee [ordinary invoice accounting adjustments](agents/ordinary-accounting.md) for\nnon-retained provider credit applications, recorded refunds and durable recovery.\n",
22305
22327
  "moduleDocs": [
22306
22328
  {
22307
22329
  "path": "agents/customer-vendor-ui.md",
@@ -22388,6 +22410,11 @@
22388
22410
  "module": "contract-billing-schedules",
22389
22411
  "content": "# Contract milestone billing (#4074)\n\nUse the public Commerce `approveContractBillingSchedule`,\n`issueContractMilestoneInvoice`, `getContractBillingSchedule` and\n`allocateContractMilestones` exports for fixed-value milestone billing. These\ncommands own monetary capacity. The host owns construction scope, estimated cost,\napproval permissions, signed evidence, regional policy and UI.\n\nStart with an accepted, frozen customer `Order` or `Agreement`. The first schedule\nrequires `amendmentMinor: 0`, `expectedRevision: 0`, currency, explicit `basis:\n'net' | 'gross'`, `approvalEvidenceRef`, `taxPolicyEvidenceRef` and exact milestone\n`{ key, label, amountMinor }` entries. Their sum must equal the original Contract\nsubtotal for net basis or totalAmount for gross basis. There is no editable\nschedule override of the accepted Contract value.\n\nEach amendment supplies the current expected revision, a new request identity,\nan explicit signed `amendmentMinor`, approval evidence and the complete next\nschedule. Its ceiling is derived from the original frozen value plus all approved\namendments. Currency/basis cannot change. Already issued milestone keys, labels\nand amounts must remain unchanged. Prior revisions and original Contract money\nremain immutable. Unissued milestones can be rescheduled through an explicitly\napproved revision. Net capacity is not a gross ceiling: each invoice's tax must\nalso be explicitly approved under the versioned policy.\n\n`allocateContractMilestones(totalMinor, weights)` accepts positive integer\nrelative weights. All nonfinal shares truncate exact rational arithmetic; the\nfinal entry receives the exact remainder. For example 100 with weights [1,1,1]\nreturns [33,33,34]. Zero amounts are allowed; negative/unsafe money and nonpositive\nweights reject. The helper chooses no tax policy or commercial percentages.\n\nPrepare a normal canonical draft Invoice and real line items through the public\nCommerce collections. Draft preparation consumes no capacity; an unissued draft may be cancelled\nwithout a claim. Then call:\n\n```ts\nconst claim = await issueContractMilestoneInvoice({\n db, tenantId, contractId, requestId: 'issue:start:v1',\n revision: 1, milestoneKey: 'start', invoiceId,\n approvedMoney: { netMinor: 4000, taxMinor: 200, grossMinor: 4200 },\n invoiceApprovalEvidenceRef: 'approved-invoice:123',\n});\n```\n\nThe command checks same tenant/customer/currency/Contract, derives current line\nmoney, verifies the exact approved net/tax/gross and schedule amount, freezes the\ninvoice and records the claim atomically. Tax-policy evidence is a host-owned\nreviewed version reference, not an instruction to infer tax rates. Preserve the\napproval's policy and original evidence in the host. Ordinary issue against a\nscheduled Contract is refused, including direct creation in a non-draft state.\nExisting issued contract invoices prevent adopting a schedule retroactively.\n\nThe explicit capacity policy is `issued-consumed`: cancellation, credits,\nwrite-offs, payments, retention and refunds never reopen a claimed milestone.\nCredits correct the canonical receivable and settlement continues through existing\nPayment/PaymentAllocation facilities. Unapplied payments remain the deposit cash\nauthority. A replacement billing entitlement requires an explicit approved\namendment; this API does not infer that a credit authorizes re-billing. Applications\nmust explain that policy rather than present a hidden re-bill action. Issued\nclaims remain readable after later amendments and cancellations.\n\nEvery mutation requires the active tenant context and uses the tenant money\nserialization barrier on the exact parent transaction executor. Identical request\nreplay returns the original evidence; a changed payload, stale revision or second\nclaim rejects. A parent rollback reverses both invoice issue and schedule claim.\nA detached read DTO cannot modify persisted state. Ordinary Contract writes and\ndeletes cannot erase schedule history. Host authorization precedes these commands;\nnone is exposed as an unauthenticated generated mutation.\n\n`billingScheduleJson` is `''` when a Contract has no schedule, and the\ncolumn defaults to `''`. A row written before that default holds NULL, which\nhydrates and saves as `''`, so an ordinary save of such a Contract succeeds;\nany other change to the field through `save()` is still refused (#4155).\n`smrt db:upgrade-commerce-money` stores `''` for those NULL rows.\n"
22390
22412
  },
22413
+ {
22414
+ "path": "agents/estimate-conversion.md",
22415
+ "module": "estimate-conversion",
22416
+ "content": "# Estimate to Order conversion (#4730)\n\nUse the public Commerce `convertEstimateToOrder` and `findOrderForEstimate`\nexports to turn an accepted quote into the `Order` that milestone billing starts\nfrom (see [contract billing schedules](contract-billing-schedules.md)). The host\nowns who may accept, the acceptance evidence and any invoicing.\n\n```ts\nconst { orderId } = await convertEstimateToOrder({\n db, tenantId, estimateId, requestId: 'accept:q-1:v1',\n acceptanceEvidenceRef: 'portal-accept:123',\n});\n```\n\nThe Estimate must be in the active tenant, `ACCEPTED`, frozen\n(`moneySnapshotId`), `moneyAuthority: 'calculated'` and have a customer. The\ncommand creates one `Order`, copies every line through the ordinary line save\n(description, quantity, price, discount, tax mode and code, product, sku, dates,\nbilling period, sort order), copies customer, currency, terms, reference, notes\nand channel, then accepts the Order so it freezes with its own snapshot. The\nOrder's `subtotal`, `taxAmount` and `totalAmount` must equal the Estimate's; if\ntax settings changed since the quote froze, the command throws\n`MoneyValidationError` and nothing is written. The Estimate is never modified\nand no invoice is raised.\n\nLineage is stored on the Order as STI meta fields (no new column):\n`sourceEstimateId`, `conversionRequestId` and `acceptanceEvidenceRef`.\n`findOrderForEstimate(db, tenantId, estimateId)` returns the converted Order or\n`null`; meta fields are not queryable, so it scans the tenant's Orders.\n\nIdempotency uses the schedule commands' vocabulary. The same `requestId` and\nevidence replays the existing Order; a changed payload under a reused\n`requestId`, a second conversion of the same Estimate under another `requestId`,\nor a `requestId` already used for a different Estimate is refused. The command\nruns under `withTenantMoneyRuntime` on the caller's executor, requires the\nactive tenant context, and rolls back with a failing parent transaction.\n\nLineage is written only by this command; an ordinary save that changes any of the\nthree fields is refused (`FROZEN_DOCUMENT`), as is creating an Order with them\nset; a converted Order's contract type is also frozen and it cannot be deleted\n(that would erase the only conversion identity). The write phase runs in its own savepoint, so a failed conversion leaves no\nOrder even if you call it inside your own money runtime and catch its error\n"
22417
+ },
22391
22418
  {
22392
22419
  "path": "agents/customer-funds.md",
22393
22420
  "module": "customer-funds",
@@ -22660,7 +22687,7 @@
22660
22687
  }
22661
22688
  },
22662
22689
  "help": {
22663
- "markdown": "## Overview\n\nEstimates are price quotes you send before a customer commits. Each one belongs\nto a customer, lists its line items and shows how long the price is good for.\n\n## Tasks\n\n### Write an estimate\n\n1. Create a new estimate.\n2. Pick the **{field:customerId}** the quote is for.\n3. Add the line items, then check the **{field:totalAmount}**.\n4. Set **{field:expiryDate}** to the last day the price is good for.\n5. Put your conditions in **{field:terms}** and save.\n\n### Follow it up\n\n1. Set **{field:status}** to sent once it goes out.\n2. Move it to accepted or declined when the customer answers.\n",
22690
+ "markdown": "## Overview\n\nEstimates are price quotes you send before a customer commits. Each one belongs\nto a customer, lists its line items and shows how long the price is good for.\n\n## Tasks\n\n### Write an estimate\n\n1. Create a new estimate.\n2. Pick the **{field:customerId}** the quote is for.\n3. Add the line items, then check the **{field:totalAmount}**.\n4. Set **{field:expiryDate}** to the last day the price is good for.\n5. Put your conditions in **{field:terms}** and save.\n\n### Follow it up\n\n1. Set **{field:status}** to sent once it goes out.\n2. Move it to accepted or declined when the customer answers.\n3. Once accepted, convert it to an order so the work can be billed; the order keeps the estimate's lines and totals and a link back to the quote.\n",
22664
22691
  "fieldRefs": [
22665
22692
  "customerId",
22666
22693
  "expiryDate",
@@ -5,10 +5,10 @@ description: "Commerce models for the SMRT framework - contracts, fulfillments,
5
5
  status: "stable"
6
6
  generated:
7
7
  by: "smrt/scripts/generate-knowledge-okf.ts"
8
- at: "2026-11-05T15:48:19Z"
8
+ at: "2026-11-06T07:55:27Z"
9
9
  audience: "internal"
10
10
  evidence_level: "source-inspected"
11
- source_revision: "sha256:32ed5526920972d35a79080ed6cc42ae111c614ba29ec26b2b040d8e013478e8"
11
+ source_revision: "sha256:df81c61c30a297cbc88414f36a109ce506c11d7a0a007850994d60b9108bf9fa"
12
12
  sources:
13
13
  - id: "manifest"
14
14
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/package.json"
@@ -44,39 +44,42 @@ sources:
44
44
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/document-money.md"
45
45
  title: "@happyvertical/smrt-commerce packages/commerce/agents/document-money.md"
46
46
  - id: "agents-11"
47
+ resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/estimate-conversion.md"
48
+ title: "@happyvertical/smrt-commerce packages/commerce/agents/estimate-conversion.md"
49
+ - id: "agents-12"
47
50
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/historical-sales.md"
48
51
  title: "@happyvertical/smrt-commerce packages/commerce/agents/historical-sales.md"
49
- - id: "agents-12"
52
+ - id: "agents-13"
50
53
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/invoice-quantity.md"
51
54
  title: "@happyvertical/smrt-commerce packages/commerce/agents/invoice-quantity.md"
52
- - id: "agents-13"
55
+ - id: "agents-14"
53
56
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/money-calculator.md"
54
57
  title: "@happyvertical/smrt-commerce packages/commerce/agents/money-calculator.md"
55
- - id: "agents-14"
58
+ - id: "agents-15"
56
59
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/money-model.md"
57
60
  title: "@happyvertical/smrt-commerce packages/commerce/agents/money-model.md"
58
- - id: "agents-15"
61
+ - id: "agents-16"
59
62
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/money-upgrade.md"
60
63
  title: "@happyvertical/smrt-commerce packages/commerce/agents/money-upgrade.md"
61
- - id: "agents-16"
64
+ - id: "agents-17"
62
65
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/observed-purchase-prices.md"
63
66
  title: "@happyvertical/smrt-commerce packages/commerce/agents/observed-purchase-prices.md"
64
- - id: "agents-17"
67
+ - id: "agents-18"
65
68
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/ordinary-accounting.md"
66
69
  title: "@happyvertical/smrt-commerce packages/commerce/agents/ordinary-accounting.md"
67
- - id: "agents-18"
70
+ - id: "agents-19"
68
71
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/payment-allocations.md"
69
72
  title: "@happyvertical/smrt-commerce packages/commerce/agents/payment-allocations.md"
70
- - id: "agents-19"
73
+ - id: "agents-20"
71
74
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/purchasing-ui.md"
72
75
  title: "@happyvertical/smrt-commerce packages/commerce/agents/purchasing-ui.md"
73
- - id: "agents-20"
76
+ - id: "agents-21"
74
77
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/quote-ui.md"
75
78
  title: "@happyvertical/smrt-commerce packages/commerce/agents/quote-ui.md"
76
- - id: "agents-21"
79
+ - id: "agents-22"
77
80
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/received-sales-contract-money.md"
78
81
  title: "@happyvertical/smrt-commerce packages/commerce/agents/received-sales-contract-money.md"
79
- - id: "agents-22"
82
+ - id: "agents-23"
80
83
  resource: "https://github.com/happyvertical/smrt/blob/main/packages/commerce/agents/tax-codes.md"
81
84
  title: "@happyvertical/smrt-commerce packages/commerce/agents/tax-codes.md"
82
85
  ---
@@ -102,6 +105,7 @@ sources:
102
105
  - `packages/commerce/agents/customer-funds.md`
103
106
  - `packages/commerce/agents/customer-vendor-ui.md`
104
107
  - `packages/commerce/agents/document-money.md`
108
+ - `packages/commerce/agents/estimate-conversion.md`
105
109
  - `packages/commerce/agents/historical-sales.md`
106
110
  - `packages/commerce/agents/invoice-quantity.md`
107
111
  - `packages/commerce/agents/money-calculator.md`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-commerce",
3
- "version": "0.60.11",
3
+ "version": "0.60.12",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "Commerce models for the SMRT framework - contracts, fulfillments, payments",
6
6
  "type": "module",
@@ -65,17 +65,17 @@
65
65
  "dependencies": {
66
66
  "@happyvertical/accounting": "^0.111.5",
67
67
  "@happyvertical/payments": "^0.111.5",
68
- "@happyvertical/smrt-agents": "0.60.11",
69
- "@happyvertical/smrt-core": "0.60.11",
70
- "@happyvertical/smrt-jobs": "0.60.11",
71
- "@happyvertical/smrt-ledgers": "0.60.11",
72
- "@happyvertical/smrt-products": "0.60.11",
73
- "@happyvertical/smrt-reports": "0.60.11",
74
- "@happyvertical/smrt-subscriptions": "0.60.11",
75
- "@happyvertical/smrt-svelte": "0.60.11",
76
- "@happyvertical/smrt-tenancy": "0.60.11",
77
- "@happyvertical/smrt-types": "0.60.11",
78
- "@happyvertical/smrt-ui": "0.60.11",
68
+ "@happyvertical/smrt-agents": "0.60.12",
69
+ "@happyvertical/smrt-core": "0.60.12",
70
+ "@happyvertical/smrt-jobs": "0.60.12",
71
+ "@happyvertical/smrt-ledgers": "0.60.12",
72
+ "@happyvertical/smrt-products": "0.60.12",
73
+ "@happyvertical/smrt-reports": "0.60.12",
74
+ "@happyvertical/smrt-subscriptions": "0.60.12",
75
+ "@happyvertical/smrt-svelte": "0.60.12",
76
+ "@happyvertical/smrt-tenancy": "0.60.12",
77
+ "@happyvertical/smrt-types": "0.60.12",
78
+ "@happyvertical/smrt-ui": "0.60.12",
79
79
  "@happyvertical/sql": "^0.111.5"
80
80
  },
81
81
  "peerDependencies": {
@@ -87,7 +87,7 @@
87
87
  }
88
88
  },
89
89
  "devDependencies": {
90
- "@happyvertical/smrt-vitest": "0.60.11",
90
+ "@happyvertical/smrt-vitest": "0.60.12",
91
91
  "@sveltejs/package": "^2.5.8",
92
92
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
93
93
  "@testing-library/jest-dom": "^7.0.1",