apple submit --build <n> (first submission, the resubmit steps; plan table with --json under serve); desktop owner actions to send for review: owner.apple_submit, owner.apple_resubmit, owner.apple_iap_submit, owner.play_production, and the price gate owner actions (owner.prices_play_products / _play_subscriptions / _apple_subscriptions; owner.prices_import passes --allow-price-changes after the dialog); OWNER_ALLOWED_ARGS ties each forbidden flag to its one action, dry runs never carry owner flags, MCP still has no submit or production release; submit dialog text in the host; system.tools androidSdk, project.inspect playRelease, declarations dataDeletion
This commit is contained in:
parent
2e7dd44ae6
commit
33eb24a3dc
17 changed files with 335 additions and 49 deletions
|
|
@ -5,8 +5,8 @@ import { join } from 'node:path';
|
|||
import { canonical, mac, MAX_TTL_MS, mint, parseSecret, TokenGuard } from '../cli/lib/confirm-token';
|
||||
import { ERR } from '../cli/lib/desktop-protocol';
|
||||
import { childEnv, pickCallEnv, type RunOptions, type Running } from '../cli/lib/runner';
|
||||
import { FORBIDDEN_ARGS, TOOLS } from '../cli/mcp-tools';
|
||||
import { describeMethods, DESKTOP_ONLY, DESKTOP_TOOLS, FORBIDDEN_METHOD_WORDS, JSON_TOOLS, methodName, OWNER_TOOLS, Session } from '../cli/serve';
|
||||
import { FORBIDDEN_ARGS, TOOLS, toArgv, validateInput } from '../cli/mcp-tools';
|
||||
import { describeMethods, DESKTOP_ONLY, DESKTOP_TOOLS, FORBIDDEN_METHOD_WORDS, JSON_TOOLS, methodName, OWNER_SUBMIT, OWNER_TOOLS, Session } from '../cli/serve';
|
||||
import { buildOne, hostTarget, leaks } from '../tools/build-sidecars';
|
||||
|
||||
type J = Record<string, unknown>;
|
||||
|
|
@ -90,17 +90,28 @@ describe('confirm tokens', () => {
|
|||
});
|
||||
|
||||
describe('serve --stdio: methods', () => {
|
||||
test('nothing submits, releases or publishes', () => {
|
||||
test('only owner actions submit or release; nothing publishes; MCP has none of them', () => {
|
||||
const names = describeMethods().map(m => m.method);
|
||||
// the owner actions (rollout share, phased release, sending one approved reply: tests/desktop-d3.test.ts) are the
|
||||
// only methods with those words, all under "owner.", and none submits, publishes, cancels, deletes or invites
|
||||
// the owner actions (rollout share, phased release, sending one approved reply, submit / resubmit, the Play
|
||||
// production release: tests/desktop-d3.test.ts) are the only methods with those words, all under "owner."
|
||||
const owner = describeMethods().filter(m => m.kind === 'owner').map(m => m.method);
|
||||
expect(owner.sort()).toEqual(OWNER_TOOLS.map(t => methodName(t.name)).sort());
|
||||
for (const n of owner) expect(n.startsWith('owner.')).toBe(true);
|
||||
for (const n of names.filter(x => !owner.includes(x))) expect(n).not.toMatch(FORBIDDEN_METHOD_WORDS);
|
||||
for (const n of names) expect(n).not.toMatch(/submit|publish|cancel|delete|remove|invite|manual/i);
|
||||
for (const n of ['apple.submit', 'apple.release', 'play.release', 'play.release_testing', 'apple.phased_release', 'play.rollout', 'reviews.send', 'apple.ppo_start', 'prices.import'])
|
||||
// submitting: exactly these owner actions, nothing else
|
||||
const submitting = [...OWNER_SUBMIT].map(methodName).sort();
|
||||
expect(submitting).toEqual(['owner.apple_iap_submit', 'owner.apple_resubmit', 'owner.apple_submit', 'owner.play_production']);
|
||||
for (const n of names.filter(x => !submitting.includes(x))) expect(n).not.toMatch(/submit|production/i);
|
||||
for (const n of names) expect(n).not.toMatch(/publish|cancel|delete|remove|invite|manual/i);
|
||||
for (const n of ['apple.submit', 'apple.resubmit', 'apple.iap_submit', 'apple.release', 'play.release', 'play.release_testing', 'apple.phased_release', 'play.rollout', 'reviews.send', 'apple.ppo_start', 'prices.import'])
|
||||
expect(names).not.toContain(n);
|
||||
// the MCP server (AI tools) never submits, resubmits or sends a production release
|
||||
for (const t of TOOLS) {
|
||||
// only the read-only IAP review plan runs iap-submit, and always with --dry
|
||||
if (t.command.some(c => /submit/.test(c))) { expect([t.name, t.write]).toEqual(['apple_iap_review_plan', false]); expect(toArgv(t, { dry_run: false }).argv).toContain('--dry'); }
|
||||
for (const s of [{}, { track: 'production' }, { dry_run: false }]) if (!validateInput(t, s).length) expect(toArgv(t, s).argv).not.toContain('--production');
|
||||
}
|
||||
expect(TOOLS.some(t => OWNER_SUBMIT.has(t.name) || t.name.startsWith('owner_'))).toBe(false);
|
||||
// every desktop tool still goes through the MCP rules: no forbidden flag can come out of any of them
|
||||
for (const t of DESKTOP_TOOLS) expect(t.command.some(c => FORBIDDEN_ARGS.includes(c))).toBe(false);
|
||||
expect(new Set(names).size).toBe(names.length);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue