@pafi-dev/issuer 0.34.0 → 0.35.1

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.
package/dist/index.d.cts CHANGED
@@ -968,16 +968,16 @@ interface BurnEvent {
968
968
  * Postgres / a file. The SDK does not own persistence because every
969
969
  * issuer has their own storage stack.
970
970
  *
971
- * **Per-token keying (audit finding H-05).** When multiple PointTokens
972
- * are wired through a single `createIssuerService` call, each
973
- * `PointIndexer` MUST get its own cursor — otherwise token A advances
974
- * the shared cursor past token B's events and token B's mints are
975
- * never finalized (off-chain balance never deducts → on-chain PT
976
- * supply for token B exceeds off-chain backing). Combined with the
977
- * H-04 monotonic-save fix this becomes a catastrophic-and-stable
978
- * state where token B's cursor can never catch up. Implementations
979
- * SHOULD expose `forKey(key)` returning a derived store keyed under
980
- * a distinct namespace; the SDK factory calls it once per token.
971
+ * **Per-token keying.** When multiple PointTokens are wired through a
972
+ * single `createIssuerService` call, each `PointIndexer` MUST get its
973
+ * own cursor — otherwise token A advances the shared cursor past
974
+ * token B's events and token B's mints are never finalized (off-chain
975
+ * balance never deducts → on-chain PT supply for token B exceeds
976
+ * off-chain backing). Combined with the monotonic-save invariant this
977
+ * becomes a catastrophic-and-stable state where token B's cursor can
978
+ * never catch up. Implementations SHOULD expose `forKey(key)`
979
+ * returning a derived store keyed under a distinct namespace; the SDK
980
+ * factory calls it once per token.
981
981
  *
982
982
  * When `forKey` is absent, the SDK falls back to the bare store and
983
983
  * emits a runtime warning if more than one token is configured. New
@@ -995,7 +995,7 @@ interface IIndexerCursorStore {
995
995
  *
996
996
  * Optional for backwards compatibility, but REQUIRED in practice
997
997
  * whenever more than one PointToken is wired through the SDK
998
- * factory (see H-05).
998
+ * factory (per-token keying section above).
999
999
  */
1000
1000
  forKey?(key: string): IIndexerCursorStore;
1001
1001
  }
@@ -1006,9 +1006,9 @@ interface IIndexerCursorStore {
1006
1006
  declare class InMemoryCursorStore implements IIndexerCursorStore {
1007
1007
  private cursor;
1008
1008
  /**
1009
- * Child stores keyed by `forKey()`. Each child has its own cursor
1010
- * (the H-05 fix), so a single InMemoryCursorStore can back N
1011
- * PointIndexers in tests / single-process callers.
1009
+ * Child stores keyed by `forKey()`. Each child has its own cursor,
1010
+ * so a single InMemoryCursorStore can back N PointIndexers in tests
1011
+ * / single-process callers.
1012
1012
  */
1013
1013
  private readonly children;
1014
1014
  load(): Promise<bigint | undefined>;
@@ -1198,11 +1198,11 @@ declare class PointIndexer {
1198
1198
 
1199
1199
  /**
1200
1200
  * Mirror of `PointIndexerFinalizeError` — raised when
1201
- * `ledger.resolveCreditByBurnTx` rejects. See audit M-12: pre-fix this
1202
- * was silently swallowed and the cursor advanced regardless,
1203
- * permanently dropping confirmed on-chain burns from the off-chain
1204
- * credit pipeline. Post-fix the error propagates, the chunk's cursor
1205
- * save is skipped, and the next tick retries.
1201
+ * `ledger.resolveCreditByBurnTx` rejects. Silently swallowing this
1202
+ * error and advancing the cursor anyway would permanently drop
1203
+ * confirmed on-chain burns from the off-chain credit pipeline. The
1204
+ * error therefore propagates, the chunk's cursor save is skipped,
1205
+ * and the next tick retries.
1206
1206
  */
1207
1207
  declare class BurnIndexerFinalizeError extends Error {
1208
1208
  readonly context: {
@@ -1516,7 +1516,7 @@ type PoolsProvider = (request: ApiPoolsRequest) => Promise<ApiPoolsResponse>;
1516
1516
 
1517
1517
  /**
1518
1518
  * Per-user redemption history needed by the evaluator. The issuer can
1519
- * implement this with their existing burn audit table (preferred) or
1519
+ * implement this with their existing burn journal table (preferred) or
1520
1520
  * use the bundled MemoryRedemptionHistoryStore for tests.
1521
1521
  */
1522
1522
  interface IRedemptionHistoryStore {
@@ -2327,15 +2327,15 @@ interface PendingUserOpEntry {
2327
2327
  * sponsored lock because the on-chain amount the user burns/mints
2328
2328
  * differs between variants.
2329
2329
  *
2330
- * Audit PACI5-21 — pre-fix `handleMobileSubmit.bindUserOpHash`
2331
- * always bound the submitted userOpHash to the SPONSORED lockId,
2332
- * even when the user submitted the fallback variant. The
2333
- * bundler-receipt fallback in `handleRedeemStatus` then resolved
2334
- * the sponsored credit (`amount - fee`) against the on-chain
2335
- * burn of the FULL `amount` — every fee-bearing fallback redeem
2336
- * permanently under-credited the user by exactly the fee. Surface
2337
- * the fallback lockId here so submit can route the bind to the
2338
- * correct ledger row.
2330
+ * If `handleMobileSubmit.bindUserOpHash` bound the submitted
2331
+ * userOpHash to the SPONSORED lockId even when the user submitted
2332
+ * the fallback variant, the bundler-receipt fallback in
2333
+ * `handleRedeemStatus` would resolve the sponsored credit
2334
+ * (`amount - fee`) against the on-chain burn of the FULL `amount`
2335
+ * — every fee-bearing fallback redeem would permanently
2336
+ * under-credit the user by exactly the fee. Surface the fallback
2337
+ * lockId here so submit can route the bind to the correct ledger
2338
+ * row.
2339
2339
  */
2340
2340
  lockId?: string;
2341
2341
  };
@@ -2506,12 +2506,13 @@ interface PreparedUserOp {
2506
2506
  * (paymaster signature mismatch) and/or AA24 (sender signature
2507
2507
  * mismatch) — opaque failures that take hours to debug.
2508
2508
  *
2509
- * Splitting "merge" and "hash" into two free functions invited
2510
- * exactly this bug each call site reinvented the merge logic,
2511
- * and one was already drifting (see audit M-02). Returning all
2512
- * three pieces (`userOp`, `userOpHash`, `typedData`) from a single
2513
- * call makes "hash before merge" structurally impossible: there is
2514
- * no intermediate userOp to compute a stale hash over.
2509
+ * Splitting "merge" and "hash" into two free functions invites
2510
+ * exactly this bug: each call site has to reinvent the merge logic,
2511
+ * and any drift between sites silently produces stale hashes.
2512
+ * Returning all three pieces (`userOp`, `userOpHash`, `typedData`)
2513
+ * from a single call makes "hash before merge" structurally
2514
+ * impossible: there is no intermediate userOp to compute a stale
2515
+ * hash over.
2515
2516
  *
2516
2517
  * Behaviour:
2517
2518
  * - When `paymasterFields` is undefined (paymaster declined / Path
@@ -2564,12 +2565,12 @@ interface PrepareMobileUserOpParams {
2564
2565
  * fallback variant (PTRedeemHandler reserves
2565
2566
  * `amount` for fallback vs `amount - fee` for sponsored).
2566
2567
  *
2567
- * Audit PACI5-21 — when omitted, `handleMobileSubmit` binds the
2568
- * fallback userOpHash to the outer sponsored `lockId`, which made
2568
+ * When omitted, `handleMobileSubmit` binds the fallback userOpHash
2569
+ * to the outer sponsored `lockId`, which makes
2569
2570
  * `handleRedeemStatus`'s bundler-receipt fallback resolve the
2570
2571
  * SMALLER sponsored credit against the on-chain burn of the FULL
2571
- * amount. Every fee-bearing fallback redeem permanently
2572
- * under-credited the user by exactly the fee. Pass the fallback
2572
+ * amount every fee-bearing fallback redeem then permanently
2573
+ * under-credits the user by exactly the fee. Pass the fallback
2573
2574
  * lockId here so submit can route the bind to the correct row.
2574
2575
  */
2575
2576
  lockIdFallback?: string;
@@ -2689,8 +2690,8 @@ interface HandleMobilePrepareParams {
2689
2690
  /**
2690
2691
  * Optional separate lock id for the fallback path. Required when the
2691
2692
  * upstream handler (e.g. PTRedeemHandler) reserves a DIFFERENT
2692
- * ledger row for the fallback variant. See audit PACI5-21 +
2693
- * `prepareMobileUserOp` for the full rationale.
2693
+ * ledger row for the fallback variant. See `prepareMobileUserOp`
2694
+ * for the full rationale.
2694
2695
  */
2695
2696
  lockIdFallback?: string;
2696
2697
  /**
@@ -3178,7 +3179,7 @@ interface IssuerServiceConfig {
3178
3179
  * If `true`, the factory calls `indexer.start()` before returning.
3179
3180
  * Default: `false` — the caller decides when to begin polling.
3180
3181
  *
3181
- * **SAFETY (H-04):** in a multi-replica deployment, ALWAYS pair
3182
+ * **SAFETY:** in a multi-replica deployment, ALWAYS pair
3182
3183
  * `autoStart: true` with `singletonLock` below. Without leader
3183
3184
  * election, every replica starts its own indexer fleet and races
3184
3185
  * against the others — see `ISingletonLock` docs for the
@@ -3805,7 +3806,7 @@ interface RequestPaymasterParams {
3805
3806
  /** Target contract (typically the PointToken). */
3806
3807
  pointTokenAddress: Address;
3807
3808
  /**
3808
- * Function name to surface in audit / paymaster context. Defaults to
3809
+ * Function name to surface in logs / paymaster context. Defaults to
3809
3810
  * a per-scenario sensible value (`mint` / `burn` / `swap` / generic
3810
3811
  * scenario name).
3811
3812
  */
@@ -3951,7 +3952,7 @@ declare class IssuerStateError extends PafiSdkError {
3951
3952
  * Caching:
3952
3953
  * - `PointToken.issuer()` — memoized for the process lifetime (immutable)
3953
3954
  * - Full state (registry + totalSupply) — 10s TTL per PointToken
3954
- * (was 30s pre-audit PACI5-3; see `ISSUER_RECORD_TTL_MS` comment)
3955
+ * (see `ISSUER_RECORD_TTL_MS` comment)
3955
3956
  * - Burst calls while a fetch is in-flight share the same Promise
3956
3957
  * (thundering-herd protection)
3957
3958
  * - Operators can call `invalidate()` after admin txs land to bust
@@ -3975,7 +3976,7 @@ declare class IssuerStateValidator {
3975
3976
  /**
3976
3977
  * Invalidate cached state for one PointToken, or everything if omitted.
3977
3978
  * Call after admin txs that change registry or cap settings — closes
3978
- * the split-brain window described in audit PACI5-3 ahead of the
3979
+ * the split-brain window described
3979
3980
  * passive TTL. Idempotent: safe to call when no entry exists.
3980
3981
  */
3981
3982
  invalidate(pointToken?: Address): void;
@@ -4062,7 +4063,7 @@ declare const REDEMPTION_HISTORY_WINDOW_SEC: number;
4062
4063
  /**
4063
4064
  * In-memory IRedemptionHistoryStore for tests + the bundled NestJS
4064
4065
  * example. Production issuers should implement this against their
4065
- * existing burn/audit table — sumRedeemedSince is hot path on every
4066
+ * existing burn/journal table — sumRedeemedSince is hot path on every
4066
4067
  * redemption preview.
4067
4068
  */
4068
4069
  declare class MemoryRedemptionHistoryStore implements IRedemptionHistoryStore {
package/dist/index.d.ts CHANGED
@@ -968,16 +968,16 @@ interface BurnEvent {
968
968
  * Postgres / a file. The SDK does not own persistence because every
969
969
  * issuer has their own storage stack.
970
970
  *
971
- * **Per-token keying (audit finding H-05).** When multiple PointTokens
972
- * are wired through a single `createIssuerService` call, each
973
- * `PointIndexer` MUST get its own cursor — otherwise token A advances
974
- * the shared cursor past token B's events and token B's mints are
975
- * never finalized (off-chain balance never deducts → on-chain PT
976
- * supply for token B exceeds off-chain backing). Combined with the
977
- * H-04 monotonic-save fix this becomes a catastrophic-and-stable
978
- * state where token B's cursor can never catch up. Implementations
979
- * SHOULD expose `forKey(key)` returning a derived store keyed under
980
- * a distinct namespace; the SDK factory calls it once per token.
971
+ * **Per-token keying.** When multiple PointTokens are wired through a
972
+ * single `createIssuerService` call, each `PointIndexer` MUST get its
973
+ * own cursor — otherwise token A advances the shared cursor past
974
+ * token B's events and token B's mints are never finalized (off-chain
975
+ * balance never deducts → on-chain PT supply for token B exceeds
976
+ * off-chain backing). Combined with the monotonic-save invariant this
977
+ * becomes a catastrophic-and-stable state where token B's cursor can
978
+ * never catch up. Implementations SHOULD expose `forKey(key)`
979
+ * returning a derived store keyed under a distinct namespace; the SDK
980
+ * factory calls it once per token.
981
981
  *
982
982
  * When `forKey` is absent, the SDK falls back to the bare store and
983
983
  * emits a runtime warning if more than one token is configured. New
@@ -995,7 +995,7 @@ interface IIndexerCursorStore {
995
995
  *
996
996
  * Optional for backwards compatibility, but REQUIRED in practice
997
997
  * whenever more than one PointToken is wired through the SDK
998
- * factory (see H-05).
998
+ * factory (per-token keying section above).
999
999
  */
1000
1000
  forKey?(key: string): IIndexerCursorStore;
1001
1001
  }
@@ -1006,9 +1006,9 @@ interface IIndexerCursorStore {
1006
1006
  declare class InMemoryCursorStore implements IIndexerCursorStore {
1007
1007
  private cursor;
1008
1008
  /**
1009
- * Child stores keyed by `forKey()`. Each child has its own cursor
1010
- * (the H-05 fix), so a single InMemoryCursorStore can back N
1011
- * PointIndexers in tests / single-process callers.
1009
+ * Child stores keyed by `forKey()`. Each child has its own cursor,
1010
+ * so a single InMemoryCursorStore can back N PointIndexers in tests
1011
+ * / single-process callers.
1012
1012
  */
1013
1013
  private readonly children;
1014
1014
  load(): Promise<bigint | undefined>;
@@ -1198,11 +1198,11 @@ declare class PointIndexer {
1198
1198
 
1199
1199
  /**
1200
1200
  * Mirror of `PointIndexerFinalizeError` — raised when
1201
- * `ledger.resolveCreditByBurnTx` rejects. See audit M-12: pre-fix this
1202
- * was silently swallowed and the cursor advanced regardless,
1203
- * permanently dropping confirmed on-chain burns from the off-chain
1204
- * credit pipeline. Post-fix the error propagates, the chunk's cursor
1205
- * save is skipped, and the next tick retries.
1201
+ * `ledger.resolveCreditByBurnTx` rejects. Silently swallowing this
1202
+ * error and advancing the cursor anyway would permanently drop
1203
+ * confirmed on-chain burns from the off-chain credit pipeline. The
1204
+ * error therefore propagates, the chunk's cursor save is skipped,
1205
+ * and the next tick retries.
1206
1206
  */
1207
1207
  declare class BurnIndexerFinalizeError extends Error {
1208
1208
  readonly context: {
@@ -1516,7 +1516,7 @@ type PoolsProvider = (request: ApiPoolsRequest) => Promise<ApiPoolsResponse>;
1516
1516
 
1517
1517
  /**
1518
1518
  * Per-user redemption history needed by the evaluator. The issuer can
1519
- * implement this with their existing burn audit table (preferred) or
1519
+ * implement this with their existing burn journal table (preferred) or
1520
1520
  * use the bundled MemoryRedemptionHistoryStore for tests.
1521
1521
  */
1522
1522
  interface IRedemptionHistoryStore {
@@ -2327,15 +2327,15 @@ interface PendingUserOpEntry {
2327
2327
  * sponsored lock because the on-chain amount the user burns/mints
2328
2328
  * differs between variants.
2329
2329
  *
2330
- * Audit PACI5-21 — pre-fix `handleMobileSubmit.bindUserOpHash`
2331
- * always bound the submitted userOpHash to the SPONSORED lockId,
2332
- * even when the user submitted the fallback variant. The
2333
- * bundler-receipt fallback in `handleRedeemStatus` then resolved
2334
- * the sponsored credit (`amount - fee`) against the on-chain
2335
- * burn of the FULL `amount` — every fee-bearing fallback redeem
2336
- * permanently under-credited the user by exactly the fee. Surface
2337
- * the fallback lockId here so submit can route the bind to the
2338
- * correct ledger row.
2330
+ * If `handleMobileSubmit.bindUserOpHash` bound the submitted
2331
+ * userOpHash to the SPONSORED lockId even when the user submitted
2332
+ * the fallback variant, the bundler-receipt fallback in
2333
+ * `handleRedeemStatus` would resolve the sponsored credit
2334
+ * (`amount - fee`) against the on-chain burn of the FULL `amount`
2335
+ * — every fee-bearing fallback redeem would permanently
2336
+ * under-credit the user by exactly the fee. Surface the fallback
2337
+ * lockId here so submit can route the bind to the correct ledger
2338
+ * row.
2339
2339
  */
2340
2340
  lockId?: string;
2341
2341
  };
@@ -2506,12 +2506,13 @@ interface PreparedUserOp {
2506
2506
  * (paymaster signature mismatch) and/or AA24 (sender signature
2507
2507
  * mismatch) — opaque failures that take hours to debug.
2508
2508
  *
2509
- * Splitting "merge" and "hash" into two free functions invited
2510
- * exactly this bug each call site reinvented the merge logic,
2511
- * and one was already drifting (see audit M-02). Returning all
2512
- * three pieces (`userOp`, `userOpHash`, `typedData`) from a single
2513
- * call makes "hash before merge" structurally impossible: there is
2514
- * no intermediate userOp to compute a stale hash over.
2509
+ * Splitting "merge" and "hash" into two free functions invites
2510
+ * exactly this bug: each call site has to reinvent the merge logic,
2511
+ * and any drift between sites silently produces stale hashes.
2512
+ * Returning all three pieces (`userOp`, `userOpHash`, `typedData`)
2513
+ * from a single call makes "hash before merge" structurally
2514
+ * impossible: there is no intermediate userOp to compute a stale
2515
+ * hash over.
2515
2516
  *
2516
2517
  * Behaviour:
2517
2518
  * - When `paymasterFields` is undefined (paymaster declined / Path
@@ -2564,12 +2565,12 @@ interface PrepareMobileUserOpParams {
2564
2565
  * fallback variant (PTRedeemHandler reserves
2565
2566
  * `amount` for fallback vs `amount - fee` for sponsored).
2566
2567
  *
2567
- * Audit PACI5-21 — when omitted, `handleMobileSubmit` binds the
2568
- * fallback userOpHash to the outer sponsored `lockId`, which made
2568
+ * When omitted, `handleMobileSubmit` binds the fallback userOpHash
2569
+ * to the outer sponsored `lockId`, which makes
2569
2570
  * `handleRedeemStatus`'s bundler-receipt fallback resolve the
2570
2571
  * SMALLER sponsored credit against the on-chain burn of the FULL
2571
- * amount. Every fee-bearing fallback redeem permanently
2572
- * under-credited the user by exactly the fee. Pass the fallback
2572
+ * amount every fee-bearing fallback redeem then permanently
2573
+ * under-credits the user by exactly the fee. Pass the fallback
2573
2574
  * lockId here so submit can route the bind to the correct row.
2574
2575
  */
2575
2576
  lockIdFallback?: string;
@@ -2689,8 +2690,8 @@ interface HandleMobilePrepareParams {
2689
2690
  /**
2690
2691
  * Optional separate lock id for the fallback path. Required when the
2691
2692
  * upstream handler (e.g. PTRedeemHandler) reserves a DIFFERENT
2692
- * ledger row for the fallback variant. See audit PACI5-21 +
2693
- * `prepareMobileUserOp` for the full rationale.
2693
+ * ledger row for the fallback variant. See `prepareMobileUserOp`
2694
+ * for the full rationale.
2694
2695
  */
2695
2696
  lockIdFallback?: string;
2696
2697
  /**
@@ -3178,7 +3179,7 @@ interface IssuerServiceConfig {
3178
3179
  * If `true`, the factory calls `indexer.start()` before returning.
3179
3180
  * Default: `false` — the caller decides when to begin polling.
3180
3181
  *
3181
- * **SAFETY (H-04):** in a multi-replica deployment, ALWAYS pair
3182
+ * **SAFETY:** in a multi-replica deployment, ALWAYS pair
3182
3183
  * `autoStart: true` with `singletonLock` below. Without leader
3183
3184
  * election, every replica starts its own indexer fleet and races
3184
3185
  * against the others — see `ISingletonLock` docs for the
@@ -3805,7 +3806,7 @@ interface RequestPaymasterParams {
3805
3806
  /** Target contract (typically the PointToken). */
3806
3807
  pointTokenAddress: Address;
3807
3808
  /**
3808
- * Function name to surface in audit / paymaster context. Defaults to
3809
+ * Function name to surface in logs / paymaster context. Defaults to
3809
3810
  * a per-scenario sensible value (`mint` / `burn` / `swap` / generic
3810
3811
  * scenario name).
3811
3812
  */
@@ -3951,7 +3952,7 @@ declare class IssuerStateError extends PafiSdkError {
3951
3952
  * Caching:
3952
3953
  * - `PointToken.issuer()` — memoized for the process lifetime (immutable)
3953
3954
  * - Full state (registry + totalSupply) — 10s TTL per PointToken
3954
- * (was 30s pre-audit PACI5-3; see `ISSUER_RECORD_TTL_MS` comment)
3955
+ * (see `ISSUER_RECORD_TTL_MS` comment)
3955
3956
  * - Burst calls while a fetch is in-flight share the same Promise
3956
3957
  * (thundering-herd protection)
3957
3958
  * - Operators can call `invalidate()` after admin txs land to bust
@@ -3975,7 +3976,7 @@ declare class IssuerStateValidator {
3975
3976
  /**
3976
3977
  * Invalidate cached state for one PointToken, or everything if omitted.
3977
3978
  * Call after admin txs that change registry or cap settings — closes
3978
- * the split-brain window described in audit PACI5-3 ahead of the
3979
+ * the split-brain window described
3979
3980
  * passive TTL. Idempotent: safe to call when no entry exists.
3980
3981
  */
3981
3982
  invalidate(pointToken?: Address): void;
@@ -4062,7 +4063,7 @@ declare const REDEMPTION_HISTORY_WINDOW_SEC: number;
4062
4063
  /**
4063
4064
  * In-memory IRedemptionHistoryStore for tests + the bundled NestJS
4064
4065
  * example. Production issuers should implement this against their
4065
- * existing burn/audit table — sumRedeemedSince is hot path on every
4066
+ * existing burn/journal table — sumRedeemedSince is hot path on every
4066
4067
  * redemption preview.
4067
4068
  */
4068
4069
  declare class MemoryRedemptionHistoryStore implements IRedemptionHistoryStore {
package/dist/index.js CHANGED
@@ -1139,9 +1139,9 @@ function createPafiEstimatorClient(config) {
1139
1139
  var InMemoryCursorStore = class _InMemoryCursorStore {
1140
1140
  cursor;
1141
1141
  /**
1142
- * Child stores keyed by `forKey()`. Each child has its own cursor
1143
- * (the H-05 fix), so a single InMemoryCursorStore can back N
1144
- * PointIndexers in tests / single-process callers.
1142
+ * Child stores keyed by `forKey()`. Each child has its own cursor,
1143
+ * so a single InMemoryCursorStore can back N PointIndexers in tests
1144
+ * / single-process callers.
1145
1145
  */
1146
1146
  children = /* @__PURE__ */ new Map();
1147
1147
  async load() {
@@ -2151,7 +2151,7 @@ var PTRedeemHandler = class {
2151
2151
  if (!config.supportedTokens) {
2152
2152
  throw new PTRedeemError(
2153
2153
  "UNSUPPORTED_POINT_TOKEN",
2154
- "PTRedeemHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts). See audit PACI5-18."
2154
+ "PTRedeemHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts)."
2155
2155
  );
2156
2156
  }
2157
2157
  this.supportedTokens = config.supportedTokens;
@@ -2165,7 +2165,7 @@ var PTRedeemHandler = class {
2165
2165
  if (this.signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
2166
2166
  throw new PTRedeemError(
2167
2167
  "INVALID_AMOUNT",
2168
- `PTRedeemHandler config: signatureDeadlineSeconds (${this.signatureDeadlineSeconds}s) must be at most redeemLockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (redeemLockDurationMs=${this.redeemLockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS / 1e3}s). See audit M-11.`
2168
+ `PTRedeemHandler config: signatureDeadlineSeconds (${this.signatureDeadlineSeconds}s) must be at most redeemLockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (redeemLockDurationMs=${this.redeemLockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS / 1e3}s).`
2169
2169
  );
2170
2170
  }
2171
2171
  if (config.redemptionService) {
@@ -2509,7 +2509,7 @@ async function handleClaimStatus(params) {
2509
2509
  if (receipt.success && receipt.txHash) {
2510
2510
  if (!lock.tokenAddress) {
2511
2511
  params.onWarning?.(
2512
- `handleClaimStatus: lock ${lock.lockId} has no tokenAddress; falling back to status-only flip (PACI5-24 defence degraded). Migrate the ledger to the multi-token schema.`
2512
+ `handleClaimStatus: lock ${lock.lockId} has no tokenAddress; falling back to status-only flip \u2014 atomic debit+flip cannot run on a legacy single-token row. Migrate the ledger to the multi-token schema.`
2513
2513
  );
2514
2514
  await params.ledger.updateMintStatus(lock.lockId, "MINTED", receipt.txHash).catch((err) => {
2515
2515
  params.onWarning?.(
@@ -2763,8 +2763,8 @@ async function prepareMobileUserOp(params) {
2763
2763
  verificationGasLimit: fallback.userOp.verificationGasLimit.toString(),
2764
2764
  preVerificationGas: fallback.userOp.preVerificationGas.toString(),
2765
2765
  userOpHash: fallback.userOpHash,
2766
- // Audit PACI5-21 — carry the fallback-specific lockId so submit
2767
- // can bind the fallback userOpHash to the correct ledger row.
2766
+ // Carry the fallback-specific lockId so submit can bind the
2767
+ // fallback userOpHash to the correct ledger row.
2768
2768
  lockId: params.lockIdFallback
2769
2769
  };
2770
2770
  }
@@ -3041,7 +3041,7 @@ var PTClaimHandler = class {
3041
3041
  if (!config.supportedTokens) {
3042
3042
  throw new PTClaimError(
3043
3043
  "UNSUPPORTED_POINT_TOKEN",
3044
- "PTClaimHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts). See audit PACI5-18."
3044
+ "PTClaimHandler requires `supportedTokens` (issuer's allow-listed PointToken contracts)."
3045
3045
  );
3046
3046
  }
3047
3047
  const lockDurationMs = config.lockDurationMs ?? DEFAULT_LOCK_MS;
@@ -3050,7 +3050,7 @@ var PTClaimHandler = class {
3050
3050
  if (signatureDeadlineSeconds * 1e3 > maxAllowedSignatureMs) {
3051
3051
  throw new PTClaimError(
3052
3052
  "VALIDATION_FAILED",
3053
- `PTClaimHandler config: signatureDeadlineSeconds (${signatureDeadlineSeconds}s) must be at most lockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (lockDurationMs=${lockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS2 / 1e3}s). See audit M-11.`,
3053
+ `PTClaimHandler config: signatureDeadlineSeconds (${signatureDeadlineSeconds}s) must be at most lockDurationMs - safety margin = ${maxAllowedSignatureMs / 1e3}s (lockDurationMs=${lockDurationMs / 1e3}s, safety=${M11_SAFETY_MARGIN_MS2 / 1e3}s).`,
3054
3054
  {
3055
3055
  lockDurationMs,
3056
3056
  signatureDeadlineSeconds,
@@ -3164,6 +3164,13 @@ var PTClaimHandler = class {
3164
3164
  callData: previewUserOp.callData
3165
3165
  }
3166
3166
  }) : 0n;
3167
+ if (feeAmount > 0n && feeAmount >= request.amount) {
3168
+ throw new PTClaimError(
3169
+ "INVALID_AMOUNT",
3170
+ `fee (${feeAmount}) must be strictly less than claim amount (${request.amount})`,
3171
+ { feeAmount: feeAmount.toString(), amount: request.amount.toString() }
3172
+ );
3173
+ }
3167
3174
  const domainName = await this.cfg.domainResolver.resolve(
3168
3175
  request.pointTokenAddress
3169
3176
  );
@@ -4894,7 +4901,7 @@ async function createIssuerService(config) {
4894
4901
  const sharedCursorWithMultipleTokens = baseCursorStore !== void 0 && typeof baseCursorStore.forKey !== "function" && tokenAddresses.length > 1;
4895
4902
  if (sharedCursorWithMultipleTokens) {
4896
4903
  console.warn(
4897
- `[@pafi-dev/issuer] cursorStore lacks forKey() and ${tokenAddresses.length} PointTokens are configured. All PointIndexers will share one cursor row, causing token-skipping (audit finding H-05). Implement IIndexerCursorStore.forKey to return per-token derived stores. This permissive path will be removed in a future major release.`
4904
+ `[@pafi-dev/issuer] cursorStore lacks forKey() and ${tokenAddresses.length} PointTokens are configured. All PointIndexers will share one cursor row, causing token-skipping. Implement IIndexerCursorStore.forKey to return per-token derived stores. This permissive path will be removed in a future major release.`
4898
4905
  );
4899
4906
  }
4900
4907
  const indexers = /* @__PURE__ */ new Map();
@@ -4985,7 +4992,7 @@ async function createIssuerService(config) {
4985
4992
  const lock = config.indexer.singletonLock;
4986
4993
  if (!lock) {
4987
4994
  console.warn(
4988
- "[@pafi-dev/issuer] indexer.autoStart=true without singletonLock \u2014 this is UNSAFE in multi-replica deployments (audit finding H-04). Either set replicas=1 + INDEXER_AUTOSTART=false on non-leader pods, or pass `singletonLock: makePostgresSingletonLock(dataSource)`. This permissive path will be removed in a future major release."
4995
+ "[@pafi-dev/issuer] indexer.autoStart=true without singletonLock \u2014 this is UNSAFE in multi-replica deployments. Either set replicas=1 + INDEXER_AUTOSTART=false on non-leader pods, or pass `singletonLock: makePostgresSingletonLock(dataSource)`. This permissive path will be removed in a future major release."
4989
4996
  );
4990
4997
  for (const idx of indexers.values()) {
4991
4998
  idx.start();
@@ -5045,7 +5052,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
5045
5052
  /**
5046
5053
  * Invalidate cached state for one PointToken, or everything if omitted.
5047
5054
  * Call after admin txs that change registry or cap settings — closes
5048
- * the split-brain window described in audit PACI5-3 ahead of the
5055
+ * the split-brain window described
5049
5056
  * passive TTL. Idempotent: safe to call when no entry exists.
5050
5057
  */
5051
5058
  invalidate(pointToken) {
@@ -5219,7 +5226,7 @@ var MemoryRedemptionHistoryStore = class {
5219
5226
  };
5220
5227
 
5221
5228
  // src/index.ts
5222
- var PAFI_ISSUER_SDK_VERSION = true ? "0.34.0" : "dev";
5229
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.35.0" : "dev";
5223
5230
  export {
5224
5231
  AdapterMisconfiguredError,
5225
5232
  AuthError,