fix: require caller-chosen project for addNote support tickets - #46
Open
detail-app[bot] wants to merge 1 commit into
Open
detail-app[bot] wants to merge 1 commit into
detail-app[bot] wants to merge 1 commit into
Conversation
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.
Detail bug report: View on Detail
Bug
NoteResolver.addNote(@Authorized(ADMIN, MANAGER)) optionally files a Linear support ticket viacreateSupportTicket, which runs a per-(project, type)dedup guard and embeds the project's mentors/Slack/GitHub-issue/event/description in the ticket. The resolver had noprojectIdargument and passedstudent.projects[0](loaded via a relation include with noorderBy/where/take) into both the dedup guard and the ticket body.For a student on more than one project (reachable through the
addProjectStudentmutation, which connects without disconnecting prior projects), this selects a project not chosen by the caller:createSupportTicketthrows and the note is never persisted, silently dropping a legitimate first-time escalation for the manager's intended project (with a message indistinguishable from a real duplicate).Fix
Make project selection caller-chosen and fail closed when ambiguous, mirroring
SupportTicketResolver.createSupportTicketwhich already takes an explicitprojectId:@Arg('projectId', () => String, { nullable: true }) projectId?: stringtoaddNote.src/linear/selectProjectForSupportTicket.ts(following the existingsrc/linear/pure-function convention):projectIdsupplied → return the member's matching project, else throwStudent is not a member of the specified project.projectId→ throwStudent is on multiple projects; projectId is required to file a support ticket.(distinct from the dedup message, so the manager knows to disambiguate rather than seeing a misleading duplicate error)if (supportTicketType && student.projects.length > 0)guard is preserved, so a student on zero projects still skips ticket filing and persists the note.The dedup guard (
hasExistingIssue, keyed bysearchLabel(type, project)=sha256(project.id,type)) and the ticket's project-context block now both target the caller-chosen project.Testing
tests/testSelectProjectForSupportTicket.ts,node:test+node:assert/strict, matching the convention intests/testSlackReporting.ts) covering: single-project (regression), multi-project fail-closed (order-independent), caller-chosen selection, invalid-projectIdmembership error, identical-instance return, and the empty-list contract. All 12 pass vianode --test --require ts-node/register/transpile-only.Container) confirmed: caller-chosenprojectIdfiles against the chosen project's mentors/issue-URL/Slack; the dedup guard aims at the chosen project (a chosen project without an open ticket files while one with an open ticket blocks); multi-project with noprojectIdfails closed with the ambiguity error (not the dedup message) and persists neither ticket nor note; membership errors throw before any Linear call; and single-project, zero-project, and no-supportTicketTypecases behave as before (note always persisted). This script was run during development but not versioned.authChecker, seeded Postgres viaprisma db push) confirmed the Linear-independent paths reproduce live: the ambiguity error and the membership error surface verbatim, omittingsupportTicketTypepersists the note with no ticket, and a validprojectIdproceeds past selection to the Linear boundary.createSupportTicket/hasExistingIssuemake a live Linear API call that rejected withAuthentication required, not authenticated...against the dummyLINEAR_API_KEYin the test environment. Completing that round-trip (filing against the chosen project; a project-A open ticket blockingprojectId=Abut notprojectId=B) requires realLINEAR_API_KEY/LINEAR_TEAM_ID/LINEAR_PROBLEM_LABEL_ID/LINEAR_BLOCKING_LABEL_ID. The per-chosen-project dedup behavior was otherwise covered by the fake-Linear end-to-end run above.npx tsc --skipLibCheck --noEmit) and the pre-existingtests/testSlackReporting.tsandsrc/automation/tasks/syncAlumniInteractions.test.tsall pass. (Note:npx eslintis currently broken in the repo due to an@typescript-eslint/parserv3 vs TypeScript 5.2 incompatibility —DeprecationError: 'originalKeywordKind'— and is not run by CI.)Automatic Fixes PRs can be configured here.