The skill's detector scored the README, PARITY.md and the extracted
comment prose. Fixed what it flagged: hollow intensifiers, "in order
to", "additionally", "the whole point", bold sentences in docs, and
bold that had wrapped across comment lines. Comment prose scores a
maximum of 4 out of 100 across the repo.
One sweep rule mangled four comments ("which is the entire point of X"
lost its clause); repaired, and the rule now keeps the clause.
Comments and strings only. 1208 tests pass, counted from the XML.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
73 lines
3.1 KiB
Markdown
73 lines
3.1 KiB
Markdown
# Contributing
|
|
|
|
The Android client for Flamenet Messenger, in Kotlin and Compose. Three modules:
|
|
`engine` (the encryption primitives), `client` (protocol and transport), `app`
|
|
(UI). Feature parity with iOS is tracked in [PARITY.md](PARITY.md), read it
|
|
before assuming something is missing by accident.
|
|
|
|
## Security bugs do not go in an issue
|
|
|
|
Email **security@flamenetmessenger.com**. See [SECURITY.md](SECURITY.md).
|
|
|
|
## Building
|
|
|
|
JDK 21 and the Android SDK. On a machine with no default Java, which is the
|
|
usual state of a Mac. Gradle reports "Unable to locate a Java Runtime" rather
|
|
than anything about JDKs, so set it explicitly:
|
|
|
|
```bash
|
|
export JAVA_HOME=/opt/homebrew/opt/openjdk@21
|
|
export ANDROID_HOME=$HOME/Library/Android/sdk
|
|
./gradlew :engine:test :client:test :app:testDebugUnitTest
|
|
```
|
|
|
|
Those three suites are the merge gate.
|
|
|
|
JVM crypto tests prove nothing about Android. The JVM's JCA and Android's
|
|
Conscrypt are different providers with different opinions. X25519/X448 need DER
|
|
key specs and API 33 on device, and code that passes `:engine:test` on the JVM
|
|
can throw on a handset. Anything touching key agreement or signatures needs an
|
|
instrumented test, which is why `interop/` exists.
|
|
|
|
Instrumented tests are not in the gate: they need an emulator and a local relay.
|
|
|
|
## What a change needs
|
|
|
|
- **Touching the wire?** iOS and the relay move with you. A field this client
|
|
required and the relay never sent broke groups completely while every unit
|
|
test stayed green. **Diff the wire types first.**
|
|
- **Touching state that arrives incrementally**: avatars, rosters, device
|
|
lists, merge, never replace. Absent from a fetch means "not loaded yet", not
|
|
"deleted".
|
|
- **Touching WebRTC callbacks?** Never let an exception escape one. It does not
|
|
surface as a caught error, it `SIGABRT`s the process. Calls have crashed this
|
|
app twice that way.
|
|
- **Adding a permission?** Declare it *and* verify on device. A missing
|
|
`ACCESS_NETWORK_STATE` presented as a dead button, not as a permission error.
|
|
- **Writing KDoc that mentions a path like `/e2e/*`?** Kotlin does not nest
|
|
block comments, so `*/` inside one closes it and the compiler reports
|
|
"Unclosed comment" at the end of the file, hundreds of lines from the cause.
|
|
|
|
## Releases
|
|
|
|
The signed release APK is built with a keystore that is **not in this
|
|
repository and never will be**, it is public. Signing keys are permanent for
|
|
the life of an installed app: a key change means every existing user must
|
|
uninstall and lose their local history, so the certificate identity is not
|
|
something to fix later.
|
|
|
|
## House rules
|
|
|
|
- Fail closed. Unverifiable signatures, unknown versions and unpinned identities
|
|
are refusals, and the user is told which.
|
|
- Never log message contents, keys, or tokens.
|
|
- No secrets, keystores, or passphrases in the repository.
|
|
- Match the surrounding style. Comments explain why a line exists, usually,
|
|
which attack or which platform quirk it accounts for.
|
|
|
|
## Comments and prose
|
|
|
|
Plain text. No emoji or symbol markers, no markdown bold inside code comments,
|
|
no em-dashes. Say what the code does and why, briefly; the history of how it
|
|
got that way belongs in the commit message, not in the file.
|