ruby_ability_graph 0.1.1 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69091644aaeaacfb2c587e3e11ed70e0b27b575b1678f762f73fc39bec024406
4
- data.tar.gz: ef060d9a0dea3f181596c4dd459c8fc847749ea1e06c30fe02cb6824d06b94bb
3
+ metadata.gz: 9bd1d62067dae4acb3905ddcd4fc1b47833a4135dd6131cc91911098a28d46cb
4
+ data.tar.gz: 1d1d37df3d8ee78d1a08f850619ef08d7fc798eebac8680d40525c17f07dc432
5
5
  SHA512:
6
- metadata.gz: fcd1d55fc2808d10063b16d67942a62458d2b183027214573d9dd3d8ec348a8cdbc9eb5da60a83b9c63ffa174f451130de17b1a872224c82c9a2058e0b0f3737
7
- data.tar.gz: 44a8503733fad18260454e043be5d0053490e0a0aeca2b22ebaaef4671f064e8fce0d8a9d772eac5480c201662f4aaf669aebef1753112532522543458b8dbae
6
+ metadata.gz: 44c8aa407082a81a668d572969e640395c564743e649aed7919fd8e03040451eb9836bfadda369281a426f7ac152cf48f7971eb3d05552a26683b69e67de7f73
7
+ data.tar.gz: 10260b71a1e46489661c61db10f0c4e7239df8201b74a2cc5b1bf9f2da84c6ad5068bb3c24cf5a37b1a82ab46f659a94f2f6245c4b6b0535928ad07373cd57b4
data/README.md CHANGED
@@ -145,7 +145,7 @@ Note: a policy check is only as trustworthy as the underlying result's `confiden
145
145
  ruby-ability-graph scan APP_PATH --html-report report.html
146
146
  ```
147
147
 
148
- Writes a single, self-contained HTML file -- inlined CSS/JS, no server, no CDN assets, nothing fetched over the network -- showing an interactive role → action → resource graph. Hover a role to trace everything it can reach; hover an edge for the underlying condition and confidence. Edges are solid green where `resolved`, dashed amber where `unsupported`, and solid red where a `--policy-file` check (if given) found a violation. A coverage line at the top mirrors the table's resolved/total summary. Only `allowed: true` results become edges -- it's a "who can access what" diagram, not a dump of every denial.
148
+ Writes a single, self-contained HTML file -- inlined CSS/JS, no server, no CDN assets, nothing fetched over the network -- showing an interactive role → action → resource graph. Hover a role to trace everything it can reach; hover an edge for the underlying condition and confidence. Each edge bundles many underlying rows (a role→action edge spans every model that pair touches), so its color reflects the fraction resolved: solid green at 100%, solid amber-to-green gradient in between, dashed amber at 0% (`unsupported`), and solid red wherever a `--policy-file` check (if given) found a violation. A coverage line at the top mirrors the table's resolved/total summary. Only `allowed: true` results become edges -- it's a "who can access what" diagram, not a dump of every denial.
149
149
 
150
150
  ![Example HTML report graph](docs/images/html-report.png)
151
151
 
@@ -73,6 +73,7 @@ module RubyAbilityGraph
73
73
  #legend span { display: inline-flex; align-items: center; gap: 6px; }
74
74
  .swatch { display: inline-block; width: 22px; height: 0; border-top-width: 3px; border-top-style: solid; }
75
75
  .swatch.resolved { border-color: var(--good); border-top-style: solid; }
76
+ .swatch.partial { height: 3px; border-top: none; background: linear-gradient(to right, var(--warning), var(--good)); }
76
77
  .swatch.unsupported { border-color: var(--warning); border-top-style: dashed; }
77
78
  .swatch.violation { border-color: var(--critical); border-top-style: solid; }
78
79
  main {
@@ -123,6 +124,7 @@ module RubyAbilityGraph
123
124
  </div>
124
125
  <div id="legend">
125
126
  <span><span class="swatch resolved"></span> Resolved</span>
127
+ <span><span class="swatch partial"></span> Bundled edge, partially resolved -- color shows % resolved</span>
126
128
  <span><span class="swatch unsupported"></span> Unsupported -- not analyzed</span>
127
129
  <span><span class="swatch violation"></span> Policy violation</span>
128
130
  </div>
@@ -165,9 +167,30 @@ module RubyAbilityGraph
165
167
  return map;
166
168
  }
167
169
 
168
- function edgeStatus(rows) {
169
- if (rows.some(function (r) { return r.violation; })) { return "violation"; }
170
- return rows.every(function (r) { return r.confidence === "resolved"; }) ? "resolved" : "unsupported";
170
+ // Aggregated edges bundle many rows (e.g. a role->action edge spans every
171
+ // model that pair touches). A single boolean verdict for the whole bundle
172
+ // is misleading at scale: one unsupported row among sixty resolved ones
173
+ // painted the entire edge amber. Color proportionally instead, so an
174
+ // edge that's mostly resolved reads as mostly green.
175
+ var COLOR_WARNING = [250, 178, 25]; // --warning, #fab219
176
+ var COLOR_GOOD = [12, 163, 12]; // --good, #0ca30c
177
+
178
+ function resolvedFraction(rows) {
179
+ var resolved = rows.filter(function (r) { return r.confidence === "resolved"; }).length;
180
+ return resolved / rows.length;
181
+ }
182
+
183
+ function mixColor(fraction) {
184
+ var rgb = COLOR_WARNING.map(function (c, i) { return Math.round(c + (COLOR_GOOD[i] - c) * fraction); });
185
+ return "rgb(" + rgb.join(",") + ")";
186
+ }
187
+
188
+ function edgeAppearance(rows) {
189
+ if (rows.some(function (r) { return r.violation; })) { return { cls: "violation" }; }
190
+ var fraction = resolvedFraction(rows);
191
+ if (fraction === 1) { return { cls: "resolved" }; }
192
+ if (fraction === 0) { return { cls: "unsupported" }; }
193
+ return { cls: "partial", style: "stroke:" + mixColor(fraction) + ";" };
171
194
  }
172
195
 
173
196
  function groupBy(rows, keyFn, shapeFn) {
@@ -240,10 +263,13 @@ module RubyAbilityGraph
240
263
 
241
264
  function drawEdge(x1, y1, x2, y2, statusRows, store, key) {
242
265
  var midX = (x1 + x2) / 2;
243
- var path = svgEl("path", {
244
- "class": "edge " + edgeStatus(statusRows),
266
+ var appearance = edgeAppearance(statusRows);
267
+ var attrs = {
268
+ "class": "edge " + appearance.cls,
245
269
  d: "M " + x1 + "," + y1 + " C " + midX + "," + y1 + " " + midX + "," + y2 + " " + x2 + "," + y2
246
- });
270
+ };
271
+ if (appearance.style) { attrs.style = appearance.style; }
272
+ var path = svgEl("path", attrs);
247
273
  svg.appendChild(path);
248
274
  store[key] = path;
249
275
  return path;
@@ -353,14 +379,22 @@ module RubyAbilityGraph
353
379
  return bits.join(" ");
354
380
  }
355
381
 
382
+ function edgeHeader(a, b, rows) {
383
+ var resolved = rows.filter(function (r) { return r.confidence === "resolved"; }).length;
384
+ var header = a + " → " + b + " -- " + resolved + "/" + rows.length + " resolved";
385
+ var violationCount = rows.filter(function (r) { return r.violation; }).length;
386
+ if (violationCount) { header += ", " + violationCount + " violation(s)"; }
387
+ return header;
388
+ }
389
+
356
390
  function raTooltip(edge) {
357
- return [edge.role + " → " + edge.action]
391
+ return [edgeHeader(edge.role, edge.action, edge.rows)]
358
392
  .concat(edge.rows.map(function (r) { return rowLine(r.model, r); }))
359
393
  .join("\n");
360
394
  }
361
395
 
362
396
  function amTooltip(edge) {
363
- return [edge.action + " → " + edge.model]
397
+ return [edgeHeader(edge.action, edge.model, edge.rows)]
364
398
  .concat(edge.rows.map(function (r) { return rowLine(r.role, r); }))
365
399
  .join("\n");
366
400
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyAbilityGraph
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_ability_graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jessica Grider
@@ -25,8 +25,8 @@ dependencies:
25
25
  version: '1.0'
26
26
  description: |
27
27
  ruby_ability_graph loads a Rails app's CanCanCan Ability class in isolation,
28
- enumerates roles x actions x models, and reports resolved permissions --
29
- distinguishing patterns it can fully resolve from ones it doesn't support.
28
+ enumerates roles x actions x models, and reports resolved permissions.
29
+ Distinguishes patterns it can fully resolve from ones it doesn't support.
30
30
  executables:
31
31
  - ruby-ability-graph
32
32
  extensions: []