@happyvertical/smrt-commerce 0.57.4 → 0.57.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -0
- package/agents/historical-sales.md +18 -0
- package/agents/ordinary-accounting.md +72 -0
- package/dist/accounting-steps-internal.d.ts +49 -0
- package/dist/accounting-steps-internal.d.ts.map +1 -0
- package/dist/chunks/{ContractLineItemCollection-J4xtRtzE.js → ContractLineItemCollection-D5hBzrct.js} +4 -4
- package/dist/chunks/{ContractLineItemCollection-J4xtRtzE.js.map → ContractLineItemCollection-D5hBzrct.js.map} +1 -1
- package/dist/chunks/{DocumentTaxCollection-C42x0YLW.js → DocumentTaxCollection-C6cI5U89.js} +29 -19
- package/dist/chunks/DocumentTaxCollection-C6cI5U89.js.map +1 -0
- package/dist/chunks/{InvoiceCollection-BIcge9Wl.js → InvoiceCollection-BolwughC.js} +13 -11
- package/dist/chunks/InvoiceCollection-BolwughC.js.map +1 -0
- package/dist/chunks/{TaxCodeCollection-RWdVaheF.js → TaxCodeCollection-CW-tWjkU.js} +2 -2
- package/dist/chunks/{TaxCodeCollection-RWdVaheF.js.map → TaxCodeCollection-CW-tWjkU.js.map} +1 -1
- package/dist/chunks/{TaxComponentCollection-Dt2jeWiC.js → TaxComponentCollection-BiJ9aAe8.js} +3 -3
- package/dist/chunks/{TaxComponentCollection-Dt2jeWiC.js.map → TaxComponentCollection-BiJ9aAe8.js.map} +1 -1
- package/dist/chunks/{allocation-integrity-DJ7-LY1j.js → allocation-integrity-CH-i-hsY.js} +6 -6
- package/dist/chunks/{allocation-integrity-DJ7-LY1j.js.map → allocation-integrity-CH-i-hsY.js.map} +1 -1
- package/dist/chunks/{contract-money-DSRTMoXm.js → contract-money-BMsq4cpL.js} +6 -6
- package/dist/chunks/{contract-money-DSRTMoXm.js.map → contract-money-BMsq4cpL.js.map} +1 -1
- package/dist/chunks/{invoice-posting-BeTPw3h9.js → invoice-posting-IXic4UEP.js} +3 -3
- package/dist/chunks/{invoice-posting-BeTPw3h9.js.map → invoice-posting-IXic4UEP.js.map} +1 -1
- package/dist/chunks/{retention-accounting-Brdj9x-V.js → retention-accounting-c7kY7gFU.js} +504 -89
- package/dist/chunks/retention-accounting-c7kY7gFU.js.map +1 -0
- package/dist/chunks/retention-accounting-internal-DNxLLVvK.js +30 -0
- package/dist/chunks/retention-accounting-internal-DNxLLVvK.js.map +1 -0
- package/dist/chunks/{tenant-money-barrier-DoF6lR8h.js → tenant-money-barrier-DEVLrpaB.js} +3 -3
- package/dist/chunks/{tenant-money-barrier-DoF6lR8h.js.map → tenant-money-barrier-DEVLrpaB.js.map} +1 -1
- package/dist/document-money.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -13
- package/dist/index.js.map +1 -1
- package/dist/invoice-accounting-sync.d.ts.map +1 -1
- package/dist/invoices.d.ts +1 -0
- package/dist/invoices.d.ts.map +1 -1
- package/dist/invoices.js +2 -2
- package/dist/manifest.json +45 -9
- package/dist/models/Invoice.d.ts +2 -0
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/Payment.d.ts +2 -0
- package/dist/models/Payment.d.ts.map +1 -1
- package/dist/models/PaymentAllocation.d.ts.map +1 -1
- package/dist/ordinary-accounting-internal.d.ts +3 -0
- package/dist/ordinary-accounting-internal.d.ts.map +1 -0
- package/dist/ordinary-accounting.d.ts +104 -0
- package/dist/ordinary-accounting.d.ts.map +1 -0
- package/dist/retention-accounting.d.ts +3 -24
- package/dist/retention-accounting.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +14 -8
- package/package.json +16 -16
- package/dist/chunks/DocumentTaxCollection-C42x0YLW.js.map +0 -1
- package/dist/chunks/InvoiceCollection-BIcge9Wl.js.map +0 -1
- package/dist/chunks/retention-accounting-Brdj9x-V.js.map +0 -1
- package/dist/chunks/retention-accounting-internal-CBQRvd74.js +0 -17
- package/dist/chunks/retention-accounting-internal-CBQRvd74.js.map +0 -1
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-commerce",
|
|
6
|
-
"packageVersion": "0.57.
|
|
6
|
+
"packageVersion": "0.57.6",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
12
|
-
"agents": "
|
|
10
|
+
"manifest": "9a21a1bf935f4bbc4b185d1f7962dbb2f49ea85972334dabe0e28bc96f5fc375",
|
|
11
|
+
"packageJson": "b15f851eaaffd13beb72f5c2a8e2b67fb115d94d5aa6ce45f517336ec518386b",
|
|
12
|
+
"agents": "9eca6ead7c608cbfa20e2293b6c7fa136022aea2415bf0520272f1cd8a979e7d",
|
|
13
13
|
"moduleDoc:agents/customer-vendor-ui.md": "2b22e519411a16d8c493496fc168da77b9acd25f6077ea8fbac00cfee3a3501c",
|
|
14
14
|
"moduleDoc:README.md": "7f56bd7667e5270acb18dc2b961f382a9e1bc450b98f7e7b3828c5bc8d7b050c",
|
|
15
15
|
"moduleDoc:agents/invoice-quantity.md": "3a5fbb464c8fe63acc021b2259ba36f052bb22c49b29e503639c5316814e2028",
|
|
16
|
-
"moduleDoc:agents/historical-sales.md": "
|
|
16
|
+
"moduleDoc:agents/historical-sales.md": "d7e68bb3a93495c91449b7406a5eefdcddb54fafea83d14d5ba8e2c8d6168de4",
|
|
17
17
|
"moduleDoc:agents/payment-allocations.md": "679894f603f62522515bce338741bafda3f10d16ef0b817b105dc2e732471fdb",
|
|
18
18
|
"moduleDoc:agents/tax-codes.md": "6b07282f0ac93db4fd42ddb4a9551d880e24ec2bd2fae9d06c06561313b3cb9f",
|
|
19
19
|
"moduleDoc:agents/document-money.md": "7f198737c66d190dbdc9cc9a3dbef460fb7c9fb8ee47dd0eaaadde2f2ba91d47",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"moduleDoc:agents/contract-billing-schedules.md": "b9e2cb806c3296d12928279a64119a67b105c57443fc7f57adcd1cf070533e26",
|
|
29
29
|
"moduleDoc:agents/customer-funds.md": "417af24b9de9c41c89917e3c6e50e324a1baa70de9e45a61772b3d84c8bfeda0",
|
|
30
30
|
"moduleDoc:agents/observed-purchase-prices.md": "e8e68d733b7b9453b4dbd54e1dcf11e1486b70ee855ac629bb4e6888eb90ca9c",
|
|
31
|
-
"moduleDoc:agents/received-sales-contract-money.md": "675d728c565346e5d808e8299a55f2543a423853be0ce9abc99dc7041af79570"
|
|
31
|
+
"moduleDoc:agents/received-sales-contract-money.md": "675d728c565346e5d808e8299a55f2543a423853be0ce9abc99dc7041af79570",
|
|
32
|
+
"moduleDoc:agents/ordinary-accounting.md": "e013142ab2dffc04402da38a9b12dba1622630d0767a5766f32962a8a5e298e9"
|
|
32
33
|
},
|
|
33
34
|
"exports": [
|
|
34
35
|
".",
|
|
@@ -21444,7 +21445,7 @@
|
|
|
21444
21445
|
"polymorphicAssociations": 0,
|
|
21445
21446
|
"uuidColumns": 262
|
|
21446
21447
|
},
|
|
21447
|
-
"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- **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",
|
|
21448
|
+
"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- **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",
|
|
21448
21449
|
"moduleDocs": [
|
|
21449
21450
|
{
|
|
21450
21451
|
"path": "agents/customer-vendor-ui.md",
|
|
@@ -21464,7 +21465,7 @@
|
|
|
21464
21465
|
{
|
|
21465
21466
|
"path": "agents/historical-sales.md",
|
|
21466
21467
|
"module": "historical-sales",
|
|
21467
|
-
"content": "# Historical issued sales and original customer funds (#4081)\n\nHistorical intake is a separate source authority, not a new sale, send, or cash\nposting. Hosts must authorize the reviewer/importer, preserve original evidence,\nand call these public commands with the explicit active tenant. All writes use\none caller-affine transaction and the existing tenant money serialization lock.\n\n`recordHistoricalSalesMoney({ db, tenantId, invoiceId, requestId, evidenceRef,\nreview, source, facts, creditedSource? })` adopts an empty draft Invoice. Supply\noriginal integer minor-unit net/tax/gross, explicit signed-versus-magnitude\npolarity, original issue calendar date/time zone, and a nullable unknown due date.\nNormal calculated Invoice construction still defaults its due date as before.\nHistorical invoices expose `moneyAuthority: 'historical'` and a frozen source\nsnapshot. They create no InvoiceLineItems, fake quantities/rates, delivery event,\nAR/revenue journal, or provider invoice.\n\nA `detail: { kind: 'lines', lines }` source creates immutable\n`HistoricalSalesLine` children. The returned `{ snapshot, lines }` binds every\nsource key to a concrete `lineId`; use these IDs for consumer crosswalks.\nUnknown line tax, gross, quantity and rate remain null. Signed real adjustment\nlines retain their source values. The line net sum and every fully known other\nsum must exactly equal its corresponding original header.\n\nHistorical credits specify the exact original invoice/money snapshot and\noptional concrete original child IDs. Independent net, tax and gross capacity\nchecks never prorate a header. `getHistoricalSalesMoney` and\n`readHistoricalSalesLines` validate immutable retained authority.\n`getInvoiceMoneyFacts` includes the historical source projection. Exact header\nreports remain available through `listHistoricalSalesHeaderFacts` even when tax\nclassification is unknown. Breakdown-dependent tax reports require explicit\nreviewed component identities, taxable and net bases and classification; they\nnever infer a percentage from the source amount or borrow today's rate.\n\nOptional original `source.retention` records exact retained cents, an explicit\nretained-first credit policy, source actors/evidence and original calendar-dated\nreleases. This contract represents retention configured at original issue; its\noriginal effective date must equal the issue calendar date. A later retention\nconfiguration requires its own supported source event contract. Derived retention\nevents retain actual `recordedAt` and separate\n`effectiveOn`; as-of original cash eligibility uses the original dates. Ordinary\ncurrent retention configuration/release commands keep their existing behavior.\nOriginal credit/release sequencing rejects a release whose retained-first\ncapacity was already consumed; same-day ordering must be explicitly reviewed.\nRelease payment terms remain the original invoice due date, including an\nexplicitly unknown date. No jurisdiction terms are invented.\n\n`recordHistoricalCustomerFunds` retains original receipt/refund evidence and\nexplicit original deposit/release policy without creating a Payment or journal.\nOriginal accounting ownership and journal references are evidence, not authority\nto create duplicate original cash. Refunds identify either conserved unapplied\nfunds or one exact issued credit. Their headers immediately reserve refund\ncapacity, even before their original allocation row is imported.\n\n`recordHistoricalCustomerAllocation` records exact source allocation identities.\nReceipt applications affect the shared invoice paid balance once. Same-original\ncredit allocation rows and refund allocation rows audit their already-recorded\neconomic effects and do not reduce balances again. Cross-invoice transferable\ncredits are not represented by this contract. Same-day cash/credit chronology\nrequires explicit reviewed ordering; earlier original cash remains preserved\nwhen a later credit creates owed/refundable overpayment. Original cash dates\nremain separate from current balances and import timestamps.\n\n`getHistoricalCustomerFundsPosition` returns exact received/allocated/refunded/\navailable minor units. `applyHistoricalCustomerFunds` and\n`refundHistoricalCustomerFunds` perform NEW movements against remaining original\nfunds using explicit current active same-tenant accounts and the pinned original\npolicy terms. Applications use the existing liability-to-AR reclassification;\nrefunds use the existing journal-backed Payment command and retain the historical\nreceipt ID. Original receipts are never forged into completed Payments. Shared\nlive/historical paid/refund capacity prevents a second allocation or refund.\n\nStable source namespace/key identities replay exact facts across import runs\nwithout replacing the original importer or evidence. Changed facts/policy or\nsource-version reuse conflicts. Ordinary/generated model writes and deletion\ncannot mutate these immutable records. Provider synchronization and new revenue\nrecognition reject historical authority until an explicit supported historical\naccounting representation is supplied; exact original money is still readable.\n\nFocused evidence covers source/header immutability, concrete children, original\ncash/credit/refund chronology, conservation, CAD journals for new movements,\ncaller rollback and isolated PostgreSQL execution. Consumer historical adapters\nmust still map every source table and prove full-cohort reconciliation; adopting\nthese public facts alone is not full reference-import acceptance.\n\nCurrent explicitly dated retention releases append after the immutable original\nrelease prefix. Both remain readable without changing original dates or source\nauthority; replay binds the explicit date and caller rollback restores the\ncomplete release history. Provider releases retain their effective date in the\ncanonical retention history as well as provider evidence. Shared SQLite and\nPostgreSQL retention suites verify reload, exact retry, original-prefix tamper\nrefusal, and transactional rollback.\n\nHistorical cash allocations are validated as dated payment prefixes, independent\nof source import order. Backdated insertion rechecks later application dates;\nordinary public allocations retain their canonical allocatedAt chronology.\nSame-day credit ordering remains explicit. Later credits alone do not\nretroactively invalidate cash received before their issue date.\n\nCurrent `releaseInvoiceRetention` commands retain optional `sameDayCreditOrder`\nin their immutable evidence, alongside the effective calendar date. An exact\nretry must preserve that ordering; changing or removing it is a changed request.\nA later original credit import on the release date uses the retained ordering:\n`release-before-credit` releases first, while `credit-before-release` applies\nthe retained-first credit before checking remaining release capacity. Missing\nordering remains ambiguous and is refused rather than inferred from record time.\n### Bounded historical report scope\n\nHistorical header and tax reports apply the explicit tenant, historical money\nauthority, inclusive issue-date period, optional currency, and non-draft/non-cancelled\nstatus predicates in the collection query before enforcing the 100,000-document\nscope limit. Unrelated archived invoices do not consume a smaller report's limit;\nmore than 100,000 matching documents is refused rather than truncated.\n\nRegression design (#4063, PR #4101 comment 4300513731):\n\n| Invariant / trigger | Positive / refusal | Actor and executor | Runtime / evidence |\n| --- | --- | --- | --- |\n| Small matching period in a large tenant archive | Query-boundary fixture returns the single matching row only when all predicates precede the limit; matching scope above the cap still refuses | Explicit tenant and caller database; reads only | Focused Vitest; sparse overflow result avoids creating an archive |\n| Native collection scope | Exact inclusive boundaries, optional currency, historical authority and tenant isolation; draft/cancelled excluded | Active tenant, native test database | Focused SQLite and isolated PostgreSQL public historical-money + report proof |\n\nNo persistence behavior changes; rollback/retry and external-provider edges are\nnot applicable to this read-only query correction. The coordinator owns broader\ncohort validation and exact-head review under the resumed four-comment batch.\n\nEvidence on Node26/pnpm11.25.0: the focused archive-query regression failed against\n78f3ac856 (two failures, one pass), then passed after this query fix. The standard\n`node scripts/run-with-ci-postgres.mjs -- pnpm --filter @happyvertical/smrt-commerce exec vitest run src/__tests__/historical-sales-report-scope.test.ts src/__tests__/historical-sales-report-scope-native.test.ts`\nproof passed all five cases in9.80seconds, including actual SQLite and isolated\nPostgreSQL scope/tenant checks. No100,000-row fixture, production writes or schema\nchanges were needed. Full logs remain external at the2026-10-16 MVP session's\n`nonfinancial-import/scoped-sales-regression-base.log`, `scoped-sales-focused.log`\nand `scoped-sales-postgres.log`. Native token usage was unavailable.\n"
|
|
21468
|
+
"content": "# Historical issued sales and original customer funds (#4081)\n\nHistorical intake is a separate source authority, not a new sale, send, or cash\nposting. Hosts must authorize the reviewer/importer, preserve original evidence,\nand call these public commands with the explicit active tenant. All writes use\none caller-affine transaction and the existing tenant money serialization lock.\n\n`recordHistoricalSalesMoney({ db, tenantId, invoiceId, requestId, evidenceRef,\nreview, source, facts, creditedSource? })` adopts an empty draft Invoice. Supply\noriginal integer minor-unit net/tax/gross, explicit signed-versus-magnitude\npolarity, original issue calendar date/time zone, and a nullable unknown due date.\nNormal calculated Invoice construction still defaults its due date as before.\nHistorical invoices expose `moneyAuthority: 'historical'` and a frozen source\nsnapshot. They create no InvoiceLineItems, fake quantities/rates, delivery event,\nAR/revenue journal, or provider invoice.\n\nA `detail: { kind: 'lines', lines }` source creates immutable\n`HistoricalSalesLine` children. The returned `{ snapshot, lines }` binds every\nsource key to a concrete `lineId`; use these IDs for consumer crosswalks.\nUnknown line tax, gross, quantity and rate remain null. Signed real adjustment\nlines retain their source values. The line net sum and every fully known other\nsum must exactly equal its corresponding original header.\n\nHistorical credits specify the exact original invoice/money snapshot and\noptional concrete original child IDs. Independent net, tax and gross capacity\nchecks never prorate a header. `getHistoricalSalesMoney` and\n`readHistoricalSalesLines` validate immutable retained authority.\n`getInvoiceMoneyFacts` includes the historical source projection. Exact header\nreports remain available through `listHistoricalSalesHeaderFacts` even when tax\nclassification is unknown. Breakdown-dependent tax reports require explicit\nreviewed component identities, taxable and net bases and classification; they\nnever infer a percentage from the source amount or borrow today's rate.\n\nOptional original `source.retention` records exact retained cents, an explicit\nretained-first credit policy, source actors/evidence and original calendar-dated\nreleases. This contract represents retention configured at original issue; its\noriginal effective date must equal the issue calendar date. A later retention\nconfiguration requires its own supported source event contract. Derived retention\nevents retain actual `recordedAt` and separate\n`effectiveOn`; as-of original cash eligibility uses the original dates. Ordinary\ncurrent retention configuration/release commands keep their existing behavior.\nOriginal credit/release sequencing rejects a release whose retained-first\ncapacity was already consumed; same-day ordering must be explicitly reviewed.\nRelease payment terms remain the original invoice due date, including an\nexplicitly unknown date. No jurisdiction terms are invented.\n\n`recordHistoricalCustomerFunds` retains original receipt/refund evidence and\nexplicit original deposit/release policy without creating a Payment or journal.\nOriginal accounting ownership and journal references are evidence, not authority\nto create duplicate original cash. Refunds identify either conserved unapplied\nfunds or one exact issued credit. Their headers immediately reserve refund\ncapacity, even before their original allocation row is imported.\n\n`recordHistoricalCustomerAllocation` records exact source allocation identities.\nReceipt applications affect the shared invoice paid balance once. Same-original\ncredit allocation rows and refund allocation rows audit their already-recorded\neconomic effects and do not reduce balances again. Cross-invoice transferable\ncredits are not represented by this contract. Same-day cash/credit chronology\nrequires explicit reviewed ordering; earlier original cash remains preserved\nwhen a later credit creates owed/refundable overpayment. Original cash dates\nremain separate from current balances and import timestamps.\n\n`getHistoricalCustomerFundsPosition` returns exact received/allocated/refunded/\navailable minor units. `applyHistoricalCustomerFunds` and\n`refundHistoricalCustomerFunds` perform NEW movements against remaining original\nfunds using explicit current active same-tenant accounts and the pinned original\npolicy terms. Applications use the existing liability-to-AR reclassification;\nrefunds use the existing journal-backed Payment command and retain the historical\nreceipt ID. Original receipts are never forged into completed Payments. Shared\nlive/historical paid/refund capacity prevents a second allocation or refund.\n\nStable source namespace/key identities replay exact facts across import runs\nwithout replacing the original importer or evidence. Changed facts/policy or\nsource-version reuse conflicts. Ordinary/generated model writes and deletion\ncannot mutate these immutable records. Provider synchronization and new revenue\nrecognition reject historical authority until an explicit supported historical\naccounting representation is supplied; exact original money is still readable.\n\nFocused evidence covers source/header immutability, concrete children, original\ncash/credit/refund chronology, conservation, CAD journals for new movements,\ncaller rollback and isolated PostgreSQL execution. Consumer historical adapters\nmust still map every source table and prove full-cohort reconciliation; adopting\nthese public facts alone is not full reference-import acceptance.\n\nCurrent explicitly dated retention releases append after the immutable original\nrelease prefix. Both remain readable without changing original dates or source\nauthority; replay binds the explicit date and caller rollback restores the\ncomplete release history. Provider releases retain their effective date in the\ncanonical retention history as well as provider evidence. Shared SQLite and\nPostgreSQL retention suites verify reload, exact retry, original-prefix tamper\nrefusal, and transactional rollback.\n\nHistorical cash allocations are validated as dated payment prefixes, independent\nof source import order. Backdated insertion rechecks later application dates;\nordinary public allocations retain their canonical allocatedAt chronology.\nSame-day credit ordering remains explicit. Later credits alone do not\nretroactively invalidate cash received before their issue date.\n\nCurrent `releaseInvoiceRetention` commands retain optional `sameDayCreditOrder`\nin their immutable evidence, alongside the effective calendar date. An exact\nretry must preserve that ordering; changing or removing it is a changed request.\nA later original credit import on the release date uses the retained ordering:\n`release-before-credit` releases first, while `credit-before-release` applies\nthe retained-first credit before checking remaining release capacity. Missing\nordering remains ambiguous and is refused rather than inferred from record time.\n### Bounded historical report scope\n\nHistorical header and tax reports apply the explicit tenant, historical money\nauthority, inclusive issue-date period, optional currency, and non-draft/non-cancelled\nstatus predicates in the collection query before enforcing the 100,000-document\nscope limit. Unrelated archived invoices do not consume a smaller report's limit;\nmore than 100,000 matching documents is refused rather than truncated.\n\nRegression design (#4063, PR #4101 comment 4300513731):\n\n| Invariant / trigger | Positive / refusal | Actor and executor | Runtime / evidence |\n| --- | --- | --- | --- |\n| Small matching period in a large tenant archive | Query-boundary fixture returns the single matching row only when all predicates precede the limit; matching scope above the cap still refuses | Explicit tenant and caller database; reads only | Focused Vitest; sparse overflow result avoids creating an archive |\n| Native collection scope | Exact inclusive boundaries, optional currency, historical authority and tenant isolation; draft/cancelled excluded | Active tenant, native test database | Focused SQLite and isolated PostgreSQL public historical-money + report proof |\n\nNo persistence behavior changes; rollback/retry and external-provider edges are\nnot applicable to this read-only query correction. The coordinator owns broader\ncohort validation and exact-head review under the resumed four-comment batch.\n\nEvidence on Node26/pnpm11.25.0: the focused archive-query regression failed against\n78f3ac856 (two failures, one pass), then passed after this query fix. The standard\n`node scripts/run-with-ci-postgres.mjs -- pnpm --filter @happyvertical/smrt-commerce exec vitest run src/__tests__/historical-sales-report-scope.test.ts src/__tests__/historical-sales-report-scope-native.test.ts`\nproof passed all five cases in9.80seconds, including actual SQLite and isolated\nPostgreSQL scope/tenant checks. No100,000-row fixture, production writes or schema\nchanges were needed. Full logs remain external at the2026-10-16 MVP session's\n`nonfinancial-import/scoped-sales-regression-base.log`, `scoped-sales-focused.log`\nand `scoped-sales-postgres.log`. Native token usage was unavailable.\n\n### Stable managed credit applications\n\nRefreshing a source invoice's credit balance reserves each provider-managed\ncredit's exact retained and currently-due applications before allocating any\nremaining capacity to unmanaged issued credits. A later same-day credit, a\nlower UUID or a different database enumeration order cannot take an already\nreserved application. This includes a zero-application credit whose excess is\nrefunded in cash. Unmanaged residual allocation follows issue date and ID order.\n\nThe reconciliation guard still rejects a missing/cancelled managed credit,\nchanged retained/application amounts or frozen applications exceeding the\nsource's remaining capacity. Ordinary refund saves and retries preserve the\nprovider allocation snapshot; they do not authorize an external reversal.\n\nAn issued unmanaged credit remains issued when residual application becomes zero,\neven when no sent/viewed delivery timestamp was recorded. Repeated refreshes retain\nits full credit effect; allocation changes do not cancel or return it to draft.\n"
|
|
21468
21469
|
},
|
|
21469
21470
|
{
|
|
21470
21471
|
"path": "agents/payment-allocations.md",
|
|
@@ -21540,6 +21541,11 @@
|
|
|
21540
21541
|
"path": "agents/received-sales-contract-money.md",
|
|
21541
21542
|
"module": "received-sales-contract-money",
|
|
21542
21543
|
"content": "# Received sales agreement money\n\n`recordReceivedSalesContractMoney({ db, tenantId, contractId, requestId,\nevidenceRef, facts })` records explicitly supplied complete original monetary\nfacts on an empty draft `Order` or `Agreement` with a same-tenant customer.\nIt reuses the public complete received-money validator: safe nonnegative minor\nunits, exact net plus tax equals gross, known zero distinct from unknown tax\nclassification, and either header-only evidence or real complete source lines.\nNo quantity, price, tax rate, line allocation or current tax policy is invented.\nSales tax components must retain `recoverableMinor: null`; purchase recovery does\nnot apply. Supplier quote lineage is not accepted on this command.\n\n`getReceivedSalesContractMoney(contract)` returns the immutable evidence or null.\nSales-named facts, snapshot and input types are public. The snapshot shares the\nexisting version-1 received-money representation and keeps `sourceQuote: null`.\nThe legacy `receivedPurchaseMoneyJson` storage name remains for schema compatibility;\napplications must use commands rather than writing that field.\n\nThe host authorizes the review and binds its immutable original source separately\nto this newly completed authority. Merely importing a source label such as signed\nor approved does not grant current acceptance. Normal acceptance freezes the\ncomplete money snapshot and permits the existing approved billing-schedule\ncommands. Issued invoices remain separate actual financial instruments.\n\nRecording or accepting an agreement does not recognize revenue, create an AR or\ntax journal, or add incurred tax-report facts. Only the applicable invoice or\npurchase accounting authority contributes those facts. Incomplete original\nagreement totals remain host evidence until reviewed complete totals are supplied.\n\nThe command uses the caller executor and active tenant, locks the parent, rejects\ncalculated lines and frozen drafts, and preserves exact retry identity. Ordinary\nmoney mutations and deletion are guarded. Replays with changed evidence or facts\nrequire a separate contract revision. Competing requests cannot overwrite the\nfirst recorded authority; outer transaction rollback includes the entire record.\n\nThe customer is frozen as soon as original money is recorded, including while\nthe agreement or order is still a draft. Reassignment requires a new contract;\nacceptance and retry preserve the original customer and monetary evidence.\n"
|
|
21544
|
+
},
|
|
21545
|
+
{
|
|
21546
|
+
"path": "agents/ordinary-accounting.md",
|
|
21547
|
+
"module": "ordinary-accounting",
|
|
21548
|
+
"content": "# Ordinary invoice accounting adjustments (#4118)\n\nOrdinary issued invoices use the same frozen money exporter as other canonical\nCommerce invoices. Their provider credit applications and already-settled refund\nrecordings need durable ownership too; they do not have a retention agreement.\n\nUse `syncOrdinaryInvoiceToAccounting` with the active tenant, canonical issued\ninvoice ID, provider, stable request ID, evidence reference, reviewed SDK\n`QuickBooksOrdinaryReceivableMapping` (`kind: 'ordinary'`) and exact\n`QuickBooksFrozenInvoiceMapping` (`invoiceMapping`). It saves both mappings before\ncalling `syncFrozenInvoiceToAccounting`. It does not fabricate quantities, tax,\nretention accounts or an original provider invoice for historical imported facts.\nThe mapping supports explicit accrual/invoice-tax-point, verified home currency,\nAR and optional bank accounts. The SDK validates real provider account/customer\nmetadata; ordinary mapping cannot withhold or release retention.\n\n`readOrdinaryInvoiceAccountingState(invoice)` returns the immutable source and\nreviewed mappings, nullable original external ID, pending/ready status, credits,\nrefunds and individual remote steps. On a lost original export response, retain\nthat state and use the existing `readFrozenAccountingSyncState` request/attempt\nidentity plus `reconcileOrdinaryBaseInvoice` and exact verified provider outcome.\nRetry the original sync command afterwards. A fresh process can reconstruct the\nrequest from the public state; it must not guess a mapping or query private JSON.\n\nFor an issued same-source credit, `loadOrdinaryCreditAccountingSnapshot` and\n`toOrdinaryCreditAccountingInput` provide read-only exact review. Then call\n`syncOrdinaryCreditToAccounting` with the credit ID/mapping, request/evidence and\nexplicit effective date. The command reserves the actual local applied amount,\nexports the frozen CreditMemo and applies only that amount to the original remote\nInvoice. Zero application leaves unapplied credit capacity; it creates no fake\nzero payment. Once reserved, later same-date credits, UUID ordering and balance\nrefreshes cannot move the provider application. Generic direct credit export is\nblocked for managed sources; the owning read helpers do not permit a write bypass.\n\n`syncOrdinaryRefundToAccounting` requires an already-completed local refund\nPayment, actual cash journal, one exact full allocation to a reconciled provider\ncredit, and effectiveOn equal to the local settlement date. It reserves remaining\nunapplied credit capacity before recording the provider cash-refund journal and\nits noncash CreditMemo application. These are accounting records of an existing\nsettlement, never a bank transfer. The Payment and its allocations cannot be\nchanged/deleted after reservation, including while an outcome is unknown.\n\nEvery remote write uses the shared recoverable step engine also used by retained\naccounting. `reconcileOrdinaryAccountingStep` requires exact observed request and\nattempt identity, authoritative readback/absence evidence and proof an interrupted\nowner stopped. `reconcileOrdinaryCreditAccounting` resolves the frozen CreditMemo\nexport. Never reset unknown state on timeout or assume a request hash alone proves\nremote idempotency. Resume the original operation after reconciliation; changed\nrequest facts fail. Network operations reject caller-owned money transactions;\nlocal reservations use the same tenant/source money locks and rollback boundary.\n\nOrdinary state and refund bindings are command-owned fields on Invoice and Payment.\nRun normal schema migration for these additive fields before using the capability.\nExisting rows remain unbound; no automatic conversion of earlier app-only posted\nhistory is performed. Retained APIs still require a real positive retention\nagreement. No live provider certification is implied by controlled SDK fixtures.\n\nFocused proof: `pnpm --filter @happyvertical/smrt-commerce exec vitest run\nsrc/__tests__/ordinary-accounting.test.ts src/__tests__/retention-accounting.test.ts`.\nThe corresponding `ordinary-accounting.optional.test.ts` and retained suite run\nthrough the standard managed PostgreSQL wrapper. The shared helper covers base,\ncredit and both refund-step lost responses; same-day ordering; changed retry;\nsource/tenant checks; reservation rollback; concurrent refund attempts; and direct\npayment/allocation mutation refusal. The retained suite protects shared-engine\ncompatibility.\n\nAn existing generic frozen export can enter ordinary coordination only when the\nreviewed mapping reconstructs its exact original creation request. This check\nruns under the reservation lock, including unresolved exports; a mismatch leaves\nordinary state absent. Once ordinary authority is reserved, base export uses the\nowning command so a competing generic export cannot replace that mapping between\nreservation and provider I/O. Read-only frozen projections remain available.\n"
|
|
21543
21549
|
}
|
|
21544
21550
|
],
|
|
21545
21551
|
"recipes": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-commerce",
|
|
3
|
-
"version": "0.57.
|
|
3
|
+
"version": "0.57.6",
|
|
4
4
|
"smrtJsdoc": "strict",
|
|
5
5
|
"description": "Commerce models for the SMRT framework - contracts, fulfillments, payments",
|
|
6
6
|
"type": "module",
|
|
@@ -63,20 +63,20 @@
|
|
|
63
63
|
"access": "public"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@happyvertical/accounting": "^0.105.
|
|
67
|
-
"@happyvertical/payments": "^0.105.
|
|
68
|
-
"@happyvertical/smrt-agents": "0.57.
|
|
69
|
-
"@happyvertical/smrt-core": "0.57.
|
|
70
|
-
"@happyvertical/smrt-jobs": "0.57.
|
|
71
|
-
"@happyvertical/smrt-ledgers": "0.57.
|
|
72
|
-
"@happyvertical/smrt-products": "0.57.
|
|
73
|
-
"@happyvertical/smrt-reports": "0.57.
|
|
74
|
-
"@happyvertical/smrt-subscriptions": "0.57.
|
|
75
|
-
"@happyvertical/smrt-svelte": "0.57.
|
|
76
|
-
"@happyvertical/smrt-tenancy": "0.57.
|
|
77
|
-
"@happyvertical/smrt-types": "0.57.
|
|
78
|
-
"@happyvertical/smrt-ui": "0.57.
|
|
79
|
-
"@happyvertical/sql": "^0.105.
|
|
66
|
+
"@happyvertical/accounting": "^0.105.2",
|
|
67
|
+
"@happyvertical/payments": "^0.105.2",
|
|
68
|
+
"@happyvertical/smrt-agents": "0.57.6",
|
|
69
|
+
"@happyvertical/smrt-core": "0.57.6",
|
|
70
|
+
"@happyvertical/smrt-jobs": "0.57.6",
|
|
71
|
+
"@happyvertical/smrt-ledgers": "0.57.6",
|
|
72
|
+
"@happyvertical/smrt-products": "0.57.6",
|
|
73
|
+
"@happyvertical/smrt-reports": "0.57.6",
|
|
74
|
+
"@happyvertical/smrt-subscriptions": "0.57.6",
|
|
75
|
+
"@happyvertical/smrt-svelte": "0.57.6",
|
|
76
|
+
"@happyvertical/smrt-tenancy": "0.57.6",
|
|
77
|
+
"@happyvertical/smrt-types": "0.57.6",
|
|
78
|
+
"@happyvertical/smrt-ui": "0.57.6",
|
|
79
|
+
"@happyvertical/sql": "^0.105.2"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
82
|
"svelte": "^5.57.0"
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
|
-
"@happyvertical/smrt-vitest": "0.57.
|
|
90
|
+
"@happyvertical/smrt-vitest": "0.57.6",
|
|
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",
|