diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aeec26f..535c45f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,8 +11,8 @@ on: - "**.md" env: - GO_VERSION: "1.21.3" # https://go.dev/dl/ - GOLANGCI_LINT_VERSION: "v1.55.1" # https://github.com/golangci/golangci-lint/releases + GO_VERSION: "1.21.4" # https://go.dev/dl/ + GOLANGCI_LINT_VERSION: "v1.55.2" # https://github.com/golangci/golangci-lint/releases jobs: lint: @@ -29,6 +29,14 @@ jobs: skip-cache: true working-directory: ./ios/server + security: + runs-on: ubuntu-latest + steps: + - uses: golang/govulncheck-action@v1 + with: + go-version-input: ${{ env.GO_VERSION }} + work-dir: ./ios/server + build: runs-on: ubuntu-latest steps: diff --git a/backend/readme.md b/backend/readme.md new file mode 100644 index 0000000..33702e2 --- /dev/null +++ b/backend/readme.md @@ -0,0 +1,62 @@ +# Backend Challenge + +This challenge is part of the backend hiring process at [Heart +Hands](https://hearthands.tech/). + +## Why this challenge? + +Heart Hands is operating with a small team of dedicated & talented people. We +are looking for seasoned engineers with a deep technical knowledge, strong +understanding of their technical stack, and excellent product intuitions to join +our team. + +This exercise has been designed to give a glimpse of what it is like to build a +messaging app, and the kind of technical challenges we face and care about. We +are expecting you to spend between 4 and 6 hours on this challenge. + +## Instructions + +You are tasked with the server-side implementation of a messaging app that +allows clients to send and receive text messages in private 1:1 chats. + +We enforce no technical constraints: you are free to choose the language, data +layer, network protocol, and design your API as you see fit. You are +purposefully being given a lot of freedom here, and you will not be judged on +these decisions alone, but we will challenge the understanding of the trade-offs +you make. + +Functional requirements: + +- [ ] Clients should be able to uniquely identify themselves with a phone number + (without authentication) +- [ ] Clients should be able to send messages to other clients via their phone + numbers +- [ ] Clients should be able to list their chats +- [ ] Clients should be able to list all messages in a chat + +## Bonus + +Some topics that we find interesting to dig: + +- [ ] Choose a network protocol that enables soft real-time message delivery to the clients +- [ ] Make the server message ingestion idempotent +- [ ] Add support for sent/delivered/read message status +- [ ] Add support for chats and messages pagination +- [ ] Implement SMS phone number verification to authenticate the clients +- [ ] Support SMS forwarding to relay the messages to the clients phone numbers + +## Challenge Review + +We know you only have a limited time alloted to deliver this challenge, and thus +will have to prioritize what you work on. A few things that are important for us +and that will be considered during the review: +- **documentation**: is the readme clear? are important parts of the code + documented? +- **impact**: which features did you prioritize? +- **maintainability**: is the code well-structured and easy to read/evolve? +- **robustness**: is the code tested or easily testable? are edge-cases + considered? is static analysis leveraged? + +*** + +Good luck, and enjoy! diff --git a/ios/readme.md b/ios/readme.md index 5d5a713..575ee6a 100644 --- a/ios/readme.md +++ b/ios/readme.md @@ -5,42 +5,41 @@ Hands](https://hearthands.tech/). ## Why this challenge? -Heart Hands is operating with a small team of dedicated and talented people. We +Heart Hands is operating with a small team of dedicated & talented people. We are looking for seasoned engineers with a deep technical knowledge, strong -understanding of their technical stack, and good product intuitions to join our -team. +understanding of their technical stack, and excellent product intuitions to join +our team. -This challenge has been designed to give a glimpse of what it is like to build a +This exercise has been designed to give a glimpse of what it is like to build a messaging app, and the kind of technical challenges we face and care about. We -are expecting you to spend no more than 48 hours on this. +are expecting you to spend between 4 and 6 hours on this challenge. -## Summary +## Instructions -You are tasked to develop a messaging app that allows to send and receive -messages with several bots, each in their own chat. +You are tasked with the implementation of an iOS messaging app that allows to +communicate (send and receive text messages) with bots, each in their own 1:1 +chat. -A server is available for you to use, you can read more about it in -[`./server`](./server). The documentation contains informations on how it can be -run and what kinds of API endpoints are available. +A server is available for you to use. You can read more about it in +[`./server`](./server). Its documentation contains informations on how it can be +run, and what kinds of API endpoints & entities are available. -## Requirements - -What are we expecting you to build? +Functional requirements: - [ ] The app should start on a screen showing the list of all chats - [ ] The app should allow opening each chat individually - [ ] The app should allow sending messages to a chat - [ ] The app should reflect the messages sent to and received from the server +- [ ] The app should be resilient to bad network conditions (drops & timeouts) ## Bonus -What could be implemented to improve the UX? +Some topics that we find interesting to dig: - [ ] Make the app work offline (both for app state and sending) -- [ ] Make the app resilient to bad network conditions (retries & timeouts) - [ ] Make the app idempotent in regards to what you send and receive - [ ] Integrate a splashscreen to hide chats while the app is loading -- [ ] Add support for optimisic sending to give instantaneity in the UI +- [ ] Add support for optimistic sending to give instantaneity in the UI - [ ] Add support for a local read/unread indicator - [ ] Avoid block changing states so the app feels fluid & snappy - [ ] Make the app compatible to run on iPad and macOS @@ -49,8 +48,23 @@ What could be implemented to improve the UX? ## Design -We have prepared a design to help you during this challenge. +We have prepared a design to help you during this challenge. You will also +receive the Figma link along with the challenge instructions. ![design](./design.png) +## Challenge Review + +We know you only have a limited time alloted to deliver this challenge, and thus +will have to prioritize what you work on. A few things that are important for us +and that will be considered during the review: +- **documentation**: is the readme clear? are important parts of the code + documented? +- **impact**: which features did you prioritize? +- **maintainability**: is the code well-structured and easy to read/evolve? +- **robustness**: is the code tested or easily testable? are edge-cases + considered? is static analysis leveraged? + +*** + Good luck, and enjoy! diff --git a/ios/server/go.mod b/ios/server/go.mod index 0679b65..2ee7061 100644 --- a/ios/server/go.mod +++ b/ios/server/go.mod @@ -1,16 +1,16 @@ module github.com/hearthands/challenges/ios/server -go 1.21.3 +go 1.21.4 require ( github.com/go-chi/chi/v5 v5.0.10 github.com/go-chi/render v1.0.3 github.com/r3labs/sse/v2 v2.10.0 - golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa ) require ( github.com/ajg/form v1.5.1 // indirect - golang.org/x/net v0.0.0-20191116160921-f9c825593386 // indirect + golang.org/x/net v0.18.0 // indirect gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect ) diff --git a/ios/server/go.sum b/ios/server/go.sum index 21fbe0f..f20900c 100644 --- a/ios/server/go.sum +++ b/ios/server/go.sum @@ -16,8 +16,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/net v0.0.0-20191116160921-f9c825593386 h1:ktbWvQrW08Txdxno1PiDpSxPXG6ndGsfnJjRRtkM0LQ= golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= diff --git a/ios/server/main.go b/ios/server/main.go index a97f709..7457c45 100644 --- a/ios/server/main.go +++ b/ios/server/main.go @@ -21,9 +21,9 @@ import ( ) var ( - hostname = envOrDefault("HOSTNAME", "localhost") // hostname used by the server - port = envOrDefault("PORT", "3000") // port used by the server - limit = 100 // maximum number of entities returned in a single request + hostname = envOrDefault("HTTP_HOST", "localhost") // hostname used by the server + port = envOrDefault("PORT", "3000") // port used by the server + limit = 100 // maximum number of entities returned in a single request ) //go:embed data.json diff --git a/ios/server/readme.md b/ios/server/readme.md index 68807ec..087daac 100644 --- a/ios/server/readme.md +++ b/ios/server/readme.md @@ -1,11 +1,11 @@ # iOS Challenge - Server Companion This server is used as a companion for the iOS challenge. Persistence is -in-memory, restarting the server will reset its state. +in-memory, and restarting the server will reset its state. The server will sometime be a bit capricious, you might observe: - failure to receive a response -- server timing out when trying to send a message +- timeouts when trying to send a message - duplicate events being received in the messages stream When that happens, you should retry and react accordingly. @@ -13,11 +13,24 @@ When that happens, you should retry and react accordingly. ## How to start the server? 1. You need to install Go on your system: follow the [official documentation](https://go.dev/doc/install) -2. Then execute the command: `go run .` +2. Then, execute the command: `go run .` + +## How to make the server reachable from another machine? + +You might want to allow the server to be reached from another machine +(simulator or a phone for example). One way to do that is to use [ngrok](). + +1. You need to install Ngrok on your system: follow the [official + documentation](https://ngrok.com/download) +2. Then, after having started the server (see above), execute the command: `ngrok http 3000` + +This will give you a public URL of the form +`https://9f98-62-194-145-77.ngrok.io`, that can be used to reach your server +from any system that has an internet connection. ## API Documentation -This API exposes a few HTTP endpoints, and an SSE stream. It allows to list +This API exposes a few HTTP endpoints and an SSE stream. It allows to list chats, and read & write messages. ### Notes diff --git a/readme.md b/readme.md index 7173f0a..6789894 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@ # Challenges [![ci status](https://github.com/hearthandsinc/challenges/actions/workflows/ci.yml/badge.svg)](https://github.com/hearthandsinc/challenges/actions/workflows/ci.yml) This repository contains the [Heart Hands](https://hearthands.tech/) engineering -challenges for [iOS](./ios) and _backend (soon)_. +challenges for [iOS](./ios) and [backend](./backend) positions. ## Feedbacks