Skip to content

DreamLoop v0.2.1

Latest

Choose a tag to compare

@saime428 saime428 released this 27 Jul 13:52
7b06796

If you installed v0.2.0 and run DreamLoop on anything but loopback, upgrade. v0.2.0 was tagged before the audit fixes merged, so it shipped without the authentication fix.

A six-dimension audit of v0.2.0 (architecture, code quality, security, frontend, tests, docs) produced 31 findings. The fixes landed after the v0.2.0 release was cut, so v0.2.0 does not contain them.

Security

  • Binding a non-loopback host (--host 0.0.0.0, the Docker demo) now enables token authentication, prints the access URL at startup, and accepts the token via cookie, header, or query. Previously the app had no authentication at all and relied on a spoofable Host header, so a published Docker port exposed every dream to the local network and let anyone repoint the AI provider.
  • Refuse header-less writes from non-loopback clients unless they authenticate. --no-auth / DREAMLOOP_NO_AUTH=1 keeps them open, because that mode has no token to offer a scripted client.
  • Hand ?token= to a cookie and redirect it out of page URLs, and redact it from uvicorn's access log, which records full query strings.
  • Compare tokens as bytes: compare_digest raises TypeError on non-ASCII input, which turned a bad token into a 500.
  • Return JSON rather than HTML for 401s on /api/ paths.

Data safety

  • migrate_analysis_table dropped the renamed old table unconditionally, so an analysis table missing a required column lost every stored analysis silently. Unmigratable rows are now preserved in a backup table, and the migration paths have test coverage.
  • Recover from a corrupt config.json instead of returning 500 from every page, including the settings page needed to fix it. Both config writers now replace the file atomically.
  • Wrap invalid model JSON as AnalysisIncomplete; a truncated or fenced response from a local model surfaced as a 500.

Fixes

  • POST /drafts/analyze stores the draft and redirects, so a refresh no longer re-runs a slow LLM call and the URL survives navigation.
  • Log the three swallowed exceptions in web.py (the project had no logging at all), stop reporting a missing dream as a provider error, and surface image-generation failures to the user.
  • Map import errors to 400/404 instead of 500.
  • init() is idempotent; every DreamLoop method re-ran the full migration.
  • feedback_summary uses one join instead of a query per feedback row.
  • Clamp dream text in cards, fix heat-cell contrast to WCAG AA, add a skip link, reset loading buttons on bfcache restore, and preload the bundled fonts.
  • Add SECURITY.md, issue and PR templates, and document that .dreamloop/ is created relative to the working directory.
  • 212 tests pass; coverage 87% -> 91%.

Install

pipx install dreamloop==0.2.1
docker run --rm -p 127.0.0.1:8765:8765 ghcr.io/saime428/dreamloop:0.2.1

Full diff: v0.2.0...v0.2.1