@produtype/core 0.57.0 → 0.59.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.
@@ -204,9 +204,20 @@ async function detectAuth(ctx) {
204
204
  const roleSignals = [...unambiguousRoles, ...comparedRoles].slice(0, 20);
205
205
  const permissionSignals = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, [/requirePermission/i, /permission_classes/i, /permissions\.py/i, /authorize\(/i, /\bcan\(/i], 20);
206
206
  const resourceLevelSignals = await (0, textSearch_1.searchInFiles)(ctx.root, sourceFiles, [
207
- /requirePermission/i,
208
- /permission_classes/i,
209
- /authorize\(/i,
207
+ /**
208
+ * Per-record, which is what this capability claims.
209
+ *
210
+ * `requirePermission` and `permission_classes` were in this list, and they are
211
+ * checks on a route: the capability's own description is "per-record checks that
212
+ * a caller may act on the specific resource, **not just the route**". Three
213
+ * projects were credited with protection against reading another user's rows —
214
+ * one of them on the strength of `permission_classes = [AllowAny]`, a line that
215
+ * says the opposite. They belong to `authz.permissions`, where they already are.
216
+ *
217
+ * `authorize(` keeps its place but needs an argument. `google_calendar.authorize()`
218
+ * is an OAuth handshake, and it was standing in for an ownership check.
219
+ */
220
+ /\bauthorize\(\s*[^)\s]/i,
210
221
  /\bcanAccess\(/i,
211
222
  /\bhasAccessTo\(/i,
212
223
  /ownerId/i,
@@ -375,7 +386,9 @@ async function detectAuth(ctx) {
375
386
  },
376
387
  {
377
388
  key: 'authz.resourceLevel',
378
- present: resourceLevelSignals.length > 0 || permissionSignals.length > 0,
389
+ // Route-level permission checks no longer stand in for per-record ones: with the
390
+ // needles above narrowed, this clause could only reintroduce what they removed.
391
+ present: resourceLevelSignals.length > 0,
379
392
  evidence: (0, absenceEvidence_1.evidenceOrSearch)(snippetEvidence(resourceLevelSignals), 'a check that the row belongs to the caller', ['requirePermission', 'permission_classes', 'authorize(', 'canAccess(', 'hasAccessTo(', 'ownerId', 'createdBy', 'req.user.id', 'userId ===']),
380
393
  },
381
394
  {
@@ -41,10 +41,26 @@ function deriveStatus(analysis, capability) {
41
41
  return detector(analysis, 'auth.emailVerification')?.present ? 'present' : 'missing';
42
42
  }
43
43
  case 'authz.roles': {
44
- if (authzPerm?.present)
44
+ /**
45
+ * Roles or permissions, which is what the capability asks for.
46
+ *
47
+ * It read "permissions present, or roles present and the answer is partial", so
48
+ * a product with `requireRole(actor, ["owner", "admin"])` checked on every
49
+ * privileged route was told its role model was half-built — for want of a
50
+ * separate permission table it never claimed to need. The capability's own
51
+ * description is "distinct roles so that not every authenticated user can do
52
+ * everything", and its recommendation says "model roles *or* permissions".
53
+ *
54
+ * It cost this product's own web application the top band: one blocking
55
+ * required capability, and this was it.
56
+ *
57
+ * The roles detector already means roles that are *checked* rather than roles
58
+ * that are named — `role ===` in a chat transcript has been excluded since the
59
+ * guard-versus-label distinction was added — so there is nothing left for a
60
+ * partial to mean here.
61
+ */
62
+ if (authzPerm?.present || authzRoles?.present)
45
63
  return 'present';
46
- if (authzRoles?.present)
47
- return 'partial';
48
64
  return 'missing';
49
65
  }
50
66
  case 'authz.ownership': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@produtype/core",
3
- "version": "0.57.0",
3
+ "version": "0.59.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": {