diff --git a/README.md b/README.md index 6a9f52b..a855806 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,8 @@ until the owner explicitly authorizes it.** Test design: [REAL_DEVICE_TEST.md](d ## Security -All protected /api/v1 capabilities use Frame Flow Bearer auth and scope checks. +Protected /api/v1 capabilities accept an administrator account session, or external +Frame Flow Bearer auth with scope checks. SQLite stores token hashes. Device keys live only in env/secret and runtime memory. Browser login uses SQLite accounts with salted scrypt password hashes and revocable, HttpOnly/SameSite=Strict cookies (30 days when remembered, 12 hours otherwise). diff --git a/tests/test_images.py b/tests/test_images.py index 47f8d49..527fda4 100644 --- a/tests/test_images.py +++ b/tests/test_images.py @@ -68,3 +68,18 @@ def test_url_default_disabled(service): def test_url_ssrf(service, url): with pytest.raises(FlowError): service.assets.fetch_url(url) + + +@pytest.mark.parametrize( + "template", + ["daily-dashboard", "weather", "calendar", "quote", "photo-text", "system-alert"], +) +def test_template_grayscale(service, template): + img = Image.open(BytesIO(service.renderer.render(template, {}, "grayscale"))) + assert img.size == (1200, 1600) + assert len(set(img.getpixel((600, 800)))) == 1 + + +def test_calendar_rejects_invalid_date(service): + with pytest.raises(FlowError): + service.renderer.render("calendar", {"date": "not-a-date"})