A test run must not publish a credential (ios#62, Android half) #63

Merged
paulhitt merged 28 commits from fix/tests-must-not-publish-credentials into main 2026-09-04 20:49:04 +00:00
paulhitt commented 2026-09-04 17:29:39 +00:00 (Migrated from gitlab.com)

The Kotlin counterpart of the iOS fix, and Android's version of the bug was
quieter rather than absent.

Android was already ahead on the part iOS got wrong: every live suite is gated
behind assumeTrue, and LiveTarget.refuseProduction refuses a production
host outright. What it still had was the credential itself.
LiveTwoProductsTest and LiveShapesTest both carried
const val PASSPHRASE = "a-long-enough-passphrase" and used it to create
accounts on accounts.flamenet.io whenever somebody set FN_LIVE_MANAGED=1.

The gate stops it running by accident. It does not stop the password being
written down. Every account those runs ever created can be signed into by
anybody who can read this repository, and "they were throwaway accounts" does
not change that — they are real accounts on a real service and they persist
until somebody deletes them.

Both now read it from the environment through LiveTarget.passphrase() with no
fallback, and both gates assume on it being non-empty, so opting in without
configuring one reports SKIPPED rather than signing up with a published value.

And a guard, matching the Swift one: TestSafetyTest fails the build if a suite
that reaches a live relay carries a credential literal, or cannot announce a
skip. Proven by putting the literal back and watching it go red.

The guard had to be narrowed twice before it was worth keeping, and both
narrowings are recorded in it. Keying on the Live name prefix flagged
LiveTarget.kt (the helper) and LiveTargetTest.kt (a unit test of the helper).
Keying on the string "http" then flagged four suites that sign up against a
MockWebServer — which is exactly the correct way to test sign-up. The
discriminator is MockWebServer: a file that stands up a mock cannot reach
anybody. It now matches the nine real live suites and nothing else, and a test
asserts the predicate matches at least five, so the checks cannot pass by
guarding an empty set.

PARITY.md gains a Test safety section. Full JVM suite green.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

The Kotlin counterpart of the iOS fix, and Android's version of the bug was quieter rather than absent. Android was already ahead on the part iOS got wrong: every live suite is gated behind `assumeTrue`, and `LiveTarget.refuseProduction` refuses a production host outright. What it still had was the credential itself. `LiveTwoProductsTest` and `LiveShapesTest` both carried `const val PASSPHRASE = "a-long-enough-passphrase"` and used it to create accounts on accounts.flamenet.io whenever somebody set FN_LIVE_MANAGED=1. The gate stops it running by accident. It does not stop the password being written down. Every account those runs ever created can be signed into by anybody who can read this repository, and "they were throwaway accounts" does not change that — they are real accounts on a real service and they persist until somebody deletes them. Both now read it from the environment through `LiveTarget.passphrase()` with no fallback, and both gates assume on it being non-empty, so opting in without configuring one reports SKIPPED rather than signing up with a published value. And a guard, matching the Swift one: TestSafetyTest fails the build if a suite that reaches a live relay carries a credential literal, or cannot announce a skip. Proven by putting the literal back and watching it go red. The guard had to be narrowed twice before it was worth keeping, and both narrowings are recorded in it. Keying on the `Live` name prefix flagged LiveTarget.kt (the helper) and LiveTargetTest.kt (a unit test of the helper). Keying on the string "http" then flagged four suites that sign up against a MockWebServer — which is exactly the correct way to test sign-up. The discriminator is MockWebServer: a file that stands up a mock cannot reach anybody. It now matches the nine real live suites and nothing else, and a test asserts the predicate matches at least five, so the checks cannot pass by guarding an empty set. PARITY.md gains a Test safety section. Full JVM suite green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
paulhitt commented 2026-09-04 17:29:40 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt
paulhitt (Migrated from gitlab.com) changed target branch from feat/files-and-wallet-parity to main 2026-09-04 20:49:03 +00:00
paulhitt commented 2026-09-04 20:49:05 +00:00 (Migrated from gitlab.com)

mentioned in commit 10dcb53fa6

mentioned in commit 10dcb53fa6908399401bff38d309fcd312b92e0e
paulhitt (Migrated from gitlab.com) merged commit 10dcb53fa6 into main 2026-09-04 20:49:05 +00:00
paulhitt commented 2026-09-09 19:01:40 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
Sign in to join this conversation.