apple signing ensure with automatic signing only adds capabilities (no profiles or certificates; the dry run says so) and lists unused storebound profiles with the exact delete command, never run; every capability write is read back (lag retries, timeout) and fails with the API answers when one did not stick; apple status, signing status and validate compare the App ID, apple.signing.capabilities and the iOS project's entitlements (CODE_SIGN_ENTITLEMENTS too) and name what is missing where; api writes outside a terminal say TTY by design and name the dedicated command; pitfalls 64-66; tests

This commit is contained in:
CRTkafa 2026-10-14 19:10:01 +08:00
parent 357319a775
commit daae3715bf
12 changed files with 463 additions and 23 deletions

View file

@ -13,7 +13,7 @@ import { readFileSync, writeFileSync } from 'node:fs';
import { resolve } from 'node:path';
import type { Args } from './lib/args';
import { allOps, authFor, type BuiltRequest, buildRequest, resolveOp, send, sendAll } from './api/client';
import { decide, gateOf, ownerReason, resourceOf, type GateKind, type Store } from './api/gate';
import { decide, dedicatedCommand, gateOf, ownerReason, resourceOf, type GateKind, type Store } from './api/gate';
import { APPLE_SPEC } from './api/apple.gen';
import { PLAY_APIS } from './api/play.gen';
import { WRAPPED } from './api/wrapped.gen';
@ -147,7 +147,9 @@ export async function run(args: Args): Promise<void> {
});
if (decision.action === 'refuse') throw new Error(`${op.id}: ${decision.why}`);
if (decision.action === 'dry') {
if (json) printJson({ dryRun: true, operation: op.id, gate: kind, why: decision.why, request: { method: req.method, url: req.url, body: typeof req.body === 'string' ? JSON.parse(req.body) : req.body ? `<${req.body.length} bytes>` : undefined } });
const instead = op.method !== 'GET' ? dedicatedCommand(st, op.id) : null;
if (instead) console.error(`api: ${op.id} has a dedicated storebound command that runs without a terminal: ${instead}`);
if (json) printJson({ dryRun: true, operation: op.id, gate: kind, why: decision.why, ...(instead ? { instead } : {}), request: { method: req.method, url: req.url, body: typeof req.body === 'string' ? JSON.parse(req.body) : req.body ? `<${req.body.length} bytes>` : undefined } });
else console.log(`dry run (${decision.why}): nothing sent\n${kind === 'owner' ? `owner only: this ${ownerReason(st, op.id, op.method)}; sending also asks you to type the operation id\n` : ''}\n${describeRequest(req)}`);
return;
}