flagmint-js-sdk 2.2.2-rc.0 → 2.2.3-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,8 +7,8 @@ export type { ConfigSyncPayload, DeltaConfigPayload, DeltasCatchUpPayload, FullC
7
7
  export { performAslHandshake } from './handshake';
8
8
  export type { AslHandshakeSuccess } from './handshake';
9
9
  export { evaluateSdkFlag, evaluateAllSdkFlags, coerceType, prepareContextForEvaluator, prepareContextForLocalEval, mapToRecord, } from './evaluateSdkFlag';
10
- export { PII_VALUE_ENCODING, normalizePiiString, hashPiiValue, isPiiAttribute, piiWireOptionsFromPayload, applyPiiHashToFlatContext, } from './piiHash';
11
- export type { PiiWireOptions } from './piiHash';
10
+ export { PII_VALUE_ENCODING, normalizePiiString, hashPiiValue, isPiiAttribute, payloadHasExplicitPiiFields, hasExplicitInvalidPiiEncoding, hasMalformedPiiAttributes, payloadRequiresUsablePiiWire, isExplicitPiiRequirementCleared, piiAttributeKeysFromPayload, piiWireOptionsFromPayload, isPiiWireBroken, resolvePiiWireForDelta, applyPiiHashToFlatContext, } from './piiHash';
11
+ export type { PiiWireOptions, ApplyPiiHashMode } from './piiHash';
12
12
  export { evaluateRule, evaluateKillSwitch, evaluateOnVariation, evaluateFlagWithTargetingRules, applyRolloutStrategy, applyPercentageRollout, applyVariantRollout, applyGradualRollout, computeCurrentPercentage, defaultHash, getContextAttribute, } from './flagEvaluator';
13
13
  export type { ExpectedFlagType, FlagEvaluationResult, Condition, TargetingRule, Rollout, Variation, Segment, EvaluationDeps, } from './flagEvaluator';
14
14
  export { flattenContext, flattenEvaluationContext } from './flattenContext';
@@ -8,6 +8,14 @@ export type PiiWireOptions = {
8
8
  piiSalt: string;
9
9
  piiValueEncoding?: typeof PII_VALUE_ENCODING | string;
10
10
  };
11
+ /**
12
+ * Extra apply options. Prefer plaintext context; only set `alreadyHashed`
13
+ * when callers intentionally supply wire digests (do not infer from hex shape).
14
+ */
15
+ export type ApplyPiiHashMode = {
16
+ /** When true, leave PII string fields unchanged (caller supplied digests). */
17
+ alreadyHashed?: boolean;
18
+ };
11
19
  /**
12
20
  * Normalize a string before PII hashing (trim + lowercase).
13
21
  * Must match FF-EU `normalizePiiString`.
@@ -31,23 +39,95 @@ export declare function hashPiiValue(value: string, salt: string): string;
31
39
  * @param piiAttributes Keys from signed config
32
40
  */
33
41
  export declare function isPiiAttribute(attribute: string | undefined | null, piiAttributes: readonly string[]): boolean;
42
+ /** Payload fields that carry PII wire metadata. */
43
+ export type PiiWirePayloadFields = {
44
+ piiAttributes?: unknown;
45
+ piiSalt?: unknown;
46
+ piiValueEncoding?: unknown;
47
+ };
48
+ /**
49
+ * Whether a payload explicitly includes any PII wire field (vs omitting all).
50
+ * Used so deltas that omit PII metadata keep the previous options, while
51
+ * deltas that send unusable fields clear them.
52
+ *
53
+ * @param payload Signed fullConfig / delta fields
54
+ */
55
+ export declare function payloadHasExplicitPiiFields(payload: PiiWirePayloadFields | null | undefined): boolean;
56
+ /**
57
+ * String attribute keys listed on a PII wire payload (ignores non-strings).
58
+ *
59
+ * @param payload Signed fullConfig / delta fields
60
+ */
61
+ export declare function piiAttributeKeysFromPayload(payload: PiiWirePayloadFields | null | undefined): string[];
62
+ /**
63
+ * True when `piiAttributes` is present but not a clean list of non-empty strings.
64
+ * e.g. `[null]`, `['']`, or a non-array — must not count as "remove all PII".
65
+ *
66
+ * @param payload Signed fullConfig / delta fields
67
+ */
68
+ export declare function hasMalformedPiiAttributes(payload: PiiWirePayloadFields | null | undefined): boolean;
69
+ /**
70
+ * True when `piiValueEncoding` is present but is not usable `hmac-v1`.
71
+ * Distinguishes omitted encoding (OK — default hmac-v1) from e.g. `123` / `hmac-v2`.
72
+ *
73
+ * @param payload Signed fullConfig / delta fields
74
+ */
75
+ export declare function hasExplicitInvalidPiiEncoding(payload: PiiWirePayloadFields | null | undefined): boolean;
76
+ /**
77
+ * True when the payload claims PII hashing is in play and the client must have
78
+ * usable salt + `hmac-v1` encoding (otherwise local eval must fail closed).
79
+ *
80
+ * @param payload Signed fullConfig / delta fields
81
+ */
82
+ export declare function payloadRequiresUsablePiiWire(payload: PiiWirePayloadFields | null | undefined): boolean;
83
+ /**
84
+ * True when the payload explicitly clears the PII attribute list.
85
+ * Only a literal empty array `[]` counts — `[null]` / `['']` are malformed, not removal.
86
+ *
87
+ * @param payload Signed fullConfig / delta fields
88
+ */
89
+ export declare function isExplicitPiiRequirementCleared(payload: PiiWirePayloadFields | null | undefined): boolean;
34
90
  /**
35
91
  * Parse PII wire options from a config-sync payload body.
36
92
  *
37
93
  * @param payload Signed fullConfig / delta fields
38
94
  * @returns Options when salt + encoding are usable; otherwise null
39
95
  */
40
- export declare function piiWireOptionsFromPayload(payload: {
41
- piiAttributes?: unknown;
42
- piiSalt?: unknown;
43
- piiValueEncoding?: unknown;
44
- } | null | undefined): PiiWireOptions | null;
96
+ export declare function piiWireOptionsFromPayload(payload: PiiWirePayloadFields | null | undefined): PiiWireOptions | null;
97
+ /**
98
+ * Whether resolved PII options are missing while the payload (or prior state)
99
+ * still requires hashing — local eval must use defaults only.
100
+ *
101
+ * Explicit `piiAttributes: []` (literal empty array) clears the requirement
102
+ * even if salt is empty — evaluation may proceed without hashing.
103
+ *
104
+ * @param payload Payload that was just applied (full or merged delta fields)
105
+ * @param resolved Result of {@link piiWireOptionsFromPayload} / delta resolve
106
+ * @param previousPriorHadPiiAttrs Whether the store previously had PII attribute keys
107
+ */
108
+ export declare function isPiiWireBroken(payload: PiiWirePayloadFields | null | undefined, resolved: PiiWireOptions | null, previousPriorHadPiiAttrs?: boolean): boolean;
109
+ /**
110
+ * Resolve PII wire options for a delta: keep prior when all PII fields are
111
+ * absent; otherwise parse after merging omitted fields from `previous`.
112
+ *
113
+ * FF-EU `piiMetadata` always emits the full triple (or nothing). Merge is
114
+ * defensive so a salt-only / attrs-only delta cannot wipe the other fields.
115
+ * Explicit empty salt or unknown encoding still clears to null.
116
+ *
117
+ * @param previous Current store options
118
+ * @param action Delta (or similar) payload fields
119
+ */
120
+ export declare function resolvePiiWireForDelta(previous: PiiWireOptions | null, action: PiiWirePayloadFields | null | undefined): PiiWireOptions | null;
45
121
  /**
46
122
  * Hash PII string fields on a flat evaluation context so they match hashed
47
123
  * rule values on the wire.
48
124
  *
125
+ * Always hashes plaintext strings (including values that look like 64-char hex).
126
+ * Pass `{ alreadyHashed: true }` only when the caller already supplied digests.
127
+ *
49
128
  * @param context Flat context map (after prepare / flatten)
50
129
  * @param options PII options from the rules store
130
+ * @param mode Optional apply mode (`alreadyHashed` skips hashing)
51
131
  * @returns New context object with PII strings hashed (or the input if no-op)
52
132
  */
53
- export declare function applyPiiHashToFlatContext(context: Record<string, unknown>, options: PiiWireOptions | null | undefined): Record<string, unknown>;
133
+ export declare function applyPiiHashToFlatContext(context: Record<string, unknown>, options: PiiWireOptions | null | undefined, mode?: ApplyPiiHashMode): Record<string, unknown>;
@@ -11,6 +11,11 @@ export type RulesState = {
11
11
  needsFullConfig: boolean;
12
12
  /** PII hash options from the last fullConfig/delta (null when absent). */
13
13
  piiWire: PiiWireOptions | null;
14
+ /**
15
+ * True when hashed PII rules are expected but salt/encoding is unusable.
16
+ * Fail closed (defaults only) until a good fullConfig arrives.
17
+ */
18
+ piiWireBroken: boolean;
14
19
  };
15
20
  export type ApplyResult = {
16
21
  ok: true;
@@ -36,7 +41,8 @@ export declare class RulesStore {
36
41
  getMacKey(): Uint8Array | null;
37
42
  getState(): RulesState;
38
43
  /**
39
- * Fail-closed readiness: lease not expired and store marked ready.
44
+ * Fail-closed readiness: lease not expired, store marked ready, and PII
45
+ * wire metadata usable when hashing is required.
40
46
  */
41
47
  isReady(now?: number): boolean;
42
48
  /**
@@ -79,4 +79,9 @@ export type RulesCacheSnapshot = {
79
79
  piiAttributes?: string[];
80
80
  piiSalt?: string;
81
81
  piiValueEncoding?: string;
82
+ /**
83
+ * When true, hydrate must stay fail-closed even if salt/attrs were omitted
84
+ * from the snapshot (broken wire with `piiWire === null`).
85
+ */
86
+ piiWireBroken?: boolean;
82
87
  };
@@ -8,6 +8,13 @@ export interface StorageAdapter {
8
8
  export declare function setCacheStorage(customStorage: StorageAdapter): void;
9
9
  export declare function loadCachedFlags<T>(apiKey: string, ttl: number): FeatureFlags<T> | null;
10
10
  export declare function saveCachedFlags<T>(apiKey: string, data: FeatureFlags<T>): void;
11
+ /**
12
+ * Drop the evaluated-flag localCache entry for an API key.
13
+ * Used when config-sync is on so a prior tab’s answers cannot poison another tab.
14
+ *
15
+ * @param apiKey SDK API key used as the storage key suffix
16
+ */
17
+ export declare function clearCachedFlags(apiKey: string): void;
11
18
  export declare function loadCachedContext<C>(apiKey: string): C | null;
12
19
  export declare function saveCachedContext<C>(apiKey: string, context: C): void;
13
20
  /** Config-sync rules localCache — no wall-clock TTL; lease `expiresAt` gates reuse. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flagmint-js-sdk",
3
- "version": "2.2.2-rc.0",
3
+ "version": "2.2.3-rc.0",
4
4
  "description": "Framework-agnostic JavaScript SDK for managing feature flags in Flagmint applications.",
5
5
  "author": "Flagmint Team",
6
6
  "license": "BSD 3-Clause",