[CompatGuard] BREAKING: UserResponse.email removed — add deprecated alias before MR !4 merges
## CompatGuard Owner Issue — Contract 1
**Severity:** 🔴 HIGH — BREAKING
**MR:** [!4 — Proof: dynamic OSS contract gate](https://gitlab.com/gitlab-ai-hackathon/transcend/34816704/-/merge_requests/4)
**Pipeline:** [#2623964361](https://gitlab.com/gitlab-ai-hackathon/transcend/34816704/-/pipelines/2623964361)
**Owners notified:** `@frontend-team`, `@billing-platform`, `@api-platform`
---
### What broke
`samples/shopstack/head/api/users.ts` renames `UserResponse.email` → `UserResponse.primaryEmail` with no backward-compatible alias. Two runtime consumers were not updated:
| Consumer | Owner | Failure mode |
|---|---|---|
| `frontend/Profile.tsx` line 6 | `@frontend-team` | `user.email` → `undefined`; JSX renders blank `<p>` silently |
| `billing/customerSync.ts` line 5 | `@billing-platform` | `billingIdentity()` returns `{ email: undefined }`; billing sync corrupts identity |
### Prior incident
> 🔴 **Issue `#184`** — *Billing sync failed after user identity response changed* — HIGH severity
> `billing/customerSync.ts` is byte-for-byte identical to the base branch. This is the prior incident reproduced exactly, not a resemblance.
### Dynamic replay result
Both probes **FAILED**:
- Probe 1-A: `user.email` not in `{ id, primaryEmail, displayName, plan }` → ❌
- Probe 1-B: `billingIdentity().email` is `undefined` → ❌
### Required actions (P0 — must complete before MR !4 merges)
- [ ] `@api-platform` — Add `email: string` as a deprecated alias on `UserResponse` alongside `primaryEmail` for ≥ 1 release; populate in `serializeUser()`
- [ ] `@frontend-team` — Update `frontend/Profile.tsx` line 6 to read `primaryEmail` (or rely on alias)
- [ ] `@billing-platform` — Update `billing/customerSync.ts` line 5 to read `primaryEmail` — **repeat of issue `#184`**
### Suggested tests
```bash
npx tsc --strict --noEmit samples/shopstack/head/api/users.ts samples/shopstack/head/frontend/Profile.tsx
npx jest tests/compat/userResponse.email.test.ts tests/compat/billingIdentity.email.test.ts --no-coverage
```
Minimum assertion for billing regression guard:
```ts
it.each(["free", "pro", "enterprise"])("billingIdentity.email defined for plan %s", (plan) => {
const id = billingIdentity(serializeUser({ id: "u1", email: "a@b.com", displayName: "A", plan }));
expect(id.email).toBe("a@b.com"); // issue #184 regression guard
});
```
### GitLab artifacts
- `compatguard-report.md` — full gate ruling
- `compatguard-report.json` — machine-readable probe results
- `compatguard-generated/compatguard-test-plan.md` — per-probe test specifications
---
*Auto-created by CompatGuard MR Gatekeeper · Pipeline #2623964361 · Commit 84728869*
issue