apphx 1.0.0 → 2.0.0

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.
Files changed (126) hide show
  1. package/README.md +52 -138
  2. package/benchmarks/peer-context-worker.mjs +186 -0
  3. package/benchmarks/peer-context.mjs +150 -0
  4. package/dist/apple-types.js.map +1 -1
  5. package/dist/cli.js +373 -121
  6. package/dist/cli.js.map +1 -1
  7. package/dist/config.js +42 -4
  8. package/dist/config.js.map +1 -1
  9. package/dist/dependencies.js +455 -16
  10. package/dist/dependencies.js.map +1 -1
  11. package/dist/export-options.js +44 -2
  12. package/dist/export-options.js.map +1 -1
  13. package/dist/flutter.js +13 -25
  14. package/dist/flutter.js.map +1 -1
  15. package/dist/go-dependencies.js +389 -0
  16. package/dist/go-dependencies.js.map +1 -0
  17. package/dist/inbox.js +7 -8
  18. package/dist/inbox.js.map +1 -1
  19. package/dist/integrations.js +29 -29
  20. package/dist/integrations.js.map +1 -1
  21. package/dist/isolation.js +190 -0
  22. package/dist/isolation.js.map +1 -0
  23. package/dist/macos.js +57 -0
  24. package/dist/macos.js.map +1 -0
  25. package/dist/mygo-build.js +55 -0
  26. package/dist/mygo-build.js.map +1 -0
  27. package/dist/policy.js +35 -0
  28. package/dist/policy.js.map +1 -0
  29. package/dist/preflight.js +1 -1
  30. package/dist/process.js +3 -3
  31. package/dist/project-profiles.js +163 -0
  32. package/dist/project-profiles.js.map +1 -0
  33. package/dist/proof.js +33 -0
  34. package/dist/proof.js.map +1 -0
  35. package/dist/remote.js +1 -1
  36. package/dist/runner.js +269 -287
  37. package/dist/runner.js.map +1 -1
  38. package/dist/scheduler.js +0 -3
  39. package/dist/scheduler.js.map +1 -1
  40. package/dist/schemas.js +156 -44
  41. package/dist/schemas.js.map +1 -1
  42. package/dist/store.js +166 -44
  43. package/dist/store.js.map +1 -1
  44. package/dist/vendor/obfuscator/dist/cli.js +72 -0
  45. package/dist/vendor/obfuscator/dist/cli.js.map +1 -0
  46. package/dist/vendor/obfuscator/dist/code.js +585 -0
  47. package/dist/vendor/obfuscator/dist/code.js.map +1 -0
  48. package/dist/vendor/obfuscator/dist/common.js +262 -0
  49. package/dist/vendor/obfuscator/dist/common.js.map +1 -0
  50. package/dist/vendor/obfuscator/dist/config.js +123 -0
  51. package/dist/vendor/obfuscator/dist/config.js.map +1 -0
  52. package/dist/vendor/obfuscator/dist/content.js +89 -0
  53. package/dist/vendor/obfuscator/dist/content.js.map +1 -0
  54. package/dist/vendor/obfuscator/dist/obfuscate.js +93 -0
  55. package/dist/vendor/obfuscator/dist/obfuscate.js.map +1 -0
  56. package/dist/vendor/obfuscator/dist/png.js +283 -0
  57. package/dist/vendor/obfuscator/dist/png.js.map +1 -0
  58. package/dist/vendor/obfuscator/dist/project.js +159 -0
  59. package/dist/vendor/obfuscator/dist/project.js.map +1 -0
  60. package/dist/vendor/obfuscator/dist/resources.js +335 -0
  61. package/dist/vendor/obfuscator/dist/resources.js.map +1 -0
  62. package/dist/vendor/obfuscator/package.json +22 -0
  63. package/dist/workspace.js +113 -0
  64. package/dist/workspace.js.map +1 -0
  65. package/evals/control.mjs +73 -0
  66. package/evals/expectations.mjs +37 -0
  67. package/evals/host.mjs +51 -0
  68. package/evals/oracle.mjs +80 -0
  69. package/evals/policy.mjs +268 -0
  70. package/examples/android-java.factory.json +18 -0
  71. package/examples/android-java.json +16 -0
  72. package/examples/existing-project.factory.json +18 -0
  73. package/examples/existing-project.json +17 -0
  74. package/examples/expo.eas.json +17 -0
  75. package/examples/expo.factory.json +18 -0
  76. package/examples/expo.json +16 -0
  77. package/examples/factory.json +0 -2
  78. package/examples/flutter.factory.json +13 -0
  79. package/examples/flutter.json +16 -0
  80. package/examples/luggage.json +5 -3
  81. package/examples/mygo-web.factory.json +18 -0
  82. package/examples/mygo-web.json +16 -0
  83. package/examples/mygo.factory.json +18 -0
  84. package/examples/mygo.json +16 -0
  85. package/examples/react-native.factory.json +18 -0
  86. package/examples/react-native.json +16 -0
  87. package/examples/remote.json +1 -1
  88. package/examples/runtime/android-java/app/build.gradle +7 -0
  89. package/examples/runtime/android-java/app/src/main/AndroidManifest.xml +8 -0
  90. package/examples/runtime/android-java/app/src/main/java/dev/apphx/runtime/MainActivity.java +44 -0
  91. package/examples/runtime/android-java/sdk-build.mjs +29 -0
  92. package/examples/runtime/android-java/settings.gradle +2 -0
  93. package/examples/runtime/android-ui.mjs +70 -0
  94. package/examples/runtime/mygo-native/go.mod +13 -0
  95. package/examples/runtime/mygo-native/go.sum +10 -0
  96. package/examples/runtime/mygo-native/main.go +173 -0
  97. package/examples/runtime/mygo-native/main_test.go +14 -0
  98. package/examples/runtime/mygo-native/mygo.json +1 -0
  99. package/examples/runtime/mygo-web/bun.lock +15 -0
  100. package/examples/runtime/mygo-web/go.mod +9 -0
  101. package/examples/runtime/mygo-web/go.sum +8 -0
  102. package/examples/runtime/mygo-web/index.html +1 -0
  103. package/examples/runtime/mygo-web/main.go +60 -0
  104. package/examples/runtime/mygo-web/mygo.config.ts +10 -0
  105. package/examples/runtime/mygo-web/package.json +1 -0
  106. package/examples/runtime/mygo-web/src/main.ts +23 -0
  107. package/examples/runtime/mygo-web/src/mygo.ts +14 -0
  108. package/examples/swift.factory.json +18 -0
  109. package/examples/swift.json +16 -0
  110. package/examples/uni-app.factory.json +18 -0
  111. package/examples/uni-app.json +16 -0
  112. package/package.json +12 -5
  113. package/scripts/bundle-obfuscator.mjs +19 -0
  114. package/scripts/runtime-smoke.mjs +209 -0
  115. package/skills/apphx/SKILL.md +180 -0
  116. package/skills/apphx/resources/google-play-research-result.json +6 -0
  117. package/skills/apphx/resources/local-research-result.json +6 -0
  118. package/skills/{apple-app-factory → apphx}/resources/requirement.json +5 -8
  119. package/skills/apphx/resources/research-result.json +12 -0
  120. package/skills/apphx/resources/review-result.json +7 -0
  121. package/dist/apple.js +0 -900
  122. package/dist/apple.js.map +0 -1
  123. package/skills/apple-app-factory/SKILL.md +0 -103
  124. package/skills/apple-app-factory/resources/research-result.json +0 -21
  125. package/skills/apple-app-factory/resources/review-result.json +0 -7
  126. /package/skills/{apple-app-factory → apphx}/LICENSE +0 -0
package/dist/apple.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"apple.js","names":["defaultRun","run"],"sources":["../src/apple.ts"],"sourcesContent":["import { createHash, createPrivateKey, sign } from 'node:crypto';\nimport type { KeyObject } from 'node:crypto';\nimport { copyFile, chmod, mkdtemp, readdir, readFile, rm, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { basename, join } from 'node:path';\nimport { z } from 'zod';\nimport { run as defaultRun } from './process.js';\nimport type { Run } from './process.js';\nimport type { AppleSpec, Spec } from './schemas.js';\nimport type { ApplePollResult, AppleReceipt } from './apple-types.js';\nexport { AppleReceiptSchema } from './apple-types.js';\nexport type { ApplePollResult, AppleReceipt } from './apple-types.js';\n\nconst UploadOperationSchema = z.object({\n url: z.string(), method: z.string(), offset: z.number().finite(), length: z.number().finite(),\n requestHeaders: z.array(z.object({ name: z.string(), value: z.string() })).nullish(),\n});\nconst AttributesSchema = z.object({\n bundleId: z.string().optional(), appVersionState: z.string().nullish(), appStoreState: z.string().nullish(), state: z.string().nullish(),\n processingState: z.string().optional(), usesNonExemptEncryption: z.boolean().nullish(),\n copyright: z.string().optional(), releaseType: z.string().optional(), locale: z.string().optional(),\n description: z.string().optional(), keywords: z.string().optional(), supportUrl: z.string().optional(), whatsNew: z.string().optional(),\n privacyPolicyUrl: z.string().optional(), contactFirstName: z.string().optional(), contactLastName: z.string().optional(),\n contactEmail: z.string().optional(), contactPhone: z.string().optional(), notes: z.string().optional(), demoAccountRequired: z.boolean().optional(),\n screenshotDisplayType: z.string().optional(), fileName: z.string().optional(), sourceFileChecksum: z.string().nullish(),\n assetDeliveryState: z.object({ state: z.string().optional() }).nullish(),\n uploadOperations: z.array(UploadOperationSchema).nullish(),\n});\nconst ResourceSchema = z.object({\n id: z.string().min(1), type: z.string().optional(), attributes: AttributesSchema.default({}),\n relationships: z.object({ appStoreVersion: z.object({ data: z.object({ id: z.string(), type: z.string().optional() }).nullish() }).optional() }).optional(),\n});\nconst ResponseSchema = z.object({\n data: z.union([ResourceSchema, z.array(ResourceSchema)]).nullish(),\n links: z.object({ next: z.string().nullish() }).optional(),\n});\nconst ErrorResponseSchema = z.object({ errors: z.array(z.object({ code: z.string().optional(), detail: z.string().nullish(), title: z.string().optional() })).optional() });\nconst ListingSchema = z.object({ results: z.array(z.object({ bundleId: z.string().optional(), version: z.string().optional() })) });\ntype Resource = z.infer<typeof ResourceSchema>;\ntype ResourceAttributes = z.infer<typeof AttributesSchema>;\ntype AppleResponse = z.infer<typeof ResponseSchema>;\ntype WriteMethod = 'POST' | 'PATCH' | 'PUT';\ninterface RequestOptions { method?: string; body?: unknown; optional?: boolean }\ninterface AppleClient {\n request(path: string, options?: RequestOptions & { optional?: false }): Promise<AppleResponse>;\n request(path: string, options: RequestOptions & { optional: true }): Promise<AppleResponse | null>;\n list(path: string | null | undefined): Promise<Resource[]>;\n credentials: { keyId: string; issuerId: string; keyPath: string };\n}\ntype Persist = (patch?: Partial<AppleReceipt>) => Promise<void>;\ntype Write = (key: string, path: string, method: WriteMethod, body: unknown) => Promise<Resource | undefined>;\ntype Reconcile = (key: string, resource: Resource) => Promise<Resource>;\ntype LocalInventory = Map<string, Map<string, { bytes: Buffer; checksum: string }>>;\nconst publishingFields = ['appId', 'bundleId', 'version', 'buildNumber', 'locale', 'description', 'keywords', 'supportUrl', 'privacyPolicyUrl', 'reviewNotes', 'copyright'] as const;\nconst contactFields = ['firstName', 'lastName', 'email', 'phone'] as const;\nexport type PublishingSpec = AppleSpec & Required<Pick<AppleSpec, typeof publishingFields[number]>> & { contact: Required<NonNullable<AppleSpec['contact']>>; manualSetupConfirmed: true };\ninterface AppleOptions { spec: Pick<Spec, 'apple'>; state?: AppleReceipt; env?: NodeJS.ProcessEnv; signal?: AbortSignal }\ninterface ShipOptions extends AppleOptions { ipaPath: string; save: (receipt: AppleReceipt) => void | Promise<unknown>; run?: Run; allowRelease?: boolean }\ninterface ScreenshotOptions {\n api: AppleClient; apple: PublishingSpec; localization: Resource;\n receipt: () => AppleReceipt; persist: Persist; write: Write; reconcile: Reconcile; signal?: AbortSignal;\n}\nfunction message(error: unknown): string { return error instanceof Error ? error.message : String(error); }\nfunction textAttribute(value: string | null | undefined): string {\n if (value === undefined || value === null) throw failure('App Store Connect returned a resource missing a required text field.', 'APPLE_API_ERROR');\n return value;\n}\nfunction resource(value: AppleResponse['data'] | undefined): Resource {\n if (!value || Array.isArray(value)) throw failure('App Store Connect returned an invalid resource.', 'APPLE_API_ERROR');\n return value;\n}\nfunction optionalResource(response: AppleResponse | null): Resource | undefined {\n return response?.data == null ? undefined : resource(response.data);\n}\n\nconst API = 'https://api.appstoreconnect.apple.com';\nconst editable = new Set<string | null | undefined>(['PREPARE_FOR_SUBMISSION', 'DEVELOPER_REJECTED', 'METADATA_REJECTED', 'REJECTED']);\nconst approved = new Set<string | null | undefined>(['ACCEPTED', 'PENDING_DEVELOPER_RELEASE', 'PENDING_APPLE_RELEASE', 'READY_FOR_SALE', 'READY_FOR_DISTRIBUTION', 'PROCESSING_FOR_DISTRIBUTION', 'PROCESSING_FOR_APP_STORE']);\nconst rejected = new Set<string | null | undefined>(['REJECTED', 'METADATA_REJECTED', 'INVALID_BINARY', 'DEVELOPER_REJECTED']);\nconst versionState = (resource: Resource) => resource.attributes.appVersionState ?? resource.attributes.appStoreState;\nconst ref = (type: string, id: string) => ({ data: { type, id } });\nconst matches = (resource: Resource, attributes: ResourceAttributes) => (Object.keys(attributes) as (keyof ResourceAttributes)[]).every(key => resource.attributes[key] === attributes[key]);\nconst query = (path: string, values: Record<string, string | number>) => `${path}?${new URLSearchParams(Object.entries(values).map(([key, value]) => [key, String(value)]))}`;\n\nfunction failure(message: string, code = 'APPLE_SETUP_REQUIRED') {\n return Object.assign(new Error(message), { code });\n}\n\nfunction requestFailure(message: string, code: string, httpStatus: number | null = null, transient = httpStatus === 408 || httpStatus === 429 || (httpStatus !== null && httpStatus >= 500)) {\n return Object.assign(failure(message, code), {\n httpStatus,\n transient,\n outcome: httpStatus !== null && httpStatus >= 400 && httpStatus < 500 && httpStatus !== 408 ? 'rejected' : 'unknown',\n });\n}\n\nfunction credential(env: NodeJS.ProcessEnv, key: string): string {\n const value = env[key];\n if (!value) throw failure(`Set ${key} in the publisher environment. App Store Connect requires a team API key with App Manager or Admin access.`);\n return value;\n}\n\nasync function client(env: NodeJS.ProcessEnv, signal?: AbortSignal): Promise<AppleClient> {\n const keyId = credential(env, 'ASC_KEY_ID');\n const issuerId = credential(env, 'ASC_ISSUER_ID');\n const keyPath = credential(env, 'ASC_PRIVATE_KEY_PATH');\n if (!/^[A-Za-z0-9]+$/.test(keyId)) throw failure('ASC_KEY_ID must be an App Store Connect key identifier.');\n let key: KeyObject;\n try {\n key = createPrivateKey(await readFile(keyPath));\n } catch (error) {\n throw failure(`Cannot load ASC_PRIVATE_KEY_PATH as a private signing key: ${message(error)}`);\n }\n if (key.asymmetricKeyType !== 'ec' || key.asymmetricKeyDetails?.namedCurve !== 'prime256v1') {\n throw failure('ASC_PRIVATE_KEY_PATH must contain the P-256 private key downloaded from App Store Connect for ES256 authentication.');\n }\n let token: string | undefined;\n let expires = 0;\n async function request(path: string, options?: RequestOptions & { optional?: false }): Promise<AppleResponse>;\n async function request(path: string, options: RequestOptions & { optional: true }): Promise<AppleResponse | null>;\n async function request(path: string, { method = 'GET', body, optional = false }: RequestOptions = {}): Promise<AppleResponse | null> {\n const url = new URL(path, API);\n if (url.origin !== API || !/^\\/v[12]\\//.test(url.pathname)) throw failure('Apple returned an unexpected API URL; refusing to send publisher credentials.', 'APPLE_API_ERROR');\n const now = Math.floor(Date.now() / 1000);\n if (expires < now + 30) {\n expires = now + 600;\n const encode = (value: unknown) => Buffer.from(JSON.stringify(value)).toString('base64url');\n const input = `${encode({ alg: 'ES256', kid: env.ASC_KEY_ID, typ: 'JWT' })}.${encode({ iss: env.ASC_ISSUER_ID, iat: now, exp: expires, aud: 'appstoreconnect-v1' })}`;\n token = `${input}.${sign('sha256', Buffer.from(input), { key, dsaEncoding: 'ieee-p1363' }).toString('base64url')}`;\n }\n let response: Response;\n try {\n response = await fetch(url, {\n method, redirect: 'error', signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(30000)]) : AbortSignal.timeout(30000),\n headers: { Authorization: `Bearer ${token}`, Accept: 'application/json', ...(body ? { 'Content-Type': 'application/json' } : {}) },\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n } catch (error) {\n throw requestFailure(`App Store Connect ${method} ${url.pathname} did not complete: ${message(error)}. Resume to reconcile saved writes; do not repeat an upload manually.`, 'APPLE_API_ERROR', null, true);\n }\n if (optional && response.status === 404) return null;\n const httpCode = response.status === 429 ? 'APPLE_RATE_LIMIT' : response.status >= 500 || response.status === 408 || response.ok ? 'APPLE_API_ERROR' : 'APPLE_SETUP_REQUIRED';\n let text: string;\n try { text = await response.text(); } catch (error) {\n throw requestFailure(`App Store Connect ${method} ${url.pathname} response body was lost (HTTP ${response.status}): ${message(error)}. Resume to reconcile saved writes.`, httpCode, response.status, response.ok || response.status === 408 || response.status === 429 || response.status >= 500);\n }\n let data: unknown;\n try { data = text ? JSON.parse(text) : {}; } catch { throw requestFailure(`App Store Connect returned non-JSON data for ${url.pathname} (HTTP ${response.status}).`, httpCode, response.status); }\n if (!response.ok) {\n const errors = ErrorResponseSchema.safeParse(data);\n const detail = (errors.success ? errors.data.errors?.map(error => `${error.code}: ${error.detail ?? error.title}`).join('; ') : '') || response.statusText;\n throw requestFailure(`App Store Connect ${method} ${url.pathname} failed (HTTP ${response.status}): ${detail}${response.status === 429 ? '. Request limit reached; resume later. No write was retried.' : ''}`, httpCode, response.status);\n }\n const parsed = ResponseSchema.safeParse(data);\n if (!parsed.success) throw requestFailure(`App Store Connect returned invalid resource data for ${url.pathname} (HTTP ${response.status}): ${parsed.error.message}`, httpCode, response.status);\n return parsed.data;\n }\n async function list(path: string | null | undefined): Promise<Resource[]> {\n const result: Resource[] = [];\n for (let page = 0; path; page++) {\n if (page >= 100) throw failure('App Store Connect pagination exceeded 100 pages; narrow the app/version selection.', 'APPLE_API_ERROR');\n const response = await request(path);\n if (!Array.isArray(response.data)) throw failure('App Store Connect returned an invalid resource list.', 'APPLE_API_ERROR');\n result.push(...response.data);\n path = response.links?.next;\n }\n return result;\n }\n return { request, list, credentials: { keyId, issuerId, keyPath } };\n}\n\nexport async function appleDoctor({ env = process.env }: { env?: NodeJS.ProcessEnv } = {}) {\n const checks: { name: string; available: boolean; detail: string }[] = [];\n try {\n const api = await client(env);\n await api.request('/v1/apps?limit=1');\n checks.push({ name: 'App Store Connect API', available: true, detail: 'Team key authenticated with read access. Submission permissions and app setup are checked when shipping.' });\n } catch (error) {\n checks.push({ name: 'App Store Connect API', available: false, detail: message(error) });\n }\n try {\n const result = await defaultRun(['xcrun', 'altool', '--help'], { env, timeoutMs: 30000 });\n const supported = result.code === 0 && `${result.stdout}\\n${result.stderr}`.includes('--upload-package');\n checks.push({ name: 'Apple binary uploader', available: supported, detail: supported ? 'xcrun altool supports package upload. No binary was uploaded.' : 'Install/select full Xcode with a current altool supporting --upload-package; Command Line Tools alone are insufficient.' });\n } catch (error) {\n checks.push({ name: 'Apple binary uploader', available: false, detail: `Cannot invoke xcrun altool: ${message(error)}. Install/select full Xcode.` });\n }\n return checks;\n}\n\nexport function validateAppleSpec(spec: Pick<Spec, 'apple'>): PublishingSpec {\n const apple = spec?.apple;\n for (const field of publishingFields) {\n const value = apple?.[field];\n if (typeof value !== 'string' || !value.trim()) throw failure(`spec.apple.${field} is required before shipping. Provide real publisher metadata, not generated placeholders.`);\n }\n for (const field of contactFields) {\n const value = apple?.contact?.[field];\n if (typeof value !== 'string' || !value.trim()) throw failure(`spec.apple.contact.${field} is required for App Review.`);\n }\n for (const field of ['supportUrl', 'privacyPolicyUrl'] as const) {\n let url: URL;\n try { url = new URL(apple?.[field] ?? ''); } catch { throw failure(`spec.apple.${field} must be a public HTTPS URL.`); }\n if (url.protocol !== 'https:' || url.username || url.password) throw failure(`spec.apple.${field} must be a public HTTPS URL without credentials.`);\n }\n if (apple?.manualSetupConfirmed !== true) throw failure('Complete App Store Connect agreements, app privacy disclosures, age rating, content rights, export compliance, pricing/availability and applicable trader/legal declarations. Then set spec.apple.manualSetupConfirmed=true as the publisher’s attestation. Automation cannot answer these declarations for you.');\n return apple as PublishingSpec;\n}\n\nasync function findVersion(api: AppleClient, appId: string, version: string): Promise<Resource | undefined> {\n const versions = await api.list(query(`/v1/apps/${encodeURIComponent(appId)}/appStoreVersions`, { 'filter[platform]': 'IOS', 'filter[versionString]': version, limit: 200 }));\n if (versions.length > 1) throw failure('Multiple matching iOS App Store versions were returned; resolve the app record in App Store Connect.', 'APPLE_API_ERROR');\n return versions[0];\n}\n\nasync function requireSelectedBuild(api: AppleClient, versionId: string, buildId: string | undefined) {\n if (!buildId) throw failure('The saved Apple receipt has no build ID. Restore the receipt for the verified upload before resuming.', 'APPLE_STATE_MISMATCH');\n const selected = optionalResource(await api.request(`/v1/appStoreVersions/${encodeURIComponent(versionId)}/build`, { optional: true }));\n if (selected?.id !== buildId) throw failure('The selected App Store build differs from this job’s saved upload. Restore the verified build in App Store Connect before resuming.', 'APPLE_STATE_MISMATCH');\n}\n\nfunction requireDeliveryProvenance(receipt: AppleReceipt): void {\n if (receipt.upload && receipt.upload.status !== 'delivered') throw failure('The saved upload has no successful delivery receipt. App Store Connect cannot prove that a matching build came from this IPA. Check Apple delivery history; do not select a build, submit, or upload again from this job.', 'APPLE_WRITE_UNCERTAIN');\n}\n\nexport async function shipApple({ spec, ipaPath, state = {}, save, run = defaultRun, env = process.env, signal, allowRelease = false }: ShipOptions): Promise<AppleReceipt> {\n const apple = validateAppleSpec(spec);\n const releaseType = allowRelease === true ? 'AFTER_APPROVAL' : 'MANUAL';\n if (allowRelease && !/^[A-Za-z]{2}$/.test(apple.storefrontCountry ?? '')) throw failure('Automatic release requires apple.storefrontCountry as a two-letter country code so public listing availability can be checked.');\n if (typeof save !== 'function') throw failure('shipApple requires a durable save callback before it can make external writes.', 'APPLE_STATE_REQUIRED');\n let receipt: AppleReceipt = structuredClone(state);\n const identity = { appId: apple.appId, bundleId: apple.bundleId, version: apple.version, buildNumber: apple.buildNumber };\n if (receipt.identity && JSON.stringify(receipt.identity) !== JSON.stringify(identity)) throw failure('The saved Apple receipt belongs to another app/version/build. Resume the original job or create a new job.', 'APPLE_STATE_MISMATCH');\n requireDeliveryProvenance(receipt);\n receipt.identity = identity;\n async function persist(patch: Partial<AppleReceipt> = {}) {\n receipt = { ...receipt, ...patch };\n await save(structuredClone(receipt));\n }\n async function reconcile(key: string, resource: Resource) {\n if (receipt.pending?.key === key) await persist({ pending: null, effects: { ...receipt.effects, [key]: { id: resource?.id } }, lastEffect: { key, id: resource?.id, reconciled: true } });\n return resource;\n }\n async function write(key: string, path: string, method: WriteMethod, body: unknown): Promise<Resource | undefined> {\n if (receipt.pending) throw failure(`The saved write “${receipt.pending.key}” has an uncertain outcome. Resume after checking App Store Connect; this factory will not duplicate it.`, 'APPLE_WRITE_UNCERTAIN');\n await persist({ pending: { key, path, method, startedAt: new Date().toISOString() } });\n let result: Resource | undefined;\n try {\n result = optionalResource(await api.request(path, { method, body }));\n if (method === 'POST' && !result) throw requestFailure('App Store Connect returned no resource for a creation request. Resume to reconcile saved writes.', 'APPLE_API_ERROR');\n } catch (error) {\n if (error instanceof Error && 'outcome' in error && error.outcome === 'rejected') await persist({ pending: null });\n throw error;\n }\n await persist({ pending: null, effects: { ...receipt.effects, [key]: { id: result?.id } }, lastEffect: { key, id: result?.id, completedAt: new Date().toISOString() } });\n return result;\n }\n async function ensureAttributes(current: Resource, attributes: ResourceAttributes, key: string): Promise<Resource> {\n if (matches(current, attributes)) return reconcile(key, current);\n const type = textAttribute(current.type);\n return resource(await write(key, `/v1/${type}/${encodeURIComponent(current.id)}`, 'PATCH', { data: { type, id: current.id, attributes } }));\n }\n const api = await client(env, signal);\n const app = resource((await api.request(`/v1/apps/${encodeURIComponent(apple.appId)}`)).data);\n if (app.attributes.bundleId !== apple.bundleId) throw failure('spec.apple.appId and bundleId identify different apps. Correct the publisher specification before uploading.');\n await persist();\n let version = await findVersion(api, apple.appId, apple.version);\n if (version && !editable.has(versionState(version))) {\n const submissionId = receipt.submissionId ?? receipt.effects?.['create-review-submission']?.id;\n if (!submissionId || (receipt.versionId && receipt.versionId !== version.id)) throw failure(`Version ${apple.version} is ${versionState(version)} and has no matching submission receipt. Inspect it in App Store Connect; this factory will not overwrite or resubmit it.`, 'APPLE_WRITE_UNCERTAIN');\n await requireSelectedBuild(api, version.id, receipt.buildId);\n const submission = resource((await api.request(`/v1/reviewSubmissions/${encodeURIComponent(submissionId)}`)).data);\n const items = await api.list(`/v1/reviewSubmissions/${submission.id}/items?include=appStoreVersion&limit=200`);\n const versionId = version.id;\n const item = items.find(item => item.relationships?.appStoreVersion?.data?.id === versionId);\n if (!item || items.length !== 1) throw failure('The saved submission does not contain only this app version. Inspect it in App Store Connect before submitting.', 'APPLE_WRITE_UNCERTAIN');\n await reconcile('add-review-item', item);\n if (submission.attributes.state === 'READY_FOR_REVIEW') {\n if (apple.screenshotsDir) {\n const localizations = await api.list(`/v1/appStoreVersions/${version.id}/appStoreVersionLocalizations?limit=200`);\n const localization = localizations.find(item => item.attributes.locale === apple.locale);\n if (!localization) throw failure(`No ${apple.locale} App Store version localization exists. Restore the screenshot localization in App Store Connect before submitting.`, 'APPLE_STATE_MISMATCH');\n await verifyScreenshots({ api, apple, localization, localInventory: await readLocalScreenshots(apple.screenshotsDir) });\n }\n await write('submit-review', `/v1/reviewSubmissions/${submission.id}`, 'PATCH', { data: { type: 'reviewSubmissions', id: submission.id, attributes: { submitted: true } } });\n } else if (['WAITING_FOR_REVIEW', 'IN_REVIEW', 'COMPLETING', 'COMPLETE'].includes(submission.attributes.state ?? '')) await reconcile('submit-review', submission);\n else throw failure(`Review submission is ${submission.attributes.state}. Resolve review issues in App Store Connect; no resubmission was attempted.`);\n await persist({ submissionId: submission.id });\n await persist({ versionId: version.id, phase: 'submitted' });\n return receipt;\n }\n const ipa = await stat(ipaPath);\n if (!ipa.isFile() || ipa.size === 0) throw failure('The IPA archive is missing or empty. Package the verified app before shipping.');\n const builds = await api.list(query('/v1/builds', { 'filter[app]': apple.appId, 'filter[version]': apple.buildNumber, 'filter[preReleaseVersion.version]': apple.version, 'filter[preReleaseVersion.platform]': 'IOS', limit: 200 }));\n if (builds.length > 1) throw failure('Multiple builds match this app/version/build number. Inspect App Store Connect before resuming.', 'APPLE_STATE_MISMATCH');\n let build = builds[0];\n if (receipt.buildId && build?.id !== receipt.buildId) throw failure('The remote build differs from this job’s saved build binding. Restore the verified build before resuming; no upload was attempted.', 'APPLE_STATE_MISMATCH');\n if (build && !receipt.upload && !receipt.buildId) throw failure(`Build ${apple.version} (${apple.buildNumber}) already exists without this job’s upload receipt. Use a new build number; do not reuse an unverified remote binary.`, 'APPLE_WRITE_UNCERTAIN');\n if (!build && !receipt.upload && !receipt.buildId) {\n const help = await run(['xcrun', 'altool', '--help'], { env, signal, timeoutMs: 30000 });\n if (help.code !== 0 || !`${help.stdout}\\n${help.stderr}`.includes('--upload-package')) throw failure('Select full Xcode with altool supporting --upload-package before shipping. No upload was attempted.');\n const keyDirectory = await mkdtemp(join(tmpdir(), 'factory-asc-'));\n try {\n const keyFile = join(keyDirectory, `AuthKey_${env.ASC_KEY_ID}.p8`);\n await copyFile(api.credentials.keyPath, keyFile);\n await chmod(keyFile, 0o600);\n const upload = { status: 'intent' as const, startedAt: new Date().toISOString() };\n await persist({ upload });\n const result = await run(['xcrun', 'altool', '--upload-package', ipaPath, '--platform', 'ios', '--apple-id', apple.appId, '--bundle-id', apple.bundleId, '--bundle-version', apple.buildNumber, '--bundle-short-version-string', apple.version, '--api-key', api.credentials.keyId, '--api-issuer', api.credentials.issuerId, '--wait', '--output-format', 'json'], { env: { ...env, API_PRIVATE_KEYS_DIR: keyDirectory }, signal, timeoutMs: 1200000 });\n if (result.code !== 0) throw failure(`Apple’s uploader exited with code ${result.code}. Inspect its delivery history and App Store Connect for ${apple.version} (${apple.buildNumber}); the saved upload intent prevents a duplicate upload. ${result.stderr || result.stdout}`, 'APPLE_WRITE_UNCERTAIN');\n await persist({ upload: { ...upload, status: 'delivered' }, phase: 'processing' });\n } finally {\n await rm(keyDirectory, { recursive: true, force: true });\n }\n }\n if (!build) {\n const deliveredBuilds = await api.list(query('/v1/builds', { 'filter[app]': apple.appId, 'filter[version]': apple.buildNumber, 'filter[preReleaseVersion.version]': apple.version, 'filter[preReleaseVersion.platform]': 'IOS', limit: 200 }));\n if (deliveredBuilds.length > 1) throw failure('Multiple builds match the successful delivery. Inspect App Store Connect before resuming.', 'APPLE_STATE_MISMATCH');\n build = deliveredBuilds[0];\n }\n if (!build) throw failure(`Build ${apple.version} (${apple.buildNumber}) is not visible in App Store Connect. Apple is processing the delivery; resume this job later.`, 'APPLE_PROCESSING');\n await persist({ buildId: build.id });\n if (['FAILED', 'INVALID'].includes(build.attributes.processingState ?? '')) throw failure(`Apple marked build ${apple.buildNumber} ${build.attributes.processingState}. Inspect processing errors in App Store Connect and package a corrected build with a new build number.`);\n if (build.attributes.processingState !== 'VALID') throw failure(`Apple is processing build ${apple.buildNumber}; resume this job later. No second upload will be made.`, 'APPLE_PROCESSING');\n if (build.attributes.usesNonExemptEncryption == null) throw failure('Answer export compliance for this build in App Store Connect, or set the correct ITSAppUsesNonExemptEncryption value in the app and upload a new build. The factory cannot infer your encryption declaration.');\n if (!version) version = resource(await write('create-version', '/v1/appStoreVersions', 'POST', { data: { type: 'appStoreVersions', attributes: { platform: 'IOS', versionString: apple.version, copyright: apple.copyright, releaseType }, relationships: { app: ref('apps', apple.appId) } } }));\n else await reconcile('create-version', version);\n await persist({ versionId: version.id });\n version = await ensureAttributes(version, { copyright: apple.copyright, releaseType }, 'version-metadata');\n const localizations = await api.list(`/v1/appStoreVersions/${version.id}/appStoreVersionLocalizations?limit=200`);\n let localization = localizations.find(item => item.attributes.locale === apple.locale);\n const metadata = { description: apple.description, keywords: apple.keywords, supportUrl: apple.supportUrl, ...(apple.whatsNew ? { whatsNew: apple.whatsNew } : {}) };\n if (!localization) localization = resource(await write('create-localization', '/v1/appStoreVersionLocalizations', 'POST', { data: { type: 'appStoreVersionLocalizations', attributes: { locale: apple.locale, ...metadata }, relationships: { appStoreVersion: ref('appStoreVersions', version.id) } } }));\n else await reconcile('create-localization', localization);\n await ensureAttributes(localization, metadata, 'localization-metadata');\n const infos = await api.list(`/v1/apps/${encodeURIComponent(apple.appId)}/appInfos?limit=200`);\n const info = infos.find(item => editable.has(item.attributes.state ?? item.attributes.appStoreState));\n if (!info) throw failure('No editable app information record exists. Check app status and age rating in App Store Connect.');\n const infoLocales = await api.list(`/v1/appInfos/${info.id}/appInfoLocalizations?limit=200`);\n const infoLocale = infoLocales.find(item => item.attributes.locale === apple.locale);\n if (!infoLocale) throw failure(`Create the ${apple.locale} app information localization in App Store Connect, including the app name and privacy policy.`);\n await ensureAttributes(infoLocale, { privacyPolicyUrl: apple.privacyPolicyUrl }, 'privacy-url');\n let review = optionalResource(await api.request(`/v1/appStoreVersions/${version.id}/appStoreReviewDetail`, { optional: true }));\n const contact = apple.contact;\n const reviewAttributes = { contactFirstName: contact.firstName, contactLastName: contact.lastName, contactEmail: contact.email, contactPhone: contact.phone, notes: apple.reviewNotes, demoAccountRequired: false };\n if (!review) review = resource(await write('create-review-details', '/v1/appStoreReviewDetails', 'POST', { data: { type: 'appStoreReviewDetails', attributes: reviewAttributes, relationships: { appStoreVersion: ref('appStoreVersions', version.id) } } }));\n else await reconcile('create-review-details', review);\n if (review.attributes?.demoAccountRequired) throw failure('This app requires a demo account. Configure review access in App Store Connect; the offline utility pipeline does not handle account credentials.');\n await ensureAttributes(review, reviewAttributes, 'review-details');\n await screenshots({ api, apple, localization, receipt: () => receipt, persist, write, reconcile, signal });\n const selected = optionalResource(await api.request(`/v1/appStoreVersions/${version.id}/build`, { optional: true }));\n if (selected?.id === build.id) await reconcile('select-build', selected);\n else await write('select-build', `/v1/appStoreVersions/${version.id}/relationships/build`, 'PATCH', { data: { type: 'builds', id: build.id } });\n let submission: Resource | undefined;\n const submissions = await api.list(query('/v1/reviewSubmissions', { 'filter[app]': apple.appId, limit: 200 }));\n for (const candidate of submissions) {\n const items = await api.list(`/v1/reviewSubmissions/${candidate.id}/items?include=appStoreVersion&limit=200`);\n const item = items.find(item => item.relationships?.appStoreVersion?.data?.id === version.id);\n if (candidate.id === receipt.submissionId || candidate.id === receipt.effects?.['create-review-submission']?.id || item) {\n if (submission && submission.id !== candidate.id) throw failure('Multiple review submissions reference this version. Resolve them in App Store Connect before resuming.', 'APPLE_WRITE_UNCERTAIN');\n submission = candidate;\n if (item) await reconcile('add-review-item', item);\n }\n }\n if (!submission && receipt.pending?.key === 'create-review-submission') throw failure('Review submission creation has an uncertain outcome. Check App Store Connect and resume after the submission becomes visible; no duplicate will be created.', 'APPLE_WRITE_UNCERTAIN');\n if (!submission) {\n if (submissions.some(item => ['READY_FOR_REVIEW', 'WAITING_FOR_REVIEW', 'IN_REVIEW', 'UNRESOLVED_ISSUES'].includes(item.attributes.state ?? ''))) throw failure('Another active review submission exists for this app. Resolve it in App Store Connect before starting this version.');\n submission = resource(await write('create-review-submission', '/v1/reviewSubmissions', 'POST', { data: { type: 'reviewSubmissions', attributes: { platform: 'IOS' }, relationships: { app: ref('apps', apple.appId) } } }));\n }\n await reconcile('create-review-submission', submission);\n await persist({ submissionId: submission.id });\n if (submission.attributes.state === 'READY_FOR_REVIEW') {\n const items = await api.list(`/v1/reviewSubmissions/${submission.id}/items?include=appStoreVersion&limit=200`);\n const item = items.find(item => item.relationships?.appStoreVersion?.data?.id === version.id);\n if (items.some(item => item.relationships?.appStoreVersion?.data?.id !== version.id)) throw failure('The review submission contains other items. Inspect and submit it in App Store Connect; the factory will not submit unrelated content.');\n if (item) await reconcile('add-review-item', item);\n else await write('add-review-item', '/v1/reviewSubmissionItems', 'POST', { data: { type: 'reviewSubmissionItems', relationships: { reviewSubmission: ref('reviewSubmissions', submission.id), appStoreVersion: ref('appStoreVersions', version.id) } } });\n await write('submit-review', `/v1/reviewSubmissions/${submission.id}`, 'PATCH', { data: { type: 'reviewSubmissions', id: submission.id, attributes: { submitted: true } } });\n } else if (['WAITING_FOR_REVIEW', 'IN_REVIEW', 'COMPLETING', 'COMPLETE'].includes(submission.attributes.state ?? '')) await reconcile('submit-review', submission);\n else throw failure(`Review submission is ${submission.attributes.state}. Resolve review issues in App Store Connect; no resubmission was attempted.`);\n await persist({ phase: 'submitted' });\n return receipt;\n}\n\nasync function readLocalScreenshots(screenshotsDir: string): Promise<LocalInventory> {\n const directories = await readdir(screenshotsDir, { withFileTypes: true });\n if (!directories.length || directories.some(entry => !entry.isDirectory() || !/^(APP|IMESSAGE_APP)_[A-Z0-9_]+$/.test(entry.name))) throw failure('screenshotsDir must contain display-type directories such as APP_IPHONE_67, each containing real app screenshots.');\n const localInventory: LocalInventory = new Map();\n for (const directory of directories) {\n const files = await readdir(join(screenshotsDir, directory.name), { withFileTypes: true });\n if (!files.length || files.length > 10 || files.some(file => !file.isFile() || !/\\.(png|jpe?g)$/i.test(file.name))) throw failure(`Screenshot display set ${directory.name} must contain 1–10 PNG/JPEG files and no other entries.`);\n const inventory = new Map<string, { bytes: Buffer; checksum: string }>();\n for (const file of files.sort((a, b) => a.name.localeCompare(b.name))) {\n const bytes = await readFile(join(screenshotsDir, directory.name, file.name));\n inventory.set(file.name, { bytes, checksum: createHash('md5').update(bytes).digest('hex') });\n }\n localInventory.set(directory.name, inventory);\n }\n return localInventory;\n}\n\nasync function screenshots({ api, apple, localization, receipt, persist, write, reconcile, signal }: ScreenshotOptions) {\n const sets = await api.list(`/v1/appStoreVersionLocalizations/${localization.id}/appScreenshotSets?limit=200`);\n let localInventory: LocalInventory | undefined;\n if (apple.screenshotsDir) {\n localInventory = await readLocalScreenshots(apple.screenshotsDir);\n const displayTypes = new Set<string>();\n for (const set of sets) {\n const displayType = textAttribute(set.attributes.screenshotDisplayType);\n const inventory = localInventory.get(displayType);\n if (!inventory || displayTypes.has(displayType)) throw failure(`Remote screenshot display set ${displayType} is extra or duplicated. Match App Store Connect to screenshotsDir before resuming; the factory will not delete publisher assets.`, 'APPLE_STATE_MISMATCH');\n displayTypes.add(displayType);\n const names = new Set<string>();\n for (const shot of await api.list(`/v1/appScreenshotSets/${set.id}/appScreenshots?limit=200`)) {\n const name = textAttribute(shot.attributes.fileName);\n const local = inventory.get(name);\n if (!local || names.has(name) || (shot.attributes.sourceFileChecksum && shot.attributes.sourceFileChecksum !== local.checksum)) throw failure(`Remote screenshot ${displayType}/${name} is extra, duplicated or differs from screenshotsDir. Match the inventories in App Store Connect before resuming; the factory will not delete publisher assets.`, 'APPLE_STATE_MISMATCH');\n names.add(name);\n }\n }\n for (const [displayType, files] of [...localInventory].sort(([a], [b]) => a.localeCompare(b))) {\n const setKey = `screenshot-set:${displayType}`;\n let set = sets.find(set => set.attributes.screenshotDisplayType === displayType);\n if (set) await reconcile(setKey, set);\n else {\n set = resource(await write(setKey, '/v1/appScreenshotSets', 'POST', { data: { type: 'appScreenshotSets', attributes: { screenshotDisplayType: displayType }, relationships: { appStoreVersionLocalization: ref('appStoreVersionLocalizations', localization.id) } } }));\n sets.push(set);\n }\n const existing = await api.list(`/v1/appScreenshotSets/${set.id}/appScreenshots?limit=200`);\n for (const [name, { bytes, checksum }] of files) {\n const key = `screenshot:${displayType}:${name}:${checksum}`;\n let shot = existing.find(item => item.attributes.fileName === name);\n if (shot?.attributes.sourceFileChecksum && shot.attributes.sourceFileChecksum !== checksum) throw failure(`Remote screenshot ${displayType}/${name} differs from the workspace. Replace it in App Store Connect or use a new filename; the factory will not delete publisher assets.`, 'APPLE_STATE_MISMATCH');\n if (shot && !shot.attributes.sourceFileChecksum && receipt().effects?.[key]?.id !== shot.id && receipt().pending?.key !== key) throw failure(`Screenshot ${displayType}/${name} has an unfinished reservation not owned by this job. Finish or remove it in App Store Connect before resuming.`, 'APPLE_WRITE_UNCERTAIN');\n if (shot) await reconcile(key, shot);\n else {\n shot = resource(await write(key, '/v1/appScreenshots', 'POST', { data: { type: 'appScreenshots', attributes: { fileName: basename(name), fileSize: bytes.length }, relationships: { appScreenshotSet: ref('appScreenshotSets', set.id) } } }));\n existing.push(shot);\n }\n const delivery = shot.attributes.assetDeliveryState?.state;\n if (delivery === 'FAILED') throw failure(`Apple rejected screenshot ${displayType}/${name}. Inspect its asset errors in App Store Connect and replace the failed reservation.`);\n if (delivery === 'COMPLETE') {\n await reconcile(`${key}:commit`, shot);\n continue;\n }\n if (delivery === 'AWAITING_UPLOAD') {\n if (!shot.attributes.uploadOperations?.length) throw failure('Apple returned no screenshot upload operations. Inspect the reservation in App Store Connect.', 'APPLE_API_ERROR');\n // Apple explicitly permits replaying asset parts until commit: https://developer.apple.com/documentation/appstoreconnectapi/uploading-assets-to-app-store-connect\n for (const [index, operation] of (shot.attributes.uploadOperations ?? []).entries()) {\n if (index < (receipt().assetParts?.[shot.id] ?? 0)) continue;\n const url = new URL(operation.url);\n if (url.protocol !== 'https:' || !url.hostname.endsWith('.apple.com') || operation.method !== 'PUT' || !Number.isInteger(operation.offset) || !Number.isInteger(operation.length) || operation.offset < 0 || operation.length <= 0 || operation.offset + operation.length > bytes.length) throw failure('Apple returned invalid screenshot upload instructions; no data was sent.', 'APPLE_API_ERROR');\n const partKey = `${key}:part:${index}`;\n const pending = receipt().pending;\n if (pending && pending.key !== partKey) throw failure(`A previous Apple write “${pending.key}” is unresolved. Resume after checking its outcome.`, 'APPLE_WRITE_UNCERTAIN');\n await persist({ pending: { key: partKey, method: 'PUT', startedAt: new Date().toISOString() } });\n let response: Response;\n try {\n const part = new Uint8Array(bytes.buffer as ArrayBuffer, bytes.byteOffset + operation.offset, operation.length);\n response = await fetch(url, { method: operation.method, redirect: 'error', headers: Object.fromEntries((operation.requestHeaders ?? []).map(header => [header.name, header.value])), body: part, signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(60000)]) : AbortSignal.timeout(60000) });\n } catch (error) {\n throw requestFailure(`Apple screenshot part upload did not complete: ${message(error)}. Resume to resend the uncommitted part.`, 'APPLE_API_ERROR');\n }\n if (!response.ok) {\n const error = requestFailure(`Apple screenshot part upload failed (HTTP ${response.status}); resume to resend the uncommitted part.`, response.status === 429 ? 'APPLE_RATE_LIMIT' : 'APPLE_API_ERROR', response.status);\n if (error.outcome === 'rejected') await persist({ pending: null });\n throw error;\n }\n try { await response.arrayBuffer(); } catch (error) {\n throw Object.assign(requestFailure(`Apple screenshot part upload response was lost (HTTP ${response.status}): ${message(error)}. Resume to resend the uncommitted part.`, 'APPLE_API_ERROR', response.status), { outcome: 'unknown' });\n }\n await persist({ pending: null, assetParts: { ...receipt().assetParts, [shot.id]: index + 1 }, lastEffect: { key: partKey, completedAt: new Date().toISOString() } });\n }\n await write(`${key}:commit`, `/v1/appScreenshots/${shot.id}`, 'PATCH', { data: { type: 'appScreenshots', id: shot.id, attributes: { uploaded: true, sourceFileChecksum: checksum } } });\n } else if (delivery === 'UPLOAD_COMPLETE') await reconcile(`${key}:commit`, shot);\n }\n }\n }\n await verifyScreenshots({ api, apple, localization, localInventory, sets });\n}\n\nasync function verifyScreenshots({ api, apple, localization, localInventory, sets = [] }: { api: AppleClient; apple: PublishingSpec; localization: Resource; localInventory?: LocalInventory; sets?: Resource[] }) {\n let complete = 0;\n if (localInventory) sets = await api.list(`/v1/appStoreVersionLocalizations/${localization.id}/appScreenshotSets?limit=200`);\n const displayTypes = new Set<string>();\n for (const set of sets) {\n const displayType = textAttribute(set.attributes.screenshotDisplayType);\n const inventory = localInventory?.get(displayType);\n if (localInventory && (!inventory || displayTypes.has(displayType))) throw failure(`Remote screenshot display set ${displayType} is extra or duplicated. Match App Store Connect to screenshotsDir before submitting; the factory will not delete publisher assets.`, 'APPLE_STATE_MISMATCH');\n displayTypes.add(displayType);\n const names = new Set<string>();\n for (const shot of await api.list(`/v1/appScreenshotSets/${set.id}/appScreenshots?limit=200`)) {\n if (inventory) {\n const name = textAttribute(shot.attributes.fileName);\n const local = inventory.get(name);\n if (!local || names.has(name) || shot.attributes.sourceFileChecksum !== local.checksum) throw failure(`Remote screenshot ${displayType}/${name} does not exactly match screenshotsDir. Match filenames and checksums in App Store Connect before submitting; the factory will not delete publisher assets.`, 'APPLE_STATE_MISMATCH');\n names.add(name);\n }\n if (shot.attributes.assetDeliveryState?.state !== 'COMPLETE') throw failure('Apple has not finished processing all screenshots. Check failed assets in App Store Connect or resume when processing finishes.', 'APPLE_PROCESSING');\n complete++;\n }\n if (inventory && names.size !== inventory.size) throw failure(`Remote screenshots for ${displayType} are missing files from screenshotsDir. Resume after the uploaded assets become visible.`, 'APPLE_PROCESSING');\n }\n if (localInventory && displayTypes.size !== localInventory.size) throw failure('Remote screenshot display sets are missing entries from screenshotsDir. Resume after the uploaded sets become visible.', 'APPLE_PROCESSING');\n if (!complete) throw failure(`No processed screenshots exist for ${apple.locale}. Set spec.apple.screenshotsDir to real screenshots grouped by Apple display type, or upload screenshots in App Store Connect.`);\n}\n\n\nexport async function pollApple({ spec, state = {}, env = process.env, signal }: AppleOptions): Promise<ApplePollResult> {\n requireDeliveryProvenance(state);\n const apple = spec?.apple;\n if (!apple?.appId || !apple.version) throw failure('Polling requires spec.apple.appId and version.');\n const api = await client(env, signal);\n const version = await findVersion(api, apple.appId, apple.version);\n if (!version) return { status: 'waiting', detail: `Version ${apple.version} is not visible in App Store Connect.` };\n if (state.versionId && version.id !== state.versionId) throw failure('The App Store version differs from the saved receipt. Inspect the app record before resuming.', 'APPLE_STATE_MISMATCH');\n const status = versionState(version);\n if (approved.has(status)) {\n await requireSelectedBuild(api, version.id, state.buildId);\n const distributionReady = ['READY_FOR_SALE', 'READY_FOR_DISTRIBUTION'].includes(status ?? '');\n let available = false;\n if (distributionReady && apple.storefrontCountry) {\n if (!/^[A-Za-z]{2}$/.test(apple.storefrontCountry)) throw failure('apple.storefrontCountry must be a two-letter country code.');\n const url = new URL('https://itunes.apple.com/lookup');\n url.search = new URLSearchParams({ id: apple.appId, country: apple.storefrontCountry }).toString();\n let response: Response;\n try {\n response = await fetch(url, { redirect: 'error', signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(30000)]) : AbortSignal.timeout(30000) });\n } catch (error) {\n throw requestFailure(`Public App Store lookup did not complete: ${message(error)}. Resume to check publication.`, 'APPLE_API_ERROR', null, true);\n }\n if (!response.ok) throw requestFailure(`Public App Store lookup failed (HTTP ${response.status}); publication has not been proven.`, 'APPLE_API_ERROR', response.status);\n let text: string;\n try { text = await response.text(); } catch (error) {\n throw requestFailure(`Public App Store lookup response was lost: ${message(error)}. Resume to check publication.`, 'APPLE_API_ERROR', response.status, true);\n }\n let data: unknown;\n try { data = JSON.parse(text); } catch {\n throw failure('Public App Store lookup returned non-JSON data; publication has not been proven.', 'APPLE_API_ERROR');\n }\n const parsed = ListingSchema.safeParse(data);\n if (!parsed.success) throw failure(`Public App Store lookup returned invalid data: ${parsed.error.message}`, 'APPLE_API_ERROR');\n available = parsed.data.results.some(item => item.bundleId === apple.bundleId && item.version === apple.version);\n }\n return { status: 'approved', distributionReady, available, detail: `Apple version state: ${status}. Approval does not imply public availability; lookup of the exact bundle/version ${available ? 'confirmed the configured storefront' : 'has not confirmed the configured storefront'}.` };\n }\n if (rejected.has(status)) return { status: 'rejected', detail: `Apple version state: ${status}. Read App Review messages in App Store Connect before changing or resubmitting the app.` };\n return { status: 'waiting', detail: `Apple version state: ${status}.` };\n}\n"],"mappings":"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"}
@@ -1,103 +0,0 @@
1
- ---
2
- name: apple-app-factory
3
- description: Build and locally package a Flutter iOS app from explicit product requirements using the embedded apple-app-factory harness. Use for app-factory init, enqueue, native research/build/independent review, external verification, packaging, or resuming a persisted job. Not a coding-agent launcher or an automatic App Store publisher.
4
- ---
5
-
6
- # Apple App Factory
7
-
8
- Use your current host's model, context, authentication, filesystem, browser and native delegation tools. The installed `app-factory` CLI owns requirements, durable turns, verification, fingerprints and local packaging. Never start another coding-agent CLI, including Hermes, as a subprocess to perform a phase. There is no factory chat UI, model credential setup, daemon, or background agent loop.
9
-
10
- This skill is advisory to the host. Factory code gates factory-owned transitions, not arbitrary host edits or shell commands. It does not sandbox your host, enforce reviewer identity, guarantee Apple approval, or verify that a policy citation's contents are true. Preserve host permissions and the user's scope.
11
-
12
- ## 1. Establish the control project
13
-
14
- 1. Use the project where the user installed/invoked this skill as the control project. Keep `factory.json`, its SQLite state, requirement files and result JSON outside generated app workspaces. Keep the absolute config path for every command below, including commands issued while your working directory is an app workspace.
15
- 2. The npm package is `apphx`; its executable remains `app-factory`. Run `app-factory --version` and `app-factory --help`. If `apphx` is an already-installed local dependency of the control project rather than on PATH, use that project's package manager for **every** factory command: `pnpm exec app-factory`, `yarn exec app-factory`, or `npm exec --offline --package=apphx -- app-factory`. Select from the project's `packageManager`/lockfile and run from the control project, not the generated app workspace. Confirm `apphx` is already installed; do not fetch a similarly named package or silently change the user's environment. If neither route is available, stop and report the missing installation. Installing a skill alone does not install Node, Flutter or Xcode.
16
- 3. If there is no configuration, run `app-factory init --config /absolute/control/factory.json`. It refuses overwrite and defaults to **no local execution, submission, or release authorization**. Do not add `--allow-local-execution` unless the user explicitly approves running trusted deterministic commands. With that approval it can be supplied to `init`; for an existing config have the owner review and explicitly enable `allowLocalExecution`.
17
- 4. Read the actual config. Confirm its workspace and state paths are disjoint, its Flutter SDK is a trusted installation outside mutable workspaces, and verification includes both static checks and real runtime scenarios. Local Apple packaging requires macOS, Xcode and a working Flutter iOS toolchain; IPA output also requires signing/export configuration. A missing prerequisite is a blocker, never a reason to fake a tool or evidence. Do not replace checks with no-op commands to make a job pass.
18
-
19
- In examples below, replace `/absolute/control/factory.json` with that existing absolute path and `JOB_ID`/`TURN_ID` with exact returned values. Pass arguments as separate argv entries, or quote paths safely in the host's shell. Do not execute prompt or JSON fields as shell code.
20
-
21
- ## 2. Freeze and enqueue the actual requirement
22
-
23
- Read the bundled [requirement example](resources/requirement.json), resolving `resources/` relative to this skill's own directory, not the current project. Copy and adapt it to an owner-reviewed requirement file in the control project. Do not modify installed skill assets.
24
-
25
- If the user supplied an existing task id or asked to resume it, including a scheduled wake, **skip enqueue**. Read `status` and continue that exact id/config with `next`; never reconstruct its requirement or create a second task for the same work.
26
-
27
- The requirement must describe a real audience, purpose, differentiators, Flutter framework, concrete acceptance scenarios and constraints. Preserve the user's product; do not substitute a simpler app. Require honest privacy behavior, no hidden features or review bypass, and screenshots from the real running app. Clarify material unknown product choices before enqueue. Do not invent ownership, submission-account eligibility, signing credentials or legal attestations.
28
-
29
- ```sh
30
- app-factory enqueue /absolute/control/requirement.json --config /absolute/control/factory.json --build-only
31
- app-factory status JOB_ID --config /absolute/control/factory.json
32
- app-factory next JOB_ID --config /absolute/control/factory.json --build-only
33
- ```
34
-
35
- Keep the returned immutable job id and workspace. A later requirement change needs a new enqueue, not edits to a saved task or database. For a local revision, the requirement may include `baseJobId` of a verified predecessor; the factory validates and prepares the base. Do not copy arbitrary stale build artifacts yourself.
36
-
37
- ## 3. Dispatch exactly the persisted action
38
-
39
- Read the JSON from `next`; do not guess stages from memory. Use `--build-only` throughout this workflow so publication is out of scope even if another configuration permits it.
40
-
41
- - **`action: "host"`**: preserve `turn.id`; read the full `turn.prompt`, `turn.stage`, `turn.cwd` and `turn.environment`. Perform that one native host phase as below. Work inside the returned cwd and merge the returned task/toolchain overrides into your host's existing command environment; do not replace it. Configured environment values are intentionally not printed in the response. This is not a host-wide security boundary; never copy publisher secrets into task commands. Only the CLI completion call advances the task. Repeated `next` resumes the same active turn without spending a second turn, unless its task deadline has expired.
42
- - **`action: "step"`**: run `app-factory step JOB_ID --config /absolute/control/factory.json --build-only` once, inspect its exit status and returned job, then ask `next` again if successful. Only deterministic verify/package stages should be needed here. `step` cannot perform research, build or review for you. Never label a host verdict as external verification.
43
- - **`action: "wait"`**: inspect the job's status, reason, error and due time. Report the exact blocker or scheduled time; do not busy-loop, automatically grant permission, or retry a failed command until it happens to pass. Resume with `next` after the prerequisite/due time is satisfied and the user intends to continue.
44
- - **`action: "done"`**: inspect the persisted outcome. `built` plus a recorded local artifact is successful local packaging. Blocked/failed/rejected outcomes are not success merely because no action remains. Report the artifact kind/path/digest and evidence, or the exact unmet requirement.
45
-
46
- For a scheduled wake, the host scheduler owns timing and non-overlap; do not create a factory daemon or a second schedule. Check `status` first: if it is `running` and the prior execution's completion is unconfirmed, stop and ask the owner rather than taking over its token. Respect the requested bound (for example one persisted action), then report state and exit. A `wait` or `done` result ends this wake; it does not authorize changing permissions, increasing budgets or polling indefinitely. A fresh scheduled session may review only if it did not implement the change and genuinely inspects the saved source/evidence. Missing independent review or human authorization pauses the work; never manufacture approval to keep a schedule moving.
47
-
48
- To stop an active host phase without completing it:
49
-
50
- ```sh
51
- app-factory abandon JOB_ID TURN_ID --config /absolute/control/factory.json --build-only
52
- ```
53
-
54
- This explicitly abandons the current token; it does not refund the consumed turn. Resume later with `next`. Never reuse an abandoned, stale or already completed token. If a completion's outcome is uncertain, inspect `status`/`next` rather than replaying it blindly. Do not edit SQLite or increase budgets to bypass a rejection. Use `app-factory retry --help` and the stopped task's reported recovery instructions only after fixing the actual cause with owner approval.
55
-
56
- ## 4. Native research
57
-
58
- Read the immutable requirement and all context in the research prompt. Use your host's web/browsing tools to read the current official [Apple App Review Guidelines](https://developer.apple.com/app-store/review/guidelines/). Evaluate **2.1, 2.3.1, 2.5.19, 4.2, 4.2.6, 4.3 and 5.1.1**, meaningful distinctness against the supplied portfolio, offline persistence/backup, privacy and accessibility. Account/content ownership for 4.2.6 cannot be attested by the model; surface unknowns.
59
-
60
- Use [research-result.json](resources/research-result.json) for the exact JSON shape, not a pre-approved verdict. Replace its unassessed content with sourced findings. Required fields: `viable` boolean, `policySources` entries with exact `rule` and official HTTPS `url` for every listed rule, `distinctness` text, and nonempty `plan`; `risks` is optional. If not viable, return false and explain the reasons rather than concealing them.
61
-
62
- Save result JSON **outside the app workspace**, for example `/absolute/control/results/JOB_ID-research.json`, then:
63
-
64
- ```sh
65
- app-factory complete JOB_ID TURN_ID /absolute/control/results/JOB_ID-research.json --config /absolute/control/factory.json --build-only
66
- app-factory next JOB_ID --config /absolute/control/factory.json --build-only
67
- ```
68
-
69
- ## 5. Native implementation
70
-
71
- Perform the returned build prompt with your own native edit, terminal and design tools in `turn.cwd`. Implement the full requirement as a real Flutter iOS project with `pubspec.yaml`, complete workflows, persistence, privacy UI and appropriate tests. For unfamiliar APIs, use real official references. Never use mock runtime evidence, placeholder features, screenshots of nonexistent UI, or a replacement product. Do not weaken configured verification or change frozen requirements/state.
72
-
73
- Native delegation may handle independent file boundaries. The implementation owner integrates before any external verification. Complete only after the source exists and the requested implementation is ready:
74
-
75
- ```sh
76
- app-factory complete JOB_ID TURN_ID --config /absolute/control/factory.json --build-only
77
- app-factory next JOB_ID --config /absolute/control/factory.json --build-only
78
- ```
79
-
80
- No result JSON is required for build. Build completion only advances to deterministic verification; it is not approval or a package.
81
-
82
- ## 6. External verification, then independent review
83
-
84
- The next deterministic `step` executes the configured prerequisite/static/runtime checks and records real results and source/dependency fingerprints. Read logs and evidence from the returned job or `app-factory events JOB_ID --config /absolute/control/factory.json`. A compilation-only success is not runtime acceptance. Never synthesize receipts or report unavailable iOS execution as passed. Fix the concrete failure through the factory's stopped-task/retry path; do not directly move its stage.
85
-
86
- When `next` returns a **review** turn, use a **fresh native reviewer context** that did not implement the change. Give it the exact review prompt, requirement, workspace and external evidence. Have it independently inspect every acceptance scenario, code and real evidence, with **no source/dependency/screenshot edits**. Evidence-producing commands that mutate the verified source invalidate approval. An implementation agent's second self-review is not independent.
87
-
88
- Use the host's native subagent/reviewer facility if present. If unavailable (including stock Pi), pause and ask the user to open a separate fresh host session for review, supply the job id/config/active turn, and return its JSON verdict. Do not launch another coding-agent process or claim independence that did not occur. The separate reviewer may complete the current token itself, or return the result to the controlling session; exactly one session completes it.
89
-
90
- Use [review-result.json](resources/review-result.json) for the strict shape: `approved` boolean, `findings` array, and `acceptanceEvidence` array. Every frozen acceptance string must appear **exactly** as `requirement`, with nonempty concrete `evidence` identifying files/symbols and observed commands/scenarios. Approve only if all acceptance criteria are supported and there are no blocking findings. The example is deliberately a rejection, not reusable evidence. Save the verdict outside the app workspace:
91
-
92
- ```sh
93
- app-factory complete JOB_ID TURN_ID /absolute/control/results/JOB_ID-review.json --config /absolute/control/factory.json --build-only
94
- app-factory next JOB_ID --config /absolute/control/factory.json --build-only
95
- ```
96
-
97
- The factory rejects incomplete evidence, rejected verdicts and changed fingerprints. It cannot prove which model/person authored a verdict; accurately report the review method and limitations.
98
-
99
- ## 7. Package locally and hand off
100
-
101
- Run the returned package `step` once with `--build-only`, then inspect `status` and `next`. Packaging produces a local simulator build or, when explicitly configured with signing prerequisites, an IPA. Report only recorded artifact paths/digests and exercised checks, including any remaining environmental limitation. Local packaging is not App Store submission, approval, TestFlight availability or release.
102
-
103
- Do not call `authorize`, upload with other tools, enable `allowSubmit`/`allowRelease`, or run publication/monitoring on the strength of this skill. Publication requires a separate explicit owner request, the existing factory permission/receipt gates, truthful account ownership, signing and Apple prerequisites. This workflow ends at the local artifact or an accurately reported blocker.
@@ -1,21 +0,0 @@
1
- {
2
- "viable": false,
3
- "policySources": [
4
- { "rule": "2.1", "url": "https://developer.apple.com/app-store/review/guidelines/#app-completeness" },
5
- { "rule": "2.3.1", "url": "https://developer.apple.com/app-store/review/guidelines/#accurate-metadata" },
6
- { "rule": "2.5.19", "url": "https://developer.apple.com/app-store/review/guidelines/#software-requirements" },
7
- { "rule": "4.2", "url": "https://developer.apple.com/app-store/review/guidelines/#minimum-functionality" },
8
- { "rule": "4.2.6", "url": "https://developer.apple.com/app-store/review/guidelines/#minimum-functionality" },
9
- { "rule": "4.3", "url": "https://developer.apple.com/app-store/review/guidelines/#spam" },
10
- { "rule": "5.1.1", "url": "https://developer.apple.com/app-store/review/guidelines/#data-collection-and-storage" }
11
- ],
12
- "distinctness": "Unassessed example: evaluate the owner's actual requirements against the supplied portfolio and current official policies before returning a real verdict.",
13
- "risks": [
14
- "The current policy contents have not been researched by this example.",
15
- "The content owner and submitting account's eligibility under 4.2.6 are unknown; a model must not invent an attestation."
16
- ],
17
- "plan": [
18
- "Read the current official policy sections and assess viability, ownership, distinct utility, privacy and runtime acceptance for the actual product.",
19
- "If viable, return a concrete product-specific implementation and verification plan; otherwise preserve viable=false and report the specific blockers."
20
- ]
21
- }
@@ -1,7 +0,0 @@
1
- {
2
- "approved": false,
3
- "findings": [
4
- "This is a result-shape example, not a completed review. A fresh independent reviewer must inspect the real implementation and external evidence."
5
- ],
6
- "acceptanceEvidence": []
7
- }
File without changes