From 0cabc8f6d1beeff7cfaef677bbf8610bc031b358 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Tue, 25 Aug 2026 12:12:34 -0400 Subject: [PATCH 1/2] chore: retire the parity gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit verify-parity.sh compared this repo's generated output against the copy each app generated for itself. Both apps now consume this package instead of generating — code-android-app#1325 and code-ios-app#645 delete the vendored protos and the codegen that fed them — so there is no second output left to compare against. The script's own header said to delete it at this point. What the gate was actually protecting is generator drift, and that protection moves entirely to scripts/toolchain.env: grpc-swift-2 reaches the plugin through a floating `from:` requirement, so the Swift moves on a transitive release with no contract change and nothing downstream to catch it. Its comment says so directly now. The READMEs' Status sections were written around the gate and around "never published, no app depends on it," both of which stopped being true at 0.1.0. Rewritten to record what the comparison found rather than to promise it stays green. --- README.md | 61 +++++++++++++-------------------- scripts/toolchain.env | 7 ++-- scripts/verify-parity.sh | 73 ---------------------------------------- 3 files changed, 28 insertions(+), 113 deletions(-) delete mode 100755 scripts/verify-parity.sh diff --git a/README.md b/README.md index 2d50b95..49177ff 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Kotlin and Swift client SDKs for the Flipcash services, generated from the contr published so the apps consume a versioned dependency instead of vendoring `.proto` files and running protoc themselves. -Today `code-android-app` and `code-ios-app` each vendor their own copy of these protos and -generate independently. That is two copies of the contract, two generator toolchains, and no -mechanism that makes them agree. This repo is the single generation point. +`code-android-app` and `code-ios-app` used to each vendor their own copy of these protos and +generate independently — two copies of the contract, two generator toolchains, and no mechanism +that made them agree. This repo is the single generation point that replaced them. It is the sibling of [`ocp-client-protocol`](https://github.com/code-payments/ocp-client-protocol). The two are separate packages because the contracts are independent — flipcash2 does not import @@ -15,32 +15,21 @@ ocp — and because they belong to different orgs once the split lands. ## Status -Pilot. It has never been published to a real registry, and neither app depends on it on a -branch. What is verified is that the generated code is a drop-in replacement for what the apps -produce now: - -| Output | Files | Compared against | Result | -|---|---|---|---| -| Kotlin/Java | 526 | `:definitions:flipcash:models:generateDebugProto` | identical | -| Swift | 50 | `FlipcashAPI/.../Core/Generated` | identical, two files renamed | - -The Kotlin split matches per generator too: 17 grpc, 17 grpckt, 33 java, 257 kotlin, 202 -validate-kt. `scripts/verify-parity.sh` is that check, and it should stay green until both apps -migrate. - -The two renamed Swift files are `messaging_v1_messaging_service.{pb,grpc}.swift`; their contents -are byte-identical to the app's `flipcash_`-prefixed copies. See below. - -Both artifacts also build: `swift build` compiles the SPM target, and `./gradlew build -publishToMavenLocal` produces a 2574-class JAR under `com.codeinc.flipcash.gen.*`. - -The consumer side is proven too. Pointing `:services:flipcash` at the mavenLocal artifact and -dropping `:definitions:flipcash:models` from its classpath builds the app and passes the module's -220 unit tests. That was done with `:services:opencode` on its own artifact at the same time, so -the combined end state builds, not just one half of it. - -Compare against a checkout whose vendored protos are current. An app checkout that predates the -username protos generates 521 files, and the five-file gap is staleness, not drift. +Released. `0.1.0` is on Maven Central and tagged for SPM. Android consumes it in +[code-android-app#1325](https://github.com/code-payments/code-android-app/pull/1325) and iOS in +[code-ios-app#645](https://github.com/code-payments/code-ios-app/pull/645), which together delete +both vendored copies. + +Before the apps migrated, `scripts/verify-parity.sh` proved this repo is a drop-in replacement +for what they generated: 526 Kotlin/Java files against +`:definitions:flipcash:models:generateDebugProto` and 50 Swift files against +`FlipcashAPI/.../Core/Generated`, both identical, with the Kotlin split matching per generator +(17 grpc, 17 grpckt, 33 java, 257 kotlin, 202 validate-kt). Two Swift filenames differed — +`messaging_v1_messaging_service.{pb,grpc}.swift` against the app's `flipcash_`-prefixed copies, +byte-identical contents, see below. That gate is retired with the copies it compared against — +an app that no longer generates has no second output to disagree with. What guards the output +now is `scripts/toolchain.env`, since a floating generator moves the Swift without any contract +change. ## Layout @@ -54,7 +43,6 @@ scripts/ install-swift-toolchain.sh pinned generators into .tools/ toolchain.env the pins generate-swift.sh regenerate Sources/ - verify-parity.sh the phase-1 gate ``` Generated Kotlin is not committed. It is a build input to a published JAR, so the @@ -75,11 +63,11 @@ scripts/generate-swift.sh # refresh committed Swift `com.codeinc.flipcash.gen.*` themselves, so unlike the OCP repo there is nothing to rewrite. `sync-protos.sh` verifies the `java_package` on every synced file instead and fails the sync if one is missing, which is what would silently break the artifact. -- **The `flipcash_` filename prefix is an artifact of module merging.** The iOS app renames - `messaging_v1_messaging_service.*` in its `Scripts/run` because both protocols generate into - one `FlipcashAPI` module and the OCP messaging service collides. With a package per protocol - the collision cannot happen, so the rename is dropped. `verify-parity.sh` replays it to keep - the comparison honest until the app migrates. +- **The `flipcash_` filename prefix was an artifact of module merging.** The iOS app renamed + `messaging_v1_messaging_service.*` in its `Scripts/run` because both protocols generated into + one `FlipcashAPI` module and the OCP messaging service collided. With a package per protocol + the collision cannot happen, so the rename is gone. The Swift type names + (`Flipcash_Messaging_V1_*` vs `Ocp_Messaging_V1_*`) never differed. - **`validate/validate.proto` is an include-path dependency only.** It is never generated. The iOS build currently generates it and then deletes the resulting `validate_validate.pb.swift`; keeping it in `proto_deps/` and off the generation list removes @@ -148,5 +136,4 @@ human step, and the one that needs a DNS TXT record. ## Not done yet -A real released version and a committed dependency in either app. This repo publishes after -`ocp-client-protocol` 0.1.0 is out and resolving from Central. +Both consumer PRs are open, not merged. diff --git a/scripts/toolchain.env b/scripts/toolchain.env index 4d3bb01..62b56ac 100644 --- a/scripts/toolchain.env +++ b/scripts/toolchain.env @@ -7,9 +7,10 @@ # 2.2.1 adds `Sendable` to the metadata enums and 2.3.0 adds `type:` to every # MethodDescriptor, which is ~840 changed lines across 9 files for no contract change. # -# This set reproduces the iOS app's committed output byte for byte, which is what -# scripts/verify-parity.sh compares against. Bumping it is a real change with a real diff: -# do it in its own commit, and expect Sources/ to move. +# This set reproduces the Swift the iOS app shipped before it migrated to this package. +# With the app's own copy gone there is nothing left to compare against, so these pins are +# the guarantee: bumping them is a real change with a real diff. Do it in its own commit, +# and expect Sources/ to move. PROTOC_VERSION=33.1 SWIFT_PROTOBUF_VERSION=1.33.3 GRPC_SWIFT_PROTOBUF_VERSION=2.1.1 diff --git a/scripts/verify-parity.sh b/scripts/verify-parity.sh deleted file mode 100755 index 8de44d5..0000000 --- a/scripts/verify-parity.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash -# -# Gate for phase 1: what this repo generates must match what the apps generate today. -# Run it against real checkouts of both apps: -# -# VERIFY_ANDROID=../code-android-app VERIFY_IOS=../code-ios-app scripts/verify-parity.sh -# -# Either side can be skipped by leaving its variable unset. This script is expected to be -# deleted once both apps consume the published artifacts -- at that point the apps have no -# independent output left to compare against. -# -set -uo pipefail - -ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -ANDROID="${VERIFY_ANDROID:-}" -IOS="${VERIFY_IOS:-}" -status=0 - -hr() { printf '%s\n' "------------------------------------------------------------"; } - -# ---------------------------------------------------------------- Swift -if [ -n "$IOS" ]; then - hr; echo "Swift: this repo vs $IOS" - ref="$IOS/FlipcashAPI/Sources/FlipcashAPI/Core/Generated" - if [ ! -d "$ref" ]; then - echo " SKIP: $ref not found" - else - "$ROOT/scripts/generate-swift.sh" >/dev/null || { echo " FAIL: codegen errored"; status=1; } - # The app prefixes messaging_v1_messaging_service.* with `flipcash_` in its Scripts/run, - # because both protocols land in one merged FlipcashAPI module and the OCP messaging - # service would otherwise collide. Separate SPM modules make that unnecessary, so the - # comparison replays the rename rather than treating it as drift. - stage="$(mktemp -d)" - trap 'rm -rf "$stage"' EXIT - cp -R "$ROOT/Sources/Flipcash2ClientProtocol/." "$stage/" - for f in "$stage"/messaging_v1_messaging_service.*; do - [ -e "$f" ] || continue - mv "$f" "$stage/flipcash_$(basename "$f")" - done - if /usr/bin/diff -rq "$stage" "$ref" >/tmp/vp-swift.txt 2>&1; then - echo " OK: $(find "$ref" -name '*.swift' | wc -l | tr -d ' ') file(s) identical (modulo the flipcash_ rename)" - else - echo " DRIFT:"; sed 's/^/ /' /tmp/vp-swift.txt; status=1 - fi - fi -fi - -# ---------------------------------------------------------------- Kotlin -if [ -n "$ANDROID" ]; then - hr; echo "Kotlin: this repo vs $ANDROID" - ref="$ANDROID/definitions/flipcash/models/build/generated/java/generateDebugProto" - if [ ! -d "$ref" ]; then - echo " SKIP: $ref not found -- build it first with:" - echo " (cd $ANDROID && ./gradlew :definitions:flipcash:models:generateDebugProto)" - else - "$ROOT/gradlew" -p "$ROOT" generateProto --quiet || { echo " FAIL: codegen errored"; status=1; } - mine="$ROOT/build/generated/sources/proto/main" - if /usr/bin/diff -rq "$mine" "$ref" >/tmp/vp-kt.txt 2>&1; then - echo " OK: $(find "$ref" -type f | wc -l | tr -d ' ') file(s) identical" - else - echo " DRIFT:"; sed 's/^/ /' /tmp/vp-kt.txt; status=1 - fi - fi -fi - -if [ -z "$ANDROID" ] && [ -z "$IOS" ]; then - echo "nothing to compare: set VERIFY_ANDROID and/or VERIFY_IOS" >&2 - exit 2 -fi - -hr -[ "$status" = 0 ] && echo "PARITY OK" || echo "PARITY FAILED" -exit "$status" From 11d91c91c681433c32107380b62bd7a55c6e6b4d Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Tue, 25 Aug 2026 12:28:21 -0400 Subject: [PATCH 2/2] docs: record that both apps are on 0.1.0 The consumer PRs merged, so the Status section's "open, not merged" no longer holds. The "Not done yet" section held nothing else, so it goes with it. --- README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 49177ff..4b60e48 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ ocp — and because they belong to different orgs once the split lands. ## Status -Released. `0.1.0` is on Maven Central and tagged for SPM. Android consumes it in -[code-android-app#1325](https://github.com/code-payments/code-android-app/pull/1325) and iOS in -[code-ios-app#645](https://github.com/code-payments/code-ios-app/pull/645), which together delete -both vendored copies. +Released, and both apps are on it. `0.1.0` is on Maven Central and tagged for SPM. Android +migrated in [code-android-app#1325](https://github.com/code-payments/code-android-app/pull/1325) +and iOS in [code-ios-app#645](https://github.com/code-payments/code-ios-app/pull/645), which +together deleted both vendored copies. Before the apps migrated, `scripts/verify-parity.sh` proved this repo is a drop-in replacement for what they generated: 526 Kotlin/Java files against @@ -133,7 +133,3 @@ gpg --keyserver keyserver.ubuntu.com --send-keys The `com.flipcash` namespace is verified in the Central Portal. That was the other one-time human step, and the one that needs a DNS TXT record. - -## Not done yet - -Both consumer PRs are open, not merged.