diff --git a/app/static/css/style.css b/app/static/css/style.css
index 4ea8a6f..ef4996f 100644
--- a/app/static/css/style.css
+++ b/app/static/css/style.css
@@ -207,6 +207,37 @@ input[type=password] {
padding: 0 0.4rem;
}
+.perm-matrix {
+ border-collapse: collapse;
+ font-size: 0.85rem;
+}
+
+.perm-matrix th,
+.perm-matrix td {
+ padding: 0.2rem 0.5rem;
+ border: 1px solid var(--border);
+ text-align: center;
+}
+
+.perm-matrix th {
+ background: var(--surface-2);
+ font-size: 0.75rem;
+ text-transform: uppercase;
+ letter-spacing: 0.04em;
+ color: var(--muted);
+}
+
+.perm-matrix .perm-scope {
+ text-align: left;
+ font-weight: 500;
+ white-space: nowrap;
+ padding-right: 1rem;
+}
+
+.perm-matrix .perm-na {
+ color: var(--muted);
+}
+
.inline-edit {
display: flex;
flex-wrap: wrap;
diff --git a/app/templates/admin/_role_row.html b/app/templates/admin/_role_row.html
index 2cb0256..7d0f37a 100644
--- a/app/templates/admin/_role_row.html
+++ b/app/templates/admin/_role_row.html
@@ -2,7 +2,32 @@
{{ r.id }} |
{{ r.name }} |
{{ r.description or "" }} |
- {% for perm in r.permissions %}{{ perm.name }}{% endfor %} |
+
+ {% set role_perm_names = r.permissions | map(attribute='name') | list %}
+
+
+
+ |
+ {% for action in actions %}{{ action }} | {% endfor %}
+
+
+
+ {% for scope in scopes %}
+
+ | {{ scope }} |
+ {% for action in actions %}
+ {% set key = scope ~ ':' ~ action %}
+ {% if key in perm_map %}
+ {{ '✓' if key in role_perm_names else '' }} |
+ {% else %}
+ — |
+ {% endif %}
+ {% endfor %}
+
+ {% endfor %}
+
+
+ |
|