Skip to content

Patch Pkcs advisory; split DbContext, AuthController and student card; more tests - #66

Open
yt314 wants to merge 6 commits into
mainfrom
claude/nifty-franklin-cpn0wj
Open

yt314 wants to merge 6 commits into
mainfrom
claude/nifty-franklin-cpn0wj

Conversation

@yt314

@yt314 yt314 commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Summary

Follow-up to #65: a dependency security fix, three more large units split up, and tests for paths that had none. Behavior is unchanged.

Unit Before After
System.Security.Cryptography.Pkcs 10.0.0 (1 high, 1 moderate advisory) 10.0.13, vulnerability scan clean
TalmidonDbContext.cs 693 lines 145 lines + 22 IEntityTypeConfiguration classes
AuthController.cs 388 lines, uses DbContext directly 186 lines, HTTP only
student-detail.component.ts / .html 427 / 331 lines 240 / 193 lines
Backend tests 295 300
Frontend tests 89 105

Changes

Dependency security fix

  • MimeKit 4.18.1 (via MailKit) pulls in System.Security.Cryptography.Pkcs 10.0.0, which has two advisories: GHSA-846f-f764-76mx (high) and GHSA-2fmv-rv2c-59x7 (moderate).
  • Even the latest MimeKit only requires >= 10.0.0, so upgrading MailKit wouldn't help. A direct reference to 10.0.13 in Talmidon.Infrastructure lifts it, with a comment explaining why the reference exists.
  • dotnet list package --vulnerable --include-transitive is now clean for all three projects.

EF configuration: one class per entity (Data/Configurations/)

  • Each entity has its own IEntityTypeConfiguration class, applied with ApplyConfigurationsFromAssembly. The fluent bodies were moved verbatim.
  • This also fixes a naming problem: ConfigureTeacher used to configure CalendarEvent, ContactRequest, SiteFeedback and SubjectSuggestion as well.
  • The context now holds only tenant isolation: the query filters and the TenantId enforcement on save.
  • No migration is needed. Model.ToDebugString() and GenerateCreateScript() are byte-identical before and after. To confirm the comparison catches changes, I made a deliberate one-character change (a max length 4000 → 4001), saw it in the diff, and reverted it.

Auth (Services/Auth/)

  • New tests first (LogoutAndResendTests), for the two endpoints that had none. They passed against the old code before the refactor:
    • Logout: revokes the caller's refresh token, leaves someone else's token working, and rejects anonymous calls.
    • Resend confirmation: sends a new email only for an unconfirmed account, nothing for a confirmed or unknown address, and returns an identical response body in every case.
  • The controller's logic moved into four services:
    • RefreshTokens: issue, rotate (with reuse detection that revokes the whole token family), revoke one (owner only), revoke all.
    • TenantResolver: the user's tenant by role.
    • AuthEmails: confirmation and password-reset emails, plus the Base64Url token encode/decode the links use.
    • TeacherRegistration: creates the user, role and teacher record in one transaction.
  • All response messages and the anti-enumeration behavior are unchanged. The confirmation link still prefers App:ApiBaseUrl over the request host.
  • ServiceError gains Unauthorized.
  • The duplicated doc comment on ConfirmEmail is merged into one.

Frontend: student card

  • StudentNotesCardComponent and StudentResourcesCardComponent were extracted from student-detail. Each had its own state, form, dialog and service, tied to the page only by the student id.
  • shared/dates/date-only.util.ts replaces three identical copies of toDateOnly (in students-list, student-detail and payments-list).
  • students-list was intentionally not split. Its methods are short, and its two dialogs are coupled on purpose by focus-handling code that stops "required" errors from flashing while a dialog opens. I added tests for its contact-request flow instead.

Testing

  • Backend: dotnet test, 300 of 300 pass.
  • Frontend: ng test, 105 of 105 pass (16 new). ng build is clean.
    • The two cards: create vs. update, validation, "visible to student" implying "visible to parent", URL trimming and the http-only check, delete only after confirmation.
    • toDateOnly: uses local time, not toISOString(), which would give the previous day in Israel for a midnight date.
    • students-list contact-request flow, which had no tests: the parent form is pre-filled, the new parent is linked to the student form, and the request is marked handled after saving. A deleted request falls back to a plain student form.
  • Browser (Playwright against the running API): 11 of 11 checks pass. Adding, editing and deleting a note (including the visibility tick), rejecting an invalid URL, adding a resource, and no page errors.

Notes for reviewers

  • Each commit stands on its own. Commit 5's message says all three toDateOnly copies were replaced; the student-detail one actually landed in commit 6. Each commit builds on its own.

Generated by Claude Code

MimeKit 4.18.1 (via MailKit) depends on Pkcs 10.0.0, which has a high
(GHSA-846f-f764-76mx) and a moderate (GHSA-2fmv-rv2c-59x7) advisory.
The latest MimeKit still only requires >= 10.0.0, so a direct reference
to 10.0.13 is what lifts it. `dotnet list package --vulnerable
--include-transitive` is now clean for all projects; 295 tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5ZtSuF2RvbretgLfz7fjJ
TalmidonDbContext.cs was 693 lines, mostly entity configuration — and
ConfigureTeacher also configured CalendarEvent, ContactRequest,
SiteFeedback and SubjectSuggestion. Each entity now has its own
IEntityTypeConfiguration in Data/Configurations (22 classes), applied
with ApplyConfigurationsFromAssembly. The context (145 lines) keeps
only what is about tenant isolation: the query filters and the
TenantId enforcement on save.

The bodies were moved verbatim. The EF model (ToDebugString) and the
generated create script are byte-identical before and after, so no
migration is needed; a deliberate one-character change was confirmed
to show up in that comparison. 295 tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5ZtSuF2RvbretgLfz7fjJ
Neither endpoint had a test. Logout: the caller's refresh token is
revoked, someone else's token is left working, and anonymous calls are
rejected. Resend-confirmation: another email only for an unconfirmed
account, nothing for a confirmed or unknown address, and the same
response body in every case. All five pass against the current code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5ZtSuF2RvbretgLfz7fjJ
AuthController (388 lines) used the DbContext directly for tokens,
tenants and registration. It is now 186 lines of HTTP mapping over
Services/Auth:

- RefreshTokens: issue, rotate (with reuse detection revoking the whole
  family), revoke one (owner only), revoke all
- TenantResolver: the user's tenant by role
- AuthEmails: confirmation and password-reset emails, plus the
  Base64Url token encode/decode the links use
- TeacherRegistration: user + role + teacher in one transaction

Responses, messages and the anti-enumeration behavior are unchanged;
the confirmation link still prefers App:ApiBaseUrl over the request
host. ServiceError gains Unauthorized. Also merges the duplicated doc
comment on ConfirmEmail. 300 tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5ZtSuF2RvbretgLfz7fjJ
The same local-date formatter was copied into students-list,
student-detail and payments-list. It now lives in
shared/dates/date-only.util.ts with tests, including the point of using
local time rather than toISOString() (which in Israel would give the
previous day for a midnight date-picker value).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5ZtSuF2RvbretgLfz7fjJ
student-detail hosted three features in one 427-line component. The
pedagogical notes and the learning resources each had their own state,
form, dialog and service, tied to the page only by the student id; they
are now StudentNotesCardComponent and StudentResourcesCardComponent.
student-detail is 240 lines (template 193).

Tests (16 new, 89 -> 105): both cards (create vs update, validation,
"visible to student" implying parent, URL trimming and http-only check,
delete after confirm), and the students-list contact-request flow, which
had no tests: prefilled parent form -> new parent linked to the student
form -> request marked handled after saving; a deleted request falls
back to a plain student form.

Verified in a browser against the running API: add/edit/delete a note,
reject an invalid URL, add a resource, no page errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5ZtSuF2RvbretgLfz7fjJ
@vercel

vercel Bot commented Oct 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
talmidon Ready Ready Preview Oct 21, 2026 8:25am UTC

This branch was successfully deployed

1 active deployment
Preview — 1d271637 Deployed Oct 20, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants