Console pages as absolute deep links: cli/lib/console-links.ts builds the URL of every App Store Connect / Play Console page from apple.appId, play.developerId and play.appId (app list / developer chooser when unknown); every plain 'App Store Connect > ...' / 'Play Console > ...' direction in cli/ and templates/ now carries it, validate / scan / declarations / release plan JSON carry url, the desktop shows an Open button; tests/console-links.test.ts guards it; AGENTS rule 11, pitfall 71

This commit is contained in:
CRTkafa 2026-10-15 19:55:37 +08:00
parent f898d642d0
commit e500e88e40
50 changed files with 381 additions and 92 deletions

View file

@ -4,6 +4,7 @@
// (App Privacy has no API at all: the owner enters it in App Store Connect), app info (categories, age rating,
// content rights), the export compliance answer and the App Review details (presence only, masked). Every answer the
// config does not prove is an "ask the owner" item, never a guess (AGENTS.md rule 5). Pure.
import { consoleLink, consoleUrl } from './console-links';
import { parseCsv } from './csv';
import { type AccountSignUp, type DataSafety, type PlayPurpose, profileOf, type ShipConfig } from './config';
import { CATEGORIES, DATA_DELETION_RESPONSE, dataDeletionResponse, dataSafetyCsv, dataSafetyIssues, dataSafetyRows } from './data-safety';
@ -163,8 +164,8 @@ export function declarations(config: ShipConfig, inp: DeclarationInputs): Declar
fromDataSafety: !!ds,
} : null;
if (apple) {
if (!ds) ask.push({ area: 'appPrivacy', id: 'ap-unknown', text: 'App Privacy (App Store Connect > App Privacy) cannot be suggested without dataSafety answers in the config.', fix: 'Answer the data collection once in dataSafety; storebound then lists the matching App Privacy answers to enter.' });
else ask.push({ area: 'appPrivacy', id: 'ap-linked', text: 'App Privacy asks per data type whether it is linked to the user\'s identity and whether it is used for tracking; the config cannot prove either.', fix: 'Answer both in App Store Connect > App Privacy for each type below (tracking also needs App Tracking Transparency in the app).' });
if (!ds) ask.push({ area: 'appPrivacy', id: 'ap-unknown', text: `App Privacy (${consoleLink('asc.app-privacy')}) cannot be suggested without dataSafety answers in the config.`, url: consoleUrl('asc.app-privacy'), fix: 'Answer the data collection once in dataSafety; storebound then lists the matching App Privacy answers to enter.' });
else ask.push({ area: 'appPrivacy', id: 'ap-linked', text: 'App Privacy asks per data type whether it is linked to the user\'s identity and whether it is used for tracking; the config cannot prove either.', fix: `Answer both in ${consoleLink('asc.app-privacy')} for each type below (tracking also needs App Tracking Transparency in the app).`, url: consoleUrl('asc.app-privacy') });
}
const info = config.apple?.info;