This software allows Delegates to securely distribute and unlock scrambles to scramblers without having to go to each device and read out a password. Delegates can easily control which scramblers have access to which scramblers and see which scrambles are currently open on every device, reducing the possibility of the wrong scrambles being used at a given time. Scramblers can quickly switch between scrambles they have access to.
Delegates sign up with a login ID and password. On their dashboard, they can upload or delete scrambles, and create scrambler accounts for scramblers. One account should be created per scrambling device. From the Delegate's dashboard, the Delegate can see which scrambles are currently open, and to who. A scramble can be opened or closed to any combination of scramblers at any given time.
At the bottom of the dashboard, all scramblers are listed along with which scrambles they are looking at. This allows the Delegate to ensure that the correct scrambles are being used.
The backend is written in Crystal with the Lucky framework, which is very similar to Rails. The frontend is written in NextJS with TypeScript.
To run locally with Docker (to try it out, this is the easier option so you don't clutter your system with dependencies):
- Clone this repo:
git clone https://github.com/UnsolvedCypher/scramble-captain.git
- Install Docker and Docker Compose
- Navigate to the
scramble-captain
directory - Run
docker-compose build
- Run
docker-compose up
. You may need to wait a few moments before the app is accessible as the database needs to be built and migrated
To run locally (for development, does not work on Windows):
- Clone this repo:
git clone https://github.com/UnsolvedCypher/scramble-captain.git
- Install Docker
- Install Lucky and Postgres
- Install Node and Yarn
- Run
./start-dev.sh
You can access the site on http://localhost
.
The frontend is set up with a .eslintrc.js
file, so it is recommended that you install the ESLint extension for your IDE or text editor so that your code is linted to match the rest of the code.
I have tried to ensure that this software is as secure as possible. If you believe you have discovered a security vulnerability, please email mmcmillan@worldcubeasosciation.org and do not open an issue or otherwise disclose the potential vulnerability until you have received confirmation that it is resolved.
Authentication is handled via JWT (see SignInUser
and UserToken
classes). The JWT is valid for 12 hours and contains the user's ID, the expiration time, and whether the user is a scrambler or not. The user's scrambler status is only used for routing on the front-end, it is never relied on by the server for granting access to any resources. On the client side, the JWT is stored in a cookie (see withAuthSync.tsx
).
All data except for the scrambles themselves are stored in a Postgres database called scramble_captain_production
. The scrambles themselves are stored in assets/scrambles
and their filename corresponds to an ID of a scramble object in the database.
A scramble_access
object is created in the database whenever a scrambler is granted access to the scramble, and is deleted when access is revoked. Similarly, a competition_access
is created when a Delegate creates a competition or adds another Delegate. Keep in mind that a User
can be either a Delegate or a scrambler- having a competition_access
object is what makes the user a Delegate.
Much of the source code is automatically generated by the Lucky framework. Any differing code is found in the mixins
, models
, serializers
, actions
, and operations
directories.
- Scramblers cannot access scrambles that they have not been granted access to. This is ensured by
Api::Auth::RequireScrambleAccess.validate
- Only Delegates of the competition may add other Delegates, open/close scrambles, and create scrambler accounts. This ensured by
Api::Auth::RequireCompetitionAdmin.validate
- Protection against a compromised scrambling computer: if the computer has spyware, another user may be able to gain access to any scrambles the scrambler can access. No computer-based scramble distribution system can prevent this.
- Compromised scrambler: scramblers can take a picture, screenshot, or otherwise transmit the scramble sequence to an unauthorized person. No scramble distribution system can prevent this and Delegates must ensure that only trusted individuals are allowed to scramble.
- Scramble access revokation: once a scrambler has access to a scramble, they could save it or take a picture of it (see above point). Even after the Delegate locks access to the scramble, there is no guarantee that a scrambler doesn't have a copy of it, so any accidentally opened then closed scrambles should not be assumed to be secret. The scramble closing functionality exists merely for convenience, so the scrambler does not accidentally open a scramble that is no longer in use.
- Accuracy of Delegate's view of which scrambles are being viewed: as previously mentioned, a malicious scrambler could save a scramble and then view it outside of Scramble Captain. The list of scrambles being viewed by each scrambler is purely informational (so the Delegate can check what scrambles are still being used). It does not ensure that no other scrambles are being viewed.