Attribute Devii AI spend to its invoking action, fix quiz question-at-a-time review, DB API/isslop result routes, workspace docs, and drop redundant docstrings

- Route Devii-driven AI gateway cost to the action/tool that triggered
  it instead of a blanket "internal" bucket, so per-feature AI spend
  is attributable.
- Fix the quiz attempt review to show one previously-answered question
  at a time instead of all of them at once, and stop a quiz endpoint
  linked from the quiz flow from responding with raw JSON.
- Add DB API async query result route and AI Usage Analyzer annotated
  source/media routes, with traversal-safe uid/path handling and
  matching tests.
- Add Code Farm action audit logging (plant/harvest/buy-plot/upgrade/
  fertilize) and related admin workspace/services/trash/gateway route
  and doc touch-ups.
- Drop redundant docstrings from access_tokens.py per the no-comments
  convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VL9Xn57W5UR3HZbbuuzxdK
This commit is contained in:
2026-09-03 08:47:57 +02:00
co-authored by Claude Sonnet 5
parent 9d7b3db314
commit 57087536e5
76 changed files with 805 additions and 338 deletions
+75
View File
@@ -1,8 +1,13 @@
# retoor <retoor@molodetz.nl>
import json
import shutil
from datetime import datetime, timezone
import pytest
from starlette.websockets import WebSocketDisconnect
from devplacepy.config import DBAPI_DIR
from devplacepy.services.manager import service_manager
@@ -74,3 +79,73 @@ def test_ws_non_owner_retries(client, auth):
assert info.value.code == 4013
finally:
service_manager.set_lock_owner(True)
def test_result_route_serves_the_persisted_rows(client, auth):
enqueued = client.post(
"/dbapi/query/async", json={"sql": "SELECT 1 AS n"}, headers=auth
)
uid = enqueued.json()["uid"]
output_dir = DBAPI_DIR / uid
output_dir.mkdir(parents=True, exist_ok=True)
result = {
"sql": "SELECT 1 AS n",
"row_count": 1,
"truncated": False,
"suspicious": [],
"rows": [{"n": 1}],
}
(output_dir / "result.json").write_text(json.dumps(result), encoding="utf-8")
try:
response = client.get(f"/dbapi/query/{uid}/result", headers=auth)
assert response.status_code == 200, response.text
assert response.json()["rows"] == [{"n": 1}]
finally:
shutil.rmtree(output_dir, ignore_errors=True)
def test_result_route_404s_without_a_written_result(client, auth):
enqueued = client.post(
"/dbapi/query/async", json={"sql": "SELECT 1 AS n"}, headers=auth
)
uid = enqueued.json()["uid"]
response = client.get(f"/dbapi/query/{uid}/result", headers=auth)
assert response.status_code == 404
def test_result_route_rejects_a_traversal_uid(client, auth):
from devplacepy.database import get_table
evil_uid = ".."
now = datetime.now(timezone.utc).isoformat()
get_table("jobs").insert(
{
"uid": evil_uid,
"kind": "dbquery",
"status": "done",
"owner_kind": "user",
"owner_id": "traversal-owner",
"preferred_name": "",
"payload": "{}",
"result": "{}",
"error": "",
"retry_count": 0,
"created_at": now,
"started_at": now,
"completed_at": now,
"updated_at": now,
"duration_ms": 0,
"last_accessed_at": "",
"expires_at": "",
"bytes_in": 0,
"bytes_out": 0,
"item_count": 0,
}
)
escape_target = DBAPI_DIR.parent / "result.json"
try:
response = client.get(f"/dbapi/query/{evil_uid}/result", headers=auth)
assert response.status_code in (400, 404), response.text
assert not escape_target.exists()
finally:
get_table("jobs").delete(uid=evil_uid)
+11 -7
View File
@@ -61,8 +61,10 @@ def _instance(**overrides) -> dict:
def test_open_workspace_requires_enabled_setting():
set_setting("workspace_enabled", "0")
assert can_open_workspace(_project(), {"uid": OWNER, "role": "Member"}) is False
set_setting("workspace_enabled", "1")
try:
assert can_open_workspace(_project(), {"uid": OWNER, "role": "Member"}) is False
finally:
set_setting("workspace_enabled", "1")
assert can_open_workspace(_project(), {"uid": OWNER, "role": "Member"}) is True
@@ -98,11 +100,13 @@ def test_create_or_resume_is_idempotent():
def test_workspace_quota_blocks_beyond_limit():
set_setting("workspace_max_per_user", "1")
user = {"uid": OWNER, "username": "owner"}
run_async(provision.ensure(_project("p-a"), user))
with pytest.raises(WorkspaceError):
run_async(provision.ensure(_project("p-b"), user))
set_setting("workspace_max_per_user", "2")
try:
user = {"uid": OWNER, "username": "owner"}
run_async(provision.ensure(_project("p-a"), user))
with pytest.raises(WorkspaceError):
run_async(provision.ensure(_project("p-b"), user))
finally:
set_setting("workspace_max_per_user", "2")
def test_tunnel_revives_rather_than_duplicates():
+103
View File
@@ -1,11 +1,14 @@
# retoor <retoor@molodetz.nl>
import time
import uuid
import requests
from tests.conftest import BASE_URL
from devplacepy.database import get_table, refresh_snapshot
from devplacepy.services.jobs.isslop import store
from devplacepy.utils import generate_uid
_counter_isslop = [0]
@@ -192,3 +195,103 @@ def test_guest_history_claimed_on_signup(app_server):
assert get_table("isslop_analyses").count(uid=uid) == 1
finally:
_clear_isslop_data()
def test_source_route_serves_the_annotated_file(app_server):
uid = generate_uid()
store.create_analysis(uid, "https://github.com/owner/repository", "guest", "src-owner")
source_name = "s" + uuid.uuid4().hex[:16] + ".txt"
store.insert_file_result(
uid,
{
"path": "app.py",
"language": "python",
"lines": 1,
"origin_score": 0.1,
"quality_deficit_score": 0.1,
"category": "human-authored",
"signals": "[]",
"source": source_name,
},
)
media_dir = store.media_dir_for(uid)
media_dir.mkdir(parents=True, exist_ok=True)
(media_dir / source_name).write_text("print('hello')\n", encoding="utf-8")
try:
r = requests.get(
f"{BASE_URL}/tools/isslop/{uid}/source",
params={"path": "app.py"},
headers=_json_headers(),
)
assert r.status_code == 200, r.text
body = r.json()
assert "print" in body["source"]
assert body["path"] == "app.py"
finally:
store.purge_analysis(uid)
def test_source_route_rejects_an_unsafe_source_token(app_server):
uid = generate_uid()
store.create_analysis(uid, "https://github.com/owner/repository", "guest", "src-traversal-owner")
store.insert_file_result(
uid,
{
"path": "app.py",
"language": "python",
"lines": 1,
"origin_score": 0.0,
"quality_deficit_score": 0.0,
"category": "human-authored",
"signals": "[]",
"source": "../../../../etc/passwd",
},
)
try:
r = requests.get(
f"{BASE_URL}/tools/isslop/{uid}/source",
params={"path": "app.py"},
headers=_json_headers(),
)
assert r.status_code == 404
finally:
store.purge_analysis(uid)
def test_media_route_serves_a_thumbnail(app_server):
uid = generate_uid()
store.create_analysis(uid, "https://github.com/owner/repository", "guest", "media-owner")
name = uuid.uuid4().hex[:16] + ".webp"
store.insert_image_result(
uid,
{
"path": "assets/hero.png",
"ai_probability": 0.2,
"grade": "n/a",
"verdict": "uncertain",
"image_kind": "image",
"tells": "[]",
"description": "",
"thumb": name,
},
)
media_dir = store.media_dir_for(uid)
media_dir.mkdir(parents=True, exist_ok=True)
(media_dir / name).write_bytes(b"not-a-real-webp-but-bytes")
try:
r = requests.get(f"{BASE_URL}/tools/isslop/{uid}/media/{name}")
assert r.status_code == 200, r.text
assert r.headers["content-type"].startswith("image/webp")
assert r.content == b"not-a-real-webp-but-bytes"
finally:
store.purge_analysis(uid)
def test_media_route_rejects_a_name_outside_the_hex_pattern(app_server):
uid = generate_uid()
store.create_analysis(uid, "https://github.com/owner/repository", "guest", "media-traversal-owner")
try:
r = requests.get(f"{BASE_URL}/tools/isslop/{uid}/media/..%2fetc%2fpasswd")
assert r.status_code == 404, r.text
finally:
store.purge_analysis(uid)
+3 -3
View File
@@ -77,7 +77,7 @@ def test_formdata_list_field_mixed_empty_and_real():
def test_formdata_literal_fields_are_scalar():
"""Literal-typed fields (e.g. target_type in CommentForm) are treated as
scalars the origin check must not crash on typing.Literal."""
scalars - the origin check must not crash on typing.Literal."""
fd = FormData([
("content", "Great comment here!"),
("target_type", "post"),
@@ -108,14 +108,14 @@ def test_formdata_literal_form_from_browser():
def test_formdata_vote_form():
"""value: int field with form data string '1' is kept for Pydantic coerce."""
"""value: int field with form data - string '1' is kept for Pydantic coerce."""
fd = FormData([("value", "1")])
body = _formdata_to_dict(fd, VoteForm)
assert body["value"] == "1" # Pydantic coerces str→int
def test_formdata_issue_status_literal():
"""IssueStatusForm has Literal['open','closed'] must not crash."""
"""IssueStatusForm has Literal['open','closed'] - must not crash."""
fd = FormData([("status", "open")])
body = _formdata_to_dict(fd, IssueStatusForm)
assert body["status"] == "open"
+5 -5
View File
@@ -81,7 +81,7 @@ def test_issue_token_returns_expected_fields(local_db):
def test_resolve_token_valid(local_db):
"""Issue a token then resolve it returns the correct user."""
"""Issue a token then resolve it - returns the correct user."""
uid = _seed_user("resolver", "resolver@test.dev")
user = get_table("users").find_one(uid=uid)
@@ -239,10 +239,10 @@ def test_resolve_user_access_token_priority_after_api_key(local_db):
"""api_key user wins over access token when the same string matches both."""
shared_key = secrets.token_hex(32) # 64-char hex
# User A owns the api_key
# User A - owns the api_key
uid_a = _seed_user("apikey_winner", "apikeywinner@test.dev", api_key=shared_key)
# User B owns an access token with the same string as the key
# User B - owns an access token with the same string as the key
uid_b = _seed_user("acctok_loser", "acctokloser@test.dev")
get_table("access_tokens").insert(
{
@@ -257,14 +257,14 @@ def test_resolve_user_access_token_priority_after_api_key(local_db):
}
)
# X-API-KEY path api_key user wins
# X-API-KEY path - api_key user wins
request = _MockRequest(headers={"X-API-KEY": shared_key})
resolved = _resolve_user(request)
assert resolved is not None
assert resolved["uid"] == uid_a
assert resolved["username"] == "apikey_winner"
# Bearer path api_key user wins
# Bearer path - api_key user wins
request2 = _MockRequest(headers={"Authorization": f"Bearer {shared_key}"})
resolved2 = _resolve_user(request2)
assert resolved2 is not None
+6 -6
View File
@@ -68,7 +68,7 @@ def _seed_token(user_uid, key, expire_time):
# ── resolve_user_by_key tests ────────────────────────────────────────────────
def test_resolve_user_by_key_valid(local_db):
"""Create a devrant token for a user, then resolve it by key the right user is returned."""
"""Create a devrant token for a user, then resolve it by key - the right user is returned."""
uid = _seed_user("dr_valid", "drvalid@test.dev")
token_key = secrets.token_hex(20)
expire_time = int(datetime.now(timezone.utc).timestamp()) + 86400
@@ -81,13 +81,13 @@ def test_resolve_user_by_key_valid(local_db):
def test_resolve_user_by_key_not_found(local_db):
"""Look up a random key that has no token verify None."""
"""Look up a random key that has no token - verify None."""
random_key = secrets.token_hex(20)
assert resolve_user_by_key(random_key) is None
def test_resolve_user_by_key_expired(local_db):
"""Create an expired token resolve returns None."""
"""Create an expired token - resolve returns None."""
uid = _seed_user("dr_expired", "drexpired@test.dev")
token_key = secrets.token_hex(20)
expire_time = int(datetime.now(timezone.utc).timestamp()) - 86400
@@ -97,7 +97,7 @@ def test_resolve_user_by_key_expired(local_db):
def test_resolve_user_by_key_inactive_user(local_db):
"""Create a token for an inactive user resolve returns None."""
"""Create a token for an inactive user - resolve returns None."""
uid = _seed_user("dr_inactive", "drinactive@test.dev", is_active=False)
token_key = secrets.token_hex(20)
expire_time = int(datetime.now(timezone.utc).timestamp()) + 86400
@@ -162,10 +162,10 @@ def test_resolve_user_prefers_api_key_over_devrant(local_db):
"""If a key matches both an api_key and a devrant token, the api_key user wins."""
shared_key = secrets.token_hex(20)
# User A owns the api_key
# User A - owns the api_key
uid_a = _seed_user("api_key_owner", "apikey@test.dev", api_key=shared_key)
# User B owns the devrant token with the same key
# User B - owns the devrant token with the same key
uid_b = _seed_user("devrant_owner", "drowner@test.dev")
expire_time = int(datetime.now(timezone.utc).timestamp()) + 86400
_seed_token(uid_b, shared_key, expire_time)