PRs reviewed: #1045, #1047, #1048, #1049, #1050, #1051, #1052, #1053, #1056, #1057, #1058, #1061, #1063, #1064, #1065, #1067, #1068, #1069, #1071, #1072, #1073
Verdict: All clear — 2 proactive security fixes landed this week, no new violations found.
Non-Negotiable Checklist
✅ Email Privacy — getRecentIssuesAction (new in #1061) returns only id, issueNumber, title, status, severity, priority, frequency, createdAt. No email or PII in the response payload. All other PRs are UI/layout changes with no new data serialization.
✅ Permissions Matrix Accuracy (CORE-ARCH-008) — #1045 is a direct fix for the previously-known matrix drift: comments.edit and comments.delete were true (unrestricted) for member/technician/admin in matrix.ts but server actions enforced owner-only. PR corrects all three roles to "own", updates descriptions, and adds ownership-context tests. Matrix and server actions now agree.
✅ Supabase SSR / Auth pattern — #1053 (mobile header redesign) uses a TypeScript discriminated union (isAuthenticated: true | false) fed from the server component in MainLayout. No client-side auth logic or session state introduced.
✅ Server-first / no unnecessary "use client" — New BottomTabBar (#1051) and MobileHeader (#1053) correctly isolate the "use client" boundary to the navigation client island; page shells remain server components.
✅ Input validation — New getRecentIssuesAction (#1061) validates machineInitials with a strict Zod regex (/^[A-Za-z0-9-]+$/, max 10 chars) and caps limit at 20. Generic error returned to caller; internal detail logged server-side only.
✅ Dependency security — #1067 patched GHSA-mw96-cpmx-2vgc (rollup prototype-pollution, build-time only) promptly via pnpm override. #1072 and #1073 are routine maintenance upgrades.
⬜ localhost domain standard — No new URLs or config files introduced this week.
⬜ Database migrations — No schema changes or migration files this week.
Broader Analysis
New unauthenticated surface: getRecentIssuesAction (#1061)
This server action is intentionally unauthenticated (it lives on the public /report page). It allows any caller to retrieve up to 20 recent issues for a given machine by initials. Since PinPoint is a single-tenant, semi-public issue tracker for the Austin Pinball Collective, issue titles and statuses are considered non-sensitive public information. The input constraint (/^[A-Za-z0-9-]+$/) prevents injection; the limit cap prevents bulk scraping. No concern.
Permissions matrix fix closes a real integrity gap (#1045)
The old matrix claimed members and higher could edit/delete any comment, which contradicted server action enforcement. This was discovered and fixed correctly — the matrix now shows "own" for all roles, matching the actual runtime behavior. Positive security practice.
GitHub Actions workflow changes (#1068, #1069, #1071)
Removing the Claude Code Review action (#1071) eliminates one external API call in CI, reducing supply chain surface. The remaining review scripts invoke project-local bash scripts rather than third-party marketplace actions — a sound practice.
jsdom 27→28 upgrade (#1073)
jsdom is used in test infrastructure only, not for runtime HTML parsing of user content. The v28 upgrade (resource loading API overhaul, MIME sniffing fixes) poses no production risk.
Recommendations
No remediation required. Positive practices to note for continued compliance:
- Continue CORE-ARCH-008 discipline — the permissions matrix fix this week is exactly the kind of proactive correction that prevents help-page misinformation from shipping. Consider adding a CI lint rule that alerts when
matrix.ts and actions diverge (e.g., by running a comparison script).
- Document
getRecentIssuesAction as intentionally public — a brief comment noting "no auth required — issues are public information on this single-tenant tracker" would help future reviewers confirm this was a deliberate decision rather than a forgotten auth check.
Generated by Weekly Security Review Agent
PRs reviewed: #1045, #1047, #1048, #1049, #1050, #1051, #1052, #1053, #1056, #1057, #1058, #1061, #1063, #1064, #1065, #1067, #1068, #1069, #1071, #1072, #1073
Verdict: All clear — 2 proactive security fixes landed this week, no new violations found.
Non-Negotiable Checklist
✅ Email Privacy —
getRecentIssuesAction(new in #1061) returns onlyid, issueNumber, title, status, severity, priority, frequency, createdAt. No email or PII in the response payload. All other PRs are UI/layout changes with no new data serialization.✅ Permissions Matrix Accuracy (CORE-ARCH-008) — #1045 is a direct fix for the previously-known matrix drift:
comments.editandcomments.deleteweretrue(unrestricted) for member/technician/admin inmatrix.tsbut server actions enforced owner-only. PR corrects all three roles to"own", updates descriptions, and adds ownership-context tests. Matrix and server actions now agree.✅ Supabase SSR / Auth pattern — #1053 (mobile header redesign) uses a TypeScript discriminated union (
isAuthenticated: true | false) fed from the server component in MainLayout. No client-side auth logic or session state introduced.✅ Server-first / no unnecessary
"use client"— NewBottomTabBar(#1051) andMobileHeader(#1053) correctly isolate the"use client"boundary to the navigation client island; page shells remain server components.✅ Input validation — New
getRecentIssuesAction(#1061) validatesmachineInitialswith a strict Zod regex (/^[A-Za-z0-9-]+$/, max 10 chars) and capslimitat 20. Generic error returned to caller; internal detail logged server-side only.✅ Dependency security — #1067 patched GHSA-mw96-cpmx-2vgc (rollup prototype-pollution, build-time only) promptly via pnpm override. #1072 and #1073 are routine maintenance upgrades.
⬜ localhost domain standard — No new URLs or config files introduced this week.
⬜ Database migrations — No schema changes or migration files this week.
Broader Analysis
New unauthenticated surface:
getRecentIssuesAction(#1061)This server action is intentionally unauthenticated (it lives on the public
/reportpage). It allows any caller to retrieve up to 20 recent issues for a given machine by initials. Since PinPoint is a single-tenant, semi-public issue tracker for the Austin Pinball Collective, issue titles and statuses are considered non-sensitive public information. The input constraint (/^[A-Za-z0-9-]+$/) prevents injection; the limit cap prevents bulk scraping. No concern.Permissions matrix fix closes a real integrity gap (#1045)
The old matrix claimed members and higher could edit/delete any comment, which contradicted server action enforcement. This was discovered and fixed correctly — the matrix now shows
"own"for all roles, matching the actual runtime behavior. Positive security practice.GitHub Actions workflow changes (#1068, #1069, #1071)
Removing the Claude Code Review action (#1071) eliminates one external API call in CI, reducing supply chain surface. The remaining review scripts invoke project-local bash scripts rather than third-party marketplace actions — a sound practice.
jsdom 27→28 upgrade (#1073)
jsdom is used in test infrastructure only, not for runtime HTML parsing of user content. The v28 upgrade (resource loading API overhaul, MIME sniffing fixes) poses no production risk.
Recommendations
No remediation required. Positive practices to note for continued compliance:
matrix.tsand actions diverge (e.g., by running a comparison script).getRecentIssuesActionas intentionally public — a brief comment noting "no auth required — issues are public information on this single-tenant tracker" would help future reviewers confirm this was a deliberate decision rather than a forgotten auth check.