refactor(frontend): seal readonly leaks + exactOptional casts (Group 70: #1593, #1594, #1590)#1597
Merged
Merged
Conversation
…1593) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…a satisfies (#1590) Flip 'as Camper' to 'satisfies Camper', which surfaced two masked exactOptionalPropertyTypes violations: assigned_bunk_cm_id (number|undefined into optional ?:number) now conditional-spread, and expand.session/ .assigned_bunk (undefined into optional ?:...|null) now coerced with ?? null. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nest via satisfies (#1590) Flip 'as SiblingWithEnrollment' to 'satisfies'. Type session_type as the CampSessionsSessionTypeOptions enum (matches the literal), conditional-spread the optional session key instead of assigning explicit undefined, and drop the manual 's is SiblingWithEnrollment' predicate in favor of TS6's inferred narrowing (the precise literal type is a subtype, satisfying the return type). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The satisfies Camper change makes the literal's expand known-present, so the optional chain on a.expand/b.expand in the sort comparator is provably redundant (eslint no-unnecessary-condition). Tighten to a.expand.session. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughSealed readonly array leaks in the graph rendering pipeline and replaced unsafe type casts with satisfies checks in camper enrollment hooks to enforce immutability and exactOptionalPropertyTypes compliance. ChangesGraph immutability enforcement
Camper and sibling type safety
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Assessment against linked issues
Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
adamflagg
added a commit
that referenced
this pull request
May 21, 2026
#1598) Closes #1596. Finishes the app-types `readonly` contract opened by #1595 — same latent readonly-leak class as the graph-type follow-ups #1593/#1594 (shipped in #1597). Two consumers were intentionally left out of #1595 to keep that a pure type-only change. ## Changes 1. **`AllCampersView.tsx`** — drop the now-redundant `as Camper[]` cast. #1595 widened `buildCamperRows` to accept `readonly Camper[]` (`csvExportHelpers.ts:73`), and `filteredCampers` is `MergedCamper[]` (`MergedCamper extends Camper`), so it's directly assignable. The standing cast only suppressed future compiler signal if the contract changed. 2. **`mergeMultiSessionCampers.ts`** — mark `AdditionalSession`'s fields and `MergedCamper.additionalSessions` `readonly`, matching the now-`readonly` `Camper` that `MergedCamper` extends. The builder constructs each `AdditionalSession` via `.map()` into fresh objects, so the element type going `readonly` is a clean change. Pure type-only hardening — **no runtime behavior change**, no active mutation existed. ## Tests Adds the first tests for `mergeMultiSessionCampers` (previously untested): - **Behavioral coverage** — multi-enrollment merge produces one entry with `additionalSessions`; single-session camper untouched. - **Readonly contract** — `@ts-expect-error` assertions enforced by `tsc --noEmit`. Verified red→green: before the change the directives are unused (TS2578); after, they type-check. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added comprehensive test suite for multi-session camper merging functionality, including validation of camper data consolidation and immutability constraints. * **Refactor** * Enhanced type safety in CSV export and camper data handling to prevent potential bugs and ensure data integrity during export operations. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/adamflagg/kindred/pull/1598?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1593, closes #1594, closes #1590.
Group 70 — type-safety follow-ups deferred out of the §3 frontend-modernization PRs (#1585–#1592). Pure type-only hardening; no runtime behavior change. Each fix makes a type honest so a load-bearing cast can be deleted or flipped to
satisfies.Changes
createGraphElements's four array params toreadonly+ narrow graph.tsCrossScopeEdge.edge_typeto'request'(matches the generated type; the API only emits'request'cross-scope edges). All fouras Parameters<…>[N]casts atSocialNetworkGraph.tsxare deleted.BunkGraphData.nodes/.edgesreadonly. Theas unknown as BunkGraphDatastays (the cachedGraphDatastructurally diverges —bunk_cm_id/bunk_name/metrics/health_score), but downstream read-only protection is restored.ascasts mask exactOptionalPropertyTypes mismatches (blockssatisfies) #1590 — make two literals honest underexactOptionalPropertyTypes:useCamperEnrollment: flippingas Camper→satisfies Campersurfaced two masked violations —assigned_bunk_cm_id(number | undefinedinto optional?: number, now conditional-spread) andexpand.session/.assigned_bunk(explicitundefinedinto?: … | null, now?? null). Also tightened a now-redundantexpand?.optional chain.useSiblings:as SiblingWithEnrollment→satisfies; conditional-spread the optionalsessionkey; typedsession_typeas theCampSessionsSessionTypeOptionsenum; dropped the manuals is SiblingWithEnrollmentpredicate in favor of TS 6's inferred narrowing (the precise literal type is a subtype, satisfying the hook's return boundary).Test Plan
npm run type-checkpasses (bothtsconfig.json+tsconfig.node.json) — each cast was verified load-bearing (removed → tsc fails) before its supporting type change.npm run lint— 0 errors, no new warnings (the two introduced by the type-honesty change are fixed).npx vitest run— 4450 pass, 0 fail.🤖 Generated with Claude Code
Summary by CodeRabbit