test: activation privacy contract test - #20
Conversation
Source-level contract test that asserts the fleet 4-event taxonomy (signup/activated/core_action/returned) never carries resume text, job descriptions, stash content, cover letters, fit-score payloads, or credentials. Guards the privacy boundary at the source level so a future regression that passes a private variable into trackActivated or trackCoreAction fails before it ships. Closes part of the automate-portfolio-identity-toolbox OpenSpec change. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9694852a49
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // payload fields beyond project_id / action. The surrounding file | ||
| // legitimately mentions "resume-tailor" (project slug) and | ||
| // "cover_letter_generated" (action enum) — those are not payload fields. | ||
| const mapBlock = analytics.match(/interface AnalyticsEventMap\s*\{([\s\S]*?)\}/)?.[1] ?? ''; |
There was a problem hiding this comment.
Fix AnalyticsEventMap extraction to scan the whole interface
When AnalyticsEventMap contains object-shaped members, this non-greedy regex stops at the first } inside the interface, which is the end of the signup property type. That means the negative field scan never sees activated, core_action, returned, or any later added event, so a future extra: { project_id: typeof PROJECT; resume: string } declaration after signup would still pass this contract test even though it violates the 4-event privacy contract.
Useful? React with 👍 / 👎.
| expect(analytics).toMatch( | ||
| /export function trackEvent\(\s*event:\s*string,\s*properties:\s*Record<string,\s*unknown>\s*=\s*\{\},\s*distinctId\?:\s*string\s*\)/ | ||
| ); |
There was a problem hiding this comment.
Make trackEvent test reject arbitrary properties
This assertion currently blesses properties: Record<string, unknown>, which is exactly what allows a direct call such as trackEvent('core_action', { resume: resumeSource }) to compile and pass the suite. Since the test does not scan direct trackEvent call sites for private keys, it does not enforce the stated privacy contract that raw private payloads must not enter analytics events.
Useful? React with 👍 / 👎.
Summary
__tests__/activation-privacy-contract.test.ts— a source-level contract test that asserts the fleet 4-event taxonomy (signup/activated/core_action/returned) never carries resume text, job descriptions, stash content, cover letters, fit-score payloads, or credentials.AnalyticsEventMaponly declaresproject_id(andactionforcore_action), theCoreActionenum is closed to the three product verbs, everytrackActivated/trackCoreActioncall site intailor-action.ts,cover-letter-action.ts, andfit-score-action.tspasses only the allowed arguments, andtrackEventdoes not accept raw private payloads.Closes task 2.2 of the
automate-portfolio-identity-toolboxOpenSpec change.Test plan
pnpm vitest run __tests__/activation-privacy-contract.test.ts→ 6/6 passpnpm biome check __tests__/activation-privacy-contract.test.ts→ cleanGenerated with Devin