Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
22a1c18
Support React Native 0.82.1 with the fmt backport
mdspinali Oct 9, 2026
9816297
Validate minimum RN consumers with Xcode 27 and iOS 17
mdspinali Oct 9, 2026
7607184
Refresh Apple pod checksums for the release candidate
mdspinali Oct 9, 2026
7d141fc
Bind minimum RN cells to measured package environments
mdspinali Oct 9, 2026
f3d1b15
Bind candidate consumer checks to both RN versions
mdspinali Oct 9, 2026
6b8a775
Use scene lifecycle in Xcode 27 validation hosts
mdspinali Oct 9, 2026
532607c
Use scene lifecycle in the CocoaPods test host
mdspinali Oct 9, 2026
215ed34
Correct local release gate environment checks
mdspinali Oct 9, 2026
424f25e
Preserve raw descriptor output during environment checks
mdspinali Oct 9, 2026
0db1381
Measure protected Android descriptor directories
mdspinali Oct 9, 2026
77ad011
Remove duplicate directory permission control
mdspinali Oct 9, 2026
e894f05
Set Android validation device storage before boot
mdspinali Oct 9, 2026
e6b8e35
Retry interrupted Android archive downloads within the deadline
mdspinali Oct 9, 2026
ff1a292
Allow bounded emulator download retries to complete
mdspinali Oct 9, 2026
6d0d74a
Check archive retry budgets on every Android track
mdspinali Oct 9, 2026
a9a6b2b
Update dependencies required by the vulnerability gate
mdspinali Oct 9, 2026
c2a7e9f
Use the supported software emulator renderer
mdspinali Oct 9, 2026
9e4ff04
Enable required API 37 graphics capabilities
mdspinali Oct 9, 2026
ae8c131
Reject abnormal emulator cleanup and report failed operations
mdspinali Oct 9, 2026
73f4c3c
Preserve bounded environment probe failure details
mdspinali Oct 9, 2026
39e3394
Validate durable Swift migration recovery before synchronization
mdspinali Oct 9, 2026
a395db8
Record bounded connect facts for native schema verification
mdspinali Oct 9, 2026
89cef59
Align native schema setup and actions with authored client state
mdspinali Oct 9, 2026
55cee27
Retain bounded package readiness failure diagnostics
mdspinali Oct 9, 2026
daecc3a
Validate Kotlin migration plans and preserve nullable field data
mdspinali Oct 9, 2026
4fd40f0
Cover durable Kotlin migration recovery corruption
mdspinali Oct 9, 2026
5f54dbd
Expose bounded migration cuts through existing client inspection
mdspinali Oct 9, 2026
1ed2442
Verify native migration cuts and historical replay through React Native
mdspinali Oct 9, 2026
8b3fdbe
Capture bounded accepted mutation outcomes in the existing inspection…
mdspinali Oct 9, 2026
f46476d
Remove completed device build output before the simulator consumer build
mdspinali Oct 9, 2026
425285a
Bind migration cuts and historical replay to the shared native scenario
mdspinali Oct 9, 2026
22ff37c
Match React Native physical proof to the authored diagnostic fixture
mdspinali Oct 9, 2026
33e1a66
Prove native migration recovery and historical mutation reconciliation
mdspinali Oct 9, 2026
8ee2012
Count authored call windows including interrupted migration cuts
mdspinali Oct 9, 2026
27ed5da
Set the release candidate preparation date
mdspinali Oct 9, 2026
864eb83
Decode both approved column forms in the local row proof
mdspinali Oct 9, 2026
e309a7a
Align schema queue documentation with the unsealed base rule
mdspinali Oct 9, 2026
baf625e
State the exact Xcode 27 validation scope
mdspinali Oct 9, 2026
2e1c74b
Bind native singleton proof to original mutation identities
mdspinali Oct 9, 2026
c0041c5
Bind React Native singleton proof to original mutation identities
mdspinali Oct 9, 2026
814be8f
Measure response-loss work before the runner process ends
mdspinali Oct 9, 2026
f62face
Set the Kotlin outcome control raw retained capture
mdspinali Oct 9, 2026
06488e0
Match completed recovery proof to native journal lifecycle
mdspinali Oct 9, 2026
594ff2f
Inspect the prepared singleton at its actual sealed response
mdspinali Oct 9, 2026
7ddac82
Validate RN singleton intent at its sealing boundary
mdspinali Oct 9, 2026
e4e3742
Check recovered cursor across capture pending retries
mdspinali Oct 9, 2026
2735854
Require null base for unresolved dependent intent
mdspinali Oct 9, 2026
efae25f
Clarify dependent intent after predecessor acceptance
mdspinali Oct 9, 2026
13900bd
Preserve native retry facts and dependent intent in RN proof
mdspinali Oct 9, 2026
9a76d51
Accept exact historical batch replay after schema activation
mdspinali Oct 9, 2026
72f3725
Remove duplicate prepared push checks from final proof
mdspinali Oct 9, 2026
ae11390
Validate RN proof terminal pull against authored expectation
mdspinali Oct 9, 2026
0dc7d8d
Stop owned Android emulators through ADB before group cleanup
mdspinali Oct 9, 2026
b03ce34
Invalidate rebuild scopes before retained row digest checks
mdspinali Oct 9, 2026
dfd9388
Compare measured server rows across native historical replay
mdspinali Oct 9, 2026
6d82cda
Capture local fixture rows during Kotlin process restart
mdspinali Oct 9, 2026
2711722
Remove duplicate local fixture selector registration
mdspinali Oct 9, 2026
f59edd6
Bind retained Swift integrity before journal cursor replacement
mdspinali Oct 9, 2026
fe1a1f5
Create native schema additions from their authored field shape
mdspinali Oct 9, 2026
0fb372d
Publish stored generated columns in the native schema fixture
mdspinali Oct 9, 2026
28eb200
Count selected local tables in Kotlin restart captures
mdspinali Oct 9, 2026
47352a7
Run native schema baselines before the authored transition
mdspinali Oct 9, 2026
e72da2d
Preserve protected Swift provenance during schema cursor replacement
mdspinali Oct 9, 2026
57e74e3
Preserve protected Kotlin provenance during schema cursor replacement
mdspinali Oct 9, 2026
dc33310
Permit Kotlin local writes during an acknowledged call pause
mdspinali Oct 9, 2026
524a55c
Allow Swift build flags for local CodeQL extraction
mdspinali Oct 9, 2026
51daf76
Recover Swift scope integrity and retain protected hard deletes
mdspinali Oct 9, 2026
33e77d5
Recover Kotlin scope integrity and retain protected hard deletes
mdspinali Oct 9, 2026
ad2ab01
Correct native recovery test setup and scope expectations
mdspinali Oct 9, 2026
e2bb7b0
Share Swift protection rules after authoritative replacement
mdspinali Oct 9, 2026
6315858
Control the saved retry deadline in Kotlin restart proof
mdspinali Oct 9, 2026
cce92a9
Validate every Swift capture truncation flag
mdspinali Oct 9, 2026
51cfb68
Report bounded Kotlin transport closure facts
mdspinali Oct 9, 2026
d7f4a85
Remove redundant protected record deduplication
mdspinali Oct 9, 2026
a0751bf
Complete Swift atomic capture test fixtures
mdspinali Oct 9, 2026
2e031bb
Keep capture fixture formatting consistent
mdspinali Oct 9, 2026
abab928
Limit the server API fixture to its test phase
mdspinali Oct 9, 2026
6e89fe5
Align GRDB declarations with the tested native API version
mdspinali Oct 9, 2026
cbb3667
Update vulnerable compression and Handlebars resolutions
mdspinali Oct 9, 2026
3f912d6
Verify owned PostgreSQL destruction before gate cleanup
mdspinali Oct 9, 2026
fe15279
Update the supported documentation TOML resolution
mdspinali Oct 9, 2026
a6c8d37
Give the complete server suite a finite two-hour budget
mdspinali Oct 9, 2026
dd2d77f
Retain verified registry activation and valid connect evidence
mdspinali Oct 9, 2026
2fbad73
Report bounded schema reconciliation counts
mdspinali Oct 10, 2026
5c96223
Permit completed batch history in schema reconciliation proof
mdspinali Oct 10, 2026
6281df1
Publish native push bindings after image verification
mdspinali Oct 10, 2026
6684bde
Preserve historical images during schema type changes
mdspinali Oct 10, 2026
7e8ea46
Refresh table metadata with accepted push images
mdspinali Oct 10, 2026
697c7d9
Simplify authored integer image encoding
mdspinali Oct 10, 2026
e2c3024
Allow either valid historical batch replay form
mdspinali Oct 10, 2026
75de889
Preserve native resolution failures at cancellation
mdspinali Oct 10, 2026
cc4ae3c
Check canceled contexts and record readiness load timing
mdspinali Oct 10, 2026
b536bbf
Keep readiness timing inside the assertion boundary
mdspinali Oct 10, 2026
24b72d5
Reuse the verified pinned Android emulator archive
mdspinali Oct 10, 2026
cfdd99f
Verify cached emulator bytes from a private snapshot
mdspinali Oct 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,6 @@ jobs:
- name: Install cargo-mutants
run: cargo install --locked --force cargo-mutants --version 27.1.0

- name: Start local PostgreSQL
run: |
make local-postgres-start
echo "ADAPTER_TEST_URL=$(cat .ignore/r2/tmp/local-postgres/postgres.url)" >> "$GITHUB_ENV"

- name: Run candidate-server tests
run: make ci-candidate-server SOAK_ARTIFACT_DIR="$RUNNER_TEMP/soak-evidence"

Expand All @@ -181,10 +176,6 @@ jobs:
# A failure before the stress test leaves no journal. The test step keeps that failure.
if-no-files-found: ignore

- name: Stop local PostgreSQL
if: always()
run: make local-postgres-stop

candidate-swift:
name: candidate Swift
if: github.event_name == 'push'
Expand Down Expand Up @@ -318,7 +309,7 @@ jobs:
candidate-rn-ios:
name: candidate React Native iOS
if: github.event_name == 'push'
runs-on: macos-15
runs-on: xcode-27
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

Expand Down Expand Up @@ -352,6 +343,18 @@ jobs:
brew install wix/brew/applesimutils
fi

- name: Select Xcode 27 and current iOS simulator
run: |
set -euo pipefail
sudo xcode-select -s /Applications/Xcode_27.0.app
test "$(xcodebuild -version | sed -n '1s/^Xcode //p')" = '27.0'
runtime="$(xcrun simctl list runtimes available -j | ruby -rjson -e 'r=JSON.parse(STDIN.read).fetch("runtimes").find { |x| x["version"] == "27.0" }; abort "iOS 27.0 runtime is required" unless r; puts r.fetch("identifier")')"
udid="$(xcrun simctl create Synchro_RN_Current com.apple.CoreSimulator.SimDeviceType.iPhone-18-Pro "$runtime")"
xcrun simctl boot "$udid"
xcrun simctl bootstatus "$udid" -b
echo "IOS_SIMULATOR_UDID=$udid" >> "$GITHUB_ENV"
echo "RN_IOS_TEST_DESTINATION=platform=iOS Simulator,id=$udid" >> "$GITHUB_ENV"

- name: Start local PostgreSQL
run: |
set -euo pipefail
Expand Down Expand Up @@ -379,6 +382,12 @@ jobs:
make synchrod-pg-test-stop
make local-postgres-stop

- name: Delete React Native simulator
if: always() && env.IOS_SIMULATOR_UDID != ''
run: |
xcrun simctl shutdown "$IOS_SIMULATOR_UDID" >/dev/null 2>&1 || true
xcrun simctl delete "$IOS_SIMULATOR_UDID" >/dev/null 2>&1 || true

candidate-rn-android:
name: candidate React Native Android
if: github.event_name == 'push'
Expand Down Expand Up @@ -450,9 +459,6 @@ jobs:
make local-postgres-start
echo "ADAPTER_TEST_URL=$(cat .ignore/r2/tmp/local-postgres/postgres.url)" >> "$GITHUB_ENV"

- name: Build React Native Android app
run: make test-rn-e2e-android-build

- name: Enable KVM permissions
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
Expand All @@ -466,7 +472,7 @@ jobs:
python3 scripts/ci/run_android_emulator.py \
--sdk-root "$ANDROID_SDK_ROOT" --sdkmanager "$SDKMANAGER" \
--api 34 --image-api 34 --avd-name Pixel_7_API_34 --profile pixel_7 --memory 6144 \
--log-dir "$RUNNER_TEMP/synchro-rn-emulator" -- make ci-candidate-rn-android
--log-dir "$RUNNER_TEMP/synchro-rn-emulator" -- make test-rn-e2e-android-build ci-candidate-rn-android

pull-request:
name: pull-request
Expand Down
47 changes: 37 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -346,12 +346,14 @@ jobs:
from pathlib import Path
cells = [
{"id": "SUP-PG-LINUX-X64-001", "environment": {"architecture": "x86_64", "os": "ubuntu-24.04", "postgresql": "18.3"}},
{"id": "SUP-IOS-MIN-001", "environment": {"ios": "16.4", "xcode": "16.4"}},
{"id": "SUP-IOS-MIN-001", "environment": {"ios": "17.0", "xcode": "27.0"}},
{"id": "SUP-IOS-CURRENT-001", "environment": {"ios": "27.0", "xcode": "27.0"}},
{"id": "SUP-ANDROID-MIN-001", "environment": {"android_api": "24", "os": "ubuntu-24.04", "system_image": "system-images;android-24;google_apis;x86_64", "system_image_revision": "27", "emulator_version": "37.2.12", "emulator_build": "16428233"}},
{"id": "SUP-ANDROID-CURRENT-001", "environment": {"android_api": "37", "os": "ubuntu-24.04", "system_image": "system-images;android-37.0;google_apis;x86_64", "system_image_revision": "6", "emulator_version": "37.2.12", "emulator_build": "16428233"}},
{"id": "SUP-RN-IOS-CURRENT-001", "environment": {"ios": "27.0", "react_native": "0.83.10", "xcode": "27.0"}},
{"id": "SUP-RN-ANDROID-CURRENT-001", "environment": {"android_api": "37", "os": "ubuntu-24.04", "react_native": "0.83.10", "system_image": "system-images;android-37.0;google_apis;x86_64", "system_image_revision": "6", "emulator_version": "37.2.12", "emulator_build": "16428233"}},
{"id": "SUP-RN-IOS-MIN-001", "environment": {"ios": "27.0", "react_native": "0.82.1", "xcode": "27.0"}},
{"id": "SUP-RN-ANDROID-MIN-001", "environment": {"android_api": "37", "os": "ubuntu-24.04", "react_native": "0.82.1", "system_image": "system-images;android-37.0;google_apis;x86_64", "system_image_revision": "6", "emulator_version": "37.2.12", "emulator_build": "16428233"}},
]
Path("dist/release-inputs/support-environments.json").write_text(json.dumps(cells, indent=2, sort_keys=True) + "\n")
PY
Expand Down Expand Up @@ -516,6 +518,9 @@ jobs:
- cell: SUP-RN-ANDROID-CURRENT-001
api: '37.0'
support_api: '37'
- cell: SUP-RN-ANDROID-MIN-001
api: '37.0'
support_api: '37'
env:
ANDROID_HOME: /usr/local/lib/android/sdk
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
Expand Down Expand Up @@ -707,10 +712,10 @@ jobs:
matrix:
include:
- cell: SUP-IOS-MIN-001
ios: '16.4'
support: '16'
xcode: '16.4'
runner: macos-15
ios: '17.0'
support: '17'
xcode: '27.0'
runner: xcode-27
- cell: SUP-IOS-CURRENT-001
ios: '27.0'
support: '27.0'
Expand All @@ -721,6 +726,11 @@ jobs:
support: '27.0'
xcode: '27.0'
runner: xcode-27
- cell: SUP-RN-IOS-MIN-001
ios: '27.0'
support: '27.0'
xcode: '27.0'
runner: xcode-27
steps:
- name: Checkout candidate
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down Expand Up @@ -763,7 +773,22 @@ jobs:
test "$(xcodebuild -version | sed -n '1s/^Xcode //p')" = "$XCODE_VERSION"
swift --version | grep -E 'Swift version 6[.]' >/dev/null
if ! xcrun simctl list runtimes available -j | ruby -rjson -e 'wanted=ARGV.fetch(0); exit(JSON.parse(STDIN.read).fetch("runtimes").any? { |r| r["version"] == wanted } ? 0 : 1)' "$IOS_VERSION"; then
sudo xcodebuild -downloadPlatform iOS -buildVersion "$IOS_VERSION"
if [ "$IOS_VERSION" = '17.0' ]; then
umask 077
runtime_dir="$(mktemp -d)"
trap 'rm -rf "$runtime_dir"' EXIT
curl -q --fail --silent --show-error --location --proto '=https' --proto-redir '=https' \
--get --data-urlencode 'path=/Developer_Tools/iOS_17_Simulator_Runtime/iOS_17_Simulator_Runtime.dmg' \
--cookie-jar "$runtime_dir/cookies" --output /dev/null \
'https://developerservices2.apple.com/services/download'
test -s "$runtime_dir/cookies"
curl -q --fail --silent --show-error --location --proto '=https' --proto-redir '=https' \
--cookie "$runtime_dir/cookies" --output "$runtime_dir/iOS_17_Simulator_Runtime.dmg" \
'https://download.developer.apple.com/Developer_Tools/iOS_17_Simulator_Runtime/iOS_17_Simulator_Runtime.dmg'
sudo xcodebuild -importPlatform "$runtime_dir/iOS_17_Simulator_Runtime.dmg"
else
sudo xcodebuild -downloadPlatform iOS -buildVersion "$IOS_VERSION"
fi
fi
runtime="$(xcrun simctl list runtimes available -j | ruby -rjson -e 'wanted=ARGV.fetch(0); r=JSON.parse(STDIN.read).fetch("runtimes").find { |x| x["version"] == wanted }; abort "required iOS runtime is unavailable" unless r; puts r.fetch("identifier")' "$IOS_VERSION")"
device="$(xcrun simctl list devicetypes -j | ruby -rjson -e 'd=JSON.parse(STDIN.read).fetch("devicetypes"); x=d.find { |i| i["name"] == "iPhone 14" } || d.find { |i| i["name"].start_with?("iPhone") }; abort "no iPhone simulator type" unless x; puts x.fetch("identifier")')"
Expand Down Expand Up @@ -887,7 +912,7 @@ jobs:
name: approve, publish, verify, and promote
if: ${{ !cancelled() && needs.candidate.result == 'success' && needs.seal.result == 'success' && needs.package-gate.result == 'success' }}
needs: [candidate, seal, package-gate]
runs-on: macos-26
runs-on: xcode-27
environment: release
permissions:
actions: read
Expand Down Expand Up @@ -1388,21 +1413,23 @@ jobs:
npm_config_cache: ${{ runner.temp }}/public-rn-npm-cache
SYNCHRO_CONSUMER_RESOLUTION: public
PACKAGED_SMOKE_TMP_ROOT: ${{ runner.temp }}/public-rn
SUPPORT_PLATFORM_VERSION: '26.5'
SUPPORT_PLATFORM_VERSION: '27.0'
run: |
set -euo pipefail
mkdir -p "$GRADLE_USER_HOME" "$npm_config_cache"
test -z "$(find "$GRADLE_USER_HOME" -mindepth 1 -print -quit)"
test -z "$(find "$npm_config_cache" -mindepth 1 -print -quit)"
test -d /Applications/Xcode_26.6.app || { echo "Xcode 26.6 is required" >&2; exit 1; }
sudo xcode-select -s /Applications/Xcode_26.6.app
test -d /Applications/Xcode_27.0.app || { echo "Xcode 27.0 is required" >&2; exit 1; }
sudo xcode-select -s /Applications/Xcode_27.0.app
sdkmanager="$(find "$ANDROID_SDK_ROOT/cmdline-tools" -type f -name sdkmanager | sort | tail -n 1)"
test -x "$sdkmanager"
yes | "$sdkmanager" --licenses >/dev/null || { statuses=("${PIPESTATUS[@]}"); test "${statuses[1]}" = 0; }
"$sdkmanager" "platform-tools" "platforms;android-36" "build-tools;36.0.0"
mkdir -p "$RUNNER_TEMP/public-rn" "$RUNNER_TEMP/empty-artifacts"
sh verification/consumers/react-native/test-consumer.sh ios "$RUNNER_TEMP/empty-artifacts" "${{ needs.candidate.outputs.version }}" build-only
sh verification/consumers/react-native/test-consumer.sh android "$RUNNER_TEMP/empty-artifacts" "${{ needs.candidate.outputs.version }}" build-only
SYNCHRO_RN_VERSION=0.82.1 sh verification/consumers/react-native/test-consumer.sh ios "$RUNNER_TEMP/empty-artifacts" "${{ needs.candidate.outputs.version }}" build-only
SYNCHRO_RN_VERSION=0.82.1 sh verification/consumers/react-native/test-consumer.sh android "$RUNNER_TEMP/empty-artifacts" "${{ needs.candidate.outputs.version }}" build-only

- name: Promote npm latest only after public checks
env:
Expand Down
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Before `0.4.0`, use the [GitHub Releases](https://github.com/trainstar/synchro/r

## [Unreleased]

## [0.4.0-rc.2] - 2026-10-05
## [0.4.0-rc.2] - 2026-10-09

This release candidate is for consumer validation of `0.4.0`.
Use exact versions. See [Release Candidate](https://github.com/trainstar/synchro/blob/master/RELEASE.md#release-candidate) for registry behavior.
Expand All @@ -18,6 +18,18 @@ Use exact versions. See [Release Candidate](https://github.com/trainstar/synchro

- Operators can register an assignment function with a SQL NULL bound to return all distinct assigned scopes. ([#300](https://github.com/trainstar/synchro/issues/300))

### Changed

- Swift Package Manager and CocoaPods integrations require GRDB 7.8 or later consistently for native inspection APIs. ([#303](https://github.com/trainstar/synchro/issues/303))
- React Native applications can use RN 0.82.1 through 0.83.x. RN 0.82.1 iOS applications require the [fmt 12.1.0 backport](https://trainstar.github.io/synchro/reference/support-policy/#react-native-0821-fmt-backport) with Xcode 27. ([#303](https://github.com/trainstar/synchro/issues/303))
- Breaking: Apple clients require iOS 17 or later. Increase the application deployment target before upgrading. See [client requirements](https://trainstar.github.io/synchro/clients/consumption/). ([#303](https://github.com/trainstar/synchro/issues/303))

### Fixed

- Native clients reject inconsistent migration journals and retain unfinished scope rebuild work during schema changes. Native clients preserve pending local edits and deletes when compatible schema changes replace cursors. Native clients rebuild only the affected scope after a local checksum mismatch. ([#331](https://github.com/trainstar/synchro/issues/331))
- Swift clients apply remote changes after a later accepted or conflict outcome replaces a terminal rejection. ([#331](https://github.com/trainstar/synchro/issues/331))
- Kotlin clients preserve rows when fields become nullable and support required-field additions without invented defaults. ([#331](https://github.com/trainstar/synchro/issues/331))

## [0.4.0-rc.1] - 2026-10-01

This release candidate is for consumer validation of `0.4.0`.
Expand Down
Loading
Loading