mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7c686d5cf | ||
|
|
314664ecd6 | ||
|
|
11f89b1345 | ||
|
|
2481956c11 | ||
|
|
8804e121b6 | ||
|
|
7b3de48dbd |
No files matched your search
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
id: 2026-08-30-ios-extension-version-verification
|
||||||
|
date: 2026-08-30
|
||||||
|
status: promoted
|
||||||
|
scope: iOS release artifact verification
|
||||||
|
evidence: build 45 Xcode archive warning plus direct PlistBuddy inspection of the exported IPA
|
||||||
|
destination: .codex/skills/release-mobile/SKILL.md
|
||||||
|
review_after: 2027-02-28
|
||||||
|
---
|
||||||
|
|
||||||
|
## Symptom
|
||||||
|
|
||||||
|
The signed iOS build logged that the widget extension build number 44 did not
|
||||||
|
match the containing app build number 45, even though export completed.
|
||||||
|
|
||||||
|
## Reproduction
|
||||||
|
|
||||||
|
Build iOS version 1.0.6 with EAS auto-increment from build 44 to 45 and retain the
|
||||||
|
archive log. Extract the resulting IPA with `ditto`, then read the containing app
|
||||||
|
and every packaged extension `Info.plist` with `PlistBuddy`.
|
||||||
|
|
||||||
|
## Cause
|
||||||
|
|
||||||
|
The archive warning described an intermediate state and was not authoritative
|
||||||
|
for the exported package. Direct IPA inspection showed both the app and
|
||||||
|
`LiveDrawWidget.appex` at version 1.0.6 build 45.
|
||||||
|
|
||||||
|
## Remediation
|
||||||
|
|
||||||
|
For every iOS release, inspect version and build values in the exported app and
|
||||||
|
all packaged extensions. Reject or rebuild only when the final IPA values differ;
|
||||||
|
do not accept or reject a release from archive warnings alone.
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
`PlistBuddy` read `CFBundleShortVersionString` 1.0.6 and `CFBundleVersion` 45 from
|
||||||
|
both packaged plists. `codesign --verify --deep --strict` passed for the app, and
|
||||||
|
the verified IPA SHA-256 was
|
||||||
|
`9d4779bddac4647911a3a38e4ee37cf794c2b8691e0746a041b629c62b308e7f`.
|
||||||
@@ -54,5 +54,9 @@ additional TestFlight distribution requires another fresh authorization.
|
|||||||
|
|
||||||
Preserve platform signing and local EAS versioning. After a build, verify that
|
Preserve platform signing and local EAS versioning. After a build, verify that
|
||||||
tracked changes are limited to the expected version metadata, then independently
|
tracked changes are limited to the expected version metadata, then independently
|
||||||
read the artifact version and signature. Report the artifact, version/build
|
read the artifact version and signature. For an iOS IPA, inspect every packaged
|
||||||
number, upload result when authorized, and store read-back state.
|
app extension as well as the containing app and require matching
|
||||||
|
`CFBundleShortVersionString` and `CFBundleVersion` values. Treat Xcode archive
|
||||||
|
warnings as diagnostic evidence, not the final artifact state: decide whether to
|
||||||
|
reject or rebuild only after reading the exported IPA itself. Report the artifact,
|
||||||
|
version/build number, upload result when authorized, and store read-back state.
|
||||||
@@ -36,6 +36,7 @@ MCP service in one npm/Turborepo workspace.
|
|||||||
mechanical one-line edit whose coordination cost exceeds the work.
|
mechanical one-line edit whose coordination cost exceeds the work.
|
||||||
11. Use high-effort reviewers only for the risk triggers in
|
11. Use high-effort reviewers only for the risk triggers in
|
||||||
`docs/agents/routing.md`.
|
`docs/agents/routing.md`.
|
||||||
|
12. Agents must not use em dash characters in text they add to this repository.
|
||||||
|
|
||||||
## Repository map
|
## Repository map
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"group.com.sauci.app"
|
"group.com.sauci.app"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"buildNumber": "44",
|
"buildNumber": "45",
|
||||||
"usesAppleSignIn": true,
|
"usesAppleSignIn": true,
|
||||||
"googleServicesFile": "./GoogleService-Info.plist",
|
"googleServicesFile": "./GoogleService-Info.plist",
|
||||||
"infoPlist": {
|
"infoPlist": {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>44</string>
|
<string>45</string>
|
||||||
<key>GOOGLE_ANALYTICS_INAPURCHASE_COLLECTION_ENABLED</key>
|
<key>GOOGLE_ANALYTICS_INAPURCHASE_COLLECTION_ENABLED</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<string>com.apple.widgetkit-extension</string>
|
<string>com.apple.widgetkit-extension</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>44</string>
|
<string>45</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0.6</string>
|
<string>1.0.6</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ for (const file of allFiles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!scoped) {
|
if (!scoped) {
|
||||||
|
const agentsFile = path.join(root, 'AGENTS.md');
|
||||||
|
const agents = await readFile(agentsFile, 'utf8');
|
||||||
|
const noEmDashRule = 'Agents must not use em dash characters in text they add to this repository.';
|
||||||
|
if (!agents.includes(noEmDashRule)) {
|
||||||
|
fail(agentsFile, 'agent writing rule against em dash characters is missing', `restore: ${noEmDashRule}`);
|
||||||
|
}
|
||||||
|
|
||||||
const packageJson = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
|
const packageJson = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
|
||||||
const codexConfigFile = path.join(root, '.codex', 'config.toml');
|
const codexConfigFile = path.join(root, '.codex', 'config.toml');
|
||||||
const codexConfig = await readFile(codexConfigFile, 'utf8');
|
const codexConfig = await readFile(codexConfigFile, 'utf8');
|
||||||
|
|||||||
Reference in new issue
Block a user