@unito/integration-sdk
Version:
Integration SDK
37 lines (36 loc) • 1.55 kB
TypeScript
/**
* Forbids spreading the entire `credentials` object into a cache-key hash input
* inside `cache.ts`.
*
* Bad:
* crc32(JSON.stringify({ ...params, ...credentials }))
*
* Good (smartsheet/google-drive/freshservice pattern):
* if (!credentials.unitoCredentialId) {
* throw new HttpErrors.UnprocessableEntityError('...');
* }
* hashValue({ ...params, userIdentifier: credentials.unitoCredentialId });
*
* `unitoCredentialId` is Unito's internal record ID for the credential row — a
* non-secret UUID. Hashing it never puts secret material in memory. Do NOT
* fall back to `accessToken`.
*
* Why:
* 1. Cache thrash on credential rotation. Access tokens rotate on every OAuth
* refresh (and refresh tokens themselves rotate on use for some providers);
* spreading the full credential makes EVERY field a cache-key input, so a
* single-field rotation invalidates the whole cache.
* 2. Credential surface area. The full credential transits memory as a JSON
* string before hashing. Any error in this path can surface in stack
* traces or memory dumps.
* 3. Wrong unit of identity. Cache should be keyed on the stable identifier
* of the credential (`unitoCredentialId`), not the credential material.
*
* Scope:
* Only fires in files whose path ends in `/src/cache.ts`. `credentials.ts`
* has legitimate `...credentials` spread (enrichment patterns) and is never
* affected.
*/
import type { Rule } from 'eslint';
declare const rule: Rule.RuleModule;
export default rule;