From 8f0ec1f77dac070fb15707be30848dae8745c6a5 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Tue, 25 Aug 2026 12:12:32 -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 | 41 +++++++++++--------------- scripts/toolchain.env | 7 +++-- scripts/verify-parity.sh | 62 ---------------------------------------- 3 files changed, 20 insertions(+), 90 deletions(-) delete mode 100755 scripts/verify-parity.sh diff --git a/README.md b/README.md index d590b86..edb10cc 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Kotlin and Swift client SDKs for the Open Code Protocol, generated from the cont 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 [`flipcash2-client-protocol`](https://github.com/code-payments/flipcash2-client-protocol). The two are separate packages because the contracts are independent — flipcash2 does not import @@ -15,25 +15,19 @@ 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: +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. -| Output | Files | Compared against | Result | -|---|---|---|---| -| Kotlin/Java | 263 | `:definitions:opencode:models:generateDebugProto` | identical | -| Swift | 9 | `FlipcashAPI/.../Payments/Generated` | identical | - -The Kotlin split matches per generator too: 4 grpc, 4 grpckt, 5 java, 119 kotlin, 131 -validate-kt. `scripts/verify-parity.sh` is that check, and it should stay green until both -apps migrate. - -Both artifacts also build: `swift build` compiles the SPM target, and `./gradlew build -publishToMavenLocal` produces a 1418-class JAR under `com.codeinc.opencode.gen.*`. - -The consumer side is proven too. Pointing `:services:opencode` at the mavenLocal artifact and -dropping `:definitions:opencode:models` from its classpath builds the app and passes the -module's 603 unit tests, with `protovalidate-runtime` and coroutines arriving transitively. +Before the apps migrated, `scripts/verify-parity.sh` proved this repo is a drop-in replacement +for what they generated: 263 Kotlin/Java files against +`:definitions:opencode:models:generateDebugProto` and 9 Swift files against +`FlipcashAPI/.../Payments/Generated`, both identical, with the Kotlin split matching per +generator (4 grpc, 4 grpckt, 5 java, 119 kotlin, 131 validate-kt). 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 @@ -47,7 +41,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 @@ -138,9 +131,7 @@ 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. The first `0.1.0` attempt -reached Central and failed validation on the unpublished signing key; `0.1.0` is still unspent -because the workflow tags only after a successful upload. +Both consumer PRs are open, not merged. Note that the artifact coordinates and the generated namespace are deliberately different. The artifact publishes under `com.flipcash`; the code inside it stays in 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 266788c..0000000 --- a/scripts/verify-parity.sh +++ /dev/null @@ -1,62 +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/Payments/Generated" - if [ ! -d "$ref" ]; then - echo " SKIP: $ref not found" - else - "$ROOT/scripts/generate-swift.sh" >/dev/null || { echo " FAIL: codegen errored"; status=1; } - if /usr/bin/diff -rq "$ROOT/Sources/OCPClientProtocol" "$ref" >/tmp/vp-swift.txt 2>&1; then - echo " OK: $(find "$ref" -name '*.swift' | wc -l | tr -d ' ') file(s) identical" - 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/opencode/models/build/generated/java/generateDebugProto" - if [ ! -d "$ref" ]; then - echo " SKIP: $ref not found -- build it first with:" - echo " (cd $ANDROID && ./gradlew :definitions:opencode: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 1d056b454c4e27e0cb9026f8746516da0e1086cf 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 sections' "open, not merged" no longer holds. Drops the "Not done yet" heading; the coordinates-vs-namespace note under it is a standing fact, not an open item, so it keeps its own heading here. --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index edb10cc..bf48764 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: 263 Kotlin/Java files against @@ -129,9 +129,7 @@ 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. +## Coordinates vs namespace Note that the artifact coordinates and the generated namespace are deliberately different. The artifact publishes under `com.flipcash`; the code inside it stays in