@invisible-labs/sdk 0.9.0-devnet → 0.11.0-devnet

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.
Files changed (38) hide show
  1. package/README.md +25 -5
  2. package/dist/.invisible-sdk-build-target.json +2 -2
  3. package/dist/{chunk-RWKG7N7I.js → chunk-A4R3DHKN.js} +2 -2
  4. package/dist/chunk-A4R3DHKN.js.map +1 -0
  5. package/dist/{chunk-6AKBRYKO.js → chunk-DOTYDYVB.js} +3 -3
  6. package/dist/{chunk-6AKBRYKO.js.map → chunk-DOTYDYVB.js.map} +1 -1
  7. package/dist/{chunk-EOPZVOVP.js → chunk-LVCDODTN.js} +582 -19
  8. package/dist/chunk-LVCDODTN.js.map +1 -0
  9. package/dist/{chunk-QF5TSUQE.js → chunk-M45APS7S.js} +405 -51
  10. package/dist/chunk-M45APS7S.js.map +1 -0
  11. package/dist/{chunk-ISIWWGSR.js → chunk-NOKBFHDP.js} +5 -5
  12. package/dist/{chunk-ISIWWGSR.js.map → chunk-NOKBFHDP.js.map} +1 -1
  13. package/dist/{chunk-HWRMSK7E.js → chunk-TNLSUQGJ.js} +4 -4
  14. package/dist/{chunk-HWRMSK7E.js.map → chunk-TNLSUQGJ.js.map} +1 -1
  15. package/dist/{chunk-EPWTRF5U.js → chunk-TYTVF3A4.js} +3 -3
  16. package/dist/{chunk-EPWTRF5U.js.map → chunk-TYTVF3A4.js.map} +1 -1
  17. package/dist/{chunk-AIKC2XQS.js → chunk-YYTRFM2F.js} +3 -3
  18. package/dist/{chunk-AIKC2XQS.js.map → chunk-YYTRFM2F.js.map} +1 -1
  19. package/dist/coordinator-EQEL23A3.js +4 -0
  20. package/dist/{coordinator-DHL3AP7V.js.map → coordinator-EQEL23A3.js.map} +1 -1
  21. package/dist/events.js +3 -3
  22. package/dist/index.d.ts +4 -4
  23. package/dist/index.js +9 -9
  24. package/dist/index.js.map +1 -1
  25. package/dist/lp.d.ts +46 -5
  26. package/dist/lp.js +675 -212
  27. package/dist/lp.js.map +1 -1
  28. package/dist/stats.js +1 -1
  29. package/dist/storage.js +2 -2
  30. package/dist/{types.generated-DrM2M4DZ.d.ts → types.generated-BpbFQlYB.d.ts} +75 -1
  31. package/dist/user.d.ts +9 -4
  32. package/dist/user.js +53 -22
  33. package/dist/user.js.map +1 -1
  34. package/package.json +2 -2
  35. package/dist/chunk-EOPZVOVP.js.map +0 -1
  36. package/dist/chunk-QF5TSUQE.js.map +0 -1
  37. package/dist/chunk-RWKG7N7I.js.map +0 -1
  38. package/dist/coordinator-DHL3AP7V.js +0 -4
package/README.md CHANGED
@@ -19,8 +19,10 @@ coordinator. The normal-user surface uses one functional sequence over a caller-
19
19
  npm install @invisible-labs/sdk@devnet
20
20
  ```
21
21
 
22
- The public package requires Node.js 22 or newer for server runtimes. Browser consumers need Web
23
- Crypto and WebSocket. The default transport uses the platform `WebSocket`.
22
+ Server runtimes require Node.js 22.23.4+, 24.22.1+, or 26.12.1+ within those
23
+ major versions. Earlier releases lack the October 2026 security fixes.
24
+ Browser consumers need Web Crypto and WebSocket. The default transport uses
25
+ the platform `WebSocket`.
24
26
 
25
27
  ## Session boundary
26
28
 
@@ -125,7 +127,7 @@ be persisted. Resume fails closed if the coordinator acknowledges a different sp
125
127
  ## Private-transfer amount limits
126
128
 
127
129
  Use the public user-entry constants for inclusive preflight validation. Values are expressed in
128
- lamports, matching the `amountLamports` request field. The current V0 bounds are `1.5 SOL`
130
+ lamports, matching the `amountLamports` request field. The current Beta bounds are `1.5 SOL`
129
131
  (`1_500_000_000` lamports) minimum and `100 SOL` (`100_000_000_000` lamports) maximum.
130
132
  The SDK rejects non-safe integers and values outside these bounds before sending a coordinator
131
133
  request.
@@ -213,10 +215,28 @@ their own encrypted storage layer for caller-managed material. Browser and exten
213
215
  caller-supplied bytes; they do not encrypt them. Encrypt before storing or use an access-controlled
214
216
  vault for production recovery material.
215
217
 
218
+ After an interrupted LP creation response, the SDK queries the existing position
219
+ using its generated Position Code authority and a fresh attested session when
220
+ needed. A matching persisted position completes creation without another wallet
221
+ signature or creation command. An unresolved result fails closed.
222
+
216
223
  LP DKG requests are bounded. If a browser worker stops responding, the SDK terminates the local
217
224
  workers and attempts the signed position-scoped DKG abort command within a bounded cleanup window
218
- before returning the original failure. LP recovery sends the same cleanup command for an
219
- incomplete position, so a reload does not wait for the coordinator's session expiry.
225
+ before returning the original failure. Recovery is read-only: it never aborts DKG owned by
226
+ another tab or process; stale coordinator sessions remain bounded by their expiry.
227
+
228
+ The default and hard cap are 16 workers per logical SDK Session, shared across lifecycle
229
+ clients and reconnects. Set `concurrency` lower for constrained hosts. Capacity rejection
230
+ (`LP_DKG_BUSY`) happens before worker creation or DKG dispatch and preserves other owners.
231
+ Local worker failures use `LP_DKG_WORKER_FAILED` after scoped cleanup and preserve
232
+ other batches sharing the Session. Transport/attestation failures retain session-reset
233
+ behavior. Raw `createLpDkgBatch` callers must bound aggregate admission themselves. Device minimums
234
+ and performance at 16 require measured qualification.
235
+
236
+ If a reconnect callback returns a Session whose active reservations cannot accept this
237
+ client's DKG ownership, `LP_CLIENT_INVALIDATED` stops only that lifecycle client and its
238
+ owned work. Recreate the client and recover positions with their saved Position Codes.
239
+ Ordinary `LP_DKG_BUSY` admission refusals preserve the client and other owners.
220
240
 
221
241
  ## Security model
222
242
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "package": "@invisible-labs/sdk",
3
3
  "target": "public",
4
- "productionBinaryHash": "176a3f8eb8941bb6b9dd85a044eff1df686df87ff757133a4df467ba46d7c7cf",
4
+ "productionBinaryHash": "a97bb1a48f5e9da2efda68ac133b75f2e2a51077f2b9ae617a69638c9876e6d8",
5
5
  "productionMrtd": "6f3e84c54ac6377614d4c139473db575a83b5db41bd845eecb4eedaf2788ea881309a410c4ceae9641406411f3f639b8",
6
- "productionRuntimeProfile": "prod-hardened"
6
+ "productionRuntimeProfile": "prod-devnet-premium-locked"
7
7
  }
@@ -132,5 +132,5 @@ function isReadable(value) {
132
132
  }
133
133
 
134
134
  export { AttestationError, COORDINATOR_CAPACITY_FULL_ERROR_CODE, COORDINATOR_CAPACITY_FULL_USER_MESSAGE, CommandError, InvalidDepositAmountError, InvisibleError, LpLifecycleError, NotImplementedError, PolicyValidationError, RoutingError, StorageError, TransportError, WalletError, isInvisibleError, normalizeError };
135
- //# sourceMappingURL=chunk-RWKG7N7I.js.map
136
- //# sourceMappingURL=chunk-RWKG7N7I.js.map
135
+ //# sourceMappingURL=chunk-A4R3DHKN.js.map
136
+ //# sourceMappingURL=chunk-A4R3DHKN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/errors.ts"],"names":[],"mappings":"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","file":"chunk-A4R3DHKN.js","sourcesContent":["/**\n * The closed error taxonomy from docs/sdk-specification.md section 8.3.\n *\n * Every error the SDK throws extends {@link InvisibleError} and carries a\n * `code` drawn from a closed, per-class string-literal union. Consumers can\n * branch on `error instanceof CommandError` and then exhaustively `switch` on\n * `error.code` with compile-time completeness.\n *\n * Error classes are the one deliberate exception to the SDK's \"no classes\"\n * rule: JavaScript errors must extend `Error` to carry a stack and support\n * `instanceof`. This mirrors @solana/kit, whose only class is `SolanaError`.\n * The conformance lint allowlists this file for that reason.\n */\n\n// ---------------------------------------------------------------------------\n// Code unions (closed sets, section 8.3)\n// ---------------------------------------------------------------------------\n\n/** Attestation verification failures. Stop; do not retry without a new pin. */\nexport type AttestationErrorCode =\n | \"CERT_CHAIN_INVALID\"\n | \"TCB_REJECTED\"\n | \"FRESHNESS_NONCE_MISMATCH\"\n | \"NOISE_BINDING_MISMATCH\"\n | \"DEBUG_BIT_SET\"\n | \"MRTD_MISMATCH\"\n | \"RUNTIME_MEASUREMENTS_MISMATCH\"\n | \"RUNTIME_PROFILE_MISMATCH\"\n | \"AZURE_MAA_ISSUER_MISMATCH\"\n | \"AZURE_MAA_JWKS_INVALID\"\n | \"AZURE_MAA_POLICY_HASH_MISMATCH\"\n | \"AZURE_MAA_NOT_COMPLIANT\"\n | \"AZURE_MAA_DCAP_MISMATCH\"\n | \"AZURE_HCL_KEYS_MISMATCH\"\n | \"AZURE_AK_PUB_INVALID\"\n | \"AZURE_TPM_AK_QUOTE_INVALID\"\n | \"AZURE_TPM_QUALIFYING_DATA_MISMATCH\"\n | \"NOT_ATTESTED\";\n\n/** Transport-level failures. Reconnect through the pool and re-attest. */\nexport type TransportErrorCode =\n | \"WS_HANDSHAKE_FAILED\"\n | \"NOISE_HANDSHAKE_FAILED\"\n | \"NOISE_FRAME_TOO_LARGE\"\n | \"CONNECTION_LOST\";\n\n/** Leader/role routing failures. Failover and re-attest. */\nexport type RoutingErrorCode =\n | \"WRONG_ROLE\"\n | \"STALE_LEADER_EPOCH\"\n | \"POOL_DEGRADED\"\n | \"VERSION_NOT_SUPPORTED\";\n\n/** Coordinator-side command rejections. Product decides whether to retry. */\nexport type CommandErrorCode =\n | \"REJECTED_GUARD\"\n | \"REJECTED_STATE\"\n | \"REJECTED_EXPIRED\"\n | \"REJECTED_STALE_JOB\"\n | \"REJECTED_RESOURCE_CAP\"\n | \"RETRYABLE_BUSY\";\n\nexport const COORDINATOR_CAPACITY_FULL_ERROR_CODE = \"ERR_ADMISSION_CAPACITY_FULL\" as const;\nexport const COORDINATOR_CAPACITY_FULL_USER_MESSAGE =\n \"The transfer service is temporarily at capacity. This transfer was not started. Please try again later.\";\n\n/** Coordinator wire error code preserved on command rejections. */\nexport type CoordinatorWireErrorCode =\n | \"ERR_INVALID_PAYLOAD\"\n | \"ERR_UNEXPECTED_TYPE\"\n | \"ERR_UNKNOWN_SWAP\"\n | \"ERR_POLICY_VIOLATION\"\n | \"ERR_INVALID_RECOVERY_CODE\"\n | \"ERR_SWAP_NOT_REFUNDABLE\"\n | \"ERR_DKG_FAILURE\"\n | \"ERR_INTERNAL\"\n | \"ERR_PRESEAL_ADMISSION_BUSY\"\n | \"ERR_INITIALIZATION_BUSY\"\n | typeof COORDINATOR_CAPACITY_FULL_ERROR_CODE\n | \"ERR_INVALID_DEPOSIT\"\n | \"ERR_SETTLEMENT_FAILED\";\n\n/** Local input-validation failures. Never sent on the wire; fix the input. */\nexport type PolicyValidationErrorCode =\n | \"INVALID_PAYOUT_PLAN\"\n | \"INVALID_WITHDRAWAL_PLAN\"\n | \"INVALID_POSITION_AUTH\"\n | \"INVALID_REDEMPTION_PLAN\"\n | \"INVALID_DESTINATION_ADDRESS\"\n | \"INVALID_AMOUNT\";\n\n/** Storage-adapter failures. */\nexport type StorageErrorCode =\n | \"STORAGE_NOT_AVAILABLE\"\n | \"STORAGE_INVALID_ADAPTER\"\n | \"STORAGE_QUOTA_EXCEEDED\"\n | \"STORAGE_KEY_MISSING\"\n | \"STORAGE_DECRYPT_FAILED\";\n\n/** Wallet-adapter failures. Bubble to the integrator UX. */\nexport type WalletErrorCode =\n | \"WALLET_NOT_CONNECTED\"\n | \"WALLET_USER_REJECTED\"\n | \"WALLET_INVALID_SIGNATURE\";\n\n/** LP lifecycle local state that callers can branch on. */\nexport type LpLifecycleErrorCode =\n | \"LP_POSITION_AUTH_MISSING\"\n | \"LP_REDEMPTION_RECONCILING\"\n | \"LP_DKG_BUSY\"\n | \"LP_CLIENT_INVALIDATED\"\n | \"LP_DKG_WORKER_FAILED\";\n\n/** Skeleton-only: a surface that exists but has no implementation yet. */\nexport type NotImplementedErrorCode = \"NOT_IMPLEMENTED\";\n\n/** Every code the SDK can surface, across all classes. */\nexport type InvisibleErrorCode =\n | AttestationErrorCode\n | TransportErrorCode\n | RoutingErrorCode\n | CommandErrorCode\n | PolicyValidationErrorCode\n | StorageErrorCode\n | WalletErrorCode\n | LpLifecycleErrorCode\n | NotImplementedErrorCode;\n\n// ---------------------------------------------------------------------------\n// Error classes\n// ---------------------------------------------------------------------------\n\n/** Options accepted by every {@link InvisibleError}. */\nexport interface InvisibleErrorOptions {\n /** The underlying error, preserved for debugging. */\n readonly cause?: unknown;\n}\n\n/** Context attached to a client-persistence storage failure. */\nexport type StorageErrorPhase =\n | \"session-init\"\n | \"write\"\n | \"allocation\"\n | \"recovery-code\"\n | \"ready\"\n | \"sync\"\n | \"refund\"\n | \"read\"\n | \"remove\"\n | \"purge\";\n\n/** Options accepted by {@link StorageError}. */\nexport interface StorageErrorOptions extends InvisibleErrorOptions {\n /** The affected normal-user swap, when known. */\n readonly swapId?: string;\n /** The client-persistence lifecycle phase that failed. */\n readonly phase?: StorageErrorPhase;\n /** True when the coordinator accepted the command before local failure. */\n readonly remoteAccepted?: boolean;\n}\n\n/** Options accepted by {@link CommandError}. */\nexport interface CommandErrorOptions extends InvisibleErrorOptions {\n /** Exact coordinator `Error` envelope code, when the rejection came from the wire. */\n readonly coordinatorCode?: CoordinatorWireErrorCode;\n /** Exact coordinator `Error` envelope message, when `message` is user-facing copy. */\n readonly coordinatorMessage?: string;\n /** Request id rejected by the coordinator, when present in the `Error` envelope. */\n readonly failedReqId?: number;\n}\n\n/**\n * Base class for every error the SDK throws. Carries a closed `code` and sets\n * `name` to the concrete subclass name so logs and `instanceof` agree.\n */\nexport abstract class InvisibleError extends Error {\n /** The closed error code for this error's class. */\n abstract readonly code: InvisibleErrorCode;\n\n constructor(message: string, options?: InvisibleErrorOptions) {\n super(message);\n // Set `cause` directly rather than through the Error constructor option so\n // the package stays on the ES2020 lib (the option is ES2022).\n if (options?.cause !== undefined) {\n (this as { cause?: unknown }).cause = options.cause;\n }\n this.name = new.target.name;\n // Restore the prototype chain across the transpiled `Error` boundary so\n // `instanceof` works for subclasses.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Attestation verification failure. */\nexport class AttestationError extends InvisibleError {\n readonly code: AttestationErrorCode;\n constructor(code: AttestationErrorCode, message: string, options?: InvisibleErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/** Transport-level failure. */\nexport class TransportError extends InvisibleError {\n readonly code: TransportErrorCode;\n constructor(code: TransportErrorCode, message: string, options?: InvisibleErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/** Leader/role routing failure. */\nexport class RoutingError extends InvisibleError {\n readonly code: RoutingErrorCode;\n constructor(code: RoutingErrorCode, message: string, options?: InvisibleErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/** Coordinator-side command rejection. */\nexport class CommandError extends InvisibleError {\n readonly code: CommandErrorCode;\n readonly coordinatorCode?: CoordinatorWireErrorCode;\n readonly coordinatorMessage?: string;\n readonly failedReqId?: number;\n\n constructor(code: CommandErrorCode, message: string, options?: CommandErrorOptions) {\n super(message, options);\n this.code = code;\n if (options?.coordinatorCode !== undefined) this.coordinatorCode = options.coordinatorCode;\n if (options?.coordinatorMessage !== undefined)\n this.coordinatorMessage = options.coordinatorMessage;\n if (options?.failedReqId !== undefined) this.failedReqId = options.failedReqId;\n }\n}\n\n/** User deposit did not match the coordinator policy amount. */\nexport class InvalidDepositAmountError extends CommandError {\n readonly receivedLamports: bigint;\n readonly expectedLamports: bigint;\n\n constructor(receivedLamports: bigint, expectedLamports: bigint) {\n super(\n \"REJECTED_GUARD\",\n `on-chain deposit balance ${receivedLamports.toString()} does not match expected ${expectedLamports.toString()} lamports`,\n );\n this.name = \"InvalidDepositAmountError\";\n this.receivedLamports = receivedLamports;\n this.expectedLamports = expectedLamports;\n }\n}\n\n/** Local input-validation failure; never reaches the wire. */\nexport class PolicyValidationError extends InvisibleError {\n readonly code: PolicyValidationErrorCode;\n constructor(code: PolicyValidationErrorCode, message: string, options?: InvisibleErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/** Storage-adapter failure. */\nexport class StorageError extends InvisibleError {\n readonly code: StorageErrorCode;\n readonly swapId?: string;\n readonly phase?: StorageErrorPhase;\n readonly remoteAccepted?: boolean;\n\n constructor(code: StorageErrorCode, message: string, options?: StorageErrorOptions) {\n super(message, options);\n this.code = code;\n if (options?.swapId !== undefined) this.swapId = options.swapId;\n if (options?.phase !== undefined) this.phase = options.phase;\n if (options?.remoteAccepted !== undefined) this.remoteAccepted = options.remoteAccepted;\n }\n}\n\n/** Wallet-adapter failure. */\nexport class WalletError extends InvisibleError {\n readonly code: WalletErrorCode;\n constructor(code: WalletErrorCode, message: string, options?: InvisibleErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/** LP lifecycle state that is local to the SDK client. */\nexport class LpLifecycleError extends InvisibleError {\n readonly code: LpLifecycleErrorCode;\n constructor(code: LpLifecycleErrorCode, message: string, options?: InvisibleErrorOptions) {\n super(message, options);\n this.code = code;\n }\n}\n\n/**\n * A surface that exists in the typed contract but has no runtime behavior yet.\n * The skeleton throws this from every command that is not the connection layer.\n * The message carries the fully-qualified command name (e.g. `user.contractRequest`).\n */\nexport class NotImplementedError extends InvisibleError {\n readonly code = \"NOT_IMPLEMENTED\" as const;\n /** The command that is not yet implemented, e.g. `lp.redeem`. */\n readonly command: string;\n constructor(command: string, options?: InvisibleErrorOptions) {\n super(`${command} is not implemented in this SDK build`, options);\n this.command = command;\n }\n}\n\n/** Type guard: is `value` any SDK error. */\nexport function isInvisibleError(value: unknown): value is InvisibleError {\n return value instanceof InvisibleError;\n}\n\n// ---------------------------------------------------------------------------\n// Normalization (analog of web/src/lib/user-facing-error.ts)\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_ERROR_MESSAGE = \"Something went wrong. Please try again.\";\n\ninterface MessageLike {\n readonly message?: unknown;\n readonly reason?: unknown;\n readonly error?: unknown;\n readonly code?: unknown;\n}\n\n/**\n * Reduce any thrown value to a readable, single-line message. Guarantees the\n * SDK never surfaces `[object Object]` / `[object ErrorEvent]` (spec section\n * 8.3). For an {@link InvisibleError} the code is prefixed as `[CODE] message`.\n */\nexport function normalizeError(error: unknown, fallback: string = DEFAULT_ERROR_MESSAGE): string {\n const direct = extractMessage(error);\n if (isReadable(direct)) return direct;\n if (isReadable(fallback)) return fallback.trim();\n return DEFAULT_ERROR_MESSAGE;\n}\n\nfunction extractMessage(error: unknown): string | null {\n if (\n error instanceof CommandError &&\n error.coordinatorCode === COORDINATOR_CAPACITY_FULL_ERROR_CODE\n ) {\n return error.message;\n }\n if (error instanceof CommandError && error.coordinatorCode !== undefined) {\n return formatCode(error.coordinatorCode, error.message);\n }\n if (error instanceof InvisibleError) return formatCode(error.code, error.message);\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n if (error === null || error === undefined) return null;\n\n if (isMessageLike(error)) {\n if (typeof error.message === \"string\" && isReadable(error.message)) {\n return formatCode(error.code, error.message);\n }\n const nested = extractMessage(error.error);\n if (isReadable(nested)) return formatCode(error.code, nested);\n const reason = extractMessage(error.reason);\n if (isReadable(reason)) return formatCode(error.code, reason);\n }\n\n return null;\n}\n\nfunction isMessageLike(value: unknown): value is MessageLike {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction formatCode(code: unknown, message: string): string {\n if (typeof code !== \"string\" || code.trim().length === 0) return message.trim();\n const trimmed = code.trim();\n return message.includes(`[${trimmed}]`) ? message.trim() : `[${trimmed}] ${message.trim()}`;\n}\n\nfunction isReadable(value: string | null): value is string {\n if (value === null) return false;\n const trimmed = value.trim();\n if (trimmed.length === 0) return false;\n return !/^\\[object (?:Object|Event|ErrorEvent|PromiseRejectionEvent)\\]$/.test(trimmed);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { TransportError } from './chunk-RWKG7N7I.js';
1
+ import { TransportError } from './chunk-A4R3DHKN.js';
2
2
 
3
3
  // src/session/state.ts
4
4
  var registry = /* @__PURE__ */ new WeakMap();
@@ -46,5 +46,5 @@ function failSessionClosed(state, cause, options = {}) {
46
46
  }
47
47
 
48
48
  export { closeSessionState, createSessionHandle, failSessionClosed, getSessionState };
49
- //# sourceMappingURL=chunk-6AKBRYKO.js.map
50
- //# sourceMappingURL=chunk-6AKBRYKO.js.map
49
+ //# sourceMappingURL=chunk-DOTYDYVB.js.map
50
+ //# sourceMappingURL=chunk-DOTYDYVB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/session/state.ts"],"names":[],"mappings":";;;AAoDA,IAAM,QAAA,uBAAe,OAAA,EAA+B;AAG7C,SAAS,oBAAoB,KAAA,EAA8B;AAChE,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,IAAI,QAAA,GAAW;AACb,MAAA,OAAO,KAAA,CAAM,QAAA;AAAA,IACf;AAAA,GACF;AACA,EAAA,QAAA,CAAS,GAAA,CAAI,QAAQ,KAAK,CAAA;AAC1B,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,gBAAgB,OAAA,EAAgC;AAC9D,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA;AAClC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,kBAAkB,KAAA,EAA2B;AAC3D,EAAA,iBAAA,CAAkB,KAAA,EAAO,IAAI,cAAA,CAAe,iBAAA,EAAmB,gBAAgB,CAAA,EAAG;AAAA,IAChF,qBAAA,EAAuB;AAAA,GACxB,CAAA;AACH;AAEO,SAAS,iBAAA,CACd,KAAA,EACA,KAAA,EACA,OAAA,GAAwD,EAAC,EACnD;AACN,EAAA,MAAM,qBAAA,GAAwB,QAAQ,qBAAA,IAAyB,IAAA;AAC/D,EAAA,MAAM,YAAA,GACJ,0BACC,KAAA,CAAM,QAAA,IAAY,MAAM,WAAA,KAAgB,IAAA,IAAQ,MAAM,OAAA,KAAY,IAAA,CAAA;AAErE,EAAA,IAAI,KAAA,CAAM,kBAAkB,IAAA,EAAM;AAChC,IAAA,YAAA,CAAa,MAAM,aAAa,CAAA;AAChC,IAAA,KAAA,CAAM,aAAA,GAAgB,IAAA;AAAA,EACxB;AACA,EAAA,KAAA,CAAM,eAAA,GAAkB,IAAA;AACxB,EAAA,KAAA,CAAM,cAAA,GAAiB,KAAA;AAEvB,EAAA,MAAM,UAAU,KAAA,CAAM,OAAA;AACtB,EAAA,KAAA,CAAM,QAAA,GAAW,KAAA;AACjB,EAAA,KAAA,CAAM,WAAA,GAAc,IAAA;AACpB,EAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,EAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AACd,EAAA,KAAA,CAAM,qBAAA,GAAwB,IAAA;AAE9B,EAAA,OAAA,EAAS,KAAA,EAAM;AACf,EAAA,KAAA,CAAM,UAAU,KAAA,EAAM;AAEtB,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,KAAA,MAAW,OAAA,IAAW,KAAA,CAAM,uBAAA,EAAyB,OAAA,CAAQ,KAAK,CAAA;AAAA,EACpE;AACF","file":"chunk-6AKBRYKO.js","sourcesContent":["/**\n * Internal session state and the opaque-handle registry.\n *\n * The public {@link Session} is opaque: consumers only read `session.attested`.\n * The real state (transport, endpoint pool, attestation result) is held here\n * and reached through {@link getSessionState}, keyed off the handle in a\n * `WeakMap` so it is never reachable from the public surface.\n */\n\nimport type { Session } from \"../core/session.js\";\nimport type { Transport } from \"../transport/types.js\";\nimport type { AttestationResult } from \"../transport/handshake.js\";\nimport type { SecureChannel } from \"./secureChannel.js\";\nimport type { CoordinatorPoolConfig } from \"../schemas/types.generated.js\";\nimport { TransportError } from \"../core/errors.js\";\nimport type { ClientPersistenceState } from \"../storage/clientPersistence.js\";\n\nexport interface SessionState {\n /** Flipped to `true` once attestation passes. */\n attested: boolean;\n /** The byte channel this session runs over. */\n readonly transport: Transport;\n /** The endpoint pool the session was created with. */\n readonly pool: CoordinatorPoolConfig;\n /** The last verified attestation result, or `null` before first attestation. */\n attestation: AttestationResult | null;\n /**\n * The live attested Noise channel, or `null` before/after attestation. All\n * application I/O Noise-encrypts through this.\n */\n channel: SecureChannel | null;\n /**\n * The per-connection 32-byte CSPRNG nonce bound into the attestation request.\n * Retained for re-attestation over the same channel.\n */\n nonce: Uint8Array | null;\n /** The coordinator's pinned Noise static public key, or `null` if unattested. */\n remoteStaticPublicKey: Uint8Array | null;\n /** Pending re-attestation timer, cleared on close. */\n reattestTimer: ReturnType<typeof setTimeout> | null;\n /** In-flight re-attestation shared by explicit and periodic checks. */\n reattestPromise: Promise<AttestationResult> | null;\n /** Fatal secure-channel cause preserved across transport close notifications. */\n lastFatalError: Error | null;\n /** Handlers invoked when an out-of-band re-attestation fails. */\n readonly policyViolationHandlers: Set<(error: Error) => void>;\n /** Resolved opt-in client-persistence policy, kept behind the opaque handle. */\n readonly clientPersistence: ClientPersistenceState;\n /** Tear down the session: clear the re-attest timer and close the channel. */\n close(): void;\n}\n\nconst registry = new WeakMap<Session, SessionState>();\n\n/** Build an opaque {@link Session} handle backed by `state`. */\nexport function createSessionHandle(state: SessionState): Session {\n const handle = {\n get attested() {\n return state.attested;\n },\n } as unknown as Session;\n registry.set(handle, state);\n return handle;\n}\n\n/**\n * Resolve the internal state for a session.\n *\n * @throws Error if the handle was not produced by `createSession`.\n */\nexport function getSessionState(session: Session): SessionState {\n const state = registry.get(session);\n if (!state) {\n throw new Error(\"invalid Session: this handle was not created by createSession\");\n }\n return state;\n}\n\nexport function closeSessionState(state: SessionState): void {\n failSessionClosed(state, new TransportError(\"CONNECTION_LOST\", \"session closed\"), {\n notifyPolicyViolation: false,\n });\n}\n\nexport function failSessionClosed(\n state: SessionState,\n cause: Error,\n options: { readonly notifyPolicyViolation?: boolean } = {},\n): void {\n const notifyPolicyViolation = options.notifyPolicyViolation ?? true;\n const shouldNotify =\n notifyPolicyViolation &&\n (state.attested || state.attestation !== null || state.channel !== null);\n\n if (state.reattestTimer !== null) {\n clearTimeout(state.reattestTimer);\n state.reattestTimer = null;\n }\n state.reattestPromise = null;\n state.lastFatalError = cause;\n\n const channel = state.channel;\n state.attested = false;\n state.attestation = null;\n state.channel = null;\n state.nonce = null;\n state.remoteStaticPublicKey = null;\n\n channel?.close();\n state.transport.close();\n\n if (shouldNotify) {\n for (const handler of state.policyViolationHandlers) handler(cause);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/session/state.ts"],"names":[],"mappings":";;;AAoDA,IAAM,QAAA,uBAAe,OAAA,EAA+B;AAG7C,SAAS,oBAAoB,KAAA,EAA8B;AAChE,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,IAAI,QAAA,GAAW;AACb,MAAA,OAAO,KAAA,CAAM,QAAA;AAAA,IACf;AAAA,GACF;AACA,EAAA,QAAA,CAAS,GAAA,CAAI,QAAQ,KAAK,CAAA;AAC1B,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,gBAAgB,OAAA,EAAgC;AAC9D,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA;AAClC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACjF;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,kBAAkB,KAAA,EAA2B;AAC3D,EAAA,iBAAA,CAAkB,KAAA,EAAO,IAAI,cAAA,CAAe,iBAAA,EAAmB,gBAAgB,CAAA,EAAG;AAAA,IAChF,qBAAA,EAAuB;AAAA,GACxB,CAAA;AACH;AAEO,SAAS,iBAAA,CACd,KAAA,EACA,KAAA,EACA,OAAA,GAAwD,EAAC,EACnD;AACN,EAAA,MAAM,qBAAA,GAAwB,QAAQ,qBAAA,IAAyB,IAAA;AAC/D,EAAA,MAAM,YAAA,GACJ,0BACC,KAAA,CAAM,QAAA,IAAY,MAAM,WAAA,KAAgB,IAAA,IAAQ,MAAM,OAAA,KAAY,IAAA,CAAA;AAErE,EAAA,IAAI,KAAA,CAAM,kBAAkB,IAAA,EAAM;AAChC,IAAA,YAAA,CAAa,MAAM,aAAa,CAAA;AAChC,IAAA,KAAA,CAAM,aAAA,GAAgB,IAAA;AAAA,EACxB;AACA,EAAA,KAAA,CAAM,eAAA,GAAkB,IAAA;AACxB,EAAA,KAAA,CAAM,cAAA,GAAiB,KAAA;AAEvB,EAAA,MAAM,UAAU,KAAA,CAAM,OAAA;AACtB,EAAA,KAAA,CAAM,QAAA,GAAW,KAAA;AACjB,EAAA,KAAA,CAAM,WAAA,GAAc,IAAA;AACpB,EAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,EAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AACd,EAAA,KAAA,CAAM,qBAAA,GAAwB,IAAA;AAE9B,EAAA,OAAA,EAAS,KAAA,EAAM;AACf,EAAA,KAAA,CAAM,UAAU,KAAA,EAAM;AAEtB,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,KAAA,MAAW,OAAA,IAAW,KAAA,CAAM,uBAAA,EAAyB,OAAA,CAAQ,KAAK,CAAA;AAAA,EACpE;AACF","file":"chunk-DOTYDYVB.js","sourcesContent":["/**\n * Internal session state and the opaque-handle registry.\n *\n * The public {@link Session} is opaque: consumers only read `session.attested`.\n * The real state (transport, endpoint pool, attestation result) is held here\n * and reached through {@link getSessionState}, keyed off the handle in a\n * `WeakMap` so it is never reachable from the public surface.\n */\n\nimport type { Session } from \"../core/session.js\";\nimport type { Transport } from \"../transport/types.js\";\nimport type { AttestationResult } from \"../transport/handshake.js\";\nimport type { SecureChannel } from \"./secureChannel.js\";\nimport type { CoordinatorPoolConfig } from \"../schemas/types.generated.js\";\nimport { TransportError } from \"../core/errors.js\";\nimport type { ClientPersistenceState } from \"../storage/clientPersistence.js\";\n\nexport interface SessionState {\n /** Flipped to `true` once attestation passes. */\n attested: boolean;\n /** The byte channel this session runs over. */\n readonly transport: Transport;\n /** The endpoint pool the session was created with. */\n readonly pool: CoordinatorPoolConfig;\n /** The last verified attestation result, or `null` before first attestation. */\n attestation: AttestationResult | null;\n /**\n * The live attested Noise channel, or `null` before/after attestation. All\n * application I/O Noise-encrypts through this.\n */\n channel: SecureChannel | null;\n /**\n * The per-connection 32-byte CSPRNG nonce bound into the attestation request.\n * Retained for re-attestation over the same channel.\n */\n nonce: Uint8Array | null;\n /** The coordinator's pinned Noise static public key, or `null` if unattested. */\n remoteStaticPublicKey: Uint8Array | null;\n /** Pending re-attestation timer, cleared on close. */\n reattestTimer: ReturnType<typeof setTimeout> | null;\n /** In-flight re-attestation shared by explicit and periodic checks. */\n reattestPromise: Promise<AttestationResult> | null;\n /** Fatal secure-channel cause preserved across transport close notifications. */\n lastFatalError: Error | null;\n /** Handlers invoked when an out-of-band re-attestation fails. */\n readonly policyViolationHandlers: Set<(error: Error) => void>;\n /** Resolved opt-in client-persistence policy, kept behind the opaque handle. */\n readonly clientPersistence: ClientPersistenceState;\n /** Tear down the session: clear the re-attest timer and close the channel. */\n close(): void;\n}\n\nconst registry = new WeakMap<Session, SessionState>();\n\n/** Build an opaque {@link Session} handle backed by `state`. */\nexport function createSessionHandle(state: SessionState): Session {\n const handle = {\n get attested() {\n return state.attested;\n },\n } as unknown as Session;\n registry.set(handle, state);\n return handle;\n}\n\n/**\n * Resolve the internal state for a session.\n *\n * @throws Error if the handle was not produced by `createSession`.\n */\nexport function getSessionState(session: Session): SessionState {\n const state = registry.get(session);\n if (!state) {\n throw new Error(\"invalid Session: this handle was not created by createSession\");\n }\n return state;\n}\n\nexport function closeSessionState(state: SessionState): void {\n failSessionClosed(state, new TransportError(\"CONNECTION_LOST\", \"session closed\"), {\n notifyPolicyViolation: false,\n });\n}\n\nexport function failSessionClosed(\n state: SessionState,\n cause: Error,\n options: { readonly notifyPolicyViolation?: boolean } = {},\n): void {\n const notifyPolicyViolation = options.notifyPolicyViolation ?? true;\n const shouldNotify =\n notifyPolicyViolation &&\n (state.attested || state.attestation !== null || state.channel !== null);\n\n if (state.reattestTimer !== null) {\n clearTimeout(state.reattestTimer);\n state.reattestTimer = null;\n }\n state.reattestPromise = null;\n state.lastFatalError = cause;\n\n const channel = state.channel;\n state.attested = false;\n state.attestation = null;\n state.channel = null;\n state.nonce = null;\n state.remoteStaticPublicKey = null;\n\n channel?.close();\n state.transport.close();\n\n if (shouldNotify) {\n for (const handler of state.policyViolationHandlers) handler(cause);\n }\n}\n"]}