From ad7c20b555beaf9157c73e232211bff7931a0861 Mon Sep 17 00:00:00 2001 From: Mikhail Fisher Date: Fri, 11 Sep 2026 15:59:45 +0200 Subject: [PATCH 1/2] feat: report ads manager trial as cli access --- docs/agent/asa-management.md | 2 +- docs/agent/skills/adapty-cli-setup/SKILL.md | 2 +- skills/adapty-cli/references/cli-commands.md | 5 +++-- src/commands/asa/whoami.ts | 9 +++++++-- src/lib/asa-schemas.ts | 2 +- test/commands/asa.test.ts | 11 ++++++++++- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/docs/agent/asa-management.md b/docs/agent/asa-management.md index 78212ac..a436e71 100644 --- a/docs/agent/asa-management.md +++ b/docs/agent/asa-management.md @@ -17,7 +17,7 @@ Every `list` and `get` command in this file returns metadata only, no metrics. E | Command | Flags | Notes | |---|---|---| -| `asa whoami` | none | Company, how access was granted, Apple connection state. Run this first. No connected Apple Ads account or no active Ads Manager subscription answers `402 ads_manager_subscription_required` on every other `asa` command. | +| `asa whoami` | none | Company, how access was granted, Apple connection state. Run this first. Ads Manager access comes from the trial (`access_source: trial`) or a subscription (`payg`, `legacy`); without either, every other `asa` command answers `402 ads_manager_subscription_required`. | | `asa connect` | `--no-wait` optional | Prints the Apple authorization link and waits for the link to be completed; `--no-wait` returns immediately instead of waiting. | | `asa apps list` | pagination only | Apps promoted in Apple Search Ads. Its rows supply `--adam-id` for `campaigns create`. | | `asa orgs list` | pagination only | Apple Search Ads organizations. Each row carries two identifiers, not interchangeable: `internal_id` (a UUID) and `org_id` (Apple's numeric id). `--org` on `campaigns create` takes `internal_id` — passing the numeric `org_id` fails with "Invalid org ID format." `payment_model` (`LOC`/`PAYG`) tells you whether campaigns in that organization need Invoicing Options — see [Line of credit](#line-of-credit-loc-organizations). | diff --git a/docs/agent/skills/adapty-cli-setup/SKILL.md b/docs/agent/skills/adapty-cli-setup/SKILL.md index 0112dc7..559c323 100644 --- a/docs/agent/skills/adapty-cli-setup/SKILL.md +++ b/docs/agent/skills/adapty-cli-setup/SKILL.md @@ -129,7 +129,7 @@ the dashboard usually means the token is scoped elsewhere. | `ERROR no_code_minted` | Login started but printed no code | Read `$TMPDIR/adapty-setup/auth.out` | | `User code not found or expired` in the browser | The waiter died, or the TTL ran out | Step 1 again, and surface the new code faster | | `AuthRequiredError` after `AUTHED` | Almost always a stale `ADAPTY_TOKEN` | `unset ADAPTY_TOKEN`, re-check | -| `402 ads_manager_subscription_required` | Authenticated fine; the company has no Ads Manager subscription | **Not a setup bug.** Say so plainly and stop. No flag works around it | +| `402 ads_manager_subscription_required` | Authenticated fine; the company has no Ads Manager access — neither the trial nor a subscription | **Not a setup bug.** Say so plainly and stop. No flag works around it | | `NetworkError`, including certificate `-25291` noise | Network or sandbox trust-store access failed before authentication could be checked | Return to the caller's quiet preflight retry. Never install or log in | ## ADAPTY_TOKEN diff --git a/skills/adapty-cli/references/cli-commands.md b/skills/adapty-cli/references/cli-commands.md index ad2ea8d..3a52043 100644 --- a/skills/adapty-cli/references/cli-commands.md +++ b/skills/adapty-cli/references/cli-commands.md @@ -155,8 +155,9 @@ There is no file-based hand-off flag: the config always rides in the URL. ## Apple Search Ads (`asa` topic) Different service behind the same token. **No `--app`**: every command is scoped to the company the token -belongs to. Requires a connected Apple Ads account plus an active Ads Manager subscription — without one -every `asa` command answers `402 ads_manager_subscription_required`. Start with `asa whoami`. +belongs to. Requires a connected Apple Ads account plus Ads Manager access — the 14-day trial counts, same +as a paid subscription. Without access every `asa` command answers `402 ads_manager_subscription_required`. +Start with `asa whoami`: its `access_source` says which one granted access (`trial`, `payg`, `legacy`). | Command | Required flags / notes | |-------------------------------------|----------------------------------------------------------------------------| diff --git a/src/commands/asa/whoami.ts b/src/commands/asa/whoami.ts index bcaedfe..fff4cea 100644 --- a/src/commands/asa/whoami.ts +++ b/src/commands/asa/whoami.ts @@ -28,8 +28,13 @@ grouped page may project to before it is refused.`; } if (result.access_source === 'none') { - this.log('\nNo active Ads Manager subscription for this company: connecting an account works, but every'); - this.log('data command answers 402 until the subscription is in place.'); + this.log('\nNo Ads Manager access for this company: connecting an account works, but every data command'); + this.log('answers 402 until the Ads Manager trial is started or a subscription is in place.'); + } + + if (result.access_source === 'trial') { + this.log('\nAccess comes from the Ads Manager trial: every command works, and they stop working when'); + this.log('the trial ends without a subscription.'); } return result; diff --git a/src/lib/asa-schemas.ts b/src/lib/asa-schemas.ts index 1f1495a..812a842 100644 --- a/src/lib/asa-schemas.ts +++ b/src/lib/asa-schemas.ts @@ -1,4 +1,4 @@ -export type AsaAccessSource = 'allowlist' | 'legacy' | 'none' | 'payg'; +export type AsaAccessSource = 'allowlist' | 'legacy' | 'none' | 'payg' | 'trial'; export type AsaAppleCredentialsStatus = 'active' | 'expired' | 'invalid' | 'unset'; diff --git a/test/commands/asa.test.ts b/test/commands/asa.test.ts index e2db483..ed707f0 100644 --- a/test/commands/asa.test.ts +++ b/test/commands/asa.test.ts @@ -43,10 +43,19 @@ describe('asa', () => { fetchStub = mockFetch([{ ...ME_RESPONSE, access_source: 'none', apple_credentials_status: 'unset' }]); const { stdout } = await runCommand('asa whoami'); expect(stdout).to.contain('Access Source: none'); - expect(stdout).to.contain('No active Ads Manager subscription'); + expect(stdout).to.contain('No Ads Manager access'); + expect(stdout).to.contain('trial'); expect(stdout).to.contain('402'); }); + it('whoami reports trial access and says it ends with the trial', async () => { + fetchStub = mockFetch([{ ...ME_RESPONSE, access_source: 'trial' }]); + const { stdout } = await runCommand('asa whoami'); + expect(stdout).to.contain('Access Source: trial'); + expect(stdout).to.contain('Ads Manager trial'); + expect(stdout).to.not.contain('402'); + }); + it('whoami prints the budgets this company actually gets', async () => { fetchStub = mockFetch([ { From 6e0b92128db8dc302507698ee7f1eafd512a2ddc Mon Sep 17 00:00:00 2001 From: Mikhail Fisher Date: Mon, 14 Sep 2026 13:53:58 +0200 Subject: [PATCH 2/2] chore: bump version to 0.8.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50e3264..1a561ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "adapty", "description": "Adapty command line interface", - "version": "0.8.5", + "version": "0.8.6", "author": "Adapty team ", "bin": { "adapty": "./bin/run.js"