You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
asc iris iap-submissions delete --submission-id <id> — iris-side dequeue of an IAP submission (DELETE /iris/v1/inAppPurchaseSubmissions/{id}). Iris-queued submissions don't round-trip through the public-SDK delete; they can only be removed via this iris-cookie-authed path. New IrisClient.delete, new IrisInAppPurchaseSubmissionRepository.deleteSubmission(session:submissionId:). REST equivalent: DELETE /api/v1/iris/iap-submissions/:submissionId on IrisIAPSubmissionsController. removeFromNextVersion affordance now resolves end-to-end through iris (CLI: asc iris iap-submissions delete --submission-id <id>; REST: DELETE /api/v1/iris/iap-submissions/<id>). RESTPathResolver.resourcePath now converts spaces in segment names to slashes so multi-word commands like iris iap-submissions produce clean URL segments. Removed the short-lived public-SDK alias POST /api/v1/iap/:iapId/unsubmit (incorrect — public DELETE doesn't accept iris-queued submissions).
removeFromNextVersion affordance on queued IAPs — when an IAP is in READY_TO_SUBMIT and Apple's iris listing reports submitWithNextAppStoreVersion: true (queued to ride along with the next app version), InAppPurchase.structuredAffordances surfaces removeFromNextVersion → asc iap unsubmit --submission-id <iapId> and suppresses the submit affordance (mutually exclusive — Apple rejects re-submits on already-queued IAPs). The dequeue uses the existing public-SDK DELETE /v1/inAppPurchaseSubmissions/{id} (Apple's iris flow keys the submission resource by parent IAP id, so --submission-id <iapId> works). Underpinned by a new best-effort iris enrichment: IrisSDKInAppPurchaseStateRepository calls GET /iris/v1/apps/:appId/inAppPurchasesV2?fields[inAppPurchases]=submitWithNextAppStoreVersion&filter[state]=READY_TO_SUBMIT, mapping each IAP to its queued bit. SDKInAppPurchaseRepository.listInAppPurchases accepts an optional irisFlagsProvider closure; the factory wires it from IrisCookieProvider + IrisSDKInAppPurchaseStateRepository. CI scripts using API-key auth keep their existing JSON output (flag stays false, no removeFromNextVersion affordance). New InAppPurchase.submitWithNextAppStoreVersion: Bool field, encoded only when true to avoid snapshot churn. New IrisInAppPurchaseStateRepository@Mockable Domain protocol.
Changed
InAppPurchase submission affordances reorganized into iris-queue family vs. public-SDK direct submit. Two inverse pairs, all gated on state == .readyToSubmit:
addToNextVersion (NEW) → asc iris iap-submissions create --iap-id <id> — queues the IAP to ride along with the next App Store version submission. Always available for ready, not-yet-queued IAPs.
removeFromNextVersion → asc iap unsubmit --submission-id <iapId> — dequeues. Mutually exclusive with the others; emitted only when iris listing reports submitWithNextAppStoreVersion: true.
submit → asc iap submit --iap-id <id> — public-SDK direct submit (standalone review). Now emitted only when isFirstTimeSubmission == false (Apple rejects the direct path for the first IAP for an app).
Established-app ready IAPs see bothsubmit and addToNextVersion; agent picks based on release strategy.
Replaces the previous behavior where submit quietly auto-dispatched between iris and public SDK paths — keys are now explicit about what each call does. New InAppPurchaseState.hasBeenApproved semantic boolean. New iris iap-submissions REST route registered with the path resolver so addToNextVersion_links resolve to /api/v1/iris/iap/<id>/submissions.
Added
asc iris iap-submissions create --iap-id <id> — IAP submission via the iris private API — closes the parity gap with the public SDK's POST /v1/inAppPurchaseSubmissions, which has no attributes field and therefore can't carry submitWithNextAppStoreVersion. The new command posts to POST /iris/v1/inAppPurchaseSubmissions with that attribute set, which is required for first-time IAP submissions (Apple binds the first IAP to the next App Store version). Defaults to --with-next-version; pass --no-with-next-version to opt out. Lives under asc iris … because it needs iris cookies (either browser cookies or a session from asc iris auth login). Surfaced via IrisStatus.affordances.submitIAP so asc iris status advertises the path when authenticated. Existing asc iap submit stays untouched — CI scripts using key-auth keep working unchanged. See docs/features/iap-subscriptions/submission-iris-parity.md.
REST: POST /api/v1/iris/iap/:iapId/submissions — body {"submitWithNextAppStoreVersion": true} (default true); returns the submission resource with _links.viewIAP pointing back at the public IAP endpoint.
Fixed
iris 2FA verify-code no longer 401s with a valid code — IdmsaAPIClient.applyHeaders was sending X-Apple-OAuth-Client-Id, X-Apple-OAuth-Redirect-URI, X-Apple-OAuth-Response-Mode, X-Apple-OAuth-Response-Type, Origin, and Referer on signin/init and signin/complete. None of XcodesOrg/XcodesApp, XcodesOrg/XcodesLoginKit, or the rorkai/App-Store-Connect-CLI Go reference send those — they taint the SRP session so the post-409 GET /appleauth/auth returns 401, rotates scnt, and the subsequent POST /verify/trusteddevice/securitycode is rejected as out-of-sequence. Header set is now narrowed to Accept, Content-Type, X-Requested-With, X-Apple-Widget-Key, scnt, X-Apple-ID-Session-Id (+ X-Apple-HC on signin/complete). signinComplete also flips to ?isRememberMeEnabled=false with body rememberMe: false to match the same references — true puts Apple in the "trust this browser" path, which mismatches a CLI session.
Added
asc iris auth login / verify-code / logout — Apple ID SRP login for the iris private API — until now iris features (asc iris apps list, asc iris status) only worked when the user had logged into App Store Connect in their browser; we'd borrow cookies from there. Headless CI had no path. The new command performs a full Apple SRP-6a handshake against idmsa.apple.com, handles 2FA (trusted-device push or phone code), then persists the resulting session to ~/.asc/iris/session.json (0600 perms). New CompositeIrisCookieProvider chains SRP-stored cookies before browser cookies, so any existing iris command immediately picks up the SRP session without code changes elsewhere. See docs/features/iris/iris-srp-login.md.
asc iris auth login --apple-id user@example.com — prompts for password on stdin, runs SRP, persists session on success or pending-2FA state on 409.
asc iris auth verify-code 123456 — submits the 2FA code, calls 2sv/trust, fetches olympus/v1/session for team metadata, persists the full session.
asc iris auth logout — deletes the persisted session.
ASC_IRIS_DEBUG=1 — dumps every idmsa request/response to stderr with a/m1/m2 redacted, so failures self-capture safely-shareable test data.
Built on adam-fowler/swift-srp (Apache 2.0) for RFC 5054 group-2048 constants, BigNum, and key generation. Apple's PBKDF2-derived x is layered on top in AppleSRPClient. PBKDF2-HMAC-SHA256 implementation cross-checked against RFC 7914 §11 vectors.
Caveat: while every layer is unit-tested with mocked HTTP and synthesized vectors, real-world correctness against Apple's specific M1 shape gets validated only on the first real login attempt. If Apple's protocol shifts, expect churn here.