Standalone Shonar Desktop: vendor portable sources + local engine; decouple from ~/Projects/Shonar
- shared/ = portable Android-origin sources vendored from deferred/desktop-server (app/build.gradle.kts srcDir repointed; PlaybackController.kt excluded as Android-only) - backend/ = bundled-lite engine (SQLite + inline queue); .venv symlinked from the old checkout, PYTHONPATH pins THIS backend's code over any editable install - repoRoot() resolves this project dir (env SHONAR_REPO still wins); desktop-dev.sh watches shared/ + backend/ - Verified: :app:compileKotlin + :app:test green (23 tests); engine boots on :8010, self-migrates, /healthz ok
This commit is contained in:
commit
76c867fca4
136 changed files with 21099 additions and 0 deletions
35
backend/tests/test_provider_info.py
Normal file
35
backend/tests/test_provider_info.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
"""provider-info handshake tests (P2/P3 client probing depends on this)."""
|
||||
|
||||
|
||||
async def test_provider_info_identifies_shonar(client):
|
||||
r = await client.get("/api/v1/provider-info")
|
||||
assert r.status_code == 200
|
||||
body = r.json()
|
||||
assert body["kind"] == "shonar"
|
||||
assert body["api_version"] == "v1"
|
||||
caps = body["capabilities"]
|
||||
assert caps["chunked_upload"] is True
|
||||
assert caps["account_deletion"] is True
|
||||
# test env configures no AI providers -> flags must be false
|
||||
assert caps["server_transcription"] is False
|
||||
assert caps["server_summary"] is False
|
||||
assert body["storage_backend"] in ("local", "s3")
|
||||
|
||||
|
||||
async def test_provider_info_leaks_no_paths_or_secrets(client):
|
||||
r = await client.get("/api/v1/provider-info")
|
||||
body = r.json()
|
||||
# every string value must be a bare identifier, never a filesystem path
|
||||
def walk(v):
|
||||
if isinstance(v, str):
|
||||
assert not v.startswith("/"), f"path-like value in handshake: {v!r}"
|
||||
low = v.lower()
|
||||
for banned in ("secret", "token", "password", "key"):
|
||||
assert banned not in low
|
||||
elif isinstance(v, dict):
|
||||
for x in v.values():
|
||||
walk(x)
|
||||
elif isinstance(v, list):
|
||||
for x in v:
|
||||
walk(x)
|
||||
walk(body)
|
||||
Loading…
Add table
Add a link
Reference in a new issue