Initial commit: site monorepo with API, web, and infra.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
влад
2026-07-16 10:11:54 +03:00
co-authored by Cursor
commit 016910ffb7
447 changed files with 73972 additions and 0 deletions
@@ -0,0 +1,120 @@
from __future__ import annotations
from uuid import uuid4
import pytest
from fastapi.testclient import TestClient
from app.modules.sync import repository as repo
from tests.orchestrator_dual_harness import OrchestratorDualHubHarness, make_enterprise
def test_hub_conflicts_via_hub_auth(client: TestClient):
enterprise_id = make_enterprise(client)
harness = OrchestratorDualHubHarness(client, enterprise_id)
hub_a, hub_b = harness.pair_hubs()
record_id = "hub-auth-conflict-1"
harness.push_from(
hub_a,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "hub-h1",
"payload": {"name": "A", "type": "g", "dry_matter": 1, "id": record_id, "version": 1, "content_hash": "hub-h1"},
"emitted_at": "2026-07-15T12:00:00Z",
"origin_site_id": hub_a.hub_site_id,
}
],
)
harness.push_from(
hub_b,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "hub-h2",
"payload": {"name": "B", "type": "g", "dry_matter": 2, "id": record_id, "version": 1, "content_hash": "hub-h2"},
"emitted_at": "2026-07-15T12:01:00Z",
"origin_site_id": hub_b.hub_site_id,
}
],
)
listed = client.get("/api/v1/sync/hub/conflicts", headers=hub_a.auth_header())
assert listed.status_code == 200
conflicts = listed.json()
assert len(conflicts) >= 1
def test_multiserver_list_and_resolve(client: TestClient):
enterprise_id = make_enterprise(client)
harness = OrchestratorDualHubHarness(client, enterprise_id)
hub_a, hub_b = harness.pair_hubs()
record_id = "ms-conflict-1"
harness.push_from(
hub_a,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "ms-h1",
"payload": {"name": "A", "type": "g", "dry_matter": 1, "id": record_id, "version": 1, "content_hash": "ms-h1"},
"emitted_at": "2026-07-15T12:00:00Z",
"origin_site_id": hub_a.hub_site_id,
}
],
)
harness.push_from(
hub_b,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "ms-h2",
"payload": {"name": "B", "type": "g", "dry_matter": 2, "id": record_id, "version": 1, "content_hash": "ms-h2"},
"emitted_at": "2026-07-15T12:01:00Z",
"origin_site_id": hub_b.hub_site_id,
}
],
)
login = client.post("/api/v1/auth/login", json={"email": "admin@compton.example", "password": "Admin1234"})
token = login.json()["access_token"]
listed = client.get(
f"/api/v1/sync/conflicts?enterprise_id={enterprise_id}",
headers={"Authorization": f"Bearer {token}"},
)
assert listed.status_code == 200
conflicts = listed.json()
assert len(conflicts) >= 1
cid = conflicts[0]["id"]
detail = client.get(
f"/api/v1/sync/conflicts/{cid}?enterprise_id={enterprise_id}",
headers={"Authorization": f"Bearer {token}"},
)
assert detail.status_code == 200
resolved = client.post(
f"/api/v1/sync/conflicts/{cid}/resolve?enterprise_id={enterprise_id}",
headers={"Authorization": f"Bearer {token}"},
json={"resolution": "keep_orchestrator"},
)
assert resolved.status_code == 200
@@ -0,0 +1,181 @@
from __future__ import annotations
import json
from datetime import UTC, datetime
from uuid import uuid4
import pytest
from fastapi.testclient import TestClient
from app.modules.sync import repository as repo
from app.modules.sync.engine import SyncEngine
from tests.orchestrator_dual_harness import OrchestratorDualHubHarness, make_enterprise
@pytest.fixture()
def chaos_harness(client: TestClient):
enterprise_id = make_enterprise(client)
harness = OrchestratorDualHubHarness(client, enterprise_id)
hub_a, hub_b = harness.pair_hubs()
return harness, hub_a, hub_b
def test_duplicate_ack_safe(client: TestClient, chaos_harness):
harness, hub_a, _hub_b = chaos_harness
record_id = "chaos-ack-1"
event = harness.make_component_event(
hub_a, record_id, name="DupAck", version=1, content_hash="da1", event_id="evt-dup-ack"
)
harness.push_from(hub_a, [event])
events = harness.pull_for(hub_a) # hub should not see own events
assert events == []
resp = client.post(
"/api/v1/sync/changes/ack",
headers=hub_a.auth_header(),
json={"event_ids": ["evt-dup-ack"], "direction": "inbound"},
)
assert resp.status_code == 200
def test_out_of_order_seq_replay_idempotent(client: TestClient, chaos_harness):
harness, hub_a, hub_b = chaos_harness
record_id = "chaos-seq-1"
e2 = harness.make_component_event(
hub_a, record_id, name="Second", version=2, content_hash="s2", event_id="evt-seq-2"
)
e1 = harness.make_component_event(
hub_a, record_id, name="First", version=1, content_hash="s1", event_id="evt-seq-1"
)
harness.push_from(hub_a, [e2])
harness.push_from(hub_a, [e1])
harness.drain()
row = harness.get_catalog(hub_b, "component", record_id)
assert row is not None
assert row["content_hash"] in {"s1", "s2"}
def test_resolve_keep_orchestrator_fanout(client: TestClient, chaos_harness):
harness, hub_a, hub_b = chaos_harness
record_id = "chaos-resolve-1"
harness.push_from(
hub_a,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "orch-hash",
"payload": {
"name": "Orch",
"type": "grain",
"dry_matter": 50.0,
"id": record_id,
"version": 1,
"content_hash": "orch-hash",
},
"emitted_at": datetime.now(UTC).isoformat(),
"origin_site_id": hub_a.hub_site_id,
}
],
)
harness.push_from(
hub_b,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "hub-hash",
"payload": {
"name": "HubB",
"type": "grain",
"dry_matter": 60.0,
"id": record_id,
"version": 1,
"content_hash": "hub-hash",
},
"emitted_at": datetime.now(UTC).isoformat(),
"origin_site_id": hub_b.hub_site_id,
}
],
)
conflicts = repo.list_conflicts(harness.enterprise_id, "pending")
assert len(conflicts) == 1
engine = SyncEngine(harness.enterprise_id, SyncEngine.ORCHESTRATOR_SITE_ID)
engine.resolve_conflict(conflicts[0].id, "admin", "keep_orchestrator")
harness.drain()
row = harness.get_orchestrator_catalog("component", record_id)
assert row is not None
assert row["content_hash"] == "orch-hash"
def test_resolve_keep_hub_fanout(client: TestClient, chaos_harness):
harness, hub_a, hub_b = chaos_harness
record_id = "chaos-resolve-hub-1"
harness.push_from(
hub_a,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "orch-hash2",
"payload": {
"name": "Orch",
"type": "grain",
"dry_matter": 50.0,
"id": record_id,
"version": 1,
"content_hash": "orch-hash2",
},
"emitted_at": "2026-07-15T10:00:00Z",
"origin_site_id": hub_a.hub_site_id,
}
],
)
harness.push_from(
hub_b,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "hub-b-hash2",
"payload": {
"name": "Hub B wins",
"type": "grain",
"dry_matter": 77.0,
"id": record_id,
"version": 1,
"content_hash": "hub-b-hash2",
},
"emitted_at": "2026-07-15T10:01:00Z",
"origin_site_id": hub_b.hub_site_id,
}
],
)
conflicts = repo.list_conflicts(harness.enterprise_id, "pending")
assert len(conflicts) == 1
engine = SyncEngine(harness.enterprise_id, SyncEngine.ORCHESTRATOR_SITE_ID)
engine.resolve_conflict(conflicts[0].id, "admin", "keep_hub")
harness.drain()
row = harness.get_orchestrator_catalog("component", record_id)
assert row is not None
assert row["content_hash"] == "hub-b-hash2"
assert row["name"] == "Hub B wins"
@@ -0,0 +1,187 @@
from __future__ import annotations
from uuid import uuid4
import pytest
from fastapi.testclient import TestClient
from tests.orchestrator_dual_harness import OrchestratorDualHubHarness, make_enterprise
@pytest.fixture()
def dual_harness(client: TestClient):
enterprise_id = make_enterprise(client)
harness = OrchestratorDualHubHarness(client, enterprise_id)
hub_a, hub_b = harness.pair_hubs()
return harness, hub_a, hub_b
def test_hub_a_push_reaches_hub_b(client: TestClient, dual_harness):
harness, hub_a, hub_b = dual_harness
record_id = "comp-dual-001"
event = harness.make_component_event(
hub_a, record_id, name="Corn A", version=1, content_hash="hash-a1"
)
harness.push_from(hub_a, [event])
harness.drain()
row = harness.get_catalog(hub_b, "component", record_id)
assert row is not None
assert row["name"] == "Corn A"
assert row["content_hash"] == "hash-a1"
def test_hub_b_push_back_to_hub_a(client: TestClient, dual_harness):
harness, hub_a, hub_b = dual_harness
record_id = "comp-dual-002"
harness.push_from(
hub_a,
[harness.make_component_event(hub_a, record_id, name="V1", version=1, content_hash="h1")],
)
harness.drain()
harness.push_from(
hub_b,
[harness.make_component_event(hub_b, record_id, name="V2 from B", version=2, content_hash="h2")],
)
harness.drain()
row_a = harness.get_catalog(hub_a, "component", record_id)
assert row_a is not None
assert row_a["content_hash"] == "h2"
assert row_a["name"] == "V2 from B"
def test_idempotent_replay(client: TestClient, dual_harness):
harness, hub_a, hub_b = dual_harness
record_id = "comp-dual-003"
event = harness.make_component_event(
hub_a, record_id, name="Once", version=1, content_hash="once1", event_id="evt-fixed-003"
)
harness.push_from(hub_a, [event])
harness.push_from(hub_a, [event])
harness.drain()
orch = harness.get_orchestrator_catalog("component", record_id)
assert orch is not None
assert orch["name"] == "Once"
row_b = harness.get_catalog(hub_b, "component", record_id)
assert row_b is not None
assert row_b["content_hash"] == "once1"
def test_ack_cursor_no_double_apply(client: TestClient, dual_harness):
harness, hub_a, hub_b = dual_harness
record_id = "comp-dual-004"
event = harness.make_component_event(
hub_a, record_id, name="Ack safe", version=1, content_hash="ack1", event_id="evt-ack-004"
)
harness.push_from(hub_a, [event])
events1 = harness.pull_for(hub_b)
assert len(events1) == 1
events2 = harness.pull_for(hub_b)
assert len(events2) == 0
row = harness.get_catalog(hub_b, "component", record_id)
assert row is not None
assert row["name"] == "Ack safe"
def test_no_conflict_single_editor(client: TestClient, dual_harness):
harness, hub_a, hub_b = dual_harness
record_id = "comp-dual-005"
harness.push_from(
hub_a,
[harness.make_component_event(hub_a, record_id, name="Solo", version=1, content_hash="solo1")],
)
harness.drain()
from app.modules.sync import repository as repo
conflicts = repo.list_conflicts(harness.enterprise_id, "pending")
assert conflicts == []
row = harness.get_orchestrator_catalog("component", record_id)
assert row is not None
assert row["name"] == "Solo"
def test_conflict_dual_edit(client: TestClient, dual_harness):
harness, hub_a, hub_b = dual_harness
record_id = "comp-dual-006"
base = {"name": "Base", "type": "grain", "dry_matter": 50.0}
harness.push_from(
hub_a,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "base-hash",
"payload": {**base, "id": record_id, "version": 1, "content_hash": "base-hash"},
"emitted_at": "2026-07-15T10:00:00Z",
"origin_site_id": hub_a.hub_site_id,
}
],
)
harness.drain()
harness.push_from(
hub_b,
[
{
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "component",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "b-conflict-hash",
"payload": {
"name": "B edit",
"type": "grain",
"dry_matter": 60.0,
"id": record_id,
"version": 1,
"content_hash": "b-conflict-hash",
},
"emitted_at": "2026-07-15T10:01:00Z",
"origin_site_id": hub_b.hub_site_id,
}
],
)
from app.modules.sync import repository as repo
conflicts = repo.list_conflicts(harness.enterprise_id, "pending")
assert len(conflicts) == 1
orch = harness.get_orchestrator_catalog("component", record_id)
assert orch is not None
assert orch["content_hash"] == "base-hash"
def test_period_recipes_composite_record_id(client: TestClient, dual_harness):
harness, hub_a, hub_b = dual_harness
period_id = "737a78a5-492a-4a84-94f3-18b4d7f21666"
recipe_id = "07fd17cf-22c3-44fe-92db-46363b24cee0"
record_id = f"{period_id}:{recipe_id}"
event = {
"event_id": str(uuid4()),
"seq": 1,
"domain": "global",
"table": "period_recipes",
"record_id": record_id,
"action": "upsert",
"version": 1,
"content_hash": "pr1",
"payload": {
"period_id": period_id,
"recipe_id": recipe_id,
"order": 1,
"version": 1,
"content_hash": "pr1",
},
"emitted_at": "2026-07-15T12:00:00Z",
"origin_site_id": hub_a.hub_site_id,
}
harness.push_from(hub_a, [event])
harness.drain()
row = harness.get_catalog(hub_b, "period_recipes", record_id)
assert row is not None
assert row.get("order") == 1
@@ -0,0 +1,72 @@
from __future__ import annotations
from pathlib import Path
from uuid import uuid4
import pytest
from fastapi.testclient import TestClient
from tests.orchestrator_dual_harness import OrchestratorDualHubHarness, make_enterprise
def test_recipe_ingredient_tree_roundtrip(client: TestClient):
enterprise_id = make_enterprise(client)
harness = OrchestratorDualHubHarness(client, enterprise_id)
hub_a, hub_b = harness.pair_hubs()
recipe_id = "recipe-tree-1"
ing_id = "ing-tree-1"
comp_id = "comp-tree-1"
harness.push_from(
hub_a,
[
harness.make_component_event(hub_a, comp_id, name="Barley", version=1, content_hash="c1"),
{
"event_id": str(uuid4()),
"seq": 2,
"domain": "global",
"table": "recipe",
"record_id": recipe_id,
"action": "upsert",
"version": 1,
"content_hash": "r1",
"payload": {
"id": recipe_id,
"name": "Mix A",
"heads_per_trip": 100,
"ingredients": [{"id": ing_id, "component_id": comp_id, "name": "Barley", "amount": 10}],
"version": 1,
"content_hash": "r1",
},
"emitted_at": "2026-07-15T12:00:00Z",
"origin_site_id": hub_a.hub_site_id,
},
{
"event_id": str(uuid4()),
"seq": 3,
"domain": "global",
"table": "ingredient",
"record_id": ing_id,
"action": "upsert",
"version": 1,
"content_hash": "i1",
"payload": {
"id": ing_id,
"recipe_id": recipe_id,
"component_id": comp_id,
"name": "Barley",
"amount": 10.0,
"version": 1,
"content_hash": "i1",
},
"emitted_at": "2026-07-15T12:00:01Z",
"origin_site_id": hub_a.hub_site_id,
},
],
)
harness.drain([hub_b])
recipe = harness.get_catalog(hub_b, "recipe", recipe_id)
assert recipe is not None
assert recipe.get("name") == "Mix A"
ing = harness.get_catalog(hub_b, "ingredient", ing_id)
assert ing is not None
assert ing.get("component_id") == comp_id
@@ -0,0 +1,39 @@
from __future__ import annotations
import os
import pytest
from app.modules.sync import repository as repo
@pytest.mark.skipif(
"postgresql" not in os.environ.get("DATABASE_URL", ""),
reason="RLS tests require PostgreSQL",
)
def test_rls_cross_enterprise():
ent_a = repo.create_enterprise("Farm A", f"farm-a-{os.getpid()}")
ent_b = repo.create_enterprise("Farm B", f"farm-b-{os.getpid()}")
assert ent_a.id != ent_b.id
hub_a = repo.create_farm_hub(ent_a.id, "Hub A", f"hub-a-{os.getpid()}", None)
hubs_b = repo.list_farm_hubs(ent_b.id)
assert all(h.id != hub_a.id for h in hubs_b)
def test_viewer_farm_scope(client):
from uuid import uuid4
from app.modules.users.repository import get_user_by_email
slug = f"abac-{uuid4().hex[:8]}"
ent = repo.create_enterprise("ABAC Farm", slug)
admin = get_user_by_email("admin@compton.example")
assert admin
repo.add_member(admin.id, ent.id, "admin")
hub1 = repo.create_farm_hub(ent.id, "H1", f"h1-{uuid4().hex[:8]}", None)
hub2 = repo.create_farm_hub(ent.id, "H2", f"h2-{uuid4().hex[:8]}", None)
viewer_id = admin.id
repo.grant_farm_access(viewer_id, hub1.id)
allowed = repo.list_farm_access(viewer_id, ent.id)
assert hub1.id in allowed
assert hub2.id not in allowed
@@ -0,0 +1,97 @@
from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
from app.core.crypto import hash_opaque_token
from app.modules.sync import repository as repo
from uuid import uuid4
@pytest.fixture()
def enterprise(client: TestClient):
slug = f"test-farm-{uuid4().hex[:8]}"
ent = repo.create_enterprise("Test Farm Co", slug)
admin = repo.get_member.__module__ # noqa: ensure import path
from app.modules.users.repository import get_user_by_email
user = get_user_by_email("admin@compton.example")
assert user
repo.add_member(user.id, ent.id, "admin")
return ent
def test_sync_capabilities(client: TestClient):
resp = client.get("/api/v1/sync/capabilities")
assert resp.status_code == 200
data = resp.json()
assert data["protocol_version"] == "1.0"
assert "global" in data["domains"]
def test_pairing_flow(client: TestClient, enterprise):
login = client.post("/api/v1/auth/login", json={"email": "admin@compton.example", "password": "Admin1234"})
token = login.json()["access_token"]
start = client.post(
"/api/v1/enterprise/pair/start",
headers={"Authorization": f"Bearer {token}"},
json={"enterprise_id": enterprise.id, "farm_name": "Farm A"},
)
assert start.status_code == 200
code = start.json()["code"]
confirm = client.post(
"/api/v1/enterprise/pair/confirm",
json={"code": code, "hub_site_id": "hub-site-001", "hub_name": "Farm A Hub"},
)
assert confirm.status_code == 200
body = confirm.json()
assert body["hub_site_id"] == "hub-site-001"
assert body["api_key"]
def test_hub_push_idempotent(client: TestClient, enterprise):
login = client.post("/api/v1/auth/login", json={"email": "admin@compton.example", "password": "Admin1234"})
token = login.json()["access_token"]
start = client.post(
"/api/v1/enterprise/pair/start",
headers={"Authorization": f"Bearer {token}"},
json={"enterprise_id": enterprise.id, "farm_name": "Farm B"},
)
code = start.json()["code"]
confirm = client.post(
"/api/v1/enterprise/pair/confirm",
json={"code": code, "hub_site_id": "hub-site-002", "hub_name": "Farm B Hub"},
)
api_key = confirm.json()["api_key"]
hub_auth = f"Hub hub-site-002:{api_key}"
from datetime import UTC, datetime
event = {
"event_id": "evt-001",
"seq": 1,
"domain": "global",
"table": "component",
"record_id": "comp-001",
"action": "upsert",
"version": 1,
"content_hash": "hash1",
"payload": {"name": "Corn", "type": "grain", "dry_matter": 88.0},
"emitted_at": datetime.now(UTC).isoformat(),
"origin_site_id": "hub-site-002",
}
push1 = client.post(
"/api/v1/sync/changes/push",
headers={"Authorization": hub_auth},
json={"events": [event]},
)
assert push1.status_code == 200
assert "evt-001" in push1.json()["applied_event_ids"]
push2 = client.post(
"/api/v1/sync/changes/push",
headers={"Authorization": hub_auth},
json={"events": [event]},
)
assert push2.status_code == 200
assert "evt-001" in push2.json()["applied_event_ids"]