Files
PartsInventorySystem/static/index.html
T
thejayman77 ab82b5e9a9 Manage the password in the app; close remaining audit findings
Password management moves out of the CLI entirely. The credential is now a
salted scrypt hash in the database (so it survives rebuilds, living in the /data
volume) rather than an environment variable; PARTS_PASSWORD is demoted to a
bootstrap value that stops working the moment a password is set in the UI. Every
token carries a session epoch, so changing the password — or "sign out other
devices" — invalidates outstanding cookies while keeping the browser that made
the change signed in. A banner nags until the handed-over password is replaced.
app/admin.py remains for the one case the UI cannot cover, a forgotten password.

Audit findings:
- Taxonomy update and delete scanned affected parts before taking the write
  lock, so a concurrent rename could leave the search index matching a name the
  UI no longer showed. All four routes now lock first; removing the lock again
  makes the new test fail exactly that way.
- History of a missing part returned 200 with an empty list; now 404.
- Infinity and NaN passed ge=0 and failed at the database. They are rejected as
  422 now, and the validation error handler no longer chokes trying to echo a
  non-finite value back.

Checks go from 134 to 181.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 10:31:06 -04:00

76 lines
2.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="color-scheme" content="dark">
<title>Parts Inventory</title>
<link rel="stylesheet" href="/static/app.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><text y='13' font-size='13'>🧰</text></svg>">
</head>
<body>
<section id="login" class="hidden">
<form id="login-form">
<h1>Parts Inventory</h1>
<p>Enter the password to continue.</p>
<input type="password" id="password" autocomplete="current-password" placeholder="Password" required>
<p id="login-error" class="hidden" style="color:var(--bad);margin:10px 0 0"></p>
<button class="primary" type="submit" style="width:100%;margin-top:14px">Unlock</button>
</form>
</section>
<section id="app" class="hidden">
<header>
<span class="brand">🧰 Parts</span>
<input class="search" id="search" type="search" placeholder="Search parts, values, MPN, tags…" autocomplete="off">
<span class="stat" id="stats"></span>
<button class="ghost small mobile-only" id="filters-btn">Filters</button>
<button class="primary" id="add-btn">+ Add</button>
<button class="ghost small" id="manage-btn" title="Settings"></button>
<button class="ghost small hidden" id="logout-btn" title="Log out"></button>
</header>
<div id="bootstrap-banner" class="banner hidden">
<span>You're still using the password that was handed to you. Set your own.</span>
<button class="small primary" id="banner-change">Change password</button>
</div>
<div class="layout">
<aside id="sidebar">
<h3>Filters</h3>
<div class="filter" id="filter-all">All parts <span class="count" id="count-all"></span></div>
<div class="filter" id="filter-low">Low stock <span class="count" id="count-low"></span></div>
<h3>Categories</h3>
<div id="category-list"></div>
<h3>Locations</h3>
<div id="location-list"></div>
<h3>Tags</h3>
<div id="tag-list"></div>
</aside>
<main>
<div class="toolbar">
<span class="grow" id="result-summary"></span>
<select id="sort">
<option value="relevance">Best match</option>
<option value="name">Name AZ</option>
<option value="quantity">Quantity, lowest</option>
<option value="updated">Recently updated</option>
<option value="created">Recently added</option>
<option value="location">Location</option>
</select>
</div>
<div id="results"></div>
<div style="text-align:center;margin:14px 0">
<button id="more-btn" class="hidden">Load more</button>
</div>
</main>
</div>
</section>
<div id="modal-root"></div>
<script src="/static/app.js"></script>
</body>
</html>