Skip to content

feat: Add alias for sha256 identities#1252

Open
jamesnrokt wants to merge 10 commits intodevelopmentfrom
feat/add-alias-for-sha256-identities
Open

feat: Add alias for sha256 identities#1252
jamesnrokt wants to merge 10 commits intodevelopmentfrom
feat/add-alias-for-sha256-identities

Conversation

@jamesnrokt
Copy link
Copy Markdown
Collaborator

Background

  • Currently clients have to use other for Sha256 identity types. This PR adds explicit aliases to other for clarity

What Has Changed

  • Add aliases for sha256 identity types

Screenshots/Video

  • N/A

Checklist

  • I have performed a self-review of my own code.
  • I have made corresponding changes to the documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have tested this locally.

Additional Notes

  • N/A

Reference Issue (For employees only. Ignore if you are an outside contributor)

  • Closes N/A

@jamesnrokt jamesnrokt requested a review from a team as a code owner April 21, 2026 21:58
@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 21, 2026

PR Summary

Medium Risk
Touches identity request preprocessing and change-detection logic used by identify/login/modify flows; regressions could trigger extra or skipped identity calls if normalization/comparison is wrong. Changes are localized and covered by new unit tests, but impact core identity behavior.

Overview
Adds support for partner-friendly sha256 identity aliases by normalizing email_sha256other and mobile_sha256other2 during identity request preprocessing and when checking whether an identity request has changed.

Updates hasIdentityRequestChanged to compare identities order-independently after normalization (avoiding false positives caused by key insertion order differences), and extends IdentityType.getIdentityType to recognize the new alias keys.

Bumps @types/mparticle__web-sdk and adjusts runtime model typings (e.g., SDKProduct required fields, SDKInitConfig omit list), with added Jest/Mocha coverage for the new alias + comparison behavior.

Reviewed by Cursor Bugbot for commit b97f566. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/identity-utils.ts
@rmi22186 rmi22186 force-pushed the feat/add-alias-for-sha256-identities branch 2 times, most recently from babd33c to 2961807 Compare May 1, 2026 15:32
@rmi22186
Copy link
Copy Markdown
Member

rmi22186 commented May 1, 2026

Updated to include mobilesha --> Other2 mapping

An identify request of:

const identifyRequest = {
    userIdentities: { 
        email_sha256: 'emailsha',
        mobile_sha256: 'mobilenumber',
    } 
}

now maps to

image

Comment thread src/identity-utils.ts Outdated
Comment thread src/identity-utils.ts Outdated
Comment thread src/identity-utils.ts Outdated
Comment thread src/identity-utils.ts Outdated
Comment thread src/identity-utils.ts Outdated
Comment thread src/identity.js Outdated
Comment thread src/sdkRuntimeModels.ts
// and the two will be merged in once the Store module is refactored
export interface SDKInitConfig
extends Omit<MPConfiguration, 'dataPlan' | 'logLevel'> {
extends Omit<MPConfiguration, 'dataPlan' | 'logLevel' | 'identityCallback'> {
Copy link
Copy Markdown
Member

@rmi22186 rmi22186 May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was required due to build issues with definitelytyped - the local SDK is actually typed more strongly and is more accurate than DT's definition. Once we deprecated DT, this will be resolved.

Comment thread src/identity-utils.ts
rmi22186 added a commit that referenced this pull request May 4, 2026
Address Cursor Bugbot finding (PR #1252): the previous
`Readonly<UserIdentities>` typing constrained keys to identity names
but accepted `string | null | undefined` for values — modeling them
as identity *values* rather than canonical key names. That left the
map vulnerable to a silent corruption: a future maintainer setting
an alias to `null` would compile, then at runtime
`normalized[null] = value` coerces the index to the literal string
"null", silently dropping the user's hash on the wire.

Switch to `Readonly<Partial<Record<keyof UserIdentities, keyof
UserIdentities>>>` so both keys *and* values must be valid identity
key names. `null`, undefined, or arbitrary strings now fail
type-check at the declaration site.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 61c828b. Configure here.

Comment thread src/identity-utils.ts
jamesnrokt and others added 9 commits May 6, 2026 07:49
- mobile_sha256 now maps to other2 (was: other) so it no longer collides
  with email_sha256 in the same canonical slot.
- Null on an alias passes through to the canonical slot instead of being
  dropped, so a Modify call with `<alias>: null` actually clears the slot —
  matching the null=clear contract honored by removeFalsyIdentityValues
  and the identity validator.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- hasIdentityRequestChanged now normalizes the new request before
  stringify-compare; fixes spurious identify-on-restore when
  SDKConfig.identifyRequest uses sha256 aliases.
- Move the declare module augmentation to public-types.ts (the file
  shipped via package.json types). Marked for removal once
  DefinitelyTyped/DefinitelyTyped#74955 publishes.
- Type SHA256_IDENTITY_ALIASES as Readonly<UserIdentities> to drop
  three downstream casts in normalizeUserIdentityKeys.
- Add hasIdentityRequestChanged regression test for the alias→canonical
  round-trip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@types/mparticle__web-sdk@2.66.0 (DefinitelyTyped/DefinitelyTyped#74955)
includes email_sha256 and mobile_sha256 on UserIdentities, so the local
augmentation in public-types.ts is no longer needed. The bump also
tightens two interfaces in ways the SDK already overrides:

- IMParticleUser now extends Omit<User, 'getCart'>. DT 2.66.0 makes
  Product.Name required, breaking the existing override of
  getCart().getCartProducts() that returns SDKProduct[] (Name optional).
  Cart APIs are deprecated; the override stays as the canonical SDK
  shape.
- SDKInitConfig adds 'identityCallback' to its Omit<MPConfiguration>
  escape list. DT 2.66.0's IdentityCallback uses
  change_results.identity_type: string; the SDK uses SDKIdentityTypeEnum
  and already redeclares identityCallback locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@types/mparticle__web-sdk@2.66.0 made Product.{Name,Sku,Price} required.
The SDK's createProduct factory already requires all three at runtime
(rejects with an error and returns null otherwise), so promoting them
to required on SDKProduct matches the actual API contract.

Also drop `| null` from SDKProduct.Attributes — no code path in src/ or
test/ assigned null to it, and DT's Product.Attributes is `?: Record<...>`
without the null variant.

With SDKProduct now structurally assignable to DT's Product, the
Omit<User, 'getCart'> escape on IMParticleUser is no longer needed —
revert to `extends User`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address Cursor Bugbot finding (PR #1252): the previous
`Readonly<UserIdentities>` typing constrained keys to identity names
but accepted `string | null | undefined` for values — modeling them
as identity *values* rather than canonical key names. That left the
map vulnerable to a silent corruption: a future maintainer setting
an alias to `null` would compile, then at runtime
`normalized[null] = value` coerces the index to the literal string
"null", silently dropping the user's hash on the wire.

Switch to `Readonly<Partial<Record<keyof UserIdentities, keyof
UserIdentities>>>` so both keys *and* values must be valid identity
key names. `null`, undefined, or arbitrary strings now fail
type-check at the declaration site.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ntities keys

The previous tightening typed the alias map as keyof UserIdentities → keyof
UserIdentities, which broke the build because email_sha256/mobile_sha256 are
input alias names that don't exist on the UserIdentities interface — they
map TO UserIdentities keys. Introduce a Sha256IdentityAlias literal union
for the keys, and widen normalizeUserIdentityKeys' input to accept the
aliases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rmi22186 rmi22186 force-pushed the feat/add-alias-for-sha256-identities branch from 61c828b to 308f87b Compare May 6, 2026 13:06
The previous JSON.stringify-based comparison was sensitive to object key
insertion order. The current-user side iterates a numeric IdentityType map
(yielding keys in IdentityType ascending order), while the new-request
side reflects partner-supplied / alias-normalized order. Equivalent
identity sets in different orders produced different stringified output,
flagging spurious changes and triggering unnecessary identify API calls
on session resume — the bugbot finding on PR #1252.

Replace the stringify with a structural compare that checks key-set
equality and per-key value equality, independent of order.

Add hasIdentityRequestChanged spec covering null inputs, order-mismatched
matches (with and without sha256 aliases), and genuine value/key changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 6, 2026

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.

3 participants