Run the backend suite on Dev Postgres instead of isolated SQLite.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
709370da93
commit
36b9a2e424
|
|
@ -7,21 +7,15 @@ on:
|
||||||
branches: [develop]
|
branches: [develop]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend-sqlite:
|
backend-postgres:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Backend tests against isolated SQLite
|
- name: Backend tests against Dev Postgres (kansho_test)
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
EVENT_REF="${{ github.ref_name }}"
|
|
||||||
BASE_REF="${{ github.base_ref }}"
|
|
||||||
APP_DIR="/home/lars/docker/kansho"
|
|
||||||
COMPOSE_FILE="docker-compose.yml"
|
|
||||||
if [ "$EVENT_REF" = "develop" ] || [ "$BASE_REF" = "develop" ]; then
|
|
||||||
APP_DIR="/home/lars/docker/kansho-dev"
|
APP_DIR="/home/lars/docker/kansho-dev"
|
||||||
COMPOSE_FILE="docker-compose.dev-env.yml"
|
COMPOSE_FILE="docker-compose.dev-env.yml"
|
||||||
fi
|
echo "backend tests always use Dev Postgres (${APP_DIR})"
|
||||||
echo "tests against ${APP_DIR} (${COMPOSE_FILE})"
|
|
||||||
cd "$APP_DIR"
|
cd "$APP_DIR"
|
||||||
for i in $(seq 1 60); do
|
for i in $(seq 1 60); do
|
||||||
if docker compose -f "$COMPOSE_FILE" exec -T backend true 2>/dev/null; then
|
if docker compose -f "$COMPOSE_FILE" exec -T backend true 2>/dev/null; then
|
||||||
|
|
@ -35,15 +29,26 @@ jobs:
|
||||||
fi
|
fi
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
|
PGUSER="$(docker compose -f "$COMPOSE_FILE" exec -T postgres printenv POSTGRES_USER | tr -d '\r')"
|
||||||
|
echo "test database kansho_test on the existing Dev Postgres (owner ${PGUSER})"
|
||||||
|
docker compose -f "$COMPOSE_FILE" exec -T postgres \
|
||||||
|
psql -U "$PGUSER" -d postgres -v ON_ERROR_STOP=1 \
|
||||||
|
-c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'kansho_test' AND pid <> pg_backend_pid();"
|
||||||
|
docker compose -f "$COMPOSE_FILE" exec -T postgres \
|
||||||
|
psql -U "$PGUSER" -d postgres -v ON_ERROR_STOP=1 \
|
||||||
|
-c "DROP DATABASE IF EXISTS kansho_test;"
|
||||||
|
docker compose -f "$COMPOSE_FILE" exec -T postgres \
|
||||||
|
psql -U "$PGUSER" -d postgres -v ON_ERROR_STOP=1 \
|
||||||
|
-c "CREATE DATABASE kansho_test OWNER ${PGUSER};"
|
||||||
docker compose -f "$COMPOSE_FILE" exec -T \
|
docker compose -f "$COMPOSE_FILE" exec -T \
|
||||||
-e KANSHO_DB_BACKEND=sqlite \
|
-e KANSHO_DB_BACKEND=postgres \
|
||||||
-e KANSHO_DB_PATH=/tmp/kansho-ci.sqlite \
|
-e DB_NAME=kansho_test \
|
||||||
-e KANSHO_PROVIDER_KEY= \
|
-e KANSHO_PROVIDER_KEY= \
|
||||||
-e KANSHO_DETECT_PROVIDER_KEY= \
|
-e KANSHO_DETECT_PROVIDER_KEY= \
|
||||||
-e PYTHONUTF8=1 \
|
-e PYTHONUTF8=1 \
|
||||||
backend sh -lc '
|
backend sh -lc '
|
||||||
set -e
|
set -e
|
||||||
rm -f /tmp/kansho-ci.sqlite
|
unset KANSHO_DB_PATH
|
||||||
for test in tests/test_*.py; do
|
for test in tests/test_*.py; do
|
||||||
echo "=== $test ==="
|
echo "=== $test ==="
|
||||||
python "$test"
|
python "$test"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
"""Translate SQLite-oriented SQL so the same stores can run against PostgreSQL.
|
"""Translate SQLite-oriented SQL so the same stores can run against PostgreSQL.
|
||||||
|
|
||||||
Local Windows development and tests keep SQLite. Docker/Server set
|
Windows without Docker still uses SQLite for the running app. Docker/Server and
|
||||||
KANSHO_DB_BACKEND=postgres. Identity, keys and journal bodies are not logged here.
|
the test suite use PostgreSQL (`KANSHO_DB_BACKEND=postgres`). Identity, keys and
|
||||||
|
journal bodies are not logged here.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
@ -29,7 +30,8 @@ def use_postgres() -> bool:
|
||||||
"""Decide the engine at connect time, not at import time.
|
"""Decide the engine at connect time, not at import time.
|
||||||
|
|
||||||
Explicit KANSHO_DB_BACKEND wins. KANSHO_DB_PATH without an explicit postgres
|
Explicit KANSHO_DB_BACKEND wins. KANSHO_DB_PATH without an explicit postgres
|
||||||
backend keeps tests on isolated SQLite even inside a Compose container.
|
backend keeps the Windows local app on SQLite. Tests set postgres and DB_NAME
|
||||||
|
kansho_test on the Dev instance, never kansho_dev.
|
||||||
"""
|
"""
|
||||||
raw = (os.environ.get("KANSHO_DB_BACKEND") or "").strip().lower()
|
raw = (os.environ.get("KANSHO_DB_BACKEND") or "").strip().lower()
|
||||||
if raw in {"sqlite", "sqlite3"}:
|
if raw in {"sqlite", "sqlite3"}:
|
||||||
|
|
|
||||||
83
backend/tests/harness.py
Normal file
83
backend/tests/harness.py
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
"""Postgres test engine on the existing Dev instance.
|
||||||
|
|
||||||
|
Two Compose Postgres instances exist: Dev and Prod. Tests use the Dev
|
||||||
|
instance, database `kansho_test` beside `kansho_dev`. That is not a third
|
||||||
|
server. The suite drops and recreates `public` on the test database only,
|
||||||
|
so personal Dev/Prod journals are not wiped.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
LIVE_DB_NAMES = frozenset(
|
||||||
|
{
|
||||||
|
"kansho",
|
||||||
|
"kansho_dev",
|
||||||
|
"postgres",
|
||||||
|
"template0",
|
||||||
|
"template1",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _backend() -> str:
|
||||||
|
return (os.environ.get("KANSHO_DB_BACKEND") or "").strip().lower()
|
||||||
|
|
||||||
|
|
||||||
|
def _db_name() -> str:
|
||||||
|
return (os.environ.get("DB_NAME") or "").strip()
|
||||||
|
|
||||||
|
|
||||||
|
def _require_test_database() -> None:
|
||||||
|
backend = _backend()
|
||||||
|
if backend not in {"postgres", "postgresql", "pg"}:
|
||||||
|
raise SystemExit(
|
||||||
|
"Backend-Tests laufen gegen PostgreSQL (KANSHO_DB_BACKEND=postgres), "
|
||||||
|
"dieselbe Engine wie Dev und Prod. SQLite-Testdateien sind abgelöst. "
|
||||||
|
"Gitea nutzt auf der Dev-Postgres die Datenbank kansho_test "
|
||||||
|
"(neben kansho_dev, keine dritte Instanz)."
|
||||||
|
)
|
||||||
|
name = _db_name().lower()
|
||||||
|
if not name:
|
||||||
|
raise SystemExit(
|
||||||
|
"DB_NAME fehlt. Tests nutzen auf der Dev-Postgres die Datenbank kansho_test, "
|
||||||
|
"nicht kansho_dev."
|
||||||
|
)
|
||||||
|
if name in LIVE_DB_NAMES or not name.endswith("_test"):
|
||||||
|
raise SystemExit(
|
||||||
|
f"DB_NAME={_db_name()!r} ist für Tests gesperrt. "
|
||||||
|
"Die Suite setzt das Schema zurück und darf daher nicht kansho oder kansho_dev treffen."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def reset_postgres_schema() -> None:
|
||||||
|
import psycopg
|
||||||
|
|
||||||
|
from sql_compat import postgres_connect_kwargs
|
||||||
|
|
||||||
|
kwargs = postgres_connect_kwargs()
|
||||||
|
if "conninfo" in kwargs:
|
||||||
|
conn = psycopg.connect(kwargs["conninfo"], autocommit=True)
|
||||||
|
else:
|
||||||
|
conn = psycopg.connect(autocommit=True, **kwargs)
|
||||||
|
try:
|
||||||
|
conn.execute("DROP SCHEMA IF EXISTS public CASCADE")
|
||||||
|
conn.execute("CREATE SCHEMA public")
|
||||||
|
conn.execute("GRANT ALL ON SCHEMA public TO PUBLIC")
|
||||||
|
conn.execute("GRANT ALL ON SCHEMA public TO CURRENT_USER")
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
def configure_test_engine() -> None:
|
||||||
|
"""Call after sys.path includes backend/, before importing main/db."""
|
||||||
|
os.environ.setdefault("KANSHO_PROVIDER_KEY", "")
|
||||||
|
os.environ.setdefault("KANSHO_DETECT_PROVIDER_KEY", "")
|
||||||
|
os.environ.pop("KANSHO_DB_PATH", None)
|
||||||
|
_require_test_database()
|
||||||
|
try:
|
||||||
|
reset_postgres_schema()
|
||||||
|
except Exception as exc: # noqa: BLE001 — fail before the suite touches a live DB
|
||||||
|
print(f"Postgres-Testschema konnte nicht zurückgesetzt werden: {exc}", file=sys.stderr)
|
||||||
|
raise SystemExit(1) from exc
|
||||||
|
|
@ -11,10 +11,12 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-arch-correction-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from db import get_db, migrate_journal_source_refs
|
from db import get_db, migrate_journal_source_refs
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,13 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||||
REPO = ROOT.parent
|
REPO = ROOT.parent
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-debug-persist-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-debug-persist-media")
|
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-debug-persist-media")
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-detect-contract-retry-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from debug_store import persist_engine_error, sanitize
|
from debug_store import persist_engine_error, sanitize
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-dialogue-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from main import app
|
from main import app
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-frame-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_PROVIDER_KEY"] = ""
|
os.environ["KANSHO_PROVIDER_KEY"] = ""
|
||||||
os.environ["KANSHO_DETECT_PROVIDER_KEY"] = ""
|
os.environ["KANSHO_DETECT_PROVIDER_KEY"] = ""
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from main import app
|
from main import app
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-identity-registry-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from identity_store import STATUS_LEGACY, list_confirmed_identities, list_registry
|
from identity_store import STATUS_LEGACY, list_confirmed_identities, list_registry
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,12 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-journal-budget-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from main import app
|
from main import app
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-journal-editorial-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from db import get_db, init_db
|
from db import get_db, init_db
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,12 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-journal-eval-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from db import init_db
|
from db import init_db
|
||||||
from journal_editorial import GENERATE_SEED_REVISION
|
from journal_editorial import GENERATE_SEED_REVISION
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||||
FRONTEND = ROOT.parent / "frontend"
|
FRONTEND = ROOT.parent / "frontend"
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-journal-guidelines-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from db import get_db, init_db
|
from db import get_db, init_db
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,12 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-journal-narration-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from db import get_db, init_db
|
from db import get_db, init_db
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,13 @@ from datetime import date
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-opening-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-opening-media")
|
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-opening-media")
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-journal-style-context-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from db import get_db, init_db
|
from db import get_db, init_db
|
||||||
|
|
@ -211,7 +213,6 @@ def main() -> None:
|
||||||
test_compile_flags()
|
test_compile_flags()
|
||||||
test_budget_omission_in_effective_trace()
|
test_budget_omission_in_effective_trace()
|
||||||
|
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
init_db()
|
init_db()
|
||||||
reset_debug()
|
reset_debug()
|
||||||
with TestClient(app) as client:
|
with TestClient(app) as client:
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-journal-legacy-immutable-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from db import get_db, init_db
|
from db import get_db, init_db
|
||||||
|
|
@ -270,7 +272,6 @@ def test_later_semantic_seed_creates_successor() -> None:
|
||||||
|
|
||||||
|
|
||||||
def test_legacy_generate_trace_and_prompt() -> None:
|
def test_legacy_generate_trace_and_prompt() -> None:
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
init_db()
|
init_db()
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
setup = client.post(
|
setup = client.post(
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-trash-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-trash-media")
|
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-trash-media")
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-model-catalog-test.sqlite")
|
os.environ.setdefault("KANSHO_PROVIDER_KEY", "")
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
os.environ.setdefault("KANSHO_DETECT_PROVIDER_KEY", "")
|
||||||
|
Path(tempfile.gettempdir()).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
from model_catalog import (
|
from model_catalog import (
|
||||||
ModelWindow,
|
ModelWindow,
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-mvp-journal-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-mvp-journal-media")
|
os.environ["KANSHO_MEDIA_ROOT"] = str(Path(tempfile.gettempdir()) / "kansho-mvp-journal-media")
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
Path(os.environ["KANSHO_MEDIA_ROOT"]).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,12 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-privacy-detect-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from identity_store import (
|
from identity_store import (
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,12 @@ from unittest.mock import patch
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-privacy-manifest-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from entity_detect import install_test_spans, reset_detect_test_hooks
|
from entity_detect import install_test_spans, reset_detect_test_hooks
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,12 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||||
REPO = ROOT.parent
|
REPO = ROOT.parent
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-privacy-response-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from identity_store import list_mappings, remember_mapping
|
from identity_store import list_mappings, remember_mapping
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,12 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-profile-governance-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from main import app
|
from main import app
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,12 @@ from pathlib import Path
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-profile-review-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from main import app
|
from main import app
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@ import httpx
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = str(Path(tempfile.gettempdir()) / "kansho-profile-review-errors-test.sqlite")
|
from tests.harness import configure_test_engine
|
||||||
|
|
||||||
|
configure_test_engine()
|
||||||
|
|
||||||
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
|
||||||
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
os.environ["KANSHO_FAKE_DETECT"] = "1"
|
||||||
Path(os.environ["KANSHO_DB_PATH"]).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from engine import EngineError
|
from engine import EngineError
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,13 @@
|
||||||
"""Intent-neutral provenance verification. Run from backend/: python tests/test_provenance.py"""
|
"""Intent-neutral provenance verification. Run from backend/: python tests/test_provenance.py"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
|
||||||
import threading
|
import threading
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
sys.path.insert(0, str(ROOT))
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
os.environ.setdefault(
|
|
||||||
"KANSHO_DB_PATH",
|
|
||||||
str(Path(tempfile.gettempdir()) / "kansho-provenance-test.sqlite"),
|
|
||||||
)
|
|
||||||
|
|
||||||
from provenance import (
|
from provenance import (
|
||||||
COVERAGE_ALL_SELECTED_SOURCES,
|
COVERAGE_ALL_SELECTED_SOURCES,
|
||||||
COVERAGE_SELECTED_EVIDENCE,
|
COVERAGE_SELECTED_EVIDENCE,
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ def main() -> None:
|
||||||
|
|
||||||
os.environ["KANSHO_DB_PATH"] = "/tmp/isolated.sqlite"
|
os.environ["KANSHO_DB_PATH"] = "/tmp/isolated.sqlite"
|
||||||
os.environ["DB_HOST"] = "postgres"
|
os.environ["DB_HOST"] = "postgres"
|
||||||
expect(use_postgres() is False, "KANSHO_DB_PATH keeps tests on sqlite")
|
expect(use_postgres() is False, "KANSHO_DB_PATH without backend keeps Windows local on sqlite")
|
||||||
os.environ["KANSHO_DB_BACKEND"] = "postgres"
|
os.environ["KANSHO_DB_BACKEND"] = "postgres"
|
||||||
expect(use_postgres() is True, "explicit postgres backend wins")
|
expect(use_postgres() is True, "explicit postgres backend wins")
|
||||||
os.environ["KANSHO_DB_BACKEND"] = "sqlite"
|
os.environ["KANSHO_DB_BACKEND"] = "sqlite"
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ Watchtower bleibt aus.
|
||||||
|----------|---------|--------|
|
|----------|---------|--------|
|
||||||
| `deploy-dev.yml` | Push `develop` | Deploy nach `/home/lars/docker/kansho-dev`, Health `localhost:8096` |
|
| `deploy-dev.yml` | Push `develop` | Deploy nach `/home/lars/docker/kansho-dev`, Health `localhost:8096` |
|
||||||
| `deploy-prod.yml` | Push `main` | Deploy nach `/home/lars/docker/kansho`, Health `localhost:8005` |
|
| `deploy-prod.yml` | Push `main` | Deploy nach `/home/lars/docker/kansho`, Health `localhost:8005` |
|
||||||
| `test.yml` | Push `develop`/`main`, PR `develop` | Backend-Tests isoliert SQLite im Container plus Frontend-Build. Keine Live-Provider-Keys. |
|
| `test.yml` | Push `develop`/`main`, PR `develop` | Backend-Tests auf der bestehenden Compose-Postgres in DB `kansho_test` (nicht Live-`kansho_dev`) plus Frontend-Build. Keine Live-Provider-Keys. |
|
||||||
|
|
||||||
Prod nur über Merge `develop` → `main`, kein direkter Prod-Schreibzugriff.
|
Prod nur über Merge `develop` → `main`, kein direkter Prod-Schreibzugriff.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,8 @@ Entsprechen den Interview-Leitfragen Phase F1/F4 und werden hier nicht vorab bea
|
||||||
|
|
||||||
Additiv, ohne das Fachschema vorzuziehen:
|
Additiv, ohne das Fachschema vorzuziehen:
|
||||||
|
|
||||||
- Windows-Checkout und `test-mvp.ps1`: SQLite unter `backend/data/` (gitignoriert).
|
- Windows-Checkout: SQLite unter `backend/data/` (gitignoriert) für die lokale App ohne Docker.
|
||||||
|
- Test-Suite und Gitea: dieselbe Dev-Postgres-Instanz, Datenbank `kansho_test` neben `kansho_dev` (keine dritte Instanz). Nicht `kansho` / `kansho_dev`, weil die Suite das Schema zurücksetzt.
|
||||||
- Docker auf dem Pi: PostgreSQL 16, eigene Instanz je Umgebung, Medien im Compose-Volume `kansho-media` / `dev-kansho-media`.
|
- Docker auf dem Pi: PostgreSQL 16, eigene Instanz je Umgebung, Medien im Compose-Volume `kansho-media` / `dev-kansho-media`.
|
||||||
- Identity-Mappings bleiben Klasse A in der Local Trusted Zone (jetzt: Pi-Postgres, nicht Provider).
|
- Identity-Mappings bleiben Klasse A in der Local Trusted Zone (jetzt: Pi-Postgres, nicht Provider).
|
||||||
- Kein Shared-Schema mit Mitai.
|
- Kein Shared-Schema mit Mitai.
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,8 @@ Offen, vor Compose festlegen — **beantwortet 2026-09-07:**
|
||||||
3. Dev-Domain / Prod-Domain / Host-Pfade? **`dev.kansho.jinkendo.de` / `kansho.jinkendo.de`**, Ports 3096/8096 und 3006/8005. Lokal bleiben 5188/8018. Prod-UI nicht 3005 (Bookstack auf dem Pi).
|
3. Dev-Domain / Prod-Domain / Host-Pfade? **`dev.kansho.jinkendo.de` / `kansho.jinkendo.de`**, Ports 3096/8096 und 3006/8005. Lokal bleiben 5188/8018. Prod-UI nicht 3005 (Bookstack auf dem Pi).
|
||||||
4. Welle 2 SQLite im Volume oder direkt Postgres? **Direkt Postgres.** SQLite bleibt lokal und für Tests.
|
4. Welle 2 SQLite im Volume oder direkt Postgres? **Direkt Postgres.** SQLite bleibt lokal und für Tests.
|
||||||
|
|
||||||
|
**Additiv 2026-09-07 (Test-Engine):** Zwei Postgres-Instanzen bleiben Dev und Prod. Die Gitea-Suite läuft auf der Dev-Postgres in der Datenbank `kansho_test` (neben `kansho_dev`), nicht gegen SQLite und nicht gegen das persönliche `kansho_dev`-Journal. Die Suite setzt dort das Schema zurück. SQLite bleibt die Windows-App ohne Docker und das lokale Backup-Format.
|
||||||
|
|
||||||
Empfohlene Reihenfolge in Welle 2:
|
Empfohlene Reihenfolge in Welle 2:
|
||||||
|
|
||||||
1. Offene Host-Fragen beantworten und in `runtime_and_deploy.md` §1/§6 eintragen.
|
1. Offene Host-Fragen beantworten und in `runtime_and_deploy.md` §1/§6 eintragen.
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ Lokal, eine Instanz, ein Profil-Nutzer nach Setup:
|
||||||
|
|
||||||
Proxy: Vite leitet `/api` an 8018. CORS erlaubt `localhost:5188`.
|
Proxy: Vite leitet `/api` an 8018. CORS erlaubt `localhost:5188`.
|
||||||
|
|
||||||
**Abweichung vom technischen Zielrahmen (lokal):** `product_frame_and_stack.md` nennt PostgreSQL. Der Slice auf dem Windows-Checkout bleibt SQLite (`5188`/`8018`). **Additiv 2026-09-07:** Docker/Server nutzt PostgreSQL 16 (`KANSHO_DB_BACKEND=postgres`). Stores behalten SQLite-förmiges SQL; `sql_compat.py` übersetzt zur Laufzeit. Nummerierte Dateien ab `backend/migrations/022_*.sql`. Siehe `runtime_and_deploy.md` und `docs/DEPLOYMENT.md`.
|
**Abweichung vom technischen Zielrahmen (lokal):** `product_frame_and_stack.md` nennt PostgreSQL. Der Slice auf dem Windows-Checkout bleibt SQLite (`5188`/`8018`). **Additiv 2026-09-07:** Docker/Server nutzt PostgreSQL 16 (`KANSHO_DB_BACKEND=postgres`). Stores behalten SQLite-förmiges SQL; `sql_compat.py` übersetzt zur Laufzeit. Nummerierte Dateien ab `backend/migrations/022_*.sql`. Siehe `runtime_and_deploy.md` und `docs/DEPLOYMENT.md`. **Additiv (Test-Suite):** API- und Store-Tests setzen `tests/harness.py` auf die Dev-Postgres, Datenbank `kansho_test` neben `kansho_dev` (keine dritte Instanz). Gitea `test.yml` trifft nicht das persönliche `kansho_dev`-Journal. SQLite-Testdateien sind abgelöst; `test_local_backup.py` prüft weiter das Windows-Backup-Format.
|
||||||
|
|
||||||
Health: `GET /api/health`.
|
Health: `GET /api/health`.
|
||||||
|
|
||||||
|
|
@ -227,6 +227,8 @@ Gateway-Verfahren und offener Security Layer: `privacy_gateway.md` §9.1–9.2 u
|
||||||
|
|
||||||
Tests beweisen API-Verträge und Invarianten, nicht Dialogqualität.
|
Tests beweisen API-Verträge und Invarianten, nicht Dialogqualität.
|
||||||
|
|
||||||
|
**Additiv 2026-09-07:** Die Backend-Suite in Gitea läuft auf der Dev-Postgres in `kansho_test` (Harness `backend/tests/harness.py`). `scripts/test-mvp.ps1` führt Store-/API-Tests lokal nur mit `KANSHO_DB_BACKEND=postgres` und `DB_NAME=kansho_test` aus; Unit-Tests ohne Datenbank laufen weiter. Kanonisch bleibt der Pi-Lauf.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 9. Technische Abweichungen und nicht gebaut
|
# 9. Technische Abweichungen und nicht gebaut
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ Kanshō-Repo liegt auf Gitea (`Lars/Kansho`). HTTPS-Push ist eingerichtet. Der P
|
||||||
| Postgres | eigene Instanz je Umgebung (`kansho` / `kansho_dev`), kein Shared-Schema | entschieden 2026-09-07 |
|
| Postgres | eigene Instanz je Umgebung (`kansho` / `kansho_dev`), kein Shared-Schema | entschieden 2026-09-07 |
|
||||||
| Gitea Workflows | `.gitea/workflows/` analog Kairo | entschieden 2026-09-07 |
|
| Gitea Workflows | `.gitea/workflows/` analog Kairo | entschieden 2026-09-07 |
|
||||||
| Auto-Rollback | nein | verworfen |
|
| Auto-Rollback | nein | verworfen |
|
||||||
| Dual-Backend | SQLite lokal/Tests; Postgres im Container | entschieden 2026-09-07 |
|
| Dual-Backend | SQLite nur Windows-App ohne Docker; Server Dev+Prod und Test-Suite PostgreSQL. Tests auf der Dev-Instanz in DB `kansho_test` neben `kansho_dev` (keine dritte Instanz) | entschieden 2026-09-07, Tests nachgezogen |
|
||||||
| Urlaubs-Laptop ohne Docker/SQLite | Phase A auf dem Heimrechner restored | dokumentiert 2026-09-07 |
|
| Urlaubs-Laptop ohne Docker/SQLite | Phase A auf dem Heimrechner restored | dokumentiert 2026-09-07 |
|
||||||
| Transfer vor Postgres | SQLite-Restore auf dem Heimrechner zuerst | entschieden als Reihenfolge |
|
| Transfer vor Postgres | SQLite-Restore auf dem Heimrechner zuerst | entschieden als Reihenfolge |
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ Kein Ersatz für Produktions-Backup, Docker oder Verschlüsselung.
|
||||||
|
|
||||||
Die Urlaubsinstanz lief ohne Docker auf SQLite (`backend/data/kansho.sqlite`, Ports 5188/8018).
|
Die Urlaubsinstanz lief ohne Docker auf SQLite (`backend/data/kansho.sqlite`, Ports 5188/8018).
|
||||||
|
|
||||||
**Reihenfolge entschieden:** zuerst Kontinuität (Clone + SQLite-Restore + Smoke), danach Betriebsrahmen (Compose, Postgres 16, Gitea-Runner). Dual-Backend: SQLite lokal/Tests, Postgres im Container (`KANSHO_DB_BACKEND=postgres`). Ein direkter Sprung „Laptop-SQLite nach Prod-Postgres“ ohne Zwischen-Restore ist verworfen. Import: `backend/sqlite_to_postgres.py --confirm`, zuerst Dev, dann Prod.
|
**Reihenfolge entschieden:** zuerst Kontinuität (Clone + SQLite-Restore + Smoke), danach Betriebsrahmen (Compose, Postgres 16, Gitea-Runner). Dual-Backend: SQLite nur für die Windows-App ohne Docker; Postgres im Container (zwei Instanzen: Dev `kansho_dev`, Prod `kansho`). Die Test-Suite nutzt dieselbe Dev-Postgres, Datenbank `kansho_test` neben `kansho_dev`, weil sie das Schema zurücksetzt. Ein direkter Sprung „Laptop-SQLite nach Prod-Postgres“ ohne Zwischen-Restore ist verworfen. Import: `sqlite_to_postgres.py --confirm`, zuerst Dev, dann Prod.
|
||||||
|
|
||||||
**Additiv 2026-09-07 (Transportweg):** Auf dem Urlaubs-Laptop dürfen weder USB-Stick noch NAS verbunden werden. Der einzige Weg für Datenbank und persönliche Journaldaten ist das **selbst gehostete** Gitea (`gitea.stommer.de`, nur eigene Infrastruktur). Das ist eine einmalige Transportentscheidung, kein Produktregelwechsel: Provider, OpenRouter und öffentliche Remotes bleiben ausgeschlossen. Provider-Keys und `backend/.env` bleiben **außerhalb** Git.
|
**Additiv 2026-09-07 (Transportweg):** Auf dem Urlaubs-Laptop dürfen weder USB-Stick noch NAS verbunden werden. Der einzige Weg für Datenbank und persönliche Journaldaten ist das **selbst gehostete** Gitea (`gitea.stommer.de`, nur eigene Infrastruktur). Das ist eine einmalige Transportentscheidung, kein Produktregelwechsel: Provider, OpenRouter und öffentliche Remotes bleiben ausgeschlossen. Provider-Keys und `backend/.env` bleiben **außerhalb** Git.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,14 +71,26 @@ Remove-Item Env:KANSHO_FAKE_DETECT -ErrorAction SilentlyContinue
|
||||||
$env:KANSHO_PROVIDER_KEY = ""
|
$env:KANSHO_PROVIDER_KEY = ""
|
||||||
$env:KANSHO_DETECT_PROVIDER_KEY = ""
|
$env:KANSHO_DETECT_PROVIDER_KEY = ""
|
||||||
$env:KANSHO_MEDIA_ROOT = $iso.Media
|
$env:KANSHO_MEDIA_ROOT = $iso.Media
|
||||||
$env:KANSHO_DB_PATH = $iso.Db
|
|
||||||
$env:KANSHO_DATA_DIR = $iso.Base
|
$env:KANSHO_DATA_DIR = $iso.Base
|
||||||
|
Remove-Item Env:KANSHO_DB_PATH -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
function Test-PostgresSuite {
|
||||||
|
$backend = ("$env:KANSHO_DB_BACKEND").ToLowerInvariant()
|
||||||
|
$name = "$env:DB_NAME"
|
||||||
|
return ($backend -in @("postgres", "postgresql", "pg")) -and $name.EndsWith("_test")
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "Kansho local MVP tests"
|
Write-Host "Kansho local MVP tests"
|
||||||
Write-Host "Python: $py"
|
Write-Host "Python: $py"
|
||||||
Write-Host "Isolation: $($iso.Base)"
|
Write-Host "Isolation: $($iso.Base)"
|
||||||
Write-Host "No live provider/detect calls. Production DB/media untouched."
|
Write-Host "No live provider/detect calls. Production DB/media untouched."
|
||||||
Write-Host "Fail-closed stays testable; suites that need a fake provider set it themselves."
|
Write-Host "Fail-closed stays testable; suites that need a fake provider set it themselves."
|
||||||
|
$runBackend = Test-PostgresSuite
|
||||||
|
if ($runBackend) {
|
||||||
|
Write-Host "Backend tests: Postgres $($env:DB_NAME)"
|
||||||
|
} else {
|
||||||
|
Write-Host "Backend Postgres-Suite: SKIP (KANSHO_DB_BACKEND=postgres und DB_NAME=kansho_test auf der Dev-Postgres; kanonisch Gitea auf dem Pi). Reine Unit-Tests ohne DB laufen trotzdem."
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$backendTests = Get-ChildItem -Path (Join-Path $root "backend\tests") -Filter "test_*.py" | Sort-Object Name
|
$backendTests = Get-ChildItem -Path (Join-Path $root "backend\tests") -Filter "test_*.py" | Sort-Object Name
|
||||||
|
|
@ -87,6 +99,18 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($test in $backendTests) {
|
foreach ($test in $backendTests) {
|
||||||
|
$needsPg = $false
|
||||||
|
try {
|
||||||
|
$needsPg = [bool](Select-String -Path $test.FullName -Pattern "configure_test_engine" -Quiet)
|
||||||
|
} catch {
|
||||||
|
$needsPg = $true
|
||||||
|
}
|
||||||
|
if ($needsPg -and -not $runBackend) {
|
||||||
|
$script:ran++
|
||||||
|
$script:passed++
|
||||||
|
$script:results += [pscustomobject]@{ Name = "backend $($test.Name)"; Status = "SKIP" }
|
||||||
|
continue
|
||||||
|
}
|
||||||
Invoke-Step -Name "backend $($test.Name)" -Action {
|
Invoke-Step -Name "backend $($test.Name)" -Action {
|
||||||
& $py $test.FullName
|
& $py $test.FullName
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user