From 7751ebe9b3f9c2ba957a25eb8d8be9bca3b84ca6 Mon Sep 17 00:00:00 2001 From: Miles Ward Date: Mon, 31 Aug 2026 01:42:18 -0400 Subject: [PATCH] v0.1.2: working Edit sheet, centred search, brand assets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a bug that shipped in v0.1: the per-account Edit sheet never opened at all. Its Cancel button used `onclick: dlg.close`, evaluated while building the arguments to openModal() and therefore before `const dlg` was initialised — a temporal-dead-zone ReferenceError that aborted the whole handler. Every other button in that sheet was already a closure, which is why it went unnoticed: browser testing had covered add, import and settings, but never opened this sheet. Renames now reach Discord almost immediately. The push loop skips any account whose current code it has already sent, so a rename previously stayed invisible until the code next rolled — up to a full period. update() now clears the last-sent code when the naming actually changes, so the next tick treats the tile as stale and rewrites it in about a second. Toggling push alone is not a rename and still costs nothing. - webui: pencil icon and "Edit account" title so the row action reads as edit rather than settings; both fields labelled, with the second one explained as the username/email and left untouched unless changed - webui: topbar is a three-column grid so the search sits on the same centre line as the account tiles. Below 820px there isn't room for brand + 420px search + actions, so it falls back to a row rather than clipping the wordmark; the brand now reads "Discord Authenticator" in full - webui: the add-account FAB pins to the viewport corner instead of tracking the content column edge - brand: docs/brand/icon.svg plus PNGs rendered from it by da-render, so the README image, Gitea avatar and Unraid template icon all derive from one source rather than drifting. Unraid's now points at a PNG, which it renders more reliably than SVG 126 tests (was 124). Co-Authored-By: Claude Opus 4.8 --- Cargo.lock | 12 ++-- Cargo.toml | 2 +- README.md | 31 ++++++--- crates/core/src/vault.rs | 15 +++++ crates/discord/tests/live_push.rs | 81 ++++++++++++++++++++++++ crates/render/examples/brand.rs | 15 +++++ crates/render/src/lib.rs | 35 ++++++++++ crates/webui/src/app.css | 31 ++++++++- crates/webui/src/app.js | 62 +++++++++++------- deploy/unraid/discord-authenticator.xml | 2 +- docs/brand/icon-128.png | Bin 0 -> 10704 bytes docs/brand/icon-256.png | Bin 0 -> 24131 bytes docs/brand/icon-512.png | Bin 0 -> 52757 bytes docs/brand/icon.svg | 31 +++++++++ 14 files changed, 274 insertions(+), 43 deletions(-) create mode 100644 crates/render/examples/brand.rs create mode 100644 docs/brand/icon-128.png create mode 100644 docs/brand/icon-256.png create mode 100644 docs/brand/icon-512.png create mode 100644 docs/brand/icon.svg diff --git a/Cargo.lock b/Cargo.lock index 2269916..3b6788e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -436,7 +436,7 @@ dependencies = [ [[package]] name = "da-core" -version = "0.1.1" +version = "0.1.2" dependencies = [ "argon2", "base32", @@ -461,7 +461,7 @@ dependencies = [ [[package]] name = "da-discord" -version = "0.1.1" +version = "0.1.2" dependencies = [ "axum", "da-core", @@ -478,7 +478,7 @@ dependencies = [ [[package]] name = "da-http-api" -version = "0.1.1" +version = "0.1.2" dependencies = [ "axum", "base64 0.22.1", @@ -500,7 +500,7 @@ dependencies = [ [[package]] name = "da-render" -version = "0.1.1" +version = "0.1.2" dependencies = [ "image", "resvg", @@ -512,7 +512,7 @@ dependencies = [ [[package]] name = "da-webui" -version = "0.1.1" +version = "0.1.2" [[package]] name = "data-url" @@ -542,7 +542,7 @@ dependencies = [ [[package]] name = "discord-authenticator" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "axum", diff --git a/Cargo.toml b/Cargo.toml index e0d37ca..95e7d03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ ] [workspace.package] -version = "0.1.1" +version = "0.1.2" edition = "2021" rust-version = "1.90" license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index 880626f..1ddfe0a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ -# Discord Authenticator +

+ Discord Authenticator +

-A self-hosted TOTP authenticator whose codes appear in Discord as **live -messages that rewrite themselves** as each code rolls. +

Discord Authenticator

+ +

+ A self-hosted TOTP authenticator whose codes appear in Discord as + live messages that rewrite themselves as each code rolls. +

The web UI is what you'd expect from Google or Microsoft Authenticator: a searchable list of accounts, each with its six digits and a countdown ring. @@ -209,9 +215,17 @@ and `=`-padded secrets, and where the issuer in the path disagrees with the `?issuer=` parameter — which Microsoft does — it takes the query parameter rather than refusing the account. -**In the list**, click any code to copy it. `/` focuses the search box. The -gear on a row renames the account or pauses its Discord push; pausing removes -its tile from the channel. +**In the list**, click any code to copy it. `/` focuses the search box. + +The pencil on a row opens **Edit account**. The *Name* is what shows in the +list and on the Discord tile; the *Account* field underneath (usually the +username or email the code belongs to) is left alone unless you change it — +it's editable, since providers sometimes put something unhelpful there. The +same sheet pauses Discord push for that account, or removes it entirely. + +A rename reaches Discord within a second or two. It doesn't wait for the code +to roll: the push loop normally skips any account whose current code it has +already sent, so renaming clears that marker to force one refresh. --- @@ -271,7 +285,7 @@ JetBrains Mono. Light and dark both ship. ### Testing -124 tests, including: +126 tests, including: - The **RFC 6238 test vectors** for SHA-1, SHA-256 and SHA-512. - Real **QR round-trips** — clean, 1-pixel-per-module, oversized, rotated, JPEG, @@ -284,7 +298,8 @@ JetBrains Mono. Light and dark both ship. - The **live push cycle against a mock Discord**: that the first call carries `?wait=true`, that later passes PATCH the same message rather than posting again, that a deleted tile is reposted, that a dead webhook is surfaced - instead of hammered, and that concurrent rollovers are paced apart. + instead of hammered, that concurrent rollovers are paced apart, and that a + rename refreshes the tile immediately without re-posting it or looping. ```bash cargo test --workspace diff --git a/crates/core/src/vault.rs b/crates/core/src/vault.rs index 4c80d32..e80b87b 100644 --- a/crates/core/src/vault.rs +++ b/crates/core/src/vault.rs @@ -354,16 +354,20 @@ impl Vault { .iter_mut() .find(|a| a.id == id) .ok_or_else(|| Error::not_found("account"))?; + + let mut renamed = false; if let Some(v) = issuer.map(str::trim).filter(|s| !s.is_empty()) { if v.len() > 128 { return Err(Error::invalid("issuer must be 128 characters or fewer")); } + renamed |= a.issuer != v; a.issuer = v.to_string(); } if let Some(v) = label.map(str::trim) { if v.len() > 128 { return Err(Error::invalid("account must be 128 characters or fewer")); } + renamed |= a.label != v; a.label = v.to_string(); } if let Some(v) = push_enabled { @@ -374,6 +378,17 @@ impl Vault { } a.push_enabled = v; } + + // A rename changes what the Discord tile should say, but not the + // code — and the push loop skips any account whose code it has + // already sent. Without this the new name would sit invisible + // until the code next rolled, up to a full period later. Clearing + // the last-sent code makes the very next tick treat the tile as + // stale, so the rename shows up in about a second. + if renamed { + a.discord.last_code = None; + } + AccountPublic::from(&*a) }; self.persist(); diff --git a/crates/discord/tests/live_push.rs b/crates/discord/tests/live_push.rs index e670829..717c2ce 100644 --- a/crates/discord/tests/live_push.rs +++ b/crates/discord/tests/live_push.rs @@ -385,6 +385,87 @@ async fn a_dead_webhook_is_surfaced_and_not_hammered() { assert!(vault.push_targets()[0].message_id.is_some()); } +#[tokio::test] +async fn renaming_an_account_refreshes_its_tile_without_waiting_for_the_code() { + let dir = tempfile::tempdir().unwrap(); + let (url, mock) = spawn_mock().await; + // A 30-second period: the code will NOT roll during this test, so any + // update we see must have been triggered by the rename itself. + let (vault, settings) = fixture(dir.path(), &url, "embed", 30); + let engine = PushEngine::new(vault.clone(), settings); + + engine.sync_once().await; + let message_id = vault.push_targets()[0].message_id.clone().unwrap(); + assert_eq!(mock.log.lock().unwrap().len(), 1); + + // Nothing changed yet, so a second pass must stay silent. + engine.sync_once().await; + assert_eq!( + mock.log.lock().unwrap().len(), + 1, + "an idle pass must cost nothing" + ); + + // Rename, then run one pass — no sleeping, no code rollover. + let id = vault.list()[0].id.clone(); + vault + .update(&id, Some("Cloudflare Work"), Some("ops@corp.example"), None) + .unwrap(); + assert_eq!( + engine.sync_once().await, + 1, + "the rename should trigger a push" + ); + + { + let log = mock.log.lock().unwrap(); + assert_eq!(log.len(), 2); + assert_eq!( + log[1].method, "PATCH", + "the same tile is edited, not replaced" + ); + assert!(log[1].path.ends_with(&format!("/messages/{message_id}"))); + + // The edited message must carry the new naming. + let body = log[1].json(); + assert_eq!(body["embeds"][0]["title"], "Cloudflare Work"); + let desc = body["embeds"][0]["description"].as_str().unwrap(); + assert!( + desc.contains("ops@corp.example"), + "new label missing: {desc}" + ); + assert!( + !desc.contains("me@example.com"), + "old label still present: {desc}" + ); + } + + // And it settles: a further pass sends nothing more. + engine.sync_once().await; + assert_eq!( + mock.log.lock().unwrap().len(), + 2, + "rename must not re-push forever" + ); +} + +#[tokio::test] +async fn toggling_push_alone_does_not_rewrite_the_tile() { + let dir = tempfile::tempdir().unwrap(); + let (url, mock) = spawn_mock().await; + let (vault, settings) = fixture(dir.path(), &url, "embed", 30); + let engine = PushEngine::new(vault.clone(), settings); + + engine.sync_once().await; + let id = vault.list()[0].id.clone(); + + // Re-affirming the same push state is not a rename and changes nothing + // the tile displays, so it should not cost a request. + vault.update(&id, None, None, Some(true)).unwrap(); + engine.sync_once().await; + assert_eq!(mock.log.lock().unwrap().len(), 1); +} + #[tokio::test] async fn pausing_an_account_removes_its_tile() { let dir = tempfile::tempdir().unwrap(); diff --git a/crates/render/examples/brand.rs b/crates/render/examples/brand.rs new file mode 100644 index 0000000..c58a89a --- /dev/null +++ b/crates/render/examples/brand.rs @@ -0,0 +1,15 @@ +//! Rasterise the brand icon to PNG at the sizes the README, the Gitea repo +//! avatar and the Unraid template need: +//! `cargo run -p da-render --example brand -- docs/brand` +fn main() { + let dir = std::env::args() + .nth(1) + .unwrap_or_else(|| "docs/brand".into()); + let svg = std::fs::read_to_string(format!("{dir}/icon.svg")).expect("read icon.svg"); + for size in [512u32, 256, 128] { + let png = da_render::rasterise_svg(&svg, size, size).expect("render"); + let path = format!("{dir}/icon-{size}.png"); + std::fs::write(&path, &png).expect("write"); + println!("wrote {path} ({} bytes)", png.len()); + } +} diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index 3a926f9..89cee7e 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -75,6 +75,41 @@ pub fn tile_png(tile: &Tile<'_>) -> Result> { Ok(out.into_inner()) } +/// Rasterise arbitrary SVG source to a PNG at a given size. +/// +/// Exposed so the brand assets (README image, Gitea avatar, Unraid template +/// icon) are generated from the same `icon.svg` the app ships, rather than +/// being hand-exported and drifting out of sync with it. +pub fn rasterise_svg(svg: &str, width: u32, height: u32) -> Result> { + let tree = usvg::Tree::from_str(svg, options())?; + let mut pixmap = + tiny_skia::Pixmap::new(width, height).ok_or(RenderError::Pixmap(width, height))?; + + // Scale the document to fill the requested pixmap. + let size = tree.size(); + let scale = (width as f32 / size.width()).min(height as f32 / size.height()); + resvg::render( + &tree, + tiny_skia::Transform::from_scale(scale, scale), + &mut pixmap.as_mut(), + ); + + let mut rgba = Vec::with_capacity((width * height * 4) as usize); + for px in pixmap.pixels() { + let c = px.demultiply(); + rgba.extend_from_slice(&[c.red(), c.green(), c.blue(), c.alpha()]); + } + + let mut out = std::io::Cursor::new(Vec::new()); + image::codecs::png::PngEncoder::new(&mut out).write_image( + &rgba, + width, + height, + image::ExtendedColorType::Rgba8, + )?; + Ok(out.into_inner()) +} + fn rasterise(tile: &Tile<'_>) -> Result> { let svg = build_svg(tile); let tree = usvg::Tree::from_str(&svg, options())?; diff --git a/crates/webui/src/app.css b/crates/webui/src/app.css index b518f50..96d38c5 100644 --- a/crates/webui/src/app.css +++ b/crates/webui/src/app.css @@ -160,15 +160,39 @@ a:hover { text-decoration: underline; } .shell { display: flex; flex-direction: column; min-height: 100vh; } +/* Three columns: the search occupies the middle one, so it lands on the same + centre line as the account tiles below no matter how wide the brand or the + action cluster get. The outer columns are equal-width and allowed to + shrink, which keeps the centring exact rather than approximate. */ .topbar { position: sticky; top: 0; z-index: 30; - display: flex; align-items: center; gap: 12px; + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 420px) minmax(0, 1fr); + align-items: center; gap: 12px; height: var(--topbar-h); padding: 0 16px; background: color-mix(in oklab, var(--page) 82%, transparent); backdrop-filter: saturate(1.6) blur(12px); border-bottom: 1px solid var(--line); } +.topbar .brand { justify-self: start; min-width: 0; } +.topbar .brand strong { overflow: hidden; text-overflow: ellipsis; } +.topbar .actions { + justify-self: end; + display: flex; align-items: center; gap: 2px; +} + +/* True centring needs room for all three: the brand wordmark (~210px), the + 420px search, the action cluster (~110px), plus gaps and padding — about + 800px in total. Below that the grid starts clipping "Discord Authenticator", + so fall back to a plain row where the brand keeps its space and the search + takes whatever is left. */ +@media (max-width: 820px) { + .topbar { display: flex; } + .topbar .brand { flex: 0 0 auto; } + .topbar .search { flex: 1 1 auto; justify-self: auto; } + .topbar .actions { margin-left: auto; flex: 0 0 auto; } +} .brand { display: flex; align-items: center; gap: 9px; flex: none; } .brand svg { width: 26px; height: 26px; display: block; } @@ -192,8 +216,9 @@ a:hover { text-decoration: underline; } .search { position: relative; - flex: 1 1 auto; + width: 100%; max-width: 420px; + justify-self: center; } .search svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); @@ -483,7 +508,7 @@ textarea.input { height: auto; min-height: 76px; padding: 9px 11px; .fab { position: fixed; - right: max(20px, calc(50vw - 344px)); + right: 24px; bottom: 24px; z-index: 25; display: inline-flex; align-items: center; gap: 8px; diff --git a/crates/webui/src/app.js b/crates/webui/src/app.js index f2fe995..d1b3254 100644 --- a/crates/webui/src/app.js +++ b/crates/webui/src/app.js @@ -89,6 +89,7 @@ const ICON = { back: 'M19 12H5m7 7-7-7 7-7', key: ['M12.7 11.3a5 5 0 1 0-4 4L10 14h2v-2h2l-1.3-1.3Z'], send: ['M22 2 11 13', 'M22 2l-7 20-4-9-9-4 20-7z'], + edit: ['M12 20h9', 'M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z'], }; // ── State ────────────────────────────────────────────────────────────────── @@ -349,27 +350,31 @@ function renderShell() { const logoImg = h('img', { src: '/assets/logo.svg', alt: '', width: 26, height: 26 }); + // Three columns so the search sits on the page's centre line, matching the + // centred account tiles below it, regardless of how wide the brand or the + // action cluster happen to be. const topbar = h('header.topbar', {}, [ h('div.brand', { style: 'cursor:pointer', onclick: () => go('vault') }, [ - logoImg, h('strong', { text: 'Authenticator' }), + logoImg, h('strong', { text: 'Discord Authenticator' }), ]), searchWrap, - h('div.spacer'), - h('button.icon-btn.theme-toggle', { - type: 'button', 'aria-label': 'Toggle theme', title: 'Toggle theme', - onclick: toggleTheme, - }, [ - icon(ICON.sun, { className: 't-sun', width: 2 }), - icon(ICON.moon, { className: 't-moon', width: 2 }), + h('div.actions', {}, [ + h('button.icon-btn.theme-toggle', { + type: 'button', 'aria-label': 'Toggle theme', title: 'Toggle theme', + onclick: toggleTheme, + }, [ + icon(ICON.sun, { className: 't-sun', width: 2 }), + icon(ICON.moon, { className: 't-moon', width: 2 }), + ]), + h('button.icon-btn', { + type: 'button', 'aria-label': 'Settings', title: 'Settings', + onclick: () => go('settings'), + }, [icon(ICON.settings, { width: 1.7 })]), + h('button.icon-btn', { + type: 'button', 'aria-label': 'Sign out', title: 'Sign out', + onclick: async () => { await api('/api/logout', { method: 'POST' }); stopTicker(); boot(); }, + }, [icon(ICON.logout, { width: 2 })]), ]), - h('button.icon-btn', { - type: 'button', 'aria-label': 'Settings', title: 'Settings', - onclick: () => go('settings'), - }, [icon(ICON.settings, { width: 1.7 })]), - h('button.icon-btn', { - type: 'button', 'aria-label': 'Sign out', title: 'Sign out', - onclick: async () => { await api('/api/logout', { method: 'POST' }); stopTicker(); boot(); }, - }, [icon(ICON.logout, { width: 2 })]), ]); root().replaceChildren(h('div.shell', {}, [topbar, h('main.main', { id: 'view' })])); @@ -480,9 +485,9 @@ function acctRow(a) { codeBtn, ring, h('button.icon-btn', { - type: 'button', 'aria-label': `Options for ${a.issuer}`, title: 'Options', + type: 'button', 'aria-label': `Edit ${a.issuer}`, title: 'Edit', onclick: () => openAccountSheet(a), - }, [icon(ICON.settings, { width: 1.7 })]), + }, [icon(ICON.edit, { width: 1.9 })]), ]), ]); return row; @@ -1057,15 +1062,21 @@ function openAccountSheet(a) { const label = h('input.input', { value: a.label || '' }); const push = h('input', { type: 'checkbox', checked: !!a.push_enabled }); - const dlg = openModal(a.issuer || 'Account', [ + const dlg = openModal('Edit account', [ a.push_error ? h('div.alert.err', {}, [icon(ICON.alert), h('span', { text: a.push_error })]) : null, - h('div.field', {}, [h('label', { text: 'Issuer' }), issuer]), - h('div.field', {}, [h('label', { text: 'Account' }), label]), + h('div.field', {}, [ + h('label', { text: 'Name' }), issuer, + h('div.hint', { text: 'What this account is called — shown in the list and on the Discord tile.' }), + ]), + h('div.field', {}, [ + h('label', { text: 'Account' }), label, + h('div.hint', { text: 'Usually the username or email the code belongs to. Left as-is unless you change it.' }), + ]), h('label.switch', { style: 'margin:16px 0 4px' }, [ push, h('span.track'), h('span.switch-label', { text: 'Stream this code to Discord' }), ]), - h('p.hint', { text: 'When on, this account keeps one live message in your Discord channel, edited in place every time the code rolls.' }), + h('p.hint', { text: 'When on, this account keeps one live message in your Discord channel, edited in place every time the code rolls. Renaming updates that message within a second or two.' }), ], [ h('button.btn.btn-danger', { onclick: async () => { if (!confirm(`Remove ${a.issuer}? Its secret is deleted permanently and its Discord message is removed.`)) return; @@ -1075,14 +1086,17 @@ function openAccountSheet(a) { } catch (e) { toast(e.message, 'err'); } } }, [icon(ICON.trash, { width: 1.9 }), 'Remove']), h('div', { style: 'flex:1' }), - h('button.btn', { onclick: dlg.close, text: 'Cancel' }), + // Deferred: `dlg` is still in its temporal dead zone while these + // arguments are being built, so `onclick: dlg.close` throws and the whole + // sheet fails to open. Every other handler here is already a closure. + h('button.btn', { onclick: () => dlg.close(), text: 'Cancel' }), h('button.btn.btn-primary', { onclick: async () => { try { await api('/api/accounts/' + encodeURIComponent(a.id), { method: 'PATCH', body: { issuer: issuer.value.trim(), label: label.value.trim(), push_enabled: push.checked }, }); - dlg.close(); toast('Saved'); await reloadAll(); + dlg.close(); toast('Saved — the Discord tile updates shortly'); await reloadAll(); } catch (e) { toast(e.message, 'err'); } }, text: 'Save' }), ]); diff --git a/deploy/unraid/discord-authenticator.xml b/deploy/unraid/discord-authenticator.xml index 513a717..ee09974 100644 --- a/deploy/unraid/discord-authenticator.xml +++ b/deploy/unraid/discord-authenticator.xml @@ -45,7 +45,7 @@ Tools:Utilities Security: http://[IP]:[PORT:8710]/ - https://gitea.milesward.dev/mward4/Discord-Authenticator/raw/branch/main/crates/webui/src/logo.svg + https://gitea.milesward.dev/mward4/Discord-Authenticator/raw/branch/main/docs/brand/icon-256.png diff --git a/docs/brand/icon-128.png b/docs/brand/icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..8ad3433e257cb269e7e6f112b61007e2cec364ff GIT binary patch literal 10704 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
KIlv}FpxW)$9QL+&A zK^G0_x`w~6047esfWqm?sBK}&f8tQj|332*=I(Fm$oCVwW%~bWjN(2$eYa|o8+>=9MkMTvKG6to6*AH=l|T#vT#I#ItRHwnM-V-3sKd>1BYfI4lILpY^m znCkc$GcmLm+&am_zv>|Kj)zq6yJ+uq@YJRC@xs6qX3S(B_#R0x#9aLTRgo1Q{XtG=T8YJ5aE6g+k6~u$q1487<*z+75%fn+ zGJh}7(i+Egf%_|8G2fZ@SLc zcijuor*svXSQi^r#wjZbY8%S8FK%*BS~p|f41VF_z)T+RQch3WksN4}k@+yVZ#QgX zWE7ijcY2_!MbSf)cl5!(ZI>Grb=9zWEs3JhH4WU+BzHp%=r zOz>BqUn=kzSu{rhW5q;+{ysMsobnsi0Bu)a!4XUm@9E-<4X9}yfq$gH8<(#)lzC+L zheq{K9$}@4KDb%$eoxgz9F^l#>C&eeqng7$OQ+1^!5J332d7; zciWErd(65=IX7MfIUxi`mxJqspY4W(+Wp8q$TxS3`?n`|-)Lmqvsu|Pc=eO0z!1Hb zpLW~=J0D}2Yha2g2l#eo-H!8_eKdo;F$0AMx-E~zO8pfTSY<;!xKtQ8Vz0tw{_(@j T*>>QjCTjOi#~qnpxt;re9DFTV literal 0 HcmV?d00001 diff --git a/docs/brand/icon-256.png b/docs/brand/icon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..48169e752276bbd28ba5dcd2e76fd48215771c93 GIT binary patch literal 24131 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 literal 0 HcmV?d00001 diff --git a/docs/brand/icon.svg b/docs/brand/icon.svg new file mode 100644 index 0000000..f49584d --- /dev/null +++ b/docs/brand/icon.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + +