@gpc-cli/cli 0.9.65 → 0.9.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  createProgram,
4
4
  handleCliError
5
- } from "./chunk-DQD2S5QH.js";
5
+ } from "./chunk-IUG4225Q.js";
6
6
  export {
7
7
  createProgram,
8
8
  handleCliError
@@ -59,6 +59,59 @@ function registerPreflightCommand(program) {
59
59
  scanners: "secrets,billing,privacy"
60
60
  });
61
61
  });
62
+ cmd.command("signing").description("Check signing key consistency across releases (requires auth)").action(async (_options, subcmd) => {
63
+ const parentOpts = subcmd.parent?.parent?.opts() ?? {};
64
+ const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
65
+ const config = await loadConfig();
66
+ const packageName = parentOpts["app"] ?? config.app;
67
+ if (!packageName) {
68
+ throw new GpcError(
69
+ "No app configured",
70
+ "MISSING_APP",
71
+ 2,
72
+ "Set a default app with 'gpc config set app <package>' or use --app"
73
+ );
74
+ }
75
+ const { resolveAuth } = await import("@gpc-cli/auth");
76
+ const client = await resolveAuth({
77
+ serviceAccountPath: config.auth?.serviceAccount
78
+ });
79
+ const accessToken = await client.getAccessToken();
80
+ const { checkSigningConsistency } = await import("@gpc-cli/core");
81
+ const result = await checkSigningConsistency(accessToken, packageName);
82
+ if (jsonMode) {
83
+ console.log(JSON.stringify(result, null, 2));
84
+ } else {
85
+ console.log("");
86
+ console.log(bold("Signing Key Consistency"));
87
+ console.log("");
88
+ if (result.firstRelease) {
89
+ console.log(
90
+ ` ${dim("\u2139")} First release (v${result.currentVersionCode}): ${result.currentFingerprint}`
91
+ );
92
+ console.log(` ${dim("Nothing to compare against yet.")}`);
93
+ } else if (result.consistent) {
94
+ console.log(
95
+ ` ${green("\u2713")} Consistent: v${result.previousVersionCode} \u2192 v${result.currentVersionCode}`
96
+ );
97
+ console.log(` ${dim("Fingerprint:")} ${result.currentFingerprint}`);
98
+ } else {
99
+ console.log(
100
+ ` ${red("\u2717")} Signing key changed between v${result.previousVersionCode} and v${result.currentVersionCode}`
101
+ );
102
+ console.log(` ${dim("Previous:")} ${result.previousFingerprint}`);
103
+ console.log(` ${dim("Current:")} ${result.currentFingerprint}`);
104
+ console.log("");
105
+ console.log(
106
+ ` ${yellow("\u26A0")} If intentional, register the new key in Play Console before September 2026.`
107
+ );
108
+ }
109
+ console.log("");
110
+ }
111
+ if (!result.consistent) {
112
+ process.exitCode = 6;
113
+ }
114
+ });
62
115
  }
63
116
  async function runPreflightAction(program, file, options) {
64
117
  if (!file && !options["metadata"] && !options["source"]) {
@@ -147,4 +200,4 @@ async function runPreflightAction(program, file, options) {
147
200
  export {
148
201
  registerPreflightCommand
149
202
  };
150
- //# sourceMappingURL=preflight-KIWZPFTX.js.map
203
+ //# sourceMappingURL=preflight-BL67VGUX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/preflight.ts"],"sourcesContent":["// Named exports only. No default export.\n\nimport type { Command } from \"commander\";\nimport { runPreflight, getAllScannerNames, formatOutput, GpcError } from \"@gpc-cli/core\";\nimport type { FindingSeverity } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { green, red, yellow, dim, bold } from \"../colors.js\";\n\nconst SEVERITY_ICONS: Record<FindingSeverity, string> = {\n critical: \"✗\",\n error: \"✗\",\n warning: \"⚠\",\n info: \"ℹ\",\n};\n\nfunction severityColor(severity: FindingSeverity, text: string): string {\n switch (severity) {\n case \"critical\":\n return bold(red(text));\n case \"error\":\n return red(text);\n case \"warning\":\n return yellow(text);\n case \"info\":\n return dim(text);\n }\n}\n\nexport function registerPreflightCommand(program: Command): void {\n const cmd = program\n .command(\"preflight [file]\")\n .description(\"Pre-submission compliance scanner for AAB files (offline)\")\n .option(\n \"--fail-on <severity>\",\n \"Fail if any finding meets or exceeds severity: critical, error, warning, info\",\n \"error\",\n )\n .option(\"--scanners <names>\", \"Comma-separated scanner names to run (default: all)\")\n .option(\"--metadata <dir>\", \"Path to metadata directory (Fastlane format) for listing checks\")\n .option(\"--source <dir>\", \"Path to source directory for code scanning\")\n .option(\"--config <path>\", \"Path to .preflightrc.json config file\")\n .action(async (file: string | undefined, options) => {\n await runPreflightAction(program, file, options);\n });\n\n // Subcommand: preflight manifest\n cmd\n .command(\"manifest <file>\")\n .description(\"Run manifest scanner only\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (file: string, options) => {\n await runPreflightAction(program, file, { ...options, scanners: \"manifest\" });\n });\n\n // Subcommand: preflight permissions\n cmd\n .command(\"permissions <file>\")\n .description(\"Run permissions scanner only\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (file: string, options) => {\n await runPreflightAction(program, file, { ...options, scanners: \"permissions\" });\n });\n\n // Subcommand: preflight metadata\n cmd\n .command(\"metadata <dir>\")\n .description(\"Run metadata scanner on a listings directory\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (dir: string, options) => {\n await runPreflightAction(program, undefined, {\n ...options,\n metadata: dir,\n scanners: \"metadata\",\n });\n });\n\n // Subcommand: preflight codescan\n cmd\n .command(\"codescan <dir>\")\n .description(\"Run code scanners (secrets, billing, privacy) on source directory\")\n .option(\"--fail-on <severity>\", \"Fail threshold\", \"error\")\n .action(async (dir: string, options) => {\n await runPreflightAction(program, undefined, {\n ...options,\n source: dir,\n scanners: \"secrets,billing,privacy\",\n });\n });\n\n // Subcommand: preflight signing\n cmd\n .command(\"signing\")\n .description(\"Check signing key consistency across releases (requires auth)\")\n .action(async (_options, subcmd) => {\n const parentOpts = subcmd.parent?.parent?.opts() ?? {};\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n\n const config = await loadConfig();\n const packageName = (parentOpts[\"app\"] as string | undefined) ?? config.app;\n if (!packageName) {\n throw new GpcError(\n \"No app configured\",\n \"MISSING_APP\",\n 2,\n \"Set a default app with 'gpc config set app <package>' or use --app\",\n );\n }\n\n const { resolveAuth } = await import(\"@gpc-cli/auth\");\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n });\n const accessToken = await client.getAccessToken();\n\n const { checkSigningConsistency } = await import(\"@gpc-cli/core\");\n const result = await checkSigningConsistency(accessToken, packageName);\n\n if (jsonMode) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\");\n console.log(bold(\"Signing Key Consistency\"));\n console.log(\"\");\n if (result.firstRelease) {\n console.log(\n ` ${dim(\"ℹ\")} First release (v${result.currentVersionCode}): ${result.currentFingerprint}`,\n );\n console.log(` ${dim(\"Nothing to compare against yet.\")}`);\n } else if (result.consistent) {\n console.log(\n ` ${green(\"✓\")} Consistent: v${result.previousVersionCode} → v${result.currentVersionCode}`,\n );\n console.log(` ${dim(\"Fingerprint:\")} ${result.currentFingerprint}`);\n } else {\n console.log(\n ` ${red(\"✗\")} Signing key changed between v${result.previousVersionCode} and v${result.currentVersionCode}`,\n );\n console.log(` ${dim(\"Previous:\")} ${result.previousFingerprint}`);\n console.log(` ${dim(\"Current:\")} ${result.currentFingerprint}`);\n console.log(\"\");\n console.log(\n ` ${yellow(\"⚠\")} If intentional, register the new key in Play Console before September 2026.`,\n );\n }\n console.log(\"\");\n }\n\n if (!result.consistent) {\n process.exitCode = 6;\n }\n });\n}\n\nasync function runPreflightAction(\n program: Command,\n file: string | undefined,\n options: Record<string, string | undefined>,\n): Promise<void> {\n if (!file && !options[\"metadata\"] && !options[\"source\"]) {\n throw new GpcError(\n \"Provide an AAB file, --metadata <dir>, or --source <dir>\",\n \"MISSING_INPUT\",\n 2,\n \"gpc preflight app.aab\",\n );\n }\n\n const failOn = options[\"failOn\"] as FindingSeverity | undefined;\n const validSeverities = new Set([\"critical\", \"error\", \"warning\", \"info\"]);\n if (failOn && !validSeverities.has(failOn)) {\n throw new GpcError(\n `Invalid --fail-on value \"${failOn}\". Use: critical, error, warning, info`,\n \"INVALID_OPTION\",\n 2,\n );\n }\n\n const scannerNames = options[\"scanners\"]?.split(\",\").map((s) => s.trim());\n if (scannerNames) {\n const known = new Set(getAllScannerNames());\n const unknown = scannerNames.filter((s) => !known.has(s));\n if (unknown.length > 0) {\n throw new GpcError(\n `Unknown scanner(s): ${unknown.join(\", \")}. Available: ${getAllScannerNames().join(\", \")}`,\n \"UNKNOWN_SCANNER\",\n 2,\n );\n }\n }\n\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n\n const result = await runPreflight({\n aabPath: file,\n metadataDir: options[\"metadata\"],\n sourceDir: options[\"source\"],\n scanners: scannerNames,\n failOn,\n configPath: options[\"config\"],\n });\n\n if (format === \"json\") {\n console.log(formatOutput(result, format));\n } else {\n // Header\n console.log(bold(\"GPC Preflight Scanner\"));\n if (file) console.log(dim(`File: ${file}`));\n console.log(dim(`Scanners: ${result.scanners.join(\", \")}`));\n console.log(\"\");\n\n if (result.findings.length === 0) {\n console.log(green(\"✓ No issues found\"));\n } else {\n // Group by severity\n for (const finding of result.findings) {\n const icon = SEVERITY_ICONS[finding.severity];\n const label = severityColor(finding.severity, `${icon} ${finding.severity.toUpperCase()}`);\n console.log(`${label} ${finding.title}`);\n console.log(` ${dim(finding.message)}`);\n if (finding.suggestion) {\n console.log(` ${dim(\"→\")} ${finding.suggestion}`);\n }\n if (finding.policyUrl) {\n console.log(` ${dim(finding.policyUrl)}`);\n }\n console.log(\"\");\n }\n }\n\n // Summary line\n const parts: string[] = [];\n if (result.summary.critical > 0) parts.push(bold(red(`${result.summary.critical} critical`)));\n if (result.summary.error > 0) parts.push(red(`${result.summary.error} error`));\n if (result.summary.warning > 0) parts.push(yellow(`${result.summary.warning} warning`));\n if (result.summary.info > 0) parts.push(dim(`${result.summary.info} info`));\n\n const summaryLine = parts.length > 0 ? parts.join(\", \") : green(\"0 issues\");\n const passedLabel = result.passed ? green(\"✓ PASSED\") : red(\"✗ FAILED\");\n console.log(`${passedLabel} ${summaryLine} ${dim(`(${result.durationMs}ms)`)}`);\n\n // Verification deadline awareness (auto-expires Sep 2026)\n if (Date.now() < new Date(\"2026-09-01\").getTime()) {\n console.log(\"\");\n console.log(\n dim(\"Note: Apps must be registered by a verified developer to be installable on\"),\n );\n console.log(dim(\"certified Android devices after Sep 2026. Run 'gpc verify' for details.\"));\n }\n }\n\n if (!result.passed) {\n process.exitCode = 6;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAGA,SAAS,cAAc,oBAAoB,cAAc,gBAAgB;AAGzE,SAAS,kBAAkB;AAG3B,IAAM,iBAAkD;AAAA,EACtD,UAAU;AAAA,EACV,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AACR;AAEA,SAAS,cAAc,UAA2B,MAAsB;AACtE,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,KAAK,IAAI,IAAI,CAAC;AAAA,IACvB,KAAK;AACH,aAAO,IAAI,IAAI;AAAA,IACjB,KAAK;AACH,aAAO,OAAO,IAAI;AAAA,IACpB,KAAK;AACH,aAAO,IAAI,IAAI;AAAA,EACnB;AACF;AAEO,SAAS,yBAAyB,SAAwB;AAC/D,QAAM,MAAM,QACT,QAAQ,kBAAkB,EAC1B,YAAY,2DAA2D,EACvE;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EACC,OAAO,sBAAsB,qDAAqD,EAClF,OAAO,oBAAoB,iEAAiE,EAC5F,OAAO,kBAAkB,4CAA4C,EACrE,OAAO,mBAAmB,uCAAuC,EACjE,OAAO,OAAO,MAA0B,YAAY;AACnD,UAAM,mBAAmB,SAAS,MAAM,OAAO;AAAA,EACjD,CAAC;AAGH,MACG,QAAQ,iBAAiB,EACzB,YAAY,2BAA2B,EACvC,OAAO,wBAAwB,kBAAkB,OAAO,EACxD,OAAO,OAAO,MAAc,YAAY;AACvC,UAAM,mBAAmB,SAAS,MAAM,EAAE,GAAG,SAAS,UAAU,WAAW,CAAC;AAAA,EAC9E,CAAC;AAGH,MACG,QAAQ,oBAAoB,EAC5B,YAAY,8BAA8B,EAC1C,OAAO,wBAAwB,kBAAkB,OAAO,EACxD,OAAO,OAAO,MAAc,YAAY;AACvC,UAAM,mBAAmB,SAAS,MAAM,EAAE,GAAG,SAAS,UAAU,cAAc,CAAC;AAAA,EACjF,CAAC;AAGH,MACG,QAAQ,gBAAgB,EACxB,YAAY,8CAA8C,EAC1D,OAAO,wBAAwB,kBAAkB,OAAO,EACxD,OAAO,OAAO,KAAa,YAAY;AACtC,UAAM,mBAAmB,SAAS,QAAW;AAAA,MAC3C,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,CAAC;AAGH,MACG,QAAQ,gBAAgB,EACxB,YAAY,mEAAmE,EAC/E,OAAO,wBAAwB,kBAAkB,OAAO,EACxD,OAAO,OAAO,KAAa,YAAY;AACtC,UAAM,mBAAmB,SAAS,QAAW;AAAA,MAC3C,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,CAAC;AAGH,MACG,QAAQ,SAAS,EACjB,YAAY,+DAA+D,EAC3E,OAAO,OAAO,UAAU,WAAW;AAClC,UAAM,aAAa,OAAO,QAAQ,QAAQ,KAAK,KAAK,CAAC;AACrD,UAAM,WAAW,CAAC,EAAE,WAAW,MAAM,KAAK,WAAW,QAAQ,MAAM;AAEnE,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAe,WAAW,KAAK,KAA4B,OAAO;AACxE,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,EAAE,YAAY,IAAI,MAAM,OAAO,eAAe;AACpD,UAAM,SAAS,MAAM,YAAY;AAAA,MAC/B,oBAAoB,OAAO,MAAM;AAAA,IACnC,CAAC;AACD,UAAM,cAAc,MAAM,OAAO,eAAe;AAEhD,UAAM,EAAE,wBAAwB,IAAI,MAAM,OAAO,eAAe;AAChE,UAAM,SAAS,MAAM,wBAAwB,aAAa,WAAW;AAErE,QAAI,UAAU;AACZ,cAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC7C,OAAO;AACL,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,KAAK,yBAAyB,CAAC;AAC3C,cAAQ,IAAI,EAAE;AACd,UAAI,OAAO,cAAc;AACvB,gBAAQ;AAAA,UACN,KAAK,IAAI,QAAG,CAAC,oBAAoB,OAAO,kBAAkB,MAAM,OAAO,kBAAkB;AAAA,QAC3F;AACA,gBAAQ,IAAI,KAAK,IAAI,iCAAiC,CAAC,EAAE;AAAA,MAC3D,WAAW,OAAO,YAAY;AAC5B,gBAAQ;AAAA,UACN,KAAK,MAAM,QAAG,CAAC,iBAAiB,OAAO,mBAAmB,YAAO,OAAO,kBAAkB;AAAA,QAC5F;AACA,gBAAQ,IAAI,KAAK,IAAI,cAAc,CAAC,IAAI,OAAO,kBAAkB,EAAE;AAAA,MACrE,OAAO;AACL,gBAAQ;AAAA,UACN,KAAK,IAAI,QAAG,CAAC,iCAAiC,OAAO,mBAAmB,SAAS,OAAO,kBAAkB;AAAA,QAC5G;AACA,gBAAQ,IAAI,KAAK,IAAI,WAAW,CAAC,IAAI,OAAO,mBAAmB,EAAE;AACjE,gBAAQ,IAAI,KAAK,IAAI,UAAU,CAAC,KAAK,OAAO,kBAAkB,EAAE;AAChE,gBAAQ,IAAI,EAAE;AACd,gBAAQ;AAAA,UACN,KAAK,OAAO,QAAG,CAAC;AAAA,QAClB;AAAA,MACF;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,QAAI,CAAC,OAAO,YAAY;AACtB,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF,CAAC;AACL;AAEA,eAAe,mBACb,SACA,MACA,SACe;AACf,MAAI,CAAC,QAAQ,CAAC,QAAQ,UAAU,KAAK,CAAC,QAAQ,QAAQ,GAAG;AACvD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,QAAQ;AAC/B,QAAM,kBAAkB,oBAAI,IAAI,CAAC,YAAY,SAAS,WAAW,MAAM,CAAC;AACxE,MAAI,UAAU,CAAC,gBAAgB,IAAI,MAAM,GAAG;AAC1C,UAAM,IAAI;AAAA,MACR,4BAA4B,MAAM;AAAA,MAClC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,QAAQ,UAAU,GAAG,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACxE,MAAI,cAAc;AAChB,UAAM,QAAQ,IAAI,IAAI,mBAAmB,CAAC;AAC1C,UAAM,UAAU,aAAa,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AACxD,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAI;AAAA,QACR,uBAAuB,QAAQ,KAAK,IAAI,CAAC,gBAAgB,mBAAmB,EAAE,KAAK,IAAI,CAAC;AAAA,QACxF;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,WAAW;AAChC,QAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAM,SAAS,MAAM,aAAa;AAAA,IAChC,SAAS;AAAA,IACT,aAAa,QAAQ,UAAU;AAAA,IAC/B,WAAW,QAAQ,QAAQ;AAAA,IAC3B,UAAU;AAAA,IACV;AAAA,IACA,YAAY,QAAQ,QAAQ;AAAA,EAC9B,CAAC;AAED,MAAI,WAAW,QAAQ;AACrB,YAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,EAC1C,OAAO;AAEL,YAAQ,IAAI,KAAK,uBAAuB,CAAC;AACzC,QAAI,KAAM,SAAQ,IAAI,IAAI,SAAS,IAAI,EAAE,CAAC;AAC1C,YAAQ,IAAI,IAAI,aAAa,OAAO,SAAS,KAAK,IAAI,CAAC,EAAE,CAAC;AAC1D,YAAQ,IAAI,EAAE;AAEd,QAAI,OAAO,SAAS,WAAW,GAAG;AAChC,cAAQ,IAAI,MAAM,wBAAmB,CAAC;AAAA,IACxC,OAAO;AAEL,iBAAW,WAAW,OAAO,UAAU;AACrC,cAAM,OAAO,eAAe,QAAQ,QAAQ;AAC5C,cAAM,QAAQ,cAAc,QAAQ,UAAU,GAAG,IAAI,IAAI,QAAQ,SAAS,YAAY,CAAC,EAAE;AACzF,gBAAQ,IAAI,GAAG,KAAK,KAAK,QAAQ,KAAK,EAAE;AACxC,gBAAQ,IAAI,WAAW,IAAI,QAAQ,OAAO,CAAC,EAAE;AAC7C,YAAI,QAAQ,YAAY;AACtB,kBAAQ,IAAI,WAAW,IAAI,QAAG,CAAC,IAAI,QAAQ,UAAU,EAAE;AAAA,QACzD;AACA,YAAI,QAAQ,WAAW;AACrB,kBAAQ,IAAI,WAAW,IAAI,QAAQ,SAAS,CAAC,EAAE;AAAA,QACjD;AACA,gBAAQ,IAAI,EAAE;AAAA,MAChB;AAAA,IACF;AAGA,UAAM,QAAkB,CAAC;AACzB,QAAI,OAAO,QAAQ,WAAW,EAAG,OAAM,KAAK,KAAK,IAAI,GAAG,OAAO,QAAQ,QAAQ,WAAW,CAAC,CAAC;AAC5F,QAAI,OAAO,QAAQ,QAAQ,EAAG,OAAM,KAAK,IAAI,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC;AAC7E,QAAI,OAAO,QAAQ,UAAU,EAAG,OAAM,KAAK,OAAO,GAAG,OAAO,QAAQ,OAAO,UAAU,CAAC;AACtF,QAAI,OAAO,QAAQ,OAAO,EAAG,OAAM,KAAK,IAAI,GAAG,OAAO,QAAQ,IAAI,OAAO,CAAC;AAE1E,UAAM,cAAc,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,UAAU;AAC1E,UAAM,cAAc,OAAO,SAAS,MAAM,eAAU,IAAI,IAAI,eAAU;AACtE,YAAQ,IAAI,GAAG,WAAW,KAAK,WAAW,KAAK,IAAI,IAAI,OAAO,UAAU,KAAK,CAAC,EAAE;AAGhF,QAAI,KAAK,IAAI,KAAI,oBAAI,KAAK,YAAY,GAAE,QAAQ,GAAG;AACjD,cAAQ,IAAI,EAAE;AACd,cAAQ;AAAA,QACN,IAAI,4EAA4E;AAAA,MAClF;AACA,cAAQ,IAAI,IAAI,yEAAyE,CAAC;AAAA,IAC5F;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,QAAQ;AAClB,YAAQ,WAAW;AAAA,EACrB;AACF;","names":[]}
@@ -17,7 +17,7 @@ function registerUpdateCommand(program) {
17
17
  program.command("update").description("Update gpc to the latest version").option("--check", "Check for updates without installing (exits 0 always)").option("--force", "Update even if already on the latest version").action(async (opts, cmd) => {
18
18
  const parentOpts = cmd.parent?.opts() ?? {};
19
19
  const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
20
- const currentVersion = "0.9.65";
20
+ const currentVersion = "0.9.66";
21
21
  if (currentVersion === "0.0.0") {
22
22
  if (jsonMode) {
23
23
  console.log(
@@ -172,4 +172,4 @@ Run: gpc update`);
172
172
  export {
173
173
  registerUpdateCommand
174
174
  };
175
- //# sourceMappingURL=update-POERCYHW.js.map
175
+ //# sourceMappingURL=update-GEH352BE.js.map
@@ -0,0 +1,330 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ isInteractive,
4
+ promptConfirm
5
+ } from "./chunk-RZQSEDKI.js";
6
+ import {
7
+ bold,
8
+ dim,
9
+ green,
10
+ red,
11
+ yellow
12
+ } from "./chunk-FAN4ZITI.js";
13
+
14
+ // src/commands/verify.ts
15
+ import { resolveAuth } from "@gpc-cli/auth";
16
+ import { loadConfig } from "@gpc-cli/config";
17
+ import { buildChecklist, renderChecklistMarkdown } from "@gpc-cli/core";
18
+ var ENFORCEMENT_DATE = /* @__PURE__ */ new Date("2026-09-30");
19
+ var ENFORCEMENT_REGIONS = ["Brazil", "Indonesia", "Singapore", "Thailand"];
20
+ var ENFORCEMENT_REGION_CODES = ["BR", "ID", "SG", "TH"];
21
+ var API_HOST = "androidpublisher.googleapis.com";
22
+ var RESOURCES = {
23
+ overview: "https://developer.android.com/developer-verification",
24
+ playConsole: "https://developer.android.com/developer-verification/guides/google-play-console",
25
+ androidConsole: "https://developer.android.com/developer-verification/guides/android-developer-console",
26
+ limitedDistribution: "https://developer.android.com/developer-verification/guides/limited-distribution",
27
+ faq: "https://developer.android.com/developer-verification/faq"
28
+ };
29
+ function daysUntilEnforcement() {
30
+ return Math.ceil((ENFORCEMENT_DATE.getTime() - Date.now()) / (1e3 * 60 * 60 * 24));
31
+ }
32
+ function isBeforeEnforcement() {
33
+ return Date.now() < ENFORCEMENT_DATE.getTime();
34
+ }
35
+ function formatDeadline() {
36
+ const days = daysUntilEnforcement();
37
+ if (days > 0) {
38
+ return `Enforcement begins September 30, 2026 (${days} days, ${ENFORCEMENT_REGION_CODES.join("/")})`;
39
+ }
40
+ return "Enforcement active. Verify your account is compliant.";
41
+ }
42
+ async function openUrl(url) {
43
+ const { execFile } = await import("child_process");
44
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
45
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
46
+ execFile(cmd, args, (err) => {
47
+ if (err) console.error(dim(`Could not open browser: ${err.message}`));
48
+ });
49
+ }
50
+ async function probeApp(accessToken, packageName) {
51
+ const baseUrl = `https://${API_HOST}/androidpublisher/v3/applications/${encodeURIComponent(packageName)}`;
52
+ const result = {
53
+ accessible: false,
54
+ bundleCount: 0,
55
+ hasGeneratedApks: false
56
+ };
57
+ const editResp = await fetch(`${baseUrl}/edits`, {
58
+ method: "POST",
59
+ headers: { Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json" },
60
+ body: JSON.stringify({}),
61
+ signal: AbortSignal.timeout(1e4)
62
+ });
63
+ if (!editResp.ok) return result;
64
+ const edit = await editResp.json();
65
+ result.accessible = true;
66
+ try {
67
+ const bundlesResp = await fetch(`${baseUrl}/edits/${edit.id}/bundles`, {
68
+ headers: { Authorization: `Bearer ${accessToken}` },
69
+ signal: AbortSignal.timeout(1e4)
70
+ });
71
+ if (bundlesResp.ok) {
72
+ const data = await bundlesResp.json();
73
+ const bundles = data.bundles ?? [];
74
+ result.bundleCount = bundles.length;
75
+ if (bundles.length > 0) {
76
+ result.latestVersionCode = bundles.reduce(
77
+ (max, b) => b.versionCode > max.versionCode ? b : max
78
+ ).versionCode;
79
+ const apksResp = await fetch(`${baseUrl}/generatedApks/${result.latestVersionCode}`, {
80
+ headers: { Authorization: `Bearer ${accessToken}` },
81
+ signal: AbortSignal.timeout(1e4)
82
+ });
83
+ if (apksResp.ok) {
84
+ const apksData = await apksResp.json();
85
+ result.hasGeneratedApks = (apksData.generatedApks?.length ?? 0) > 0;
86
+ }
87
+ }
88
+ }
89
+ } finally {
90
+ await fetch(`${baseUrl}/edits/${edit.id}`, {
91
+ method: "DELETE",
92
+ headers: { Authorization: `Bearer ${accessToken}` },
93
+ signal: AbortSignal.timeout(5e3)
94
+ }).catch(() => {
95
+ });
96
+ }
97
+ return result;
98
+ }
99
+ function registerVerifyCommand(program) {
100
+ const verify = program.command("verify").description("Android developer verification status and resources").option("--open", "Open the verification page in your browser").action(async (opts, cmd) => {
101
+ const parentOpts = cmd.parent?.opts() ?? {};
102
+ const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
103
+ let accountEmail = "unknown";
104
+ let accessToken;
105
+ let config;
106
+ try {
107
+ config = await loadConfig();
108
+ const client = await resolveAuth({
109
+ serviceAccountPath: config.auth?.serviceAccount
110
+ });
111
+ accountEmail = client.getClientEmail();
112
+ accessToken = await client.getAccessToken();
113
+ } catch {
114
+ }
115
+ if (opts["open"]) {
116
+ await openUrl(RESOURCES.overview);
117
+ if (jsonMode) {
118
+ console.log(JSON.stringify({ opened: RESOURCES.overview }));
119
+ } else {
120
+ console.log(`Opened ${RESOURCES.overview}`);
121
+ }
122
+ return;
123
+ }
124
+ const packageName = parentOpts["app"] ?? config?.app;
125
+ let appInfo;
126
+ if (accessToken && packageName) {
127
+ try {
128
+ appInfo = await probeApp(accessToken, packageName);
129
+ } catch {
130
+ }
131
+ }
132
+ const days = daysUntilEnforcement();
133
+ const actionItems = [];
134
+ if (!accessToken) {
135
+ actionItems.push({
136
+ priority: "high",
137
+ title: "Authenticate with Google Play",
138
+ command: "gpc auth login"
139
+ });
140
+ }
141
+ if (appInfo && appInfo.bundleCount === 0) {
142
+ actionItems.push({
143
+ priority: "medium",
144
+ title: "Upload your first AAB",
145
+ command: "gpc publish"
146
+ });
147
+ }
148
+ if (appInfo && !appInfo.hasGeneratedApks) {
149
+ actionItems.push({
150
+ priority: "medium",
151
+ title: "Enroll in Play App Signing"
152
+ });
153
+ }
154
+ if (days > 0 && days <= 90) {
155
+ actionItems.push({
156
+ priority: "high",
157
+ title: "Enforcement is less than 90 days away. Complete verification now."
158
+ });
159
+ }
160
+ actionItems.push({
161
+ priority: "low",
162
+ title: "Run full readiness walkthrough",
163
+ command: "gpc verify checklist"
164
+ });
165
+ if (jsonMode) {
166
+ console.log(
167
+ JSON.stringify(
168
+ {
169
+ enforcement: {
170
+ date: "2026-09-30",
171
+ daysRemaining: days,
172
+ regions: ENFORCEMENT_REGIONS,
173
+ active: !isBeforeEnforcement()
174
+ },
175
+ account: accountEmail,
176
+ app: appInfo ? {
177
+ packageName,
178
+ accessible: appInfo.accessible,
179
+ bundleCount: appInfo.bundleCount,
180
+ latestVersionCode: appInfo.latestVersionCode,
181
+ playAppSigningEnrolled: appInfo.hasGeneratedApks
182
+ } : void 0,
183
+ actionItems,
184
+ resources: RESOURCES
185
+ },
186
+ null,
187
+ 2
188
+ )
189
+ );
190
+ return;
191
+ }
192
+ console.log("");
193
+ console.log(bold("Android Developer Verification"));
194
+ console.log("");
195
+ console.log(` Status: ${days <= 90 ? yellow(formatDeadline()) : dim(formatDeadline())}`);
196
+ console.log(` Account: ${accountEmail}`);
197
+ if (appInfo) {
198
+ console.log(` App: ${packageName}`);
199
+ console.log(
200
+ ` Bundles: ${appInfo.bundleCount}${appInfo.latestVersionCode ? ` (latest: v${appInfo.latestVersionCode})` : ""}`
201
+ );
202
+ console.log(
203
+ ` Signing: ${appInfo.hasGeneratedApks ? green("Play App Signing enrolled") : yellow("Not enrolled or no bundles")}`
204
+ );
205
+ }
206
+ console.log("");
207
+ if (actionItems.length > 1) {
208
+ console.log(" Action items:");
209
+ for (const item of actionItems) {
210
+ const icon = item.priority === "high" ? red("!") : item.priority === "medium" ? yellow("!") : dim("-");
211
+ const cmdHint = item.command ? ` ${dim(`\u2192 ${item.command}`)}` : "";
212
+ console.log(` ${icon} ${item.title}${cmdHint}`);
213
+ }
214
+ console.log("");
215
+ }
216
+ console.log(" Resources:");
217
+ console.log(` ${dim("\u2192")} ${RESOURCES.overview}`);
218
+ console.log(` ${dim("\u2192")} ${RESOURCES.playConsole}`);
219
+ console.log(` ${dim("\u2192")} ${RESOURCES.faq}`);
220
+ console.log("");
221
+ console.log(dim(" Run 'gpc verify --open' to open the verification page in your browser."));
222
+ console.log(dim(" Full guide: gpc docs developer-verification"));
223
+ console.log("");
224
+ });
225
+ verify.command("checklist").description("Verification readiness walkthrough").action(async (_opts, subcmd) => {
226
+ const parentOpts = subcmd.parent?.parent?.opts() ?? {};
227
+ const jsonMode = !!(parentOpts["json"] || parentOpts["output"] === "json");
228
+ const interactive = isInteractive(subcmd.parent?.parent);
229
+ let accountEmail = "unknown";
230
+ let accessToken;
231
+ let config;
232
+ let authenticated = false;
233
+ try {
234
+ config = await loadConfig();
235
+ const client = await resolveAuth({
236
+ serviceAccountPath: config.auth?.serviceAccount
237
+ });
238
+ accountEmail = client.getClientEmail();
239
+ accessToken = await client.getAccessToken();
240
+ authenticated = true;
241
+ } catch {
242
+ }
243
+ const packageName = parentOpts["app"] ?? config?.app;
244
+ let appAccessible;
245
+ let bundleCount;
246
+ let hasGeneratedApks;
247
+ if (accessToken && packageName) {
248
+ try {
249
+ const probe = await probeApp(accessToken, packageName);
250
+ appAccessible = probe.accessible;
251
+ bundleCount = probe.bundleCount;
252
+ hasGeneratedApks = probe.hasGeneratedApks;
253
+ } catch {
254
+ }
255
+ }
256
+ const interactiveAnswers = {};
257
+ if (interactive && !jsonMode && !parentOpts["json"]) {
258
+ console.log("");
259
+ console.log(bold("Developer Verification Checklist"));
260
+ console.log(dim(" Answer Y/N for items we cannot auto-detect.\n"));
261
+ const manualSteps = [
262
+ {
263
+ id: "identity-verified",
264
+ question: "Have you completed identity verification in Play Console?"
265
+ },
266
+ {
267
+ id: "auto-registration-reviewed",
268
+ question: "Have you reviewed your auto-registration results in Play Console?"
269
+ },
270
+ {
271
+ id: "additional-keys",
272
+ question: "Have you registered all additional signing keys used outside Play?"
273
+ }
274
+ ];
275
+ for (const step of manualSteps) {
276
+ interactiveAnswers[step.id] = await promptConfirm(step.question, false);
277
+ }
278
+ }
279
+ const result = buildChecklist({
280
+ authenticated,
281
+ accountEmail,
282
+ appAccessible,
283
+ bundleCount,
284
+ hasGeneratedApks,
285
+ interactiveAnswers: Object.keys(interactiveAnswers).length > 0 ? interactiveAnswers : void 0
286
+ });
287
+ if (jsonMode) {
288
+ console.log(JSON.stringify(result, null, 2));
289
+ return;
290
+ }
291
+ console.log("");
292
+ console.log(bold(`Verification Readiness: ${result.completed}/${result.total}`));
293
+ console.log("");
294
+ for (const item of result.items) {
295
+ let icon;
296
+ let label;
297
+ if (item.status === "done") {
298
+ icon = green("\u2713");
299
+ label = item.title;
300
+ } else if (item.status === "action-needed") {
301
+ icon = red("\u2717");
302
+ label = item.title;
303
+ } else {
304
+ icon = yellow("?");
305
+ label = item.title;
306
+ }
307
+ console.log(` ${icon} ${label}`);
308
+ if (item.detail && item.status !== "done") {
309
+ console.log(` ${dim(item.detail)}`);
310
+ }
311
+ if (item.actionUrl && item.status !== "done") {
312
+ console.log(` ${dim("\u2192")} ${item.actionUrl}`);
313
+ }
314
+ }
315
+ console.log("");
316
+ const md = renderChecklistMarkdown(result, accountEmail);
317
+ if (!interactive) {
318
+ console.log(dim("--- Markdown report ---"));
319
+ console.log(md);
320
+ } else {
321
+ console.log(
322
+ dim(" Tip: run with --json or --no-interactive to get a machine-readable report.")
323
+ );
324
+ }
325
+ });
326
+ }
327
+ export {
328
+ registerVerifyCommand
329
+ };
330
+ //# sourceMappingURL=verify-O2PSBTIC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/verify.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { buildChecklist, renderChecklistMarkdown } from \"@gpc-cli/core\";\nimport { green, yellow, red, dim, bold } from \"../colors.js\";\nimport { isInteractive, promptConfirm } from \"../prompt.js\";\n\nconst ENFORCEMENT_DATE = new Date(\"2026-09-30\");\nconst ENFORCEMENT_REGIONS = [\"Brazil\", \"Indonesia\", \"Singapore\", \"Thailand\"];\nconst ENFORCEMENT_REGION_CODES = [\"BR\", \"ID\", \"SG\", \"TH\"];\nconst API_HOST = \"androidpublisher.googleapis.com\";\n\nconst RESOURCES = {\n overview: \"https://developer.android.com/developer-verification\",\n playConsole: \"https://developer.android.com/developer-verification/guides/google-play-console\",\n androidConsole:\n \"https://developer.android.com/developer-verification/guides/android-developer-console\",\n limitedDistribution:\n \"https://developer.android.com/developer-verification/guides/limited-distribution\",\n faq: \"https://developer.android.com/developer-verification/faq\",\n};\n\nfunction daysUntilEnforcement(): number {\n return Math.ceil((ENFORCEMENT_DATE.getTime() - Date.now()) / (1000 * 60 * 60 * 24));\n}\n\nfunction isBeforeEnforcement(): boolean {\n return Date.now() < ENFORCEMENT_DATE.getTime();\n}\n\nfunction formatDeadline(): string {\n const days = daysUntilEnforcement();\n if (days > 0) {\n return `Enforcement begins September 30, 2026 (${days} days, ${ENFORCEMENT_REGION_CODES.join(\"/\")})`;\n }\n return \"Enforcement active. Verify your account is compliant.\";\n}\n\nasync function openUrl(url: string): Promise<void> {\n const { execFile } = await import(\"node:child_process\");\n const cmd =\n process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"cmd\" : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n execFile(cmd, args, (err) => {\n if (err) console.error(dim(`Could not open browser: ${err.message}`));\n });\n}\n\ninterface AppProbeResult {\n accessible: boolean;\n bundleCount: number;\n latestVersionCode?: number;\n hasGeneratedApks: boolean;\n}\n\nasync function probeApp(accessToken: string, packageName: string): Promise<AppProbeResult> {\n const baseUrl = `https://${API_HOST}/androidpublisher/v3/applications/${encodeURIComponent(packageName)}`;\n const result: AppProbeResult = {\n accessible: false,\n bundleCount: 0,\n hasGeneratedApks: false,\n };\n\n const editResp = await fetch(`${baseUrl}/edits`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}`, \"Content-Type\": \"application/json\" },\n body: JSON.stringify({}),\n signal: AbortSignal.timeout(10_000),\n });\n if (!editResp.ok) return result;\n\n const edit = (await editResp.json()) as { id: string };\n result.accessible = true;\n\n try {\n const bundlesResp = await fetch(`${baseUrl}/edits/${edit.id}/bundles`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(10_000),\n });\n if (bundlesResp.ok) {\n const data = (await bundlesResp.json()) as { bundles?: { versionCode: number }[] };\n const bundles = data.bundles ?? [];\n result.bundleCount = bundles.length;\n if (bundles.length > 0) {\n result.latestVersionCode = bundles.reduce((max, b) =>\n b.versionCode > max.versionCode ? b : max,\n ).versionCode;\n\n const apksResp = await fetch(`${baseUrl}/generatedApks/${result.latestVersionCode}`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(10_000),\n });\n if (apksResp.ok) {\n const apksData = (await apksResp.json()) as {\n generatedApks?: { certificateSha256Fingerprint?: string }[];\n };\n result.hasGeneratedApks = (apksData.generatedApks?.length ?? 0) > 0;\n }\n }\n }\n } finally {\n await fetch(`${baseUrl}/edits/${edit.id}`, {\n method: \"DELETE\",\n headers: { Authorization: `Bearer ${accessToken}` },\n signal: AbortSignal.timeout(5_000),\n }).catch(() => {});\n }\n\n return result;\n}\n\nexport function registerVerifyCommand(program: Command): void {\n const verify = program\n .command(\"verify\")\n .description(\"Android developer verification status and resources\")\n .option(\"--open\", \"Open the verification page in your browser\")\n .action(async (opts, cmd) => {\n const parentOpts = cmd.parent?.opts() ?? {};\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n\n let accountEmail = \"unknown\";\n let accessToken: string | undefined;\n let config;\n try {\n config = await loadConfig();\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n });\n accountEmail = client.getClientEmail();\n accessToken = await client.getAccessToken();\n } catch {\n // Auth not configured\n }\n\n if (opts[\"open\"]) {\n await openUrl(RESOURCES.overview);\n if (jsonMode) {\n console.log(JSON.stringify({ opened: RESOURCES.overview }));\n } else {\n console.log(`Opened ${RESOURCES.overview}`);\n }\n return;\n }\n\n const packageName = (parentOpts[\"app\"] as string | undefined) ?? config?.app;\n let appInfo: AppProbeResult | undefined;\n if (accessToken && packageName) {\n try {\n appInfo = await probeApp(accessToken, packageName);\n } catch {\n // Non-blocking\n }\n }\n\n const days = daysUntilEnforcement();\n const actionItems: { priority: string; title: string; command?: string }[] = [];\n\n if (!accessToken) {\n actionItems.push({\n priority: \"high\",\n title: \"Authenticate with Google Play\",\n command: \"gpc auth login\",\n });\n }\n if (appInfo && appInfo.bundleCount === 0) {\n actionItems.push({\n priority: \"medium\",\n title: \"Upload your first AAB\",\n command: \"gpc publish\",\n });\n }\n if (appInfo && !appInfo.hasGeneratedApks) {\n actionItems.push({\n priority: \"medium\",\n title: \"Enroll in Play App Signing\",\n });\n }\n if (days > 0 && days <= 90) {\n actionItems.push({\n priority: \"high\",\n title: \"Enforcement is less than 90 days away. Complete verification now.\",\n });\n }\n actionItems.push({\n priority: \"low\",\n title: \"Run full readiness walkthrough\",\n command: \"gpc verify checklist\",\n });\n\n if (jsonMode) {\n console.log(\n JSON.stringify(\n {\n enforcement: {\n date: \"2026-09-30\",\n daysRemaining: days,\n regions: ENFORCEMENT_REGIONS,\n active: !isBeforeEnforcement(),\n },\n account: accountEmail,\n app: appInfo\n ? {\n packageName,\n accessible: appInfo.accessible,\n bundleCount: appInfo.bundleCount,\n latestVersionCode: appInfo.latestVersionCode,\n playAppSigningEnrolled: appInfo.hasGeneratedApks,\n }\n : undefined,\n actionItems,\n resources: RESOURCES,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(\"\");\n console.log(bold(\"Android Developer Verification\"));\n console.log(\"\");\n console.log(` Status: ${days <= 90 ? yellow(formatDeadline()) : dim(formatDeadline())}`);\n console.log(` Account: ${accountEmail}`);\n if (appInfo) {\n console.log(` App: ${packageName}`);\n console.log(\n ` Bundles: ${appInfo.bundleCount}${appInfo.latestVersionCode ? ` (latest: v${appInfo.latestVersionCode})` : \"\"}`,\n );\n console.log(\n ` Signing: ${appInfo.hasGeneratedApks ? green(\"Play App Signing enrolled\") : yellow(\"Not enrolled or no bundles\")}`,\n );\n }\n console.log(\"\");\n\n if (actionItems.length > 1) {\n console.log(\" Action items:\");\n for (const item of actionItems) {\n const icon =\n item.priority === \"high\"\n ? red(\"!\")\n : item.priority === \"medium\"\n ? yellow(\"!\")\n : dim(\"-\");\n const cmdHint = item.command ? ` ${dim(`→ ${item.command}`)}` : \"\";\n console.log(` ${icon} ${item.title}${cmdHint}`);\n }\n console.log(\"\");\n }\n\n console.log(\" Resources:\");\n console.log(` ${dim(\"→\")} ${RESOURCES.overview}`);\n console.log(` ${dim(\"→\")} ${RESOURCES.playConsole}`);\n console.log(` ${dim(\"→\")} ${RESOURCES.faq}`);\n console.log(\"\");\n console.log(dim(\" Run 'gpc verify --open' to open the verification page in your browser.\"));\n console.log(dim(\" Full guide: gpc docs developer-verification\"));\n console.log(\"\");\n });\n\n verify\n .command(\"checklist\")\n .description(\"Verification readiness walkthrough\")\n .action(async (_opts, subcmd) => {\n const parentOpts = subcmd.parent?.parent?.opts() ?? {};\n const jsonMode = !!(parentOpts[\"json\"] || parentOpts[\"output\"] === \"json\");\n const interactive = isInteractive(subcmd.parent?.parent);\n\n let accountEmail = \"unknown\";\n let accessToken: string | undefined;\n let config;\n let authenticated = false;\n try {\n config = await loadConfig();\n const client = await resolveAuth({\n serviceAccountPath: config.auth?.serviceAccount,\n });\n accountEmail = client.getClientEmail();\n accessToken = await client.getAccessToken();\n authenticated = true;\n } catch {\n // Auth not configured\n }\n\n const packageName = (parentOpts[\"app\"] as string | undefined) ?? config?.app;\n let appAccessible: boolean | undefined;\n let bundleCount: number | undefined;\n let hasGeneratedApks: boolean | undefined;\n\n if (accessToken && packageName) {\n try {\n const probe = await probeApp(accessToken, packageName);\n appAccessible = probe.accessible;\n bundleCount = probe.bundleCount;\n hasGeneratedApks = probe.hasGeneratedApks;\n } catch {\n // Non-blocking\n }\n }\n\n const interactiveAnswers: Record<string, boolean> = {};\n if (interactive && !jsonMode && !parentOpts[\"json\"]) {\n console.log(\"\");\n console.log(bold(\"Developer Verification Checklist\"));\n console.log(dim(\" Answer Y/N for items we cannot auto-detect.\\n\"));\n\n const manualSteps = [\n {\n id: \"identity-verified\",\n question: \"Have you completed identity verification in Play Console?\",\n },\n {\n id: \"auto-registration-reviewed\",\n question: \"Have you reviewed your auto-registration results in Play Console?\",\n },\n {\n id: \"additional-keys\",\n question: \"Have you registered all additional signing keys used outside Play?\",\n },\n ];\n\n for (const step of manualSteps) {\n interactiveAnswers[step.id] = await promptConfirm(step.question, false);\n }\n }\n\n const result = buildChecklist({\n authenticated,\n accountEmail,\n appAccessible,\n bundleCount,\n hasGeneratedApks,\n interactiveAnswers:\n Object.keys(interactiveAnswers).length > 0 ? interactiveAnswers : undefined,\n });\n\n if (jsonMode) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(\"\");\n console.log(bold(`Verification Readiness: ${result.completed}/${result.total}`));\n console.log(\"\");\n\n for (const item of result.items) {\n let icon: string;\n let label: string;\n if (item.status === \"done\") {\n icon = green(\"✓\");\n label = item.title;\n } else if (item.status === \"action-needed\") {\n icon = red(\"✗\");\n label = item.title;\n } else {\n icon = yellow(\"?\");\n label = item.title;\n }\n console.log(` ${icon} ${label}`);\n if (item.detail && item.status !== \"done\") {\n console.log(` ${dim(item.detail)}`);\n }\n if (item.actionUrl && item.status !== \"done\") {\n console.log(` ${dim(\"→\")} ${item.actionUrl}`);\n }\n }\n\n console.log(\"\");\n\n const md = renderChecklistMarkdown(result, accountEmail);\n if (!interactive) {\n console.log(dim(\"--- Markdown report ---\"));\n console.log(md);\n } else {\n console.log(\n dim(\" Tip: run with --json or --no-interactive to get a machine-readable report.\"),\n );\n }\n });\n}\n"],"mappings":"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","names":[]}
@@ -7,7 +7,7 @@ import "./chunk-3SJ6OXCZ.js";
7
7
  // src/commands/version.ts
8
8
  function registerVersionCommand(program) {
9
9
  program.command("version").description("Show version information").action(() => {
10
- const version = "0.9.65";
10
+ const version = "0.9.66";
11
11
  if (program.opts()["output"] === "json") {
12
12
  console.log(
13
13
  JSON.stringify({
@@ -25,4 +25,4 @@ function registerVersionCommand(program) {
25
25
  export {
26
26
  registerVersionCommand
27
27
  };
28
- //# sourceMappingURL=version-2HT32CYP.js.map
28
+ //# sourceMappingURL=version-2RUEWMPK.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gpc-cli/cli",
3
- "version": "0.9.65",
3
+ "version": "0.9.66",
4
4
  "description": "GPC — Google Play Console CLI. 217 API endpoints including Managed Google Play. Upload AABs, manage releases, monitor vitals, publish private enterprise apps. Fastlane alternative for Android.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,10 +19,10 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "commander": "^14.0.3",
22
- "@gpc-cli/api": "1.0.36",
23
22
  "@gpc-cli/auth": "0.9.14",
24
23
  "@gpc-cli/config": "0.9.14",
25
- "@gpc-cli/core": "0.9.55",
24
+ "@gpc-cli/core": "0.9.56",
25
+ "@gpc-cli/api": "1.0.36",
26
26
  "@gpc-cli/plugin-sdk": "0.9.10"
27
27
  },
28
28
  "keywords": [