# Code Submission This project is a Leptos + Axum app for a multi-step code submission challenge. It exposes a small web UI where users enter a code, accepts challenge submissions for valid codes, and can toggle the server between offline and live mode for SMS-driven challenge flow testing. ## Overview The app supports: - A home page for entering challenge codes. - A `/submit/:code` route that validates supported codes. - A `/manage` page to toggle the server between live and offline states. - A `/history` page for successful submission records. - A protected `POST /event/buzz` endpoint for challenge code 1, which validates a secret and timing window. - TextBee SMS notifications when the server is live. This repository is not a generic template anymore; it is a working challenge server with specific code-handling behavior and operational configuration. ## Project structure ```text . ├── Cargo.toml ├── README.md ├── dev.env ├── LICENSE ├── end2end/ │ ├── package.json │ ├── playwright.config.ts │ └── tests/ ├── public/ │ ├── challenge3.txt │ ├── challenge3_annotated.txt │ └── favicon.ico ├── src/ │ ├── app.rs │ ├── lib.rs │ ├── main.rs │ ├── manage.rs │ ├── secrets.rs │ └── codes/ │ ├── code1.rs │ ├── code2.rs │ ├── code5.rs │ ├── history.rs │ └── mod.rs ├── style/ │ └── main.scss └── target/ ``` ## Features ### Code 1 Code 1 is the timed buzz challenge. It accepts a `POST /event/buzz` request with: ```json { "delay_ms": 6388, "secret": "" } ``` Behavior: - `delay_ms` must be a non-negative integer. - `secret` must match `CODE1_SECRET` exactly. - The request is only accepted in the `America/Chicago` window from 11:00 AM to 1:30 PM inclusive. - The server computes the signed delta from the target of `6430 ms`. - Deltas outside the inclusive range `-500` to `+500` are rejected and ignored. - Valid submissions return HTTP `202`. - When live, the app sends SMS notifications via TextBee to the configured recipients. - When offline, it logs the planned SMS actions instead. The challenge text includes the literal strings `CHALLENGE_1_FIRST` and `CHALLENGE_1_SECOND`, which are sent to the configured recipients once the buzz is accepted. ### Code 2 The code value is `QJ4EAN` and is case-insensitive. On successful submission: - It records the success in the submission history. - If the server is live, it sends a TextBee SMS to `RECIPIENT_SELF`. - If the server is offline, it logs the notification instead. ### Code 5 The code value is `V7MK2P` and is case-insensitive. On successful submission: - It records the success in the submission history. - If the server is live, it sends a TextBee SMS to `RECIPIENT_SELF`. - If the server is offline, it logs the notification instead. - It shows a completion message without providing a download. ## Getting started ### Prerequisites You need Rust, the Leptos toolchain, and the project dependencies. If you do not have `cargo-leptos` installed: ```bash cargo install cargo-leptos --locked ``` If you need the additional tooling required by cargo-leptos: ```bash rustup toolchain install nightly --allow-downgrade rustup target add wasm32-unknown-unknown cargo install cargo-generate npm install -g sass ``` Then install the end-to-end test dependencies: ```bash cd end2end npm install ``` ### Environment configuration Copy the sample environment file to `.env` before starting the app: ```powershell Copy-Item dev.env .env ``` The app loads `.env` automatically at startup and validates the required values. The expected settings are defined in `src/secrets.rs` and include: - `DEV_SECRET_KEY` — required for admin actions such as toggling live/offline mode and accessing submission history. - `TEXTBEE_API_KEY` — required for sending SMS via TextBee. - `TEXTBEE_DEVICE_ID` — optional, selects a specific paired device. - `RECIPIENT_SELF`, `RECIPIENT_1`, `RECIPIENT_2` — each must be a valid E.164 phone number. - `CODE1_SECRET` — required and must be at least 32 bytes long. - `PROD` — set to `true` to start the server in the live state. Truthy values are `1`, `true`, `yes`, and `on` (case-insensitive); any other value starts the server offline. Do not commit secrets or expose them in client-side code. ### Run the app ```bash cargo leptos watch ``` Then open the local app in your browser as directed by cargo-leptos. ## Management and admin flow The app includes a status management page at `/manage`. - It shows whether the server is currently live. - It lets an operator toggle the server status. - It requires the configured `DEV_SECRET_KEY` before changing state. This is how the system can be transitioned between testing/offline and live challenge operation without exposing the settings publicly. ## Challenge testing ### Test Code 1 with curl With the server running locally and `CODE1_SECRET` set in your shell: ```sh curl.exe -X POST http://127.0.0.1:3000/event/buzz -H "Content-Type: application/json" -d '{"delay_ms":6388,"secret":""}' ``` The server calculates `6388 - 6430 = -42` ms, and a valid request returns HTTP `202`. ### Test Code 1 with Postman Create a `POST` request to `http://127.0.0.1:3000/event/buzz`, select Body > raw > JSON, and send: ```json { "delay_ms": 6388, "secret": "" } ``` ### Test Code 1 with Node.js ```javascript async function main() { const delayMs = 6388; const secret = process.env.CODE1_SECRET; if (!secret) throw new Error("CODE1_SECRET is not set"); const response = await fetch("http://127.0.0.1:3000/event/buzz", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ delay_ms: delayMs, secret }), }); console.log(response.status, await response.text()); } main().catch((error) => { console.error(error); process.exitCode = 1; }); ``` When the server is live, a successful test event sends the configured TextBee SMS to the configured recipients. When it is offline, it logs the action instead. ## Build, test, and release ### Compile for release ```bash cargo leptos build --release ``` This will generate the server binary in `target/release` and the site bundle in `target/site`. ### End-to-end tests ```bash cargo leptos end-to-end ``` ```bash cargo leptos end-to-end --release ``` Cargo-leptos uses Playwright for browser tests and the test files are under `end2end/tests`. ## Remote deployment without the Rust toolchain After running `cargo leptos build --release`, the minimum files needed are: 1. The server binary in `target/server/release` 2. The `site` directory and all files inside it in `target/site` Copy these files to your remote server. The expected directory structure is: ```text code_submission site/ ``` Set the appropriate environment variables before starting the binary: ```sh export LEPTOS_OUTPUT_NAME="code_submission" export LEPTOS_SITE_ROOT="site" export LEPTOS_SITE_PKG_DIR="pkg" export LEPTOS_SITE_ADDR="0.0.0.0:3000" export LEPTOS_RELOAD_PORT="3001" ``` Then run the server binary. ## Licensing This project is released under the repository's existing license. The default template license is present in `LICENSE`, and you should replace it with an appropriate license if you intend to distribute this project publicly.