Parlor is a Kotlin Multiplatform party-game container for Android and iOS. It currently ships two game modules:
- Whodunit — bundled English/Arabic cases, with Classic Vote and Elimination modes.
- Mafia — a host-authoritative social-deduction game.
Both games support local play and same-LAN multi-device play through P2pKit. Desktop is a development and deterministic-test target, not a shipping target. Room-code entry uses LAN discovery; raw-IP/manual endpoint connection, public-internet rendezvous/NAT traversal, relay, spectators, and host migration are not supported in the first release. Hotspot behavior remains a device/OS/topology-specific physical release gate, not a universal promise.
The current architecture and release contracts are documented in:
docs/PRODUCTION_ARCHITECTURE.mdARCHITECTURE.md— original design historydocs/adr/0001-game-module-registration.mddocs/adr/0002-manual-endpoint-connection.mddocs/HOW_TO_ADD_A_GAME.mddocs/P2P_MANUAL_TEST.mddocs/P2P_REMEDIATION_STATUS.mddocs/P2PKIT_MAVEN_PROVENANCE.mddocs/RELEASE_GATES.mddocs/RELEASE_AUTOMATION.mddocs/PRIVACY_AND_COMPLIANCE.md
- JDK 21
- Android SDK 36 (
minSdk = 26,targetSdk = 36) - Policy-pinned Xcode for Store-qualified Apple builds (currently Xcode 26.3 build 17C529; minimum deployment target iOS 16)
- P2pKit 0.7.0-rc3 from Maven Central
The checked-in Gradle 8.13 wrapper is the build entry point.
Production and local builds resolve the pinned P2pKit modules directly from Maven Central:
io.github.apdelrahman1911:p2p-core:0.7.0-rc3
io.github.apdelrahman1911:p2p-transport-lan:0.7.0-rc3The build does not use mavenLocal(), a sibling checkout, or a repository
override. Keep both P2pKit modules on the same pinned version. Strict Gradle
dependency verification pins the reviewed release bytes; see the provenance
receipt before changing the coordinate or any checksum.
# Android device or emulator
./gradlew :composeApp:installDebug
# Desktop development target
./gradlew :composeApp:runFor iOS, open iosApp/iosApp.xcodeproj, select a local development team, and
run the app from Xcode.
# All common/desktop tests plus unsigned Android release bundle and lint
./gradlew productionCheck
# Release Kotlin frameworks for physical iOS and both simulator architectures
./gradlew productionAppleCheckThese commands prove local source and unsigned-artifact quality. Store signing,
physical two-device networking, accessibility with TalkBack/VoiceOver, store
privacy forms, and provider configuration remain explicit external gates; see
docs/RELEASE_GATES.md.
parlor/
├── build-logic/ # Gradle convention plugins
├── composeApp/ # Shared Compose app and platform entry points
├── iosApp/ # Thin Xcode wrapper
├── game-modes/
│ ├── whodunit/ # Rules, protocol adapter, UI, assets, tests
│ └── mafia/ # Rules, protocol adapter, UI, assets, tests
├── shared/
│ ├── core/ # IDs, results, time, randomness, and versioning
│ ├── design-system/ # Tokens, components, localization, motion
│ ├── engine/ # Generic game contracts and registry
│ ├── engine-testing/ # Non-shipping extensibility fixture
│ ├── session/ # Local and host-authoritative session logic
│ ├── networking/ # Versioned transport-independent protocol
│ ├── transport-p2p/ # The only P2pKit adapter
│ ├── content/ # Bundled offline content and validation
│ └── storage/ # Settings and protected snapshots
└── docs/ # Rules, ADRs, test matrices, release runbooks
Game modules do not import P2pKit. Discovery, admission, reconnect, ordering, deduplication, and terminal behavior belong to shared session/networking code. The non-shipping second-game fixture proves that a definition can be registered and exercised without changing that networking core.