feat(core): make SDK initialization single-flight safe#28
Conversation
WalkthroughRefactored initialization flow in Clix to use a task-based coordinator pattern that manages single-flight initialization operations. Added iOS Simulator test infrastructure via Makefile, introduced coordination tests, and updated configuration to exclude CocoaPods and ignore local environment configs. Changes
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4ba1443e77
ℹ️ 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".
| "apiKey": "clix_pk_A0wRnlwQT64tgL1BuMxZKlt_8_SvfA", | ||
| "endpoint": "https://external-api-dev.clix.so", | ||
| "extraHeaders": { | ||
| "Cf-Access-Token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBlMmJmNTNlN2Y3MmY2Zjg3NDY1ZTk3ODM5ZmY2NDMwOTBkMDYxMDZiYjUyOGM3MzI2YWI5OGMzNjc2N2IyYTEifQ.eyJhdWQiOlsiODAzYjE3NDhhOTVlNzc5YjMyOTMxYjZlNjlmMDhjMjNhYTUzNTAwMDc0YmE2YmQ4ZjVhODg4MTg5YWU2ZTYwMCJdLCJlbWFpbCI6Im1pbmt5dUBncmV5Ym94aHEuY29tIiwiZXhwIjoxNzY1ODY4MzgwLCJpYXQiOjE3NjUyNjM1ODAsIm5iZiI6MTc2NTI2MzU4MCwiaXNzIjoiaHR0cHM6Ly9ncmV5Ym94LmNsb3VkZmxhcmVhY2Nlc3MuY29tIiwidHlwZSI6ImFwcCIsImlkZW50aXR5X25vbmNlIjoiT09jdlFISnZDYlNlQUhweCIsInN1YiI6IjRlOWI2ZjdjLTI0Y2ItNTlkNy1hZDE4LTM2MDg3MzA3MzQ1MiIsImNvdW50cnkiOiJLUiJ9.R_yiobT1zX9cpv_vxcGxKJhFERPJLuGIetHsdFBzTSAY_YbbFsPorfO7hKunwvv76ANZPD-fCx2eXZQ06a2c5yYeOkZn99V5KRH1si85TfmobRDxqD8DIabW0x5uGMSLWLFSFBOR7L-v1YFiITqis1LcNqA6bK6JnK_su1GxWscyXYrDGrgBcGxvZ4Xw5P78Y--yw8vKwpP0m1wwC-Zoxsj_hI4Z5BRfER2Xx2Yv1vq8BdaROEcKTAHXwOgPEycrJ4zwPdMlEZ2y7bUjZqtf-J7G0r2WEtl_WCZy9_HlUQ6Fry0CDajgcy7J5J_XtfwJ7VME45q8_hZMKYhH3-ZGtw" |
There was a problem hiding this comment.
Remove committed bearer token from sample config
This commit adds a real Cf-Access-Token value to a tracked JSON file, which exposes a reusable credential to anyone with repository access and risks unauthorized access to protected dev APIs until the token is rotated or expires. Sample config files should not contain live secrets; replace this with a placeholder and load the token from an untracked local override or environment at runtime.
Useful? React with 👍 / 👎.
Route async initialization through a shared actor-managed task so concurrent initialize calls await the same execution path. Add InitCoordinator concurrency tests, iOS simulator test target, SwiftLint exclusion updates, and ignore ClixConfig.*.json to prevent accidental commits of local environment config variants.
b45cf04 to
1272813
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@Makefile`:
- Around line 16-26: Compute SIMULATOR_UDID in a way that matches both uppercase
and lowercase hex (use case-insensitive grep or normalize with tr) and protect
the test target by checking SIMULATOR_UDID is non-empty before invoking
xcodebuild; if empty, print a clear error and exit early. Update the
SIMULATOR_UDID assignment (the shell command that calls xcrun simctl list
devices available and the grep -oE pattern) to accept lowercase hex and/or pipe
through tr '[:lower:]' '[:upper:]', and modify the test target to guard on
SIMULATOR_UDID (use a shell conditional to echo a descriptive message and exit 1
if it's empty) so xcodebuild is never called with an invalid id.
In `@Samples/BasicApp/Resources/ClixConfig.dev.json`:
- Around line 1-8: Remove the hard-coded secrets from ClixConfig.dev.json:
delete the "Cf-Access-Token" value inside "extraHeaders" and the "apiKey" value,
replace them with non-secret placeholders (e.g., "<REDACTED_API_KEY>" and
"<REDACTED_CF_ACCESS_TOKEN>"), and update any code that reads
ClixConfig.dev.json to load real values from environment variables or a
gitignored local config (e.g., process.env.CLIX_API_KEY /
process.env.CF_ACCESS_TOKEN or a .env/.local.json file). Revoke/rotate the
exposed JWT and API key immediately, ensure the repo no longer contains them,
and add the local config filename to .gitignore so secrets are not committed
again.
In `@Samples/BasicApp/Resources/ClixConfig.prod.json`:
- Around line 1-6: The committed production sample config contains a real API
credential in "apiKey" inside ClixConfig.prod.json; replace the hard-coded value
with a placeholder (e.g. "<YOUR_API_KEY>") and update code that reads this file
to load the real key from a gitignored local config or environment/CI secret
instead (ensure the "apiKey" field is populated at runtime), then rotate/revoke
the exposed key immediately.
| # Detect first available iPhone Simulator UDID | ||
| SIMULATOR_UDID := $(shell xcrun simctl list devices available | grep iPhone | head -1 | grep -oE '[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}') | ||
|
|
||
| # Target to run tests on iOS Simulator | ||
| test: | ||
| @echo "Running tests on iOS Simulator ($(SIMULATOR_UDID))..." | ||
| @xcodebuild test \ | ||
| -workspace .swiftpm/xcode/package.xcworkspace \ | ||
| -scheme Clix \ | ||
| -destination 'id=$(SIMULATOR_UDID)' \ | ||
| -quiet |
There was a problem hiding this comment.
Guard against missing/format-variant simulator UDIDs to avoid flaky make test.
If no iPhone simulator is available—or if UDIDs are lowercase—SIMULATOR_UDID becomes empty and xcodebuild fails with a confusing error. Add a guard and a case-insensitive match.
🛠️ Suggested Makefile hardening
-SIMULATOR_UDID := $(shell xcrun simctl list devices available | grep iPhone | head -1 | grep -oE '[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}')
+SIMULATOR_UDID := $(shell xcrun simctl list devices available | grep -m1 iPhone | grep -oE '[0-9A-Fa-f-]{36}')
test:
+ `@if` [ -z "$(SIMULATOR_UDID)" ]; then \
+ echo "No available iPhone simulator found. Run 'xcrun simctl list devices available'."; \
+ exit 1; \
+ fi
`@echo` "Running tests on iOS Simulator ($(SIMULATOR_UDID))..."🤖 Prompt for AI Agents
In `@Makefile` around lines 16 - 26, Compute SIMULATOR_UDID in a way that matches
both uppercase and lowercase hex (use case-insensitive grep or normalize with
tr) and protect the test target by checking SIMULATOR_UDID is non-empty before
invoking xcodebuild; if empty, print a clear error and exit early. Update the
SIMULATOR_UDID assignment (the shell command that calls xcrun simctl list
devices available and the grep -oE pattern) to accept lowercase hex and/or pipe
through tr '[:lower:]' '[:upper:]', and modify the test target to guard on
SIMULATOR_UDID (use a shell conditional to echo a descriptive message and exit 1
if it's empty) so xcodebuild is never called with an invalid id.
| { | ||
| "projectId": "5dbdd10e-6ea6-4ff7-836d-bd30a6d1a521", | ||
| "apiKey": "clix_pk_A0wRnlwQT64tgL1BuMxZKlt_8_SvfA", | ||
| "endpoint": "https://external-api-dev.clix.so", | ||
| "extraHeaders": { | ||
| "Cf-Access-Token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBlMmJmNTNlN2Y3MmY2Zjg3NDY1ZTk3ODM5ZmY2NDMwOTBkMDYxMDZiYjUyOGM3MzI2YWI5OGMzNjc2N2IyYTEifQ.eyJhdWQiOlsiODAzYjE3NDhhOTVlNzc5YjMyOTMxYjZlNjlmMDhjMjNhYTUzNTAwMDc0YmE2YmQ4ZjVhODg4MTg5YWU2ZTYwMCJdLCJlbWFpbCI6Im1pbmt5dUBncmV5Ym94aHEuY29tIiwiZXhwIjoxNzY1ODY4MzgwLCJpYXQiOjE3NjUyNjM1ODAsIm5iZiI6MTc2NTI2MzU4MCwiaXNzIjoiaHR0cHM6Ly9ncmV5Ym94LmNsb3VkZmxhcmVhY2Nlc3MuY29tIiwidHlwZSI6ImFwcCIsImlkZW50aXR5X25vbmNlIjoiT09jdlFISnZDYlNlQUhweCIsInN1YiI6IjRlOWI2ZjdjLTI0Y2ItNTlkNy1hZDE4LTM2MDg3MzA3MzQ1MiIsImNvdW50cnkiOiJLUiJ9.R_yiobT1zX9cpv_vxcGxKJhFERPJLuGIetHsdFBzTSAY_YbbFsPorfO7hKunwvv76ANZPD-fCx2eXZQ06a2c5yYeOkZn99V5KRH1si85TfmobRDxqD8DIabW0x5uGMSLWLFSFBOR7L-v1YFiITqis1LcNqA6bK6JnK_su1GxWscyXYrDGrgBcGxvZ4Xw5P78Y--yw8vKwpP0m1wwC-Zoxsj_hI4Z5BRfER2Xx2Yv1vq8BdaROEcKTAHXwOgPEycrJ4zwPdMlEZ2y7bUjZqtf-J7G0r2WEtl_WCZy9_HlUQ6Fry0CDajgcy7J5J_XtfwJ7VME45q8_hZMKYhH3-ZGtw" | ||
| } | ||
| } |
There was a problem hiding this comment.
Do not commit Cf-Access-Token/JWT or API keys in dev config.
This file includes a bearer token and API key (also flagged by secret scanning). These must be removed from the repo, rotated/revoked, and supplied via gitignored local files or CI secrets.
🔐 Suggested placeholder config (redacted)
- "apiKey": "<REDACTED_API_KEY>",
+ "apiKey": "YOUR_API_KEY",
"extraHeaders": {
- "Cf-Access-Token": "<REDACTED_JWT>"
+ "Cf-Access-Token": "YOUR_CF_ACCESS_TOKEN"
}🧰 Tools
🪛 Gitleaks (8.30.0)
[high] 6-6: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
[high] 3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
In `@Samples/BasicApp/Resources/ClixConfig.dev.json` around lines 1 - 8, Remove
the hard-coded secrets from ClixConfig.dev.json: delete the "Cf-Access-Token"
value inside "extraHeaders" and the "apiKey" value, replace them with non-secret
placeholders (e.g., "<REDACTED_API_KEY>" and "<REDACTED_CF_ACCESS_TOKEN>"), and
update any code that reads ClixConfig.dev.json to load real values from
environment variables or a gitignored local config (e.g.,
process.env.CLIX_API_KEY / process.env.CF_ACCESS_TOKEN or a .env/.local.json
file). Revoke/rotate the exposed JWT and API key immediately, ensure the repo no
longer contains them, and add the local config filename to .gitignore so secrets
are not committed again.
| { | ||
| "projectId": "c2aedfdb-f785-493f-b0a6-88e0692af81f", | ||
| "apiKey": "clix_pk_RRvP1mScpce4_XrK9uiYMQF09Crhjw", | ||
| "endpoint": "https://api.clix.so", | ||
| "extraHeaders": {} | ||
| } |
There was a problem hiding this comment.
Remove committed API credentials from the production sample config.
The apiKey value appears to be a real credential; committing it risks unauthorized access. Replace with placeholders and load real values from a gitignored local file or CI secrets, and rotate/revoke the exposed key.
🔐 Suggested placeholder config (redacted)
- "projectId": "<REDACTED_PROJECT_ID>",
- "apiKey": "<REDACTED_API_KEY>",
+ "projectId": "YOUR_PROJECT_ID",
+ "apiKey": "YOUR_API_KEY",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| { | |
| "projectId": "c2aedfdb-f785-493f-b0a6-88e0692af81f", | |
| "apiKey": "clix_pk_RRvP1mScpce4_XrK9uiYMQF09Crhjw", | |
| "endpoint": "https://api.clix.so", | |
| "extraHeaders": {} | |
| } | |
| { | |
| "projectId": "YOUR_PROJECT_ID", | |
| "apiKey": "YOUR_API_KEY", | |
| "endpoint": "https://api.clix.so", | |
| "extraHeaders": {} | |
| } |
🤖 Prompt for AI Agents
In `@Samples/BasicApp/Resources/ClixConfig.prod.json` around lines 1 - 6, The
committed production sample config contains a real API credential in "apiKey"
inside ClixConfig.prod.json; replace the hard-coded value with a placeholder
(e.g. "<YOUR_API_KEY>") and update code that reads this file to load the real
key from a gitignored local config or environment/CI secret instead (ensure the
"apiKey" field is populated at runtime), then rotate/revoke the exposed key
immediately.
Summary
Clix.initialize(config:)single-flight by reusing one actor-managed taskInitCoordinatorsingle-flight and rerun behaviormake testtarget for iOS simulator, update SwiftLint exclusions, and add BasicApp env config JSON filesWhy
Concurrent initialization calls could start duplicated setup work. This change ensures all callers await the same in-flight initialization task and improves deterministic initialization behavior.
Type of Change
Testing
make test(iOS Simulator) passedswift test(not applicable in this environment due to macOS dependency constraints)Risk / Impact
Related Issue
Summary by CodeRabbit
Tests
Chores