Files
ewoooc/routes/market_intel_routes.py
OoO 72ded9e1e5
All checks were successful
CD Pipeline / deploy (push) Successful in 1m21s
V10.507 接入 Webcrumbs 並收斂 writer approval gate
2026-05-31 19:01:54 +08:00

919 lines
31 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""市場情報頁面與 API 路由。"""
from datetime import datetime, timedelta, timezone
from flask import Blueprint, jsonify, render_template, request
from auth import login_required
from config import SYSTEM_VERSION
from services.market_intel import MarketIntelService
from services.market_intel.candidate_queue_writer_cli import build_candidate_queue_writer_cli_plan
from services.market_intel.candidate_queue_writer_preflight import build_candidate_queue_writer_preflight
from services.market_intel.candidate_queue_writer_postwrite_smoke import build_candidate_queue_writer_postwrite_smoke
from services.market_intel.candidate_queue_writer_operator_drill import build_candidate_queue_writer_operator_drill
from services.market_intel.candidate_queue_writer_run_package import build_candidate_queue_writer_run_package
from services.market_intel.candidate_queue_writer_run_readiness import build_candidate_queue_writer_run_readiness
from services.market_intel.candidate_queue_writer_run_receipt import build_candidate_queue_writer_run_receipt
from services.market_intel.candidate_queue_writer_run_closeout import build_candidate_queue_writer_run_closeout
from services.market_intel.candidate_queue_review_handoff import build_candidate_queue_review_handoff
from services.market_intel.mcp_activation_evidence import build_mcp_activation_evidence_preview
from services.market_intel.mcp_fetch_target_review import (
build_mcp_fetch_target_review_preview,
)
from services.market_intel.mcp_manual_fetch_handoff import (
build_mcp_manual_fetch_handoff_preview,
)
from services.market_intel.mcp_runtime_promotion import build_mcp_runtime_promotion_preview
from services.market_intel.mcp_runtime_smoke_receipt import build_mcp_runtime_smoke_receipt_preview
TAIPEI_TZ = timezone(timedelta(hours=8))
market_intel_bp = Blueprint("market_intel", __name__)
def _service():
return MarketIntelService()
@market_intel_bp.route("/market_intel")
@market_intel_bp.route("/market_intel/campaigns")
@login_required
def campaigns():
service = _service()
status = service.get_runtime_status()
return render_template(
"market_intel/disabled.html",
active_page="market_intel",
datetime_now=datetime.now(TAIPEI_TZ).strftime("%Y-%m-%d %H:%M:%S"),
system_version=SYSTEM_VERSION,
status=status,
adapter_count=len(service.get_adapter_summaries()),
manual_fetch_allowed=service.manual_fetch_allowed(),
current_section="campaigns",
)
@market_intel_bp.route("/market_intel/products")
@market_intel_bp.route("/market_intel/matches")
@market_intel_bp.route("/market_intel/opportunities")
@login_required
def disabled_section():
service = _service()
status = service.get_runtime_status()
return render_template(
"market_intel/disabled.html",
active_page="market_intel",
datetime_now=datetime.now(TAIPEI_TZ).strftime("%Y-%m-%d %H:%M:%S"),
system_version=SYSTEM_VERSION,
status=status,
adapter_count=len(service.get_adapter_summaries()),
manual_fetch_allowed=service.manual_fetch_allowed(),
current_section="disabled",
)
@market_intel_bp.route("/api/market_intel/status")
@login_required
def market_intel_status():
return jsonify(_service().get_runtime_status().to_dict())
@market_intel_bp.route("/api/market_intel/schema")
@login_required
def market_intel_schema():
return jsonify({"tables": _service().get_schema_tables()})
@market_intel_bp.route("/api/market_intel/schema_smoke")
@login_required
def market_intel_schema_smoke():
return jsonify(_service().build_schema_smoke())
@market_intel_bp.route("/api/market_intel/schema_db_probe")
@login_required
def market_intel_schema_db_probe():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(_service().build_schema_db_probe(execute_requested=execute_requested))
@market_intel_bp.route("/api/market_intel/platform_seed_db_diff")
@login_required
def market_intel_platform_seed_db_diff():
platform_code = request.args.get("platform", "all")
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_platform_seed_db_diff(
platform_code=platform_code,
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/legacy_source_bridge")
@login_required
def market_intel_legacy_source_bridge():
execute_requested = request.args.get("execute", "false").lower() == "true"
sample_limit = request.args.get("limit", default=5, type=int)
return jsonify(
_service().build_legacy_source_bridge(
execute_requested=execute_requested,
sample_limit=sample_limit,
)
)
@market_intel_bp.route("/api/market_intel/mcp_readiness")
@login_required
def market_intel_mcp_readiness():
execute_requested = request.args.get("execute", "false").lower() == "true"
timeout_sec = request.args.get("timeout", default=3, type=int)
return jsonify(
_service().build_mcp_readiness(
execute_requested=execute_requested,
timeout_sec=timeout_sec,
)
)
@market_intel_bp.route("/api/market_intel/mcp_tool_contract")
@login_required
def market_intel_mcp_tool_contract():
return jsonify(_service().build_mcp_tool_contract())
@market_intel_bp.route("/api/market_intel/mcp_deploy_preflight")
@login_required
def market_intel_mcp_deploy_preflight():
return jsonify(_service().build_mcp_deploy_preflight())
@market_intel_bp.route("/api/market_intel/mcp_activation_runbook")
@login_required
def market_intel_mcp_activation_runbook():
return jsonify(_service().build_mcp_activation_runbook())
@market_intel_bp.route("/api/market_intel/mcp_fetch_gate")
@login_required
def market_intel_mcp_fetch_gate():
fetch_requested = request.args.get("fetch", "false").lower() == "true"
execute_readiness = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_mcp_fetch_gate(
fetch_requested=fetch_requested,
execute_readiness=execute_readiness,
)
)
@market_intel_bp.route("/api/market_intel/mcp_completion_audit")
@login_required
def market_intel_mcp_completion_audit():
return jsonify(_service().build_mcp_completion_audit())
@market_intel_bp.route("/api/market_intel/mcp_activation_evidence", methods=["GET", "POST"])
@login_required
def market_intel_mcp_activation_evidence():
evidence = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
evidence = payload.get("evidence", payload)
return jsonify(
build_mcp_activation_evidence_preview(
evidence=evidence,
phase=_service().phase,
)
)
@market_intel_bp.route("/api/market_intel/mcp_runtime_smoke_receipt", methods=["GET", "POST"])
@login_required
def market_intel_mcp_runtime_smoke_receipt():
receipt = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
receipt = payload.get("receipt", payload)
return jsonify(
build_mcp_runtime_smoke_receipt_preview(
receipt=receipt,
phase=_service().phase,
)
)
@market_intel_bp.route("/api/market_intel/mcp_runtime_promotion", methods=["GET", "POST"])
@login_required
def market_intel_mcp_runtime_promotion():
activation_evidence = {}
runtime_receipt = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
package = payload.get("promotion_package") or payload
activation_evidence = package.get("activation_evidence", {})
runtime_receipt = package.get("runtime_receipt", {})
return jsonify(
build_mcp_runtime_promotion_preview(
activation_evidence=activation_evidence,
runtime_receipt=runtime_receipt,
phase=_service().phase,
)
)
@market_intel_bp.route("/api/market_intel/mcp_manual_fetch_handoff", methods=["GET", "POST"])
@login_required
def market_intel_mcp_manual_fetch_handoff():
promotion_package = {}
promotion_review = None
operator_acknowledgements = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
handoff_package = payload.get("handoff_package") or payload
promotion_package = handoff_package.get("promotion_package", {})
promotion_review = handoff_package.get("promotion_review")
operator_acknowledgements = handoff_package.get(
"operator_acknowledgements",
{},
)
service = _service()
return jsonify(
build_mcp_manual_fetch_handoff_preview(
promotion_package=promotion_package,
promotion_review=promotion_review,
operator_acknowledgements=operator_acknowledgements,
runtime_status=service.get_runtime_status(),
phase=service.phase,
)
)
@market_intel_bp.route("/api/market_intel/mcp_fetch_target_review", methods=["GET", "POST"])
@login_required
def market_intel_mcp_fetch_target_review():
handoff_package = {}
handoff_review = None
target_review = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
package = payload.get("target_review_package") or payload
handoff_package = package.get("handoff_package", {})
handoff_review = package.get("handoff_review")
target_review = (
package
if "platform_targets" in package
else package.get("target_review", {})
)
return jsonify(
build_mcp_fetch_target_review_preview(
handoff_package=handoff_package,
handoff_review=handoff_review,
target_review=target_review,
phase=_service().phase,
)
)
@market_intel_bp.route("/api/market_intel/scheduler_plan")
@login_required
def market_intel_scheduler_plan():
return jsonify(_service().build_scheduler_plan())
@market_intel_bp.route("/api/market_intel/manual_sample_plan")
@login_required
def market_intel_manual_sample_plan():
return jsonify(_service().build_manual_sample_plan())
@market_intel_bp.route("/api/market_intel/manual_sample_acceptance")
@login_required
def market_intel_manual_sample_acceptance():
return jsonify(_service().build_manual_sample_acceptance())
@market_intel_bp.route("/api/market_intel/manual_sample_review")
@login_required
def market_intel_manual_sample_review():
return jsonify(_service().build_manual_sample_review())
@market_intel_bp.route("/api/market_intel/manual_sample_review/evaluate", methods=["POST"])
@login_required
def market_intel_manual_sample_review_evaluate():
payload = request.get_json(silent=True)
if not isinstance(payload, dict):
data = _service().build_manual_sample_review_evaluation(
sample_result=None,
payload_error="invalid_json_object",
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_service().build_manual_sample_review_evaluation(sample_result=sample_result)
)
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_handoff",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_handoff():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _service().build_manual_sample_candidate_handoff(
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_service().build_manual_sample_candidate_handoff(
sample_result=sample_result,
limit=limit,
)
)
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_draft",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_draft():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _service().build_manual_sample_candidate_queue_draft(
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_service().build_manual_sample_candidate_queue_draft(
sample_result=sample_result,
limit=limit,
)
)
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_approval",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_approval():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _service().build_manual_sample_candidate_queue_approval(
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_service().build_manual_sample_candidate_queue_approval(
sample_result=sample_result,
limit=limit,
)
)
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_transaction",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_transaction():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _service().build_manual_sample_candidate_queue_transaction(
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_service().build_manual_sample_candidate_queue_transaction(
sample_result=sample_result,
limit=limit,
)
)
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_writer_status",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_writer_status():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
execute_requested = request.args.get("execute", "false").lower() == "true"
apply_real_write = request.args.get("apply_real_write", "false").lower() == "true"
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
transaction_preview = service.build_manual_sample_candidate_queue_transaction(
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
writer_preflight = build_candidate_queue_writer_preflight(
transaction_preview=transaction_preview,
execute_requested=False,
)
data = build_candidate_queue_writer_cli_plan(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
execute_requested=execute_requested,
apply_real_write=apply_real_write,
approval_token=None,
approval_token_secret=None,
)
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_writer_preflight",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_writer_preflight():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
execute_requested = request.args.get("execute", "false").lower() == "true"
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
transaction_preview = service.build_manual_sample_candidate_queue_transaction(
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = build_candidate_queue_writer_preflight(
transaction_preview=transaction_preview,
execute_requested=execute_requested,
)
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_writer_postwrite_smoke",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_writer_postwrite_smoke():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
execute_requested = request.args.get("execute", "false").lower() == "true"
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
transaction_preview = service.build_manual_sample_candidate_queue_transaction(
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = build_candidate_queue_writer_postwrite_smoke(
transaction_preview=transaction_preview,
execute_requested=execute_requested,
)
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
def _build_candidate_queue_writer_stack(
*,
service,
sample_result,
payload_error,
limit,
operator_evidence=None,
):
transaction_preview = service.build_manual_sample_candidate_queue_transaction(
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
writer_preflight = build_candidate_queue_writer_preflight(
transaction_preview=transaction_preview,
execute_requested=False,
)
writer_status = build_candidate_queue_writer_cli_plan(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
approval_token=None,
approval_token_secret=None,
)
postwrite_smoke = build_candidate_queue_writer_postwrite_smoke(
transaction_preview=transaction_preview,
execute_requested=False,
)
operator_drill = build_candidate_queue_writer_operator_drill(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
writer_status=writer_status,
postwrite_smoke=postwrite_smoke,
)
run_package = build_candidate_queue_writer_run_package(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
writer_status=writer_status,
postwrite_smoke=postwrite_smoke,
operator_drill=operator_drill,
)
run_readiness = build_candidate_queue_writer_run_readiness(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
writer_status=writer_status,
postwrite_smoke=postwrite_smoke,
operator_drill=operator_drill,
run_package=run_package,
operator_evidence=operator_evidence or {},
)
return {
"transaction_preview": transaction_preview,
"writer_preflight": writer_preflight,
"writer_status": writer_status,
"postwrite_smoke": postwrite_smoke,
"operator_drill": operator_drill,
"run_package": run_package,
"run_readiness": run_readiness,
}
def _extract_candidate_queue_writer_run_payload():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
return None, {}, {}, {}, "invalid_json_object", limit
return (
payload.get("sample_result", payload),
payload.get("operator_evidence", {}),
payload.get("writer_output", {}),
payload.get("postwrite_smoke_result", {}),
None,
limit,
)
def _build_candidate_queue_writer_run_response(builder):
service = _service()
sample_result, operator_evidence, writer_output, postwrite_smoke_result, payload_error, limit = (
_extract_candidate_queue_writer_run_payload()
)
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
operator_evidence=operator_evidence,
)
receipt = build_candidate_queue_writer_run_receipt(
transaction_preview=stack["transaction_preview"],
run_readiness=stack["run_readiness"],
writer_output=writer_output,
postwrite_smoke_result=postwrite_smoke_result,
operator_evidence=operator_evidence,
)
closeout = build_candidate_queue_writer_run_closeout(
transaction_preview=stack["transaction_preview"],
run_receipt=receipt,
operator_evidence=operator_evidence,
)
data = builder(stack, receipt, closeout, operator_evidence)
data["phase"] = service.phase
return jsonify(data), 400 if payload_error else 200
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_writer_operator_drill",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_writer_operator_drill():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = stack["operator_drill"]
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_writer_run_package",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_writer_run_package():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = stack["run_package"]
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@market_intel_bp.route(
"/api/market_intel/manual_sample_review/candidate_queue_writer_run_readiness",
methods=["POST"],
)
@login_required
def market_intel_manual_sample_candidate_queue_writer_run_readiness():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
service = _service()
payload_error = None
operator_evidence = {}
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
operator_evidence = payload.get("operator_evidence", {})
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
operator_evidence=operator_evidence,
)
data = stack["run_readiness"]
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@market_intel_bp.route("/api/market_intel/manual_sample_review/candidate_queue_writer_run_receipt", methods=["POST"])
@login_required
def market_intel_manual_sample_candidate_queue_writer_run_receipt():
return _build_candidate_queue_writer_run_response(
lambda stack, receipt, closeout, operator_evidence: receipt
)
@market_intel_bp.route("/api/market_intel/manual_sample_review/candidate_queue_writer_run_closeout", methods=["POST"])
@login_required
def market_intel_manual_sample_candidate_queue_writer_run_closeout():
return _build_candidate_queue_writer_run_response(
lambda stack, receipt, closeout, operator_evidence: closeout
)
@market_intel_bp.route("/api/market_intel/manual_sample_review/candidate_queue_review_handoff", methods=["POST"])
@login_required
def market_intel_manual_sample_candidate_queue_review_handoff():
return _build_candidate_queue_writer_run_response(
lambda stack, receipt, closeout, operator_evidence: build_candidate_queue_review_handoff(
transaction_preview=stack["transaction_preview"],
run_closeout=closeout,
operator_evidence=operator_evidence,
)
)
@market_intel_bp.route("/api/market_intel/match_review_plan")
@login_required
def market_intel_match_review_plan():
return jsonify(_service().build_match_review_plan())
@market_intel_bp.route("/api/market_intel/opportunity_plan")
@login_required
def market_intel_opportunity_plan():
return jsonify(_service().build_opportunity_plan())
@market_intel_bp.route("/api/market_intel/opportunity_scoring_plan")
@login_required
def market_intel_opportunity_scoring_plan():
return jsonify(_service().build_opportunity_scoring_plan())
@market_intel_bp.route("/api/market_intel/opportunity_evidence_plan")
@login_required
def market_intel_opportunity_evidence_plan():
return jsonify(_service().build_opportunity_evidence_plan())
@market_intel_bp.route("/api/market_intel/opportunity_alert_plan")
@login_required
def market_intel_opportunity_alert_plan():
return jsonify(_service().build_opportunity_alert_plan())
@market_intel_bp.route("/api/market_intel/adapters")
@login_required
def market_intel_adapters():
return jsonify({"adapters": _service().get_adapter_summaries()})
@market_intel_bp.route("/api/market_intel/dry_run_plan")
@login_required
def market_intel_dry_run_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_dry_run_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/discovery_plan")
@login_required
def market_intel_discovery_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_discovery_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/manual_discovery")
@login_required
def market_intel_manual_discovery():
platform_code = request.args.get("platform", "all")
fetch = request.args.get("fetch", "false").lower() == "true"
return jsonify(_service().run_manual_discovery(platform_code=platform_code, fetch=fetch))
@market_intel_bp.route("/api/market_intel/candidate_preview")
@login_required
def market_intel_candidate_preview():
platform_code = request.args.get("platform", "all")
fetch = request.args.get("fetch", "false").lower() == "true"
min_band = request.args.get("min_band", "all")
limit = request.args.get("limit", default=50, type=int)
limit = max(1, min(limit or 50, 200))
return jsonify(
_service().build_candidate_preview(
platform_code=platform_code,
fetch=fetch,
min_band=min_band,
limit=limit,
)
)
@market_intel_bp.route("/api/market_intel/platform_seed_plan")
@login_required
def market_intel_platform_seed_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_platform_seed_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/platform_seed_write_guard")
@login_required
def market_intel_platform_seed_write_guard():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_platform_seed_write_guard(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/platform_seed_writer_plan")
@login_required
def market_intel_platform_seed_writer_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_platform_seed_writer_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/migration_blueprint")
@login_required
def market_intel_migration_blueprint():
return jsonify(_service().build_migration_blueprint())
@market_intel_bp.route("/api/market_intel/migration_apply_drill")
@login_required
def market_intel_migration_apply_drill():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_migration_apply_drill(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/migration_catalog_review")
@login_required
def market_intel_migration_catalog_review():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_migration_catalog_review(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/migration_live_smoke")
@login_required
def market_intel_migration_live_smoke():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_migration_live_smoke(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/live_db_inventory")
@login_required
def market_intel_live_db_inventory():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_live_db_inventory(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/seed_writer_cli_status")
@login_required
def market_intel_seed_writer_cli_status():
platform_code = request.args.get("platform", "all")
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_seed_writer_cli_status(
platform_code=platform_code,
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/write_approval_runbook")
@login_required
def market_intel_write_approval_runbook():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_write_approval_runbook(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/deployment_readiness")
@login_required
def market_intel_deployment_readiness():
return jsonify(_service().build_deployment_readiness())
from routes import market_intel_mcp_run_routes # noqa: E402,F401
from routes import market_intel_mcp_review_routes # noqa: E402,F401