// Checks a console form against the config after the agent (or the owner) filled it. Read-only. // storebound console verify
[--from ] [--from-text ] [--json] // --from takes the JSON of the plan's verify.capture snippet (input states: aria-checked, checked, aria-selected) or page text. // storebound console verify play-app-record --url [--write] // apple-app-privacy: the page text of the App Privacy page (the Data Types section's per-type summaries; the App Store // Connect API has no App Privacy endpoint). play-app-record: the JSON of the plan's capture snippet (input states) or // the page text. play-content-rating, play-target-audience: the summary page text. play-app-content: the plan's // capture JSON (cards still showing "Start declaration"); play-store-settings, the other App content cards and // play-production-countries / -release: the page text after Save. apple-app-record: the App Store // Connect API (the app by bundle id; a GET) or, with --from-text, the page text. apple-age-rating: the API. // play-app-record also reads the Play Console app id from the URL Create app redirects to (/app//app-dashboard; // --url, or the capture JSON's url) and shows the play.appId change as a dry diff; --write saves it into the config (an // upsert; the only write of this command, and only to the local config file). // Exit 1 on any mismatch, and when nothing could be matched. Pure logic in cli/lib/console-verify.ts. MCP: console_verify. import { readFileSync } from 'node:fs'; import type { Ctx } from '../lib/ctx'; import { isPlanForm, PLAN_FORM_IDS } from '../lib/console-answers'; import { verifyAgeRatingApi, verifyAppRecordApi, type VerifyResult, verifyTable, verifyText } from '../lib/console-verify'; import { log, printJson } from '../lib/log'; import { appIdChange, appIdDiff, writePlayAppId } from '../lib/play-app-id'; import { basename } from 'node:path'; import * as rt from '../lib/rt'; async function readText(src: string): Promise { if (src === '-' || src === 'true') return rt.stdinText(); return readFileSync(src, 'utf8'); } export async function run(ctx: Ctx): Promise { const { config, root } = ctx.loaded; const args = ctx.args, json = args.has('json'); const form = args._[0]; if (!isPlanForm(form)) throw new Error(`console verify [--from-text ]: one of ${PLAN_FORM_IDS.join(', ')}`); const from = args.get('from') ?? args.get('from-text'), url = args.get('url'); const inline = args.get('text') ?? (url !== undefined ? url : undefined); if (url !== undefined && form !== 'play-app-record') throw new Error('console verify: --url is for play-app-record (the URL Create app redirects to)'); let r: VerifyResult; if (from !== undefined || inline !== undefined) { const text = inline ?? await readText(from!); if (!text.trim()) throw new Error('console verify: the page text is empty'); r = verifyText(form, config, text); } else if (form === 'apple-app-record' || form === 'apple-age-rating') { const bundleId = config.apple?.bundleId; if (!bundleId) throw new Error('console verify: apple.bundleId is not set'); const { ascClient } = await import('../apple/asc'); const c = await ascClient(root, bundleId, config.apple?.appId); if (form === 'apple-app-record') { const found = await c.asc('GET', `/v1/apps?filter[bundleId]=${encodeURIComponent(bundleId)}`); const hit = (found.data as { attributes: { bundleId: string; name?: string; sku?: string; primaryLocale?: string } }[]).find(a => a.attributes.bundleId === bundleId); r = verifyAppRecordApi(config, hit?.attributes ?? null); } else { const info = await c.editableAppInfo(); const age = await c.maybe(`/v1/appInfos/${info.id}/ageRatingDeclaration`); r = verifyAgeRatingApi(config, (age?.data?.attributes ?? null) as Record | null); } } else throw new Error(`console verify ${form}: pass the page text with --from-text (run \`storebound console plan ${form}\` for what to capture)`); // play-app-record: the app id from the redirect URL -> play.appId (dry diff; --write saves it) let appId: { change: ReturnType; written: boolean } | null = null; if (r.playAppId && config.play) { const change = appIdChange(config, r.playAppId); const written = args.has('write') && !args.has('dry') && !!ctx.loaded.path ? writePlayAppId(ctx.loaded.path, config, r.playAppId) : false; appId = { change, written }; } if (json) printJson(appId ? { ...r, appId } : r); else { console.log(verifyTable(r)); if (appId) { const file = basename(ctx.loaded.path || 'storebound.config.ts'); console.log(`\n${appIdDiff(appId.change, file)}`); if (appId.written) log('console', `wrote play.appId '${appId.change.to}' into ${file}`); else if (appId.change.changed) console.log('dry: run the same command with --write to save it'); } } if (!r.ok) process.exitCode = 1; }