Three bugs fixed:
1. Phase 30 (auth.ts): After SRP login the encrypted_key_set was returned
from the server but the vault key and RSA private key were never unwrapped
with the AUK. keyStore.getVaultKey() was always null, causing Tier 1
config-backup diffs to crash with a TypeError.
Fix: unwrap vault key and private key using crypto.subtle.unwrapKey after
successful SRP verification. Non-fatal: warns to console if decryption
fails so login always succeeds.
2. Token refresh (auth.py): The /refresh endpoint required refresh_token in
the request body, but the frontend never stored or sent it. After the 15-
minute access token TTL, all authenticated API calls would fail silently
because the interceptor sent an empty body and received 422 (not 401),
so the retry loop never fired.
Fix: login/srpVerify now set an httpOnly refresh_token cookie scoped to
/api/auth/refresh. The refresh endpoint now accepts the token from either
cookie (preferred) or body (legacy). Logout clears both cookies.
RefreshRequest.refresh_token is now Optional to allow empty-body calls.
3. Silent token rotation: the /refresh endpoint now also rotates the refresh
token cookie on each use (issues a fresh token), reducing the window for
stolen refresh token replay.
The Secret Key encoder used 26 base-30 characters which can only
represent 30^26 ≈ 2^127.58 values. Since the key is 128 bits,
~25% of generated keys silently lost their high bits during
formatting, making the Emergency Kit key unable to reconstruct
the original bytes on a new browser.
Changed KEY_CHAR_LENGTH from 26 to 27 (30^27 > 2^128). Parser
accepts both old 26-char and new 27-char keys for backward
compatibility. Format: A3-XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXX
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restore original 6-step quick start with comments. Increase arch flow
box contrast (bg-deep background, stronger border) and arrow size.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Hero: tighter 3-line intro focused on the problem
- What It Does: updated section label
- Safe Config: panic-revert language, fleet-wide templates
- Who This Is For: expanded audience descriptions
- Architecture: new section with vertical flow diagram
- Quick Start: simplified to 3 commands
- CTA: open source + self-hosted, closing tagline
- Slow gradient fill animation from 1.2s to 2s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gradient on left half of background, white on right. Animation sweeps
from white to gradient. Uses 'both' fill mode for correct state during
delay and after completion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The gradient sweeps left-to-right across "Centralized Management"
after a 0.3s delay, transitioning from plain text to the teal-burgundy
gradient over 1.2s.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each list gets a dynamically generated keyframe where only 1/N of the
cycle is active. Bullets are staggered 0.8s apart so they take turns
pulsing in sequence, looping forever.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Teal bullet dots pulse with a staggered throb when list items scroll
into view. Uses IntersectionObserver with 120ms stagger per item.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Section labels, titles, descriptions, and closing statements are now
centered. Bullet lists remain left-aligned within their centered
container for readability. Fixes visual disconnect between centered
hero and left-justified content sections.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace marketing-heavy hero, feature cards, and architecture diagram
with straightforward copy aimed at real MikroTik operators. New sections:
What It Does, Safe Configuration, Built for Real Operators, Designed for
Scale, and Open Source CTA.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace verbose ASCII architecture in README with clean linear flow.
Remove tech stack badge grid from landing page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Banner on landing page, docs page, and GitHub README warning that the
software is in active development and not yet ready for production use.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
execute_cli was passing the full CLI string (e.g. '/ping address=8.8.8.8
count=4') as a single command to the Go poller. go-routeros expects the
command path and args separately. Now splits into command + prefixed args.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The target input showed "8.8.8.8" as placeholder text but the actual
value was empty. Clicking Ping/Traceroute silently returned because
the empty target guard fired. Users saw the placeholder and assumed
the tool was broken.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The server-generated PDF had a placeholder for the Secret Key that was
never filled in client-side, making the Emergency Kit useless. Users
who relied on it could not recover their Secret Key on new devices.
Now generates the PDF entirely client-side via browser print dialog,
with the real Secret Key embedded. No server round-trip, key never
leaves the browser.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a user logs in from a browser with an outdated Secret Key in
IndexedDB (e.g. after server rebuild/re-enrollment), the SRP handshake
fails with 401 but the Secret Key input field was never shown — leaving
the user stuck with no way to enter their current key.
Now detects stale-key 401s and prompts for manual Secret Key entry.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The FleetTable empty state navigated with ?add=true but the devices page
never read that param. Now it opens the AddDeviceForm when add=true is
in the search params.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CurrentUser object uses user_id attribute, not id. Caused AttributeError
on PUT /api/settings/smtp.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When use_tls=false, the old logic set start_tls=true for any port != 25,
which broke plain SMTP servers like Mailpit. Now:
- Port 465: implicit TLS
- use_tls=true on other ports: STARTTLS
- use_tls=false: plain SMTP (no TLS)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Absolute paths (/Volumes/ssd01/mikrotik/docker-data/) are machine-specific
and won't work on any other system. Use ./docker-data/ so the repo works
wherever it's cloned.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- POSTGRES_PASSWORD and DB URLs now match what docker-compose.override.yml
and init-postgres.sql actually use (postgres/postgres, app_password)
- CREDENTIAL_ENCRYPTION_KEY is now valid base64 (32 bytes) so the API
actually starts instead of crashing on the Pydantic validator
- JWT_SECRET_KEY is a dev-only value (insecure defaults check skips dev)
- Added quick-start comment block with login credentials
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add GitHub link to nav bar on both index and docs pages
- Add git clone + cd commands to Quick Start terminal block
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 1200x630 og-image.png with rug rosette branding
- Add og:image and twitter:image to docs.html
- Upgrade docs.html twitter:card from summary to summary_large_image
- Add og:locale to docs.html
- Add footer with nav links to docs.html
- Add GitHub repo link to both page footers
- Update sitemap.xml lastmod to 2026-03-09
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>