Compare commits

..
Author SHA1 Message Date
bruno 6713510ce9 Merge pull request 'fix(ci): tag OpenAPI 'Coffres Secrets' declare + compteur de themes 15 -> 16' (#34) from fix/ci-tests-openapi-themes into main
CI / security (push) Failing after 0s
CI / lint (push) Successful in 2m57s
CI / test (push) Successful in 5m37s
CI / build (push) Successful in 3m15s
CI / e2e (push) In progress
2026-10-28 08:27:31 -04:00
bruno bf5b32de16 Merge pull request 'feat(ui): icone coffre-fort SVG pour le noeud Secrets' (#33) from fix/icone-secrets-coffre-fort into main
CI / security (push) Successful in 1m58s
CI / lint (push) Successful in 2m55s
CI / test (push) Failing after 1s
CI / build (push) Skipped
CI / e2e (push) Skipped
2026-10-28 08:25:45 -04:00
bruno 2a1780b43d docs: commentaire 15 -> 16 themes integres (meme compteur obsolete que test_themes.py)
CI / security (pull_request) Failing after 0s
CI / lint (pull_request) Successful in 3m11s
CI / test (pull_request) Failing after 5m8s
CI / build (pull_request) Skipped
CI / e2e (pull_request) Skipped
2026-10-28 08:25:38 -04:00
bruno be05ec99b5 fix(tests): test_theme_count 15 -> 16 (theme spark ajoute en 2.80.2) 2026-10-28 08:25:35 -04:00
bruno 3a42bc034d fix(tests): declare le tag OpenAPI 'Coffres Secrets' (test_used_tags_are_declared) 2026-10-28 08:25:32 -04:00
bruno 27e7664ef0 feat(ui): dimensionnement de l'icone coffre-fort du noeud Secrets
CI / lint (pull_request) Failing after 4s
CI / test (pull_request) Skipped
CI / build (pull_request) Skipped
CI / e2e (pull_request) Skipped
CI / security (pull_request) Successful in 1m56s
2026-10-28 08:24:23 -04:00
bruno ccbf1d3269 feat(ui): icone coffre-fort SVG pour le noeud Secrets (remplace le cadenas emoji) 2026-10-28 08:24:16 -04:00
bruno 0ca14739f9 Merge pull request 'fix(lint): tri des imports dans backend/routers/coffres.py (I001)' (#32) from fix/ruff-coffres-imports into main
CI / security (push) Successful in 1m56s
CI / lint (push) Successful in 3m14s
CI / test (push) Failing after 5m5s
CI / build (push) Skipped
CI / e2e (push) Skipped
2026-10-28 08:16:47 -04:00
bruno d9192ef355 fix(lint): tri des imports dans backend/routers/coffres.py (I001)
CI / lint (pull_request) Failing after 0s
CI / test (pull_request) Skipped
CI / build (pull_request) Skipped
CI / e2e (pull_request) Skipped
CI / security (pull_request) Successful in 1m59s
2026-10-28 08:13:35 -04:00
bruno 4c9bfd576c Merge pull request 'chore(release): version 2.81.0 (Coffre Secrets Phases 2-5)' (#31) from fix/version-2.81.0 into main
CI / security (push) Failing after 0s
CI / lint (push) Failing after 1m50s
CI / test (push) Skipped
CI / build (push) Skipped
CI / e2e (push) Skipped
2026-10-28 00:16:49 -04:00
6 changed files with 10 additions and 8 deletions
+1
View File
@@ -41,6 +41,7 @@ TAGS_METADATA: list[dict[str, str]] = [
{"name": "Webhooks", "description": "HTTP callbacks signed with HMAC-SHA256 for file events."}, {"name": "Webhooks", "description": "HTTP callbacks signed with HMAC-SHA256 for file events."},
{"name": "Conflicts", "description": "Detect and resolve Syncthing sync-conflict files."}, {"name": "Conflicts", "description": "Detect and resolve Syncthing sync-conflict files."},
{"name": "Admin", "description": "Admin-only system monitoring: stats, audit log, backup stats and live stream."}, {"name": "Admin", "description": "Admin-only system monitoring: stats, audit log, backup stats and live stream."},
{"name": "Coffres Secrets", "description": "Secret vaults: encrypted coffres, secrets, consumers, grants and distribution — metadata only, values are never exposed."},
{"name": "Plugins", "description": "Install, enable and manage user plugins."}, {"name": "Plugins", "description": "Install, enable and manage user plugins."},
{"name": "Push", "description": "Web Push (VAPID) subscription management and test notifications."}, {"name": "Push", "description": "Web Push (VAPID) subscription management and test notifications."},
{"name": "Duplicates", "description": "Duplicate-note detection and confirmed merge (#166)."}, {"name": "Duplicates", "description": "Duplicate-note detection and confirmed merge (#166)."},
+1 -1
View File
@@ -34,10 +34,10 @@ from __future__ import annotations
import logging import logging
import os import os
from backend.auth.middleware import require_admin, require_auth
from fastapi import APIRouter, Body, Depends, HTTPException, Request from fastapi import APIRouter, Body, Depends, HTTPException, Request
from backend.audit import get_recent_entries, log_coffre_event from backend.audit import get_recent_entries, log_coffre_event
from backend.auth.middleware import require_admin, require_auth
from backend.coffre_crypto import ( from backend.coffre_crypto import (
CryptoIndisponibleError, CryptoIndisponibleError,
KEKAbsenteError, KEKAbsenteError,
+2 -2
View File
@@ -59,11 +59,11 @@ function _sharedIcon(size = 16) {
// renommer/déplacer/supprimer). Le menu ⋮ est un menu propre ci-dessous. // renommer/déplacer/supprimer). Le menu ⋮ est un menu propre ci-dessous.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Icône cadenas (U+1F510) du nœud Secrets, distincte de la maison et du diamant. */ /** Icône coffre-fort du nœud Secrets (SVG Safe Vault Streamline, fourni par Bruno), distincte de la maison et du diamant. Le tracé utilise currentColor pour rester lisible en thème clair comme sombre (le noir d'origine serait invisible en sombre). */
function _secretsIcon() { function _secretsIcon() {
const s = document.createElement("span"); const s = document.createElement("span");
s.className = "coffres-icon-lock"; s.className = "coffres-icon-lock";
s.textContent = "\u{1F510}"; s.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" aria-hidden="true"><g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"><path d="M12.5 0.5h-11c-0.552285 0 -1 0.447715 -1 1V11c0 0.5523 0.447715 1 1 1h11c0.5523 0 1 -0.4477 1 -1V1.5c0 -0.552285 -0.4477 -1 -1 -1Z"/><path d="M8.5 8c0.9665 0 1.75 -0.7835 1.75 -1.75S9.4665 4.5 8.5 4.5s-1.75 0.7835 -1.75 1.75S7.5335 8 8.5 8Z"/><path d="M8.5 3.25V4.5"/><path d="M8.5 8v1.25"/><path d="M11.5 6.25h-1.25"/><path d="M6.75 6.25H5.5"/><path d="m10.62 4.12988 -0.88001 0.88"/><path d="m7.26 7.48999 -0.88 0.88"/><path d="m10.62 8.36999 -0.88001 -0.88"/><path d="m7.26 5.00988 -0.88 -0.88"/><path d="M3 4.5V8"/><path d="M2 12v1.5"/><path d="M11.5 12v1.5"/></g></svg>';
return s; return s;
} }
+1 -1
View File
@@ -653,7 +653,7 @@ function applyTheme(themeKey, mode) {
root.style.setProperty(key, vars[key]); root.style.setProperty(key, vars[key]);
}); });
// #180 — the spreadsheet grid follows the active theme: derive its tokens // #180 — the spreadsheet grid follows the active theme: derive its tokens
// from the generic surfaces so every theme (15 built-in × 4 modes, custom // from the generic surfaces so every theme (16 built-in × 4 modes, custom
// imports) gets a matching grid instead of the hardcoded dark/light pair. // imports) gets a matching grid instead of the hardcoded dark/light pair.
// color-mix keeps the zebra stripe subtle on both dark and light grounds. // color-mix keeps the zebra stripe subtle on both dark and light grounds.
// #185 — `--grid-border` no longer reuses `--border` (which sits 1-2% off the // #185 — `--grid-border` no longer reuses `--border` (which sits 1-2% off the
+2 -1
View File
@@ -14372,7 +14372,8 @@ body.has-draco-bar .app-container { height: calc(100vh - 60px); }
.coffres-alerts { margin: 12px 0; } .coffres-alerts { margin: 12px 0; }
.coffres-alert { color: var(--warning, #f59e0b); padding: 2px 0; } .coffres-alert { color: var(--warning, #f59e0b); padding: 2px 0; }
.coffres-form { display: grid; gap: 8px; max-width: 560px; margin: 8px 0; } .coffres-form { display: grid; gap: 8px; max-width: 560px; margin: 8px 0; }
.coffres-icon-lock { font-size: 16px; line-height: 1; } .coffres-icon-lock { display: inline-flex; align-items: center; line-height: 1; }
.coffres-icon-lock svg { width: 16px; height: 16px; flex: none; }
.coffres-alert-dot { color: var(--warning, #f59e0b); font-weight: 700; margin-left: 4px; } .coffres-alert-dot { color: var(--warning, #f59e0b); font-weight: 700; margin-left: 4px; }
.coffres-context-menu { position: fixed; z-index: 1000; min-width: 220px; background: var(--bg-secondary, #161b22); border: 1px solid var(--border, #21262d); border-radius: 8px; padding: 4px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); } .coffres-context-menu { position: fixed; z-index: 1000; min-width: 220px; background: var(--bg-secondary, #161b22); border: 1px solid var(--border, #21262d); border-radius: 8px; padding: 4px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); }
.coffres-context-item { display: block; width: 100%; text-align: left; padding: 8px 12px; background: transparent; border: none; color: var(--text-primary, #e6edf3); cursor: pointer; border-radius: 6px; } .coffres-context-item { display: block; width: 100%; text-align: left; padding: 8px 12px; background: transparent; border: none; color: var(--text-primary, #e6edf3); cursor: pointer; border-radius: 6px; }
+3 -3
View File
@@ -2,7 +2,7 @@
Validates: Validates:
- Theme JSON structure validity - Theme JSON structure validity
- All 15 built-in themes have required keys and valid CSS colors - All 16 built-in themes have required keys and valid CSS colors
- High-contrast and sepia mode generators produce valid CSS vars - High-contrast and sepia mode generators produce valid CSS vars
- Import/export round-trip - Import/export round-trip
- AVAILABLE_MODES includes all 4 modes - AVAILABLE_MODES includes all 4 modes
@@ -80,9 +80,9 @@ class TestThemeStructure:
assert '_genSepia' in self.content assert '_genSepia' in self.content
def test_theme_count(self): def test_theme_count(self):
"""Should have 15 built-in themes.""" """Should have 16 built-in themes."""
names = _extract_theme_names(self.content) names = _extract_theme_names(self.content)
assert len(names) == 15, f"Expected 15 themes, found {len(names)}: {names}" assert len(names) == 16, f"Expected 16 themes, found {len(names)}: {names}"
def test_required_export_functions(self): def test_required_export_functions(self):
"""All required functions should be exported.""" """All required functions should be exported."""