# Checklist: bezpečný AI agent pro Ads API

Pracovní checklist pro připojení AI agenta na Meta Ads, Google Ads nebo další reklamní platformu tak, aby credential nikdy nebyl v promptu, repozitáři ani shellové historii.

> **Zásada:** token, API key, service-account JSON, heslo ani 1Password secret reference nepatří do chatu, Markdownu, connection profile ani do commitu.

---

## 0. Ujasni si scope

- [ ] Mám explicitní souhlas pracovat s konkrétním reklamním účtem.
- [ ] Vím, zda je cílem report, draft, nebo live změna.
- [ ] Pro live změnu mám jasně daný cíl, rozpočet, měření a osobu, která ji schválila.
- [ ] Vím, kdo může změnit oprávnění nebo token zneplatnit.

## 1. Najdi primární dokumentaci

Začni u oficiálního zdroje platformy, ne u blogu nebo náhodného GitHub repozitáře.

| Platforma | Dokumentace |
| --- | --- |
| Meta Ads | <https://developers.facebook.com/documentation/ads-commerce/marketing-api> |
| Meta setup | <https://developers.facebook.com/documentation/ads-commerce/marketing-api/get-started> |
| Google Ads | <https://developers.google.com/google-ads/api> |
| ChatGPT Ads | <https://developers.openai.com/ads/api-overview> |
| TikTok Ads | <https://business-api.tiktok.com/portal/docs> |
| Pinterest Ads | <https://developers.pinterest.com/docs/api/v5/> |
| RTB House | <https://api.panel.rtbhouse.com/api/docs> |

- [ ] Ověřil/a jsem aktuální API verzi a changelog.
- [ ] Znám autentizační model platformy.
- [ ] Znám minimum oprávnění pro reporting a zvlášť pro mutace.
- [ ] Znám první read-only endpoint pro ověření účtu.
- [ ] Znám rate limit a pravidla pro retry.

### Meta minimum

- [ ] System user má přístup k cílovému ad accountu.
- [ ] Appka je na system userovi nainstalovaná.
- [ ] Token má `ads_read` pro reporting, případně `ads_management` pro změny.
- [ ] Používám explicitně verzovanou Graph API cestu.
- [ ] První request načte účet a jeho `currency`, `timezone_name` a `account_status`.

### Google Ads minimum

- [ ] V Google Cloud projektu je zapnuté Google Ads API.
- [ ] Service account má přímý přístup k cílovému účtu nebo MCC.
- [ ] Vím, zda je připojený účet `client`, nebo `manager`.
- [ ] U MCC je vybraný výchozí cílový customer ID pro reporting.

## 2. Vytvoř platformní skill

- [ ] Skill má výstižný název a description, podle kterého se správně načte.
- [ ] Explicitně říká, že reporting je read-only.
- [ ] Rozlišuje režimy `report`, `draft` a `execute`.
- [ ] Před první prací ověřuje account scope read-only requestem.
- [ ] Zastaví se, pokud účet není jednoznačný.
- [ ] Nové entity vytváří jako `PAUSED`, kde to platforma dovoluje.
- [ ] Vyžaduje validate-only před zápisem, kde ho API podporuje.
- [ ] Po zápisu provede read-back změněného objektu.
- [ ] Destruktivní akce vyžadují explicitní potvrzení.
- [ ] Neobsahuje klientská ID, výkon, tokeny ani jiné credentialy.
- [ ] Endpointy a payloady má oddělené v referencích, aby základní instrukce nebyly zbytečně dlouhé.

### Minimální struktura

```text
.opencode/skills/meta-marketing-api/
├── SKILL.md
└── references/
    ├── core-operations.md
    └── official-links.md
```

## 3. Nastav, aby se skill sám doplňoval

Když agent musí během runu něco dohledat, protože to skill neobsahuje, má se to zapsat zpátky do skillu. Příště se to pak nehledá znovu.

- [ ] Skill má místo, kam se doplnění zapisuje (`SKILL.md` nebo `references/`).
- [ ] Skill obsahuje instrukci, aby agent po dohledání navrhl konkrétní doplnění.
- [ ] Součástí návrhu je přesný text, kontext zadání a odkaz na oficiální dokumentaci.
- [ ] Agent změnu nezapisuje sám, ale nechává ji ke schválení.
- [ ] Do skillu se nikdy nedostane client ID, výkon ani credentials.
- [ ] Základní `SKILL.md` zůstává krátký; detaily jdou do referencí.
- [ ] Původní verze skillu zůstává zachovaná.

### Ověření na testovacích zadáních

- [ ] Připravil/a jsem 3–5 realistických zadání.
- [ ] Každá kontrola je binární ano/ne, ne pocitová známka.
- [ ] Když se něco nepovede, promítne se to do skillu nebo do referencí.

### Příklady binárních kontrol

- [ ] Výstup použil jen účet vybraný v connection profile?
- [ ] Zůstal agent v read-only režimu, když zadání nechtělo změnu?
- [ ] Obsahuje výstup období, zdroj dat, metodu měření a další krok?
- [ ] Zastavil se agent při nejednoznačném scope?
- [ ] Neobsahuje výstup token, secret reference ani raw API response?
- [ ] Ověřil si agent endpoint a verzi v oficiální dokumentaci místo z paměti?

## 4. Ulož credential do 1Passwordu

Vytvoř jeden vault pro klienta. V něm samostatnou položku pro každou platformu. Credential ulož do concealed fieldu.

| Položka | Povinný field |
| --- | --- |
| `Meta Ads API` | `META_ACCESS_TOKEN` |
| `Google Ads API` | `GOOGLE_SERVICE_ACCOUNT_JSON` |
| `ChatGPT Ads API` | `OPENAI_ADS_API_KEY` |
| `Pinterest Ads API` | `PINTEREST_ACCESS_TOKEN` |
| `RTB House API` | `RTB_HOUSE_API_TOKEN` |
| `TikTok Ads API` | `TIKTOK_ACCESS_TOKEN` |

- [ ] Credential není v poznámce ani v custom text fieldu bez maskování.
- [ ] Credential není v `.env`, shell history ani v repozitáři.
- [ ] Nastavil/a jsem minimální nutná oprávnění na straně reklamní platformy.
- [ ] V 1Passwordu mám zapnutou integraci pro CLI nebo Desktop SDK.
- [ ] Vím, jak token zneplatnit a nahradit při incidentu.

## 5. Napoj runtime na 1Password

### Jednodušší start přes CLI

- [ ] Používám `op run` pro předání secrets jen konkrétnímu procesu.
- [ ] Příkaz ani jeho log nevypisují hodnotu tokenu.
- [ ] Nepředávám token přes URL ani shell argument.
- [ ] Proces dostává jen minimum secrets, které opravdu potřebuje.

Dokumentace: <https://www.1password.dev/cli/secret-references>

### Bezpečnější varianta přes lokální daemon a Desktop SDK

- [ ] Agent posílá jen strukturovaný request lokálnímu clientovi.
- [ ] Secret se načítá až uvnitř lokálního daemon procesu.
- [ ] Daemon drží credential jen v paměti a má krátký timeout.
- [ ] Každý client profile má vlastní lokální socket s právy `600`.
- [ ] API hosty a cesty jsou allowlistované.
- [ ] API chyby jsou redigované a nevrací raw upstream response.

## 6. Vytvoř netajný connection profile

Ulož ho mimo skill a mimo sdílený repozitář, například do:

```text
<projekt>/.opencode/ads-api-connections/<client>.json
```

- [ ] Adresář má práva `700`.
- [ ] Adresář je v `.gitignore`.
- [ ] Profil je vlastněný aktuálním uživatelem a není symlink.
- [ ] Profil obsahuje jen netajná metadata.
- [ ] Platforma je označena jako ověřená až po úspěšném read-back probe.

### Vzor

```json
{
  "version": 2,
  "name": "example-client",
  "onepassword_account": "my-1password-account",
  "onepassword_vault": "Example Client API",
  "platforms": {
    "google_ads": {
      "auth_type": "service_account_json",
      "account_type": "client",
      "customer_id": "1234567890",
      "api_version": "v25"
    },
    "meta": {
      "ad_account_id": "act_1234567890",
      "api_version": "v25.0"
    }
  }
}
```

### Do profilu patří

- [ ] název klienta,
- [ ] 1Password account a vault,
- [ ] ad account ID, customer ID, MCC ID nebo advertiser ID,
- [ ] API verze,
- [ ] typ účtu a ověřený scope,
- [ ] datum posledního ověření.

### Do profilu nikdy nepatří

- [ ] access token nebo API key,
- [ ] service-account JSON,
- [ ] heslo,
- [ ] secret reference,
- [ ] raw API response.

## 7. Proveď první bezpečný probe

- [ ] První request je read-only.
- [ ] Ověřil/a jsem název účtu, ID, měnu, časové pásmo a status.
- [ ] Pokud se vrátilo více účtů, správný scope potvrdil člověk.
- [ ] Výsledek probe odpovídá očekávanému klientovi.
- [ ] Teprve teď je platforma v profilu označená jako ověřená.

## 8. Pravidla pro běžný provoz

- [ ] Reporting jde pouze přes GET/Insights requesty.
- [ ] Draft obsahuje payload, ale nic nezapisuje.
- [ ] Execute vyžaduje explicitní zadání v aktuální konverzaci.
- [ ] Create operace mají bezpečný status `PAUSED`/`DISABLED`, kde je podporovaný.
- [ ] Před zápisem proběhne validace payloadu.
- [ ] Po zápisu proběhne read-back.
- [ ] Při rate limitu nejdřív načtu stav a až pak řeším retry.
- [ ] Mazání nebo archivace vyžadují explicitní potvrzení „ano, znič to“.

## 9. Incident: token se dostal do chatu nebo repozitáře

- [ ] Okamžitě token zneplatním na straně platformy.
- [ ] Vydám nový token s minimálním nutným scope.
- [ ] Nový token uložím jen do 1Passwordu.
- [ ] Zkontroluji historii konverzace, soubory projektu, `.env` a logy.
- [ ] Ověřím, že v connection profile nezůstala secret reference ani hodnota tokenu.
- [ ] Udělám nový read-only probe s novým credentialem.

---

## Krátká kontrola před každou live změnou

1. **Pro kterého klienta a účet přesně pracuji?**
2. **Je to report, draft, nebo execute?**
3. **Je scope ověřený?**
4. **Je payload validovaný?**
5. **Vznikne nový objekt v bezpečném paused stavu?**
6. **Mám explicitní potvrzení pro live změnu?**
7. **Umím po změně udělat read-back?**

Když je u některé odpovědi „nevím“, správný další krok není hádat. Je zastavit se.
