@openlup/platform 0.23.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +327 -269
  2. package/README.md +123 -12
  3. package/dist/communications/contracts/subscriptionPaymentExpired.d.ts +3 -2
  4. package/dist/communications/contracts/subscriptionPaymentExpired.js +1 -1
  5. package/dist/communications/contracts/subscriptionPaymentFailed.d.ts +4 -3
  6. package/dist/communications/contracts/subscriptionPaymentFailed.js +4 -5
  7. package/dist/composition/index.d.ts +1 -0
  8. package/dist/composition/index.js +1 -0
  9. package/dist/composition/subscriptionContribution.d.ts +18 -0
  10. package/dist/composition/subscriptionContribution.js +19 -0
  11. package/dist/fulfillment/contracts/dispatch.d.ts +4 -0
  12. package/dist/fulfillment/dispatchProjection.d.ts +1 -1
  13. package/dist/fulfillment/dispatchProjection.js +4 -2
  14. package/dist/fulfillment/omnipack/client.js +14 -6
  15. package/dist/fulfillment/omnipack/index.js +5 -2
  16. package/dist/fulfillment/providerDispatchWorker.d.ts +38 -0
  17. package/dist/fulfillment/providerDispatchWorker.js +19 -1
  18. package/dist/inventory/index.d.ts +2 -0
  19. package/dist/inventory/index.js +1 -0
  20. package/dist/inventory/postgresStockAvailability.d.ts +24 -0
  21. package/dist/inventory/postgresStockAvailability.js +48 -0
  22. package/dist/invoicing/accountingCanonicalProviderLines.d.ts +5 -0
  23. package/dist/invoicing/accountingCanonicalProviderLines.js +104 -0
  24. package/dist/invoicing/accountingLineAllocation.d.ts +2 -0
  25. package/dist/invoicing/accountingLineAllocation.js +69 -0
  26. package/dist/invoicing/adapterConformance.d.ts +42 -0
  27. package/dist/invoicing/adapterConformance.js +296 -0
  28. package/dist/invoicing/artifacts.d.ts +7 -0
  29. package/dist/invoicing/artifacts.js +20 -0
  30. package/dist/invoicing/bindings.d.ts +46 -0
  31. package/dist/invoicing/bindings.js +69 -0
  32. package/dist/invoicing/channelPolicy.d.ts +28 -0
  33. package/dist/invoicing/channelPolicy.js +27 -0
  34. package/dist/invoicing/continuity.d.ts +12 -0
  35. package/dist/invoicing/continuity.js +18 -0
  36. package/dist/invoicing/contracts/facts.d.ts +11 -1
  37. package/dist/invoicing/contracts/host.d.ts +3 -4
  38. package/dist/invoicing/contracts/index.d.ts +1 -1
  39. package/dist/invoicing/contracts/store.d.ts +15 -5
  40. package/dist/invoicing/contribution.d.ts +21 -0
  41. package/dist/invoicing/contribution.js +19 -0
  42. package/dist/invoicing/correction.d.ts +42 -0
  43. package/dist/invoicing/correction.js +44 -0
  44. package/dist/invoicing/delivery.d.ts +85 -0
  45. package/dist/invoicing/delivery.js +79 -0
  46. package/dist/invoicing/documentHistory.d.ts +50 -0
  47. package/dist/invoicing/documentHistory.js +213 -0
  48. package/dist/invoicing/documentSync.d.ts +24 -0
  49. package/dist/invoicing/documentSync.js +26 -0
  50. package/dist/invoicing/dutyCollector.d.ts +15 -0
  51. package/dist/invoicing/dutyCollector.js +35 -0
  52. package/dist/invoicing/fulfillmentTrigger.d.ts +56 -0
  53. package/dist/invoicing/fulfillmentTrigger.js +90 -0
  54. package/dist/invoicing/handoff.d.ts +37 -0
  55. package/dist/invoicing/handoff.js +62 -0
  56. package/dist/invoicing/index.d.ts +38 -0
  57. package/dist/invoicing/index.js +36 -0
  58. package/dist/invoicing/issue.d.ts +39 -0
  59. package/dist/invoicing/issue.js +55 -0
  60. package/dist/invoicing/migrations.d.ts +48 -0
  61. package/dist/invoicing/migrations.js +25 -0
  62. package/dist/invoicing/nativeUnsupported.d.ts +9 -0
  63. package/dist/invoicing/nativeUnsupported.js +22 -0
  64. package/dist/invoicing/paymentReadback.d.ts +20 -0
  65. package/dist/invoicing/paymentReadback.js +47 -0
  66. package/dist/invoicing/postgresInvoiceStore.d.ts +55 -0
  67. package/dist/invoicing/postgresInvoiceStore.js +344 -0
  68. package/dist/invoicing/readModel.d.ts +74 -0
  69. package/dist/invoicing/readModel.js +90 -0
  70. package/dist/invoicing/readback.d.ts +4 -0
  71. package/dist/invoicing/readback.js +30 -0
  72. package/dist/invoicing/reversal.d.ts +37 -0
  73. package/dist/invoicing/reversal.js +28 -0
  74. package/dist/invoicing/sellerRevision.d.ts +19 -0
  75. package/dist/invoicing/sellerRevision.js +14 -0
  76. package/dist/invoicing/settlementSync.d.ts +18 -0
  77. package/dist/invoicing/settlementSync.js +32 -0
  78. package/dist/invoicing/snapshot.d.ts +52 -0
  79. package/dist/invoicing/snapshot.js +141 -0
  80. package/dist/subscriptions/commandExamples.d.ts +6 -0
  81. package/dist/subscriptions/commandExamples.js +20 -0
  82. package/dist/subscriptions/contracts/commands.d.ts +8 -1
  83. package/dist/subscriptions/contracts/index.d.ts +2 -2
  84. package/dist/subscriptions/contracts/stockWait.d.ts +12 -1
  85. package/dist/subscriptions/index.d.ts +22 -4
  86. package/dist/subscriptions/index.js +22 -3
  87. package/dist/subscriptions/lifecycleMessages.d.ts +9 -0
  88. package/dist/subscriptions/lifecycleMessages.js +38 -0
  89. package/dist/subscriptions/paymentOutcomes.js +1 -1
  90. package/dist/subscriptions/postgresCommandStore.d.ts +44 -0
  91. package/dist/subscriptions/postgresCommandStore.js +172 -0
  92. package/dist/subscriptions/postgresRetryStore.d.ts +6 -0
  93. package/dist/subscriptions/postgresRetryStore.js +11 -0
  94. package/dist/subscriptions/postgresStockWaitStore.d.ts +62 -0
  95. package/dist/subscriptions/postgresStockWaitStore.js +174 -0
  96. package/dist/subscriptions/services.d.ts +31 -0
  97. package/dist/subscriptions/services.js +15 -0
  98. package/package.json +3 -3
  99. package/release-gates.json +21 -7
  100. package/sql/20260809210000_accounting_document_rail.sql +889 -0
  101. package/sql/20260811150000_accounting_payout_rail.sql +333 -0
  102. package/sql/20260812130000_accounting_document_lifecycle_rail.sql +460 -0
  103. package/sql/20261022190000_invoicing_durable_duties.sql +494 -0
  104. package/sql/20261022191000_invoicing_document_effects.sql +249 -0
  105. package/sql/20261022192000_invoicing_payment_decoupling.sql +144 -0
  106. package/sql/20261022195000_invoicing_seller_revision.sql +65 -0
  107. package/sql/20261024170000_subscription_command_lifecycle.sql +404 -0
  108. package/sql/20261024180000_subscription_stock_wait.sql +330 -0
  109. package/sql/20261024183000_inventory_available_to_promise.sql +70 -0
  110. package/sql/20261024184000_subscription_renewal_reserve_uses_seam.sql +147 -0
  111. package/sql/20261024184500_subscription_retry_late_positive_stock.sql +59 -0
  112. package/sql/20261024184600_subscription_retry_candidate_payment_filter.sql +22 -0
  113. package/src/communications/contracts/subscriptionPaymentExpired.ts +4 -3
  114. package/src/communications/contracts/subscriptionPaymentFailed.ts +8 -8
  115. package/src/composition/index.ts +1 -0
  116. package/src/composition/subscriptionContribution.ts +25 -0
  117. package/src/fulfillment/contracts/dispatch.ts +4 -0
  118. package/src/fulfillment/dispatchProjection.ts +4 -2
  119. package/src/fulfillment/omnipack/client.ts +13 -6
  120. package/src/fulfillment/omnipack/index.ts +5 -2
  121. package/src/fulfillment/providerDispatchWorker.ts +14 -1
  122. package/src/inventory/index.ts +2 -0
  123. package/src/inventory/postgresStockAvailability.ts +54 -0
  124. package/src/invoicing/accountingCanonicalProviderLines.ts +134 -0
  125. package/src/invoicing/accountingLineAllocation.ts +69 -0
  126. package/src/invoicing/adapterConformance.ts +249 -0
  127. package/src/invoicing/artifacts.ts +19 -0
  128. package/src/invoicing/bindings.ts +80 -0
  129. package/src/invoicing/channelPolicy.ts +50 -0
  130. package/src/invoicing/continuity.ts +15 -0
  131. package/src/invoicing/contracts/facts.ts +12 -1
  132. package/src/invoicing/contracts/host.ts +3 -4
  133. package/src/invoicing/contracts/index.ts +1 -1
  134. package/src/invoicing/contracts/store.ts +11 -7
  135. package/src/invoicing/contribution.ts +28 -0
  136. package/src/invoicing/correction.ts +56 -0
  137. package/src/invoicing/delivery.ts +122 -0
  138. package/src/invoicing/documentHistory.ts +301 -0
  139. package/src/invoicing/documentSync.ts +51 -0
  140. package/src/invoicing/dutyCollector.ts +31 -0
  141. package/src/invoicing/fulfillmentTrigger.ts +144 -0
  142. package/src/invoicing/handoff.ts +71 -0
  143. package/src/invoicing/index.ts +38 -0
  144. package/src/invoicing/issue.ts +64 -0
  145. package/src/invoicing/migrations.ts +25 -0
  146. package/src/invoicing/nativeUnsupported.ts +24 -0
  147. package/src/invoicing/paymentReadback.ts +70 -0
  148. package/src/invoicing/postgresInvoiceStore.ts +334 -0
  149. package/src/invoicing/readModel.ts +80 -0
  150. package/src/invoicing/readback.ts +26 -0
  151. package/src/invoicing/reversal.ts +34 -0
  152. package/src/invoicing/sellerRevision.ts +20 -0
  153. package/src/invoicing/settlementSync.ts +37 -0
  154. package/src/invoicing/snapshot.ts +192 -0
  155. package/src/subscriptions/commandExamples.ts +19 -0
  156. package/src/subscriptions/contracts/commands.ts +35 -2
  157. package/src/subscriptions/contracts/index.ts +2 -2
  158. package/src/subscriptions/contracts/stockWait.ts +14 -2
  159. package/src/subscriptions/index.ts +30 -3
  160. package/src/subscriptions/lifecycleMessages.ts +37 -0
  161. package/src/subscriptions/paymentOutcomes.ts +1 -1
  162. package/src/subscriptions/postgresCommandStore.ts +183 -0
  163. package/src/subscriptions/postgresRetryStore.ts +11 -0
  164. package/src/subscriptions/postgresStockWaitStore.ts +170 -0
  165. package/src/subscriptions/services.ts +21 -0
@@ -0,0 +1,39 @@
1
+ import type { InvoiceWriteResult } from "./contracts/provider.js";
2
+ /** Donor issue sequencing over explicit compatibility callbacks. No transaction
3
+ * spans a callback; hosts bind their existing claim/preflight/finalizer contracts.
4
+ * @consumer server/domains/accounting/accountingJobService.ts
5
+ */
6
+ export declare function runInvoiceIssueJob<Claim extends {
7
+ attemptCount: number;
8
+ }, Snapshot, Evidence, Result extends Pick<Extract<InvoiceWriteResult, {
9
+ kind: "issued";
10
+ }>, "providerDocumentRef" | "providerDocumentNumber">>(input: {
11
+ createEnabled: boolean;
12
+ providerEnabled: boolean;
13
+ claim(): Promise<readonly Claim[]>;
14
+ localPreflight(claim: Claim): Promise<boolean>;
15
+ project(claim: Claim): Snapshot;
16
+ blockMapper(claim: Claim, code: string, error: unknown): Promise<unknown>;
17
+ readPayment(claim: Claim): Promise<Evidence>;
18
+ freshPreflight(claim: Claim, evidence: Evidence): Promise<boolean>;
19
+ /** Resolve only accepted/recovered document receipts; unknown/absent is not an ACK. */
20
+ create(snapshot: Snapshot, options: {
21
+ recoveryLookupRequired: boolean;
22
+ }): Promise<Result>;
23
+ finish(claim: Claim, result: Result): Promise<unknown>;
24
+ isClaimFenceError(error: unknown): boolean;
25
+ fail(claim: Claim, error: unknown, retrySeconds: number): Promise<unknown>;
26
+ }): Promise<{
27
+ ok: boolean;
28
+ checked: number;
29
+ updated: number;
30
+ skipped: boolean;
31
+ reason: string;
32
+ failures: number;
33
+ } | {
34
+ ok: boolean;
35
+ checked: number;
36
+ updated: number;
37
+ skipped: boolean;
38
+ failures: number;
39
+ }>;
@@ -0,0 +1,55 @@
1
+ /** Donor issue sequencing over explicit compatibility callbacks. No transaction
2
+ * spans a callback; hosts bind their existing claim/preflight/finalizer contracts.
3
+ * @consumer server/domains/accounting/accountingJobService.ts
4
+ */
5
+ export async function runInvoiceIssueJob(input) {
6
+ if (!input.createEnabled)
7
+ return skipped("create_disabled");
8
+ if (!input.providerEnabled)
9
+ return skipped("provider_disabled");
10
+ const claims = await input.claim();
11
+ let updated = 0;
12
+ let failures = 0;
13
+ for (const claim of claims) {
14
+ try {
15
+ if (!await input.localPreflight(claim)) {
16
+ failures += 1;
17
+ continue;
18
+ }
19
+ let snapshot;
20
+ try {
21
+ snapshot = input.project(claim);
22
+ }
23
+ catch (error) {
24
+ const canonicalCode = canonicalMapperErrorCode(error);
25
+ if (!canonicalCode)
26
+ throw error;
27
+ await input.blockMapper(claim, canonicalCode, error);
28
+ failures += 1;
29
+ continue;
30
+ }
31
+ const providerEvidence = await input.readPayment(claim);
32
+ if (!await input.freshPreflight(claim, providerEvidence)) {
33
+ failures += 1;
34
+ continue;
35
+ }
36
+ const result = await input.create(snapshot, { recoveryLookupRequired: claim.attemptCount > 1 });
37
+ await input.finish(claim, result);
38
+ updated += 1;
39
+ }
40
+ catch (error) {
41
+ failures += 1;
42
+ if (input.isClaimFenceError(error))
43
+ continue;
44
+ await input.fail(claim, error, Math.min(3600, 300 * Math.max(1, claim.attemptCount)));
45
+ }
46
+ }
47
+ return { ok: failures === 0, checked: claims.length, updated, skipped: false, failures };
48
+ }
49
+ function canonicalMapperErrorCode(error) {
50
+ if (!(error instanceof Error))
51
+ return null;
52
+ const match = /\b(accounting_invoice_canonical_[a-z0-9_]+)/.exec(error.message);
53
+ return match?.[1] ?? null;
54
+ }
55
+ function skipped(reason) { return { ok: true, checked: 0, updated: 0, skipped: true, reason, failures: 0 }; }
@@ -0,0 +1,48 @@
1
+ /** Sparse native projections, not an installation chain. Install the full catalogue. */
2
+ export declare const INVOICING_MIGRATIONS: {
3
+ readonly native: {
4
+ readonly correctionStorage: "child_document";
5
+ readonly fiscalScope: "explicit_host_facts";
6
+ readonly units: readonly [{
7
+ readonly position: 7;
8
+ readonly catalogPath: "db/platform/migrations/20260809210000_accounting_document_rail.sql";
9
+ readonly sha256: "f5c6c4b3d5ccdd7c7137669edba7d45c63685edc57fe982e3e8fd559214ccc8e";
10
+ readonly url: URL;
11
+ }, {
12
+ readonly position: 13;
13
+ readonly catalogPath: "db/platform/migrations/20260811150000_accounting_payout_rail.sql";
14
+ readonly sha256: "b127631196362d59ceb94700426766659589601c69a5adfb1b5d6bbeadf5b0db";
15
+ readonly url: URL;
16
+ }, {
17
+ readonly position: 15;
18
+ readonly catalogPath: "db/platform/migrations/20260812130000_accounting_document_lifecycle_rail.sql";
19
+ readonly sha256: "450ae24b8ba9438ea267cfbf52f9c78a790b1803f369c216577566952fa43b5f";
20
+ readonly url: URL;
21
+ }, {
22
+ readonly position: 77;
23
+ readonly catalogPath: "db/platform/migrations/20261022190000_invoicing_durable_duties.sql";
24
+ readonly sha256: "2d7bf98924b4ef29b3e8f902d768e45dd9c850242f4358a0193a0c00d0f3d081";
25
+ readonly url: URL;
26
+ }, {
27
+ readonly position: 78;
28
+ readonly catalogPath: "db/platform/migrations/20261022191000_invoicing_document_effects.sql";
29
+ readonly sha256: "0eac3453e2b82c43e4fff9e35bcd6daefdd0bb5f992937f7f411d690550428cf";
30
+ readonly url: URL;
31
+ }, {
32
+ readonly position: 79;
33
+ readonly catalogPath: "db/platform/migrations/20261022192000_invoicing_payment_decoupling.sql";
34
+ readonly sha256: "f4af30ee4c9365ea51bd0e95e5cc7ae869cf15dce5867fdd640f679438b36058";
35
+ readonly url: URL;
36
+ }, {
37
+ readonly position: 80;
38
+ readonly catalogPath: "db/platform/migrations/20261022195000_invoicing_seller_revision.sql";
39
+ readonly sha256: "5a6348d9af296cfc6383894e3489f70af1f3bb5026c0cc329daa9f3f95802b22";
40
+ readonly url: URL;
41
+ }];
42
+ };
43
+ readonly managed: {
44
+ readonly correctionStorage: "base_row";
45
+ readonly fiscalScope: "host_managed_projection";
46
+ readonly units: readonly ["supabase/migrations/20261022193000_invoicing_correction_claims.sql", "supabase/migrations/20261022193100_invoicing_correction_compatibility.sql", "supabase/migrations/20261022195100_invoicing_seller_revision.sql"];
47
+ };
48
+ };
@@ -0,0 +1,25 @@
1
+ /** Sparse native projections, not an installation chain. Install the full catalogue. */
2
+ export const INVOICING_MIGRATIONS = {
3
+ native: {
4
+ correctionStorage: "child_document",
5
+ fiscalScope: "explicit_host_facts",
6
+ units: [
7
+ { position: 7, catalogPath: "db/platform/migrations/20260809210000_accounting_document_rail.sql", sha256: "f5c6c4b3d5ccdd7c7137669edba7d45c63685edc57fe982e3e8fd559214ccc8e", url: new URL("../../sql/20260809210000_accounting_document_rail.sql", import.meta.url) },
8
+ { position: 13, catalogPath: "db/platform/migrations/20260811150000_accounting_payout_rail.sql", sha256: "b127631196362d59ceb94700426766659589601c69a5adfb1b5d6bbeadf5b0db", url: new URL("../../sql/20260811150000_accounting_payout_rail.sql", import.meta.url) },
9
+ { position: 15, catalogPath: "db/platform/migrations/20260812130000_accounting_document_lifecycle_rail.sql", sha256: "450ae24b8ba9438ea267cfbf52f9c78a790b1803f369c216577566952fa43b5f", url: new URL("../../sql/20260812130000_accounting_document_lifecycle_rail.sql", import.meta.url) },
10
+ { position: 77, catalogPath: "db/platform/migrations/20261022190000_invoicing_durable_duties.sql", sha256: "2d7bf98924b4ef29b3e8f902d768e45dd9c850242f4358a0193a0c00d0f3d081", url: new URL("../../sql/20261022190000_invoicing_durable_duties.sql", import.meta.url) },
11
+ { position: 78, catalogPath: "db/platform/migrations/20261022191000_invoicing_document_effects.sql", sha256: "0eac3453e2b82c43e4fff9e35bcd6daefdd0bb5f992937f7f411d690550428cf", url: new URL("../../sql/20261022191000_invoicing_document_effects.sql", import.meta.url) },
12
+ { position: 79, catalogPath: "db/platform/migrations/20261022192000_invoicing_payment_decoupling.sql", sha256: "f4af30ee4c9365ea51bd0e95e5cc7ae869cf15dce5867fdd640f679438b36058", url: new URL("../../sql/20261022192000_invoicing_payment_decoupling.sql", import.meta.url) },
13
+ { position: 80, catalogPath: "db/platform/migrations/20261022195000_invoicing_seller_revision.sql", sha256: "5a6348d9af296cfc6383894e3489f70af1f3bb5026c0cc329daa9f3f95802b22", url: new URL("../../sql/20261022195000_invoicing_seller_revision.sql", import.meta.url) },
14
+ ],
15
+ },
16
+ managed: {
17
+ correctionStorage: "base_row",
18
+ fiscalScope: "host_managed_projection",
19
+ units: [
20
+ "supabase/migrations/20261022193000_invoicing_correction_claims.sql",
21
+ "supabase/migrations/20261022193100_invoicing_correction_compatibility.sql",
22
+ "supabase/migrations/20261022195100_invoicing_seller_revision.sql",
23
+ ],
24
+ },
25
+ };
@@ -0,0 +1,9 @@
1
+ import type { InvoiceHostPorts, InvoiceStorePort, InvoiceServicesOptions } from "./contracts/index.js";
2
+ /** @consumer Host native binding / installed cold consumer. No executor, inputs,
3
+ * provider or storage is inspected: every missing native seam refuses before writes.
4
+ */
5
+ export declare function createNativeUnsupportedInvoicePorts(): {
6
+ host: InvoiceHostPorts;
7
+ store: InvoiceStorePort;
8
+ provider: NonNullable<InvoiceServicesOptions["provider"]>;
9
+ };
@@ -0,0 +1,22 @@
1
+ const refusal = Object.freeze({ kind: "unsupported", code: "host_binding_required", retryable: false, effectMayHaveSucceeded: false });
2
+ /** @consumer Host native binding / installed cold consumer. No executor, inputs,
3
+ * provider or storage is inspected: every missing native seam refuses before writes.
4
+ */
5
+ export function createNativeUnsupportedInvoicePorts() {
6
+ const unsupported = async () => refusal;
7
+ return {
8
+ host: {
9
+ facts: { read: unsupported }, seller: { read: unsupported }, money: { read: unsupported }, fiscal: { verify: unsupported },
10
+ artifacts: { read: unsupported, download: unsupported, persist: unsupported }, registry: { lookup: unsupported },
11
+ delivery: { send: unsupported }, clearance: { observe: unsupported }, settlement: { record: unsupported, resolve: unsupported },
12
+ policy: { decide: unsupported, receipts: unsupported }, accountHistory: { read: unsupported, resolveDownload: unsupported },
13
+ },
14
+ store: {
15
+ captureDuty: unsupported, installFacts: unsupported, sweep: unsupported, prepareFacts: unsupported, finishFacts: unsupported,
16
+ readDuties: unsupported, claim: unsupported, preflight: unsupported, finish: unsupported, fail: unsupported,
17
+ requestReversal: unsupported, requestLocalDocument: unsupported, listClearanceTargets: unsupported,
18
+ recordObservation: unsupported, claimDeliveries: unsupported, settleDelivery: unsupported,
19
+ },
20
+ provider: { issue: unsupported, correct: unsupported, read: unsupported, void: unsupported },
21
+ };
22
+ }
@@ -0,0 +1,20 @@
1
+ type PaymentEvidence = {
2
+ providerStatus: "succeeded" | "failed" | "pending" | "unknown" | "unavailable";
3
+ providerAmountCents: number | null;
4
+ providerCurrency: string | null;
5
+ providerEvidence: Record<string, unknown>;
6
+ };
7
+ export declare function readInvoicePaymentEvidence(payment: {
8
+ provider: string;
9
+ providerPaymentId: string | null;
10
+ }, provider: {
11
+ readPayment(input: {
12
+ providerPaymentId: string;
13
+ }): Promise<{
14
+ status: "succeeded" | "failed" | "pending" | "unknown";
15
+ providerStatus: string;
16
+ amountMinor: number | null;
17
+ currency: string | null;
18
+ }>;
19
+ } | undefined): Promise<PaymentEvidence>;
20
+ export {};
@@ -0,0 +1,47 @@
1
+ export async function readInvoicePaymentEvidence(payment, provider) {
2
+ const providerName = payment.provider;
3
+ if (!provider || !payment.providerPaymentId) {
4
+ return unavailable(providerName, payment.providerPaymentId, provider ? "provider_payment_id_missing" : "provider_not_configured");
5
+ }
6
+ try {
7
+ const readback = await provider.readPayment({
8
+ providerPaymentId: payment.providerPaymentId,
9
+ });
10
+ return {
11
+ providerStatus: readback.status,
12
+ providerAmountCents: integerOrNull(readback.amountMinor),
13
+ providerCurrency: currencyOrNull(readback.currency),
14
+ providerEvidence: {
15
+ source: "provider_api",
16
+ provider: providerName,
17
+ providerPaymentId: payment.providerPaymentId,
18
+ providerStatus: readback.providerStatus.slice(0, 80),
19
+ amountAvailable: integerOrNull(readback.amountMinor) !== null,
20
+ currencyAvailable: currencyOrNull(readback.currency) !== null,
21
+ },
22
+ };
23
+ }
24
+ catch {
25
+ return unavailable(providerName, payment.providerPaymentId, "provider_read_failed");
26
+ }
27
+ }
28
+ function unavailable(provider, providerPaymentId, reason) {
29
+ return {
30
+ providerStatus: "unavailable",
31
+ providerAmountCents: null,
32
+ providerCurrency: null,
33
+ providerEvidence: {
34
+ source: "provider_api",
35
+ provider,
36
+ providerPaymentId,
37
+ unavailableReason: reason,
38
+ },
39
+ };
40
+ }
41
+ function integerOrNull(value) {
42
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
43
+ }
44
+ function currencyOrNull(value) {
45
+ const normalized = value?.trim().toUpperCase() ?? "";
46
+ return /^[A-Z]{3}$/.test(normalized) ? normalized : null;
47
+ }
@@ -0,0 +1,55 @@
1
+ import type { InvoiceStorePort, InvoiceHostPorts, InvoiceProviderPort } from "./contracts/index.js";
2
+ type InvoiceClaim = Parameters<InvoiceStorePort["preflight"]>[0]["claim"];
3
+ type NativeStore = InvoiceStorePort & {
4
+ /** Read-only discovery before a host can install facts. Replays may repeat targets. */
5
+ discoverDuties(limit: number, afterDutyId?: string | null): Promise<readonly {
6
+ readonly dutyId: string;
7
+ readonly orderId: string;
8
+ }[]>;
9
+ };
10
+ type DeliveryClaim = Exclude<Awaited<ReturnType<InvoiceStorePort["claimDeliveries"]>>, {
11
+ kind: "unsupported";
12
+ }>[number];
13
+ type DeliveryProjection = {
14
+ /** Host-owned M04 keys, presentation and recipient resolution, after leasing.
15
+ * Return only the envelope for this document; a failed projection never sends.
16
+ */
17
+ projectDelivery(input: {
18
+ readonly deliveryRef: string;
19
+ readonly documentId: string;
20
+ readonly channel: string;
21
+ readonly recipientRef: string;
22
+ readonly attemptCount: number;
23
+ }): Promise<Pick<DeliveryClaim, "identity" | "delivery">>;
24
+ };
25
+ type Executor = {
26
+ query(text: string, values?: unknown[]): Promise<{
27
+ rows: Record<string, unknown>[];
28
+ }>;
29
+ };
30
+ /** Bind an autocommit executor. Never pass a transaction spanning host/provider I/O.
31
+ * Missing fiscal facts or delivery binding refuse before writes; no scheduler is installed.
32
+ */
33
+ export declare function createPostgresInvoiceStore(db: Executor, options?: Partial<DeliveryProjection> & {
34
+ readonly seller?: InvoiceHostPorts["seller"];
35
+ }): NativeStore;
36
+ type MoneyEvidence = Awaited<ReturnType<InvoiceHostPorts["money"]["read"]>>;
37
+ /** Native issue/readback binding; every store operation commits before host I/O.
38
+ * @consumer Explicit native host issue binding and installed-consumer conformance.
39
+ */
40
+ export declare function runNativeInvoiceIssueJob(input: {
41
+ store: Pick<InvoiceStorePort, "claim" | "preflight" | "finish" | "fail">;
42
+ provider: Pick<InvoiceProviderPort, "issue" | "correct" | "read">;
43
+ money: InvoiceHostPorts["money"];
44
+ readLocalPayment(claim: InvoiceClaim): Promise<MoneyEvidence>;
45
+ providerRef: string;
46
+ orderId?: string | null;
47
+ limit?: number;
48
+ visibilitySeconds?: number;
49
+ }): Promise<import("./contracts/provider.js").InvoiceUnsupported | {
50
+ checked: number;
51
+ updated: number;
52
+ failures: number;
53
+ ok: boolean;
54
+ }>;
55
+ export {};