Skip to content

Certificate wizard: register Macs, report the right slot, check the profile signs this app - #5815

Merged
shai-almog merged 2 commits into
masterfrom
fix/cert-wizard-5773-5793
Sep 14, 2026
Merged

Certificate wizard: register Macs, report the right slot, check the profile signs this app#5815
shai-almog merged 2 commits into
masterfrom
fix/cert-wizard-5773-5793

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Fixes #5773 and the client half of #5793. Four independent defects plus a preflight gap.

1. A Mac cannot be registered (#5773)

CloudSigningService.registerDevice hardcoded "IOS". The signing service has always accepted MAC_OS — only the dialog never asked. So the wizard offered a MAC_APP_DEVELOPMENT profile type that nothing could satisfy: isUsableDevice correctly hides an iPhone from a Mac profile's picker, and no Mac could be registered to put in it. A profile type you can select and never create.

The registration dialog now picks the platform, and the UDID hint follows it — a Mac is registered by its hardware UUID, not by an iPhone's 25-character identifier.

The reporter's screenshot is the iOS profile device picker, where hiding Macs is correct. The bug is the missing registration path, not that screen.

2. The overview announced readiness it did not have (#5773)

Both cards read row zero of an unfiltered list:

state.certificates.isEmpty() ? "-" : state.certificates.get(0).displayName()
state.profiles.isEmpty()     ? "-" : state.profiles.get(0).name()

So an account holding a Mac certificate and a development profile was told "Apple distribution certificate: Ready — dtest11 MAC APP DISTRIBUTION" and "App Store profile: Ready — dtest11 Development". Neither slot was filled.

To be fair to the code: the wizard was never going to use either for an iOS build. WizardDecisions.certificateTypeSatisfies has always been strict and needed no change. But that panel is why the reporter concluded it was signing iOS builds with Mac App Store assets, and a readiness panel that reports readiness it does not have is worse than no panel at all.

The selection moved to WizardDecisions, where it is testable without a display. The profile card now requires the type and that Apple has not marked the profile INVALID — "Ready" for a profile the next build cannot sign with is the same false assurance.

3. A downloaded "Apple Development" certificate went to the release slot

afterCertificateDownload tested "IOS_DEVELOPMENT".equals(...) alone, while every other decision in the class goes through isDevelopmentCertificate, which also counts Apple's generic DEVELOPMENT type. A manual download of an Apple Development certificate therefore offered to install into codename1.ios.release.certificate, overwriting the unqualified key with it.

4. "Sync with Apple" calls both halves (#5793)

It called the certificate reconcile alone — and there was no profile reconcile to call. Companion PR: codenameone/BuildCloud#147, which explains why the profile list could never come into step with Apple.

A 404/405 from the new route is tolerated, so a wizard newer than the deployed service still syncs certificates instead of failing outright. Any other status is reported.

Also: the preflight never checked the app's own profile

IOSProvisioningPreflight applies profileCoversBundleId to every app extension and never to the app itself, so the app's profile was checked only for readability, expiry and distribution method. A profile issued for a different App ID passed preflight and failed minutes later on the build server with:

Provisioning profile "dtest11 STORE" doesn't match the entitlements file's values for the application-identifier and keychain-access-groups entitlements

Both of those entitlements are $(AppIdentifierPrefix)$(CFBundleIdentifier) — which is to say both of them are that comparison, spelled by Xcode after the upload. Both reporters spent a cloud build each to be told it, and every fact needed was on disk beforehand.

It deliberately does not catch the same bundle id under a different team prefix: nothing in codenameone_settings.properties states the team, so that half stays a server-side failure. There is a test asserting the limit rather than leaving it implied.

(Incidentally: #5793's own diagnosis of this error — the multicast entitlement — is wrong. That would name com.apple.developer.networking.multicast.)

Test infrastructure

The wizard's surefire skipTests was hardcoded true, which -DskipTests=false cannot reach, so its 78 existing tests could not be run here or anywhere. It is now the same opt-in property scripts/settings/common uses, for the same reason, with the same default:

cd scripts/certificatewizard
mvn -pl common test -Dcn1.certificatewizard.skipTests=false

Verification

  • Certificate wizard: 81 tests pass (78 existing, first run of any of them + 3 new).
  • IOSProvisioningPreflightTest: 45 pass (39 existing + 6 new). A/B probe run — stubbing out the new check makes profileForAnotherAppIsRefused fail, so it does bite.
  • SpotBugs on codenameone-maven-plugin: 0 findings.
  • Repo gates green: control characters (11386 files), copyright headers, package-info, since-tags, cast-semantics, build-hint catalog.

Ordering

codenameone/BuildCloud#147 should be deployed first. Nothing here breaks without it — the sync degrades to today's behaviour — but the profile half stays inert until that route exists.

🤖 Generated with Claude Code

…rofile signs this app

Issues #5773 and #5793, whose reports overlap. Four defects, each independent.

**A Mac cannot be registered.** CloudSigningService.registerDevice hardcoded
"IOS". The service has always accepted MAC_OS -- only the dialog never asked --
so a wizard that offers MAC_APP_DEVELOPMENT offered a profile type nothing could
satisfy: isUsableDevice correctly hides an iPhone from a Mac profile's picker,
and no Mac could be put in it. The registration dialog now picks the platform,
and the UDID hint follows it, because a Mac is registered by its hardware UUID
rather than by an iPhone's 25-character identifier.

**The overview announced readiness it did not have.** Both cards read row zero of
an unfiltered list, so an account holding a Mac certificate and a development
profile was told "Apple distribution certificate: Ready -- dtest11 MAC APP
DISTRIBUTION" and "App Store profile: Ready -- dtest11 Development". Neither slot
was filled. The wizard was never going to USE either for an iOS build --
certificateTypeSatisfies has always been strict, and that part needed no change
-- but the panel is why the reporter concluded it was signing iOS builds with Mac
App Store assets, and a readiness panel that lies is worse than none. The
selection moved to WizardDecisions, where it can be tested without a display, and
the profile card now requires the type AND that Apple has not marked it INVALID.

**A downloaded "Apple Development" certificate was offered to the release slot.**
afterCertificateDownload tested certificateType against IOS_DEVELOPMENT alone,
while every other decision in the class goes through isDevelopmentCertificate,
which also counts Apple's generic DEVELOPMENT type. So a manual download of an
Apple Development certificate would install into
codename1.ios.release.certificate and overwrite the unqualified key with it.

**"Sync with Apple" could not sync profiles at all**, because the signing service
had no endpoint to sync them with -- the companion BuildCloud change adds
POST /profiles/reconcile and explains why. The wizard now calls both halves. A
404/405 from the profile half is tolerated so that a wizard newer than the
deployed service still syncs certificates instead of failing outright; any other
status is reported.

Also here: IOSProvisioningPreflight was applying profileCoversBundleId to every
app EXTENSION and never to the app itself, so the app's own profile was checked
only for readability, expiry and distribution method. A profile issued for a
different App ID passed preflight and failed minutes later on the build server
with "Provisioning profile ... doesn't match the entitlements file's values for
the application-identifier and keychain-access-groups entitlements" -- both of
which are $(AppIdentifierPrefix)$(CFBundleIdentifier), which is to say both of
them are that comparison, spelled by Xcode after the upload. Both reporters spent
a cloud build each to be told it. What it deliberately does not catch is the same
bundle id under a different TEAM prefix: nothing in codenameone_settings.properties
states the team, so that half stays a server-side failure, and there is a test
asserting the limit rather than leaving it implied.

The wizard's surefire skipTests was hardcoded true, which -DskipTests=false could
not reach, so its 78 existing tests could not be run here or anywhere. It is now
the same opt-in property scripts/settings/common uses, for the same reason, with
the same default. Verified locally: 81 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-13T18:24:27.587136Z b63b0e1 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 48ac2a37ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Review finding on #5815, and correct -- and it is the same defect this PR set out
to fix, in a narrower form that the companion BuildCloud change makes more
likely rather than less.

appStoreProfileForOverview returned the first ACTIVE IOS_APP_STORE profile on
the account without looking at its bundle id. Before this PR the card showed
profiles.get(0), so any profile at all; after it, any App Store profile on the
account. Once "Sync with Apple" imports the whole account rather than only what
this wizard created (codenameone/BuildCloud#147), a team that ships more than one
app is likely to have another app's App Store profile matched first -- announced
"Ready" here, and then refused for this project by the very preflight check added
in this same PR.

So the selection now matches the bundle id too, and the doc lists all three
things that have to line up, since each has been wrong in this one card.

A blank or unreadable project identifier skips the filter rather than guessing
it, which is the rule IOSProvisioningPreflight follows for the same reason: a
card reading "None yet" beside a perfectly good profile is its own kind of wrong.

The certificate card is deliberately NOT scoped this way. An Apple Distribution
certificate signs anything the team ships; a provisioning profile is issued for
one App ID. That asymmetry is noted at the call site so it does not read as an
oversight.

82 wizard tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • build-hint-catalog: 0 findings (no issues)
    • build-hint-tools: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 151 screenshots: 151 matched.

Native Android coverage

  • 📊 Line coverage: 9.24% (9184/99417 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.99% (47193/524920), branch 3.55% (1767/49739), complexity 3.52% (1868/53026), method 5.43% (1514/27888), class 10.89% (407/3736)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 9.24% (9184/99417 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.99% (47193/524920), branch 3.55% (1767/49739), complexity 3.52% (1868/53026), method 5.43% (1514/27888), class 10.89% (407/3736)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 398ms / native 252ms = 1.5x speedup
SIMD float-mul (64K x300) java 225ms / native 65ms = 3.4x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 97.000 ms
Base64 CN1 decode 85.000 ms
Base64 native encode 390.000 ms
Base64 encode ratio (CN1/native) 0.249x (75.1% faster)
Base64 native decode 296.000 ms
Base64 decode ratio (CN1/native) 0.287x (71.3% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 181 screenshots: 181 matched.
✅ JavaScript-port screenshot tests passed.

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 160 screenshots: 160 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 222 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 87ms / native 5ms = 17.4x speedup
SIMD float-mul (64K x300) java 82ms / native 3ms = 27.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 158.000 ms
Base64 CN1 decode 96.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.333x (66.7% faster)
Image applyMask (SIMD off) 35.000 ms
Image applyMask (SIMD on) 26.000 ms
Image applyMask ratio (SIMD on/off) 0.743x (25.7% faster)
Image modifyAlpha (SIMD off) 30.000 ms
Image modifyAlpha (SIMD on) 25.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.833x (16.7% faster)
Image modifyAlpha removeColor (SIMD off) 29.000 ms
Image modifyAlpha removeColor (SIMD on) 23.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.793x (20.7% faster)

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 148 screenshots: 148 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 322 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 70ms / native 6ms = 11.6x speedup
SIMD float-mul (64K x300) java 76ms / native 4ms = 19.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 233.000 ms
Base64 CN1 decode 117.000 ms
Base64 native encode 895.000 ms
Base64 encode ratio (CN1/native) 0.260x (74.0% faster)
Base64 native decode 332.000 ms
Base64 decode ratio (CN1/native) 0.352x (64.8% faster)
Base64 SIMD encode 62.000 ms
Base64 encode ratio (SIMD/CN1) 0.266x (73.4% faster)
Base64 SIMD decode 48.000 ms
Base64 decode ratio (SIMD/CN1) 0.410x (59.0% faster)
Base64 encode ratio (SIMD/native) 0.069x (93.1% faster)
Base64 decode ratio (SIMD/native) 0.145x (85.5% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 15.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.133x (86.7% faster)
Image applyMask (SIMD off) 54.000 ms
Image applyMask (SIMD on) 30.000 ms
Image applyMask ratio (SIMD on/off) 0.556x (44.4% faster)
Image modifyAlpha (SIMD off) 38.000 ms
Image modifyAlpha (SIMD on) 24.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.632x (36.8% faster)
Image modifyAlpha removeColor (SIMD off) 31.000 ms
Image modifyAlpha removeColor (SIMD on) 22.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.710x (29.0% faster)

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 217 screenshots: 217 matched.
✅ Native Apple Watch (watchOS, Core Graphics) screenshot tests passed.

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 149 screenshots: 149 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 1441 seconds

Build and Run Timing

Metric Duration
Simulator Boot 70000 ms
Simulator Boot (Run) 1000 ms
App Install 16000 ms
App Launch 8000 ms
Test Execution 431000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 152ms / native 4ms = 38.0x speedup
SIMD float-mul (64K x300) java 143ms / native 3ms = 47.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 348.000 ms
Base64 CN1 decode 133.000 ms
Base64 native encode 3662.000 ms
Base64 encode ratio (CN1/native) 0.095x (90.5% faster)
Base64 native decode 4434.000 ms
Base64 decode ratio (CN1/native) 0.030x (97.0% faster)
Base64 SIMD encode 55.000 ms
Base64 encode ratio (SIMD/CN1) 0.158x (84.2% faster)
Base64 SIMD decode 52.000 ms
Base64 decode ratio (SIMD/CN1) 0.391x (60.9% faster)
Base64 encode ratio (SIMD/native) 0.015x (98.5% faster)
Base64 decode ratio (SIMD/native) 0.012x (98.8% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 10.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.300x (70.0% faster)
Image applyMask (SIMD off) 99.000 ms
Image applyMask (SIMD on) 154.000 ms
Image applyMask ratio (SIMD on/off) 1.556x (55.6% slower)
Image modifyAlpha (SIMD off) 248.000 ms
Image modifyAlpha (SIMD on) 85.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.343x (65.7% faster)
Image modifyAlpha removeColor (SIMD off) 240.000 ms
Image modifyAlpha removeColor (SIMD on) 323.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.346x (34.6% slower)

@shai-almog

shai-almog commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 144 screenshots: 144 matched.
✅ Native Apple TV (tvOS, Metal) screenshot tests passed.

@shai-almog
shai-almog merged commit d3d40fb into master Sep 14, 2026
41 checks passed
@shai-almog
shai-almog deleted the fix/cert-wizard-5773-5793 branch September 14, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] more certificate wizard problems

1 participant