code rabbit test - #122
Conversation
Enhance rocky/README.md with first-time setup and testing instructions (npm install, how to run the dev server and build). Configure the Vite dev server port to 5000 in rocky/vite.config.ts to standardize local development.
Enhance rocky/README.md with first-time setup and testing instructions (npm install, how to run the dev server and build). Configure the Vite dev server port to 5000 in rocky/vite.config.ts to standardize local development.
Makes a key under sk_kent_(key) then stores its hash into the db.json file. I also added a 12 hour timeout to the keys which can be changed but after 12 hours the key dies. To test this start with npm install in terminal, then npx ts-node api-key-thing.ts generate to generate the key and store the hash in a db.json file, and finally copy the given key and use npx ts-node api-key-thing.ts validate sk_kent_(your_key_here) gives you a access granted if it worked or access denied just for now and gives you your id and time created/expires.
Moved api gen files to folder
Moved to api-key-gen folder
Moved to api-key-gen folder
Moved to api-key-gen folder
Moved to api-key-gen folder
Added usage instructions for API key generation demo.
Command to run in terminal to get CSV
Chart code
we can now CRUD users, courses, api keys; to do this i have updated main.py
Refactor frame handling and consolidate the app layout Sidebar.svelte now uses frameMap to render navigation dynamically and adds TypeScript typing and a label helper. Root +layout.svelte is updated to host the Topbar/Sidebar shell and conditionally render login routes (removing the separate /app layout and page), and the root +page now renders the active frame component via svelte:component. Styles were consolidated Deleted legacy /app route files.
…rontend Its all good, I aprove
mongita exists in the backend
I have put instructions on how to run DB with flask, how to add new entities to the database
addded requirement.txt
we can now CRUD users, courses, api keys; to do this i have updated main.py
I have put instructions on how to run DB with flask, how to add new entities to the database
addded requirement.txt
added mongita folder to gitignore
…cors) so front + backend can connect
Unignore test_db.py and add a basic unit test that uses MongitaClientMemory to swap the app's users/courses/api_keys collections to an in-memory DB.
Added 1 more test case
…abase Test page addition
Move UI components into clearer directories and pull styles out of views: - Rename/move Sidebar, Topbar, WidgetCard, and WidgetPanel to new paths and update their imports. - Add a new cards/CourseCard.svelte and convert the previous CourseCard Svelte file into styles/course-card.css. - Move DashboardView styles into lib/styles/dashboard.css and update DashboardView to import the card component from cards/. - Update global, app-layout, sidebar and widget-panel CSS to fix layout/height/scrolling behavior and tweak widget panel visuals. - Update route imports (+layout.svelte and +page.svelte) to the new component locations and ensure relevant styles are imported. These changes tidy the project structure and separate presentation from view logic, while addressing layout/scroll issues.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment Tip CodeRabbit can enforce grammar and style rules using `languagetool`.Configure the |
There was a problem hiding this comment.
Actionable comments posted: 7
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (17)
burndown/milestone_burndown.py-52-55 (1)
52-55:⚠️ Potential issue | 🟡 MinorSame division by zero risk as in
burndown.py.Apply the same defensive check here if
PROJECT_STARTequalsPROJECT_END.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@burndown/milestone_burndown.py` around lines 52 - 55, The comprehension that builds ideal_line can divide by zero when len(all_dates) - 1 == 0 (e.g., PROJECT_START == PROJECT_END); update the code around ideal_line to defensively handle that case: detect when len(all_dates) <= 1 and produce a single-point or constant list (e.g., [total_issues] * len(all_dates)) instead of performing the division, otherwise keep the existing comprehension; refer to ideal_line, all_dates, total_issues, and the PROJECT_START/PROJECT_END condition to locate where to add the guard.burndown/README.md-28-32 (1)
28-32:⚠️ Potential issue | 🟡 MinorFile name mismatch in documentation.
Line 28 references
milestoneBurndown.py, but the actual file is namedmilestone_burndown.py. Also,Python3should be lowercasepython3for consistency with line 51.📝 Proposed fix
-3. Run milestoneBurndown.py in your CLI like this: +3. Run milestone_burndown.py in your CLI like this:-Python3 milestoneBurndown.py
+python3 milestone_burndown.py🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@burndown/README.md` around lines 28 - 32, Update the README command to match the actual script filename and lowercase the interpreter: replace the incorrect reference to milestoneBurndown.py with milestone_burndown.py and change "Python3" to "python3" so the example line reads "python3 milestone_burndown.py" (search for the string milestoneBurndown.py and the capitalized Python3 to locate the lines to edit).burndown/burndown.py-52-55 (1)
52-55:⚠️ Potential issue | 🟡 MinorPotential division by zero if date range is a single day.
If
PROJECT_STARTequalsPROJECT_END,len(all_dates)would be 1, causing aZeroDivisionErrorat(len(all_dates) - 1).🛡️ Proposed defensive fix
# Ideal burndown (red) +num_days = len(all_dates) +if num_days <= 1: + ideal_line = [total_issues] +else: + ideal_line = [ + total_issues - (total_issues * i / (num_days - 1)) + for i in range(num_days) + ] -ideal_line = [ - total_issues - (total_issues * i / (len(all_dates) - 1)) - for i in range(len(all_dates)) -]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@burndown/burndown.py` around lines 52 - 55, The list comprehension assigning ideal_line can divide by zero when len(all_dates) == 1; change the logic in the ideal_line calculation (the comprehension that uses total_issues and all_dates) to guard the denominator by computing denom = max(1, len(all_dates) - 1) or handle the single-day case explicitly (e.g., return [total_issues] for that one date) so the expression total_issues * i / denom never raises ZeroDivisionError.api-key-gen/README.md-2-2 (1)
2-2:⚠️ Potential issue | 🟡 MinorMinor grammar fix: use hyphen for compound modifier.
"12 hour timeout" should be "12-hour timeout" when used as a compound adjective.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@api-key-gen/README.md` at line 2, Replace the phrase "12 hour timeout" with the hyphenated compound modifier "12-hour timeout" in the README content (the sentence describing key expiration such as "Makes a key under sk_kent_(key) then stores its hash into a db.json file. I also added a 12 hour timeout to the keys...") to correct the grammar.rocky-interface/src/lib/styles/course-card.css-78-78 (1)
78-78:⚠️ Potential issue | 🟡 MinorFix comment whitespace.
Static analysis flagged missing whitespace before
*/in the comment.Proposed fix
-/* LIST*/ +/* LIST */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/styles/course-card.css` at line 78, The comment token "/* LIST*/" is missing a space before the closing `*/`; update that comment to "/* LIST */" (and fix any other comments with no-space-before-*/ occurrences) so it conforms to the style/linter rules, then re-run the CSS linter/formatter to ensure no other comment-whitespace warnings remain.rocky-backend/README.md-78-80 (1)
78-80:⚠️ Potential issue | 🟡 MinorPort number mismatch.
The documentation references port 5000, but
main.pyruns on port 5001. Update the URLs to match.Proposed fix
### 3. Test with Postman / Thunder Client -- **POST** `http://127.0.0.1:5000/assignments` with `Content-Type: application/json` and a JSON body -- **GET** `http://127.0.0.1:5000/assignments` to retrieve all -- **DELETE** `http://127.0.0.1:5000/assignments/<id>` to remove one +- **POST** `http://127.0.0.1:5001/assignments` with `Content-Type: application/json` and a JSON body +- **GET** `http://127.0.0.1:5001/assignments` to retrieve all +- **DELETE** `http://127.0.0.1:5001/assignments/<id>` to remove one🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-backend/README.md` around lines 78 - 80, The README's example endpoints use port 5000 but the application in main.py is started on port 5001; update the documented URLs (`http://127.0.0.1:5000/...`) to `http://127.0.0.1:5001/...` so they match the actual runtime in main.py (where app.run or the port constant is set to 5001); ensure all occurrences (POST /assignments, GET /assignments, DELETE /assignments/<id>) are changed consistently.rocky-backend/README.md-22-29 (1)
22-29:⚠️ Potential issue | 🟡 MinorClarify the Flask run command.
Line 23 combines two separate commands incorrectly. It should be either
python main.pyorflask --app main run --debug, not both together.Proposed fix
# Running Flask ```cmd -python main.py flask --app main run --debug - -OR - python main.py +``` +Or using Flask CLI: +```cmd +flask --app main run --debug --port 5001</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against the current code and only fix it if needed.
In
@rocky-backend/README.mdaround lines 22 - 29, The README contains a
malformed combined command string; replace the single line "python main.py
flask --app main run --debug" with two separate, correct commands: the script
invocation "python main.py" and the Flask CLI invocation "flask --app main run
--debug" (optionally add "--port 5001" if you want a non-default port). Update
the README example to show these as separate alternatives and ensure the fenced
code blocks remain valid around each command so users can copy them easily.</details> </blockquote></details> <details> <summary>rocky-interface/README.md-2-2 (1)</summary><blockquote> `2-2`: _⚠️ Potential issue_ | _🟡 Minor_ **Fix onboarding wording to avoid confusion.** Line 2 has awkward grammar, and Line 16 incorrectly suggests a global Svelte install is needed. `npm install` + local scripts are sufficient. <details> <summary>📝 Proposed doc fix</summary> ```diff -Kent State University's Computer Science's Web Interface to Obtain API Keys for Student Projects. +Kent State University's Computer Science web interface for obtaining API keys for student projects. ... -Make sure you have npm and svelte installed. Then, start a development server: +Make sure you have Node.js and npm installed. Then, start a development server:Also applies to: 16-16
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/README.md` at line 2, Reword the project description sentence to be grammatical (e.g., "Kent State University Computer Science web interface to obtain API keys for student projects.") and edit the onboarding instructions that mention a global Svelte install: remove any instruction to install Svelte globally and replace it with a brief, clear command sequence such as "Run npm install, then use the local scripts (e.g., npm run dev) to start the app" so the README advises using local npm scripts instead of a global Svelte installation.rocky-interface/src/lib/components/Topbar.svelte-6-10 (1)
6-10:⚠️ Potential issue | 🟡 MinorAvoid redundant screen-reader announcement for the logo.
At Line 6, the logo
alt="Rocky"is duplicated by visible text in Lines 8–9. If the image is decorative, use empty alt text.♿ Suggested accessibility tweak
- <img src="/rock.png" alt="Rocky" class="brand-logo" /> + <img src="/rock.png" alt="" class="brand-logo" />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/components/Topbar.svelte` around lines 6 - 10, The logo image is redundantly announced to screen readers because its alt="Rocky" repeats the visible brand text; update the <img class="brand-logo"> to be purely decorative by setting an empty alt attribute (alt="") so only the visible elements (<div class="brand-name"> and <div class="brand-sub">) are read, or alternatively add aria-hidden="true" to the image if you prefer; keep the visible brand-name/brand-sub markup unchanged.rocky-interface/src/lib/styles/global.css-9-15 (1)
9-15:⚠️ Potential issue | 🟡 MinorPotential CSS conflict:
.main-contentis also defined indashboard.css.This class is defined here with
overflow: visible, butdashboard.cssalso defines.main-contentwithoverflow: hiddenand additional properties. Depending on stylesheet load order, this may cause unexpected layout behavior. Consider renaming one of them or consolidating into a single definition.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/styles/global.css` around lines 9 - 15, The .main-content CSS class is defined twice with conflicting overflow rules (visible here vs hidden in dashboard.css); rename one of the classes (e.g., .main-content -> .global-main-content or .dashboard-main) or consolidate into a single shared class to remove the conflict, then update all usages in templates/components that reference .main-content (search for elements using the .main-content selector) and adjust the CSS in either the current stylesheet or dashboard.css (and remove the duplicate definition) so only one authoritative rule remains.rocky-interface/src/lib/components/views/DashboardView.svelte-39-39 (1)
39-39:⚠️ Potential issue | 🟡 MinorAccessibility: Backdrop
<div>is not keyboard accessible.The backdrop div handles click events but lacks keyboard support. Users navigating with keyboard cannot dismiss the menu via Escape key. Consider adding a
keydownhandler for Escape, or using a more accessible pattern.Suggested approach
Add an
on:keydownhandler to close the menu on Escape, typically on the window or a focusable element:<svelte:window on:keydown={(e) => e.key === 'Escape' && (showViewMenu = false)} />Or add
role="button"andtabindex="0"with keyboard handler to the backdrop itself if it needs to be focusable.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/components/views/DashboardView.svelte` at line 39, The backdrop div that toggles showViewMenu on click is not keyboard accessible; update DashboardView.svelte to handle Escape key to close the menu by adding a global key handler (e.g., use <svelte:window on:keydown={...}> to set showViewMenu = false when e.key === 'Escape') or make the backdrop focusable (add role="button" and tabindex="0") and attach an on:keydown handler to that element to close showViewMenu on Enter/Escape; ensure the same showViewMenu variable used in the div's on:click is toggled by the keyboard handler so keyboard users can dismiss the menu.rocky-interface/src/lib/styles/global.css-5-5 (1)
5-5:⚠️ Potential issue | 🟡 MinorFix font-family: remove quotes from system keywords and add a generic fallback.
The static analysis correctly flags issues here:
"ui-sans-serif"and"system-ui"are CSS system font keywords and should not be quoted."National"and"Soho"appear to be custom fonts and can keep quotes (or remove them if single-word).- A generic fallback (
sans-serif) is missing at the end of the stack.Proposed fix
body { margin: 0; padding: 0; height: 100%; - font-family: "National", "Soho", "ui-sans-serif", "system-ui"; + font-family: "National", "Soho", ui-sans-serif, system-ui, sans-serif; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/styles/global.css` at line 5, The font-family declaration currently quotes system font keywords and lacks a generic fallback; update the font-family rule (the font-family declaration in global.css) to remove quotes around ui-sans-serif and system-ui, keep or remove quotes for custom fonts "National" and "Soho" as desired, and append a generic fallback like sans-serif at the end of the stack so the final value uses unquoted system keywords and includes sans-serif.rocky-interface/src/lib/styles/login.css-38-38 (1)
38-38:⚠️ Potential issue | 🟡 MinorFix font-family: same issues as in
global.css.Remove quotes from system font keywords and add a generic fallback.
Proposed fix
- font-family: "National", "Soho", "ui-sans-serif", "system-ui"; + font-family: "National", "Soho", ui-sans-serif, system-ui, sans-serif;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/styles/login.css` at line 38, Update the font-family declaration in login.css (the font-family rule shown) to mirror the global.css fix: remove unnecessary quotes around system font keywords (e.g., National, Soho, ui-sans-serif, system-ui) and append the standard system-font fallbacks and a generic fallback (include -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, and finally sans-serif) so the rule uses unquoted system font keywords and a robust fallback stack.rocky-interface/src/lib/styles/sidebar.css-11-22 (1)
11-22:⚠️ Potential issue | 🟡 MinorRemove empty line before
colordeclaration (stylelint).The static analysis flagged an empty line before the
colordeclaration on line 17.Proposed fix
.nav-link { appearance: none; border: 0; background: transparent; text-align: left; - color: `#FFFFFF`; padding: 14px 20px; width: 100%; cursor: pointer; font-size: 16px; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/styles/sidebar.css` around lines 11 - 22, Remove the stray blank line inside the .nav-link rule before the color declaration: open the .nav-link CSS block (selector .nav-link) and delete the empty line so the color: `#FFFFFF`; sits directly with the other declarations, then run stylelint to confirm the whitespace warning is resolved.rocky-interface/src/routes/DBtest/+page.svelte-14-17 (1)
14-17:⚠️ Potential issue | 🟡 MinorMissing error handling and response status check.
The
fetchcall doesn't check if the response was successful before parsing JSON. If the server returns an error status,res.json()may fail or return unexpected data.🛡️ Proposed fix with error handling
async function loadUsers() { -const res = await fetch('http://localhost:5001/users'); -users = await res.json(); + try { + const res = await fetch('http://localhost:5001/users'); + if (!res.ok) { + console.error('Failed to load users:', res.status); + return; + } + users = await res.json(); + } catch (err) { + console.error('Error loading users:', err); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/routes/DBtest/`+page.svelte around lines 14 - 17, The loadUsers function lacks response-status checks and error handling: wrap the fetch in try/catch, verify the Response.ok before calling res.json(), and handle non-ok responses (log/throw or set a safe fallback for users). Update the async function loadUsers to check res.ok and handle/parses error payloads appropriately, and ensure the users variable is assigned a sensible default on failure to avoid downstream errors.rocky-interface/src/routes/DBtest/+page.svelte-39-44 (1)
39-44:⚠️ Potential issue | 🟡 MinorMissing
awaitonloadUsers().Same issue as
addUser()— theloadUsers()call on line 43 should be awaited to ensure the UI updates correctly after deletion.🐛 Proposed fix
async function deleteUser(id: string) { -await fetch(`http://localhost:5001/users/${id}`, { -method: 'DELETE' -}); -loadUsers(); + try { + const res = await fetch(`http://localhost:5001/users/${id}`, { + method: 'DELETE' + }); + if (!res.ok) { + console.error('Failed to delete user:', res.status); + return; + } + await loadUsers(); + } catch (err) { + console.error('Error deleting user:', err); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/routes/DBtest/`+page.svelte around lines 39 - 44, The deleteUser function calls loadUsers() without awaiting it, causing the UI to refresh before deletion completes; update the deleteUser implementation (the async function deleteUser) to await loadUsers() after the fetch completes (same pattern used in addUser) so the UI updates only after the delete request and reload finish.rocky-interface/src/routes/DBtest/+page.svelte-20-36 (1)
20-36:⚠️ Potential issue | 🟡 MinorMissing
awaitonloadUsers()and no error handling.On line 35,
loadUsers()is called withoutawait, so the function doesn't wait for the users to reload before completing. This can cause race conditions or UI inconsistencies.Additionally, the hardcoded
flash_id: "test123"androle: "student"suggest this is test/demo code. Consider making these configurable or adding a comment clarifying this is intentional for testing.🐛 Proposed fix
async function addUser() { -await fetch('http://localhost:5001/users', { -method: 'POST', -headers: { 'Content-Type': 'application/json' }, -body: JSON.stringify({ -name, -email, -flash_id: "test123", -role: "student" -}) -}); - - -name = ''; -email = ''; -loadUsers(); + try { + const res = await fetch('http://localhost:5001/users', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + name, + email, + flash_id: "test123", // TODO: Make configurable + role: "student" // TODO: Make configurable + }) + }); + if (!res.ok) { + console.error('Failed to add user:', res.status); + return; + } + name = ''; + email = ''; + await loadUsers(); + } catch (err) { + console.error('Error adding user:', err); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/routes/DBtest/`+page.svelte around lines 20 - 36, The addUser function calls loadUsers() without awaiting it and lacks error handling and uses hardcoded test values; update addUser to await the POST response, wrap the network calls in try/catch to handle and log/display errors, and await loadUsers() (i.e., await loadUsers()) before clearing inputs so the UI waits for the refresh; also replace or surface the hardcoded flash_id and role (e.g., make flash_id and role parameters/variables or add a clear comment that they are test values) to avoid leaving test/demo values in production.
🧹 Nitpick comments (13)
burndown/burndown.py (2)
15-73: Consider wrapping script logic in aif __name__ == "__main__":guard.Running code at module level prevents reuse (e.g., importing
parse_datetimeelsewhere) and makes testing harder. This is a good-to-have improvement for maintainability.♻️ Suggested structure
def main(): # ... existing logic from lines 15-73 ... if __name__ == "__main__": main()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@burndown/burndown.py` around lines 15 - 73, The module runs script logic at import time; wrap the top-level workflow (loading CSV, parsing dates, computing actual/ideal lines, and plotting) into a new main() function and leave utility functions like parse_datetime at module scope so they remain importable; call main() under an if __name__ == "__main__": guard and ensure main references existing symbols (CSV_FILE, CREATED_COLUMN, CLOSED_COLUMN, PROJECT_START, PROJECT_END) and returns/handles errors as before.
42-48: Performance note: O(n × m) complexity for burndown calculation.The loop iterates over each date and filters the entire DataFrame each time. For large issue counts or long date ranges, this could be slow. A vectorized approach or pre-sorting could improve performance, but this is likely acceptable for typical usage (< 1000 issues over a few months).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@burndown/burndown.py` around lines 42 - 48, The current O(n×m) loop over actual_dates repeatedly filters df (variables: remaining, actual_dates, df, CLOSED_COLUMN), so replace it with a vectorized approach: extract and sort closed_dates = df[CLOSED_COLUMN].dropna().sort_values().to_numpy(), compute cumulative closed counts for each date using numpy.searchsorted (closed_count = np.searchsorted(closed_dates, actual_dates, side='right')), then set remaining = total_issues - closed_count (where total_issues = len(df)); this avoids repeated DataFrame filtering and handles open issues (NaNs) by excluding them from closed_dates.burndown/milestone_burndown.py (1)
1-73: Significant code duplication withburndown.py.This file shares ~95% of its code with
burndown.py. Consider extracting shared logic into a common module to reduce maintenance burden and ensure consistency.♻️ Suggested refactor approach
Create a shared module (e.g.,
burndown_common.py) with reusable functions:# burndown_common.py import pandas as pd from pathlib import Path import sys def load_issues(csv_file, created_col="createdAt", closed_col="closedAt"): file_path = Path(csv_file) if not file_path.is_file(): print(f"Error: File '{csv_file}' not found.") sys.exit(1) df = pd.read_csv(csv_file, encoding='utf-8-sig', quotechar='"') df.columns = df.columns.str.strip() df[created_col] = parse_datetime(df[created_col]) df[closed_col] = parse_datetime(df[closed_col]) return df def parse_datetime(series): series = pd.to_datetime(series, errors='coerce', utc=True) return series.dt.tz_convert(None) def compute_burndown(df, closed_col, dates): # ... shared computation logic ... def plot_burndown(actual_dates, remaining, all_dates, ideal_line, title, ...): # ... shared plotting logic ...Then each script becomes a thin wrapper calling these functions with different parameters.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@burndown/milestone_burndown.py` around lines 1 - 73, This file duplicates most logic from burndown.py; extract shared behavior into a new module (e.g., burndown_common.py) that exposes functions like load_issues(csv_file, created_col="createdAt", closed_col="closedAt") which encapsulates the CSV loading and the parse_datetime(series) helper, compute_burndown(df, closed_col, start, end, today) which returns actual_dates and remaining and all_dates and ideal_line, and plot_burndown(actual_dates, remaining, all_dates, ideal_line, title) which contains the matplotlib plotting; then simplify milestone_burndown.py to call load_issues(CSV_FILE), compute_burndown(df, CLOSED_COLUMN, PROJECT_START, PROJECT_END, today) and plot_burndown(...) while preserving the existing constants (CSV_FILE, CREATED_COLUMN, CLOSED_COLUMN, PROJECT_START, PROJECT_END) and function names (parse_datetime, compute_burndown, plot_burndown) to make the refactor minimal and maintain behavior.burndown/README.md (1)
3-3: Consider fixing markdown structure issues flagged by linter.The heading level jumps from h1 to h3. Additionally, the fenced code blocks should specify a language (e.g.,
bashorshell) for proper syntax highlighting.📝 Proposed fix for heading and code blocks
-### Get to repository in your CLI +## Get to repository in your CLIFor code blocks, add the language identifier:
-``` +```bash ( echo "closedAt,createdAt,number,state,title"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@burndown/README.md` at line 3, Change the "### Get to repository in your CLI" heading to a second-level heading (use "##") to fix the h1→h3 jump, and update all fenced code blocks in burndown/README.md to include a language identifier (e.g., ```bash or ```shell) so the linter can apply syntax highlighting; target the README heading and any code fences shown around the repository/CLI examples to make these edits.rocky-backend/src/app.html (1)
1-11: Consider removing or relocating this SvelteKit template fromrocky-backend.If
rocky-backendis intended to be Flask-only, keeping SvelteKit template files here creates ambiguity in build/deploy ownership.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-backend/src/app.html` around lines 1 - 11, This SvelteKit HTML template (app.html) containing markers like %sveltekit.head% and %sveltekit.body% and the body attribute data-sveltekit-preload-data="hover" should be removed from the Flask-only backend or moved into the frontend/SvelteKit repo; either delete this file from rocky-backend or relocate it to the SvelteKit project, and update any build/deploy configs that referenced %sveltekit.head%/%sveltekit.body% so the backend has no ambiguous frontend template artifacts.rocky-backend/test_db.py (2)
6-16: Consider addingtearDownfor test isolation.Without clearing collections between tests, data created in one test persists into subsequent tests within the same class, which can cause flaky or order-dependent failures.
Proposed addition
def setUp(self): # Swap to in-memory DB so tests never touch disk data client = MongitaClientMemory() db = client["test_db"] main.users = db["users"] main.courses = db["courses"] main.api_keys = db["api_keys"] main.app.config["TESTING"] = True self.client = main.app.test_client() + + def tearDown(self): + # Clear collections after each test for isolation + main.users.delete_many({}) + main.courses.delete_many({}) + main.api_keys.delete_many({})🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-backend/test_db.py` around lines 6 - 16, Add a tearDown to BaseTest to ensure test isolation by clearing or resetting the in-memory collections after each test; for example, implement BaseTest.tearDown that calls main.users.delete_many({}), main.courses.delete_many({}), and main.api_keys.delete_many({}) (or reinstantiates MongitaClientMemory and rebinds main.users/main.courses/main.api_keys) so no data persists between tests started in setUp.
30-40: Assert response body intest_get_users.The test creates a user but only checks the status code of the GET response. Verifying the returned data ensures the endpoint actually returns the created user.
Proposed improvement
def test_get_users(self): # Create a user first self.client.post("/users", json={ "name": "Bob", "email": "bob@example.com", "flash_id": "bob123", "role": "student" }) # Now test getting users response = self.client.get("/users") self.assertEqual(response.status_code, 200) + data = response.get_json() + self.assertEqual(len(data), 1) + self.assertEqual(data[0]["name"], "Bob") + self.assertEqual(data[0]["email"], "bob@example.com")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-backend/test_db.py` around lines 30 - 40, In test_get_users, after creating the user via self.client.post("/users", ...), assert the GET /users response body contains the created user: parse response.json() (response variable) and verify the list includes an entry with name "Bob", email "bob@example.com" and flash_id "bob123" (and optionally role "student"), and also assert expected list length or that at least one matching user exists; update test_get_users to perform these JSON assertions instead of only checking response.status_code.rocky-backend/main.py (1)
57-62: Consider addingcreated_atfor courses.
create_userandcreate_api_keyadd timestamps, butcreate_coursedoes not. This inconsistency may cause issues when querying or auditing records.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-backend/main.py` around lines 57 - 62, create_course currently inserts the incoming payload directly via courses.insert_one without a timestamp; before inserting, add a created_at timestamp on the data (matching the same format used by create_user and create_api_key) and ensure the datetime import is present so created_at is populated (e.g., UTC ISO or the project's existing format) before calling courses.insert_one(data).rocky-interface/src/lib/styles/login.css (1)
3-15: Minor: Remove empty lines before declarations (stylelint).Lines 7 and 10 have empty lines before declarations that stylelint flags. Consider removing for consistency.
Proposed fix
.background { min-height: 100vh; min-width: 100vw; - display: grid; place-items: center; - background-image: url("/commencement_dark.jpg"); background-size: cover;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/styles/login.css` around lines 3 - 15, The .background CSS rule contains unnecessary blank lines before some declarations that trigger stylelint; edit the .background rule to remove the empty lines (so declarations like display, place-items, background-image, background-size, background-position, background-repeat, background-attachment appear without extra blank lines between them) to satisfy stylelint's spacing rules and keep formatting consistent.rocky-interface/src/lib/components/Sidebar.svelte (2)
12-14: Remove redundant type casts.Since
primaryFramesis already typed asframeName[], theas frameNamecasts onframeare unnecessary.Proposed simplification
{`#each` primaryFrames as frame} - <button class="nav-link" class:active={$currentFrame === (frame as frameName)} on:click={() => currentFrame.set(frame as frameName)}>{toLabel(frame as frameName)}</button> + <button class="nav-link" class:active={$currentFrame === frame} on:click={() => currentFrame.set(frame)}>{toLabel(frame)}</button> {/each}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/components/Sidebar.svelte` around lines 12 - 14, The template is using unnecessary casts of `frame` to `frameName`; since `primaryFrames` is already `frameName[]`, remove the redundant `as frameName` occurrences in the each block so the button uses `{$currentFrame === frame}`, `on:click={() => currentFrame.set(frame)}`, and `{toLabel(frame)}` directly; update the `each` block to reference `frame` without casting (symbols: primaryFrames, frame, currentFrame, toLabel).
1-9: Minor: Leading whitespace before<script>tag.Line 1 has a tab character before
<script lang="ts">. While this likely won't cause issues, it's unconventional. The rest of the component logic looks good.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/components/Sidebar.svelte` around lines 1 - 9, Remove the leading tab before the <script lang="ts"> tag in Sidebar.svelte so the file starts with the script tag at column 0 (normalize whitespace); update the file header to eliminate that leading whitespace and reformat the file (or run the project's formatter) to ensure the <script> tag and the constants/functions like currentFrame, frameMap, frames, primaryFrames, and toLabel remain unchanged.rocky-interface/src/lib/components/cards/CourseCard.svelte (1)
24-24: Buttons lack click handlers.The "Go to Course" buttons in both card and list modes have no
on:clickhandlers. If this is intentional placeholder UI, consider adding a TODO comment or disabling the buttons to indicate they're not yet functional.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/lib/components/cards/CourseCard.svelte` at line 24, The "Go to Course →" button in CourseCard.svelte currently has no click handler; either wire it up or visibly mark it as non-functional: add an on:click handler on the button with the intended navigation callback (e.g., call a prop function like onNavigate or dispatch a Svelte event from CourseCard) and ensure both card and list render paths use the same .go-btn element, or if it's intentionally a placeholder, add disabled attribute and a TODO comment above the <button class="go-btn"> element indicating future behavior. Reference the CourseCard.svelte component and the .go-btn button when making the change so both modes are updated consistently.rocky-interface/src/routes/DBtest/+page.svelte (1)
55-57: Consider adding input validation.The form allows submitting with empty
nameor💡 Simple validation approach
-<button on:click={addUser}>Add User</button> +<button on:click={addUser} disabled={!name.trim() || !email.trim()}>Add User</button>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rocky-interface/src/routes/DBtest/`+page.svelte around lines 55 - 57, The form currently allows submitting empty values; add validation around the bound variables name and email and prevent submission when invalid by updating the button to be disabled when name or email are empty/whitespace and by adding a guard in the addUser function that trims inputs, checks non-empty (and optionally a simple email regex) and returns early (or shows an error) if validation fails; reference the input bindings name and email and the click handler addUser to implement both UI-disable and safe server-side guard.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rocky-backend/.gitignore`:
- Around line 2-3: The .gitignore currently uses a global ignore pattern "*"
with an exception for "!test_db.py", which hides the entire repository from
source control; remove or replace the broad "*" entry and instead list specific
ignore patterns (e.g., build/, *.pyc, .env, node_modules, dist/, etc.) so that
source folders and config are tracked, and remove the inverted-exception
"!test_db.py" (or convert to explicit allow rules) so only intended files are
ignored; locate the lines containing the "*" and "!test_db.py" tokens and
replace them with a conservative set of ignores that do not exclude the backend
code, docs, or config.
In `@rocky-backend/main.py`:
- Around line 20-26: The create_user handler assumes request.json is present; if
request.json is None accessing data["created_at"] will crash. Update the
create_user function to validate the JSON body: check if request.json (data) is
None and return a 400/JSON error response when missing or invalid, and verify
required fields (e.g., name, email, flash_id, role) before mutating/using data;
only then set data["created_at"] and call users.insert_one(data). Apply the same
guard pattern to other POST/PUT handlers that read request.json to prevent
TypeError on missing/invalid JSON.
- Around line 121-122: app.run is currently invoked with debug=True which
enables the unsafe Werkzeug interactive debugger; change this to read debug mode
from configuration or an environment variable instead (e.g., use
os.environ.get('FLASK_DEBUG') or app.config['DEBUG'] to determine the boolean)
and pass that value to app.run(debug=...) or omit debug and rely on Flask config
so debug is disabled in production; ensure any environment value is parsed to a
boolean before passing to app.run.
- Around line 36-41: The get_user route (and all routes that call
ObjectId(user_id)) must validate/handle invalid ObjectId values to avoid
unhandled bson.errors.InvalidId exceptions: wrap the ObjectId(...) conversion in
a try/except catching bson.errors.InvalidId (or validate the 24-hex format
first) and return a 400 Bad Request JSON error when invalid; update functions
like get_user and the other handlers that call ObjectId to perform this
try/except, import InvalidId from bson.errors, and ensure successful conversions
proceed to query the users collection and return 404 if not found.
In `@rocky-interface/src/routes/`+page.svelte:
- Line 10: Guard the dynamic component lookup before mounting: check whether
frameMap[$currentFrame as frameName] is defined before using <svelte:component
this={...}> and render a fallback (e.g., a placeholder message or null) when
it's undefined. Locate the dynamic mount using the symbols frameMap,
$currentFrame (frameName) and svelte:component and update the template to
conditionally render the component only if the lookup yields a value, otherwise
render the fallback UI to avoid runtime crashes.
In `@rocky-interface/src/routes/DBtest/`+page.svelte:
- Line 15: The fetch calls in +page.svelte are using a hardcoded base URL
('http://localhost:5001') which will fail in production; create a shared API
base constant (e.g., export API_BASE_URL from a new $lib/config.ts that reads
import.meta.env.VITE_API_URL || 'http://localhost:5001') and replace all direct
uses of 'http://localhost:5001' in this file (the const res = await fetch(...)
calls) with fetch(`${API_BASE_URL}/users`) (or equivalent endpoints) by
importing API_BASE_URL into DBtest/+page.svelte so environments can control the
backend URL.
In `@rocky-interface/src/routes/login/`+page.svelte:
- Around line 18-20: The Sign In button (class "signin") has no behavior; add a
click handler to initiate the auth flow by implementing a handleSignIn function
and wiring it to the button (e.g., <button class="signin"
on:click={handleSignIn}>). In handleSignIn (in the same +page.svelte script)
import goto from '$app/navigation' and call goto('/auth/login') or the route
that triggers your backend auth endpoint; alternatively submit a form by placing
the button inside a <form action="/auth/login" method="post"> if you prefer
server form flow. Ensure the handler name handleSignIn and the "signin" button
class are used so the change is easy to locate.
---
Minor comments:
In `@api-key-gen/README.md`:
- Line 2: Replace the phrase "12 hour timeout" with the hyphenated compound
modifier "12-hour timeout" in the README content (the sentence describing key
expiration such as "Makes a key under sk_kent_(key) then stores its hash into a
db.json file. I also added a 12 hour timeout to the keys...") to correct the
grammar.
In `@burndown/burndown.py`:
- Around line 52-55: The list comprehension assigning ideal_line can divide by
zero when len(all_dates) == 1; change the logic in the ideal_line calculation
(the comprehension that uses total_issues and all_dates) to guard the
denominator by computing denom = max(1, len(all_dates) - 1) or handle the
single-day case explicitly (e.g., return [total_issues] for that one date) so
the expression total_issues * i / denom never raises ZeroDivisionError.
In `@burndown/milestone_burndown.py`:
- Around line 52-55: The comprehension that builds ideal_line can divide by zero
when len(all_dates) - 1 == 0 (e.g., PROJECT_START == PROJECT_END); update the
code around ideal_line to defensively handle that case: detect when
len(all_dates) <= 1 and produce a single-point or constant list (e.g.,
[total_issues] * len(all_dates)) instead of performing the division, otherwise
keep the existing comprehension; refer to ideal_line, all_dates, total_issues,
and the PROJECT_START/PROJECT_END condition to locate where to add the guard.
In `@burndown/README.md`:
- Around line 28-32: Update the README command to match the actual script
filename and lowercase the interpreter: replace the incorrect reference to
milestoneBurndown.py with milestone_burndown.py and change "Python3" to
"python3" so the example line reads "python3 milestone_burndown.py" (search for
the string milestoneBurndown.py and the capitalized Python3 to locate the lines
to edit).
In `@rocky-backend/README.md`:
- Around line 78-80: The README's example endpoints use port 5000 but the
application in main.py is started on port 5001; update the documented URLs
(`http://127.0.0.1:5000/...`) to `http://127.0.0.1:5001/...` so they match the
actual runtime in main.py (where app.run or the port constant is set to 5001);
ensure all occurrences (POST /assignments, GET /assignments, DELETE
/assignments/<id>) are changed consistently.
- Around line 22-29: The README contains a malformed combined command string;
replace the single line "python main.py flask --app main run --debug" with two
separate, correct commands: the script invocation "python main.py" and the Flask
CLI invocation "flask --app main run --debug" (optionally add "--port 5001" if
you want a non-default port). Update the README example to show these as
separate alternatives and ensure the fenced code blocks remain valid around each
command so users can copy them easily.
In `@rocky-interface/README.md`:
- Line 2: Reword the project description sentence to be grammatical (e.g., "Kent
State University Computer Science web interface to obtain API keys for student
projects.") and edit the onboarding instructions that mention a global Svelte
install: remove any instruction to install Svelte globally and replace it with a
brief, clear command sequence such as "Run npm install, then use the local
scripts (e.g., npm run dev) to start the app" so the README advises using local
npm scripts instead of a global Svelte installation.
In `@rocky-interface/src/lib/components/Topbar.svelte`:
- Around line 6-10: The logo image is redundantly announced to screen readers
because its alt="Rocky" repeats the visible brand text; update the <img
class="brand-logo"> to be purely decorative by setting an empty alt attribute
(alt="") so only the visible elements (<div class="brand-name"> and <div
class="brand-sub">) are read, or alternatively add aria-hidden="true" to the
image if you prefer; keep the visible brand-name/brand-sub markup unchanged.
In `@rocky-interface/src/lib/components/views/DashboardView.svelte`:
- Line 39: The backdrop div that toggles showViewMenu on click is not keyboard
accessible; update DashboardView.svelte to handle Escape key to close the menu
by adding a global key handler (e.g., use <svelte:window on:keydown={...}> to
set showViewMenu = false when e.key === 'Escape') or make the backdrop focusable
(add role="button" and tabindex="0") and attach an on:keydown handler to that
element to close showViewMenu on Enter/Escape; ensure the same showViewMenu
variable used in the div's on:click is toggled by the keyboard handler so
keyboard users can dismiss the menu.
In `@rocky-interface/src/lib/styles/course-card.css`:
- Line 78: The comment token "/* LIST*/" is missing a space before the closing
`*/`; update that comment to "/* LIST */" (and fix any other comments with
no-space-before-*/ occurrences) so it conforms to the style/linter rules, then
re-run the CSS linter/formatter to ensure no other comment-whitespace warnings
remain.
In `@rocky-interface/src/lib/styles/global.css`:
- Around line 9-15: The .main-content CSS class is defined twice with
conflicting overflow rules (visible here vs hidden in dashboard.css); rename one
of the classes (e.g., .main-content -> .global-main-content or .dashboard-main)
or consolidate into a single shared class to remove the conflict, then update
all usages in templates/components that reference .main-content (search for
elements using the .main-content selector) and adjust the CSS in either the
current stylesheet or dashboard.css (and remove the duplicate definition) so
only one authoritative rule remains.
- Line 5: The font-family declaration currently quotes system font keywords and
lacks a generic fallback; update the font-family rule (the font-family
declaration in global.css) to remove quotes around ui-sans-serif and system-ui,
keep or remove quotes for custom fonts "National" and "Soho" as desired, and
append a generic fallback like sans-serif at the end of the stack so the final
value uses unquoted system keywords and includes sans-serif.
In `@rocky-interface/src/lib/styles/login.css`:
- Line 38: Update the font-family declaration in login.css (the font-family rule
shown) to mirror the global.css fix: remove unnecessary quotes around system
font keywords (e.g., National, Soho, ui-sans-serif, system-ui) and append the
standard system-font fallbacks and a generic fallback (include -apple-system,
BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, and finally
sans-serif) so the rule uses unquoted system font keywords and a robust fallback
stack.
In `@rocky-interface/src/lib/styles/sidebar.css`:
- Around line 11-22: Remove the stray blank line inside the .nav-link rule
before the color declaration: open the .nav-link CSS block (selector .nav-link)
and delete the empty line so the color: `#FFFFFF`; sits directly with the other
declarations, then run stylelint to confirm the whitespace warning is resolved.
In `@rocky-interface/src/routes/DBtest/`+page.svelte:
- Around line 14-17: The loadUsers function lacks response-status checks and
error handling: wrap the fetch in try/catch, verify the Response.ok before
calling res.json(), and handle non-ok responses (log/throw or set a safe
fallback for users). Update the async function loadUsers to check res.ok and
handle/parses error payloads appropriately, and ensure the users variable is
assigned a sensible default on failure to avoid downstream errors.
- Around line 39-44: The deleteUser function calls loadUsers() without awaiting
it, causing the UI to refresh before deletion completes; update the deleteUser
implementation (the async function deleteUser) to await loadUsers() after the
fetch completes (same pattern used in addUser) so the UI updates only after the
delete request and reload finish.
- Around line 20-36: The addUser function calls loadUsers() without awaiting it
and lacks error handling and uses hardcoded test values; update addUser to await
the POST response, wrap the network calls in try/catch to handle and log/display
errors, and await loadUsers() (i.e., await loadUsers()) before clearing inputs
so the UI waits for the refresh; also replace or surface the hardcoded flash_id
and role (e.g., make flash_id and role parameters/variables or add a clear
comment that they are test values) to avoid leaving test/demo values in
production.
---
Nitpick comments:
In `@burndown/burndown.py`:
- Around line 15-73: The module runs script logic at import time; wrap the
top-level workflow (loading CSV, parsing dates, computing actual/ideal lines,
and plotting) into a new main() function and leave utility functions like
parse_datetime at module scope so they remain importable; call main() under an
if __name__ == "__main__": guard and ensure main references existing symbols
(CSV_FILE, CREATED_COLUMN, CLOSED_COLUMN, PROJECT_START, PROJECT_END) and
returns/handles errors as before.
- Around line 42-48: The current O(n×m) loop over actual_dates repeatedly
filters df (variables: remaining, actual_dates, df, CLOSED_COLUMN), so replace
it with a vectorized approach: extract and sort closed_dates =
df[CLOSED_COLUMN].dropna().sort_values().to_numpy(), compute cumulative closed
counts for each date using numpy.searchsorted (closed_count =
np.searchsorted(closed_dates, actual_dates, side='right')), then set remaining =
total_issues - closed_count (where total_issues = len(df)); this avoids repeated
DataFrame filtering and handles open issues (NaNs) by excluding them from
closed_dates.
In `@burndown/milestone_burndown.py`:
- Around line 1-73: This file duplicates most logic from burndown.py; extract
shared behavior into a new module (e.g., burndown_common.py) that exposes
functions like load_issues(csv_file, created_col="createdAt",
closed_col="closedAt") which encapsulates the CSV loading and the
parse_datetime(series) helper, compute_burndown(df, closed_col, start, end,
today) which returns actual_dates and remaining and all_dates and ideal_line,
and plot_burndown(actual_dates, remaining, all_dates, ideal_line, title) which
contains the matplotlib plotting; then simplify milestone_burndown.py to call
load_issues(CSV_FILE), compute_burndown(df, CLOSED_COLUMN, PROJECT_START,
PROJECT_END, today) and plot_burndown(...) while preserving the existing
constants (CSV_FILE, CREATED_COLUMN, CLOSED_COLUMN, PROJECT_START, PROJECT_END)
and function names (parse_datetime, compute_burndown, plot_burndown) to make the
refactor minimal and maintain behavior.
In `@burndown/README.md`:
- Line 3: Change the "### Get to repository in your CLI" heading to a
second-level heading (use "##") to fix the h1→h3 jump, and update all fenced
code blocks in burndown/README.md to include a language identifier (e.g.,
```bash or ```shell) so the linter can apply syntax highlighting; target the
README heading and any code fences shown around the repository/CLI examples to
make these edits.
In `@rocky-backend/main.py`:
- Around line 57-62: create_course currently inserts the incoming payload
directly via courses.insert_one without a timestamp; before inserting, add a
created_at timestamp on the data (matching the same format used by create_user
and create_api_key) and ensure the datetime import is present so created_at is
populated (e.g., UTC ISO or the project's existing format) before calling
courses.insert_one(data).
In `@rocky-backend/src/app.html`:
- Around line 1-11: This SvelteKit HTML template (app.html) containing markers
like %sveltekit.head% and %sveltekit.body% and the body attribute
data-sveltekit-preload-data="hover" should be removed from the Flask-only
backend or moved into the frontend/SvelteKit repo; either delete this file from
rocky-backend or relocate it to the SvelteKit project, and update any
build/deploy configs that referenced %sveltekit.head%/%sveltekit.body% so the
backend has no ambiguous frontend template artifacts.
In `@rocky-backend/test_db.py`:
- Around line 6-16: Add a tearDown to BaseTest to ensure test isolation by
clearing or resetting the in-memory collections after each test; for example,
implement BaseTest.tearDown that calls main.users.delete_many({}),
main.courses.delete_many({}), and main.api_keys.delete_many({}) (or
reinstantiates MongitaClientMemory and rebinds
main.users/main.courses/main.api_keys) so no data persists between tests started
in setUp.
- Around line 30-40: In test_get_users, after creating the user via
self.client.post("/users", ...), assert the GET /users response body contains
the created user: parse response.json() (response variable) and verify the list
includes an entry with name "Bob", email "bob@example.com" and flash_id "bob123"
(and optionally role "student"), and also assert expected list length or that at
least one matching user exists; update test_get_users to perform these JSON
assertions instead of only checking response.status_code.
In `@rocky-interface/src/lib/components/cards/CourseCard.svelte`:
- Line 24: The "Go to Course →" button in CourseCard.svelte currently has no
click handler; either wire it up or visibly mark it as non-functional: add an
on:click handler on the button with the intended navigation callback (e.g., call
a prop function like onNavigate or dispatch a Svelte event from CourseCard) and
ensure both card and list render paths use the same .go-btn element, or if it's
intentionally a placeholder, add disabled attribute and a TODO comment above the
<button class="go-btn"> element indicating future behavior. Reference the
CourseCard.svelte component and the .go-btn button when making the change so
both modes are updated consistently.
In `@rocky-interface/src/lib/components/Sidebar.svelte`:
- Around line 12-14: The template is using unnecessary casts of `frame` to
`frameName`; since `primaryFrames` is already `frameName[]`, remove the
redundant `as frameName` occurrences in the each block so the button uses
`{$currentFrame === frame}`, `on:click={() => currentFrame.set(frame)}`, and
`{toLabel(frame)}` directly; update the `each` block to reference `frame`
without casting (symbols: primaryFrames, frame, currentFrame, toLabel).
- Around line 1-9: Remove the leading tab before the <script lang="ts"> tag in
Sidebar.svelte so the file starts with the script tag at column 0 (normalize
whitespace); update the file header to eliminate that leading whitespace and
reformat the file (or run the project's formatter) to ensure the <script> tag
and the constants/functions like currentFrame, frameMap, frames, primaryFrames,
and toLabel remain unchanged.
In `@rocky-interface/src/lib/styles/login.css`:
- Around line 3-15: The .background CSS rule contains unnecessary blank lines
before some declarations that trigger stylelint; edit the .background rule to
remove the empty lines (so declarations like display, place-items,
background-image, background-size, background-position, background-repeat,
background-attachment appear without extra blank lines between them) to satisfy
stylelint's spacing rules and keep formatting consistent.
In `@rocky-interface/src/routes/DBtest/`+page.svelte:
- Around line 55-57: The form currently allows submitting empty values; add
validation around the bound variables name and email and prevent submission when
invalid by updating the button to be disabled when name or email are
empty/whitespace and by adding a guard in the addUser function that trims
inputs, checks non-empty (and optionally a simple email regex) and returns early
(or shows an error) if validation fails; reference the input bindings name and
email and the click handler addUser to implement both UI-disable and safe
server-side guard.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8729dd3b-ef80-4677-8b1c-215e079f05ad
⛔ Files ignored due to path filters (6)
package-lock.jsonis excluded by!**/package-lock.jsonrocky-backend/src/lib/assets/favicon.svgis excluded by!**/*.svgrocky-interface/package-lock.jsonis excluded by!**/package-lock.jsonrocky-interface/static/commencement_dark.jpgis excluded by!**/*.jpgrocky-interface/static/ksu_horizontal.pngis excluded by!**/*.pngrocky-interface/static/rock.pngis excluded by!**/*.png
📒 Files selected for processing (51)
api-key-gen/.gitignoreapi-key-gen/README.mdburndown/README.mdburndown/burndown.pyburndown/commandToGetCSV.txtburndown/milestone_burndown.pyrocky-backend/.gitignorerocky-backend/README.mdrocky-backend/main.pyrocky-backend/src/app.d.tsrocky-backend/src/app.htmlrocky-backend/src/lib/index.tsrocky-backend/test_db.pyrocky-interface/.gitignorerocky-interface/.npmrcrocky-interface/.prettierignorerocky-interface/.prettierrcrocky-interface/README.mdrocky-interface/package.jsonrocky-interface/src/app.cssrocky-interface/src/app.d.tsrocky-interface/src/app.htmlrocky-interface/src/lib/components/Sidebar.svelterocky-interface/src/lib/components/Topbar.svelterocky-interface/src/lib/components/WidgetPanel.svelterocky-interface/src/lib/components/cards/CourseCard.svelterocky-interface/src/lib/components/cards/WidgetCard.svelterocky-interface/src/lib/components/views/AccountView.svelterocky-interface/src/lib/components/views/AnalyticsView.svelterocky-interface/src/lib/components/views/CoursesView.svelterocky-interface/src/lib/components/views/DashboardView.svelterocky-interface/src/lib/components/views/HelpView.svelterocky-interface/src/lib/components/views/UsersView.svelterocky-interface/src/lib/stores/frameStore.tsrocky-interface/src/lib/styles/app-layout.cssrocky-interface/src/lib/styles/course-card.cssrocky-interface/src/lib/styles/dashboard.cssrocky-interface/src/lib/styles/global.cssrocky-interface/src/lib/styles/login.cssrocky-interface/src/lib/styles/sidebar.cssrocky-interface/src/lib/styles/topbar.cssrocky-interface/src/lib/styles/widget-panel.cssrocky-interface/src/routes/+layout.svelterocky-interface/src/routes/+page.svelterocky-interface/src/routes/DBtest/+page.svelterocky-interface/src/routes/login/+page.svelterocky-interface/static/robots.txtrocky-interface/svelte.config.jsrocky-interface/tsconfig.jsonrocky-interface/vite.config.tstest.txt
💤 Files with no reviewable changes (1)
- test.txt
| * | ||
| !test_db.py |
There was a problem hiding this comment.
* here will hide nearly the entire backend from source control.
Ignoring everything and only unignoring test_db.py will cause new backend code/docs/config to be skipped unless manually force-added. That’s a high-risk default for maintainability and CI reliability.
Suggested safer `.gitignore` shape
-*
-!test_db.py
-__pycache__
-../mongita
+__pycache__/
+*.py[cod]
+.pytest_cache/
+.mypy_cache/
+.venv/
+venv/
+mongita/🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rocky-backend/.gitignore` around lines 2 - 3, The .gitignore currently uses a
global ignore pattern "*" with an exception for "!test_db.py", which hides the
entire repository from source control; remove or replace the broad "*" entry and
instead list specific ignore patterns (e.g., build/, *.pyc, .env, node_modules,
dist/, etc.) so that source folders and config are tracked, and remove the
inverted-exception "!test_db.py" (or convert to explicit allow rules) so only
intended files are ignored; locate the lines containing the "*" and
"!test_db.py" tokens and replace them with a conservative set of ignores that do
not exclude the backend code, docs, or config.
| @app.route("/users", methods=["POST"]) | ||
| def create_user(): | ||
| # Expected: { name, email, flash_id, role: "student"|"instructor"|"admin" } | ||
| data = request.json | ||
| data["created_at"] = datetime.now(timezone.utc).isoformat() | ||
| users.insert_one(data) | ||
| return jsonify({"message": "User created"}) |
There was a problem hiding this comment.
Guard against missing request body.
request.json returns None when the request lacks a JSON body or has invalid JSON. Accessing data["created_at"] on None will raise a TypeError. This affects all POST/PUT handlers.
Proposed fix
`@app.route`("/users", methods=["POST"])
def create_user():
# Expected: { name, email, flash_id, role: "student"|"instructor"|"admin" }
data = request.json
+ if not data:
+ return jsonify({"error": "Request body required"}), 400
data["created_at"] = datetime.now(timezone.utc).isoformat()
users.insert_one(data)
return jsonify({"message": "User created"})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @app.route("/users", methods=["POST"]) | |
| def create_user(): | |
| # Expected: { name, email, flash_id, role: "student"|"instructor"|"admin" } | |
| data = request.json | |
| data["created_at"] = datetime.now(timezone.utc).isoformat() | |
| users.insert_one(data) | |
| return jsonify({"message": "User created"}) | |
| `@app.route`("/users", methods=["POST"]) | |
| def create_user(): | |
| # Expected: { name, email, flash_id, role: "student"|"instructor"|"admin" } | |
| data = request.json | |
| if not data: | |
| return jsonify({"error": "Request body required"}), 400 | |
| data["created_at"] = datetime.now(timezone.utc).isoformat() | |
| users.insert_one(data) | |
| return jsonify({"message": "User created"}) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rocky-backend/main.py` around lines 20 - 26, The create_user handler assumes
request.json is present; if request.json is None accessing data["created_at"]
will crash. Update the create_user function to validate the JSON body: check if
request.json (data) is None and return a 400/JSON error response when missing or
invalid, and verify required fields (e.g., name, email, flash_id, role) before
mutating/using data; only then set data["created_at"] and call
users.insert_one(data). Apply the same guard pattern to other POST/PUT handlers
that read request.json to prevent TypeError on missing/invalid JSON.
| def get_user(user_id): | ||
| user = users.find_one({"_id": ObjectId(user_id)}) | ||
| if not user: | ||
| return jsonify({"error": "User not found"}), 404 | ||
| user["_id"] = str(user["_id"]) | ||
| return jsonify(user) |
There was a problem hiding this comment.
Handle invalid ObjectId gracefully.
If user_id is not a valid 24-character hex string, ObjectId(user_id) raises bson.errors.InvalidId, resulting in an unhandled 500 error. This applies to all routes using ObjectId() (Lines 37, 46, 51, 73, 82, 87, 110, 118).
Proposed fix for get_user (apply similar pattern to other routes)
+from bson.errors import InvalidId
+
`@app.route`("/users/<user_id>", methods=["GET"])
def get_user(user_id):
+ try:
+ oid = ObjectId(user_id)
+ except InvalidId:
+ return jsonify({"error": "Invalid user ID format"}), 400
- user = users.find_one({"_id": ObjectId(user_id)})
+ user = users.find_one({"_id": oid})
if not user:
return jsonify({"error": "User not found"}), 404
user["_id"] = str(user["_id"])
return jsonify(user)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rocky-backend/main.py` around lines 36 - 41, The get_user route (and all
routes that call ObjectId(user_id)) must validate/handle invalid ObjectId values
to avoid unhandled bson.errors.InvalidId exceptions: wrap the ObjectId(...)
conversion in a try/except catching bson.errors.InvalidId (or validate the
24-hex format first) and return a 400 Bad Request JSON error when invalid;
update functions like get_user and the other handlers that call ObjectId to
perform this try/except, import InvalidId from bson.errors, and ensure
successful conversions proceed to query the users collection and return 404 if
not found.
| if __name__ == "__main__": | ||
| app.run(debug=True, port = 5001) No newline at end of file |
There was a problem hiding this comment.
Do not deploy with debug=True.
The Werkzeug debugger exposes an interactive console that can execute arbitrary code if reached. Use environment variables or Flask configuration to control debug mode.
Proposed fix using environment variable
+import os
+
if __name__ == "__main__":
- app.run(debug=True, port = 5001)
+ app.run(debug=os.getenv("FLASK_DEBUG", "false").lower() == "true", port=5001)🧰 Tools
🪛 ast-grep (0.41.1)
[warning] 121-121: Detected Flask app with debug=True. Do not deploy to production with this flag enabled as it will leak sensitive information. Instead, consider using Flask configuration variables or setting 'debug' using system environment variables.
Context: app.run(debug=True, port = 5001)
Note: [CWE-489] Active Debug Code. [REFERENCES]
- https://labs.detectify.com/2015/10/02/how-patreon-got-hacked-publicly-exposed-werkzeug-debugger/
(debug-enabled-python)
🪛 Ruff (0.15.6)
[error] 122-122: Use of debug=True in Flask app detected
(S201)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rocky-backend/main.py` around lines 121 - 122, app.run is currently invoked
with debug=True which enables the unsafe Werkzeug interactive debugger; change
this to read debug mode from configuration or an environment variable instead
(e.g., use os.environ.get('FLASK_DEBUG') or app.config['DEBUG'] to determine the
boolean) and pass that value to app.run(debug=...) or omit debug and rely on
Flask config so debug is disabled in production; ensure any environment value is
parsed to a boolean before passing to app.run.
|
|
||
| <div class="page-layout"> | ||
| <div class="main-content"> | ||
| <svelte:component this={frameMap[$currentFrame as frameName]} /> |
There was a problem hiding this comment.
Guard dynamic frame lookup before mounting the component.
On Line 10, frameMap[$currentFrame as frameName] can be undefined; mounting an undefined component risks a runtime crash. Add a fallback render path.
💡 Proposed fix
<div class="main-content">
- <svelte:component this={frameMap[$currentFrame as frameName]} />
+ {`#if` frameMap[$currentFrame as frameName]}
+ <svelte:component this={frameMap[$currentFrame as frameName]} />
+ {:else}
+ <p>Unable to load the selected view.</p>
+ {/if}
</div>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <svelte:component this={frameMap[$currentFrame as frameName]} /> | |
| <div class="main-content"> | |
| {`#if` frameMap[$currentFrame as frameName]} | |
| <svelte:component this={frameMap[$currentFrame as frameName]} /> | |
| {:else} | |
| <p>Unable to load the selected view.</p> | |
| {/if} | |
| </div> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rocky-interface/src/routes/`+page.svelte at line 10, Guard the dynamic
component lookup before mounting: check whether frameMap[$currentFrame as
frameName] is defined before using <svelte:component this={...}> and render a
fallback (e.g., a placeholder message or null) when it's undefined. Locate the
dynamic mount using the symbols frameMap, $currentFrame (frameName) and
svelte:component and update the template to conditionally render the component
only if the lookup yields a value, otherwise render the fallback UI to avoid
runtime crashes.
|
|
||
|
|
||
| async function loadUsers() { | ||
| const res = await fetch('http://localhost:5001/users'); |
There was a problem hiding this comment.
Hardcoded localhost URL won't work in production.
The API URL http://localhost:5001 is hardcoded throughout this file (lines 15, 21, 40). This will break in any non-local environment.
Consider using an environment variable or a centralized API configuration:
♻️ Suggested approach
Create a shared API config or use SvelteKit's environment variables:
// In a shared config file, e.g., $lib/config.ts
export const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:5001';Then import and use it:
+import { API_BASE_URL } from '$lib/config';
+
async function loadUsers() {
- const res = await fetch('http://localhost:5001/users');
+ const res = await fetch(`${API_BASE_URL}/users`);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rocky-interface/src/routes/DBtest/`+page.svelte at line 15, The fetch calls
in +page.svelte are using a hardcoded base URL ('http://localhost:5001') which
will fail in production; create a shared API base constant (e.g., export
API_BASE_URL from a new $lib/config.ts that reads import.meta.env.VITE_API_URL
|| 'http://localhost:5001') and replace all direct uses of
'http://localhost:5001' in this file (the const res = await fetch(...) calls)
with fetch(`${API_BASE_URL}/users`) (or equivalent endpoints) by importing
API_BASE_URL into DBtest/+page.svelte so environments can control the backend
URL.
| <button class="signin" > | ||
| Sign In | ||
| </button> |
There was a problem hiding this comment.
Sign-in control is non-functional.
On Lines 18-20, the button has no behavior, so users cannot initiate authentication from this page. Please wire it to the login/auth flow (form action or navigation handler).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rocky-interface/src/routes/login/`+page.svelte around lines 18 - 20, The Sign
In button (class "signin") has no behavior; add a click handler to initiate the
auth flow by implementing a handleSignIn function and wiring it to the button
(e.g., <button class="signin" on:click={handleSignIn}>). In handleSignIn (in the
same +page.svelte script) import goto from '$app/navigation' and call
goto('/auth/login') or the route that triggers your backend auth endpoint;
alternatively submit a form by placing the button inside a <form
action="/auth/login" method="post"> if you prefer server form flow. Ensure the
handler name handleSignIn and the "signin" button class are used so the change
is easy to locate.
Summary by CodeRabbit
New Features
Documentation
Chores