@produtype/core 0.96.0 → 0.98.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.
@@ -39,7 +39,31 @@ async function detectBilling(ctx) {
39
39
  /\/webhooks?\/stripe/i,
40
40
  /\/stripe\/webhooks?/i,
41
41
  ], 30);
42
- const hasStrongStripeSignal = hasStripeDep || stripeContextHits.length > 0;
42
+ /**
43
+ * The processor, declared wherever this project declares its dependencies.
44
+ *
45
+ * `hasDep` reads `package.json` and nothing else, so a product that charges people
46
+ * in any other language had to be caught by the `STRIPE_` variable search instead.
47
+ * pretix is a ticketing platform with `stripe==7.9.*`, `paypalrestsdk` and
48
+ * `paypal-checkout-serversdk` in its pyproject, and it was told at `high` that it
49
+ * has no way to charge for the product.
50
+ *
51
+ * Only processors, not billing vocabulary: the `movie-like-billing-no-stripe`
52
+ * fixture exists to hold that line, and a route called `/api/billing/plans` is
53
+ * still not a payment integration.
54
+ */
55
+ const PROCESSOR_PACKAGES = ['stripe', 'braintree', 'paddle', 'lemonsqueezy', 'mollie', 'razorpay', 'adyen'];
56
+ const processorDeps = [
57
+ ...(0, detectContext_1.hasAnyPyDep)(ctx, [...PROCESSOR_PACKAGES, 'paypalrestsdk', 'paypal-checkout-serversdk', 'mollie-api-python']),
58
+ ...(0, detectContext_1.hasAnyRubyDep)(ctx, [...PROCESSOR_PACKAGES, 'paypal-sdk-rest']),
59
+ ...(0, detectContext_1.hasAnyPhpDep)(ctx, ['stripe/stripe-php', 'paypal/rest-api-sdk-php', 'mollie/mollie-api-php', 'braintree/braintree_php']),
60
+ ...(0, detectContext_1.hasAnyGradleDep)(ctx, ['com.stripe:stripe-java', 'com.braintreepayments']),
61
+ ...(0, detectContext_1.hasAnyDotnetDep)(ctx, ['Stripe.net', 'Braintree', 'PayPalCheckoutSdk']),
62
+ ...(0, detectContext_1.hasAnyRustDep)(ctx, ['stripe-rust', 'async-stripe']),
63
+ ];
64
+ for (const dep of processorDeps)
65
+ evidence.push({ type: 'dependency', value: dep });
66
+ const hasStrongStripeSignal = hasStripeDep || processorDeps.length > 0 || stripeContextHits.length > 0;
43
67
  const webhookRouteHits = hasStrongStripeSignal
44
68
  ? await (0, textSearch_1.searchInFiles)(ctx.root, ctx.files.source, [
45
69
  /\/webhooks?\b/i,
@@ -195,6 +195,21 @@ async function detectSecurity(ctx) {
195
195
  /^\s*SECURE_REFERRER_POLICY\s*=/m,
196
196
  /^\s*SECURE_CROSS_ORIGIN_OPENER_POLICY\s*=/m,
197
197
  /^\s*CSP_DEFAULT_SRC\s*=/m,
198
+ /**
199
+ * Rails writes its header policy as Ruby, not as a header name.
200
+ *
201
+ * `config.content_security_policy do |policy|` in an initializer is the policy
202
+ * itself, and `config.force_ssl = true` is what turns on Strict-Transport-Security
203
+ * for the whole application. lobsters has both and was told at `high` to add
204
+ * security headers.
205
+ *
206
+ * Both are lines somebody chose to write. Rails' *default* headers —
207
+ * `X-Frame-Options: SAMEORIGIN`, nosniff, and the rest of `DefaultHeaders` —
208
+ * are not counted, for the reason Django's `SecurityMiddleware` is not: every
209
+ * application has them, so they distinguish nothing.
210
+ */
211
+ /config\.content_security_policy\b/,
212
+ /^\s*config\.force_ssl\s*=\s*true/m,
198
213
  ], 20);
199
214
  /**
200
215
  * Spring Security, which writes the headers without being asked.
@@ -256,7 +271,15 @@ async function detectSecurity(ctx) {
256
271
  (0, detectContext_1.hasDep)(ctx, 'rate-limiter-flexible') ||
257
272
  (0, detectContext_1.hasDep)(ctx, 'next-rate-limit') ||
258
273
  (0, detectContext_1.hasAnyPyDep)(ctx, ['django-ratelimit', 'slowapi', 'flask-limiter']).length > 0 ||
259
- (0, detectContext_1.hasAnyRustDep)(ctx, ['governor', 'tower_governor', 'tower-governor', 'actix-governor', 'ratelimit']).length > 0;
274
+ (0, detectContext_1.hasAnyRustDep)(ctx, ['governor', 'tower_governor', 'tower-governor', 'actix-governor', 'ratelimit']).length > 0 ||
275
+ /**
276
+ * Ruby's, which is one gem and nearly universal in Rails.
277
+ *
278
+ * lobsters declares `gem "rack-attack" # rate-limiting` and was told at `high`
279
+ * that it does not throttle. The list had grown npm, Python and Rust entries and
280
+ * skipped the ecosystem where the answer is a single well-known name.
281
+ */
282
+ (0, detectContext_1.hasAnyRubyDep)(ctx, ['rack-attack', 'rack_attack']).length > 0;
260
283
  /**
261
284
  * Throttling by what the protocol says, not by what the variable is called.
262
285
  *
@@ -306,6 +329,17 @@ async function detectSecurity(ctx) {
306
329
  * issuing the refusal rather than reading one: a constant is what you construct
307
330
  * a response from, where receiving is a comparison against `.status`.
308
331
  */
332
+ /**
333
+ * Laravel's, which is a middleware alias the framework registers.
334
+ *
335
+ * `Route::middleware(['throttle:oauth2-socialite'])` is monica applying the
336
+ * limiter that ships with the framework, and `RateLimiter::for('login', ...)`
337
+ * is where the limit is defined. Neither is a package to depend on — the
338
+ * limiter is part of Laravel — so a list of packages could never find them, and
339
+ * monica was told at `high` that it does not throttle.
340
+ */
341
+ /['"]throttle:[\w.-]+['"]/,
342
+ /\bRateLimiter::for\s*\(/,
309
343
  /StatusCode::TOO_MANY_REQUESTS/,
310
344
  /http\.StatusTooManyRequests/,
311
345
  /HttpStatus\.TOO_MANY_REQUESTS/,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@produtype/core",
3
- "version": "0.96.0",
3
+ "version": "0.98.0",
4
4
  "description": "Deterministic CLI and library that analyzes a web application repository and reports how far it is from production-ready for the kind of product it is meant to be.",
5
5
  "license": "MIT",
6
6
  "bin": {