feature: API-ключи клиентов и журнал использования в Postgres (#4, #17)

- Postgres в compose; пакет db (SQLAlchemy async): clients, windows, requests.
- Все эндпоинты, кроме /health, — только с ключом в X-API-Key, иначе 401; без
  выпущенных ключей доступа нет. В базе — только sha256 ключа.
- Задача и окно сессии привязаны к клиенту: чужой ключ их не видит.
- Воркер пишет журнал: окно (открыто, последнее обращение, закрыто) и задачу
  (в очереди, начало, конец, итог, данные без секретов). Сбой записи не роняет задачу.
- python -m db.cli create|list|revoke|stats; make key-create/key-list/key-revoke/stats.
- smoke и loadtest с ключом.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
protokeyandClaude Opus 5.5 committed 2026-10-13 21:48:48 +04:00
1 parent 9dc2c0b619
commit 1a4bd8d672
34 files changed
+857 -81

No files matched your search

+4 -4
View File
@@ -109,21 +109,21 @@ def test_invalid_request_is_422_without_task(env):
assert env.messages == []
def test_session_cookie_reused(env, tmp_path):
def test_session_cookie_reused(env):
sid = str(uuid.uuid4())
env.client.cookies.set("session_id", sid)
resp = post(env)
assert resp.cookies["session_id"] == sid
assert FakeSession.instances[0].kwargs["user_data_dir"] == str(tmp_path / sid)
assert FakeSession.instances[0].kwargs["user_data_dir"] == str(env.profiles / sid)
@pytest.mark.parametrize("bad", ["../../etc", "not-a-uuid", "/tmp/x"])
def test_bad_session_cookie_gets_new_session(env, tmp_path, bad):
def test_bad_session_cookie_gets_new_session(env, bad):
env.client.cookies.set("session_id", bad)
resp = post(env)
sid = resp.cookies["session_id"]
assert sid != bad and uuid.UUID(sid)
assert [p.name for p in tmp_path.iterdir()] == [sid]
assert [p.name for p in env.profiles.iterdir()] == [sid]
def test_user_agent_param_rejected(env):