feat(campaigns): answer "why won't this launch?" in the browser
A live sync against the real account failed with Meta code 100, subcode
4834011, and the only thing we stored was the literal string "Invalid
parameter". Meta had written an explanation — it puts one in
error_user_title and error_user_msg — and MetaError was discarding it.
Every explanatory field is now kept, describe() prefers the text written
for a person, and as_dict() carries the lot into the API response and the
stored sync_error.
That still left diagnosis needing a terminal, which is no good: the person
who has to attach a payment method or fix a Page id is a client, not a
developer. GET /campaigns/diagnostics runs seven ordered readiness checks
and returns a remedy with each failure. It stops at the first hard failure
— with no token every later check fails for the same reason, and five
identical errors hide the one that matters.
POST /campaigns/diagnostics/smoke-test closes the remaining gap: the unit
suite proves we send what we think we send, not that Meta accepts it. It
builds the real chain, reads back from Graph that every object is PAUSED,
and deletes in a finally. If cleanup fails, the ids come back in the
response rather than being abandoned in a real ad account.
Both routes are declared above /{campaign_id}. /diagnostics is a single
path segment, so the wildcard would otherwise answer it — the same
shadowing /discover and /adopt are already guarded against. Four tests go
through HTTP to pin the ordering, because the rest of this file's tests
call the functions directly and would pass against an unreachable
endpoint.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -126,6 +126,33 @@ cd maskanx-backend; npm run local # :8088
|
||||
cd maskanx-frontend; npm run dev
|
||||
```
|
||||
|
||||
### 1.6 Check the setup from the browser
|
||||
|
||||
Open the **Campaigns** page. The **Setup** panel at the top runs every check
|
||||
that can stop a launch and, for each failure, says what to do about it:
|
||||
|
||||
| Check | What it means when it fails |
|
||||
|---|---|
|
||||
| Meta access token | `META_ADS_ACCESS_TOKEN` is missing — add it in Settings → Environments |
|
||||
| Token is valid | Meta rejected the token; generate a new system user token |
|
||||
| Ad account | `META_ADS_ACCOUNT_ID` is unset, or the system user cannot reach it |
|
||||
| Account status | The ad account is disabled or unsettled — only fixable in Business Manager |
|
||||
| Payment method | No funding source. Add one in Business Manager → Billing |
|
||||
| Facebook Page | `META_PAGE_ID` is unset or unreachable. The panel lists the Pages your token *can* reach, so you can copy the right id |
|
||||
| Operator identity | `MASKANX_OPERATOR_TOKENS` is unset, so approvals cannot be attributed and launch stays blocked |
|
||||
|
||||
The panel is read-only — it creates nothing in Meta. Press **Re-check** after
|
||||
changing an environment variable.
|
||||
|
||||
Once every check is green, **Run connection test** becomes available. It
|
||||
builds a real campaign, ad set and ad in your account, reads back from Meta
|
||||
that all three are `PAUSED`, then deletes them. It is the only check that
|
||||
proves Meta accepts what MaskanX sends. Nothing can be spent — the objects
|
||||
are paused for their whole, few-second life — and if deletion ever fails,
|
||||
the ids are shown on screen so you can remove them in Ads Manager.
|
||||
|
||||
Nobody needs a terminal for any of this.
|
||||
|
||||
---
|
||||
|
||||
## Part 2 — Your first campaign
|
||||
@@ -310,6 +337,12 @@ Worth knowing, because the design gives up some convenience for it:
|
||||
|
||||
## Verifying it end to end
|
||||
|
||||
**If you are running the system, use the browser.** Campaigns page →
|
||||
**Setup** → **Run connection test** does everything described below, reports
|
||||
each step on screen, and needs no terminal. See §1.6.
|
||||
|
||||
The rest of this section is for developers working on the code.
|
||||
|
||||
The unit suite runs entirely against a fake transport: it proves the code
|
||||
sends what we think it sends, not that Meta accepts it. One opt-in test
|
||||
closes that gap by syncing a real campaign, reading back from Graph that
|
||||
|
||||
Reference in New Issue
Block a user