meta-optimizer (Viviful) and this project share one Slack bot/app, but a
Slack app only supports a single Interactivity Request URL — so a single
approval_server must be able to tell which project's Baserow a button click
belongs to. Button values now carry a project tag ("approve:formacion:<id>"
instead of bare "approve:<id>"); approval_server.py parses it and routes
accordingly, with a registry slot to add other projects (e.g. "viviful") via
their Baserow REST credentials without importing their code.
Confirmed via api.slack.com/apps that the current Interactivity Request URL
points at a dead ngrok tunnel (ERR_NGROK_3200) — no approval server is
actually reachable in production today, for either project. Deployment is
being handled separately as part of the general app rollout.
Ports meta-optimizer's Meta Ads execution/approval/creative-analysis layer
(agent.py, meta_ads_client.py, baserow_client.py, slack_notifier.py,
approval_server.py) and replaces the per-vertical CPL model with the
PPL + monthly-capping-per-course model already used by leads-optimizer,
via a new airtable_client.py that shares Cursos/Familias/CentroCurso/
CursoMes/Leads Lake with that project and adds Meta Ads Campaigns /
MetaCampaignMes alongside its Google Ads Campaigns / GACampaignMes.