Skip to content

feat(core): make SDK initialization single-flight safe#28

Open
pitzcarraldo wants to merge 1 commit into
mainfrom
feat/single-flight-initialization
Open

feat(core): make SDK initialization single-flight safe#28
pitzcarraldo wants to merge 1 commit into
mainfrom
feat/single-flight-initialization

Conversation

@pitzcarraldo

@pitzcarraldo pitzcarraldo commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make async Clix.initialize(config:) single-flight by reusing one actor-managed task
  • ensure initialization completion is always signaled, even when setup throws
  • add concurrency tests for InitCoordinator single-flight and rerun behavior
  • add make test target for iOS simulator, update SwiftLint exclusions, and add BasicApp env config JSON files

Why

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

  • New feature
  • Bug fix
  • Breaking change
  • Refactor
  • Documentation
  • Workflow/CI

Testing

  • make test (iOS Simulator) passed
  • swift test (not applicable in this environment due to macOS dependency constraints)

Risk / Impact

  • low to medium: initialization flow changed to task-coalescing behavior
  • covered by new unit tests around coordinator task lifecycle

Related Issue

  • #XXXX

Summary by CodeRabbit

  • Tests

    • Added comprehensive tests for initialization coordination to ensure proper single-flight operation behavior and task management.
  • Chores

    • Updated build configuration to support automated testing on iOS Simulator.
    • Updated linting exclusions and ignore patterns for project maintenance.

@coderabbitai

coderabbitai Bot commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Refactored 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

Cohort / File(s) Summary
Configuration & Build
.swiftlint.yml, Makefile, .gitignore
Added CocoaPods Pods path to SwiftLint exclusions, introduced iOS Simulator test target with UDID detection, and added local environment config ignore pattern.
Core Initialization Refactor
Sources/Core/Clix.swift
Refactored initialize(config:) to delegate to task-based coordination via InitCoordinator, supporting single-flight initialization operations with task reuse and cleanup logic.
Test Coverage
Tests/ClixTests.swift
Added Counter actor and coordination tests verifying single-flight behavior and sequential operation support after task completion.
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly reflects the main objective: implementing single-flight safe initialization for the SDK core, which is the primary architectural change in this changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/single-flight-initialization

Comment @coderabbitai help to get the list of available commands and usage tips.

@pitzcarraldo pitzcarraldo self-assigned this Feb 6, 2026

@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: 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"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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.
@pitzcarraldo pitzcarraldo force-pushed the feat/single-flight-initialization branch from b45cf04 to 1272813 Compare February 6, 2026 07:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Comment thread Makefile
Comment on lines +16 to +26
# 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

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.

Comment on lines +1 to +8
{
"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"
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

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.

Comment on lines +1 to +6
{
"projectId": "c2aedfdb-f785-493f-b0a6-88e0692af81f",
"apiKey": "clix_pk_RRvP1mScpce4_XrK9uiYMQF09Crhjw",
"endpoint": "https://api.clix.so",
"extraHeaders": {}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

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.

Suggested change
{
"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.

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.

1 participant