Legal-i commited on
Commit
061d6cb
·
verified ·
1 Parent(s): c9ceb89

Stage 211: forecast.threshold_crossed (infra/api/app.py)

Browse files
Files changed (1) hide show
  1. infra/api/app.py +28 -0
infra/api/app.py CHANGED
@@ -2067,6 +2067,34 @@ def create_app(db_path: Optional[str] = None,
2067
  except ValueError as e:
2068
  raise ApiError("bad_request", str(e), status=400) from e
2069
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2070
  @app.post("/tenants/{tenant_id}/forecasts/batch", tags=["runs"])
2071
  async def post_forecasts_batch_route(
2072
  tenant_id: str,
 
2067
  except ValueError as e:
2068
  raise ApiError("bad_request", str(e), status=400) from e
2069
 
2070
+ # Stage 211 — manual trigger for the forecast-threshold scan.
2071
+ # Admin role required: this fires webhooks + writes audit rows,
2072
+ # so the operator running it should have the same authority as
2073
+ # someone who'd configure a cron. The intended runtime is a
2074
+ # daily cron picking this up; for now the dashboard / curl is
2075
+ # the trigger.
2076
+ @app.post("/tenants/{tenant_id}/forecast/check_thresholds",
2077
+ tags=["runs"])
2078
+ async def post_forecast_check_thresholds_route(
2079
+ tenant_id: str, body: dict,
2080
+ key: ApiKey = Depends(auth_dep),
2081
+ ):
2082
+ require_tenant_access(key, tenant_id)
2083
+ require_role(key, ROLE_ADMIN)
2084
+ days_threshold = body.get("days_threshold", 7)
2085
+ if not isinstance(days_threshold, int):
2086
+ raise ApiError(
2087
+ "bad_request",
2088
+ "days_threshold must be an integer", status=400,
2089
+ )
2090
+ try:
2091
+ return svc.check_forecast_thresholds(
2092
+ tenant_id, days_threshold=days_threshold,
2093
+ actor=key.key_id,
2094
+ )
2095
+ except ValueError as e:
2096
+ raise ApiError("bad_request", str(e), status=400) from e
2097
+
2098
  @app.post("/tenants/{tenant_id}/forecasts/batch", tags=["runs"])
2099
  async def post_forecasts_batch_route(
2100
  tenant_id: str,