···11+# Step 1: Protect your code
22+33+It's been a busy month at Mergington High! Your simple website for managing extra-curricular activities has really taken off. What started as a basic sign-up form for a few activities has grown into the go-to place for half the school activities. 📚✨
44+55+Principal Martinez was so impressed with your work that they announced at the last staff meeting that ALL clubs should start using the website. While this is exciting, you're a bit nervous - the last thing you want is an accidental change breaking the system right before the big Fall Activities Fair! 😰
66+77+When more teachers start helping with the Mergington High activities website, it's important to add some safeguards. Thankfully, GitHub provides several ways to protect your repository:
88+99+1. **Repository Rulesets** - These provide safeguards to limit:
1010+1111+ - Pushing code directly to important branches
1212+ - Deleting or renaming branches
1313+ - Force pushing (which can overwrite history)
1414+ - (and much more)
1515+1616+1. **`.gitignore`** - This special file tells Git which files it should NOT track, like:
1717+1818+ - Temporary files that your code creates while running
1919+ - Secret configuration files with sensitive information
2020+ - System files that other developers don't need
2121+2222+> [!TIP]
2323+> Think of these settings like the editorial process of a school yearbook. Various student committees will take photos and write articles, then the yearbook president will make adjustments to make sure everything flows together properly. Finally, a teacher/advisor will sign off that all content is appropriate.
2424+2525+## ⌨️ Activity: (optional) Get to know our extracurricular activities site
2626+2727+<details>
2828+<summary>Show Steps</summary>
2929+3030+In other exercise, we have been developing the Extracurricular activities website. You can follow these steps to start up the development environment and try it out.
3131+3232+> ! **Important:** Opening a development environment and running the application is not necessary to complete this exercise. You can skip this activity if desired.
3333+3434+1. Right-click the below button to open the **Create Codespace** page in a new tab. Use the default configuration.
3535+3636+ [](https://codespaces.new/{{full_repo_name}}?quickstart=1)
3737+3838+1. Wait some time for the environment to be prepared. It will automatically install all requirements and services.
3939+4040+1. Validate the **GitHub Copilot** and **Python** extensions are installed and enabled.
4141+4242+ <img width="300" alt="copilot extension for VS Code" src="https://github.com/user-attachments/assets/ef1ef984-17fc-4b20-a9a6-65a866def468" /><br/>
4343+ <img width="300" alt="python extension for VS Code" src="https://github.com/user-attachments/assets/3040c0f5-1658-47e2-a439-20504a384f77" />
4444+4545+1. Try running the the application. In the left sidebar, select the **Run and Debug** tab and then press the **Start Debugging** icon.
4646+4747+ <details>
4848+ <summary>📸 Show screenshot</summary><br/>
4949+5050+ <img width="300" alt="run and debug" src="https://github.com/user-attachments/assets/50b27f2a-5eab-4827-9343-ab5bce62357e" />
5151+5252+ </details>
5353+5454+ <details>
5555+ <summary>🤷 Having trouble?</summary><br/>
5656+5757+ If the **Run and Debug** area is empty, try reloading VS Code: Open the command palette (`Ctrl`+`Shift`+`P`) and search for `Developer: Reload Window`.
5858+5959+ <img width="300" alt="empty run and debug panel" src="https://github.com/user-attachments/assets/0dbf1407-3a97-401a-a630-f462697082d6" />
6060+6161+ </details>
6262+6363+1. Use the **Ports** tab to find the webpage address, open it, and verify it is running.
6464+6565+ <details>
6666+ <summary>📸 Show screenshot</summary><br/>
6767+6868+ <img width="350" alt="ports tab" src="https://github.com/user-attachments/assets/8d24d6b5-202d-4109-8174-2f0d1e4d8d44" />
6969+7070+ 
7171+7272+ </details>
7373+7474+</details>
7575+7676+## ⌨️ Activity: Add a branch ruleset
7777+7878+To get started, let's add some protections so that no one accidentally breaks the club registration system.
7979+8080+1. If necessary, open another tab and navigate to this repository. We will start on the **Settings** tab.
8181+8282+1. In the left navigation, expand the **Rules** area and select **Rulesets**.
8383+8484+1. Click the **New ruleset** dropdown and select **New branch ruleset**.
8585+8686+ <img width="250" alt="image" src="https://github.com/user-attachments/assets/1e9fd519-1421-4d6b-b654-a3fe53a8fb75" />
8787+8888+1. Set the **Ruleset Name** as `Protect main` and change the **Enforcement status** to `Active`.
8989+9090+ <img width="250" alt="image" src="https://github.com/user-attachments/assets/ce30fd34-39b5-4e22-b348-4af61fd05cd1" />
9191+9292+1. Find the the **Targets** section and use the **Add target** dropdown to add 2 entries:
9393+9494+ 1. Add the **Include default branch** option to ensure protections aren't bypassed by switching the default branch.
9595+9696+ <img width="250" alt="image" src="https://github.com/user-attachments/assets/217263cc-d5c2-4ac0-b03c-a72494e5c812" />
9797+9898+ 1. Use the **include by pattern** option and enter the pattern `main`.
9999+100100+ <img width="250" alt="image" src="https://github.com/user-attachments/assets/968c9ed8-b051-44eb-af42-d99670ad31fd" />
101101+102102+ <img width="250" alt="image" src="https://github.com/user-attachments/assets/ddc52767-d93e-4c9e-a77a-90c3b5c08fb5" />
103103+104104+1. Find the **Rules** section and ensure the following items are checked.
105105+106106+ - [x] Restrict deletions
107107+ - [x] Require a pull request before merging
108108+ - Required approvals: `0`
109109+ - [x] Require review from Code Owners
110110+ - [x] Block force pushes
111111+112112+1. Scroll to the bottom and click the **Create** button to save the ruleset.
113113+114114+## ⌨️ Activity: Create a `.gitignore` file
115115+116116+We know many teachers use different tools, so let's make sure they don't accidentally commit unnecessary files.
117117+118118+1. At the top navigation, return to the **Code** tab ane verify you are on the `main` branch.
119119+120120+1. Above the list of files, click the **Add file** dropdown and select **Create new file**.
121121+122122+ <img width="300" alt="New file button" src="https://github.com/user-attachments/assets/8f3f8da8-1471-485a-9df5-8c03ecba2d8e"/>
123123+124124+1. Enter the file name `.gitignore`. We will ignore the template selector for now and make our own. Copy the below example content into it.
125125+126126+ <img width="350" alt="preview of new file" src="https://github.com/user-attachments/assets/580d1a63-a264-4d44-8901-50ad708b8822"/>
127127+128128+ ```gitignore
129129+ # Python backend for club management
130130+ __pycache__/
131131+ *.py[cod] # Python compiled files
132132+ *$py.class
133133+ *.so
134134+ .Python
135135+ env/
136136+ .env # Where database passwords are stored
137137+ venv/ # Virtual environment for testing
138138+ .venv
139139+140140+ # Teacher IDE settings
141141+ .vscode/ # Ms. Rodriguez uses VS Code
142142+ .idea/ # Mr. Chen uses PyCharm
143143+144144+ # Local development & testing
145145+ instance/
146146+ .pytest_cache/
147147+ .coverage # Test coverage reports
148148+ htmlcov/
149149+150150+ # Staff computer files
151151+ .DS_Store # For teachers with Macs
152152+ Thumbs.db # For teachers with Windows
153153+ ```
154154+155155+1. In the top right, select the **Commit changes...** button. Notice that it won't let us commit to the `main` branch! Our ruleset is working! Nice!
156156+157157+ <img width="400" alt="image" src="https://github.com/user-attachments/assets/4e85948d-75c8-4c13-8ddd-4707bf9b0805" />
158158+159159+1. Enter `prepare-to-collaborate` for the branch name then click the **Propose changes** button. You will be forwarded to a new page to start a new pull request.
160160+161161+1. Set the title to `Prepare to collaborate` and click the **Create pull request** button. **Do NOT merge yet**, since we will be adding more collaboration related changes.
162162+163163+1. With the file committed, wait a moment for Mona to check your work, provide feedback, and share the next lesson.
164164+165165+> [!TIP]
166166+> GitHub and the community have built a repository with [sample `.gitignore` files](https://github.com/github/gitignore) for many situations. Make sure to check it out!
167167+168168+<details>
169169+<summary>🤷 Having trouble?</summary><br/>
170170+171171+Make sure you pushed the `.gitignore` file to `prepare-to-collaborate` branch. Exact naming for both matters!
172172+173173+</details>
···11+# Step 2: Prepare to collaborate
22+33+Your simple school website has become quite popular! After showing it at the last staff meeting, Ms. Rodriguez from the Art Club and Mr. Chen from the Chess Club came up to you super excited. They have tons of ideas for new features!
44+55+- Ms. Rodriguez wants to add a photo gallery
66+- Mr. Chen dreams of adding a tournament bracket system for the chess/sports activities! 🎨♟️
77+88+While you're thrilled about their enthusiasm, you realize you need to set up some guidelines before letting them start changing code. The last thing you want is conflicting changes breaking the registration system right before spring break!
99+1010+Opening your project to other teachers at Mergington High means thinking about how everyone will collaborate together without breaking each other's code.
1111+1212+**Collaborators** are the people you have granted write access to the project through repository settings.
1313+1414+- Provide other people permissions to change project files while still protecting repository settings.
1515+- Personal repositories have simple permissions. Organization repositories allow flexible permissions such as read, write, maintain, and admin.
1616+1717+To help with collaboration, GitHub provides two special files:
1818+1919+1. **`CONTRIBUTING.md` file** - A "How to Help" guide. Some example content:
2020+2121+ - How to prepare a developer setup of the extra-curricular activities website.
2222+ - The process for suggesting changes.
2323+ - The project's coding style preference, to keep things consistent.
2424+ - How to ask for help when stuck.
2525+2626+1. **`CODEOWNERS` file** - Assign specific people or teams responsible for a portion of the project.
2727+2828+ - When someone creates a pull request, GitHub will automatically ask the right person to review it.
2929+3030+## ⌨️ Activity: Create a welcoming contribution guide
3131+3232+The IT Club meeting is tomorrow, and you need to prepare for Ms. Rodriguez and Mr. Chen to join the project. Let's start a document to help them contribute effectively.
3333+3434+1. At the top navigation, return to the **Code** tab. Ensure you are on the `prepare-to-collaborate` branch.
3535+3636+ <img width="265" alt="image showing the correct branch" src="https://github.com/user-attachments/assets/bd12d0cc-0920-4158-9e96-e3a8fb994c1a" />
3737+3838+1. In the top directory, create a new file called `CONTRIBUTING.md` (case sensitive).
3939+4040+1. Add a welcoming message.
4141+4242+ ```md
4343+ # Contributing to the Mergington High Extra-Curricular Activities Website
4444+4545+ Thank you for your interest in helping improve our school's website!
4646+ Whether you want to add your club's activities, fix a bug, or suggest
4747+ new features, this guide will help you get started. 🎉
4848+ ```
4949+5050+1. Add instructions to help teachers quickly start developing.
5151+5252+ ```md
5353+ ## Development Setup
5454+5555+ 1. Clone the repository to your computer.
5656+ 2. Install Python requirements: `pip install -r requirements.txt`.
5757+ 3. Run the development server: `python src/app.py`.
5858+ 4. Visit http://localhost:8000 in your browser to see the website.
5959+6060+ ## Making Changes
6161+6262+ 1. Create a new branch for your changes.
6363+ - Use descriptive names like `art-gallery-feature` or `fix-chess-signup`
6464+ 2. Make your changes and test them locally with sample student data.
6565+ - Use the MongoDB extension to preview the included sample date.
6666+ 3. Push your branch and create a pull request.
6767+ 4. Wait for review and address any feedback.
6868+6969+ ## Code Style
7070+7171+ - Follow PEP 8 for Python code (backend).
7272+ - Use clear, descriptive variable names (student_name, start_time, etc.)
7373+ - Add comments to describe blocks of logic.
7474+ ```
7575+7676+1. Add a section for getting help.
7777+7878+ ```md
7979+ ## Need help or have ideas?
8080+8181+ - Check the open issues first.
8282+ - If your problem is there, add a comment or up-vote.
8383+ - If not there, create a new issue. Be as descriptive as possible.
8484+ - Ask in our weekly IT Club office hours (Thursdays at lunch in Room 203).
8585+ - For other general problems, email the tech team at techclub@mergingtonhigh.example.edu
8686+ ```
8787+8888+1. In the top right, use the **Commit changes...** button and commit your changes directly to `prepare-to-collaborate` branch.
8989+9090+## ⌨️ Activity: Assign code ownership
9191+9292+With others joining the fun, you want to stay involved on anything affecting architecture and core functionality. Let's assign you to the related files.
9393+9494+1. At the top navigation, return to the **Code** tab. Ensure you are on the `prepare-to-collaborate` branch.
9595+9696+1. In the top directory, create a new file called `CODEOWNERS` (case sensitive and no extension).
9797+9898+1. Add the following content:
9999+100100+ ```codeowners
101101+ # Core functionality - changes here should be rare!
102102+ /src/app.py @{{ login }}
103103+ /src/backend/database.py @{{ login }}
104104+ /src/backend/routers/auth.py @{{ login }}
105105+106106+ # The frontend will need refactored soon to be more object oriented.
107107+ /src/static/ @{{ login }}
108108+ ```
109109+110110+1. In the top right, use the **Commit changes...** button and commit your changes directly to `prepare-to-collaborate` branch.
111111+112112+1. With the files committed, wait a moment for Mona to check your work, provide feedback, and share the next lesson.
113113+114114+## ⌨️ Activity: (Optional) Add your first collaborator
115115+116116+Ready to let your colleague start working on that photo gallery feature? Let's do it!
117117+118118+> [!IMPORTANT]
119119+> This step is optional because it requires another person with a GitHub account to participate.
120120+121121+1. In the top navigation, select the **Settings** tab.
122122+123123+1. In the left navigation, select **Collaborators**.
124124+125125+1. Find the **Manage access** area and click the **Add people** button.
126126+127127+ <img width="350" alt="" src="https://github.com/user-attachments/assets/686c32c6-11c2-4e69-bad1-39062d5b4376" />
128128+129129+1. Enter a friend/colleague's GitHub username or email then press the **Add to repository** button.
130130+131131+ <img width="350" alt="" src="https://github.com/user-attachments/assets/d0eaf344-baf0-4a9c-9291-c11e7a9fdaa3" />
132132+133133+> [!IMPORTANT]
134134+> Personal repositories only have one collaboration role type. A "collaborator" receives **write** permissions but NOT **admin** permissions. If you need finer permissions, consider starting a free [organization](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/about-organizations) and assigning [repository roles](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/repository-roles-for-an-organization).
···11+# Step 3: Foster healthy growth
22+33+With so many eager contributors, Principal Martinez pulled you aside after morning announcements: "Your website is becoming critical school infrastructure! We need to make sure it grows in a healthy way as more teachers join. Can you add some guidelines to keep everything organized?"
44+55+As your extra-curricular activities website grows, you'll need more than just technical protections and contribution guides. You'll also have to encourage healthy and constructive communication.
66+77+Let's look at a couple ways to do that:
88+99+1. **Code of Conduct** - This document sets expectations for how community members should interact. Think of it like the Student Handbook at Mergington High - it outlines respectful behavior, how to report non-technical problems, and consequences for violations.
1010+1111+2. **Issue Templates** - These provide structure when someone reports a problem or suggests a new feature. They can help the community effectively communicate their needs for new features and provide enough information to solve bugs.
1212+1313+## ⌨️ Activity: Set expectations with a Code of Conduct
1414+1515+Let's start by establishing some community guidelines for your growing team of teacher-contributors.
1616+1717+> [!TIP]
1818+> The [Contributor Covenant](https://www.contributor-covenant.org/) is a popular code of conduct used by many projects.
1919+2020+1. At the top navigation, return to the **Code** tab. Ensure you are on the `prepare-to-collaborate` branch.
2121+2222+1. In the top directory, create a new file called `CODE_OF_CONDUCT.md` (case sensitive).
2323+2424+1. Add the following content:
2525+2626+ ```markdown
2727+ # Mergington High School Code of Conduct
2828+2929+ ## Our Pledge
3030+3131+ In the interest of fostering an open and welcoming environment for
3232+ our school community, we as contributors and maintainers pledge to
3333+ make participation in the Extra-Curricular Activities project a
3434+ respectful and harassment-free experience for everyone.
3535+3636+ ## Our Standards
3737+3838+ Examples of behavior that contributes to creating a positive environment include:
3939+4040+ - Using welcoming and inclusive language
4141+ - Being respectful of differing viewpoints and experiences
4242+ - Gracefully accepting constructive criticism
4343+ - Focusing on what is best for the students and the school community
4444+ - Showing empathy towards other community members
4545+4646+ Examples of unacceptable behavior include:
4747+4848+ - The use of inappropriate language or imagery
4949+ - Trolling, insulting comments, and personal attacks
5050+ - Public or private harassment
5151+ - Publishing others' private information without explicit permission
5252+ - Other conduct which could reasonably be considered inappropriate in a school setting
5353+5454+ ## Responsibilities
5555+5656+ Project maintainers are responsible for clarifying the standards of
5757+ acceptable behavior and are expected to take appropriate and fair
5858+ corrective action in response to any instances of unacceptable behavior.
5959+6060+ Project maintainers have the right and responsibility to remove, edit,
6161+ or reject comments, commits, code, issues, and other contributions that
6262+ are not aligned to this Code of Conduct.
6363+6464+ ## Scope
6565+6666+ This Code of Conduct applies both within project spaces and in public spaces
6767+ when an individual is representing the project or the school. Examples of
6868+ representing the project include using an official project email address,
6969+ posting via an official social media account, or acting as an appointed
7070+ representative at an online or offline event.
7171+7272+ ## Enforcement
7373+7474+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
7575+ reported to the IT Club faculty advisor. All complaints will be reviewed and
7676+ investigated promptly and fairly.
7777+7878+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may
7979+ face temporary or permanent repercussions as determined by the school administration.
8080+8181+ ## Attribution
8282+8383+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
8484+ version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html)
8585+ ```
8686+8787+1. In the top right, use the **Commit changes...** button and commit your changes directly to `prepare-to-collaborate` branch.
8888+8989+## ⌨️ Activity: Communicate easier with issue templates
9090+9191+Now let's create templates so other teachers can report bugs or request features in a standardized way.
9292+9393+> [!TIP]
9494+> You might consider trying the public preview for [issue forms](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms), which provide a friendlier user experience when creating issues.
9595+9696+1. In the top navigation, select the **Settings** tab.
9797+9898+1. Find the **Features** section and verify **Issues** is enabled.
9999+100100+ <img width="350" alt="" src="https://github.com/user-attachments/assets/dafb976b-4b8c-4c5e-8989-04d3e7bbe70d" />
101101+102102+1. Click the **Set up templates** button to enter the issue templates editor.
103103+104104+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/bd94af1e-d564-472f-a435-f12fa1bf3b5c" />
105105+106106+1. Click the **Add template** dropdown and select **Bug report**.
107107+108108+ <img width="350" alt="" src="https://github.com/user-attachments/assets/baee263d-b233-4029-b629-9544eacf1e27" />
109109+110110+1. Click the **Preview and edit** button to show the current template. Click the **Edit icon** (pencil) to make the fields editable.
111111+112112+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/1c8500f7-10b2-406b-9385-d5b9480e2f71" /><br/>
113113+114114+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/77e312e2-af3c-4015-94f0-b1cf7409cc40" /><br/>
115115+116116+ <img width="700" alt="image" src="https://github.com/user-attachments/assets/c2aecd6e-d021-4149-b088-7cbf883a7e33" />
117117+118118+1. (Optional) Let's keep it simple for our students and fellow teachers. Remove the sections about Desktop and Smartphone details.
119119+120120+1. Repeat the above steps for the "Feature request" template.
121121+122122+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/6456e261-fcd8-4845-b1ab-f2c2d5883c77" />
123123+124124+1. With our templates prepared, let's commit them. In the top right, click the **Propose changes** button. Enter a description and set the branch to `add-issue-templates`, then click **Commit changes**. You can ignore the automatically created pull request.
125125+126126+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/a00a3740-ce0c-430c-9541-e56b7d9b45d6" />
127127+128128+1. With the files committed, wait a moment for Mona to check your work, provide feedback, and share the next lesson.
129129+130130+> [!TIP]
131131+> Did you notice that you are working in parallel on 2 branches now? That's exactly what working with multiple collaborators is like.
···11+# Step 4: Prepare for the inevitable
22+33+As you settle into the teachers' lounge with your coffee, you realize something: With more and more teachers contributing to the code, it's only a matter of time before security vulnerabilities creep in. 😱
44+55+Every codebase, no matter how well-maintained, will eventually face security challenges. Let's try to proactively prepare for that day by configuring a few tools GitHub offers:
66+77+1. **Dependabot** - Track and create alerts for vulnerabilities found in upstream dependencies used in your project. Automatically create pull requests to upgrade dependencies to safe versions.
88+99+1. **Code Scanning** - Analyze your repository's code to find security vulnerabilities and coding errors. Use GitHub Copilot Autofix to automatically suggest fixes for these alerts.
1010+1111+1. **Security Policy and Private vulnerability reporting** - Provide a guide and simple form for security researchers and end users to responsibly report vulnerabilities directly to the repository maintainer. This prevents sensitive issues from being publicly disclosed before they're fixed.
1212+1313+> [!NOTE]
1414+> This is just a quick setup guide. For a more detailed setup of each service, we recommend the related GitHub Skills exercises and/or GitHub documentation.
1515+1616+## ⌨️ Activity: Automate security updates with Dependabot
1717+1818+Let's configure Dependabot to use default settings and automatically combine fixes for open alerts, and create pull requests. This will allow us to stay up to date with very little overhead! Nice!
1919+2020+> [!TIP]
2121+> For a deeper dive, check out the [Secure Repository Supply Chain](https://github.com/skills/secure-repository-supply-chain) Skills exercise!
2222+2323+1. In the top navigation, select the **Settings** tab.
2424+2525+1. In the left navigation, select **Advanced Security**.
2626+2727+1. Find the **Dependabot** section. Verify or change the settings to match the following:
2828+2929+ - **Dependabot alerts**: `enabled`
3030+ - **Dependabot security updates**: `enabled`
3131+ - **Grouped security updates**: `enabled`
3232+ - **Dependabot on Actions runners**: `enabled`
3333+3434+1. Find **Dependabot version updates** and click the **Enable** button. This will open an editor to create a configuration file.
3535+3636+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/a4d7ae19-0439-4b78-bcbf-9fce5c5410ff" />
3737+3838+1. In the left files list, at the top, click the **Expand file tree** button to show the list of files. At the top, change the branch to `prepare-to-collaborate`. Remember, our ruleset won't let us directly change files on `main`.
3939+4040+ <img width="500" alt="image" src="https://github.com/user-attachments/assets/18a3cd1a-75ab-4e5e-a4c4-efd175d91ced" />
4141+4242+1. Set the `package-ecosytem` to `pip` so Dependabot will automatically monitor our Python requirements.
4343+4444+ <img width="500" alt="image" src="https://github.com/user-attachments/assets/0bc90e67-4b71-4780-8272-20dc0fff5c4c" />
4545+4646+1. In the top right, use the **Commit changes...** button and commit your changes directly to `prepare-to-collaborate` branch.
4747+4848+## ⌨️ Activity: Detect dangerous patterns with code scanning
4949+5050+None of us at the high school are professional software developers. Let's enable code scanning to alert us if we are potentially doing something unsafe. And, let's configure GitHub Copilot to create pull requests with solutions.
5151+5252+> [!TIP]
5353+> Want to learn more about code scanning and writing custom queries? Check out the [Introduction to CodeQL](https://github.com/skills/introduction-to-codeql) Skills exercise after you finish this one!
5454+5555+1. In the top navigation, select the **Settings** tab.
5656+5757+1. In the left navigation, select **Advanced Security**.
5858+5959+1. Find the **Code scanning** section. Click the **Set up** button and select the **Default** option to open a configuration panel.
6060+6161+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/5b3a89e5-c71a-44d9-b917-d1a21dc52181" />
6262+6363+1. Click the **Enable CodeQL** button to accept the default configuration.
6464+6565+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/6d5f7164-d8ed-4b5d-bbcf-8aed9e7acc5d" />
6666+6767+1. Below the **Tools** section. Verify **Copilot Autofix** is set to `On`.
6868+6969+ <img width="350" alt="image" src="https://github.com/user-attachments/assets/b9d57e7a-f392-4c51-b137-f205a77adb79" />
7070+7171+## ⌨️ Activity: Provide a safe path for security findings
7272+7373+Now that the automated options are ready, let's create a guide for real-life humans to report any security vulnerabilities they find in a safe way.
7474+7575+1. In the top navigation, select the **Settings** tab.
7676+7777+1. In the left navigation, select **Advanced Security**.
7878+7979+1. Find the **Private vulnerability reporting** setting and verify it is `enabled`.
8080+8181+1. At the top navigation, click the **Security** tab.
8282+8383+1. In the left navigation, click the **Policy** option.
8484+8585+1. Click the **Start setup** button. An editor will be started to create the file `SECURITY.md`.
8686+8787+ <img width="350" alt="" src="https://github.com/user-attachments/assets/183b9fcc-1521-47fd-8165-b476a8ccb370"/><br/>
8888+8989+ <img width="350" alt="" src="https://github.com/user-attachments/assets/36c272d1-bc4a-48c8-b234-56173a214cdb"/>
9090+9191+1. In the left files list, at the top, click the **Expand file tree** button to show the list of files. At the top, change the branch to `prepare-to-collaborate`. Remember, our ruleset won't let us directly change files on `main`.
9292+9393+1. We will ignore the provided template and instead use a recommendation from Mergington High School's IT department. Add the following content:
9494+9595+ > 💡**Tip** If you switch to a branch that does not contain the same file, the editor will become empty. Press the **Restore** button to retrieve the previous editor's content.
9696+9797+ ```markdown
9898+ # Mergington High School Security Policy
9999+100100+ ## Reporting a Vulnerability
101101+102102+ At Mergington High, we take the security of our Extra-Curricular Activities website seriously, especially
103103+ since it contains student information. If you discover a security vulnerability, please follow these steps:
104104+105105+ 1. **Do not** create an issue on this repository, disclose the vulnerability publicly, or discuss it with other teachers/students.
106106+ 1. In the top navigation of this repository, click the **Security** tab.
107107+ 1. In the top right, click the **Report a vulnerability** button.
108108+ 1. Fill out the provided form. It will request information like:
109109+ - A description of the vulnerability
110110+ - Steps to reproduce the issue
111111+ - Potential impact on student data or website functionality
112112+ - Suggested fix (if you have one)
113113+ 1. Email the IT Club faculty advisor at techsupport@mergingtonhigh.example.edu and inform them you have made a report. **Do not** include any vulnerability details.
114114+115115+ ## Response Timeline
116116+117117+ - We will acknowledge receipt of your report within 2 school days
118118+ - We will provide an initial assessment within 5 school days
119119+ - Critical issues affecting student data will be addressed immediately
120120+ - We will create a private fork to solve the issue and invite you as a collaborator so you can see our progress and contribute.
121121+122122+ ## Thank You
123123+124124+ Your help in keeping our school's digital resources secure is greatly appreciated!
125125+ Responsible disclosure of security vulnerabilities helps protect our entire school community.
126126+ ```
127127+128128+1. In the top right, use the **Commit changes...** button and commit your changes directly to `prepare-to-collaborate` branch.
129129+130130+1. With the files committed, wait a moment for Mona to check your work, provide feedback, and share the next lesson.
···11+# Step 5: Release
22+33+With all our preparations ready, it's time to release them!
44+55+## ⌨️ Activity: Merge our collaboration changes
66+77+1. In the top navigation, select the **Pull requests** tab.
88+99+1. Find the pull request for the `prepare-to-collaborate` branch and merge it. You may need to wait for your new security scans to finish.
1010+1111+1. Find the pull request for the `add-issue-templates` branch and merge it. You may need to wait for your new security scans to finish.
1212+1313+1. With both pull requests merged, Mona will prepare the final review and acknowledge the exercise as finished! Nice work! You are all done! 🎉
···11+## Review
22+33+_Congratulations, you've completed this exercise! You're all set for an awesome time collaborating with your fellow teachers!_
44+55+<img src="https://octodex.github.com/images/jetpacktocat.png" alt=celebrate width=150 align=right>
66+77+You've successfully prepared Mergington High's extracurricular activities website for healthy and safe collaboration. Make sure you let the principal know so he can brag to the IT department about your proactive efforts!
88+99+Here is a snippet of something you can share:
1010+1111+- Protected our code from accidental mistakes with `.gitignore` and branch protections.
1212+- Set clear guidelines for teacher contributions with `CONTRIBUTING.md` and `CODEOWNERS`.
1313+- Established community standards with a Code of Conduct and structured issue templates.
1414+- Prepared for the future security challenges by enabling automated scanning and providing safe submission procedures.
1515+1616+### What's next?
1717+1818+This exercise was meant to introduce you to many of the different areas of managing a repository. However, there is still more to learn!
1919+2020+Here are some additional exercises for a deeper dive:
2121+2222+- [Skills: Secure your repository supply chain](https://github.com/skills/secure-repository-supply-chain)
2323+- [Skills: Introduction to CodeQL](https://github.com/skills/introduction-to-codeql)
2424+- [Skills: Introduction to Secret Scanning](https://github.com/skills/introduction-to-secret-scanning)
2525+2626+Here are some useful references from the [GitHub Docs](https://docs.github.com/en):
2727+2828+- [How to ignore files](https://docs.github.com/en/get-started/git-basics/ignoring-files)
2929+- [Template gitignore files](https://github.com/github/gitignore)
3030+- [Creating rulesets for a repository](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/creating-rulesets-for-a-repository#using-fnmatch-syntax)
3131+- [Managing a branch protection rule](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule)
3232+- [About code owners](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners)
3333+- [Setting guidelines for contributors](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/setting-guidelines-for-repository-contributors)
3434+- [Add a code of conduct](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/adding-a-code-of-conduct-to-your-project)
3535+- [Configuring default setup for code scanning](https://docs.github.com/en/code-security/code-scanning/enabling-code-scanning/configuring-default-setup-for-code-scanning)
3636+- [Adding a security policy](https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository)
···11+MIT License
22+33+Copyright (c) 2025 GitHub Skills
44+55+Permission is hereby granted, free of charge, to any person obtaining a copy
66+of this software and associated documentation files (the "Software"), to deal
77+in the Software without restriction, including without limitation the rights
88+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+copies of the Software, and to permit persons to whom the Software is
1010+furnished to do so, subject to the following conditions:
1111+1212+The above copyright notice and this permission notice shall be included in all
1313+copies or substantial portions of the Software.
1414+1515+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+SOFTWARE.
···11+# Mergington High School Activities API
22+33+A super simple FastAPI application that allows students to view and sign up for extracurricular activities.
44+55+## Features
66+77+- View all available extracurricular activities
88+- Sign up for activities
99+1010+## Getting Started
1111+1212+1. Install the dependencies:
1313+1414+ ```
1515+ pip install fastapi uvicorn
1616+ ```
1717+1818+2. Run the application:
1919+2020+ ```
2121+ python app.py
2222+ ```
2323+2424+3. Open your browser and go to:
2525+ - API documentation: http://localhost:8000/docs
2626+ - Alternative documentation: http://localhost:8000/redoc
2727+2828+## API Endpoints
2929+3030+| Method | Endpoint | Description |
3131+| ------ | ----------------------------------------------------------------- | ------------------------------------------------------------------- |
3232+| GET | `/activities` | Get all activities with their details and current participant count |
3333+| POST | `/activities/{activity_name}/signup?email=student@mergington.edu` | Sign up for an activity |
3434+3535+## Data Model
3636+3737+The application uses a simple data model with meaningful identifiers:
3838+3939+1. **Activities** - Uses activity name as identifier:
4040+4141+ - Description
4242+ - Schedule
4343+ - Maximum number of participants allowed
4444+ - List of student emails who are signed up
4545+4646+2. **Students** - Uses email as identifier:
4747+ - Name
4848+ - Grade level
4949+5050+All data is stored in memory, which means data will be reset when the server restarts.
···11+"""
22+High School Management System API
33+44+A super simple FastAPI application that allows students to view and sign up
55+for extracurricular activities at Mergington High School.
66+"""
77+88+from fastapi import FastAPI
99+from fastapi.staticfiles import StaticFiles
1010+from fastapi.responses import RedirectResponse
1111+import os
1212+from pathlib import Path
1313+from .backend import routers, database
1414+1515+# Initialize web host
1616+app = FastAPI(
1717+ title="Mergington High School API",
1818+ description="API for viewing and signing up for extracurricular activities"
1919+)
2020+2121+# Initialize database with sample data if empty
2222+database.init_database()
2323+2424+# Mount the static files directory for serving the frontend
2525+current_dir = Path(__file__).parent
2626+app.mount("/static", StaticFiles(directory=os.path.join(current_dir, "static")), name="static")
2727+2828+# Root endpoint to redirect to static index.html
2929+@app.get("/")
3030+def root():
3131+ return RedirectResponse(url="/static/index.html")
3232+3333+# Include routers
3434+app.include_router(routers.activities.router)
3535+app.include_router(routers.auth.router)
···11+"""
22+Endpoints for the High School Management System API
33+"""
44+55+from fastapi import APIRouter, HTTPException, Query
66+from fastapi.responses import RedirectResponse
77+from typing import Dict, Any, Optional, List
88+99+from ..database import activities_collection, teachers_collection
1010+1111+router = APIRouter(
1212+ prefix="/activities",
1313+ tags=["activities"]
1414+)
1515+1616+@router.get("/", response_model=Dict[str, Any])
1717+def get_activities(
1818+ day: Optional[str] = None,
1919+ start_time: Optional[str] = None,
2020+ end_time: Optional[str] = None
2121+) -> Dict[str, Any]:
2222+ """
2323+ Get all activities with their details, with optional filtering by day and time
2424+2525+ - day: Filter activities occurring on this day (e.g., 'Monday', 'Tuesday')
2626+ - start_time: Filter activities starting at or after this time (24-hour format, e.g., '14:30')
2727+ - end_time: Filter activities ending at or before this time (24-hour format, e.g., '17:00')
2828+ """
2929+ # Build the query based on provided filters
3030+ query = {}
3131+3232+ if day:
3333+ query["schedule_details.days"] = {"$in": [day]}
3434+3535+ if start_time:
3636+ query["schedule_details.start_time"] = {"$gte": start_time}
3737+3838+ if end_time:
3939+ query["schedule_details.end_time"] = {"$lte": end_time}
4040+4141+ # Query the database
4242+ activities = {}
4343+ for activity in activities_collection.find(query):
4444+ name = activity.pop('_id')
4545+ activities[name] = activity
4646+4747+ return activities
4848+4949+@router.get("/days", response_model=List[str])
5050+def get_available_days() -> List[str]:
5151+ """Get a list of all days that have activities scheduled"""
5252+ # Aggregate to get unique days across all activities
5353+ pipeline = [
5454+ {"$unwind": "$schedule_details.days"},
5555+ {"$group": {"_id": "$schedule_details.days"}},
5656+ {"$sort": {"_id": 1}} # Sort days alphabetically
5757+ ]
5858+5959+ days = []
6060+ for day_doc in activities_collection.aggregate(pipeline):
6161+ days.append(day_doc["_id"])
6262+6363+ return days
6464+6565+@router.post("/{activity_name}/signup")
6666+def signup_for_activity(activity_name: str, email: str, teacher_username: Optional[str] = Query(None)):
6767+ """Sign up a student for an activity - requires teacher authentication"""
6868+ # Check teacher authentication
6969+ if not teacher_username:
7070+ raise HTTPException(status_code=401, detail="Authentication required for this action")
7171+7272+ teacher = teachers_collection.find_one({"_id": teacher_username})
7373+ if not teacher:
7474+ raise HTTPException(status_code=401, detail="Invalid teacher credentials")
7575+7676+ # Get the activity
7777+ activity = activities_collection.find_one({"_id": activity_name})
7878+ if not activity:
7979+ raise HTTPException(status_code=404, detail="Activity not found")
8080+8181+ # Validate student is not already signed up
8282+ if email in activity["participants"]:
8383+ raise HTTPException(
8484+ status_code=400, detail="Already signed up for this activity")
8585+8686+ # Add student to participants
8787+ result = activities_collection.update_one(
8888+ {"_id": activity_name},
8989+ {"$push": {"participants": email}}
9090+ )
9191+9292+ if result.modified_count == 0:
9393+ raise HTTPException(status_code=500, detail="Failed to update activity")
9494+9595+ return {"message": f"Signed up {email} for {activity_name}"}
9696+9797+@router.post("/{activity_name}/unregister")
9898+def unregister_from_activity(activity_name: str, email: str, teacher_username: Optional[str] = Query(None)):
9999+ """Remove a student from an activity - requires teacher authentication"""
100100+ # Check teacher authentication
101101+ if not teacher_username:
102102+ raise HTTPException(status_code=401, detail="Authentication required for this action")
103103+104104+ teacher = teachers_collection.find_one({"_id": teacher_username})
105105+ if not teacher:
106106+ raise HTTPException(status_code=401, detail="Invalid teacher credentials")
107107+108108+ # Get the activity
109109+ activity = activities_collection.find_one({"_id": activity_name})
110110+ if not activity:
111111+ raise HTTPException(status_code=404, detail="Activity not found")
112112+113113+ # Validate student is signed up
114114+ if email not in activity["participants"]:
115115+ raise HTTPException(
116116+ status_code=400, detail="Not registered for this activity")
117117+118118+ # Remove student from participants
119119+ result = activities_collection.update_one(
120120+ {"_id": activity_name},
121121+ {"$pull": {"participants": email}}
122122+ )
123123+124124+ if result.modified_count == 0:
125125+ raise HTTPException(status_code=500, detail="Failed to update activity")
126126+127127+ return {"message": f"Unregistered {email} from {activity_name}"}