Initial commit: CI Agent competitive-intelligence monitoring app

FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring,
source collection, LLM-based change analysis, enrichment, and account
security (Turnstile, escalating lockout, email verification).
This commit is contained in:
2026-08-05 10:48:20 -04:00
commit 1a4c80958f
365 changed files with 43541 additions and 0 deletions
@@ -0,0 +1,331 @@
"""Notification destination CRUD, ownership isolation, and the
company-linking behavior this feature is built around: reusing an existing
destination by (type, value) instead of duplicating it, dedupe display,
and garbage-collecting a destination once no company references it."""
from __future__ import annotations
import uuid
def _register_and_login(client) -> dict[str, str]:
email = f"user-{uuid.uuid4().hex[:12]}@example.com"
client.post(
"/api/v1/auth/register",
json={"email": email, "password": "correct-horse-1", "display_name": "Test User"},
)
tokens = client.post(
"/api/v1/auth/login", json={"email": email, "password": "correct-horse-1"}
).json()
return {"Authorization": f"Bearer {tokens['access_token']}"}
def _create_company(client, headers, name: str | None = None) -> dict:
return client.post(
"/api/v1/companies",
json={"name": name or f"Co {uuid.uuid4().hex[:6]}", "frequency_type": "weekly"},
headers=headers,
).json()
def test_create_email_destination(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
resp = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company["id"]],
},
headers=headers,
)
assert resp.status_code == 201
body = resp.json()
assert body["type"] == "email"
assert body["verified"] is False
assert body["minimum_severity"] == "medium"
assert [c["id"] for c in body["companies"]] == [company["id"]]
def test_create_destination_requires_at_least_one_company(client):
headers = _register_and_login(client)
resp = client.post(
"/api/v1/notification-destinations",
json={"type": "email", "destination_value": "[email protected]", "company_ids": []},
headers=headers,
)
assert resp.status_code == 422
def test_create_destination_rejects_a_company_id_the_user_doesnt_own(client):
owner_headers = _register_and_login(client)
other_headers = _register_and_login(client)
other_company = _create_company(client, other_headers)
resp = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [other_company["id"]],
},
headers=owner_headers,
)
assert resp.status_code == 400
def test_create_email_destination_rejects_invalid_email(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
resp = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "not-an-email",
"company_ids": [company["id"]],
},
headers=headers,
)
assert resp.status_code == 422
def test_create_sms_destination_rejects_invalid_phone(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
resp = client.post(
"/api/v1/notification-destinations",
json={"type": "sms", "destination_value": "not-a-phone", "company_ids": [company["id"]]},
headers=headers,
)
assert resp.status_code == 422
def test_create_sms_destination_accepts_e164(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
resp = client.post(
"/api/v1/notification-destinations",
json={
"type": "sms",
"destination_value": "+15551234567",
"company_ids": [company["id"]],
},
headers=headers,
)
assert resp.status_code == 201
def test_reusing_the_same_email_for_a_second_company_links_instead_of_duplicating(client):
"""The bug this feature exists to fix: the wizard used to create a brand
new NotificationDestination row per company even when the email was
already registered. Now it must reuse the same row and just add a link."""
headers = _register_and_login(client)
company_a = _create_company(client, headers, name="Company A")
company_b = _create_company(client, headers, name="Company B")
first = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company_a["id"]],
},
headers=headers,
).json()
second = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]", # different casing on purpose
"company_ids": [company_b["id"]],
},
headers=headers,
).json()
assert first["id"] == second["id"]
listing = client.get("/api/v1/notification-destinations", headers=headers).json()
assert len(listing) == 1
linked_ids = {c["id"] for c in listing[0]["companies"]}
assert linked_ids == {company_a["id"], company_b["id"]}
def test_update_destination_value_resets_verification(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
created = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company["id"]],
},
headers=headers,
).json()
resp = client.patch(
f"/api/v1/notification-destinations/{created['id']}",
json={"destination_value": "[email protected]"},
headers=headers,
)
assert resp.status_code == 200
assert resp.json()["verified"] is False
def test_destinations_scoped_to_owner(client):
owner_headers = _register_and_login(client)
other_headers = _register_and_login(client)
company = _create_company(client, owner_headers)
created = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company["id"]],
},
headers=owner_headers,
).json()
resp = client.patch(
f"/api/v1/notification-destinations/{created['id']}",
json={"enabled": False},
headers=other_headers,
)
assert resp.status_code == 404
def test_delete_destination(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
created = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company["id"]],
},
headers=headers,
).json()
resp = client.delete(f"/api/v1/notification-destinations/{created['id']}", headers=headers)
assert resp.status_code == 204
listing = client.get("/api/v1/notification-destinations", headers=headers).json()
assert all(d["id"] != created["id"] for d in listing)
def test_deleting_a_companys_only_destination_link_garbage_collects_it(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company["id"]],
},
headers=headers,
)
resp = client.delete(f"/api/v1/companies/{company['id']}", headers=headers)
assert resp.status_code == 204
listing = client.get("/api/v1/notification-destinations", headers=headers).json()
assert listing == []
def test_deleting_one_of_two_linked_companies_keeps_the_destination(client):
headers = _register_and_login(client)
company_a = _create_company(client, headers, name="Keep")
company_b = _create_company(client, headers, name="Delete me")
client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company_a["id"], company_b["id"]],
},
headers=headers,
)
resp = client.delete(f"/api/v1/companies/{company_b['id']}", headers=headers)
assert resp.status_code == 204
listing = client.get("/api/v1/notification-destinations", headers=headers).json()
assert len(listing) == 1
assert [c["id"] for c in listing[0]["companies"]] == [company_a["id"]]
def test_unlink_company_keeps_the_destination_when_other_links_remain(client):
headers = _register_and_login(client)
company_a = _create_company(client, headers, name="Keep")
company_b = _create_company(client, headers, name="Unlink me")
created = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company_a["id"], company_b["id"]],
},
headers=headers,
).json()
resp = client.delete(
f"/api/v1/notification-destinations/{created['id']}/companies/{company_b['id']}",
headers=headers,
)
assert resp.status_code == 204
listing = client.get("/api/v1/notification-destinations", headers=headers).json()
assert len(listing) == 1
assert [c["id"] for c in listing[0]["companies"]] == [company_a["id"]]
def test_unlinking_the_last_company_garbage_collects_the_destination(client):
headers = _register_and_login(client)
company = _create_company(client, headers)
created = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company["id"]],
},
headers=headers,
).json()
resp = client.delete(
f"/api/v1/notification-destinations/{created['id']}/companies/{company['id']}",
headers=headers,
)
assert resp.status_code == 204
listing = client.get("/api/v1/notification-destinations", headers=headers).json()
assert listing == []
def test_unlink_company_is_scoped_to_the_destinations_owner(client):
owner_headers = _register_and_login(client)
other_headers = _register_and_login(client)
company = _create_company(client, owner_headers)
created = client.post(
"/api/v1/notification-destinations",
json={
"type": "email",
"destination_value": "[email protected]",
"company_ids": [company["id"]],
},
headers=owner_headers,
).json()
resp = client.delete(
f"/api/v1/notification-destinations/{created['id']}/companies/{company['id']}",
headers=other_headers,
)
assert resp.status_code == 404
# The destination and its link both survive the rejected attempt.
listing = client.get("/api/v1/notification-destinations", headers=owner_headers).json()
assert len(listing) == 1
assert [c["id"] for c in listing[0]["companies"]] == [company["id"]]