@fora-protocol/sdk 1.0.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.
Files changed (115) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +37 -0
  3. package/gen/ts/vocab/functiontokens.js +78 -0
  4. package/gen/ts/vocab/functiontokens.ts +84 -0
  5. package/gen/ts/vocab/geographytokens.js +30 -0
  6. package/gen/ts/vocab/geographytokens.ts +37 -0
  7. package/gen/ts/vocab/pricingunits.js +56 -0
  8. package/gen/ts/vocab/pricingunits.ts +63 -0
  9. package/gen/ts/vocab/quotametrics.js +40 -0
  10. package/gen/ts/vocab/quotametrics.ts +47 -0
  11. package/gen/ts/vocab/usertypes.js +40 -0
  12. package/gen/ts/vocab/usertypes.ts +46 -0
  13. package/gen/ts/wire/base.js +245 -0
  14. package/gen/ts/wire/base.ts +255 -0
  15. package/gen/ts/wire/names.js +41 -0
  16. package/gen/ts/wire/names.ts +42 -0
  17. package/gen/ts/wire/schemas.js +111 -0
  18. package/gen/ts/wire/schemas.ts +216 -0
  19. package/package.json +164 -0
  20. package/sdk/ts/client/content.d.ts +74 -0
  21. package/sdk/ts/client/content.js +466 -0
  22. package/sdk/ts/client/errors.d.ts +79 -0
  23. package/sdk/ts/client/errors.js +148 -0
  24. package/sdk/ts/client/index.d.ts +241 -0
  25. package/sdk/ts/client/index.js +740 -0
  26. package/sdk/ts/client/route.d.ts +41 -0
  27. package/sdk/ts/client/route.js +107 -0
  28. package/sdk/ts/client/send.d.ts +64 -0
  29. package/sdk/ts/client/send.js +142 -0
  30. package/sdk/ts/client/transport.d.ts +187 -0
  31. package/sdk/ts/client/transport.js +381 -0
  32. package/sdk/ts/core/multisig-parse.d.ts +47 -0
  33. package/sdk/ts/core/multisig-parse.js +234 -0
  34. package/sdk/ts/core/sign-request.d.ts +83 -0
  35. package/sdk/ts/core/sign-request.js +146 -0
  36. package/sdk/ts/core/sign.d.ts +31 -0
  37. package/sdk/ts/core/sign.js +82 -0
  38. package/sdk/ts/core/signing-transport.d.ts +75 -0
  39. package/sdk/ts/core/signing-transport.js +172 -0
  40. package/sdk/ts/core/verifier.d.ts +177 -0
  41. package/sdk/ts/core/verifier.js +269 -0
  42. package/sdk/ts/core/verify-multisig-request.d.ts +72 -0
  43. package/sdk/ts/core/verify-multisig-request.js +112 -0
  44. package/sdk/ts/core/verify-request.d.ts +181 -0
  45. package/sdk/ts/core/verify-request.js +284 -0
  46. package/sdk/ts/core/window.d.ts +22 -0
  47. package/sdk/ts/core/window.js +43 -0
  48. package/sdk/ts/core/wire-canon.d.ts +20 -0
  49. package/sdk/ts/core/wire-canon.js +174 -0
  50. package/sdk/ts/hono/middleware.d.ts +38 -0
  51. package/sdk/ts/hono/middleware.js +64 -0
  52. package/sdk/ts/resolvers/errors.d.ts +130 -0
  53. package/sdk/ts/resolvers/errors.js +150 -0
  54. package/sdk/ts/resolvers/http.d.ts +98 -0
  55. package/sdk/ts/resolvers/http.js +274 -0
  56. package/sdk/ts/resolvers/index.d.ts +9 -0
  57. package/sdk/ts/resolvers/index.js +15 -0
  58. package/sdk/ts/resolvers/jwks.d.ts +2 -0
  59. package/sdk/ts/resolvers/jwks.js +43 -0
  60. package/sdk/ts/resolvers/offer-key-cache.d.ts +68 -0
  61. package/sdk/ts/resolvers/offer-key-cache.js +152 -0
  62. package/sdk/ts/resolvers/registration-requirements.d.ts +47 -0
  63. package/sdk/ts/resolvers/registration-requirements.js +220 -0
  64. package/sdk/ts/resolvers/ssrf.d.ts +28 -0
  65. package/sdk/ts/resolvers/ssrf.js +235 -0
  66. package/sdk/ts/resolvers/static.d.ts +7 -0
  67. package/sdk/ts/resolvers/static.js +16 -0
  68. package/sdk/ts/resolvers/wba.d.ts +134 -0
  69. package/sdk/ts/resolvers/wba.js +506 -0
  70. package/sdk/ts/resolvers/wellknown.d.ts +28 -0
  71. package/sdk/ts/resolvers/wellknown.js +169 -0
  72. package/sdk/ts/src/acceptance.d.ts +46 -0
  73. package/sdk/ts/src/acceptance.js +162 -0
  74. package/sdk/ts/src/base64url.d.ts +19 -0
  75. package/sdk/ts/src/base64url.js +55 -0
  76. package/sdk/ts/src/crossfield.d.ts +28 -0
  77. package/sdk/ts/src/crossfield.js +215 -0
  78. package/sdk/ts/src/endpoint-rule.d.ts +30 -0
  79. package/sdk/ts/src/endpoint-rule.js +63 -0
  80. package/sdk/ts/src/errordetail.d.ts +115 -0
  81. package/sdk/ts/src/errordetail.js +256 -0
  82. package/sdk/ts/src/hashurl.d.ts +5 -0
  83. package/sdk/ts/src/hashurl.js +15 -0
  84. package/sdk/ts/src/host-ref.d.ts +70 -0
  85. package/sdk/ts/src/host-ref.js +320 -0
  86. package/sdk/ts/src/hosts.d.ts +138 -0
  87. package/sdk/ts/src/hosts.js +214 -0
  88. package/sdk/ts/src/idempotency.d.ts +11 -0
  89. package/sdk/ts/src/idempotency.js +27 -0
  90. package/sdk/ts/src/jsondepth.d.ts +27 -0
  91. package/sdk/ts/src/jsondepth.js +77 -0
  92. package/sdk/ts/src/licenseterm.d.ts +113 -0
  93. package/sdk/ts/src/licenseterm.js +433 -0
  94. package/sdk/ts/src/money.d.ts +21 -0
  95. package/sdk/ts/src/money.js +60 -0
  96. package/sdk/ts/src/offer-sign.d.ts +11 -0
  97. package/sdk/ts/src/offer-sign.js +31 -0
  98. package/sdk/ts/src/opaque-url.d.ts +3 -0
  99. package/sdk/ts/src/opaque-url.js +20 -0
  100. package/sdk/ts/src/pop.d.ts +51 -0
  101. package/sdk/ts/src/pop.js +166 -0
  102. package/sdk/ts/src/regschema.d.ts +229 -0
  103. package/sdk/ts/src/regschema.js +1315 -0
  104. package/sdk/ts/src/scopes.d.ts +20 -0
  105. package/sdk/ts/src/scopes.js +45 -0
  106. package/sdk/ts/src/signurl.d.ts +23 -0
  107. package/sdk/ts/src/signurl.js +107 -0
  108. package/sdk/ts/src/thumbprint.d.ts +14 -0
  109. package/sdk/ts/src/thumbprint.js +24 -0
  110. package/sdk/ts/src/verify.d.ts +49 -0
  111. package/sdk/ts/src/verify.js +109 -0
  112. package/sdk/ts/src/wire-names.d.ts +1 -0
  113. package/sdk/ts/src/wire-names.js +16 -0
  114. package/sdk/ts/src/wire.d.ts +68 -0
  115. package/sdk/ts/src/wire.js +114 -0
@@ -0,0 +1,215 @@
1
+ import { z } from "zod";
2
+ import { GetAccountStatusResponseSchema, LicenseSchema, LicenseTermSchema, ObligationSchema, PricingSchema, RegistrationFailureSchema, RestrictionSchema, WellKnownManifestSchema, } from "../../../gen/ts/wire/schemas.js";
3
+ function asObj(v) {
4
+ return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
5
+ }
6
+ /** Read a field by its snake_case name (the only wire naming). */
7
+ function field(o, ...names) {
8
+ for (const n of names) {
9
+ if (o[n] !== undefined)
10
+ return o[n];
11
+ }
12
+ return undefined;
13
+ }
14
+ function str(v) {
15
+ return typeof v === "string" ? v : "";
16
+ }
17
+ // ---- generated enum members (reused, not forked) --------------------------
18
+ const OBLIGATION_KIND_SHARE_ALIKE = "OBLIGATION_KIND_SHARE_ALIKE";
19
+ const TERM_SEMANTICS_REFERENCE_ONLY = "TERM_SEMANTICS_REFERENCE_ONLY";
20
+ const REGISTRATION_FAILURE_INVALID_DATA = "REGISTRATION_FAILURE_REASON_INVALID_REGISTRATION_DATA";
21
+ const PRICING_MODEL_FREE = "PRICING_MODEL_FREE";
22
+ const PRICING_MODEL_PER_UNIT = "PRICING_MODEL_PER_UNIT";
23
+ /**
24
+ * LicenseTerm.restrictions max_items. The one-per-kind rule stays silent above it,
25
+ * matching the contract — see licenseTermRules.
26
+ */
27
+ const MAX_RESTRICTIONS = 8;
28
+ // ---- per-message cross-field predicates -----------------------------------
29
+ // Each returns the rule-ids VIOLATED by the instance (empty => passes). The
30
+ // boolean expression mirrors the CEL predicate; a rule-id is emitted when the
31
+ // CEL predicate is FALSE (protovalidate rejects when the expression is false).
32
+ /** License.digest_required_with_uri: `this.uri == '' || this.uri_digest != ''`. */
33
+ function licenseRules(o) {
34
+ const uri = str(field(o, "uri"));
35
+ // uri_digest is a string field; the shared valid instance also models a
36
+ // present digest as a `digest` object — both count as "digest present".
37
+ const uriDigest = str(field(o, "uri_digest"));
38
+ const digestObj = asObj(field(o, "digest"));
39
+ const hasDigest = uriDigest !== "" || digestObj !== undefined;
40
+ if (uri !== "" && !hasDigest)
41
+ return ["license.digest_required_with_uri"];
42
+ return [];
43
+ }
44
+ /**
45
+ * LicenseTerm rules:
46
+ * - reference_only.requires_uri:
47
+ * `this.semantics != REFERENCE_ONLY || (has(this.license) && this.license.uri != '')`
48
+ * - one_restriction_per_kind:
49
+ * `this.restrictions.size() > 8 || this.restrictions.all(r, this.restrictions.filter(o, o.kind == r.kind).size() <= 1)`
50
+ *
51
+ * The size test in the second rule is part of its meaning, not a detail of how the
52
+ * contract evaluates it: a list longer than the cap is refused by the cap, and this
53
+ * rule stays silent about it so the reported fault is the length. Mirroring it here
54
+ * is what keeps this face's verdict equal to the wire's on such a list.
55
+ */
56
+ function licenseTermRules(o) {
57
+ const out = [];
58
+ const semantics = str(field(o, "semantics"));
59
+ if (semantics === TERM_SEMANTICS_REFERENCE_ONLY) {
60
+ const license = asObj(field(o, "license"));
61
+ if (!license || str(field(license, "uri")) === "") {
62
+ out.push("license_term.reference_only.requires_uri");
63
+ }
64
+ }
65
+ const restrictions = field(o, "restrictions");
66
+ if (Array.isArray(restrictions) && restrictions.length <= MAX_RESTRICTIONS) {
67
+ const kinds = restrictions.map((r) => str(field(asObj(r) ?? {}, "kind")));
68
+ const seen = new Set();
69
+ let dup = false;
70
+ for (const k of kinds) {
71
+ if (seen.has(k))
72
+ dup = true;
73
+ seen.add(k);
74
+ }
75
+ if (dup)
76
+ out.push("license_term.one_restriction_per_kind");
77
+ }
78
+ return out;
79
+ }
80
+ /**
81
+ * Obligation.share_alike.requires_scope_license:
82
+ * `this.kind != SHARE_ALIKE || (has(this.scope_license) && (this.scope_license.id != '' || this.scope_license.uri != ''))`.
83
+ */
84
+ function obligationRules(o) {
85
+ if (str(field(o, "kind")) !== OBLIGATION_KIND_SHARE_ALIKE)
86
+ return [];
87
+ const raw = field(o, "scope_license");
88
+ // scope_license is a License (object with id/uri); a bare non-empty string is
89
+ // also accepted as an identifying id (the CEL's `id != ''` intent).
90
+ const identified = (typeof raw === "string" && raw !== "") ||
91
+ (asObj(raw) !== undefined &&
92
+ (str(field(asObj(raw), "id")) !== "" || str(field(asObj(raw), "uri")) !== ""));
93
+ return identified ? [] : ["obligation.share_alike.requires_scope_license"];
94
+ }
95
+ /**
96
+ * Pricing rules:
97
+ * - per_unit.requires_unit: `this.model != PER_UNIT || this.unit != ''`
98
+ * - free.zero_rate: `this.model != FREE || this.rate == '' || this.rate.matches('^0+([.]0+)?$')`
99
+ */
100
+ function pricingRules(o) {
101
+ const out = [];
102
+ const model = str(field(o, "model"));
103
+ if (model === PRICING_MODEL_PER_UNIT && str(field(o, "unit")) === "") {
104
+ out.push("pricing.per_unit.requires_unit");
105
+ }
106
+ if (model === PRICING_MODEL_FREE) {
107
+ const rate = str(field(o, "rate"));
108
+ if (rate !== "" && !/^0+([.]0+)?$/.test(rate)) {
109
+ out.push("pricing.free.zero_rate");
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+ /** Restriction.permitted_prohibited_disjoint: `this.permitted.all(p, !(p in this.prohibited))`. */
115
+ function restrictionRules(o) {
116
+ const permitted = field(o, "permitted");
117
+ const prohibited = field(o, "prohibited");
118
+ if (!Array.isArray(permitted) || !Array.isArray(prohibited))
119
+ return [];
120
+ const banned = new Set(prohibited.map((p) => str(p)));
121
+ for (const p of permitted) {
122
+ if (banned.has(str(p)))
123
+ return ["restriction.permitted_prohibited_disjoint"];
124
+ }
125
+ return [];
126
+ }
127
+ /**
128
+ * WellKnownManifest.terms_digest_requires_terms_uri:
129
+ * `this.terms_digest == '' || this.terms_uri != ''`. A digest pins the document
130
+ * at terms_uri, so publishing one without the address it pins leaves nothing to
131
+ * check the bytes against. Mirror of the License rule above.
132
+ */
133
+ function wellKnownManifestRules(o) {
134
+ const termsDigest = str(field(o, "terms_digest"));
135
+ const termsUri = str(field(o, "terms_uri"));
136
+ if (termsDigest !== "" && termsUri === "") {
137
+ return ["well_known_manifest.terms_digest_requires_terms_uri"];
138
+ }
139
+ return [];
140
+ }
141
+ /**
142
+ * GetAccountStatusResponse.terms_digest_requires_billing_ref:
143
+ * `this.terms_digest == '' || this.billing_ref != ''`. The digest is what this
144
+ * ACCOUNT accepted, so it cannot travel without the account handle it hangs on. A
145
+ * reader that took the digest from a response carrying no billing_ref would be
146
+ * reading an acceptance for an account that does not exist. Mirror of the
147
+ * WellKnownManifest rule above, asked of the read side.
148
+ */
149
+ function getAccountStatusResponseRules(o) {
150
+ const termsDigest = str(field(o, "terms_digest"));
151
+ const billingRef = str(field(o, "billing_ref"));
152
+ if (termsDigest !== "" && billingRef === "") {
153
+ return ["get_account_status_response.terms_digest_requires_billing_ref"];
154
+ }
155
+ return [];
156
+ }
157
+ /**
158
+ * RegistrationFailure.field_errors_scoped_to_invalid_data:
159
+ * `this.field_errors.size() == 0 || this.reason == 6`. The member list names what
160
+ * failed the published schema, so any other reason carrying it publishes detail
161
+ * that does not apply to the refusal.
162
+ */
163
+ function registrationFailureRules(o) {
164
+ const fieldErrors = field(o, "field_errors");
165
+ if (Array.isArray(fieldErrors) && fieldErrors.length > 0) {
166
+ if (str(field(o, "reason")) !== REGISTRATION_FAILURE_INVALID_DATA) {
167
+ return ["registration_failure.field_errors_scoped_to_invalid_data"];
168
+ }
169
+ }
170
+ return [];
171
+ }
172
+ const RULES_BY_MESSAGE = {
173
+ GetAccountStatusResponse: getAccountStatusResponseRules,
174
+ License: licenseRules,
175
+ LicenseTerm: licenseTermRules,
176
+ Obligation: obligationRules,
177
+ Pricing: pricingRules,
178
+ Restriction: restrictionRules,
179
+ RegistrationFailure: registrationFailureRules,
180
+ WellKnownManifest: wellKnownManifestRules,
181
+ };
182
+ /**
183
+ * crossFieldRuleIds returns the cross-field (message-CEL) rule-ids the instance
184
+ * violates, empty when it passes cross-field validation. Direct analogue of the
185
+ * Go oracle's ValidationRuleIDs(err) over the crossfield corpus.
186
+ */
187
+ export function crossFieldRuleIds(message, json) {
188
+ const fn = RULES_BY_MESSAGE[message];
189
+ if (!fn)
190
+ throw new Error(`crossFieldRuleIds: unknown message ${message}`);
191
+ const o = asObj(json);
192
+ return o ? fn(o) : [];
193
+ }
194
+ function attach(schema, message) {
195
+ // Inside the generic, `superRefine` is typed on ZodTypeAny (Output and Input
196
+ // both `any`), which the compiler cannot relate to the deferred ReturnType;
197
+ // each exported constant below is annotated with the concrete CrossField.
198
+ return schema.superRefine((value, ctx) => {
199
+ for (const ruleId of crossFieldRuleIds(message, value)) {
200
+ ctx.addIssue({
201
+ code: z.ZodIssueCode.custom,
202
+ message: `cross-field rule violated: ${ruleId}`,
203
+ params: { ruleId },
204
+ });
205
+ }
206
+ });
207
+ }
208
+ export const GetAccountStatusResponseCrossFieldSchema = attach(GetAccountStatusResponseSchema, "GetAccountStatusResponse");
209
+ export const LicenseCrossFieldSchema = attach(LicenseSchema, "License");
210
+ export const LicenseTermCrossFieldSchema = attach(LicenseTermSchema, "LicenseTerm");
211
+ export const ObligationCrossFieldSchema = attach(ObligationSchema, "Obligation");
212
+ export const PricingCrossFieldSchema = attach(PricingSchema, "Pricing");
213
+ export const RestrictionCrossFieldSchema = attach(RestrictionSchema, "Restriction");
214
+ export const RegistrationFailureCrossFieldSchema = attach(RegistrationFailureSchema, "RegistrationFailure");
215
+ export const WellKnownManifestCrossFieldSchema = attach(WellKnownManifestSchema, "WellKnownManifest");
@@ -0,0 +1,30 @@
1
+ /** Why an endpoint a manifest advertises may not be handed back, or undefined
2
+ * when it may.
3
+ *
4
+ * The manifest that named this endpoint is served by the very host the call is
5
+ * bound for, so the endpoint is only as trustworthy as that host. An Exchange may
6
+ * advertise itself or a subdomain of itself, on the same port, and nothing else —
7
+ * a dial-time address guard has no objection to an unrelated PUBLIC host, so
8
+ * nothing below this catches one.
9
+ *
10
+ * Userinfo is refused for a different reason with the same shape: the host
11
+ * comparison reads the authority's host and ignores any user:password before it,
12
+ * so an endpoint carrying credentials would pass the host check and then have the
13
+ * HTTP client stamp an Authorization header the SDK never chose, on a leg that
14
+ * already carries the caller's own signature.
15
+ *
16
+ * It lives in ONE place because it has two callers, and they check the same value
17
+ * for different reasons. The resolver checks what a manifest advertised, because
18
+ * that is a property of reading an endpoint out of a manifest. The client re-checks
19
+ * whatever its endpoint resolver handed back, because that resolver is an
20
+ * injectable seam and this SDK cannot make a signed call conditional on a
21
+ * stranger's implementation having remembered the rule. Stated twice it drifts, and
22
+ * a half-mirrored version of this rule is how a signed call ends up carrying
23
+ * credentials the SDK never chose. The Go oracle keeps it in a shared internal
24
+ * package for exactly this reason.
25
+ *
26
+ * Both halves are decided over ONE reading of the reference, by the shared parse
27
+ * in src/host-ref.ts. That is not tidiness: a value naming no scheme is a URL to
28
+ * one parser and a path to another, and the two answers put a credential on
29
+ * opposite sides of the check — "u:p@exchange.example" is where they part. */
30
+ export declare function endpointRefusal(host: string, endpoint: string): string | undefined;
@@ -0,0 +1,63 @@
1
+ // The endpoint rule: whether an endpoint may be sent a signed call, given the host that
2
+ // named it. Pure — no IO — so both the resolver that reads it out of a manifest and the
3
+ // client that re-checks an injected resolver's answer share one statement of it.
4
+ //
5
+ // Deliberately not exported from the package manifest: it is the SDK's own rule, not a
6
+ // face a consumer composes.
7
+ import { anchoredParsed, parseRef } from "./host-ref.js";
8
+ /** Why an endpoint a manifest advertises may not be handed back, or undefined
9
+ * when it may.
10
+ *
11
+ * The manifest that named this endpoint is served by the very host the call is
12
+ * bound for, so the endpoint is only as trustworthy as that host. An Exchange may
13
+ * advertise itself or a subdomain of itself, on the same port, and nothing else —
14
+ * a dial-time address guard has no objection to an unrelated PUBLIC host, so
15
+ * nothing below this catches one.
16
+ *
17
+ * Userinfo is refused for a different reason with the same shape: the host
18
+ * comparison reads the authority's host and ignores any user:password before it,
19
+ * so an endpoint carrying credentials would pass the host check and then have the
20
+ * HTTP client stamp an Authorization header the SDK never chose, on a leg that
21
+ * already carries the caller's own signature.
22
+ *
23
+ * It lives in ONE place because it has two callers, and they check the same value
24
+ * for different reasons. The resolver checks what a manifest advertised, because
25
+ * that is a property of reading an endpoint out of a manifest. The client re-checks
26
+ * whatever its endpoint resolver handed back, because that resolver is an
27
+ * injectable seam and this SDK cannot make a signed call conditional on a
28
+ * stranger's implementation having remembered the rule. Stated twice it drifts, and
29
+ * a half-mirrored version of this rule is how a signed call ends up carrying
30
+ * credentials the SDK never chose. The Go oracle keeps it in a shared internal
31
+ * package for exactly this reason.
32
+ *
33
+ * Both halves are decided over ONE reading of the reference, by the shared parse
34
+ * in src/host-ref.ts. That is not tidiness: a value naming no scheme is a URL to
35
+ * one parser and a path to another, and the two answers put a credential on
36
+ * opposite sides of the check — "u:p@exchange.example" is where they part. */
37
+ export function endpointRefusal(host, endpoint) {
38
+ let advertised;
39
+ try {
40
+ advertised = parseRef(endpoint);
41
+ }
42
+ catch (err) {
43
+ // The error already names the reference, with any credential redacted. Echoing
44
+ // the raw endpoint alongside it would put the credential straight back — which
45
+ // is what happened when this branch moved ahead of the userinfo refusal below.
46
+ return `host=${JSON.stringify(host)}: ${String(err)}`;
47
+ }
48
+ if (advertised.hasUserinfo) {
49
+ // Deliberately does not echo the endpoint: it carries the credential.
50
+ return `host=${JSON.stringify(host)} advertises an endpoint carrying userinfo`;
51
+ }
52
+ let served;
53
+ try {
54
+ served = parseRef(host);
55
+ }
56
+ catch (err) {
57
+ return `the serving host is unusable: ${String(err)}`;
58
+ }
59
+ if (!anchoredParsed(served, advertised)) {
60
+ return `host=${JSON.stringify(host)} advertises endpoint ${JSON.stringify(endpoint)} on a different host`;
61
+ }
62
+ return undefined;
63
+ }
@@ -0,0 +1,115 @@
1
+ import type { z } from "zod";
2
+ import type { CatalogRejectionReasonSchema, DenialReasonSchema, DisputeFailureReasonSchema, DomainVerificationFailureReasonSchema, RegistrationFailureReasonSchema, RetrievalAuthFailureReasonSchema, UsageReportRejectionReasonSchema } from "../../../gen/ts/wire/schemas.ts";
3
+ import { ErrorDetailSchema } from "../../../gen/ts/wire/schemas.ts";
4
+ export type ErrorDetail = z.infer<typeof ErrorDetailSchema>;
5
+ /** The fully-qualified proto name Connect stamps on an ErrorDetail transport detail. */
6
+ export declare const ERROR_DETAIL_TYPE = "fora.v1.ErrorDetail";
7
+ /**
8
+ * The ErrorDetail `reason` oneof members, in proto field-number order (the same
9
+ * order the Go helpers.Reason accessor walks). Exactly one is populated when a
10
+ * typed reason is present; all are absent for a generic transport-class failure.
11
+ */
12
+ export declare const REASON_FIELDS: readonly ["transaction_denial", "catalog_rejection", "registration_failure", "dispute_failure", "domain_verification_failure", "retrieval_auth_failure", "usage_report_rejection"];
13
+ export type ReasonField = (typeof REASON_FIELDS)[number];
14
+ /** The extracted typed reason: which oneof family fired, and its enum NAME. */
15
+ export interface TypedReason {
16
+ field: ReasonField;
17
+ value: string;
18
+ }
19
+ /**
20
+ * Parse a canonical proto-JSON ErrorDetail object into the generated model. The
21
+ * payload is the proto-JSON object (snake_case keys, enums as NAME strings). This
22
+ * is the low-level decode the corpus replay exercises and the building block of
23
+ * {@link errorDetailFrom}.
24
+ */
25
+ export declare function parseErrorDetail(payload: unknown): ErrorDetail;
26
+ /**
27
+ * Return the active typed reason (oneof family + enum NAME), or null when no reason
28
+ * is set. Mirrors the Go helpers.Reason accessor so callers branch on the family +
29
+ * value, never on the human message string.
30
+ */
31
+ export declare function reason(detail: ErrorDetail): TypedReason | null;
32
+ /**
33
+ * Extract the first FORA ErrorDetail from a Connect error (or its details array).
34
+ * `err` is either a Connect error object (carrying a `details` array) or the
35
+ * details iterable itself. Each detail entry is the Connect wire form
36
+ * `{ "type": "fora.v1.ErrorDetail", ... }`; the ErrorDetail proto-JSON is read from
37
+ * the entry's `debug` projection (Connect includes it for JSON clients) or from a
38
+ * `value` already decoded to an object. Returns null when `err` carries no
39
+ * ErrorDetail — the TS analog of the Go `(detail, false)`.
40
+ *
41
+ * The opaque binary `value` of a detail is intentionally NOT decoded here: the JSON
42
+ * SDKs have no protobuf binary codec, so they consume the proto-JSON form.
43
+ *
44
+ * Both payload forms are read through protoNames, because `debug` arrives
45
+ * lowerCamelCase and a decoded `value` — which only a caller that owns a binary codec
46
+ * can supply — may be either. A snake_case object passes through it unchanged.
47
+ */
48
+ export declare function errorDetailFrom(err: unknown): ErrorDetail | null;
49
+ /** ExecuteTransaction denial reason (the DenialReason enum NAME set). */
50
+ export type DenialReason = z.infer<typeof DenialReasonSchema>;
51
+ /** Signed-URL / proof-of-possession failure reason. */
52
+ export type RetrievalAuthFailureReason = z.infer<typeof RetrievalAuthFailureReasonSchema>;
53
+ /** CatalogService rejection reason. */
54
+ export type CatalogRejectionReason = z.infer<typeof CatalogRejectionReasonSchema>;
55
+ /** Agent/provider registration failure reason. */
56
+ export type RegistrationFailureReason = z.infer<typeof RegistrationFailureReasonSchema>;
57
+ /** DisputeTransaction filing failure reason. */
58
+ export type DisputeFailureReason = z.infer<typeof DisputeFailureReasonSchema>;
59
+ /** Domain-verification failure reason. */
60
+ export type DomainVerificationFailureReason = z.infer<typeof DomainVerificationFailureReasonSchema>;
61
+ /** ReportUsage rejection reason. */
62
+ export type UsageReportRejectionReason = z.infer<typeof UsageReportRejectionReasonSchema>;
63
+ /**
64
+ * Build an ErrorDetail carrying a typed DenialReason (ExecuteTransaction denial).
65
+ * TS peer of Go `helpers.TransactionDenialDetail`. Sets only the `transaction_denial`
66
+ * reason block; the message's extra sub-fields (offer_id, restriction_mismatches) and
67
+ * metadata are omitted — mutate the returned object post-construction if needed.
68
+ */
69
+ export declare function transactionDenialDetail(domain: string, message: string, reason: DenialReason): ErrorDetail;
70
+ /**
71
+ * Build an ErrorDetail carrying a typed RetrievalAuthFailureReason.
72
+ * TS peer of Go `helpers.RetrievalAuthFailureDetail` (signed-URL / proof-of-possession
73
+ * check failed).
74
+ */
75
+ export declare function retrievalAuthFailureDetail(domain: string, message: string, reason: RetrievalAuthFailureReason): ErrorDetail;
76
+ /**
77
+ * Build an ErrorDetail carrying a typed CatalogRejectionReason.
78
+ * TS peer of Go `helpers.CatalogRejectionDetail`. Sets only the `catalog_rejection`
79
+ * reason block; `rejected_paths` is omitted.
80
+ */
81
+ export declare function catalogRejectionDetail(domain: string, message: string, reason: CatalogRejectionReason): ErrorDetail;
82
+ /** One offending `registration_data` member on a schema-enforcement refusal. */
83
+ export type RegistrationFieldError = {
84
+ /** RFC 6901 JSON Pointer relative to `registration_data`; "" is the whole object. */
85
+ path: string;
86
+ /** Non-authoritative description of what failed; states the constraint, never the value. */
87
+ error: string;
88
+ };
89
+ /**
90
+ * Build an ErrorDetail carrying a typed RegistrationFailureReason.
91
+ * TS peer of Go `helpers.RegistrationFailureDetail` (agent/provider registration
92
+ * refused).
93
+ *
94
+ * `fieldErrors` carries the offending `registration_data` members when the reason
95
+ * is `REGISTRATION_FAILURE_REASON_INVALID_REGISTRATION_DATA`. It is optional
96
+ * rather than positional so the six reasons that carry no per-member detail keep
97
+ * the three-argument call, matching Go's variadic. Passing it with any other
98
+ * reason is a caller error — the field's contract says the list is empty then.
99
+ */
100
+ export declare function registrationFailureDetail(domain: string, message: string, reason: RegistrationFailureReason, fieldErrors?: readonly RegistrationFieldError[]): ErrorDetail;
101
+ /**
102
+ * Build an ErrorDetail carrying a typed DisputeFailureReason.
103
+ * TS peer of Go `helpers.DisputeFailureDetail` (DisputeTransaction filing refused).
104
+ */
105
+ export declare function disputeFailureDetail(domain: string, message: string, reason: DisputeFailureReason): ErrorDetail;
106
+ /**
107
+ * Build an ErrorDetail carrying a typed DomainVerificationFailureReason.
108
+ * TS peer of Go `helpers.DomainVerificationFailureDetail` (domain verification failed).
109
+ */
110
+ export declare function domainVerificationFailureDetail(domain: string, message: string, reason: DomainVerificationFailureReason): ErrorDetail;
111
+ /**
112
+ * Build an ErrorDetail carrying a typed UsageReportRejectionReason.
113
+ * TS peer of Go `helpers.UsageReportRejectionDetail` (ReportUsage filing rejected).
114
+ */
115
+ export declare function usageReportRejectionDetail(domain: string, message: string, reason: UsageReportRejectionReason): ErrorDetail;