Skip to content

feat(v4): expose deferred GetKeywordsSuggestion, AdImageAssociation, PayCampaignsByCard (#459)#462

Merged
axisrow merged 4 commits into
mainfrom
feat/v4-deferred-methods
May 29, 2026
Merged

feat(v4): expose deferred GetKeywordsSuggestion, AdImageAssociation, PayCampaignsByCard (#459)#462
axisrow merged 4 commits into
mainfrom
feat/v4-deferred-methods

Conversation

@axisrow

@axisrow axisrow commented May 29, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the functional deferred v4 Live methods from #459 as typed CLI commands (no raw --json), with focused dry-run tests.

Method Command Notes
GetKeywordsSuggestion v4keywords get-suggestion --keyword … read-only; repeatable seed phrases → {"Keywords":[…]}
AdImageAssociation v4adimage get / v4adimage set Get via SelectionCriteria; Set --association AD_ID[=HASH] (attach/detach)
PayCampaignsByCard v4finance pay-campaigns-by-card dry-run-only — undocumented + financially sensitive; live path stays closed

Finance disclaimer

All v4 Live finance commands now carry an explicit "Not tested against the live API" warning in --help and in the README V4 Live Finance section (per maintainer request).

Intentionally NOT exposed (documented in README)

  • DeleteReport / DeleteOfflineReport — disabled by Yandex (docs list them under «Отключенные методы» / «Метод отключен. Используйте API версии 5»); use the v5 reports API. These were in the issue's mechanical method list but their contracts (docs-verified 2026-05-28) mark them disabled.
  • PingAPI / PingAPI_X / GetVersion / GetAvailableVersions — diagnostics/version probes, no documented request shape.

Registries / gates updated

  • smoke_matrix: SAFE += v4adimage.get, v4keywords.get-suggestion; DANGEROUS += v4adimage.set, v4finance.pay-campaigns-by-card
  • api_coverage_payloads v4 WSDL-exclusions; EXPECTED_COMMANDS

Testing

  • New focused dry-run tests: tests/test_v4keywords.py, tests/test_v4adimage.py, plus pay-campaigns-by-card cases in tests/test_v4finance_money.py
  • Full suite green: 2033 passed, 47 skipped
  • ruff check . clean

Closes #459

🤖 Generated with Claude Code

axisrow and others added 2 commits May 29, 2026 20:40
…PayCampaignsByCard (#459)

Adds typed CLI commands for the functional v4 Live methods that were
deferred from the 0.4.0 surface:

- v4keywords get-suggestion (GetKeywordsSuggestion, read-only)
- v4adimage get/set (AdImageAssociation, Get/Set; no raw --json)
- v4finance pay-campaigns-by-card (PayCampaignsByCard, dry-run-only —
  undocumented + financially sensitive, so the live path stays closed)

All v4 Live finance commands now carry an explicit "Not tested against
the live API" disclaimer in --help and README.

Intentionally NOT exposed (documented in README):
- DeleteReport / DeleteOfflineReport — disabled by Yandex (use v5 reports)
- PingAPI / PingAPI_X / GetVersion / GetAvailableVersions — diagnostics probes

Registries updated: smoke_matrix (SAFE: v4adimage.get, v4keywords.get-suggestion;
DANGEROUS: v4adimage.set, v4finance.pay-campaigns-by-card), api_coverage v4
WSDL-exclusions, EXPECTED_COMMANDS. New focused dry-run tests; full suite green
(2033 passed).

Closes #459

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diagnostic helper distinguishing a real docs move (clean 404) from a
SmartCaptcha IP rate-limit (302→showcaptcha) for the 4 v5 docs URLs that
preflight flagged GONE. Manual-only; not wired into CI.

Refs #460, #128

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@axisrow axisrow mentioned this pull request May 29, 2026
@axisrow

axisrow commented May 29, 2026

Copy link
Copy Markdown
Owner Author

@claude review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production.

@claude

claude Bot commented May 29, 2026

Copy link
Copy Markdown

Claude finished @axisrow's task in 1m 53s —— View job


Review: PR #462 — v4 deferred methods

  • Read the diff vs origin/main
  • Review v4adimage.py (get/set, association parsing)
  • Review v4keywords.py (get-suggestion)
  • Review v4finance.py (pay-campaigns-by-card, dry-run-only)
  • Check registries/gates (smoke_matrix, api_coverage, EXPECTED_COMMANDS)
  • Post review findings

No critical bugs, security vulnerabilities, or data-loss risks found. The implementation is consistent with the existing v4 Live patterns and well guarded. Summary below.

What holds up well

  • pay-campaigns-by-card is correctly fenced off. _require_dry_run(dry_run) blocks any live send, the command is in DANGEROUS in smoke_matrix, excluded in api_coverage_payloads, and the contract marks it PARAM_UNDOCUMENTED / live_probe_allowed=False. The financial token is masked in the dry-run body via _masked_finance_body. This matches the stated "live path stays closed" intent.
  • Money parsing is safe. parse_v4_money_sum rejects non-positive, non-finite, and malformed amounts before the body is built (direct_cli/v4/money.py:16).
  • v4adimage set validation is solid — non-integer / non-positive / duplicate AdID all raise UsageError, the 10000 cap is enforced, and attach/detach semantics (omit AdImageHash → detach) match the documented contract (v4adimage.py:62).
  • Field names match the contracts exactly (AdIDS, CampaignIDS, StatusAdImageModerate, etc. vs. v4_contracts.py:526), and all registries (cli.py, EXPECTED_COMMANDS, smoke_matrix, api_coverage_payloads) are updated consistently. Tests cover dry-run shapes, error paths, and contract wiring.

Minor, non-blocking notes (not critical — flagging for awareness only)

  1. scripts/probe_drift_urls.sh:39 hard-codes https://yandex.ru/dev/direct/doc/... URL string literals. This sits adjacent to the CLAUDE.md "No URL literals outside the registry" convention (reports drift checker: hard-coded URLs retired by Yandex (type / fields-list / period / spec.html) #426). It's a manual-only diagnostic (not wired into CI) probing candidate paths that by definition aren't in the registry, so it doesn't break anything — but it's the same pattern that caused the captcha-cache poisoning, so worth a deliberate exception comment or keeping an eye on.
  2. Stale contract note: the AdImageAssociation contract notes still say "No CLI command is exposed yet; this row only records the contract." (v4_contracts.py:558) — now inaccurate since this PR exposes v4adimage get/set. Cosmetic only.

Neither note affects functionality. From a correctness/security/data-loss standpoint this PR is in good shape.
· feat/v4-deferred-methods

- v4_contracts.py: update AdImageAssociation note — the method is now
  exposed as `v4adimage get`/`set` (was "No CLI command is exposed yet").
- probe_drift_urls.sh: document the deliberate exception to the
  "No URL literals outside the registry" rule (#426) — the script probes
  candidate paths not yet in the registry, is read-only, and never writes
  to any docs cache, so it cannot poison it.

Both raised as non-blocking notes by the reviewer; no functional change.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@axisrow

axisrow commented May 29, 2026

Copy link
Copy Markdown
Owner Author

@claude review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production.

@claude

claude Bot commented May 29, 2026

Copy link
Copy Markdown

Claude finished @axisrow's task in 2m 31s —— View job


Review: PR #462 — v4 deferred methods (focused: bugs / security / data-loss / perf)

  • Read the diff vs origin/main
  • Review v4adimage.py (get/set, association parsing)
  • Review v4keywords.py (get-suggestion)
  • Review v4finance.py (pay-campaigns-by-card)
  • Check registries/gates & contracts
  • Post review findings

No critical bugs, security vulnerabilities, or data-loss risks found. This is a clean, well-fenced implementation. Details below.

Correctness / safety — holds up

  • pay-campaigns-by-card cannot send live. _require_dry_run is the first statement (v4finance.py:711); it's in DANGEROUS (smoke_matrix.py), excluded from coverage payloads, and the contract is live_probe_allowed=False. The token is masked via _masked_finance_body (v4finance.py:119). Live path is genuinely closed.
  • No token leakage. All finance dry-runs route through _masked_finance_body, which overwrites finance_token with <redacted> after build_v4_body. v4adimage/v4keywords carry no token at all.
  • v4adimage set validation is robust (v4adimage.py:62): non-integer / non-positive / duplicate AdID all raise UsageError, the 10000 cap is enforced, and AD_ID=HASH splits with split("=", 1) so base64 hashes containing = padding are preserved correctly. Omitting the hash → detach matches the documented contract.
  • Field names match the contract exactly (AdIDS, CampaignIDS, StatusAdImageModerate; v4_contracts.py:526), and the param shape is documented (PARAM_OBJECT), so call_v4's fail-closed shape guard (v4/__init__.py:42) is satisfied.
  • Per-subcommand safety split is right: v4adimage.get (read) → SAFE, v4adimage.set (mutation) → DANGEROUS. command_category keys on the subcommand, so the mutating half stays out of any auto-runner.
  • Registries are consistentcli.py, EXPECTED_COMMANDS, smoke_matrix, api_coverage_payloads, and the contract notes are all updated together.

Minor, non-blocking (awareness only — not critical)

  1. Broad live read via SAFE smoke. v4adimage.get is in the SAFE list and, with no filters, sends {"Action":"Get","SelectionCriteria":{}} — i.e. up to 10000 associations per the docs. It's strictly read-only so there's no harm, just a larger-than-typical production read when the safe-smoke script runs. Worth knowing; not a defect.
  2. Empty-token CSV edge. In _get_param, a degenerate value like --logins "," passes the if logins: truthiness check but parse_csv_strings(",") returns None, so SelectionCriteria["Logins"] is set to null. Read-only and harmless; only flagging for completeness.
  3. scripts/probe_drift_urls.sh URL literals (carried from the prior review) — manual-only diagnostic, not wired into CI, so it doesn't break the "no URL literals outside the registry" invariant, but it's the same pattern behind reports drift checker: hard-coded URLs retired by Yandex (type / fields-list / period / spec.html) #426. A one-line exception comment would make the intent explicit.

From a correctness, security, and data-loss standpoint this PR is in good shape to merge. I was unable to execute the test suite in this environment (pytest invocation not permitted by the sandbox), so I relied on static review — the PR reports the full suite green (2033 passed, 47 skipped).
· feat/v4-deferred-methods

A degenerate value like --logins "," made parse_csv_strings return None,
which was written as "Logins": null into the request body. Now the key is
set only when there are real values, never null/empty. Same guard applied
to AdImageHashes/AdIDS/CampaignIDS. Malformed ID lists still raise
UsageError loudly (parse_ids rejects them).

Raised as a non-blocking note in review of PR #462; added two edge-case
tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@axisrow

axisrow commented May 29, 2026

Copy link
Copy Markdown
Owner Author

@claude review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production.

@claude

claude Bot commented May 29, 2026

Copy link
Copy Markdown

Claude finished @axisrow's task in 1m 25s —— View job


Review: PR #462 — v4 deferred methods (focused: bugs / security / data-loss / perf)

  • Read the diff vs origin/main
  • Review v4adimage.py (get/set, association parsing)
  • Review v4keywords.py (get-suggestion)
  • Review v4finance.py (pay-campaigns-by-card)
  • Check registries/gates & contracts
  • Post review findings

No critical bugs, security vulnerabilities, or data-loss risks found. This is the third pass and the implementation has only tightened since the prior reviews. Details below.

Correctness / safety — verified

  • pay-campaigns-by-card is genuinely closed to live. _require_dry_run(dry_run) is the first statement (v4finance.py:702); the contract is PARAM_UNDOCUMENTED + live_probe_allowed=False (v4_contracts.py:127). Even if the dry-run guard were bypassed, call_v4's fail-closed guard would still refuse it — an undocumented param shape at SAFETY_DANGEROUS raises UsageError rather than posting (v4/__init__.py:43-49). Belt and suspenders. It's also in DANGEROUS (smoke_matrix.py:172) and excluded from coverage payloads.
  • No finance-token leakage. The dry-run routes through _masked_finance_body, which overwrites finance_token with <redacted> after build_v4_body (v4finance.py:119-124). v4adimage/v4keywords carry no token.
  • v4adimage set validation is robust (v4adimage.py:70-108): non-integer / non-positive / duplicate AdID all raise UsageError; the 10000 cap is enforced; AD_ID=HASH uses split("=", 1) so base64 = padding in the hash is preserved; omitting the hash → detach matches the contract.
  • Prior CSV-null edge is fixed. The earlier review noted --logins "," could write "Logins": null. Commit bdb5a7e now gates every SelectionCriteria key on a truthiness check (v4adimage.py:41-62), so degenerate CSV omits the key entirely; malformed ID lists still raise UsageError via parse_ids. Two edge-case tests added.
  • get-suggestion input is clean — empty/whitespace seeds are stripped and an all-empty set raises UsageError (v4keywords.py:20-23).
  • Money parsing stays safeparse_v4_money_sum rejects non-positive / non-finite / malformed amounts before the body is built; _campaign_ids_param rejects non-positive IDs.
  • Registries consistentcli.py, EXPECTED_COMMANDS, smoke_matrix, api_coverage_payloads, and the now-corrected AdImageAssociation contract note are all updated together. Read/write safety split is right (v4adimage.get→SAFE, .set→DANGEROUS).

Minor, non-blocking (awareness only)

  1. pay-campaigns-by-card dry-run omits ContractID/PayMethod that the documented PayCampaigns shape carries (v4finance.py:734-742). The docstring acknowledges this is a best-effort preview of an undocumented method, and the live path is closed, so it's harmless — just noting the dry-run body is not a complete mirror.
  2. scripts/probe_drift_urls.sh URL literals (carried from prior reviews) — manual-only diagnostic, not wired into CI, so it doesn't violate the "no URL literals outside the registry" invariant, but it's the same pattern behind reports drift checker: hard-coded URLs retired by Yandex (type / fields-list / period / spec.html) #426. A one-line exception comment would make intent explicit.

From a correctness, security, and data-loss standpoint this PR is in good shape to merge. I relied on static review — the PR reports the full suite green (2033 passed, 47 skipped); I was unable to execute pytest in this environment.
· feat/v4-deferred-methods

@axisrow

axisrow commented May 29, 2026

Copy link
Copy Markdown
Owner Author

Спасибо за третий проход. Триаж двух non-blocking замечаний:

  1. pay-campaigns-by-card dry-run опускает ContractID/PayMethodSKIP (намеренно). Метод PARAM_UNDOCUMENTED; по contract-source rule мы не достраиваем недокументированные поля. Dry-run явно помечен в docstring как best-effort превью, а live-путь закрыт (_require_dry_run + fail-closed guard). Добавлять поля «по аналогии с PayCampaigns» было бы выдумыванием wire-shape без источника.

  2. probe_drift_urls.sh URL-литералыALREADY_FIXED в коммите e5c42ca. Explicit-exception комментарий уже в файле (строки 10–14): литералы допустимы, потому что скрипт пробирует кандидаты путей, которых по определению нет в реестре, выполняет read-only HTTP-пробы и никогда не пишет в кэш доков, поэтому отравить его не может. Diff vs origin/main показывает литералы, но комментарий рядом с ними уже объясняет исключение.

Ни одного FIX-вердикта — перехожу к проверке CI и мержу.

@axisrow axisrow merged commit e86c5ae into main May 29, 2026
6 checks passed
@axisrow axisrow deleted the feat/v4-deferred-methods branch May 29, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v4 Live: expose deferred methods not shipped in 0.4.0 CLI

1 participant