@zackbart/connecta 0.30.0 → 0.31.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.
- package/CHANGELOG.md +32 -0
- package/README.md +6 -3
- package/bin/version.mjs +1 -1
- package/dist/call-recovery.js +25 -0
- package/dist/config-schema.d.ts +14 -7
- package/dist/config-schema.js +29 -10
- package/dist/connectors/guarded-fetch.d.ts +9 -1
- package/dist/connectors/guarded-fetch.js +14 -2
- package/dist/errors.d.ts +2 -0
- package/dist/invocation.js +32 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/view.d.ts +9 -0
- package/dist/operator-ui/view.js +11 -0
- package/dist/program-writes.js +2 -47
- package/dist/provider.d.ts +7 -5
- package/dist/provider.js +3 -4
- package/dist/providers/_shared/rest/dispatch.js +41 -0
- package/dist/providers/_shared/rest/operation-index.d.ts +133 -0
- package/dist/providers/_shared/rest/operation-index.js +527 -0
- package/dist/providers/_shared/rest/tools.d.ts +141 -0
- package/dist/providers/_shared/rest/tools.js +569 -0
- package/dist/providers/_shared/rest/value-safety.d.ts +151 -0
- package/dist/providers/_shared/rest/value-safety.js +580 -0
- package/dist/providers/cloudflare/graphql.js +385 -0
- package/dist/providers/cloudflare/index.d.ts +47 -51
- package/dist/providers/cloudflare/index.js +188 -1997
- package/dist/providers/cloudflare/openapi.generated.js +3347 -0
- package/dist/providers/cloudflare/rest.d.ts +37 -0
- package/dist/providers/cloudflare/rest.js +1056 -0
- package/dist/providers/cloudflare/skill.generated.js +7 -4
- package/dist/providers/cloudflare/value-safety.js +1247 -0
- package/dist/providers/notion/index.d.ts +35 -31
- package/dist/providers/notion/index.js +60 -1499
- package/dist/providers/notion/openapi.generated.js +75 -0
- package/dist/providers/notion/rest.d.ts +24 -0
- package/dist/providers/notion/rest.js +1067 -0
- package/dist/providers/notion/skill.generated.js +5 -4
- package/dist/providers/notion/value-safety.js +31 -0
- package/dist/providers/stripe/index.d.ts +26 -20
- package/dist/providers/stripe/index.js +103 -130
- package/dist/providers/stripe/openapi.generated.js +649 -0
- package/dist/providers/stripe/rest.d.ts +14 -0
- package/dist/providers/stripe/rest.js +395 -0
- package/dist/providers/stripe/skill.generated.js +7 -5
- package/dist/providers/stripe/value-safety.js +705 -0
- package/dist/providers/vercel/index.d.ts +31 -22
- package/dist/providers/vercel/index.js +96 -853
- package/dist/providers/vercel/openapi.generated.js +456 -0
- package/dist/providers/vercel/rest.d.ts +20 -0
- package/dist/providers/vercel/rest.js +1002 -0
- package/dist/providers/vercel/skill.generated.js +4 -5
- package/dist/providers/vercel/value-safety.js +328 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/write-outcome.js +47 -0
- package/documentation/README.md +1 -0
- package/documentation/architecture.md +120 -8
- package/documentation/integrating.md +16 -5
- package/documentation/meta-tools.md +9 -2
- package/documentation/provider-auth-migration.md +307 -0
- package/documentation/provider-migration-0.29.md +17 -5
- package/examples/worker/README.md +2 -2
- package/package.json +3 -2
- package/templates/node/README.md +2 -2
- package/templates/node/package.json +1 -1
- package/dist/providers/vercel/mcp-ownership.js +0 -212
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
// Stripe's reviewed value-safety table (#801), on the shared mechanism in
|
|
2
|
+
// `../_shared/rest/value-safety.ts`: every operation the detector flags in the
|
|
3
|
+
// pinned spec (`value-safety.candidates.json`) has one verdict here, and
|
|
4
|
+
// `value-safety.node.test.ts` runs the shared harness over it.
|
|
5
|
+
//
|
|
6
|
+
// Stripe repeats one object graph across hundreds of operations (a
|
|
7
|
+
// PaymentIntent is embedded in charges, invoices, and errors), so most flagged
|
|
8
|
+
// fields are reviewed once for the whole API in `fields` rather than per
|
|
9
|
+
// operation, and the detector does not walk id-or-object expansions
|
|
10
|
+
// (`expansions: false`): Stripe answers an id unless the caller expands it,
|
|
11
|
+
// and the field review and heuristic apply to whatever an expansion returns.
|
|
12
|
+
//
|
|
13
|
+
// The decisions against the bar (decision 0005, "Value safety"):
|
|
14
|
+
//
|
|
15
|
+
// - Refused: operations whose purpose is to hand out a credential. Ephemeral
|
|
16
|
+
// keys and Terminal connection tokens are API credentials; account links
|
|
17
|
+
// (v1 and v2), Terminal onboarding links, login links, account sessions,
|
|
18
|
+
// customer sessions, and billing portal
|
|
19
|
+
// sessions sign their holder into a Stripe-hosted surface as a connected
|
|
20
|
+
// account or a customer; a file link makes a private file (dispute
|
|
21
|
+
// evidence, identity documents) public; Financial Connections sessions and
|
|
22
|
+
// the meter event session exist to return a client secret or a stream
|
|
23
|
+
// token. Stripe's OAuth endpoints (connect.stripe.com) are not in the
|
|
24
|
+
// pinned spec, so the generic tools refuse them as unknown paths.
|
|
25
|
+
// - Redacted: client secrets (PaymentIntents, SetupIntents, Checkout and
|
|
26
|
+
// Identity sessions, Sources, Financial Connections, invoice confirmation
|
|
27
|
+
// secrets). They are publishable-side secrets: with the account's
|
|
28
|
+
// publishable key they confirm, complete, or read the object from a
|
|
29
|
+
// browser. Connecta's agent works server-side and never needs one, while
|
|
30
|
+
// the objects around them are the API's core, so the field goes and the
|
|
31
|
+
// operation stays. Webhook and event destination signing secrets, Apps
|
|
32
|
+
// secret payloads, app-install OAuth codes, Terminal Wi-Fi passwords,
|
|
33
|
+
// forwarded request header values, pre-signed upload URLs, and file link
|
|
34
|
+
// URLs go the same way.
|
|
35
|
+
// - Resource rules (`resources`, keyed on Stripe's `object` discriminator)
|
|
36
|
+
// apply to every object wherever a response embeds it: expansions, lists,
|
|
37
|
+
// search results, and events' `data.object` and `previous_attributes`. They
|
|
38
|
+
// are the backstop for expansions: an expanded File carries its public file
|
|
39
|
+
// links, an expanded PaymentIntent its client secret.
|
|
40
|
+
// - Hosted Checkout URLs are withheld by default and come back verbatim only
|
|
41
|
+
// for a provably guest payment session (`GUEST_CHECKOUT`: no Customer, no
|
|
42
|
+
// Account, no Customer creation, no saved payment method options,
|
|
43
|
+
// `mode: "payment"`): such a page only takes a payment. A bound session can
|
|
44
|
+
// display, reuse, or remove saved payment methods, so its URL keeps only its
|
|
45
|
+
// origin. Identity verification URLs come back verbatim: the page
|
|
46
|
+
// collects documents from the person being verified and shows no stored
|
|
47
|
+
// data. Payment link URLs are public by design and bound to no customer.
|
|
48
|
+
// - Issuing card numbers and CVCs come back only as expansions, which the
|
|
49
|
+
// connector refuses on every Issuing path (`rest.ts`); the card operations
|
|
50
|
+
// also redact both fields.
|
|
51
|
+
import { redact, refuse, safe, vendorErrors, } from "../_shared/rest/value-safety.js";
|
|
52
|
+
const EPHEMERAL_KEY = "It mints an ephemeral API key whose `secret` makes authorized Stripe API requests for a customer or Issuing card.";
|
|
53
|
+
const CONNECTION_TOKEN = "It mints a Terminal connection token whose `secret` connects a reader SDK to this account.";
|
|
54
|
+
const ACCOUNT_LINK = "It creates a single-use link that lets its holder enter or change a connected account's identity and bank details. Create account links from your platform's server code or the Dashboard.";
|
|
55
|
+
const LOGIN_LINK = "It creates a single-use link that signs its holder into a connected account's Express Dashboard.";
|
|
56
|
+
const ACCOUNT_SESSION = "It returns a client secret that grants embedded-component access to a connected account.";
|
|
57
|
+
const CUSTOMER_SESSION = "It returns a client secret that grants client-side access to a customer's saved payment methods.";
|
|
58
|
+
const ONBOARDING_LINK = "It creates a link that accepts Tap to Pay terms on the merchant's behalf; open it from the Dashboard or your own onboarding flow.";
|
|
59
|
+
const PORTAL_SESSION = "It creates a customer portal session whose URL signs its holder in as the customer (payment methods, subscriptions, invoices).";
|
|
60
|
+
const FILE_LINK = "It creates a public URL to a private file (dispute evidence and identity documents among them) that anyone holding it can download.";
|
|
61
|
+
const FC_SESSION = "It exists to return a client secret for the Financial Connections authorization flow in a browser.";
|
|
62
|
+
const METER_SESSION = "It mints an authentication token for the meter event stream.";
|
|
63
|
+
const EPHEMERAL_REVOKE = "Revokes an ephemeral key; the answer repeats the key's secret, which is redacted.";
|
|
64
|
+
const WEBHOOK = "Webhook endpoints carry a signing secret and a destination URL whose path or query can be a bearer secret.";
|
|
65
|
+
const EVENT_DESTINATION = "Event destinations carry a webhook signing secret and a destination URL whose path or query can be a bearer secret.";
|
|
66
|
+
const APPS_SECRET = "An Apps secret's payload is the stored secret value; names and scopes stay. Expanding payload is also refused (`rest.ts`).";
|
|
67
|
+
const APP_INSTALL = "An app install's auth_code is an OAuth authorization code exchangeable for tokens.";
|
|
68
|
+
const TERMINAL_CONFIG = "Terminal configurations carry Wi-Fi passwords and a private key password; the key file is a File id, and the pre-shared-key network's SSID stays.";
|
|
69
|
+
const FORWARDING = "Forwarded requests carry header values sent to and returned by a third party (API keys, Authorization); header names stay.";
|
|
70
|
+
const PRESIGNED = "Product catalog imports answer pre-signed upload and error-file URLs that grant access without Stripe authentication.";
|
|
71
|
+
const ISSUING_CARD = "Full card numbers and CVCs are refused as expansions (`rest.ts`) and redacted here; the card id, last4, and expiry stay.";
|
|
72
|
+
const FILE = "A file's own URL needs the account's secret key; its file links are public bearer URLs, reduced to their origin.";
|
|
73
|
+
const FILE_LINK_READ = "A file link's URL lets anyone download the file; only its origin comes back.";
|
|
74
|
+
const CHECKOUT = "Checkout Sessions carry a client secret (redacted). The hosted page URL follows the checkout.session resource rule: verbatim for a guest session, origin only for one bound to a customer.";
|
|
75
|
+
const IDENTITY_SESSION = "Identity verification sessions carry a client secret (redacted); the hosted verification URL follows the identity.verification_session resource rule.";
|
|
76
|
+
const FC_SESSION_READ = "A Financial Connections session's client secret is redacted; its linked accounts stay.";
|
|
77
|
+
const REPORT_FILE = "Report and query results are Files whose URL needs the account's secret key to download.";
|
|
78
|
+
const DELETED = "Answers a deletion; no secret.";
|
|
79
|
+
const PAYMENTS = "Payment objects: the flagged fields are payment-method options, issuer authorization codes, network-token metadata, and payer-facing redirect URLs (credential query parameters sanitized). No credential.";
|
|
80
|
+
const PAYMENTS_SECRET = "Payment objects carry a client secret, redacted; the rest is payment-method options, issuer codes, and network-token metadata.";
|
|
81
|
+
const BILLING = "Customer and billing objects: the flagged fields are payment-method settings and embedded payment metadata; embedded client secrets are redacted by the field review.";
|
|
82
|
+
const BILLING_SECRET = "Billing objects carry a client or confirmation secret, redacted; the rest is billing and payment-method metadata.";
|
|
83
|
+
const ACCOUNTS = "Connected account settings, external accounts, and requirement references (file and object ids); no credential.";
|
|
84
|
+
const ISSUING = "Issuing objects: cardholder preferences, network-token metadata, and authorization codes. Full card numbers and CVCs are refused as expansions.";
|
|
85
|
+
const TERMINAL = "Terminal readers and their actions; collected-input metadata, no credential.";
|
|
86
|
+
const MONEY = "Money movement and Treasury flows, flagged for transfer and flow vocabulary; financial addresses are receiving details, not credentials.";
|
|
87
|
+
const VERIFICATION = "Verification and Financial Connections records; flow and refresh tokens are object ids.";
|
|
88
|
+
const QUERY = "A saved Sigma query; flagged for its name, no credential.";
|
|
89
|
+
/** The reviewed verdict for every flagged operation, and for the credential families the detector does not flag. */
|
|
90
|
+
const OPERATIONS = {
|
|
91
|
+
"POST /v1/account_links": refuse(ACCOUNT_LINK),
|
|
92
|
+
"POST /v1/account_sessions": refuse(ACCOUNT_SESSION),
|
|
93
|
+
"POST /v1/accounts/{account}/login_links": refuse(LOGIN_LINK),
|
|
94
|
+
"POST /v1/billing_portal/sessions": refuse(PORTAL_SESSION),
|
|
95
|
+
"POST /v1/customer_sessions": refuse(CUSTOMER_SESSION),
|
|
96
|
+
"POST /v1/ephemeral_keys": refuse(EPHEMERAL_KEY),
|
|
97
|
+
"POST /v1/file_links": refuse(FILE_LINK),
|
|
98
|
+
"POST /v1/financial_connections/sessions": refuse(FC_SESSION),
|
|
99
|
+
"POST /v1/link_account_sessions": refuse(FC_SESSION),
|
|
100
|
+
"POST /v1/terminal/connection_tokens": refuse(CONNECTION_TOKEN),
|
|
101
|
+
"POST /v1/terminal/onboarding_links": refuse(ONBOARDING_LINK),
|
|
102
|
+
"POST /v2/billing/meter_event_session": refuse(METER_SESSION),
|
|
103
|
+
"POST /v2/core/account_links": refuse(ACCOUNT_LINK),
|
|
104
|
+
...Object.fromEntries([
|
|
105
|
+
"GET /v1/account",
|
|
106
|
+
"GET /v1/accounts",
|
|
107
|
+
"POST /v1/accounts",
|
|
108
|
+
"GET /v1/accounts/{account}",
|
|
109
|
+
"POST /v1/accounts/{account}",
|
|
110
|
+
"POST /v1/accounts/{account}/bank_accounts",
|
|
111
|
+
"GET /v1/accounts/{account}/bank_accounts/{id}",
|
|
112
|
+
"POST /v1/accounts/{account}/bank_accounts/{id}",
|
|
113
|
+
"GET /v1/accounts/{account}/external_accounts",
|
|
114
|
+
"POST /v1/accounts/{account}/external_accounts",
|
|
115
|
+
"GET /v1/accounts/{account}/external_accounts/{id}",
|
|
116
|
+
"POST /v1/accounts/{account}/external_accounts/{id}",
|
|
117
|
+
"POST /v1/accounts/{account}/reject",
|
|
118
|
+
"POST /v1/accounts/{account}/unreject",
|
|
119
|
+
"POST /v2/core/account_tokens",
|
|
120
|
+
"GET /v2/core/account_tokens/{id}",
|
|
121
|
+
"GET /v2/core/accounts",
|
|
122
|
+
"POST /v2/core/accounts",
|
|
123
|
+
"POST /v2/core/accounts/{account_id}/person_tokens",
|
|
124
|
+
"GET /v2/core/accounts/{account_id}/person_tokens/{id}",
|
|
125
|
+
"GET /v2/core/accounts/{account_id}/persons",
|
|
126
|
+
"POST /v2/core/accounts/{account_id}/persons",
|
|
127
|
+
"GET /v2/core/accounts/{account_id}/persons/{id}",
|
|
128
|
+
"POST /v2/core/accounts/{account_id}/persons/{id}",
|
|
129
|
+
"GET /v2/core/accounts/{id}",
|
|
130
|
+
"POST /v2/core/accounts/{id}",
|
|
131
|
+
"POST /v2/core/accounts/{id}/close",
|
|
132
|
+
].map((key) => [key, vendorErrors(safe(ACCOUNTS))])),
|
|
133
|
+
"GET /v1/apps/secrets": redact(APPS_SECRET, ["data.payload"]),
|
|
134
|
+
...Object.fromEntries(["POST /v1/apps/secrets", "POST /v1/apps/secrets/delete", "GET /v1/apps/secrets/find"].map((key) => [
|
|
135
|
+
key,
|
|
136
|
+
redact(APPS_SECRET, ["payload"]),
|
|
137
|
+
])),
|
|
138
|
+
...Object.fromEntries([
|
|
139
|
+
"POST /v1/apps/installs",
|
|
140
|
+
"GET /v1/apps/installs/{id}",
|
|
141
|
+
"POST /v1/apps/installs/{id}",
|
|
142
|
+
"POST /v1/apps/installs/{id}/uninstall",
|
|
143
|
+
].map((key) => [key, redact(APP_INSTALL, ["auth_code"])])),
|
|
144
|
+
"GET /v1/apps/installs": redact(APP_INSTALL, ["data.auth_code"]),
|
|
145
|
+
...Object.fromEntries([
|
|
146
|
+
"GET /v1/checkout/sessions/{session}/line_items",
|
|
147
|
+
"GET /v1/customers",
|
|
148
|
+
"POST /v1/customers",
|
|
149
|
+
"GET /v1/customers/search",
|
|
150
|
+
"GET /v1/customers/{customer}",
|
|
151
|
+
"POST /v1/customers/{customer}",
|
|
152
|
+
"GET /v1/customers/{customer}/payment_methods",
|
|
153
|
+
"GET /v1/customers/{customer}/payment_methods/{payment_method}",
|
|
154
|
+
"GET /v1/customers/{customer}/subscriptions",
|
|
155
|
+
"POST /v1/customers/{customer}/subscriptions",
|
|
156
|
+
"GET /v1/customers/{customer}/subscriptions/{subscription_exposed_id}",
|
|
157
|
+
"POST /v1/customers/{customer}/subscriptions/{subscription_exposed_id}",
|
|
158
|
+
"DELETE /v1/customers/{customer}/subscriptions/{subscription_exposed_id}",
|
|
159
|
+
"GET /v1/payment_links",
|
|
160
|
+
"POST /v1/payment_links",
|
|
161
|
+
"GET /v1/payment_links/{payment_link}",
|
|
162
|
+
"POST /v1/payment_links/{payment_link}",
|
|
163
|
+
"GET /v1/payment_links/{payment_link}/line_items",
|
|
164
|
+
"GET /v1/prices",
|
|
165
|
+
"POST /v1/prices",
|
|
166
|
+
"GET /v1/prices/search",
|
|
167
|
+
"GET /v1/prices/{price}",
|
|
168
|
+
"POST /v1/prices/{price}",
|
|
169
|
+
"GET /v1/quotes",
|
|
170
|
+
"POST /v1/quotes",
|
|
171
|
+
"GET /v1/quotes/{quote}",
|
|
172
|
+
"POST /v1/quotes/{quote}",
|
|
173
|
+
"POST /v1/quotes/{quote}/accept",
|
|
174
|
+
"POST /v1/quotes/{quote}/cancel",
|
|
175
|
+
"GET /v1/quotes/{quote}/computed_upfront_line_items",
|
|
176
|
+
"POST /v1/quotes/{quote}/finalize",
|
|
177
|
+
"GET /v1/quotes/{quote}/line_items",
|
|
178
|
+
"GET /v1/shipping_rates/{shipping_rate_token}",
|
|
179
|
+
"POST /v1/shipping_rates/{shipping_rate_token}",
|
|
180
|
+
"GET /v1/subscription_items",
|
|
181
|
+
"POST /v1/subscription_items",
|
|
182
|
+
"GET /v1/subscription_items/{item}",
|
|
183
|
+
"POST /v1/subscription_items/{item}",
|
|
184
|
+
"GET /v1/subscriptions",
|
|
185
|
+
"POST /v1/subscriptions",
|
|
186
|
+
"GET /v1/subscriptions/search",
|
|
187
|
+
"GET /v1/subscriptions/{subscription_exposed_id}",
|
|
188
|
+
"POST /v1/subscriptions/{subscription_exposed_id}",
|
|
189
|
+
"DELETE /v1/subscriptions/{subscription_exposed_id}",
|
|
190
|
+
"POST /v1/subscriptions/{subscription}/migrate",
|
|
191
|
+
"POST /v1/subscriptions/{subscription}/pause",
|
|
192
|
+
"POST /v1/subscriptions/{subscription}/resume",
|
|
193
|
+
].map((key) => [key, vendorErrors(safe(BILLING))])),
|
|
194
|
+
...Object.fromEntries([
|
|
195
|
+
"POST /v1/customers/{customer}/bank_accounts",
|
|
196
|
+
"POST /v1/customers/{customer}/bank_accounts/{id}",
|
|
197
|
+
"DELETE /v1/customers/{customer}/bank_accounts/{id}",
|
|
198
|
+
"POST /v1/customers/{customer}/cards",
|
|
199
|
+
"POST /v1/customers/{customer}/cards/{id}",
|
|
200
|
+
"DELETE /v1/customers/{customer}/cards/{id}",
|
|
201
|
+
"POST /v1/customers/{customer}/sources",
|
|
202
|
+
"GET /v1/customers/{customer}/sources/{id}",
|
|
203
|
+
"POST /v1/customers/{customer}/sources/{id}",
|
|
204
|
+
"DELETE /v1/customers/{customer}/sources/{id}",
|
|
205
|
+
].map((key) => [key, vendorErrors(redact(BILLING_SECRET, ["client_secret"]))])),
|
|
206
|
+
...Object.fromEntries([
|
|
207
|
+
"POST /v1/invoices",
|
|
208
|
+
"POST /v1/invoices/create_preview",
|
|
209
|
+
"GET /v1/invoices/{invoice}",
|
|
210
|
+
"POST /v1/invoices/{invoice}",
|
|
211
|
+
"POST /v1/invoices/{invoice}/add_lines",
|
|
212
|
+
"POST /v1/invoices/{invoice}/attach_payment",
|
|
213
|
+
"POST /v1/invoices/{invoice}/finalize",
|
|
214
|
+
"POST /v1/invoices/{invoice}/mark_uncollectible",
|
|
215
|
+
"POST /v1/invoices/{invoice}/pay",
|
|
216
|
+
"POST /v1/invoices/{invoice}/remove_lines",
|
|
217
|
+
"POST /v1/invoices/{invoice}/send",
|
|
218
|
+
"POST /v1/invoices/{invoice}/update_lines",
|
|
219
|
+
"POST /v1/invoices/{invoice}/void",
|
|
220
|
+
].map((key) => [key, vendorErrors(redact(BILLING_SECRET, ["confirmation_secret"]))])),
|
|
221
|
+
"GET /v1/customers/{customer}/sources": vendorErrors(redact(BILLING_SECRET, ["data.client_secret"])),
|
|
222
|
+
...Object.fromEntries(["GET /v1/invoices", "GET /v1/invoices/search"].map((key) => [
|
|
223
|
+
key,
|
|
224
|
+
vendorErrors(redact(BILLING_SECRET, ["data.confirmation_secret"])),
|
|
225
|
+
])),
|
|
226
|
+
...Object.fromEntries([
|
|
227
|
+
"POST /v1/checkout/sessions",
|
|
228
|
+
"GET /v1/checkout/sessions/{session}",
|
|
229
|
+
"POST /v1/checkout/sessions/{session}",
|
|
230
|
+
"POST /v1/checkout/sessions/{session}/expire",
|
|
231
|
+
].map((key) => [key, vendorErrors(redact(CHECKOUT, ["client_secret"]))])),
|
|
232
|
+
"GET /v1/checkout/sessions": vendorErrors(redact(CHECKOUT, ["data.client_secret"])),
|
|
233
|
+
"DELETE /v1/webhook_endpoints/{webhook_endpoint}": vendorErrors(safe(DELETED)),
|
|
234
|
+
"DELETE /v1/ephemeral_keys/{key}": redact(EPHEMERAL_REVOKE, ["secret"]),
|
|
235
|
+
"GET /v2/core/event_destinations": redact(EVENT_DESTINATION, [
|
|
236
|
+
"data.webhook_endpoint.signing_secret",
|
|
237
|
+
"origin:data.webhook_endpoint.url",
|
|
238
|
+
]),
|
|
239
|
+
...Object.fromEntries([
|
|
240
|
+
"POST /v2/core/event_destinations",
|
|
241
|
+
"GET /v2/core/event_destinations/{id}",
|
|
242
|
+
"POST /v2/core/event_destinations/{id}",
|
|
243
|
+
"POST /v2/core/event_destinations/{id}/disable",
|
|
244
|
+
"POST /v2/core/event_destinations/{id}/enable",
|
|
245
|
+
].map((key) => [
|
|
246
|
+
key,
|
|
247
|
+
redact(EVENT_DESTINATION, ["webhook_endpoint.signing_secret", "origin:webhook_endpoint.url"]),
|
|
248
|
+
])),
|
|
249
|
+
...Object.fromEntries(["GET /v1/financial_connections/sessions/{session}", "GET /v1/link_account_sessions/{session}"].map((key) => [
|
|
250
|
+
key,
|
|
251
|
+
vendorErrors(redact(FC_SESSION_READ, ["client_secret"])),
|
|
252
|
+
])),
|
|
253
|
+
"GET /v1/files": vendorErrors(redact(FILE, ["origin:data.links.data.url"], ["url", "data.url"])),
|
|
254
|
+
...Object.fromEntries(["POST /v1/files", "GET /v1/files/{file}"].map((key) => [
|
|
255
|
+
key,
|
|
256
|
+
vendorErrors(redact(FILE, ["origin:links.data.url"], ["url"])),
|
|
257
|
+
])),
|
|
258
|
+
...Object.fromEntries(["GET /v1/file_links/{link}", "POST /v1/file_links/{link}"].map((key) => [
|
|
259
|
+
key,
|
|
260
|
+
redact(FILE_LINK_READ, ["origin:url"]),
|
|
261
|
+
])),
|
|
262
|
+
"GET /v1/file_links": redact(FILE_LINK_READ, ["origin:url", "origin:data.url"]),
|
|
263
|
+
"GET /v1/forwarding/requests": redact(FORWARDING, [
|
|
264
|
+
"data.request_details.headers.value",
|
|
265
|
+
"data.response_details.headers.value",
|
|
266
|
+
]),
|
|
267
|
+
...Object.fromEntries(["POST /v1/forwarding/requests", "GET /v1/forwarding/requests/{id}"].map((key) => [
|
|
268
|
+
key,
|
|
269
|
+
redact(FORWARDING, ["request_details.headers.value", "response_details.headers.value"]),
|
|
270
|
+
])),
|
|
271
|
+
...Object.fromEntries([
|
|
272
|
+
"POST /v1/identity/verification_sessions",
|
|
273
|
+
"GET /v1/identity/verification_sessions/{session}",
|
|
274
|
+
"POST /v1/identity/verification_sessions/{session}",
|
|
275
|
+
"POST /v1/identity/verification_sessions/{session}/cancel",
|
|
276
|
+
"POST /v1/identity/verification_sessions/{session}/redact",
|
|
277
|
+
].map((key) => [key, vendorErrors(redact(IDENTITY_SESSION, ["client_secret"]))])),
|
|
278
|
+
"GET /v1/identity/verification_sessions": vendorErrors(redact(IDENTITY_SESSION, ["data.client_secret"])),
|
|
279
|
+
...Object.fromEntries([
|
|
280
|
+
"GET /v1/issuing/cardholders",
|
|
281
|
+
"POST /v1/issuing/cardholders",
|
|
282
|
+
"GET /v1/issuing/cardholders/{cardholder}",
|
|
283
|
+
"POST /v1/issuing/cardholders/{cardholder}",
|
|
284
|
+
"GET /v1/issuing/disputes",
|
|
285
|
+
"POST /v1/issuing/disputes",
|
|
286
|
+
"GET /v1/issuing/disputes/{dispute}",
|
|
287
|
+
"POST /v1/issuing/disputes/{dispute}",
|
|
288
|
+
"POST /v1/issuing/disputes/{dispute}/submit",
|
|
289
|
+
"POST /v1/issuing/personalization_designs",
|
|
290
|
+
"GET /v1/issuing/personalization_designs/{personalization_design}",
|
|
291
|
+
"POST /v1/issuing/personalization_designs/{personalization_design}",
|
|
292
|
+
"GET /v1/issuing/tokens",
|
|
293
|
+
"GET /v1/issuing/tokens/{token}",
|
|
294
|
+
"POST /v1/issuing/tokens/{token}",
|
|
295
|
+
"POST /v1/test_helpers/issuing/personalization_designs/{personalization_design}/activate",
|
|
296
|
+
"POST /v1/test_helpers/issuing/personalization_designs/{personalization_design}/deactivate",
|
|
297
|
+
"POST /v1/test_helpers/issuing/personalization_designs/{personalization_design}/reject",
|
|
298
|
+
].map((key) => [key, vendorErrors(safe(ISSUING))])),
|
|
299
|
+
"GET /v1/issuing/transactions": vendorErrors(safe(ISSUING, ["data.token", "data.authorization"])),
|
|
300
|
+
"GET /v1/issuing/authorizations": vendorErrors(safe(ISSUING, ["data.token", "data.transactions.token", "data.transactions.authorization"])),
|
|
301
|
+
...Object.fromEntries([
|
|
302
|
+
"GET /v1/issuing/transactions/{transaction}",
|
|
303
|
+
"POST /v1/issuing/transactions/{transaction}",
|
|
304
|
+
"POST /v1/test_helpers/issuing/transactions/create_force_capture",
|
|
305
|
+
"POST /v1/test_helpers/issuing/transactions/create_unlinked_refund",
|
|
306
|
+
"POST /v1/test_helpers/issuing/transactions/{transaction}/refund",
|
|
307
|
+
].map((key) => [key, vendorErrors(safe(ISSUING, ["token", "authorization"]))])),
|
|
308
|
+
...Object.fromEntries([
|
|
309
|
+
"GET /v1/issuing/authorizations/{authorization}",
|
|
310
|
+
"POST /v1/issuing/authorizations/{authorization}",
|
|
311
|
+
"POST /v1/test_helpers/issuing/authorizations",
|
|
312
|
+
"POST /v1/test_helpers/issuing/authorizations/{authorization}/capture",
|
|
313
|
+
"POST /v1/test_helpers/issuing/authorizations/{authorization}/expire",
|
|
314
|
+
"POST /v1/test_helpers/issuing/authorizations/{authorization}/finalize_amount",
|
|
315
|
+
"POST /v1/test_helpers/issuing/authorizations/{authorization}/fraud_challenges/respond",
|
|
316
|
+
"POST /v1/test_helpers/issuing/authorizations/{authorization}/increment",
|
|
317
|
+
"POST /v1/test_helpers/issuing/authorizations/{authorization}/reverse",
|
|
318
|
+
].map((key) => [key, vendorErrors(safe(ISSUING, ["token", "transactions.token", "transactions.authorization"]))])),
|
|
319
|
+
"GET /v1/issuing/cards": vendorErrors(redact(ISSUING_CARD, ["data.number", "data.cvc"])),
|
|
320
|
+
...Object.fromEntries([
|
|
321
|
+
"POST /v1/issuing/cards",
|
|
322
|
+
"GET /v1/issuing/cards/{card}",
|
|
323
|
+
"POST /v1/issuing/cards/{card}",
|
|
324
|
+
"POST /v1/test_helpers/issuing/cards/{card}/shipping/deliver",
|
|
325
|
+
"POST /v1/test_helpers/issuing/cards/{card}/shipping/fail",
|
|
326
|
+
"POST /v1/test_helpers/issuing/cards/{card}/shipping/return",
|
|
327
|
+
"POST /v1/test_helpers/issuing/cards/{card}/shipping/ship",
|
|
328
|
+
"POST /v1/test_helpers/issuing/cards/{card}/shipping/submit",
|
|
329
|
+
].map((key) => [key, vendorErrors(redact(ISSUING_CARD, ["number", "cvc"]))])),
|
|
330
|
+
...Object.fromEntries([
|
|
331
|
+
"POST /v1/test_helpers/treasury/inbound_transfers/{id}/fail",
|
|
332
|
+
"POST /v1/test_helpers/treasury/inbound_transfers/{id}/return",
|
|
333
|
+
"POST /v1/test_helpers/treasury/inbound_transfers/{id}/succeed",
|
|
334
|
+
"POST /v1/test_helpers/treasury/outbound_payments/{id}",
|
|
335
|
+
"POST /v1/test_helpers/treasury/outbound_payments/{id}/fail",
|
|
336
|
+
"POST /v1/test_helpers/treasury/outbound_payments/{id}/post",
|
|
337
|
+
"POST /v1/test_helpers/treasury/outbound_payments/{id}/return",
|
|
338
|
+
"POST /v1/test_helpers/treasury/outbound_transfers/{outbound_transfer}",
|
|
339
|
+
"POST /v1/test_helpers/treasury/outbound_transfers/{outbound_transfer}/fail",
|
|
340
|
+
"POST /v1/test_helpers/treasury/outbound_transfers/{outbound_transfer}/post",
|
|
341
|
+
"POST /v1/test_helpers/treasury/outbound_transfers/{outbound_transfer}/return",
|
|
342
|
+
"POST /v1/test_helpers/treasury/received_credits",
|
|
343
|
+
"POST /v1/test_helpers/treasury/received_debits",
|
|
344
|
+
"GET /v1/topups",
|
|
345
|
+
"POST /v1/topups",
|
|
346
|
+
"GET /v1/topups/{topup}",
|
|
347
|
+
"POST /v1/topups/{topup}",
|
|
348
|
+
"POST /v1/topups/{topup}/cancel",
|
|
349
|
+
"GET /v1/transfers",
|
|
350
|
+
"POST /v1/transfers",
|
|
351
|
+
"GET /v1/transfers/{id}/reversals",
|
|
352
|
+
"POST /v1/transfers/{id}/reversals",
|
|
353
|
+
"GET /v1/transfers/{transfer}",
|
|
354
|
+
"POST /v1/transfers/{transfer}",
|
|
355
|
+
"GET /v1/transfers/{transfer}/reversals/{id}",
|
|
356
|
+
"POST /v1/transfers/{transfer}/reversals/{id}",
|
|
357
|
+
"GET /v1/treasury/financial_accounts",
|
|
358
|
+
"POST /v1/treasury/financial_accounts",
|
|
359
|
+
"GET /v1/treasury/financial_accounts/{financial_account}",
|
|
360
|
+
"POST /v1/treasury/financial_accounts/{financial_account}",
|
|
361
|
+
"POST /v1/treasury/financial_accounts/{financial_account}/close",
|
|
362
|
+
"GET /v1/treasury/inbound_transfers",
|
|
363
|
+
"POST /v1/treasury/inbound_transfers",
|
|
364
|
+
"GET /v1/treasury/inbound_transfers/{id}",
|
|
365
|
+
"POST /v1/treasury/inbound_transfers/{inbound_transfer}/cancel",
|
|
366
|
+
"GET /v1/treasury/outbound_payments",
|
|
367
|
+
"POST /v1/treasury/outbound_payments",
|
|
368
|
+
"GET /v1/treasury/outbound_payments/{id}",
|
|
369
|
+
"POST /v1/treasury/outbound_payments/{id}/cancel",
|
|
370
|
+
"GET /v1/treasury/outbound_transfers",
|
|
371
|
+
"POST /v1/treasury/outbound_transfers",
|
|
372
|
+
"GET /v1/treasury/outbound_transfers/{outbound_transfer}",
|
|
373
|
+
"POST /v1/treasury/outbound_transfers/{outbound_transfer}/cancel",
|
|
374
|
+
"GET /v1/treasury/received_credits",
|
|
375
|
+
"GET /v1/treasury/received_credits/{id}",
|
|
376
|
+
"GET /v1/treasury/received_debits",
|
|
377
|
+
"GET /v1/treasury/received_debits/{id}",
|
|
378
|
+
"GET /v1/treasury/transaction_entries",
|
|
379
|
+
"GET /v1/treasury/transaction_entries/{id}",
|
|
380
|
+
"GET /v1/treasury/transactions",
|
|
381
|
+
"GET /v1/treasury/transactions/{id}",
|
|
382
|
+
].map((key) => [key, vendorErrors(safe(MONEY))])),
|
|
383
|
+
...Object.fromEntries([
|
|
384
|
+
"GET /v1/charges",
|
|
385
|
+
"POST /v1/charges",
|
|
386
|
+
"GET /v1/charges/search",
|
|
387
|
+
"GET /v1/charges/{charge}",
|
|
388
|
+
"POST /v1/charges/{charge}",
|
|
389
|
+
"POST /v1/charges/{charge}/capture",
|
|
390
|
+
"GET /v1/charges/{charge}/dispute",
|
|
391
|
+
"POST /v1/charges/{charge}/dispute",
|
|
392
|
+
"POST /v1/charges/{charge}/dispute/close",
|
|
393
|
+
"POST /v1/charges/{charge}/refund",
|
|
394
|
+
"GET /v1/confirmation_tokens/{confirmation_token}",
|
|
395
|
+
"GET /v1/disputes",
|
|
396
|
+
"GET /v1/disputes/{dispute}",
|
|
397
|
+
"POST /v1/disputes/{dispute}",
|
|
398
|
+
"POST /v1/disputes/{dispute}/close",
|
|
399
|
+
"POST /v1/external_accounts/{id}",
|
|
400
|
+
"GET /v1/payment_attempt_records",
|
|
401
|
+
"GET /v1/payment_attempt_records/{id}",
|
|
402
|
+
"GET /v1/payment_methods",
|
|
403
|
+
"POST /v1/payment_methods",
|
|
404
|
+
"GET /v1/payment_methods/{payment_method}",
|
|
405
|
+
"POST /v1/payment_methods/{payment_method}",
|
|
406
|
+
"POST /v1/payment_methods/{payment_method}/attach",
|
|
407
|
+
"POST /v1/payment_methods/{payment_method}/detach",
|
|
408
|
+
"GET /v1/payment_records",
|
|
409
|
+
"POST /v1/payment_records/report_payment",
|
|
410
|
+
"GET /v1/payment_records/{id}",
|
|
411
|
+
"POST /v1/payment_records/{id}/report_payment_attempt",
|
|
412
|
+
"POST /v1/payment_records/{id}/report_payment_attempt_canceled",
|
|
413
|
+
"POST /v1/payment_records/{id}/report_payment_attempt_failed",
|
|
414
|
+
"POST /v1/payment_records/{id}/report_payment_attempt_guaranteed",
|
|
415
|
+
"POST /v1/payment_records/{id}/report_payment_attempt_informational",
|
|
416
|
+
"POST /v1/payment_records/{id}/report_refund",
|
|
417
|
+
"GET /v1/setup_attempts",
|
|
418
|
+
"GET /v1/sources/{source}/mandate_notifications/{mandate_notification}",
|
|
419
|
+
"POST /v1/test_helpers/confirmation_tokens",
|
|
420
|
+
"GET /v1/three_d_secure/authentications",
|
|
421
|
+
"POST /v1/three_d_secure/authentications",
|
|
422
|
+
"GET /v1/three_d_secure/authentications/{authentication}",
|
|
423
|
+
"POST /v1/three_d_secure/authentications/{authentication}/cancel",
|
|
424
|
+
"POST /v1/three_d_secure/authentications/{authentication}/submit",
|
|
425
|
+
"POST /v1/tokens",
|
|
426
|
+
"GET /v1/tokens/{token}",
|
|
427
|
+
].map((key) => [key, vendorErrors(safe(PAYMENTS))])),
|
|
428
|
+
...Object.fromEntries([
|
|
429
|
+
"POST /v1/payment_intents",
|
|
430
|
+
"GET /v1/payment_intents/{intent}",
|
|
431
|
+
"POST /v1/payment_intents/{intent}",
|
|
432
|
+
"POST /v1/payment_intents/{intent}/apply_customer_balance",
|
|
433
|
+
"POST /v1/payment_intents/{intent}/cancel",
|
|
434
|
+
"POST /v1/payment_intents/{intent}/capture",
|
|
435
|
+
"POST /v1/payment_intents/{intent}/confirm",
|
|
436
|
+
"POST /v1/payment_intents/{intent}/increment_authorization",
|
|
437
|
+
"POST /v1/payment_intents/{intent}/verify_microdeposits",
|
|
438
|
+
"POST /v1/setup_intents",
|
|
439
|
+
"GET /v1/setup_intents/{intent}",
|
|
440
|
+
"POST /v1/setup_intents/{intent}",
|
|
441
|
+
"POST /v1/setup_intents/{intent}/cancel",
|
|
442
|
+
"POST /v1/setup_intents/{intent}/confirm",
|
|
443
|
+
"POST /v1/setup_intents/{intent}/verify_microdeposits",
|
|
444
|
+
"POST /v1/sources",
|
|
445
|
+
"GET /v1/sources/{source}",
|
|
446
|
+
"POST /v1/sources/{source}",
|
|
447
|
+
"POST /v1/sources/{source}/verify",
|
|
448
|
+
].map((key) => [key, vendorErrors(redact(PAYMENTS_SECRET, ["client_secret"]))])),
|
|
449
|
+
...Object.fromEntries(["GET /v1/payment_intents", "GET /v1/payment_intents/search", "GET /v1/setup_intents"].map((key) => [
|
|
450
|
+
key,
|
|
451
|
+
vendorErrors(redact(PAYMENTS_SECRET, ["data.client_secret"])),
|
|
452
|
+
])),
|
|
453
|
+
"GET /v2/commerce/product_catalog/imports": redact(PRESIGNED, [
|
|
454
|
+
"origin:data.status_details.awaiting_upload.upload_url.url",
|
|
455
|
+
"origin:data.status_details.succeeded_with_errors.error_file.download_url.url",
|
|
456
|
+
]),
|
|
457
|
+
...Object.fromEntries(["POST /v2/commerce/product_catalog/imports", "GET /v2/commerce/product_catalog/imports/{id}"].map((key) => [
|
|
458
|
+
key,
|
|
459
|
+
redact(PRESIGNED, [
|
|
460
|
+
"origin:status_details.awaiting_upload.upload_url.url",
|
|
461
|
+
"origin:status_details.succeeded_with_errors.error_file.download_url.url",
|
|
462
|
+
]),
|
|
463
|
+
])),
|
|
464
|
+
"POST /v1/sigma/saved_queries/{id}": vendorErrors(safe(QUERY)),
|
|
465
|
+
"GET /v1/sigma/scheduled_query_runs": vendorErrors(safe(REPORT_FILE, ["data.file.url"])),
|
|
466
|
+
"GET /v1/reporting/report_runs": vendorErrors(safe(REPORT_FILE, ["data.result.url"])),
|
|
467
|
+
"GET /v1/sigma/scheduled_query_runs/{scheduled_query_run}": vendorErrors(safe(REPORT_FILE, ["file.url"])),
|
|
468
|
+
...Object.fromEntries(["POST /v1/reporting/report_runs", "GET /v1/reporting/report_runs/{report_run}"].map((key) => [
|
|
469
|
+
key,
|
|
470
|
+
vendorErrors(safe(REPORT_FILE, ["result.url"])),
|
|
471
|
+
])),
|
|
472
|
+
...Object.fromEntries([
|
|
473
|
+
"POST /v1/terminal/readers",
|
|
474
|
+
"GET /v1/terminal/readers/{reader}",
|
|
475
|
+
"POST /v1/terminal/readers/{reader}",
|
|
476
|
+
"POST /v1/terminal/readers/{reader}/cancel_action",
|
|
477
|
+
"POST /v1/terminal/readers/{reader}/collect_inputs",
|
|
478
|
+
"POST /v1/terminal/readers/{reader}/collect_payment_method",
|
|
479
|
+
"POST /v1/terminal/readers/{reader}/confirm_payment_intent",
|
|
480
|
+
"POST /v1/terminal/readers/{reader}/process_payment_intent",
|
|
481
|
+
"POST /v1/terminal/readers/{reader}/process_setup_intent",
|
|
482
|
+
"POST /v1/terminal/readers/{reader}/refund_payment",
|
|
483
|
+
"POST /v1/terminal/readers/{reader}/set_reader_display",
|
|
484
|
+
"POST /v1/test_helpers/terminal/readers/{reader}/present_payment_method",
|
|
485
|
+
"POST /v1/test_helpers/terminal/readers/{reader}/succeed_input_collection",
|
|
486
|
+
"POST /v1/test_helpers/terminal/readers/{reader}/timeout_input_collection",
|
|
487
|
+
].map((key) => [key, vendorErrors(safe(TERMINAL, ["action.collect_inputs.inputs.signature"]))])),
|
|
488
|
+
"GET /v1/terminal/readers": vendorErrors(safe(TERMINAL, ["data.action.collect_inputs.inputs.signature"])),
|
|
489
|
+
"GET /v1/terminal/configurations": redact(TERMINAL_CONFIG, [
|
|
490
|
+
"data.wifi.enterprise_eap_peap.password",
|
|
491
|
+
"data.wifi.personal_psk.password",
|
|
492
|
+
"data.wifi.enterprise_eap_tls.private_key_file_password",
|
|
493
|
+
], ["data.wifi.enterprise_eap_tls.private_key_file", "data.wifi.personal_psk"]),
|
|
494
|
+
...Object.fromEntries([
|
|
495
|
+
"POST /v1/terminal/configurations",
|
|
496
|
+
"GET /v1/terminal/configurations/{configuration}",
|
|
497
|
+
"POST /v1/terminal/configurations/{configuration}",
|
|
498
|
+
].map((key) => [
|
|
499
|
+
key,
|
|
500
|
+
redact(TERMINAL_CONFIG, [
|
|
501
|
+
"wifi.enterprise_eap_peap.password",
|
|
502
|
+
"wifi.personal_psk.password",
|
|
503
|
+
"wifi.enterprise_eap_tls.private_key_file_password",
|
|
504
|
+
], ["wifi.enterprise_eap_tls.private_key_file", "wifi.personal_psk"]),
|
|
505
|
+
])),
|
|
506
|
+
...Object.fromEntries([
|
|
507
|
+
"GET /v1/financial_connections/transactions",
|
|
508
|
+
"GET /v1/financial_connections/transactions/{transaction}",
|
|
509
|
+
"GET /v1/identity/verification_reports",
|
|
510
|
+
"GET /v1/identity/verification_reports/{report}",
|
|
511
|
+
].map((key) => [key, vendorErrors(safe(VERIFICATION))])),
|
|
512
|
+
"GET /v1/webhook_endpoints": redact(WEBHOOK, ["data.secret", "origin:url", "origin:data.url"]),
|
|
513
|
+
...Object.fromEntries([
|
|
514
|
+
"POST /v1/webhook_endpoints",
|
|
515
|
+
"GET /v1/webhook_endpoints/{webhook_endpoint}",
|
|
516
|
+
"POST /v1/webhook_endpoints/{webhook_endpoint}",
|
|
517
|
+
].map((key) => [key, redact(WEBHOOK, ["secret", "origin:url"])])),
|
|
518
|
+
};
|
|
519
|
+
const CLIENT_SECRET = "A publishable-side secret: with the account's publishable key it confirms, completes, or reads its object from a browser. The agent works server-side and never needs one.";
|
|
520
|
+
const METADATA = "Payment, Issuing, or account metadata the detector flags by vocabulary; no credential.";
|
|
521
|
+
/** Field names reviewed once for Stripe's shared object graph. */
|
|
522
|
+
const FIELDS = {
|
|
523
|
+
client_secret: { verdict: "redact", reason: CLIENT_SECRET },
|
|
524
|
+
confirmation_secret: { verdict: "redact", reason: "Carries the invoice PaymentIntent's client secret." },
|
|
525
|
+
client_token: { verdict: "redact", reason: "A payment method's client-side session token (Klarna)." },
|
|
526
|
+
secret: {
|
|
527
|
+
verdict: "redact",
|
|
528
|
+
reason: "Ephemeral key, Terminal connection token, and webhook endpoint secrets: each authenticates to Stripe or signs its events.",
|
|
529
|
+
},
|
|
530
|
+
signing_secret: { verdict: "redact", reason: "An event destination's webhook signing secret." },
|
|
531
|
+
auth_code: { verdict: "redact", reason: "An OAuth authorization code exchangeable for tokens." },
|
|
532
|
+
authentication_token: { verdict: "redact", reason: "A meter event stream authentication token." },
|
|
533
|
+
password: { verdict: "redact", reason: "A Terminal Wi-Fi password." },
|
|
534
|
+
private_key_file_password: { verdict: "redact", reason: "A Terminal Wi-Fi private key password." },
|
|
535
|
+
cvc: { verdict: "redact", reason: "An Issuing card's CVC." },
|
|
536
|
+
...Object.fromEntries([
|
|
537
|
+
["request_incremental_authorization_support", "A payment-method option flag."],
|
|
538
|
+
["request_incremental_authorization", "A payment-method option."],
|
|
539
|
+
["request_extended_authorization", "A payment-method option."],
|
|
540
|
+
["incremental_authorization_supported", "Whether a payment supports incremental authorization; a flag."],
|
|
541
|
+
["incremental_authorization", "Incremental authorization status."],
|
|
542
|
+
["extended_authorization", "Extended authorization status."],
|
|
543
|
+
["tokenization_method", "How a card number was tokenized (apple_pay, google_pay)."],
|
|
544
|
+
["authorization_code", "The issuer's approval code on a charge or Issuing authorization; it grants nothing."],
|
|
545
|
+
["authorization_response_code", "An EMV issuer response code."],
|
|
546
|
+
["authorization_method", "How Issuing card details were provided."],
|
|
547
|
+
["issuing_authorization", "An Issuing authorization id."],
|
|
548
|
+
["no_valid_authorization", "Issuing dispute evidence."],
|
|
549
|
+
["network_token", "Whether a network token was used; metadata, not the token."],
|
|
550
|
+
["token_currency", "A crypto payment's token currency."],
|
|
551
|
+
["token_risk_score", "A network token risk score."],
|
|
552
|
+
["used", "Whether a token was used; a flag."],
|
|
553
|
+
["cvc_token", "A CVC recollection token id, usable only with the account's secret key."],
|
|
554
|
+
["bank_account_token", "A bank account token object, usable only with the account's secret key."],
|
|
555
|
+
["evidence_customer_signature", "Card-present signature evidence metadata."],
|
|
556
|
+
["customer_signature", "A dispute evidence File id."],
|
|
557
|
+
["require_signature", "Whether card delivery requires a signature; a flag."],
|
|
558
|
+
["company_authorization", "Document File ids."],
|
|
559
|
+
["front_back", "Verification document File ids."],
|
|
560
|
+
["front", "A verification document File id."],
|
|
561
|
+
["back", "A verification document File id."],
|
|
562
|
+
["inquiry", "A requirement's inquiry reference id."],
|
|
563
|
+
["resource", "A requirement's resource reference id."],
|
|
564
|
+
["person", "A Person id."],
|
|
565
|
+
["verification_flow", "A verification flow id."],
|
|
566
|
+
["require_verification", "Whether one-time-password verification is required; a flag."],
|
|
567
|
+
["setup_intent", "An embedded SetupIntent; its client secret is redacted by name."],
|
|
568
|
+
["preferred_locales", "A cardholder's languages."],
|
|
569
|
+
["hosted_payment_method_save", "An invoice setting."],
|
|
570
|
+
["password_provided", "Whether a website password was provided; a flag."],
|
|
571
|
+
[
|
|
572
|
+
"financial_addresses",
|
|
573
|
+
"Treasury receiving details (routing and account numbers for credits), not credentials.",
|
|
574
|
+
],
|
|
575
|
+
["flow", "A Treasury flow id."],
|
|
576
|
+
["transaction_refresh", "A Financial Connections refresh id."],
|
|
577
|
+
["client_ip", "The IP address that created a token."],
|
|
578
|
+
["accept_header", "A browser's Accept header recorded for 3D Secure."],
|
|
579
|
+
["header", "A quote PDF header text."],
|
|
580
|
+
["private_key_file", "A File id for a Terminal Wi-Fi key."],
|
|
581
|
+
["redirect_to_url", "A payer-facing authentication redirect; credential query parameters are sanitized."],
|
|
582
|
+
["alipay_handle_redirect", "A payer-facing Alipay redirect; credential query parameters are sanitized."],
|
|
583
|
+
["redirect", "A Source's payer-facing redirect; credential query parameters are sanitized."],
|
|
584
|
+
["deleted", "Whether an object was deleted; a flag."],
|
|
585
|
+
["location", "A Terminal location id."],
|
|
586
|
+
["device_fingerprint", "A hashed device id."],
|
|
587
|
+
["wallet_provider", "A digital wallet name."],
|
|
588
|
+
["network", "A card network name."],
|
|
589
|
+
["last4", "The last four digits."],
|
|
590
|
+
["card", "An Issuing card or token's card id or object; full numbers come back only as refused expansions."],
|
|
591
|
+
["id", "An identifier."],
|
|
592
|
+
["name", "A name."],
|
|
593
|
+
["type", "A type."],
|
|
594
|
+
["status", "A status."],
|
|
595
|
+
["created", "A timestamp."],
|
|
596
|
+
].map(([name, reason]) => [name, { verdict: "keep", reason: reason || METADATA }])),
|
|
597
|
+
};
|
|
598
|
+
/**
|
|
599
|
+
* When a Checkout Session's hosted page is only a payment page. Deny by
|
|
600
|
+
* default: the URL comes back whole only when every field of the pinned
|
|
601
|
+
* checkout.session schema that can bind the session to an identity or its
|
|
602
|
+
* saved payment methods is empty, and the session only takes a payment. A
|
|
603
|
+
* bound page (an existing Customer or Account, a Customer it will create, or
|
|
604
|
+
* saved-payment-method options) can display, reuse, or remove that
|
|
605
|
+
* identity's saved payment methods, so it is a capability on the customer.
|
|
606
|
+
* `providers:spec` derives the binding fields from the schema (identity-named
|
|
607
|
+
* fields and fields referencing a Customer or Account) and the harness fails
|
|
608
|
+
* until a new one is listed here.
|
|
609
|
+
*/
|
|
610
|
+
const GUEST_CHECKOUT = {
|
|
611
|
+
bindings: {
|
|
612
|
+
customer: [],
|
|
613
|
+
customer_account: [],
|
|
614
|
+
// The one value treated as unbound: `if_required` creates a Customer only when the session needs one, and a
|
|
615
|
+
// guest payment session (no customer, account, or saved-method options) does not. `always`, or any other
|
|
616
|
+
// value, withholds the page.
|
|
617
|
+
customer_creation: ["if_required"],
|
|
618
|
+
saved_payment_method_options: [],
|
|
619
|
+
},
|
|
620
|
+
unbound: {
|
|
621
|
+
customer_email: "Prefills the email a guest types; it names no Customer and grants nothing on the page beyond the payment.",
|
|
622
|
+
customer_details: "What the payer entered (name, email, address, tax ids), collected during or after the payment; it binds nothing.",
|
|
623
|
+
},
|
|
624
|
+
// Setup and subscription sessions save a payment method to a Customer.
|
|
625
|
+
requires: { mode: ["payment"] },
|
|
626
|
+
};
|
|
627
|
+
const SENSITIVE_HEADERS = ["request_details.headers.value", "response_details.headers.value"];
|
|
628
|
+
const WIFI_PASSWORDS = [
|
|
629
|
+
"wifi.enterprise_eap_peap.password",
|
|
630
|
+
"wifi.personal_psk.password",
|
|
631
|
+
"wifi.enterprise_eap_tls.private_key_file_password",
|
|
632
|
+
];
|
|
633
|
+
/**
|
|
634
|
+
* Rules for Stripe objects wherever a response embeds them, keyed on the
|
|
635
|
+
* `object` discriminator: expansions, lists, search results, and events'
|
|
636
|
+
* `data.object` and `previous_attributes`. Operation verdicts review what an
|
|
637
|
+
* operation returns by its own shape; these are the backstop for expansions.
|
|
638
|
+
*/
|
|
639
|
+
const RESOURCES = {
|
|
640
|
+
key: "object",
|
|
641
|
+
partials: ["previous_attributes"],
|
|
642
|
+
rules: {
|
|
643
|
+
file_link: { reason: "A file link's URL downloads the file without authentication.", paths: ["origin:url"] },
|
|
644
|
+
file: { reason: "A File embeds its public file links.", paths: ["origin:links.data.url"] },
|
|
645
|
+
ephemeral_key: { reason: "An ephemeral key's secret is an API credential.", paths: ["secret"] },
|
|
646
|
+
"terminal.connection_token": { reason: "A connection token's secret connects a reader.", paths: ["secret"] },
|
|
647
|
+
"terminal.onboarding_link": {
|
|
648
|
+
reason: "Accepts Tap to Pay terms on the merchant's behalf.",
|
|
649
|
+
paths: ["redirect_url"],
|
|
650
|
+
},
|
|
651
|
+
account_link: { reason: "Signs its holder into a connected account's onboarding.", paths: ["url"] },
|
|
652
|
+
"v2.core.account_link": { reason: "Signs its holder into a connected account's onboarding.", paths: ["url"] },
|
|
653
|
+
login_link: { reason: "Signs its holder into a connected account's Express Dashboard.", paths: ["url"] },
|
|
654
|
+
account_session: { reason: "Grants embedded-component access to a connected account.", paths: ["client_secret"] },
|
|
655
|
+
customer_session: {
|
|
656
|
+
reason: "Grants client-side access to a customer's payment methods.",
|
|
657
|
+
paths: ["client_secret"],
|
|
658
|
+
},
|
|
659
|
+
"billing_portal.session": { reason: "Signs its holder in as the customer.", paths: ["url"] },
|
|
660
|
+
"financial_connections.session": { reason: CLIENT_SECRET, paths: ["client_secret"] },
|
|
661
|
+
webhook_endpoint: {
|
|
662
|
+
reason: "A signing secret, and a destination whose path or query can be a bearer secret.",
|
|
663
|
+
paths: ["secret", "origin:url"],
|
|
664
|
+
},
|
|
665
|
+
"v2.core.event_destination": {
|
|
666
|
+
reason: "A signing secret, and a destination whose path or query can be a bearer secret.",
|
|
667
|
+
paths: ["webhook_endpoint.signing_secret", "origin:webhook_endpoint.url"],
|
|
668
|
+
},
|
|
669
|
+
"issuing.card": { reason: "A full card number and CVC.", paths: ["number", "cvc"] },
|
|
670
|
+
"apps.secret": { reason: "A stored secret value.", paths: ["payload"] },
|
|
671
|
+
"apps.install": { reason: "An OAuth authorization code.", paths: ["auth_code"] },
|
|
672
|
+
payment_intent: { reason: CLIENT_SECRET, paths: ["client_secret"] },
|
|
673
|
+
setup_intent: { reason: CLIENT_SECRET, paths: ["client_secret"] },
|
|
674
|
+
source: { reason: CLIENT_SECRET, paths: ["client_secret"] },
|
|
675
|
+
invoice: { reason: "Carries the invoice PaymentIntent's client secret.", paths: ["confirmation_secret"] },
|
|
676
|
+
"checkout.session": {
|
|
677
|
+
reason: "A client secret; and a hosted page that, bound to a Customer or Account, can display, reuse, or remove saved payment methods. Only a provably guest payment session's page comes back verbatim.",
|
|
678
|
+
paths: ["client_secret"],
|
|
679
|
+
verbatim: ["url"],
|
|
680
|
+
guest: GUEST_CHECKOUT,
|
|
681
|
+
withheld: ["origin:url"],
|
|
682
|
+
},
|
|
683
|
+
"identity.verification_session": {
|
|
684
|
+
reason: "A client secret; the hosted page collects documents from the person being verified and shows no stored data, so it comes back verbatim.",
|
|
685
|
+
paths: ["client_secret"],
|
|
686
|
+
verbatim: ["url"],
|
|
687
|
+
},
|
|
688
|
+
"terminal.configuration": { reason: "Wi-Fi passwords.", paths: WIFI_PASSWORDS },
|
|
689
|
+
"forwarding.request": { reason: "Header values sent to and returned by a third party.", paths: SENSITIVE_HEADERS },
|
|
690
|
+
"v2.commerce.product_catalog_import": {
|
|
691
|
+
reason: "Pre-signed upload and error-file URLs.",
|
|
692
|
+
paths: [
|
|
693
|
+
"origin:status_details.awaiting_upload.upload_url.url",
|
|
694
|
+
"origin:status_details.succeeded_with_errors.error_file.download_url.url",
|
|
695
|
+
],
|
|
696
|
+
},
|
|
697
|
+
"v2.billing.meter_event_session": { reason: "A meter event stream token.", paths: ["authentication_token"] },
|
|
698
|
+
},
|
|
699
|
+
};
|
|
700
|
+
export const STRIPE_VALUE_SAFETY = {
|
|
701
|
+
title: "Stripe",
|
|
702
|
+
operations: OPERATIONS,
|
|
703
|
+
fields: FIELDS,
|
|
704
|
+
resources: RESOURCES,
|
|
705
|
+
};
|