@fun-xyz/fiat-contract 0.11.1 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -78,6 +78,12 @@ this package is [ENG-5268](https://linear.app/funxyz/issue/ENG-5268).
78
78
  13. **Providerless is terminal-routing-only.** `FiatStepResponse.provider` may be absent only for
79
79
  `BLOCKED`, including `ALL_PROVIDERS_DECLINED` when routing selected no provider. Every other state
80
80
  remains provider-bound and requires `provider`; provider-specific blocked responses may keep it.
81
+ 14. **Path commitment is not a quote.** A response may carry `routingSessionRef` while pricing is
82
+ legitimately deferred for provider auth or activation. Transitions echo that opaque reference in
83
+ `params`; clients submit it unchanged. `Quote.quoteRef` remains required whenever a real `Quote`
84
+ is present, and PAY must never be exposed without real current economics.
85
+ 15. **KYC may precede pricing.** Provider auth or activation may legitimately defer pricing, so a
86
+ KYC state may omit `quote`. A real `Quote` still requires `quoteRef`, and PAY is never quote-less.
81
87
 
82
88
  ## KYC SDK hints, results, and client delivery
83
89
 
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.11.1";
2
+ var version = "0.11.3";
3
3
 
4
4
  // src/table.ts
5
5
  var TABLE_VERSION = version;
@@ -102,7 +102,13 @@ var TRANSITION_TABLE = {
102
102
  docStatus: "SPECIFIED",
103
103
  allowedTransitions: [
104
104
  { id: "start", mode: "SUBMIT", endpoint: "POST /fiat/session" },
105
- { id: "verify", mode: "SUBMIT", endpoint: "POST /fiat/session/verify" }
105
+ { id: "verify", mode: "SUBMIT", endpoint: "POST /fiat/session/verify" },
106
+ {
107
+ id: "report_auth_result",
108
+ mode: "CLIENT_SURFACE",
109
+ endpoint: "POST /fiat/session/verify",
110
+ note: "Reports a provider-owned authentication surface result; the backend alone reassesses and selects the next state."
111
+ }
106
112
  ],
107
113
  mayReturn: [
108
114
  "SESSION_AUTH",
@@ -116,7 +122,8 @@ var TRANSITION_TABLE = {
116
122
  notes: [
117
123
  "A bad code re-enters this same state with error {category: USER_ERROR, code: BAD_CODE} \u2014 banner, not a screen change.",
118
124
  "No resend affordance is specified in either doc (known gap, FE doc Screen 2).",
119
- "A provider-owned surface may declare client-executed delivery from allowlisted CURRENT_SESSION_INPUTS only."
125
+ "A provider-owned surface may declare client-executed delivery from allowlisted CURRENT_SESSION_INPUTS only.",
126
+ "A provider-owned authentication surface reports through CLIENT_SURFACE; it is not a user-entered OTP submission."
120
127
  ]
121
128
  },
122
129
  "KYC/CAPTURE": {
@@ -507,4 +514,4 @@ export {
507
514
  tableEntry,
508
515
  isTerminal
509
516
  };
510
- //# sourceMappingURL=chunk-TXI4KLBL.mjs.map
517
+ //# sourceMappingURL=chunk-EXLSD4UP.mjs.map
package/dist/index.js CHANGED
@@ -777,7 +777,7 @@ var SessionAuthStateSchema = $sessionAuthState;
777
777
  var $kycCaptureState = obj({
778
778
  kind: import_zod.z.literal("KYC"),
779
779
  phase: import_zod.z.literal("CAPTURE"),
780
- quote: $quote,
780
+ quote: $quote.optional(),
781
781
  surface: $surface,
782
782
  error: $failureReason.optional()
783
783
  });
@@ -785,7 +785,7 @@ var KycCaptureStateSchema = $kycCaptureState;
785
785
  var $kycInputRequiredState = obj({
786
786
  kind: import_zod.z.literal("KYC"),
787
787
  phase: import_zod.z.literal("INPUT_REQUIRED"),
788
- quote: $quote,
788
+ quote: $quote.optional(),
789
789
  form: $formDescriptor,
790
790
  error: $failureReason.optional()
791
791
  });
@@ -793,7 +793,7 @@ var KycInputRequiredStateSchema = $kycInputRequiredState;
793
793
  var $kycNoActionRequiredState = obj({
794
794
  kind: import_zod.z.literal("KYC"),
795
795
  phase: import_zod.z.literal("NO_ACTION_REQUIRED"),
796
- quote: $quote,
796
+ quote: $quote.optional(),
797
797
  reason: import_zod.z.enum(["IN_REVIEW", "ON_HOLD", "REJECTED"]),
798
798
  retryAfter: import_zod.z.string().optional(),
799
799
  failureReason: $failureReason.optional(),
@@ -874,19 +874,21 @@ var $providerBoundStepResponse = obj({
874
874
  state: $providerBoundFlowState,
875
875
  provider: $provider,
876
876
  transitions: import_zod.z.array($transition),
877
+ routingSessionRef: import_zod.z.string().optional(),
877
878
  orderId: import_zod.z.string().optional()
878
879
  });
879
880
  var $blockedStepResponse = obj({
880
881
  state: $blockedState,
881
882
  provider: $provider.optional(),
882
883
  transitions: import_zod.z.array($transition),
884
+ routingSessionRef: import_zod.z.string().optional(),
883
885
  orderId: import_zod.z.string().optional()
884
886
  });
885
887
  var $stepResponse = import_zod.z.union([$providerBoundStepResponse, $blockedStepResponse]);
886
888
  var FiatStepResponseSchema = $stepResponse;
887
889
 
888
890
  // package.json
889
- var version = "0.11.1";
891
+ var version = "0.11.3";
890
892
 
891
893
  // src/table.ts
892
894
  var TABLE_VERSION = version;
@@ -989,7 +991,13 @@ var TRANSITION_TABLE = {
989
991
  docStatus: "SPECIFIED",
990
992
  allowedTransitions: [
991
993
  { id: "start", mode: "SUBMIT", endpoint: "POST /fiat/session" },
992
- { id: "verify", mode: "SUBMIT", endpoint: "POST /fiat/session/verify" }
994
+ { id: "verify", mode: "SUBMIT", endpoint: "POST /fiat/session/verify" },
995
+ {
996
+ id: "report_auth_result",
997
+ mode: "CLIENT_SURFACE",
998
+ endpoint: "POST /fiat/session/verify",
999
+ note: "Reports a provider-owned authentication surface result; the backend alone reassesses and selects the next state."
1000
+ }
993
1001
  ],
994
1002
  mayReturn: [
995
1003
  "SESSION_AUTH",
@@ -1003,7 +1011,8 @@ var TRANSITION_TABLE = {
1003
1011
  notes: [
1004
1012
  "A bad code re-enters this same state with error {category: USER_ERROR, code: BAD_CODE} \u2014 banner, not a screen change.",
1005
1013
  "No resend affordance is specified in either doc (known gap, FE doc Screen 2).",
1006
- "A provider-owned surface may declare client-executed delivery from allowlisted CURRENT_SESSION_INPUTS only."
1014
+ "A provider-owned surface may declare client-executed delivery from allowlisted CURRENT_SESSION_INPUTS only.",
1015
+ "A provider-owned authentication surface reports through CLIENT_SURFACE; it is not a user-entered OTP submission."
1007
1016
  ]
1008
1017
  },
1009
1018
  "KYC/CAPTURE": {
package/dist/index.mjs CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  tableEntry,
13
13
  unofferedEndpoints,
14
14
  unreachableStates
15
- } from "./chunk-TXI4KLBL.mjs";
15
+ } from "./chunk-EXLSD4UP.mjs";
16
16
 
17
17
  // src/codes.ts
18
18
  var COUNTRY_CURRENCY_LIST = [
@@ -676,7 +676,7 @@ var SessionAuthStateSchema = $sessionAuthState;
676
676
  var $kycCaptureState = obj({
677
677
  kind: z.literal("KYC"),
678
678
  phase: z.literal("CAPTURE"),
679
- quote: $quote,
679
+ quote: $quote.optional(),
680
680
  surface: $surface,
681
681
  error: $failureReason.optional()
682
682
  });
@@ -684,7 +684,7 @@ var KycCaptureStateSchema = $kycCaptureState;
684
684
  var $kycInputRequiredState = obj({
685
685
  kind: z.literal("KYC"),
686
686
  phase: z.literal("INPUT_REQUIRED"),
687
- quote: $quote,
687
+ quote: $quote.optional(),
688
688
  form: $formDescriptor,
689
689
  error: $failureReason.optional()
690
690
  });
@@ -692,7 +692,7 @@ var KycInputRequiredStateSchema = $kycInputRequiredState;
692
692
  var $kycNoActionRequiredState = obj({
693
693
  kind: z.literal("KYC"),
694
694
  phase: z.literal("NO_ACTION_REQUIRED"),
695
- quote: $quote,
695
+ quote: $quote.optional(),
696
696
  reason: z.enum(["IN_REVIEW", "ON_HOLD", "REJECTED"]),
697
697
  retryAfter: z.string().optional(),
698
698
  failureReason: $failureReason.optional(),
@@ -773,12 +773,14 @@ var $providerBoundStepResponse = obj({
773
773
  state: $providerBoundFlowState,
774
774
  provider: $provider,
775
775
  transitions: z.array($transition),
776
+ routingSessionRef: z.string().optional(),
776
777
  orderId: z.string().optional()
777
778
  });
778
779
  var $blockedStepResponse = obj({
779
780
  state: $blockedState,
780
781
  provider: $provider.optional(),
781
782
  transitions: z.array($transition),
783
+ routingSessionRef: z.string().optional(),
782
784
  orderId: z.string().optional()
783
785
  });
784
786
  var $stepResponse = z.union([$providerBoundStepResponse, $blockedStepResponse]);
package/dist/table.js CHANGED
@@ -36,7 +36,7 @@ __export(table_exports, {
36
36
  module.exports = __toCommonJS(table_exports);
37
37
 
38
38
  // package.json
39
- var version = "0.11.1";
39
+ var version = "0.11.3";
40
40
 
41
41
  // src/table.ts
42
42
  var TABLE_VERSION = version;
@@ -139,7 +139,13 @@ var TRANSITION_TABLE = {
139
139
  docStatus: "SPECIFIED",
140
140
  allowedTransitions: [
141
141
  { id: "start", mode: "SUBMIT", endpoint: "POST /fiat/session" },
142
- { id: "verify", mode: "SUBMIT", endpoint: "POST /fiat/session/verify" }
142
+ { id: "verify", mode: "SUBMIT", endpoint: "POST /fiat/session/verify" },
143
+ {
144
+ id: "report_auth_result",
145
+ mode: "CLIENT_SURFACE",
146
+ endpoint: "POST /fiat/session/verify",
147
+ note: "Reports a provider-owned authentication surface result; the backend alone reassesses and selects the next state."
148
+ }
143
149
  ],
144
150
  mayReturn: [
145
151
  "SESSION_AUTH",
@@ -153,7 +159,8 @@ var TRANSITION_TABLE = {
153
159
  notes: [
154
160
  "A bad code re-enters this same state with error {category: USER_ERROR, code: BAD_CODE} \u2014 banner, not a screen change.",
155
161
  "No resend affordance is specified in either doc (known gap, FE doc Screen 2).",
156
- "A provider-owned surface may declare client-executed delivery from allowlisted CURRENT_SESSION_INPUTS only."
162
+ "A provider-owned surface may declare client-executed delivery from allowlisted CURRENT_SESSION_INPUTS only.",
163
+ "A provider-owned authentication surface reports through CLIENT_SURFACE; it is not a user-entered OTP submission."
157
164
  ]
158
165
  },
159
166
  "KYC/CAPTURE": {
package/dist/table.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  tableEntry,
12
12
  unofferedEndpoints,
13
13
  unreachableStates
14
- } from "./chunk-TXI4KLBL.mjs";
14
+ } from "./chunk-EXLSD4UP.mjs";
15
15
  export {
16
16
  DOCUMENTED_ENDPOINTS,
17
17
  STATE_KEYS,
package/dist/types.d.ts CHANGED
@@ -544,23 +544,26 @@ export type FlowState =
544
544
  surface?: Surface;
545
545
  error?: FailureReason;
546
546
  }
547
- /** Pre-order KYC states carry the routed quote so the entry screen can keep price visible. */
547
+ /**
548
+ * Pre-order KYC normally carries the routed quote so the entry screen can keep price visible.
549
+ * `quote` may be absent when provider auth or activation gates pricing.
550
+ */
548
551
  | {
549
552
  kind: 'KYC';
550
553
  phase: 'CAPTURE';
551
- quote: Quote;
554
+ quote?: Quote;
552
555
  surface: Surface;
553
556
  error?: FailureReason;
554
557
  } | {
555
558
  kind: 'KYC';
556
559
  phase: 'INPUT_REQUIRED';
557
- quote: Quote;
560
+ quote?: Quote;
558
561
  form: FormDescriptor;
559
562
  error?: FailureReason;
560
563
  } | {
561
564
  kind: 'KYC';
562
565
  phase: 'NO_ACTION_REQUIRED';
563
- quote: Quote;
566
+ quote?: Quote;
564
567
  /**
565
568
  * Note the deliberate name collision (Charles's nit, review 2026-08-14): `ON_HOLD` appears
566
569
  * here as a KYC reason *and* in `OrderStatus`. They are different things and both names come
@@ -641,6 +644,14 @@ export type BlockedReason = 'REGION_UNSUPPORTED' | 'ASSET_UNSUPPORTED' | 'ALL_PR
641
644
  */
642
645
  type FiatStepResponseBase = {
643
646
  transitions: Transition[];
647
+ /**
648
+ * Stable identity for a routing continuation before provider pricing is observable.
649
+ *
650
+ * A quote-less CONTINUE/PENDING response carries this instead of fabricating a `Quote` or
651
+ * `quoteRef`. It may remain present after a real quote is promoted so the backend can preserve
652
+ * the committed provider path independently from the quote binding.
653
+ */
654
+ routingSessionRef?: string;
644
655
  /** TODO(open-decision): `orderId` placement — see `PAYMENT{INSTRUCT}.orderId` above. */
645
656
  orderId?: string;
646
657
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fun-xyz/fiat-contract",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "description": "Published conformance contract for Fun's headless fiat onramp: FlowState/Transition types, zod schemas, the transition table as data, recorded fixtures, assertion helpers.",
5
5
  "license": "MIT",
6
6
  "repository": {