Catalyst / admin/Bid-Sentinel 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / Bid-Sentinel

public

Bid Scrape and Tracking Application with AI Capability

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
Bid-Sentinel / bid-sentinel-v2 / backend / app / main.py 1684 B · main
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""FastAPI application entrypoint."""
import logging
from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.audit import AuditMiddleware
from app.config import settings
from app.routers import (
    audit,
    auth,
    intelligence,
    mail,
    settings as settings_router,
    tenders,
    users,
)
from app.scraper.scheduler import scheduler
from app.seed import create_tables, seed_portals

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s [%(name)s] %(message)s",
)
logger = logging.getLogger("main")


@asynccontextmanager
async def lifespan(app: FastAPI):
    # --- startup ---
    logger.info("Initializing database...")
    await create_tables()
    await seed_portals()
    scheduler.start()
    yield
    # --- shutdown ---
    await scheduler.stop()


app = FastAPI(
    title="Bid Sentinel API",
    version="2.0.0",
    description="Bid Sentinel — scrape, track and manage UK public and private sector Cyber Security tenders.",
    lifespan=lifespan,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origin_list,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
# Records mutating requests to the audit trail (admin-viewable).
app.add_middleware(AuditMiddleware)

app.include_router(auth.router)
app.include_router(users.router)
app.include_router(tenders.router)
app.include_router(settings_router.router)
app.include_router(audit.router)
app.include_router(intelligence.router)
app.include_router(mail.router)


@app.get("/health", tags=["meta"])
async def health():
    return {"status": "ok"}