"Not expiry. I think it happens when the screen locks."
What an Unattended Build Leans On
A pipeline that archives and uploads while its owner is away depends on three things it cannot see from its own log. It signs with a private key in the login keychain, which an ssh session cannot use (the previous part's one-shot GUI-domain job is the bridge). It lets xcodebuild -allowProvisioningUpdates talk to Apple's developer services to create and update profiles, which xcodebuild -help says needs either an account added in Xcode's Accounts settings or an App Store Connect API key passed as -authenticationKeyPath, -authenticationKeyID and -authenticationKeyIssuerID. And for an upload, it uses that same authentication to reach App Store Connect.
The Error That Looked Like an Expired Session
An upload died at the very end, after tests, archive and gates had all passed, with a bare error: exportArchive Failed to Use Accounts. It reads exactly like an expired Apple ID session, so the first diagnosis was to sign out of Xcode and back in. That seemed to work, and three uploads succeeded in a row. The next failure arrived precisely when the owner left and switched the display off, and he made the call: not expiry, a locked screen. With the session locked, the keychain refused Xcode's account session, and each failed run had spent eight minutes getting there.
Two fixes followed. A pipeline without an API key now checks the screen before building: CoreGraphics' CGSessionCopyCurrentDictionary() carries CGSSessionScreenIsLocked while the session is locked and omits it while unlocked, calibrated against a real locked session. And the lasting fix removes the dependency: a team API key from App Store Connect, whose private key (AuthKey_<id>.p8) Apple lets you download once, kept outside every repository with its key id and issuer id beside it. With it, xcodebuild authenticates without the Accounts session at all. Give the key the Admin role: a family app measured that a key with the App Manager role may neither create the cloud-managed distribution certificate nor regenerate the managed profiles that automatic signing asks for.
Refuse a Half-Dropped Key
The key reader distinguishes three states. No config means the Mac uses its Xcode session, as before. A complete config prints six flags. A config that exists but is incomplete (a missing .p8, an issuer id that is not a UUID) is a hard failure, because a half-dropped key would otherwise look exactly like no key and quietly upload through the very session it was meant to replace.
One zsh detail decides whether the flags reach xcodebuild intact. The quoted capture ("${(@f)$(…)}") turns empty output into one empty element, so xcodebuild receives an empty-string argument. The unquoted (${(f)"$(…)"}) gives an empty array for no output and still keeps a path with a space as one word. Both were measured before this lesson used them.