Donkie e4563e58c7 auth: core primitives
Levels, principals, password hashing, cookies and login throttling. Pure
library code -- nothing imports it into a request path yet.

levels.py
  An ordered read < edit < manage scale. Ranks live in a separate mapping
  rather than as comparison operators on the enum: StrEnum inherits str's
  operators, so defining __lt__/__ge__ would shadow string ordering with a
  second alphabetical meaning that happens to agree today and would stop
  agreeing the moment a level is renamed. Callers use covers().

principal.py
  A frozen dataclass describing who is asking and what they may do. The
  absence of a credential is None rather than a Principal, so "nobody" can
  never be mistaken for a permission holder. Carries the tenant_id seam from
  the design doc: always None, present so auth functions already thread a
  tenant and adding tenancy later is a filter inside them rather than a
  change to forty routers. UNRESTRICTED is what gates return when auth is
  off, before any database access.

hashing.py
  scrypt at n=2**14, r=8, p=1 -- argon2-cffi and bcrypt ship compiled wheels
  that are painful on the armv7 image, and scrypt is memory-hard and in the
  standard library. OWASP's headline n=2**17 would be multi-second on the
  ARM boards Spoolman runs on; their memory-constrained variant raises p,
  which costs the same time without the memory hardness.

  Hashes embed their own parameters, so the cost can be raised later without
  a migration: verification re-derives with the stored parameters and
  needs_rehash() reports staleness for opportunistic upgrade at login.

  Deriving blocks for ~50 ms here and several times that on a Pi. Spoolman
  is a single process, so a synchronous call in a handler would stall every
  other request. Measured 4 hashes serially at 171 ms against 63 ms across
  four threads, confirming scrypt releases the GIL and the _async wrappers
  are a real offload. Handlers must use those.

  Session tokens are hashed with plain unsalted SHA-256, deliberately: they
  are 256 bits of cryptographic randomness, so there is no dictionary to
  attack and no work factor worth paying. The digest exists so a database
  leak does not hand over usable cookies.

cookies.py
  Session cookie is HttpOnly, so CSRF is handled by double submit against a
  second script-readable cookie. Secure is only ever concluded from positive
  evidence -- real TLS, or a proxy listed in SPOOLMAN_TRUSTED_PROXIES saying
  so -- because setting it on a plain-HTTP LAN deployment makes the browser
  discard the cookie and presents as a login that succeeds and does nothing.

ratelimit.py
  In-process sliding windows keyed by username and by client address. Sound
  because the deployment contract is one process, the same assumption the
  websocket manager and scheduler already make; counters reset on restart,
  which is why lockout is also persisted on auth_user. X-Forwarded-For and
  X-Forwarded-Proto are honoured only from a configured trusted proxy,
  otherwise any client could spoof them to evade the limiter.

Also adds AuthenticationRequiredError and PermissionDeniedError to
exceptions.py, matching the existing bare-Exception style.

Verified: level ordering and rejection of unknown names; principal frozen
and anonymous capped at read; hash round-trip, distinct salts, corrupt
hashes never validating, needs_rehash on stale parameters, and dummy_verify
costing 41 ms against a real verify's 42 ms so unknown usernames are
timing-indistinguishable; window limit/expiry/reset; untrusted
X-Forwarded-For ignored and untrusted proxies unable to force Secure; and
all nine CSRF cases including a lowercase-method bypass attempt.
2026-07-28 08:50:24 +02:00
2026-01-18 22:45:29 +01:00
2026-07-28 08:50:24 +02:00
2023-07-04 11:45:25 +02:00
2023-05-28 23:10:36 +02:00
2026-07-27 20:09:43 +02:00
2026-07-27 20:09:43 +02:00

Icon of a filament spool

Keep track of your inventory of 3D-printer filament spools.

Spoolman is a self-hosted web service designed to help you efficiently manage your 3D printer filament spools and monitor their usage. It acts as a centralized database that seamlessly integrates with popular 3D printing software like OctoPrint and Klipper/Moonraker. When connected, it automatically updates spool weights as printing progresses, giving you real-time insights into filament usage.

Static Badge GitHub Release

Features

  • Filament Management: Keep comprehensive records of filament types, manufacturers, and individual spools.
  • API Integration: The REST API allows easy integration with other software, facilitating automated workflows and data exchange.
  • Real-Time Updates: Stay informed with live spool updates through Websockets, providing immediate feedback during printing operations.
  • Central Filament Database: A community-supported database of manufacturers and filaments simplify adding new spools to your inventory. Contribute by heading to SpoolmanDB.
  • Web-Based Client: Spoolman includes a built-in web client that lets you manage data effortlessly:
    • View, create, edit, and delete filament data.
    • Add custom fields to tailor information to your specific needs.
    • Print labels with QR codes for easy spool identification and tracking.
    • Contribute to its translation into 18 languages via Weblate.
  • Database Support: SQLite, PostgreSQL, MySQL, and CockroachDB.
  • Multi-Printer Management: Handles spool updates from several printers simultaneously.
  • Advanced Monitoring: Integrate with Prometheus for detailed historical analysis of filament usage, helping you track and optimize your printing processes. See the Wiki for instructions on how to set it up.

Spoolman integrates with:

Web client preview: image

Installation

Please see the Installation page on the Wiki for details how to install Spoolman.

S
Description
Keep track of your inventory of 3D-printer filament spools.
Readme MIT
15 MiB
0 Stars 1 Watchers 0 Forks
v0.27.0
Latest
2026-09-25 08:35:18 -05:00
Languages
Python 37.8%
TypeScript 37.4%
Svelte 23%
JavaScript 0.7%
CSS 0.4%
Other 0.7%