@capxul/sdk 1.0.0-alpha.9 → 1.2.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.
- package/README.md +121 -6
- package/dist/{InMemoryAuthCacheAdapter-v5W-XB5M.mjs → InMemoryAuthCacheAdapter-Dr1sEd9y.mjs} +36 -16
- package/dist/InMemoryAuthCacheAdapter-Dr1sEd9y.mjs.map +1 -0
- package/dist/create-capxul-client-C7H5b68l.d.mts +2764 -0
- package/dist/create-capxul-client-C7H5b68l.d.mts.map +1 -0
- package/dist/create-capxul-client-DiqVIxsV.mjs +6980 -0
- package/dist/create-capxul-client-DiqVIxsV.mjs.map +1 -0
- package/dist/index.d.mts +119 -2020
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2464 -6308
- package/dist/index.mjs.map +1 -1
- package/dist/node/index.d.mts +3 -6
- package/dist/node/index.d.mts.map +1 -1
- package/dist/node/index.mjs +27 -27
- package/dist/node/index.mjs.map +1 -1
- package/dist/signer-CJT0pPiO.d.mts +301 -0
- package/dist/signer-CJT0pPiO.d.mts.map +1 -0
- package/dist/testing/index.d.mts +54 -0
- package/dist/testing/index.d.mts.map +1 -0
- package/dist/testing/index.mjs +1068 -0
- package/dist/testing/index.mjs.map +1 -0
- package/package.json +17 -18
- package/dist/InMemoryAuthCacheAdapter-v5W-XB5M.mjs.map +0 -1
- package/dist/index-CTXgQ_xR.d.mts +0 -158
- package/dist/index-CTXgQ_xR.d.mts.map +0 -1
- package/dist/ports/safe-deployment.d.mts +0 -2
- package/dist/ports/safe-deployment.mjs +0 -38
- package/dist/ports/safe-deployment.mjs.map +0 -1
- package/dist/safe-deployment-D3k9yndM.d.mts +0 -136
- package/dist/safe-deployment-D3k9yndM.d.mts.map +0 -1
- package/dist/signer-DqDtJU1l.d.mts +0 -145
- package/dist/signer-DqDtJU1l.d.mts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#deps","#rawBalance","#pendingOtps","#otpCountersByEmail","#authUserIdByEmail","#allocatedAuthUserIds","#authCache","#clock","#otpTtlMs","#failures","#getOrIssueAuthUserId","#tokenCounter","#jwtCounter","#authUserIdCounter","#script","fail","#script","#subscribers","#resolve","#identities","#clock","fail","#now","#accounts","#clock","#identity","#failures","#provisionMutex","#now","#rows","#failures","#balanceOfRaw","#created","#sumSubAccountRaws","#patchBalance","#events","#operations","#rawMode"],"sources":["../../src/testing/account/InMemoryAccountReadAdapter.ts","../../src/adapters/_shared/clock.ts","../../src/testing/clock/ManualClockAdapter.ts","../../src/testing/auth-client/InMemoryAuthClientAdapter.ts","../../src/testing/bootstrap/BootstrapStubAdapter.ts","../../src/testing/convex-call/ConvexCallStubAdapter.ts","../../src/testing/identity/InMemoryIdentityAdapter.ts","../../src/testing/smart-account/smart-account-derivation.ts","../../src/testing/smart-account/InMemorySmartAccountAdapter.ts","../../src/testing/sub-account/InMemorySubAccountAdapter.ts","../../src/testing/telemetry/RecordingTelemetryAdapter.ts","../../src/testing/index.ts"],"sourcesContent":["import { Errors, type CapxulError } from \"@capxul/config\";\nimport type { Account } from \"@capxul/types\";\nimport { toAccountId } from \"@capxul/types\";\nimport { Effect, Layer } from \"effect\";\n\nimport { fromWei } from \"../../domain/money/from-wei\";\nimport type {\n AccountReadError,\n AccountReadPort,\n FundFromFaucetInput,\n FundFromFaucetResult,\n ReadAccountBalanceInput,\n} from \"../../ports/account-read\";\nimport { toWei } from \"../../domain/money/to-wei\";\nimport { accountReadErrorFromCapxul, AccountReadPortTag } from \"../../ports/account-read\";\n\nexport type InMemoryAccountReadLayerDeps = {\n readonly account?: Account;\n readonly rawBalance?: string;\n readonly decimals?: number;\n readonly currency?: string;\n readonly accountId?: string;\n readonly failures?: {\n readonly readBalance?: CapxulError;\n readonly fundFromFaucet?: CapxulError;\n };\n};\n\nexport class InMemoryAccountReadAdapter implements AccountReadPort {\n readonly #deps: InMemoryAccountReadLayerDeps;\n #rawBalance: string;\n\n constructor(deps: InMemoryAccountReadLayerDeps = {}) {\n this.#deps = deps;\n this.#rawBalance = deps.rawBalance ?? \"0\";\n }\n\n readBalance(_input: ReadAccountBalanceInput): Effect.Effect<Account, AccountReadError> {\n const scriptedFailure = this.#deps.failures?.readBalance;\n if (scriptedFailure !== undefined) {\n return Effect.fail(accountReadErrorFromCapxul(\"readBalance\", scriptedFailure));\n }\n if (this.#deps.account !== undefined) {\n return Effect.succeed(cloneAccount(this.#deps.account));\n }\n const decimals = this.#deps.decimals ?? 6;\n const currency = this.#deps.currency ?? \"USD\";\n const money = fromWei(this.#rawBalance, decimals, currency);\n return Effect.succeed({\n id: toAccountId(this.#deps.accountId ?? \"account_01TEST000000000000000000\"),\n balance: money,\n available: money,\n });\n }\n\n fundFromFaucet(\n input: FundFromFaucetInput,\n ): Effect.Effect<FundFromFaucetResult, AccountReadError> {\n const scriptedFailure = this.#deps.failures?.fundFromFaucet;\n if (scriptedFailure !== undefined) {\n return Effect.fail(accountReadErrorFromCapxul(\"fundFromFaucet\", scriptedFailure));\n }\n const expectedDecimals = this.#deps.decimals ?? 6;\n const expectedCurrency = this.#deps.currency ?? \"USD\";\n if (\n input.amount.decimals !== expectedDecimals ||\n String(input.amount.currency) !== expectedCurrency\n ) {\n return Effect.fail(\n accountReadErrorFromCapxul(\n \"fundFromFaucet\",\n Errors.invalidInput(\"amount\", \"decimals/currency must match adapter config\"),\n ),\n );\n }\n const minted = BigInt(toWei(input.amount));\n this.#rawBalance = (BigInt(this.#rawBalance) + minted).toString();\n return Effect.succeed({ txHash: \"0x\" + \"f\".repeat(64) });\n }\n}\n\nexport function InMemoryAccountReadLayer(\n deps: InMemoryAccountReadLayerDeps = {},\n): Layer.Layer<AccountReadPortTag, AccountReadError, never> {\n return Layer.succeed(AccountReadPortTag, new InMemoryAccountReadAdapter(deps));\n}\n\nfunction cloneAccount(account: Account): Account {\n return {\n id: account.id,\n balance: { ...account.balance },\n available: { ...account.available },\n };\n}\n","import { Errors, type CapxulError } from \"@capxul/config\";\nimport type { EpochMs } from \"@capxul/types\";\nimport { Effect, Result } from \"effect\";\n\nimport type { ClockPort } from \"../../ports/clock\";\n\nexport type ClockNowResult =\n | { readonly ok: true; readonly value: EpochMs }\n | { readonly ok: false; readonly error: CapxulError };\n\nexport async function readClockNow(clock: ClockPort): Promise<ClockNowResult> {\n try {\n const result = await Effect.runPromise(Effect.result(clock.now));\n if (Result.isFailure(result)) {\n return { ok: false, error: Errors.providerError(\"clock\", \"now\", result.failure) };\n }\n return { ok: true, value: result.success };\n } catch (cause) {\n return { ok: false, error: Errors.providerError(\"clock\", \"now\", cause) };\n }\n}\n","/* oxlint-disable typescript/no-this-alias -- Effect.gen callbacks are generator functions, so adapter receivers are captured explicitly. */\nimport type { DurationMs, EpochMs } from \"@capxul/types\";\nimport { toDurationMs, toEpochMs } from \"@capxul/types\";\nimport { Effect, Layer } from \"effect\";\n\nimport { ClockError, ClockPortTag, type ClockPort } from \"../../ports/clock\";\nimport type { ClockAdapterUnderTest } from \"./under-test\";\n\ninterface PendingSleep {\n readonly deadline: number;\n readonly resolve: () => void;\n readonly seq: number;\n}\n\n/**\n * Event-discipline test clock. Time moves only when a release primitive is\n * invoked. `tickOne()` releases EXACTLY ONE pending sleep (the earliest\n * deadline, FIFO at ties) and snaps `now()` to that deadline. `advance(ms)`\n * composes repeated `tickOne()` calls over the resulting window — used to\n * keep the cross-adapter conformance harness uniform with the distance model\n * of `VirtualClockAdapter`. See `packages/sdk/docs/architecture.md` and the\n * slice spec `docs/slices/clock-adapters.md`.\n */\nexport class ManualClockAdapter implements ClockPort {\n private currentTime = 0;\n private queue: PendingSleep[] = [];\n private seqCounter = 0;\n\n constructor(deps: Record<string, never>) {\n void deps;\n }\n\n readonly now: Effect.Effect<EpochMs, ClockError, never> = Effect.sync(() =>\n toEpochMs(this.currentTime),\n );\n\n sleep(duration: DurationMs): Effect.Effect<void, ClockError, never> {\n return Effect.promise(\n () =>\n new Promise<void>((resolve) => {\n this.queue.push({\n deadline: this.currentTime + (duration as number),\n resolve,\n seq: this.seqCounter++,\n });\n }),\n );\n }\n\n /**\n * Release exactly one pending sleep — the earliest deadline, FIFO at ties.\n * Snaps `now()` forward to that sleep's deadline. No-op if the queue is\n * empty (preserves the empty-tick safety property).\n */\n tickOne(): Promise<void> {\n return Effect.runPromise(this.tickOneEffect());\n }\n\n tickOneEffect(): Effect.Effect<void, ClockError, never> {\n const self = this;\n return Effect.gen(function* () {\n if (self.queue.length === 0) return;\n const nextIndex = self.findEarliestIndex();\n const next = self.queue.splice(nextIndex, 1)[0]!;\n if (next.deadline > self.currentTime) {\n self.currentTime = next.deadline;\n }\n next.resolve();\n yield* Effect.yieldNow;\n });\n }\n\n /**\n * Cross-adapter harness affordance. Releases every sleep whose deadline\n * falls inside `[currentTime, currentTime + ms]` via repeated `tickOne()`,\n * then snaps `now()` to `currentTime + ms`. The composition is the seam\n * that lets the harness drive Manual and Virtual identically.\n */\n advance(ms: number): Promise<void> {\n return Effect.runPromise(this.advanceEffect(toDurationMs(ms)));\n }\n\n advanceEffect(duration: DurationMs): Effect.Effect<void, ClockError, never> {\n const self = this;\n return Effect.gen(function* () {\n yield* Effect.yieldNow;\n const target = self.currentTime + (duration as number);\n while (self.queue.length > 0 && self.earliestDeadline() <= target) {\n yield* self.tickOneEffect();\n }\n self.currentTime = target;\n });\n }\n\n private findEarliestIndex(): number {\n let bestIndex = 0;\n let best = this.queue[0]!;\n for (let i = 1; i < this.queue.length; i++) {\n const candidate = this.queue[i]!;\n if (\n candidate.deadline < best.deadline ||\n (candidate.deadline === best.deadline && candidate.seq < best.seq)\n ) {\n best = candidate;\n bestIndex = i;\n }\n }\n return bestIndex;\n }\n\n private earliestDeadline(): number {\n return this.queue[this.findEarliestIndex()]!.deadline;\n }\n\n static forConformance(): ClockAdapterUnderTest {\n return new ManualClockUnderTest(new ManualClockAdapter({}));\n }\n}\n\nclass ManualClockUnderTest implements ClockAdapterUnderTest {\n constructor(public readonly clock: ManualClockAdapter) {}\n\n advance(ms: number): Promise<void> {\n return this.clock.advance(ms);\n }\n}\n\nexport function ManualClockLayer(): Layer.Layer<ClockPortTag, ClockError, never> {\n return Layer.succeed(ClockPortTag, new ManualClockAdapter({}));\n}\n\nexport function advanceManualClock(\n duration: DurationMs,\n): Effect.Effect<void, ClockError, ClockPortTag> {\n return Effect.gen(function* () {\n const clock = yield* ClockPortTag;\n if (!(clock instanceof ManualClockAdapter)) {\n return yield* Effect.fail(\n new ClockError({\n operation: \"sleep\",\n cause: new Error(\"advanceManualClock requires ManualClockLayer\"),\n }),\n );\n }\n return yield* clock.advanceEffect(duration);\n });\n}\n\nexport function tickManualClockOnce(): Effect.Effect<void, ClockError, ClockPortTag> {\n return Effect.gen(function* () {\n const clock = yield* ClockPortTag;\n if (!(clock instanceof ManualClockAdapter)) {\n return yield* Effect.fail(\n new ClockError({\n operation: \"sleep\",\n cause: new Error(\"tickManualClockOnce requires ManualClockLayer\"),\n }),\n );\n }\n return yield* clock.tickOneEffect();\n });\n}\n","import { Errors, type CapxulError } from \"@capxul/config\";\nimport type { AuthSession, AuthUserId, DurationMs, Email, EpochMs } from \"@capxul/types\";\nimport {\n toAuthUserId,\n toDurationMs,\n toEpochMs,\n toEpochSeconds,\n toJwtToken,\n toSessionToken,\n} from \"@capxul/types\";\nimport { Effect, Result } from \"effect\";\n\nimport type {\n AuthClientOperationOptions,\n AuthClientPort,\n AuthClientResult,\n CanSendOtpInput,\n CanSendOtpStatus,\n GetConvexJwtOptions,\n SendOtpInput,\n VerifyOtpInput,\n} from \"../../ports/auth-client\";\nimport { AuthClientPortTag } from \"../../ports/auth-client\";\nimport type { AuthCacheError, AuthCachePort, CachedJwt } from \"../../ports/auth-cache\";\nimport type { ClockPort } from \"../../ports/clock\";\nimport { Layer } from \"effect\";\nimport { authClientPortFromPromiseAdapter } from \"../../adapters/auth-client/effect-port\";\nimport { InMemoryAuthCacheAdapter } from \"../../adapters/auth-cache/InMemoryAuthCacheAdapter\";\nimport { readClockNow } from \"../../adapters/_shared/clock\";\nimport { ManualClockAdapter } from \"../clock/ManualClockAdapter\";\n\nconst DEFAULT_OTP_TTL_MS = toDurationMs(5 * 60 * 1000);\nconst DEFAULT_SESSION_TTL_MS = toDurationMs(24 * 60 * 60 * 1000);\nconst DEFAULT_JWT_TTL_MS = toDurationMs(15 * 60 * 1000);\n\ninterface PendingOtp {\n readonly otp: string;\n readonly issuedAt: EpochMs;\n}\n\n/**\n * Hermetic OTP + session state machine implementing `AuthClientPort`. Wires\n * through `AuthCachePort` for persistence (clause A11) and `ClockPort`\n * for TTL + expiry math. OTPs are deterministic per-email counters (`\"000000\"`,\n * `\"000001\"`, …) so test assertions remain stable. Session tokens are\n * deterministic per-adapter counters (`\"tok_0\"`, `\"tok_1\"`, …). Returning users\n * (same email post-signOut) get the same `AuthUserId`.\n *\n * Never throws — every failure path returns `{ ok: false, error: CapxulError }`.\n * Honors `options.signal` via a pre-check (clause A10): an aborted controller\n * before method entry yields `{ ok: false, error: Errors.cancelled({ operation }) }`\n * without any state change.\n */\nexport class InMemoryAuthClientAdapter {\n readonly #pendingOtps = new Map<Email, PendingOtp>();\n readonly #otpCountersByEmail = new Map<Email, number>();\n readonly #authUserIdByEmail = new Map<Email, AuthUserId>();\n readonly #allocatedAuthUserIds = new Set<AuthUserId>();\n readonly #authCache: AuthCachePort;\n readonly #clock: ClockPort;\n readonly #otpTtlMs: DurationMs;\n readonly #failures: InMemoryAuthClientFailures;\n #authUserIdCounter = 0;\n #tokenCounter = 0;\n #jwtCounter = 0;\n\n constructor(deps: {\n readonly authCache: AuthCachePort;\n readonly clock: ClockPort;\n readonly otpTtlMs?: DurationMs;\n readonly failures?: InMemoryAuthClientFailures;\n }) {\n this.#authCache = deps.authCache;\n this.#clock = deps.clock;\n this.#otpTtlMs = deps.otpTtlMs ?? DEFAULT_OTP_TTL_MS;\n this.#failures = deps.failures ?? {};\n }\n\n /** Test affordance: peek the OTP for an email, simulating \"user reads email.\" */\n peekOtpForTesting(email: Email): string | undefined {\n return this.#pendingOtps.get(email)?.otp;\n }\n\n /** Test affordance: make a seeded identity own the session minted for its email. */\n bindAuthUserIdForTesting(email: Email, authUserId: AuthUserId): void {\n this.#authUserIdByEmail.set(email, authUserId);\n this.#allocatedAuthUserIds.add(authUserId);\n }\n\n async canSendOtp(\n input: CanSendOtpInput,\n options?: AuthClientOperationOptions,\n ): Promise<AuthClientResult<CanSendOtpStatus>> {\n if (options?.signal?.aborted) {\n return { ok: false, error: Errors.cancelled({ operation: \"canSendOtp\" }) };\n }\n if (this.#failures.canSendOtp !== undefined) {\n return { ok: false, error: this.#failures.canSendOtp };\n }\n const pending = this.#pendingOtps.get(input.email);\n if (pending === undefined) {\n return { ok: true, value: { allowed: true, cooldownMs: toDurationMs(0) } };\n }\n const nowResult = await readClockNow(this.#clock);\n if (!nowResult.ok) return nowResult;\n const elapsedMs = (nowResult.value as number) - (pending.issuedAt as number);\n const cooldownMs = Math.max(0, (this.#otpTtlMs as number) - elapsedMs);\n if (cooldownMs === 0) {\n this.#pendingOtps.delete(input.email);\n return { ok: true, value: { allowed: true, cooldownMs: toDurationMs(0) } };\n }\n return { ok: true, value: { allowed: false, cooldownMs: toDurationMs(cooldownMs) } };\n }\n\n async sendOtp(\n input: SendOtpInput,\n options?: AuthClientOperationOptions,\n ): Promise<AuthClientResult<void>> {\n if (options?.signal?.aborted) {\n return { ok: false, error: Errors.cancelled({ operation: \"sendOtp\" }) };\n }\n if (this.#failures.sendOtp !== undefined) {\n return { ok: false, error: this.#failures.sendOtp };\n }\n const issuedAt = await readClockNow(this.#clock);\n if (!issuedAt.ok) return issuedAt;\n const counter = this.#otpCountersByEmail.get(input.email) ?? 0;\n this.#otpCountersByEmail.set(input.email, counter + 1);\n const otp = counter.toString().padStart(6, \"0\");\n this.#pendingOtps.set(input.email, {\n otp,\n issuedAt: issuedAt.value,\n });\n return { ok: true, value: undefined };\n }\n\n async verifyOtp(\n input: VerifyOtpInput,\n options?: AuthClientOperationOptions,\n ): Promise<AuthClientResult<AuthSession>> {\n if (options?.signal?.aborted) {\n return { ok: false, error: Errors.cancelled({ operation: \"verifyOtp\" }) };\n }\n if (this.#failures.verifyOtp !== undefined) {\n return { ok: false, error: this.#failures.verifyOtp };\n }\n const pending = this.#pendingOtps.get(input.email);\n if (pending === undefined) {\n return { ok: false, error: Errors.invalidInput(\"email\", \"no OTP issued for this email\") };\n }\n const nowResult = await readClockNow(this.#clock);\n if (!nowResult.ok) return nowResult;\n const now = nowResult.value;\n if ((now as number) - (pending.issuedAt as number) > (this.#otpTtlMs as number)) {\n this.#pendingOtps.delete(input.email);\n return { ok: false, error: Errors.otpExpired() };\n }\n if (input.otp !== pending.otp) {\n return { ok: false, error: Errors.invalidInput(\"otp\", \"incorrect OTP\") };\n }\n\n const authUserId = this.#getOrIssueAuthUserId(input.email);\n const token = toSessionToken(`tok_${this.#tokenCounter++}`);\n const expiresAt = toEpochMs((now as number) + (DEFAULT_SESSION_TTL_MS as number));\n const session: AuthSession = {\n authUserId,\n email: input.email,\n token,\n expiresAt,\n };\n const cacheWrite = await runAuthCacheEffect(this.#authCache.setSession(session), \"setSession\");\n if (!cacheWrite.ok) return cacheWrite;\n this.#pendingOtps.delete(input.email);\n return { ok: true, value: session };\n }\n\n async getSession(\n options?: AuthClientOperationOptions,\n ): Promise<AuthClientResult<AuthSession | null>> {\n if (options?.signal?.aborted) {\n return { ok: false, error: Errors.cancelled({ operation: \"getSession\" }) };\n }\n if (this.#failures.getSession !== undefined) {\n return { ok: false, error: this.#failures.getSession };\n }\n const cacheRead = await runAuthCacheEffect(this.#authCache.getSession, \"getSession\");\n if (!cacheRead.ok) return cacheRead;\n const persisted = cacheRead.value;\n if (persisted === null) {\n return { ok: true, value: null };\n }\n const nowResult = await readClockNow(this.#clock);\n if (!nowResult.ok) return nowResult;\n const now = nowResult.value;\n if ((persisted.expiresAt as number) <= (now as number)) {\n const cacheClear = await runAuthCacheEffect(this.#authCache.clearSession, \"clearSession\");\n if (!cacheClear.ok) return cacheClear;\n return { ok: true, value: null };\n }\n return { ok: true, value: persisted };\n }\n\n async signOut(options?: AuthClientOperationOptions): Promise<AuthClientResult<void>> {\n if (options?.signal?.aborted) {\n return { ok: false, error: Errors.cancelled({ operation: \"signOut\" }) };\n }\n if (this.#failures.signOut !== undefined) {\n return { ok: false, error: this.#failures.signOut };\n }\n return runAuthCacheEffect(this.#authCache.clearSession, \"clearSession\");\n }\n\n async getConvexJwt(options?: GetConvexJwtOptions): Promise<AuthClientResult<CachedJwt>> {\n if (options?.signal?.aborted) {\n return { ok: false, error: Errors.cancelled({ operation: \"getConvexJwt\" }) };\n }\n if (this.#failures.getConvexJwt !== undefined) {\n return { ok: false, error: this.#failures.getConvexJwt };\n }\n if (options?.forceRefresh !== true) {\n const cacheRead = await runAuthCacheEffect(this.#authCache.getJwt, \"getJwt\");\n if (!cacheRead.ok) return cacheRead;\n if (cacheRead.value !== null) {\n return { ok: true, value: cacheRead.value };\n }\n }\n const now = await readClockNow(this.#clock);\n if (!now.ok) return now;\n const jwt: CachedJwt = {\n token: toJwtToken(`in-memory-jwt-${this.#jwtCounter++}`),\n expEpochSeconds: toEpochSeconds(\n Math.floor((now.value as number) / 1000 + (DEFAULT_JWT_TTL_MS as number) / 1000),\n ),\n };\n const cacheWrite = await runAuthCacheEffect(this.#authCache.setJwt(jwt), \"setJwt\");\n if (!cacheWrite.ok) return cacheWrite;\n return { ok: true, value: jwt };\n }\n\n #getOrIssueAuthUserId(email: Email): AuthUserId {\n const existing = this.#authUserIdByEmail.get(email);\n if (existing !== undefined) {\n return existing;\n }\n let fresh: AuthUserId;\n do {\n fresh = toAuthUserId(`user_${this.#authUserIdCounter++}`);\n } while (this.#allocatedAuthUserIds.has(fresh));\n this.#authUserIdByEmail.set(email, fresh);\n this.#allocatedAuthUserIds.add(fresh);\n return fresh;\n }\n}\n\nexport function InMemoryAuthClientLayer(\n deps: {\n readonly authCache: AuthCachePort;\n readonly clock: ClockPort;\n readonly otpTtlMs?: DurationMs;\n readonly failures?: InMemoryAuthClientFailures;\n } = {\n authCache: new InMemoryAuthCacheAdapter(),\n clock: new ManualClockAdapter({}),\n },\n): Layer.Layer<AuthClientPortTag> {\n return Layer.succeed(AuthClientPortTag, makeInMemoryAuthClientPort(deps));\n}\n\nexport function makeInMemoryAuthClientPort(deps: {\n readonly authCache: AuthCachePort;\n readonly clock: ClockPort;\n readonly otpTtlMs?: DurationMs;\n readonly failures?: InMemoryAuthClientFailures;\n}): AuthClientPort {\n return authClientPortFromPromiseAdapter(new InMemoryAuthClientAdapter(deps));\n}\n\nexport type InMemoryAuthClientFailures = {\n readonly canSendOtp?: CapxulError;\n readonly sendOtp?: CapxulError;\n readonly verifyOtp?: CapxulError;\n readonly getSession?: CapxulError;\n readonly signOut?: CapxulError;\n readonly getConvexJwt?: CapxulError;\n};\n\nasync function runAuthCacheEffect<T>(\n effect: Effect.Effect<T, AuthCacheError>,\n operation: string,\n): Promise<AuthClientResult<T>> {\n const result = await Effect.runPromise(Effect.result(effect));\n if (Result.isFailure(result)) {\n return {\n ok: false,\n error: Errors.providerError(\"auth-cache\", operation, result.failure),\n };\n }\n return { ok: true, value: result.success };\n}\n","import type { CapxulError } from \"@capxul/config\";\nimport { Errors } from \"@capxul/config\";\nimport { Effect, Layer } from \"effect\";\n\nimport type { BootstrapInput, BootstrapPort, BootstrapResolution } from \"../../ports/bootstrap\";\nimport {\n BootstrapPortTag,\n bootstrapErrorFromCapxul,\n type BootstrapError,\n} from \"../../ports/bootstrap\";\n\nexport type BootstrapStubScript = {\n /** Keyed by `bootstrapStubScriptKey(input)`. */\n readonly resolutions?: ReadonlyMap<string, BootstrapResolution>;\n /** Keyed by `bootstrapStubScriptKey(input)`. */\n readonly failures?: ReadonlyMap<string, CapxulError>;\n /**\n * Returned when neither map matches. Defaults to `Errors.notAuthenticated()`\n * so the Stub is enumeration-resistant by default.\n */\n readonly defaultFailure?: CapxulError;\n};\n\nexport type BootstrapLayerScenario =\n | \"success\"\n | \"unknownKey\"\n | \"wrongOrigin\"\n | \"revokedKey\"\n | \"pastGraceKey\"\n | \"networkFailure\"\n | \"providerFailure\"\n | \"malformedBodyFailure\";\n\nexport type BootstrapFixtureLayerDeps = {\n readonly input: BootstrapInput;\n readonly resolution: BootstrapResolution;\n readonly scenario?: BootstrapLayerScenario;\n readonly invalidInputs?: Readonly<Record<string, BootstrapInput>>;\n readonly failures?: {\n readonly notAuthenticated?: CapxulError;\n readonly network?: CapxulError;\n readonly provider?: CapxulError;\n readonly malformedBody?: CapxulError;\n };\n};\n\nexport type BootstrapStubLayerDeps =\n | { readonly script: BootstrapStubScript }\n | BootstrapFixtureLayerDeps;\n\nexport class BootstrapStubAdapter implements BootstrapPort {\n readonly #script: BootstrapStubScript;\n\n constructor(deps: { readonly script: BootstrapStubScript }) {\n this.#script = deps.script;\n }\n\n resolve(input: BootstrapInput): Effect.Effect<BootstrapResolution, BootstrapError> {\n const key = bootstrapStubScriptKey(input);\n const failure = this.#script.failures?.get(key);\n if (failure !== undefined) {\n return fail(kindFromCapxulError(failure), failure);\n }\n const resolution = this.#script.resolutions?.get(key);\n if (resolution !== undefined) {\n return Effect.succeed(resolution);\n }\n const defaultFailure = this.#script.defaultFailure ?? Errors.notAuthenticated();\n return fail(kindFromCapxulError(defaultFailure), defaultFailure);\n }\n}\n\nexport function bootstrapStubScriptKey(input: BootstrapInput): string {\n return `${String(input.publishableKey)}::${input.origin ?? \"\"}`;\n}\n\nexport function BootstrapStubLayer(\n input: BootstrapStubLayerDeps,\n scenario: BootstrapLayerScenario = \"success\",\n): Layer.Layer<BootstrapPortTag> {\n if (\"script\" in input) {\n return Layer.succeed(BootstrapPortTag, new BootstrapStubAdapter(input));\n }\n return Layer.succeed(\n BootstrapPortTag,\n makeFixtureBootstrapPort(input, input.scenario ?? scenario),\n );\n}\n\nexport function makeFixtureBootstrapPort(\n input: BootstrapFixtureLayerDeps,\n scenario: BootstrapLayerScenario = \"success\",\n): BootstrapPort {\n return {\n resolve: (request) => {\n const scenarioFailure = failureForScenario(input, scenario);\n if (scenarioFailure !== null) return scenarioFailure;\n if (sameBootstrapInput(request, input.input)) return Effect.succeed(input.resolution);\n return fail(\n \"notAuthenticated\",\n input.failures?.notAuthenticated ?? Errors.notAuthenticated(),\n );\n },\n };\n}\n\nfunction failureForScenario(\n input: BootstrapFixtureLayerDeps,\n scenario: BootstrapLayerScenario,\n): Effect.Effect<never, BootstrapError> | null {\n if (scenario === \"networkFailure\") {\n return fail(\"network\", input.failures?.network ?? Errors.networkError(\"bootstrap.resolve\"));\n }\n if (scenario === \"providerFailure\") {\n return fail(\n \"provider\",\n input.failures?.provider ?? Errors.providerError(\"bootstrap\", \"resolve\", \"provider failure\"),\n );\n }\n if (scenario === \"malformedBodyFailure\") {\n return fail(\n \"malformedBody\",\n input.failures?.malformedBody ??\n Errors.providerError(\"bootstrap\", \"resolve\", \"malformed body\"),\n );\n }\n return null;\n}\n\nfunction kindFromCapxulError(error: CapxulError): BootstrapError[\"kind\"] {\n if (error.code === \"NOT_AUTHENTICATED\") return \"notAuthenticated\";\n if (error.code === \"NETWORK_ERROR\") return \"network\";\n if (error.code === \"RATE_LIMITED\") return \"rateLimited\";\n if (error.code === \"INVALID_INPUT\") return \"invalidInput\";\n return \"provider\";\n}\n\nfunction fail(\n kind: BootstrapError[\"kind\"],\n error: CapxulError,\n): Effect.Effect<never, BootstrapError> {\n return Effect.fail(bootstrapErrorFromCapxul(kind, error));\n}\n\nfunction sameBootstrapInput(left: BootstrapInput, right: BootstrapInput): boolean {\n if (left.publishableKey !== right.publishableKey) return false;\n if ((left.origin === undefined) !== (right.origin === undefined)) return false;\n return left.origin === right.origin;\n}\n","import { CapxulError, Errors } from \"@capxul/config\";\nimport { getFunctionName, type FunctionReference } from \"convex/server\";\nimport { Effect, Layer } from \"effect\";\n\nimport {\n ConvexCallPortTag,\n convexCallErrorFromCapxul,\n type ConvexCallError,\n type ConvexCallPort,\n type Snapshot,\n type Unsubscribe,\n} from \"../../ports/convex-call\";\n\nexport type ConvexCallStubScript = {\n readonly responses?: ReadonlyMap<string, unknown>;\n readonly failures?: ReadonlyMap<string, unknown>;\n readonly subscriptions?: ReadonlyMap<string, ReadonlyArray<Snapshot<unknown>>>;\n};\n\nexport type ConvexCallStubLayerDeps = {\n readonly script: ConvexCallStubScript;\n};\n\ntype Subscriber = {\n readonly callback: (snapshot: Snapshot<unknown>) => void;\n cursor: number;\n};\n\nconst activeStubAdapters = new Set<ConvexCallStubAdapter>();\n\nexport class ConvexCallStubAdapter implements ConvexCallPort {\n readonly #script: ConvexCallStubScript;\n readonly #subscribers = new Map<string, Set<Subscriber>>();\n\n constructor(deps: ConvexCallStubLayerDeps) {\n this.#script = deps.script;\n }\n\n query<TArgs extends Record<string, unknown>, TOutput>(\n fn: FunctionReference<\"query\", \"public\", TArgs, TOutput>,\n _args: TArgs,\n ): Effect.Effect<TOutput, ConvexCallError> {\n return this.#resolve<TOutput>(getFunctionName(fn));\n }\n\n mutation<TArgs extends Record<string, unknown>, TOutput>(\n fn: FunctionReference<\"mutation\", \"public\", TArgs, TOutput>,\n _args: TArgs,\n ): Effect.Effect<TOutput, ConvexCallError> {\n return this.#resolve<TOutput>(getFunctionName(fn));\n }\n\n action<TArgs extends Record<string, unknown>, TOutput>(\n fn: FunctionReference<\"action\", \"public\", TArgs, TOutput>,\n _args: TArgs,\n ): Effect.Effect<TOutput, ConvexCallError> {\n return this.#resolve<TOutput>(getFunctionName(fn));\n }\n\n subscribe<TArgs extends Record<string, unknown>, TOutput>(\n fn: FunctionReference<\"query\", \"public\", TArgs, TOutput>,\n _args: TArgs,\n callback: (snapshot: Snapshot<TOutput>) => void,\n ): Effect.Effect<Unsubscribe, ConvexCallError> {\n return Effect.sync(() => {\n const path = getFunctionName(fn);\n const cb = callback as (snapshot: Snapshot<unknown>) => void;\n cb({ status: \"loading\" });\n const sequence = this.#script.subscriptions?.get(path);\n const subscriber: Subscriber = { callback: cb, cursor: 0 };\n let subs = this.#subscribers.get(path);\n if (subs === undefined) {\n subs = new Set();\n this.#subscribers.set(path, subs);\n }\n subs.add(subscriber);\n if (sequence !== undefined && sequence.length > 0) {\n cb(sequence[0]!);\n subscriber.cursor = 1;\n }\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n const liveSubs = this.#subscribers.get(path);\n if (liveSubs === undefined) return;\n liveSubs.delete(subscriber);\n if (liveSubs.size === 0) this.#subscribers.delete(path);\n };\n });\n }\n\n advanceSubscription(path: string): void {\n const sequence = this.#script.subscriptions?.get(path);\n if (sequence === undefined) return;\n const subs = this.#subscribers.get(path);\n if (subs === undefined) return;\n for (const sub of subs) {\n if (sub.cursor >= sequence.length) continue;\n const next = sequence[sub.cursor]!;\n sub.cursor += 1;\n sub.callback(next);\n }\n }\n\n #resolve<TOutput>(path: string): Effect.Effect<TOutput, ConvexCallError> {\n const failure = this.#script.failures?.get(path);\n if (failure !== undefined) {\n return Effect.fail(mapFailure(path, failure));\n }\n if (this.#script.responses?.has(path)) {\n return Effect.succeed(this.#script.responses.get(path) as TOutput);\n }\n return Effect.fail(\n convexCallErrorFromCapxul(path, Errors.providerError(\"convex\", path, \"unknown function\")),\n );\n }\n}\n\nexport function ConvexCallStubLayer(\n deps: ConvexCallStubLayerDeps,\n): Layer.Layer<ConvexCallPortTag, never, never> {\n return Layer.effect(\n ConvexCallPortTag,\n Effect.acquireRelease(\n Effect.sync(() => {\n const adapter = new ConvexCallStubAdapter(deps);\n activeStubAdapters.add(adapter);\n return adapter;\n }),\n (adapter) =>\n Effect.sync(() => {\n activeStubAdapters.delete(adapter);\n }),\n ),\n );\n}\n\nexport function advanceConvexCallStubSubscription<TArgs extends Record<string, unknown>, TOutput>(\n fn: FunctionReference<\"query\", \"public\", TArgs, TOutput>,\n): Effect.Effect<void> {\n return Effect.sync(() => {\n const path = getFunctionName(fn);\n for (const adapter of activeStubAdapters) {\n adapter.advanceSubscription(path);\n }\n });\n}\n\nfunction mapFailure(operation: string, failure: unknown): ConvexCallError {\n if (failure instanceof CapxulError) return convexCallErrorFromCapxul(operation, failure);\n if (failure instanceof Error) {\n return convexCallErrorFromCapxul(operation, Errors.providerError(\"convex\", operation, failure));\n }\n return convexCallErrorFromCapxul(\n operation,\n Errors.providerError(\"convex\", operation, new Error(String(failure))),\n );\n}\n","/* oxlint-disable typescript/no-this-alias -- Effect.gen callbacks are generator functions, so adapter receivers are captured explicitly. */\nimport type { CapxulError } from \"@capxul/config\";\nimport { Errors } from \"@capxul/config\";\nimport type { AuthUserId, EpochMs, Profile } from \"@capxul/types\";\nimport { toKycTier } from \"@capxul/types\";\nimport { Effect, Layer } from \"effect\";\n\nimport { ClockPortTag, type ClockPort } from \"../../ports/clock\";\nimport type {\n CompleteOnboardingIdentityInput,\n CreateIdentityInput,\n IdentityError,\n IdentityPort,\n UpdateIdentityInput,\n} from \"../../ports/identity\";\nimport { identityErrorFromCapxul, IdentityPortTag } from \"../../ports/identity\";\n\nexport type InMemoryIdentityLayerDeps = {\n readonly clock: ClockPort;\n};\n\nexport class InMemoryIdentityAdapter implements IdentityPort {\n readonly #identities = new Map<AuthUserId, Profile>();\n readonly #clock: ClockPort;\n\n constructor(deps: InMemoryIdentityLayerDeps) {\n this.#clock = deps.clock;\n }\n\n loadByAuthUserId(authUserId: AuthUserId): Effect.Effect<Profile | null, IdentityError> {\n return Effect.sync(() => cloneProfileOrNull(this.#identities.get(authUserId) ?? null));\n }\n\n create(input: CreateIdentityInput): Effect.Effect<Profile, IdentityError> {\n const self = this;\n return Effect.gen(function* () {\n if (self.#identities.has(input.authUserId)) {\n return yield* fail(\"create\", Errors.invalidInput(\"authUserId\", \"already exists\"));\n }\n const now = yield* self.#now(\"create.clock\");\n const profile: Profile = {\n authUserId: input.authUserId,\n email: input.email,\n displayName: input.displayName ?? null,\n country: input.country ?? null,\n onboarded: false,\n withdrawalAddress: null,\n username: null,\n imageUrl: null,\n kycTier: toKycTier(0),\n createdAt: now,\n updatedAt: now,\n };\n self.#identities.set(input.authUserId, cloneProfile(profile));\n return cloneProfile(profile);\n });\n }\n\n update(input: UpdateIdentityInput): Effect.Effect<Profile, IdentityError> {\n const self = this;\n return Effect.gen(function* () {\n const existing = self.#identities.get(input.authUserId);\n if (existing === undefined) {\n return yield* fail(\"update\", Errors.profileNotFound(input.authUserId));\n }\n const now = yield* self.#now(\"update.clock\");\n const updated: Profile = {\n authUserId: existing.authUserId,\n email: existing.email,\n kycTier: existing.kycTier,\n createdAt: existing.createdAt,\n displayName: input.displayName !== undefined ? input.displayName : existing.displayName,\n country: input.country !== undefined ? input.country : existing.country,\n onboarded: existing.onboarded,\n withdrawalAddress: existing.withdrawalAddress,\n username: existing.username,\n imageUrl: existing.imageUrl,\n updatedAt: now,\n };\n self.#identities.set(input.authUserId, cloneProfile(updated));\n return cloneProfile(updated);\n });\n }\n\n completeOnboarding(\n input: CompleteOnboardingIdentityInput,\n ): Effect.Effect<Profile, IdentityError> {\n const self = this;\n return Effect.gen(function* () {\n const now = yield* self.#now(\"completeOnboarding.clock\");\n const existing = self.#identities.get(input.authUserId);\n const profile: Profile = {\n authUserId: input.authUserId,\n email: existing?.email ?? input.email,\n displayName: input.displayName,\n country: input.country,\n onboarded: true,\n withdrawalAddress: input.withdrawalAddress ?? existing?.withdrawalAddress ?? null,\n username: existing?.username ?? null,\n imageUrl: existing?.imageUrl ?? null,\n kycTier: existing?.kycTier ?? toKycTier(0),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n };\n self.#identities.set(input.authUserId, cloneProfile(profile));\n return cloneProfile(profile);\n });\n }\n\n #now(operation: string): Effect.Effect<EpochMs, IdentityError> {\n return this.#clock.now.pipe(\n Effect.mapError((cause) =>\n identityErrorFromCapxul(operation, Errors.providerError(\"clock\", \"now\", cause), cause),\n ),\n );\n }\n}\n\nexport function InMemoryIdentityLayer(): Layer.Layer<IdentityPortTag, IdentityError, ClockPortTag> {\n return Layer.effect(\n IdentityPortTag,\n Effect.map(ClockPortTag, (clock) => new InMemoryIdentityAdapter({ clock })),\n );\n}\n\nfunction fail(operation: string, error: CapxulError): Effect.Effect<never, IdentityError> {\n return Effect.fail(identityErrorFromCapxul(operation, error));\n}\n\nfunction cloneProfile(profile: Profile): Profile {\n return {\n authUserId: profile.authUserId,\n email: profile.email,\n displayName: profile.displayName,\n country: profile.country,\n onboarded: profile.onboarded,\n withdrawalAddress: profile.withdrawalAddress,\n username: profile.username,\n imageUrl: profile.imageUrl,\n kycTier: profile.kycTier,\n createdAt: profile.createdAt,\n updatedAt: profile.updatedAt,\n };\n}\n\nfunction cloneProfileOrNull(profile: Profile | null): Profile | null {\n return profile === null ? null : cloneProfile(profile);\n}\n","import type { Address, ChainId } from \"@capxul/types\";\nimport { toAddress } from \"@capxul/types\";\nimport { encodePacked, getCreate2Address, keccak256 } from \"viem\";\n\nimport { addressForViem, wireChainId } from \"../../adapters/_shared/wire\";\n\nconst SUPPORTED_CHAIN_IDS = new Set<number>([84532, 8453]);\nconst SAFE_DEPLOYER_ADDRESS: Address = toAddress(\"0xa6b71e26c5e0845f74c812102ca7114b6a896ab2\");\nconst SAFE_INITCODE_HASH = keccak256(\"0x\");\n\nexport function isSupportedSmartAccountChain(chainId: ChainId): boolean {\n return SUPPORTED_CHAIN_IDS.has(wireChainId(chainId));\n}\n\nexport function deriveSmartAccountAddress(signerAddress: Address, chainId: ChainId): Address {\n const normalizedSigner = toAddress(signerAddress);\n const salt = keccak256(\n encodePacked([\"address\", \"uint256\"], [addressForViem(normalizedSigner), BigInt(chainId)]),\n );\n return toAddress(\n getCreate2Address({\n from: addressForViem(SAFE_DEPLOYER_ADDRESS),\n salt,\n bytecodeHash: SAFE_INITCODE_HASH,\n }),\n );\n}\n","/* oxlint-disable typescript/no-this-alias -- Effect.gen callbacks are generator functions, so adapter receivers are captured explicitly. */\nimport type { CapxulError } from \"@capxul/config\";\nimport { deriveCapxulSafeAddress, Errors } from \"@capxul/config\";\nimport type { Address, AuthUserId, EpochMs, SmartAccount } from \"@capxul/types\";\nimport { toAddress } from \"@capxul/types\";\nimport { Effect, Layer, Semaphore } from \"effect\";\n\nimport { ClockPortTag, type ClockPort } from \"../../ports/clock\";\nimport { IdentityPortTag, type IdentityPort } from \"../../ports/identity\";\nimport type {\n ClaimInput,\n ConfirmDeploymentInput,\n ProvisionInput,\n SmartAccountError,\n SmartAccountPort,\n} from \"../../ports/smart-account\";\nimport { smartAccountErrorFromCapxul, SmartAccountPortTag } from \"../../ports/smart-account\";\nimport { isSupportedSmartAccountChain } from \"./smart-account-derivation\";\n\nexport type InMemorySmartAccountLayerDeps = {\n readonly clock: ClockPort;\n readonly identity: IdentityPort;\n readonly failures?: {\n readonly loadByAuthUserId?: CapxulError;\n readonly loadBySmartAccountAddress?: CapxulError;\n readonly provision?: CapxulError;\n readonly claim?: CapxulError;\n };\n};\n\n/**\n * Hermetic backend stand-in (PRD #462 / derivation v2): `provision` derives\n * the Safe from the identity email alone via the REAL canonical derivation\n * (`deriveCapxulSafeAddress({ email })` — owner is the pinned bootstrap\n * constant). No signer exists at provision; `claim` installs the signer and\n * marks the row deployed, mirroring the backend's one-userOp claim lane.\n */\nexport class InMemorySmartAccountAdapter implements SmartAccountPort {\n readonly #accounts = new Map<AuthUserId, SmartAccount>();\n readonly #clock: ClockPort;\n readonly #identity: IdentityPort;\n readonly #failures: InMemorySmartAccountLayerDeps[\"failures\"];\n readonly #provisionMutex = Semaphore.makeUnsafe(1);\n\n constructor(deps: InMemorySmartAccountLayerDeps) {\n this.#clock = deps.clock;\n this.#identity = deps.identity;\n this.#failures = deps.failures;\n }\n\n loadByAuthUserId(authUserId: AuthUserId): Effect.Effect<SmartAccount | null, SmartAccountError> {\n const scriptedFailure = this.#failures?.loadByAuthUserId;\n if (scriptedFailure !== undefined) return fail(\"loadByAuthUserId\", scriptedFailure);\n return Effect.sync(() => cloneSmartAccountOrNull(this.#accounts.get(authUserId) ?? null));\n }\n\n loadBySmartAccountAddress(\n address: Address,\n ): Effect.Effect<SmartAccount | null, SmartAccountError> {\n const scriptedFailure = this.#failures?.loadBySmartAccountAddress;\n if (scriptedFailure !== undefined) return fail(\"loadBySmartAccountAddress\", scriptedFailure);\n return Effect.sync(() => {\n const needle = toAddress(address);\n for (const account of this.#accounts.values()) {\n if (account.smartAccountAddress === needle) return cloneSmartAccount(account);\n }\n return null;\n });\n }\n\n provision(input: ProvisionInput): Effect.Effect<SmartAccount, SmartAccountError> {\n const scriptedFailure = this.#failures?.provision;\n if (scriptedFailure !== undefined) return fail(\"provision\", scriptedFailure);\n const self = this;\n return Effect.gen(function* () {\n if (!isSupportedSmartAccountChain(input.chainId)) {\n return yield* fail(\n \"provision\",\n Errors.invalidInput(\"chainId\", `unsupported chainId ${String(input.chainId)}`),\n );\n }\n\n const identity = yield* self.#identity\n .loadByAuthUserId(input.authUserId)\n .pipe(\n Effect.mapError((error) =>\n smartAccountErrorFromCapxul(\"provision.identity\", error.publicError, error),\n ),\n );\n if (identity === null) {\n return yield* fail(\"provision\", Errors.profileNotFound(String(input.authUserId)));\n }\n\n const existing = self.#accounts.get(input.authUserId);\n if (existing !== undefined) return cloneSmartAccount(existing);\n\n const now = yield* self.#now(\"provision.clock\");\n const account: SmartAccount = {\n authUserId: input.authUserId,\n // PRD #462: no signer exists at provision — installed at claim.\n signerAddress: null,\n smartAccountAddress: toAddress(deriveCapxulSafeAddress({ email: identity.email })),\n chainId: input.chainId,\n deployedAt: null,\n claimedAt: null,\n createdAt: now,\n };\n self.#accounts.set(input.authUserId, cloneSmartAccount(account));\n return cloneSmartAccount(account);\n }).pipe(self.#provisionMutex.withPermits(1));\n }\n\n promoteDeployedAt(authUserId: AuthUserId, deployedAt: EpochMs): void {\n const existing = this.#accounts.get(authUserId);\n if (existing === undefined) return;\n if (existing.deployedAt !== null) return;\n this.#accounts.set(authUserId, { ...existing, deployedAt });\n }\n\n confirmDeployment(input: ConfirmDeploymentInput): Effect.Effect<SmartAccount, SmartAccountError> {\n const self = this;\n return Effect.gen(function* () {\n const existing = self.#accounts.get(input.authUserId);\n if (existing === undefined) {\n return yield* fail(\"confirmDeployment\", Errors.profileNotFound(String(input.authUserId)));\n }\n if (existing.smartAccountAddress !== toAddress(input.safeAddress)) {\n return yield* fail(\n \"confirmDeployment\",\n Errors.invalidInput(\"safeAddress\", \"does not match backend smart-account row\"),\n );\n }\n // γ-B: backend (this hermetic stand-in) is the ORACLE for\n // `deployedAt`. Derive from the clock — NEVER from any field on\n // `input.evidence`.\n if (existing.deployedAt !== null) {\n return cloneSmartAccount(existing);\n }\n const now = yield* self.#now(\"confirmDeployment.clock\");\n const updated: SmartAccount = { ...existing, deployedAt: now };\n self.#accounts.set(input.authUserId, cloneSmartAccount(updated));\n return cloneSmartAccount(updated);\n }).pipe(self.#provisionMutex.withPermits(1));\n }\n\n claim(input: ClaimInput): Effect.Effect<SmartAccount, SmartAccountError> {\n const scriptedFailure = this.#failures?.claim;\n if (scriptedFailure !== undefined) return fail(\"claim\", scriptedFailure);\n const self = this;\n return Effect.gen(function* () {\n const existing = self.#accounts.get(input.authUserId);\n if (existing === undefined) {\n return yield* fail(\n \"claim\",\n Errors.invalidInput(\"account\", \"no provisioned smart account for this user\"),\n );\n }\n if (existing.chainId !== input.chainId) {\n return yield* fail(\n \"claim\",\n Errors.invalidInput(\"chainId\", \"does not match backend smart-account row\"),\n );\n }\n const newOwner = toAddress(input.signerAddress);\n // Idempotency mirrors the backend claim action: a confirmed claim is\n // final; a different signer is an explicit error (recovery is a\n // separate lane, out of scope per PRD #462).\n if (existing.claimedAt !== null) {\n if (existing.signerAddress !== newOwner) {\n return yield* fail(\n \"claim\",\n Errors.invalidInput(\"signerAddress\", \"account already claimed by a different signer\"),\n );\n }\n return cloneSmartAccount(existing);\n }\n const now = yield* self.#now(\"claim.clock\");\n const updated: SmartAccount = {\n ...existing,\n signerAddress: newOwner,\n claimedAt: now,\n deployedAt: existing.deployedAt ?? now,\n };\n self.#accounts.set(input.authUserId, cloneSmartAccount(updated));\n return cloneSmartAccount(updated);\n }).pipe(self.#provisionMutex.withPermits(1));\n }\n\n #now(operation: string): Effect.Effect<EpochMs, SmartAccountError> {\n return this.#clock.now.pipe(\n Effect.mapError((cause) =>\n smartAccountErrorFromCapxul(operation, Errors.providerError(\"clock\", \"now\", cause), cause),\n ),\n );\n }\n}\n\nexport function InMemorySmartAccountLayer(\n deps: {\n readonly failures?: InMemorySmartAccountLayerDeps[\"failures\"];\n } = {},\n): Layer.Layer<SmartAccountPortTag, SmartAccountError, ClockPortTag | IdentityPortTag> {\n return Layer.effect(\n SmartAccountPortTag,\n Effect.gen(function* () {\n const clock = yield* ClockPortTag;\n const identity = yield* IdentityPortTag;\n return new InMemorySmartAccountAdapter({\n clock,\n identity,\n ...(deps.failures === undefined ? {} : { failures: deps.failures }),\n });\n }),\n );\n}\n\nfunction fail(operation: string, error: CapxulError): Effect.Effect<never, SmartAccountError> {\n return Effect.fail(smartAccountErrorFromCapxul(operation, error));\n}\n\nfunction cloneSmartAccount(account: SmartAccount): SmartAccount {\n return {\n authUserId: account.authUserId,\n signerAddress: account.signerAddress,\n smartAccountAddress: account.smartAccountAddress,\n chainId: account.chainId,\n deployedAt: account.deployedAt,\n claimedAt: account.claimedAt,\n createdAt: account.createdAt,\n };\n}\n\nfunction cloneSmartAccountOrNull(account: SmartAccount | null): SmartAccount | null {\n return account === null ? null : cloneSmartAccount(account);\n}\n","import { Errors, type CapxulError } from \"@capxul/config\";\nimport type { AccountId, Money, SubAccount } from \"@capxul/types\";\nimport { toCurrencyCode, toEpochMs, toSubAccountId } from \"@capxul/types\";\nimport { Effect, Layer } from \"effect\";\n\nimport { fromWei } from \"../../domain/money/from-wei\";\nimport { toWei } from \"../../domain/money/to-wei\";\nimport type {\n CreateSubAccountInput,\n RenameSubAccountInput,\n SubAccountError,\n SubAccountIdInput,\n SubAccountPort,\n TransferInput,\n TransferResult,\n} from \"../../ports/sub-account\";\nimport { subAccountErrorFromCapxul, SubAccountPortTag } from \"../../ports/sub-account\";\n\nexport class InMemorySubAccountAdapter implements SubAccountPort {\n readonly #rows = new Map<string, SubAccount>();\n readonly #failures: { readonly create?: CapxulError };\n // The Safe's on-chain `balanceOf` as a base-unit integer string. `transfer`\n // validates a `main`-source against `balanceOfRaw − Σ(sub-account balances)`\n // and recomputes `available` against it — mirroring the backend action which\n // reads the real chain. Defaults to \"0\" (an unfunded Safe).\n readonly #balanceOfRaw: string;\n // Monotonic id counter — never derived from #rows.size, which shrinks on\n // delete and would let a later create collide with an existing id.\n #created: number;\n\n constructor(\n deps: {\n readonly failures?: { readonly create?: CapxulError };\n readonly seed?: readonly SubAccount[];\n readonly balanceOfRaw?: string;\n } = {},\n ) {\n this.#failures = deps.failures ?? {};\n this.#balanceOfRaw = deps.balanceOfRaw ?? \"0\";\n for (const row of deps.seed ?? []) {\n this.#rows.set(row.id as string, row);\n }\n this.#created = this.#rows.size;\n }\n\n create(input: CreateSubAccountInput): Effect.Effect<SubAccount, SubAccountError> {\n const failure = this.#failures.create;\n if (failure !== undefined) {\n return Effect.fail(subAccountErrorFromCapxul(\"create\", failure));\n }\n this.#created += 1;\n const id = toSubAccountId(`subaccount_test${String(this.#created)}`);\n const row: SubAccount = {\n id,\n accountId: input.accountId,\n name: input.name,\n balance: { currency: toCurrencyCode(\"USD\"), value: \"0\", decimals: 6 },\n createdAt: toEpochMs(Date.now()),\n };\n this.#rows.set(id as string, row);\n return Effect.succeed(row);\n }\n\n get(input: SubAccountIdInput): Effect.Effect<SubAccount | null, SubAccountError> {\n return Effect.succeed(this.#rows.get(input.subAccountId as string) ?? null);\n }\n\n list(input: {\n readonly accountId: AccountId;\n }): Effect.Effect<readonly SubAccount[], SubAccountError> {\n const accountId = input.accountId as string;\n return Effect.succeed(\n [...this.#rows.values()].filter((row) => (row.accountId as string) === accountId),\n );\n }\n\n rename(input: RenameSubAccountInput): Effect.Effect<SubAccount, SubAccountError> {\n const existing = this.#rows.get(input.subAccountId as string);\n if (existing === undefined) {\n return Effect.fail(\n subAccountErrorFromCapxul(\"rename\", Errors.accountNotFound(input.subAccountId as string)),\n );\n }\n const next = { ...existing, name: input.name };\n this.#rows.set(input.subAccountId as string, next);\n return Effect.succeed(next);\n }\n\n delete(input: SubAccountIdInput): Effect.Effect<void, SubAccountError> {\n const existing = this.#rows.get(input.subAccountId as string);\n if (existing === undefined) {\n return Effect.fail(\n subAccountErrorFromCapxul(\"delete\", Errors.accountNotFound(input.subAccountId as string)),\n );\n }\n // Representation-agnostic zero check: Money.value is a major-unit decimal\n // string (\"0\", \"0.0\", \"0.00\" all denote an empty bucket). Mirrors the\n // backend `remove` invariant and the CLI money.ts zero check.\n if (Number(existing.balance.value) !== 0) {\n return Effect.fail(\n subAccountErrorFromCapxul(\n \"delete\",\n Errors.invalidInput(\"subAccountId\", \"delete requires zero balance\"),\n ),\n );\n }\n this.#rows.delete(input.subAccountId as string);\n return Effect.succeed(undefined);\n }\n\n transfer(input: TransferInput): Effect.Effect<TransferResult, SubAccountError> {\n const decimals = input.amount.decimals;\n const invalid = (\n field: string,\n reason: string,\n ): Effect.Effect<TransferResult, SubAccountError> =>\n Effect.fail(subAccountErrorFromCapxul(\"transfer\", Errors.invalidInput(field, reason)));\n\n // Brand the amount into base units. `toWei`/`parseUnits` throws on a\n // malformed decimal string; catch it as INVALID_INPUT rather than a defect.\n let rawAmount: bigint;\n try {\n rawAmount = BigInt(toWei(input.amount));\n } catch {\n return invalid(\"amount\", \"must be a decimal money string\");\n }\n if (rawAmount <= 0n) return invalid(\"amount\", \"must be positive\");\n if (input.from === input.to) return invalid(\"transfer\", \"from and to must differ\");\n\n // Resolve endpoints — an unknown sub-account id is INVALID_INPUT.\n const fromRow =\n input.from === \"main\" ? null : (this.#rows.get(input.from as string) ?? \"missing\");\n if (fromRow === \"missing\") return invalid(\"subAccountId\", \"unknown sub-account\");\n const toRow = input.to === \"main\" ? null : (this.#rows.get(input.to as string) ?? \"missing\");\n if (toRow === \"missing\") return invalid(\"subAccountId\", \"unknown sub-account\");\n\n const safeRaw = BigInt(this.#balanceOfRaw);\n const subTotalRaw = this.#sumSubAccountRaws(decimals);\n\n // Validate source funds.\n if (input.from === \"main\") {\n const availableRaw = safeRaw - subTotalRaw;\n if (availableRaw < rawAmount) {\n return Effect.fail(\n subAccountErrorFromCapxul(\n \"transfer\",\n Errors.insufficientBalance(\"main\", maxRaw(availableRaw), rawAmount.toString(10)),\n ),\n );\n }\n } else if (fromRow !== null) {\n const fromRaw = BigInt(toWei({ value: fromRow.balance.value, decimals }));\n if (fromRaw < rawAmount) {\n return Effect.fail(\n subAccountErrorFromCapxul(\n \"transfer\",\n Errors.insufficientBalance(fromRow.name, fromRaw.toString(10), rawAmount.toString(10)),\n ),\n );\n }\n }\n\n // Apply the patch (main is implicit — never a row).\n let nextFrom: SubAccount | null = null;\n let nextTo: SubAccount | null = null;\n if (fromRow !== null) {\n const fromRaw = BigInt(toWei({ value: fromRow.balance.value, decimals }));\n nextFrom = this.#patchBalance(fromRow, (fromRaw - rawAmount).toString(10), decimals);\n }\n if (toRow !== null) {\n const toRaw = BigInt(toWei({ value: toRow.balance.value, decimals }));\n nextTo = this.#patchBalance(toRow, (toRaw + rawAmount).toString(10), decimals);\n }\n\n const newAvailableRaw = safeRaw - this.#sumSubAccountRaws(decimals);\n const available = fromWei(maxRaw(newAvailableRaw), decimals, input.amount.currency as string);\n return Effect.succeed({ available, from: nextFrom, to: nextTo });\n }\n\n #sumSubAccountRaws(decimals: number): bigint {\n let total = 0n;\n for (const row of this.#rows.values()) {\n total += BigInt(toWei({ value: row.balance.value, decimals }));\n }\n return total;\n }\n\n #patchBalance(row: SubAccount, rawBalance: string, decimals: number): SubAccount {\n const balance: Money = fromWei(rawBalance, decimals, row.balance.currency as string);\n const next: SubAccount = { ...row, balance };\n this.#rows.set(row.id as string, next);\n return next;\n }\n}\n\n/** Floor a (possibly negative) base-unit raw to a non-negative base-10 string. */\nfunction maxRaw(raw: bigint): string {\n return (raw < 0n ? 0n : raw).toString(10);\n}\n\nexport function InMemorySubAccountLayer(\n deps: { readonly failures?: { readonly create?: CapxulError } } = {},\n): Layer.Layer<SubAccountPortTag, SubAccountError, never> {\n return Layer.succeed(SubAccountPortTag, new InMemorySubAccountAdapter(deps));\n}\n","import { Effect, Layer } from \"effect\";\n\nimport {\n redactTelemetryEvent,\n TelemetryPortTag,\n type TelemetryEvent,\n type TelemetryGroupInput,\n type TelemetryIdentifyInput,\n type TelemetryPort,\n type TelemetryProps,\n} from \"../../ports/telemetry\";\n\nexport type RecordingTelemetryOperation =\n | { readonly type: \"emit\"; readonly event: TelemetryEvent }\n | { readonly type: \"identify\"; readonly input: TelemetryIdentifyInput }\n | { readonly type: \"group\"; readonly input: TelemetryGroupInput }\n | { readonly type: \"reset\" };\n\nexport interface RecordingTelemetryAdapterOptions {\n readonly rawMode?: boolean;\n}\n\nexport class RecordingTelemetryAdapter implements TelemetryPort {\n readonly #events: TelemetryEvent[] = [];\n readonly #operations: RecordingTelemetryOperation[] = [];\n readonly #rawMode: boolean;\n\n constructor(options: RecordingTelemetryAdapterOptions = {}) {\n this.#rawMode = options.rawMode === true;\n }\n\n get events(): readonly TelemetryEvent[] {\n return this.#events.map(cloneEvent);\n }\n\n get operations(): readonly RecordingTelemetryOperation[] {\n return this.#operations.map(cloneOperation);\n }\n\n emit(event: TelemetryEvent): Effect.Effect<void, never, never> {\n return Effect.sync(() => {\n const recorded = redactTelemetryEvent(event, { rawMode: this.#rawMode });\n this.#events.push(recorded);\n this.#operations.push({ type: \"emit\", event: cloneEvent(recorded) });\n });\n }\n\n identify(input: TelemetryIdentifyInput): Effect.Effect<void, never, never> {\n return Effect.sync(() => {\n this.#operations.push({\n type: \"identify\",\n input: cloneIdentifyInput(input),\n });\n });\n }\n\n group(input: TelemetryGroupInput): Effect.Effect<void, never, never> {\n return Effect.sync(() => {\n this.#operations.push({\n type: \"group\",\n input: cloneGroupInput(input),\n });\n });\n }\n\n reset(): Effect.Effect<void, never, never> {\n return Effect.sync(() => {\n this.#operations.push({ type: \"reset\" });\n });\n }\n\n clear(): void {\n this.#events.length = 0;\n this.#operations.length = 0;\n }\n}\n\nexport function RecordingTelemetryLayer(\n adapter: RecordingTelemetryAdapter = new RecordingTelemetryAdapter(),\n): Layer.Layer<TelemetryPortTag, never, never> {\n return Layer.succeed(TelemetryPortTag, adapter);\n}\n\nfunction cloneEvent(event: TelemetryEvent): TelemetryEvent {\n return event.props === undefined\n ? { name: event.name }\n : { name: event.name, props: cloneProps(event.props) };\n}\n\nfunction cloneOperation(operation: RecordingTelemetryOperation): RecordingTelemetryOperation {\n switch (operation.type) {\n case \"emit\":\n return { type: \"emit\", event: cloneEvent(operation.event) };\n case \"identify\":\n return { type: \"identify\", input: cloneIdentifyInput(operation.input) };\n case \"group\":\n return { type: \"group\", input: cloneGroupInput(operation.input) };\n case \"reset\":\n return { type: \"reset\" };\n }\n}\n\nfunction cloneIdentifyInput(input: TelemetryIdentifyInput): TelemetryIdentifyInput {\n return {\n distinctId: input.distinctId,\n ...(input.anonDistinctId === undefined ? {} : { anonDistinctId: input.anonDistinctId }),\n ...(input.traits === undefined ? {} : { traits: cloneProps(input.traits) }),\n ...(input.properties === undefined ? {} : { properties: cloneProps(input.properties) }),\n };\n}\n\nfunction cloneGroupInput(input: TelemetryGroupInput): TelemetryGroupInput {\n return input.properties === undefined\n ? { groupType: input.groupType, groupKey: input.groupKey }\n : {\n groupType: input.groupType,\n groupKey: input.groupKey,\n properties: cloneProps(input.properties),\n };\n}\n\nfunction cloneProps(props: TelemetryProps): TelemetryProps {\n const cloned: TelemetryProps = {};\n for (const [key, value] of Object.entries(props)) {\n cloned[key] = cloneTelemetryValue(value);\n }\n return cloned;\n}\n\nfunction cloneTelemetryValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(cloneTelemetryValue);\n if (value === null || typeof value !== \"object\") return value;\n if (Object.getPrototypeOf(value) !== Object.prototype) return value;\n const cloned: Record<string, unknown> = {};\n for (const [key, nested] of Object.entries(value)) {\n cloned[key] = cloneTelemetryValue(nested);\n }\n return cloned;\n}\n","import { Effect } from \"effect\";\n\nimport {\n toAllowedOrigin,\n toAppId,\n toAuthUserId,\n toChainId,\n toCountryCode,\n toDurationMs,\n toEmail,\n toEpochMs,\n toPublishableKey,\n toSessionToken,\n} from \"@capxul/types\";\n\nimport { authClientPortFromPromiseAdapter } from \"../adapters/auth-client/effect-port\";\nimport { InMemoryAuthCacheAdapter } from \"../adapters/auth-cache/InMemoryAuthCacheAdapter\";\nimport type { IdentityTransition } from \"../domain/machine/shell\";\nimport type { FlowPorts } from \"../flows/types\";\nimport type { BootstrapResolution } from \"../ports/bootstrap\";\nimport type {\n TelemetryEvent,\n TelemetryGroupInput,\n TelemetryIdentifyInput,\n} from \"../ports/telemetry\";\nimport { assembleCapxulClient, type CapxulClient } from \"../surface/create-capxul-client\";\nimport { InMemoryAccountReadAdapter } from \"./account/InMemoryAccountReadAdapter\";\nimport { InMemoryAuthClientAdapter } from \"./auth-client/InMemoryAuthClientAdapter\";\nimport { BootstrapStubAdapter } from \"./bootstrap/BootstrapStubAdapter\";\nimport { ManualClockAdapter } from \"./clock/ManualClockAdapter\";\nimport { ConvexCallStubAdapter } from \"./convex-call/ConvexCallStubAdapter\";\nimport { InMemoryIdentityAdapter } from \"./identity/InMemoryIdentityAdapter\";\nimport { InMemorySmartAccountAdapter } from \"./smart-account/InMemorySmartAccountAdapter\";\nimport { InMemorySubAccountAdapter } from \"./sub-account/InMemorySubAccountAdapter\";\nimport {\n RecordingTelemetryAdapter,\n type RecordingTelemetryOperation,\n} from \"./telemetry/RecordingTelemetryAdapter\";\n\nconst TEST_BOOTSTRAP: BootstrapResolution = {\n applicationId: toAppId(\"app_01HX0000000000000000000000\"),\n chainId: toChainId(84_532),\n sessionToken: toSessionToken(\"bootstrap-test-token\"),\n issuedAt: toEpochMs(0),\n expiresIn: toDurationMs(60_000),\n authBaseUrl: \"https://auth.example.test\",\n convexUrl: \"https://convex.example.test\",\n siteBaseUrl: \"https://example.test\",\n openfortPublishableKey: \"pk_test_openfort_fixture\",\n shieldPublishableKey: \"shield_pk_test_fixture\",\n};\n\nexport interface CreateCapxulTestClientOptions {\n readonly requirement?: \"none\" | \"counterfactual\" | \"deployed\";\n}\n\nexport interface SeedTestIdentityInput {\n readonly authUserId: string;\n readonly email: string;\n readonly displayName?: string;\n readonly country?: string;\n}\n\nexport interface CapxulTestClient {\n readonly client: CapxulClient;\n readonly clock: CapxulTestClock;\n readonly observation: CapxulTestObservation;\n readonly transitions: readonly IdentityTransition[];\n readonly observations: readonly RecordingTelemetryOperation[];\n readonly peekOtp: (email: string) => string | undefined;\n readonly seedIdentity: (input: SeedTestIdentityInput) => Promise<void>;\n readonly close: () => Promise<void>;\n}\n\nexport interface CapxulTestClock {\n readonly advance: (ms: number) => Promise<void>;\n}\n\nexport interface CapxulTestObservation {\n readonly emit: (event: TelemetryEvent) => Promise<void>;\n readonly identify: (input: TelemetryIdentifyInput) => Promise<void>;\n readonly group: (input: TelemetryGroupInput) => Promise<void>;\n readonly reset: () => Promise<void>;\n}\n\n/**\n * Assemble the real public client over deterministic in-memory ports.\n * Unconfigured backend calls fail locally; no adapter owns a network exit.\n */\nexport function createCapxulTestClient(\n options: CreateCapxulTestClientOptions = {},\n): CapxulTestClient {\n const clock = new ManualClockAdapter({});\n const authCache = new InMemoryAuthCacheAdapter();\n const authClient = new InMemoryAuthClientAdapter({ authCache, clock });\n const identity = new InMemoryIdentityAdapter({ clock });\n const telemetry = new RecordingTelemetryAdapter();\n const ports: FlowPorts = {\n authClient: authClientPortFromPromiseAdapter(authClient),\n authCache,\n identity,\n smartAccount: new InMemorySmartAccountAdapter({ clock, identity }),\n accountRead: new InMemoryAccountReadAdapter({ rawBalance: \"0\" }),\n subAccount: new InMemorySubAccountAdapter(),\n bootstrap: new BootstrapStubAdapter({\n script: {\n resolutions: new Map([\n [\n `${toPublishableKey(\"cap_pk_test_0123456789ABCDEFGHJKMNPQRSTVWXYZ\")}::${toAllowedOrigin(\"https://example.test\")}`,\n TEST_BOOTSTRAP,\n ],\n ]),\n },\n }),\n clock,\n telemetry,\n convexCall: new ConvexCallStubAdapter({ script: {} }),\n };\n const client = assembleCapxulClient({\n ports,\n bootstrap: TEST_BOOTSTRAP,\n authCache,\n requirement: options.requirement ?? \"none\",\n });\n const transitions: IdentityTransition[] = [];\n const unsubscribe = client._internal.identity.subscribeTransitions((record) => {\n transitions.push(record);\n });\n let closed = false;\n const clockControl: CapxulTestClock = Object.freeze({\n advance: (ms: number) => clock.advance(ms),\n });\n\n return {\n client,\n clock: clockControl,\n observation: {\n emit: (event) => Effect.runPromise(telemetry.emit(event)),\n identify: (input) => Effect.runPromise(telemetry.identify(input)),\n group: (input) => Effect.runPromise(telemetry.group(input)),\n reset: () => Effect.runPromise(telemetry.reset()),\n },\n get transitions() {\n return transitions.slice();\n },\n get observations() {\n return telemetry.operations;\n },\n peekOtp: (email) => authClient.peekOtpForTesting(toEmail(email)),\n seedIdentity: async (input) => {\n const authUserId = toAuthUserId(input.authUserId);\n const email = toEmail(input.email);\n await Effect.runPromise(\n identity.create({\n authUserId,\n email,\n ...(input.displayName === undefined ? {} : { displayName: input.displayName }),\n ...(input.country === undefined ? {} : { country: toCountryCode(input.country) }),\n }),\n );\n authClient.bindAuthUserIdForTesting(email, authUserId);\n },\n close: async () => {\n if (closed) return;\n closed = true;\n unsubscribe();\n await client._internal.close?.();\n },\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capxul/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"package.json",
|
|
@@ -16,37 +16,34 @@
|
|
|
16
16
|
"types": "./dist/node/index.d.mts",
|
|
17
17
|
"import": "./dist/node/index.mjs"
|
|
18
18
|
},
|
|
19
|
-
"./
|
|
20
|
-
"types": "./dist/
|
|
21
|
-
"import": "./dist/
|
|
19
|
+
"./testing": {
|
|
20
|
+
"types": "./dist/testing/index.d.mts",
|
|
21
|
+
"import": "./dist/testing/index.mjs"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|
|
25
|
-
"access": "public"
|
|
26
|
-
"tag": "alpha"
|
|
25
|
+
"access": "public"
|
|
27
26
|
},
|
|
28
27
|
"dependencies": {
|
|
29
|
-
"@effect/
|
|
30
|
-
"@effect/platform": "^0.96.1",
|
|
31
|
-
"@effect/platform-node": "^0.106.0",
|
|
32
|
-
"@effect/schema": "^0.75.5",
|
|
28
|
+
"@effect/platform-node": "4.0.0-beta.105",
|
|
33
29
|
"@openfort/openfort-js": "^1.3.6",
|
|
34
30
|
"convex": "^1.39.1",
|
|
35
|
-
"effect": "
|
|
36
|
-
"viem": "^2.
|
|
31
|
+
"effect": "4.0.0-beta.105",
|
|
32
|
+
"viem": "^2.53.1"
|
|
37
33
|
},
|
|
38
34
|
"devDependencies": {
|
|
39
|
-
"@effect/vitest": "
|
|
35
|
+
"@effect/vitest": "4.0.0-beta.105",
|
|
40
36
|
"@vitest/coverage-v8": "4.1.7",
|
|
41
37
|
"fast-check": "^3.23.2",
|
|
42
38
|
"permissionless": "0.3.4",
|
|
39
|
+
"posthog-js": "^1.399.2",
|
|
43
40
|
"typescript": "5.9.2",
|
|
44
41
|
"vitest": "npm:@voidzero-dev/vite-plus-test@0.1.23",
|
|
45
|
-
"@capxul/
|
|
46
|
-
"@capxul/observability": "
|
|
47
|
-
"@capxul/
|
|
48
|
-
"@capxul/types": "0.1.0
|
|
49
|
-
"@capxul/
|
|
42
|
+
"@capxul/wire": "0.1.0",
|
|
43
|
+
"@capxul/observability": "1.2.0",
|
|
44
|
+
"@capxul/config": "0.1.0",
|
|
45
|
+
"@capxul/types": "0.1.0",
|
|
46
|
+
"@capxul/errors": "0.0.1"
|
|
50
47
|
},
|
|
51
48
|
"_permissionlessPinReason": "permissionless.toSafeSmartAccount is pinned to 0.3.4 for live Safe deployment E2E. Counterfactual address fixtures captured 2026-05-17 in packages/backend/convex/_shared/__tests__/counterfactual.test.ts and packages/config/tests/safe.test.ts must be re-verified before upgrading.",
|
|
52
49
|
"scripts": {
|
|
@@ -56,7 +53,9 @@
|
|
|
56
53
|
"_vp-tasks-allowed": "vp-allowed: `test` + `test:coverage` are vp tasks in vite.config.ts so vitest self-writes don't bust cache (#205). `test:coverage:full` keeps the script form because it composes 5 reporters at invocation time.",
|
|
57
54
|
"test:coverage:full": "CAPXUL_FAST_CHECK_NUM_RUNS=50 vp test run --coverage --coverage.reporter=text --coverage.reporter=json-summary --coverage.reporter=json --coverage.reporter=html --coverage.reporter=clover",
|
|
58
55
|
"test:e2e": "vp test run --config vitest.e2e.config.ts",
|
|
56
|
+
"proofs:live": "vp exec bash ../../scripts/prove-organization-core-live.sh",
|
|
59
57
|
"proof:openfort-embedded-deploy": "vp test run --config vitest.e2e.config.ts e2e/openfort-embedded-deploy.live.ts",
|
|
58
|
+
"proof:observation-linkage": "CAPXUL_OBSERVATION_LINKAGE_ONLY=1 vp dlx tsx e2e/org-domain-sdk-live.ts",
|
|
60
59
|
"org:domain-live": "vp dlx tsx e2e/org-domain-sdk-live.ts"
|
|
61
60
|
}
|
|
62
61
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryAuthCacheAdapter-v5W-XB5M.mjs","names":[],"sources":["../../errors/src/errors.ts","../../errors/src/convex-error-decoding.ts","../../types/src/index.ts","../src/ports/auth-cache.ts","../src/adapters/auth-cache/serialization.ts","../src/adapters/auth-cache/BrowserAuthCacheAdapter.ts","../src/adapters/auth-cache/InMemoryAuthCacheAdapter.ts"],"sourcesContent":["// The canonical error-code catalog as a runtime constant. `CapxulErrorCode`\n// is derived from it so the type and any runtime check that needs to\n// enumerate codes (e.g. the convex-error codec's `KNOWN_CODES`) share a\n// single source of truth — a TypeScript union alone can't be introspected\n// at runtime, which previously forced a hand-maintained duplicate.\nexport const CAPXUL_ERROR_CODES = [\n \"NOT_AUTHENTICATED\",\n \"EMAIL_DELIVERY_FAILED\",\n \"PROFILE_NOT_FOUND\",\n \"SMART_ACCOUNT_MISSING\",\n \"PLAYER_NOT_FOUND\",\n \"ACCOUNT_NOT_FOUND\",\n \"PROVIDER_ERROR\",\n \"INVALID_INPUT\",\n \"ENV_MISSING\",\n \"NOT_IMPLEMENTED\",\n \"VERIFICATION_REQUIRED\",\n \"INSUFFICIENT_BALANCE\",\n \"INVALID_RECIPIENT\",\n \"ROLE_PERMISSION_DENIED\",\n \"TRANSACTION_FAILED\",\n \"RATE_LIMITED\",\n \"NETWORK_ERROR\",\n \"UNKNOWN\",\n \"OTP_EXPIRED\",\n \"SIGNER_REJECTED\",\n \"CANCELLED\",\n \"WRONG_STATE\",\n] as const;\n\nexport type CapxulErrorCode = (typeof CAPXUL_ERROR_CODES)[number];\n\n/**\n * Why an auth/provider call failed — a flat CAUSE enum. The *where* (which\n * OpenFort operation) stays in the separate `operation` detail field; this\n * names the root cause so a single `$exception` can be triaged without\n * parsing the message. Five members, no free strings:\n *\n * - `auth-origin-mismatch`: OTP cookies live on `localhost:PORT` but OpenFort\n * hits the Convex host → no session reaches the provider.\n * - `stale-openfort-cache`: an old `userId` in scoped storage makes the SDK\n * skip re-auth → 401 on `v2/accounts`.\n * - `app-env-allowlist`: missing `VITE_CAPXUL_CONVEX_SITE_URL` / the origin is\n * not allowlisted → 401.\n * - `no-secure-context`: sandboxed/headless browser with no Web Crypto, so\n * `getAddress`/`configure` can never produce an address. Previously vanished\n * into `unknown`; the signer's secure-context probe now names it.\n * - `unknown`: catch-all when no cause could be determined.\n */\nexport type FailureMode =\n | \"auth-origin-mismatch\"\n | \"stale-openfort-cache\"\n | \"app-env-allowlist\"\n | \"no-secure-context\"\n | \"unknown\";\n\nexport type CapxulErrorDetails = Record<string, unknown>;\n\nexport type SignerSource = \"openfort-embedded\" | \"injected-eip1193\" | \"local-private-key\";\n\nexport type VerificationRequiredDetails =\n | { readonly requiredTier: number }\n | { readonly rail: string; readonly currentKind: string };\n\nexport type SerializedCapxulError = {\n readonly code: CapxulErrorCode;\n readonly message: string;\n readonly details?: CapxulErrorDetails;\n readonly correlationId?: string;\n readonly layer?: string;\n};\n\nexport type CapxulErrorOptions = {\n readonly cause?: unknown;\n readonly details?: CapxulErrorDetails;\n readonly correlationId?: string;\n readonly layer?: string;\n};\n\nexport class CapxulError extends Error {\n readonly code: CapxulErrorCode;\n readonly details?: CapxulErrorDetails;\n readonly correlationId?: string;\n readonly layer?: string;\n\n constructor(code: CapxulErrorCode, message: string, options: CapxulErrorOptions = {}) {\n super(message, \"cause\" in options ? { cause: options.cause } : undefined);\n this.name = \"CapxulError\";\n this.code = code;\n if (options.details !== undefined) {\n this.details = options.details;\n }\n if (options.correlationId !== undefined) {\n this.correlationId = options.correlationId;\n }\n if (options.layer !== undefined) {\n this.layer = options.layer;\n }\n }\n}\n\nexport function isCapxulError(value: unknown): value is CapxulError {\n return value instanceof CapxulError;\n}\n\nexport function serializeCapxulError(error: CapxulError): SerializedCapxulError {\n return compactSerialized({\n code: error.code,\n message: error.message,\n details: error.details,\n correlationId: error.correlationId,\n layer: error.layer,\n });\n}\n\nexport function deserializeCapxulError(serialized: SerializedCapxulError): CapxulError {\n return new CapxulError(\n serialized.code,\n serialized.message,\n compactErrorOptions({\n details: serialized.details,\n correlationId: serialized.correlationId,\n layer: serialized.layer,\n }),\n );\n}\n\nfunction compactSerialized(serialized: {\n readonly code: CapxulErrorCode;\n readonly message: string;\n readonly details: CapxulErrorDetails | undefined;\n readonly correlationId: string | undefined;\n readonly layer: string | undefined;\n}): SerializedCapxulError {\n const result: {\n code: CapxulErrorCode;\n message: string;\n details?: CapxulErrorDetails;\n correlationId?: string;\n layer?: string;\n } = {\n code: serialized.code,\n message: serialized.message,\n };\n\n if (serialized.details !== undefined) {\n result.details = serialized.details;\n }\n if (serialized.correlationId !== undefined) {\n result.correlationId = serialized.correlationId;\n }\n if (serialized.layer !== undefined) {\n result.layer = serialized.layer;\n }\n\n return result;\n}\n\nfunction compactErrorOptions(options: {\n readonly cause?: unknown;\n readonly details: CapxulErrorDetails | undefined;\n readonly correlationId: string | undefined;\n readonly layer: string | undefined;\n}): CapxulErrorOptions {\n const result: {\n cause?: unknown;\n details?: CapxulErrorDetails;\n correlationId?: string;\n layer?: string;\n } = {};\n\n if (\"cause\" in options) {\n result.cause = options.cause;\n }\n if (options.details !== undefined) {\n result.details = options.details;\n }\n if (options.correlationId !== undefined) {\n result.correlationId = options.correlationId;\n }\n if (options.layer !== undefined) {\n result.layer = options.layer;\n }\n\n return result;\n}\n\nexport const Errors = {\n notAuthenticated: (message?: string, opts?: { readonly failure_mode?: FailureMode }) =>\n new CapxulError(\n \"NOT_AUTHENTICATED\",\n message ?? \"Not authenticated\",\n opts?.failure_mode ? { details: { failure_mode: opts.failure_mode } } : undefined,\n ),\n emailDeliveryFailed: (detail: string) =>\n new CapxulError(\"EMAIL_DELIVERY_FAILED\", \"Failed to send email\", {\n details: { detail },\n }),\n\n profileNotFound: (authUserId: string) =>\n new CapxulError(\"PROFILE_NOT_FOUND\", `Profile not found for user ${authUserId}`, {\n details: { authUserId },\n }),\n\n smartAccountMissing: (authUserId: string) =>\n new CapxulError(\"SMART_ACCOUNT_MISSING\", \"Smart account not provisioned\", {\n details: { authUserId },\n }),\n\n playerNotFound: (playerId?: string) =>\n new CapxulError(\n \"PLAYER_NOT_FOUND\",\n playerId ? `Openfort player ${playerId} not found` : \"Openfort player not found\",\n playerId === undefined ? undefined : { details: { playerId } },\n ),\n\n accountNotFound: (accountId?: string) =>\n new CapxulError(\n \"ACCOUNT_NOT_FOUND\",\n accountId ? `Openfort account ${accountId} not found` : \"Openfort account not found\",\n accountId === undefined ? undefined : { details: { accountId } },\n ),\n\n providerError: (\n provider: string,\n operation: string,\n cause: unknown,\n opts?: { readonly failure_mode?: FailureMode },\n ) => {\n const details: Record<string, unknown> = { provider, operation };\n if (opts?.failure_mode) {\n details.failure_mode = opts.failure_mode;\n }\n return new CapxulError(\"PROVIDER_ERROR\", `Provider error: ${provider} ${operation}`, {\n cause,\n details,\n });\n },\n\n invalidInput: (field: string, reason: string) =>\n new CapxulError(\"INVALID_INPUT\", `Invalid ${field}: ${reason}`, {\n details: { field, reason },\n }),\n\n envMissing: (name: string) =>\n new CapxulError(\"ENV_MISSING\", `Environment variable ${name} not configured`, {\n details: { name },\n }),\n\n notImplemented: (domain: string, method: string) =>\n new CapxulError(\n \"NOT_IMPLEMENTED\",\n `${domain}.${method} is not yet implemented. This feature is planned for a future release.`,\n { details: { domain, method } },\n ),\n\n /**\n * Sibling factory to {@link Errors.providerError} for the per-state timeout\n * path in flows (initially ProvisioningFlow's mint_openfort / deploy_safe /\n * register_indexer `after:` timers). Same `PROVIDER_ERROR` code as\n * `providerError`, plus a `details.reason: \"timeout\"` discriminator so\n * downstream observers can distinguish failure modes without parsing the\n * message string. The redacted message names the timeout budget; the\n * native `cause` carries the same information for `reportError` fidelity.\n */\n providerTimeout: (provider: string, operation: string, timeoutMs: number) =>\n new CapxulError(\n \"PROVIDER_ERROR\",\n `Provider error: ${provider} ${operation} (timeout exceeded ${timeoutMs}ms)`,\n {\n details: { provider, operation, reason: \"timeout\" },\n cause: new Error(`timeout: ${operation} exceeded ${timeoutMs}ms`),\n },\n ),\n\n verificationRequired: (details: VerificationRequiredDetails) => {\n const message =\n \"rail\" in details\n ? `Verification is required before ${details.rail} can use ${details.currentKind}.`\n : `Verification tier ${details.requiredTier} is required.`;\n\n return new CapxulError(\"VERIFICATION_REQUIRED\", message, {\n details,\n });\n },\n\n insufficientBalance: (asset: string, available: string, required: string) =>\n new CapxulError(\"INSUFFICIENT_BALANCE\", `Insufficient ${asset} balance`, {\n details: { asset, available, required },\n }),\n\n invalidRecipient: (reason: string) =>\n new CapxulError(\"INVALID_RECIPIENT\", `Invalid recipient: ${reason}`, {\n details: { reason },\n }),\n\n /**\n * The org Zodiac Roles modifier REFUSED the spend on-chain (G4 · #547): the\n * member's role condition (per-tx cap, per-day allowance, allowed recipient,\n * or membership) was violated, so `execTransactionWithRole` reverted. This is\n * a PERMISSION denial — explicitly NOT an `INSUFFICIENT_BALANCE` (the treasury\n * held the funds; the role's authority is what bound). `reason` discriminates\n * the violated condition (`over_cap` / `daily_cap` / `not_member` /\n * `disallowed_recipient` / `condition_violation`); leak-safe — no on-chain\n * identifiers ever enter the details.\n */\n rolePermissionDenied: (details: {\n readonly reason:\n | \"over_cap\"\n | \"daily_cap\"\n | \"not_member\"\n | \"disallowed_recipient\"\n | \"condition_violation\";\n readonly operation?: string;\n }) =>\n new CapxulError(\n \"ROLE_PERMISSION_DENIED\",\n `Org role denied this spend on-chain (${details.reason}).`,\n {\n details:\n details.operation === undefined\n ? { reason: details.reason }\n : { reason: details.reason, operation: details.operation },\n },\n ),\n\n /**\n * A transaction (or sponsored UserOp) failed. `details.reason` discriminates\n * the failure mode for callers that must distinguish a CONFIRMED on-chain\n * revert (`\"onchain_revert\"` — the op executed and reverted, e.g. a Zodiac\n * Roles condition violation) from an inconclusive infra failure. A confirmed\n * revert is the ONLY mode the org spend port may map to a roles denial.\n */\n transactionFailed: (operation: string, cause?: unknown, extra?: { readonly reason?: string }) =>\n new CapxulError(\"TRANSACTION_FAILED\", `Transaction failed: ${operation}`, {\n cause,\n details: extra?.reason === undefined ? { operation } : { operation, reason: extra.reason },\n }),\n\n rateLimited: (details?: { readonly retryAfterMs?: number; readonly resource?: string }) =>\n new CapxulError(\n \"RATE_LIMITED\",\n \"Rate limit exceeded\",\n details === undefined ? undefined : { details: { ...details } },\n ),\n\n networkError: (operation: string, cause?: unknown) =>\n new CapxulError(\"NETWORK_ERROR\", `Network error during ${operation}`, {\n cause,\n details: { operation },\n }),\n\n unknown: (cause?: unknown) => new CapxulError(\"UNKNOWN\", \"Unknown error\", { cause }),\n\n otpExpired: (details?: { readonly email?: string; readonly expiredAt?: number }) =>\n new CapxulError(\n \"OTP_EXPIRED\",\n \"Verification code has expired. Request a new one.\",\n details === undefined ? undefined : { details: { ...details } },\n ),\n\n signerRejected: (details: {\n readonly source: SignerSource;\n readonly reason?: string;\n readonly cause?: unknown;\n }) =>\n new CapxulError(\"SIGNER_REJECTED\", \"Signer rejected the request.\", {\n cause: details.cause,\n details:\n details.reason === undefined\n ? { source: details.source }\n : { source: details.source, reason: details.reason },\n }),\n\n cancelled: (details?: { readonly operation?: string; readonly reason?: string }) =>\n new CapxulError(\n \"CANCELLED\",\n \"Operation was cancelled.\",\n details === undefined ? undefined : { details: { ...details } },\n ),\n\n /**\n * Method called from a flow state where its precondition fails (TA16). The\n * SDK's method API short-circuits with this error before driving the\n * internal state machine. `currentState` is the Effect-machine snapshot\n * tag (stringified — substrate is `@effect/experimental/Machine` per\n * `docs/canon/decisions/state-machine-substrate.md`); `validStates`\n * enumerates the states the method accepts.\n */\n wrongState: (details: {\n readonly method: string;\n readonly currentState: string;\n readonly validStates: readonly string[];\n }) =>\n new CapxulError(\n \"WRONG_STATE\",\n `${details.method} called from state '${details.currentState}'; valid states: ${details.validStates.join(\", \")}`,\n { details: { ...details, validStates: [...details.validStates] } },\n ),\n} as const;\n","// Shared `decodeConvexError` helper (TA5) — used by both the SDK's\n// `ConvexCallAdapter.mapToCapxulError` AND the backend `credentials/http.ts`\n// `bootstrapClient` handler. Single source of truth for cross-Convex-boundary\n// error decoding rules.\n//\n// Recognizes the `ConvexError(SerializedCapxulError)` object-shape produced by\n// `withErrorBoundary` (Probe B finding, 2026-05-19):\n//\n// { name: \"ConvexError\", data: { code, message, details?, correlationId?, layer? } }\n//\n// AND the defensive string-shape branch for older Convex versions where\n// `data` is a JSON-serialized string. Pass-through for raw `CapxulError`\n// instances (which arrive directly when the throw happened in the same\n// V8 isolate as the catch). Returns null when the value is not a\n// recognizable shape — the caller falls back to NETWORK_ERROR + reportError.\n\nimport {\n CAPXUL_ERROR_CODES,\n CapxulError,\n type CapxulErrorCode,\n type SerializedCapxulError,\n deserializeCapxulError,\n} from \"./errors.ts\";\n\n// Derived from the canonical catalog in errors.ts — single source of truth,\n// so a new code added to `CAPXUL_ERROR_CODES` is recognized here automatically.\nconst KNOWN_CODES: ReadonlySet<CapxulErrorCode> = new Set(CAPXUL_ERROR_CODES);\n\nfunction isCapxulCode(value: unknown): value is CapxulErrorCode {\n return typeof value === \"string\" && KNOWN_CODES.has(value as CapxulErrorCode);\n}\n\nfunction reconstruct(serialized: Record<string, unknown>): CapxulError | null {\n if (!isCapxulCode(serialized.code)) return null;\n const payload: SerializedCapxulError = {\n code: serialized.code,\n message: typeof serialized.message === \"string\" ? serialized.message : String(serialized.code),\n ...(typeof serialized.details === \"object\" &&\n serialized.details !== null &&\n !Array.isArray(serialized.details)\n ? { details: serialized.details as Record<string, unknown> }\n : {}),\n ...(typeof serialized.correlationId === \"string\"\n ? { correlationId: serialized.correlationId }\n : {}),\n ...(typeof serialized.layer === \"string\" ? { layer: serialized.layer } : {}),\n };\n return deserializeCapxulError(payload);\n}\n\nexport function decodeConvexError(err: unknown): CapxulError | null {\n if (err === null || err === undefined) return null;\n\n // Pass-through: same isolate, real CapxulError instance.\n if (err instanceof CapxulError) return err;\n\n if (typeof err !== \"object\") return null;\n\n // The canonical shape produced by `withErrorBoundary` then crossed by\n // Convex's `ctx.runQuery` / `ConvexHttpClient`: a `ConvexError` whose\n // `data` is the `SerializedCapxulError` object literal.\n const record = err as Record<string, unknown>;\n if (!(\"data\" in record)) return null;\n const data = record.data;\n\n if (typeof data === \"object\" && data !== null) {\n return reconstruct(data as Record<string, unknown>);\n }\n\n // Defensive depth — some Convex versions JSON-stringify the data at\n // the runtime boundary. Probe B confirmed @convex-dev/better-auth 0.10.13\n // + convex 1.39.x do NOT do this, but the cheap parse keeps forward\n // compatibility.\n if (typeof data === \"string\") {\n try {\n const parsed = JSON.parse(data) as unknown;\n if (typeof parsed === \"object\" && parsed !== null) {\n return reconstruct(parsed as Record<string, unknown>);\n }\n } catch {\n // Fall through.\n }\n }\n\n return null;\n}\n","import { Errors } from \"@capxul/errors\";\nimport type { Brand } from \"./brand\";\n\nexport type { Brand } from \"./brand\";\n\nexport type Address = Brand<string, \"Address\">;\nexport type Email = Brand<string, \"Email\">;\nexport type Identity = Brand<string, \"Identity\">;\n// `Profile` is the SDK's user-shaped record returned by `IdentityPort`. Pure\n// record of brand-typed fields — not itself a brand. The field-level brands\n// satisfy `IdentityPort` clause I8 at compile time. Hosted here per the\n// canon (`docs/canon/ports/identity.md`).\nexport type Profile = {\n readonly authUserId: AuthUserId;\n readonly email: Email;\n readonly displayName: string | null;\n readonly country: CountryCode | null;\n readonly kycTier: KycTier;\n readonly createdAt: EpochMs;\n readonly updatedAt: EpochMs;\n};\n// `SmartAccount` is the SDK's ERC-4337 record returned by `SmartAccountPort`.\n// Pure record of brand-typed fields — not itself a brand. `deployedAt` is\n// nullable: `null` means the address is counterfactual (derived, not yet\n// on-chain). PRD #462 (derivation v2): `signerAddress` is the CLAIMED owner —\n// `null` until the claim userOp installs the user's signer (`claimedAt`\n// records that event); the address derives from the email alone. Hosted here\n// per the canon (`docs/canon/ports/smart-account.md`).\nexport type SmartAccount = {\n readonly authUserId: AuthUserId;\n readonly signerAddress: Address | null;\n readonly smartAccountAddress: Address;\n readonly chainId: ChainId;\n readonly deployedAt: EpochMs | null;\n readonly claimedAt: EpochMs | null;\n readonly createdAt: EpochMs;\n};\n// `Money` is the SDK's consumer-facing value type (canon\n// `account-balance-model.md` §10). Every public monetary value is a `Money`\n// — never wei, never raw token units. `value` is a major-unit decimal string\n// (e.g. \"1.5\" USD); `decimals` is the on-chain token precision used for the\n// internal `fromWei`/`toWei` round-trip at the SDK boundary (USDX is 6).\n// Pure record of a brand-typed field + primitives — not itself a brand.\nexport type Money = {\n readonly currency: CurrencyCode;\n readonly value: string;\n readonly decimals: number;\n};\n\n// `Account` is the SDK's logical money account (canon §6, §9). `id` is the\n// `account_`-shaped `AccountId` — NOT the Safe address and NOT an Openfort id.\n// `balance` is the Safe's top-line holdings; `available` is money not assigned\n// to any sub-account (canon §5/§12). With no sub-accounts (Slice 1a),\n// `available === balance`. Pure record of brand-typed fields — not a brand.\nexport type Account = {\n readonly id: AccountId;\n readonly balance: Money;\n readonly available: Money;\n};\n\n/** Named bucket partitioning a logical Account (canon §9). */\nexport type SubAccount = {\n readonly id: SubAccountId;\n readonly accountId: AccountId;\n readonly name: string;\n readonly balance: Money;\n readonly createdAt: EpochMs;\n};\n\nexport type AuthUserId = Brand<string, \"AuthUserId\">;\nexport type AnonymousDistinctId = Brand<string, \"AnonymousDistinctId\">;\nexport type PlayerId = Brand<string, \"PlayerId\">;\nexport type AccountId = Brand<string, \"AccountId\">;\nexport type SubAccountId = Brand<string, \"SubAccountId\">;\nexport type OrgId = Brand<string, \"OrgId\">;\nexport type AppId = Brand<string, \"AppId\">;\nexport type AllowedOrigin = Brand<string, \"AllowedOrigin\">;\nexport type PublishableKey = Brand<string, \"PublishableKey\">;\nexport type PublishableKeyId = Brand<string, \"PublishableKeyId\">;\nexport type DurationMs = Brand<number, \"DurationMs\">;\n// `DeveloperApplication` and `PublishableKeyRecord` are the SDK's record\n// shapes returned by `CredentialsPort`. Pure records of brand-typed fields\n// — not themselves brands. The field-level brands satisfy CR13 + the record\n// branding clauses of `credentials.test-d.ts` at compile time. Hosted here\n// per the canon (`docs/canon/ports/credentials.md`).\nexport type DeveloperApplication = {\n readonly id: AppId;\n readonly authUserId: AuthUserId;\n readonly name: string;\n readonly allowedOrigins: readonly AllowedOrigin[];\n readonly createdAt: EpochMs;\n readonly archivedAt: EpochMs | null;\n};\nexport type PublishableKeyRecord = {\n readonly id: PublishableKeyId;\n readonly applicationId: AppId;\n readonly activeFromMs: EpochMs;\n readonly gracePeriodEndsMs: EpochMs | null;\n readonly revokedAt: EpochMs | null;\n};\nexport type TxHash = Brand<string, \"TxHash\">;\nexport type DocumentHash = Brand<string, \"DocumentHash\">;\nexport type EpochMs = Brand<number, \"EpochMs\">;\nexport type EpochSeconds = Brand<number, \"EpochSeconds\">;\nexport type ChainId = Brand<number, \"ChainId\">;\nexport type CountryCode = Brand<string, \"CountryCode\">;\nexport type CurrencyCode = Brand<SupportedCurrencyCode, \"CurrencyCode\">;\nexport type KycTier = Brand<0 | 1 | 2 | 3, \"KycTier\">;\nexport type BlockNumber = Brand<number, \"BlockNumber\">;\nexport type LogIndex = Brand<number, \"LogIndex\">;\nexport type WeiAmount = Brand<string, \"WeiAmount\">;\nexport type SafeAddress = Brand<string, \"SafeAddress\">;\nexport type ModuleAddress = Brand<string, \"ModuleAddress\">;\nexport type RunId = Brand<string, \"RunId\">;\nexport type RoleKey = Brand<string, \"RoleKey\">;\nexport type AllowanceKey = Brand<string, \"AllowanceKey\">;\nexport type SessionToken = Brand<string, \"SessionToken\">;\nexport type JwtToken = Brand<string, \"JwtToken\">;\n\n// `AuthSession` is the record type shared by `AuthClientPort` and\n// `SessionStoragePort`. Hosted here per the canon\n// (`docs/canon/ports/auth-client.md`) so both ports depend on it\n// symmetrically. Every field is branded — field-level brands satisfy the\n// AuthSession branding contract asserted in `auth-client.test-d.ts`.\nexport type AuthSession = {\n readonly authUserId: AuthUserId;\n readonly email: Email;\n readonly token: SessionToken;\n readonly expiresAt: EpochMs;\n};\n\nexport const EVM_ADDRESS_RE = /^0x[0-9a-f]{40}$/i;\nexport const BYTES32_RE = /^0x[0-9a-f]{64}$/i;\nexport const PUBLISHABLE_KEY_PATTERN = /^cap_pk_(test|live)_[0-9A-HJKMNP-TV-Z]{32}$/;\nexport const SUPPORTED_CURRENCIES = [\n { code: \"USD\", symbol: \"$\", name: \"US Dollar\" },\n { code: \"NGN\", symbol: \"NGN\", name: \"Nigerian Naira\" },\n { code: \"GHS\", symbol: \"GHS\", name: \"Ghanaian Cedi\" },\n { code: \"KES\", symbol: \"KSh\", name: \"Kenyan Shilling\" },\n { code: \"UGX\", symbol: \"USh\", name: \"Ugandan Shilling\" },\n] as const;\nexport const SUPPORTED_CURRENCY_CODES = SUPPORTED_CURRENCIES.map((currency) => currency.code);\ntype SupportedCurrencyCode = (typeof SUPPORTED_CURRENCIES)[number][\"code\"];\nexport const CURRENCY_SYMBOLS = Object.fromEntries(\n SUPPORTED_CURRENCIES.map((currency) => [currency.code, currency.symbol]),\n) as Record<SupportedCurrencyCode, string>;\n\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst COUNTRY_CODE_RE = /^[A-Z]{2}$/;\nconst ANONYMOUS_DISTINCT_ID_RE = /^anon_[a-zA-Z0-9-]+$/;\n// Canon §6: the logical Account brand is `account_`-shaped. The tail mirrors\n// the `app_` ULID-shape generator (`account_<26 Crockford base32 chars>`) but\n// the brand only enforces the `account_` prefix + a non-empty alphanumeric\n// tail so existing opaque test ids (`account_123`) and generated ULIDs both\n// satisfy it.\nconst ACCOUNT_ID_RE = /^account_[0-9A-Za-z]+$/;\nconst SUBACCOUNT_ID_RE = /^subaccount_[0-9A-Za-z]+$/;\n// Exported so `@capxul/wire`'s `AppIdSchema` can reuse the same regex via\n// `Schema.filter(...)` and stay in lockstep with `toAppId` (Decision 2,\n// 2b parity).\nexport const APP_ID_RE = /^app_[0-7][0-9A-HJKMNP-TV-Z]{25}$/;\nconst TX_HASH_RE = /^0x[0-9a-f]{64}$/i;\nconst DOCUMENT_HASH_HEX_RE = /^[0-9a-fA-F]{64}$/;\nconst WEI_RE = /^[0-9]+$/;\nconst RUN_ID_RE = /^run_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\nconst MAX_SAFE_EPOCH_SECONDS = Math.floor(Number.MAX_SAFE_INTEGER / 1000);\n\nexport function toAddress(raw: unknown): Address {\n if (typeof raw !== \"string\" || !EVM_ADDRESS_RE.test(raw)) {\n throw Errors.invalidInput(\"address\", invalidValueReason(\"invalid EVM address format\", raw));\n }\n\n return raw.toLowerCase() as Address;\n}\n\nexport function isEvmAddress(raw: unknown): raw is string {\n return typeof raw === \"string\" && EVM_ADDRESS_RE.test(raw);\n}\n\nexport function toEmail(raw: unknown): Email {\n if (typeof raw !== \"string\" || !EMAIL_RE.test(raw)) {\n throw Errors.invalidInput(\"email\", invalidValueReason(\"must look like an email address\", raw));\n }\n\n return raw.toLowerCase() as Email;\n}\n\nexport function toIdentity(raw: unknown): Identity {\n return toNonEmptyStringBrand(raw, \"identity\") as Identity;\n}\n\nexport function toAuthUserId(raw: unknown): AuthUserId {\n return toNonEmptyStringBrand(raw, \"authUserId\") as AuthUserId;\n}\n\nexport function toAnonymousDistinctId(raw: unknown): AnonymousDistinctId {\n if (typeof raw !== \"string\" || !ANONYMOUS_DISTINCT_ID_RE.test(raw)) {\n throw Errors.invalidInput(\n \"anonDistinctId\",\n invalidValueReason(\"must be anon_ plus letters, digits, or hyphens\", raw),\n );\n }\n\n return raw as AnonymousDistinctId;\n}\n\nexport function toPlayerId(raw: unknown): PlayerId {\n return toNonEmptyStringBrand(raw, \"playerId\") as PlayerId;\n}\n\nexport function toAccountId(raw: unknown): AccountId {\n if (typeof raw !== \"string\" || !ACCOUNT_ID_RE.test(raw)) {\n throw Errors.invalidInput(\n \"accountId\",\n invalidValueReason(\"must be account_ plus an alphanumeric id\", raw),\n );\n }\n\n return raw as AccountId;\n}\n\nexport function toSubAccountId(raw: unknown): SubAccountId {\n if (typeof raw !== \"string\" || !SUBACCOUNT_ID_RE.test(raw)) {\n throw Errors.invalidInput(\n \"subAccountId\",\n invalidValueReason(\"must be subaccount_ plus an alphanumeric id\", raw),\n );\n }\n\n return raw as SubAccountId;\n}\n\nexport function toOrgId(raw: unknown): OrgId {\n return toNonEmptyStringBrand(raw, \"orgId\") as OrgId;\n}\n\nexport function toAppId(raw: unknown): AppId {\n if (typeof raw !== \"string\" || !APP_ID_RE.test(raw)) {\n throw Errors.invalidInput(\"appId\", invalidValueReason(\"must be app_ plus a ULID\", raw));\n }\n\n return raw as AppId;\n}\n\nexport function toAllowedOrigin(raw: unknown): AllowedOrigin {\n if (typeof raw !== \"string\") {\n throw Errors.invalidInput(\"allowedOrigin\", \"must be an http or https origin string\");\n }\n\n const normalized = normalizeAllowedOrigin(raw);\n if (normalized === null) {\n throw Errors.invalidInput(\n \"allowedOrigin\",\n invalidValueReason(\"must be an http or https origin\", raw),\n );\n }\n\n return normalized as AllowedOrigin;\n}\n\nexport function toPublishableKeyId(raw: unknown): PublishableKeyId {\n return toNonEmptyStringBrand(raw, \"keyId\") as PublishableKeyId;\n}\n\nexport function toDurationMs(raw: unknown): DurationMs {\n if (typeof raw !== \"number\" || !Number.isSafeInteger(raw) || raw < 0) {\n throw Errors.invalidInput(\n \"duration\",\n invalidValueReason(\"must be a non-negative safe integer\", raw),\n );\n }\n\n return raw as DurationMs;\n}\n\nexport function toPublishableKey(raw: unknown): PublishableKey {\n if (typeof raw !== \"string\" || !PUBLISHABLE_KEY_PATTERN.test(raw)) {\n throw Errors.invalidInput(\n \"publishableKey\",\n invalidValueReason(\"must match cap_pk_(test|live) plus 32 Crockford base32 chars\", raw),\n );\n }\n\n return raw as PublishableKey;\n}\n\nexport function toTxHash(raw: unknown): TxHash {\n if (typeof raw !== \"string\" || !TX_HASH_RE.test(raw)) {\n throw Errors.invalidInput(\"txHash\", invalidValueReason(\"must be 0x + 64 hex chars\", raw));\n }\n\n return raw.toLowerCase() as TxHash;\n}\n\nexport function toDocumentHash(raw: unknown): DocumentHash {\n if (typeof raw !== \"string\") {\n throw Errors.invalidInput(\"documentHash\", \"must be a string\");\n }\n\n const stripped = raw.startsWith(\"0x\") || raw.startsWith(\"0X\") ? raw.slice(2) : raw;\n if (!DOCUMENT_HASH_HEX_RE.test(stripped)) {\n throw Errors.invalidInput(\"documentHash\", \"must be 32 bytes of hex\");\n }\n\n return `0x${stripped.toLowerCase()}` as DocumentHash;\n}\n\nexport function toEpochMs(raw: unknown): EpochMs {\n assertSafeNonNegativeInteger(raw, \"epochMs\");\n return raw as EpochMs;\n}\n\nexport function toEpochSeconds(raw: unknown): EpochSeconds {\n assertSafeNonNegativeInteger(raw, \"epochSeconds\");\n return raw as EpochSeconds;\n}\n\nexport function secondsToMs(seconds: EpochSeconds): EpochMs {\n if (seconds > MAX_SAFE_EPOCH_SECONDS) {\n throw Errors.invalidInput(\"epochSeconds\", `${seconds} would overflow when multiplied by 1000`);\n }\n\n return toEpochMs(seconds * 1000);\n}\n\nexport function epochMsToSeconds(ms: EpochMs): EpochSeconds {\n return toEpochSeconds(Math.floor(ms / 1000));\n}\n\nexport function toChainId(raw: unknown): ChainId {\n if (typeof raw !== \"number\" || !Number.isSafeInteger(raw) || raw <= 0) {\n throw Errors.invalidInput(\n \"chainId\",\n invalidValueReason(\"must be a positive safe integer\", raw),\n );\n }\n\n return raw as ChainId;\n}\n\nexport function toBlockNumber(raw: unknown): BlockNumber {\n assertSafeNonNegativeInteger(raw, \"blockNumber\");\n return raw as BlockNumber;\n}\n\nexport function toLogIndex(raw: unknown): LogIndex {\n assertSafeNonNegativeInteger(raw, \"logIndex\");\n return raw as LogIndex;\n}\n\nexport function toWeiAmount(raw: unknown): WeiAmount {\n if (typeof raw !== \"string\" || !WEI_RE.test(raw)) {\n throw Errors.invalidInput(\n \"weiAmount\",\n invalidValueReason(\"must be a non-negative integer string\", raw),\n );\n }\n\n return raw as WeiAmount;\n}\n\nexport function toCountryCode(raw: unknown): CountryCode {\n if (typeof raw !== \"string\") {\n throw Errors.invalidInput(\"countryCode\", \"must be a string\");\n }\n\n const upper = raw.toUpperCase();\n if (!COUNTRY_CODE_RE.test(upper)) {\n throw Errors.invalidInput(\n \"countryCode\",\n invalidValueReason(\"must be a 2-letter ISO 3166-1 alpha-2 code\", raw),\n );\n }\n\n return upper as CountryCode;\n}\n\nexport function toCurrencyCode(raw: unknown): CurrencyCode {\n if (typeof raw !== \"string\" || !SUPPORTED_CURRENCY_CODES.includes(raw as SupportedCurrencyCode)) {\n throw Errors.invalidInput(\"currencyCode\", invalidValueReason(\"unsupported currency\", raw));\n }\n\n return raw as CurrencyCode;\n}\n\nexport function currencySymbolFor(code: CurrencyCode): string {\n const symbol = CURRENCY_SYMBOLS[code as SupportedCurrencyCode];\n if (symbol === undefined) {\n throw Errors.invalidInput(\"currencyCode\", `no symbol registered for \"${String(code)}\"`);\n }\n\n return symbol;\n}\n\nexport function toKycTier(raw: unknown): KycTier {\n if (typeof raw !== \"number\" || !Number.isInteger(raw) || raw < 0 || raw > 3) {\n throw Errors.invalidInput(\"kycTier\", invalidValueReason(\"must be an integer in [0, 3]\", raw));\n }\n\n return raw as KycTier;\n}\n\nexport function toSafeAddress(raw: unknown): SafeAddress {\n if (typeof raw !== \"string\" || !EVM_ADDRESS_RE.test(raw)) {\n throw Errors.invalidInput(\"safeAddress\", invalidValueReason(\"invalid EVM address format\", raw));\n }\n\n return raw.toLowerCase() as SafeAddress;\n}\n\nexport function toModuleAddress(raw: unknown): ModuleAddress {\n if (typeof raw !== \"string\" || !EVM_ADDRESS_RE.test(raw)) {\n throw Errors.invalidInput(\n \"moduleAddress\",\n invalidValueReason(\"invalid EVM address format\", raw),\n );\n }\n\n return raw.toLowerCase() as ModuleAddress;\n}\n\nexport function toRunId(raw: unknown): RunId {\n if (typeof raw !== \"string\" || !RUN_ID_RE.test(raw)) {\n throw Errors.invalidInput(\"runId\", \"must match the format run_<uuid>\");\n }\n\n return raw as RunId;\n}\n\nexport function toRoleKey(raw: unknown): RoleKey {\n if (typeof raw !== \"string\" || !BYTES32_RE.test(raw)) {\n throw Errors.invalidInput(\"roleKey\", invalidValueReason(\"must be 0x + 64 hex chars\", raw));\n }\n\n return raw.toLowerCase() as RoleKey;\n}\n\nexport function toAllowanceKey(raw: unknown): AllowanceKey {\n if (typeof raw !== \"string\" || !BYTES32_RE.test(raw)) {\n throw Errors.invalidInput(\"allowanceKey\", invalidValueReason(\"must be 0x + 64 hex chars\", raw));\n }\n\n return raw.toLowerCase() as AllowanceKey;\n}\n\nexport function toSessionToken(raw: unknown): SessionToken {\n if (typeof raw !== \"string\" || raw.length === 0) {\n throw Errors.invalidInput(\"token\", \"must be a non-empty string\");\n }\n\n return raw as SessionToken;\n}\n\nexport function toJwtToken(raw: unknown): JwtToken {\n if (typeof raw !== \"string\" || raw.length === 0) {\n throw Errors.invalidInput(\"jwtToken\", \"must be a non-empty string\");\n }\n\n return raw as JwtToken;\n}\n\nfunction toNonEmptyStringBrand(raw: unknown, field: string): string {\n if (typeof raw !== \"string\" || raw.length === 0) {\n throw Errors.invalidInput(field, \"must be a non-empty string\");\n }\n\n return raw;\n}\n\nfunction assertSafeNonNegativeInteger(raw: unknown, field: string): asserts raw is number {\n if (typeof raw !== \"number\" || !Number.isSafeInteger(raw) || raw < 0) {\n throw Errors.invalidInput(\n field,\n invalidValueReason(\"must be a non-negative safe integer\", raw),\n );\n }\n}\n\nfunction normalizeAllowedOrigin(raw: string): string | null {\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n return null;\n }\n\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return null;\n }\n\n if (parsed.hostname.includes(\"*\")) {\n return null;\n }\n\n return parsed.origin;\n}\n\nfunction invalidValueReason(prefix: string, raw: unknown): string {\n if (typeof raw === \"string\") {\n return `${prefix}: ${raw.slice(0, 40)}`;\n }\n\n return `${prefix}: ${String(raw)}`;\n}\n","import { Context, Data, Effect } from \"effect\";\nimport type { AuthSession, EpochSeconds, JwtToken } from \"@capxul/types\";\n\n/**\n * AuthCachePort (TA4) — replaces `SessionStoragePort` in the rebuild slice's\n * consumer-facing wiring. Stores the user-snapshot Session AND the cached\n * Convex JWT (W7 bridge endpoint). The two slots are independent so a session\n * refresh doesn't invalidate the JWT and vice versa.\n *\n * Three adapters (TA7):\n * - `BrowserAuthCacheAdapter` — backed by `localStorage`\n * - `FileSystemAuthCacheAdapter` — mode-0600 JSON file in `~/.config/capxul/`\n * - `InMemoryAuthCacheAdapter` — for tests\n *\n * `SessionStoragePort` was retired by the Stage 4 rebuild; session and JWT\n * persistence now share this cache boundary.\n */\nexport interface AuthCachePort {\n readonly getSession: Effect.Effect<AuthSession | null, AuthCacheError>;\n readonly setSession: (session: AuthSession) => Effect.Effect<void, AuthCacheError>;\n readonly clearSession: Effect.Effect<void, AuthCacheError>;\n\n /**\n * JWT cache for the `/api/auth/convex/token` bridge endpoint (W7).\n * Stored separately from the session so a session refresh doesn't\n * invalidate cached JWT.\n */\n readonly getJwt: Effect.Effect<CachedJwt | null, AuthCacheError>;\n readonly setJwt: (jwt: CachedJwt) => Effect.Effect<void, AuthCacheError>;\n readonly clearJwt: Effect.Effect<void, AuthCacheError>;\n}\n\n/**\n * Cached Convex JWT shape (TA4). `expEpochSeconds` is decoded from the JWT's\n * `exp` claim at fetch time so the `tokenProvider` cache eviction logic can\n * proactively refresh at `exp - 30s` per TA3.\n */\nexport interface CachedJwt {\n readonly token: JwtToken;\n readonly expEpochSeconds: EpochSeconds;\n}\n\nexport class AuthCacheError extends Data.TaggedError(\"AuthCacheError\")<{\n readonly operation: string;\n readonly cause: unknown;\n}> {}\n\nexport class AuthCachePortTag extends Context.Tag(\"@capxul/sdk/ports/AuthCachePort\")<\n AuthCachePortTag,\n AuthCachePort\n>() {}\n","import {\n toAuthUserId,\n toEmail,\n toEpochMs,\n toEpochSeconds,\n toJwtToken,\n toSessionToken,\n type AuthSession,\n} from \"@capxul/types\";\n\nimport type { CachedJwt } from \"../../ports/auth-cache\";\n\nexport function parseAuthSession(raw: unknown): AuthSession | null {\n if (typeof raw !== \"object\" || raw === null) return null;\n const candidate = raw as {\n readonly authUserId?: unknown;\n readonly email?: unknown;\n readonly token?: unknown;\n readonly expiresAt?: unknown;\n };\n\n try {\n return {\n authUserId: toAuthUserId(candidate.authUserId),\n email: toEmail(candidate.email),\n token: toSessionToken(candidate.token),\n expiresAt: toEpochMs(candidate.expiresAt),\n };\n } catch {\n return null;\n }\n}\n\nexport function parseCachedJwt(raw: unknown): CachedJwt | null {\n if (typeof raw !== \"object\" || raw === null) return null;\n const candidate = raw as {\n readonly token?: unknown;\n readonly expEpochSeconds?: unknown;\n };\n\n try {\n return {\n token: toJwtToken(candidate.token),\n expEpochSeconds: toEpochSeconds(candidate.expEpochSeconds),\n };\n } catch {\n return null;\n }\n}\n","import { Effect, Layer } from \"effect\";\nimport type { AuthSession } from \"@capxul/types\";\n\nimport {\n AuthCacheError,\n AuthCachePortTag,\n type AuthCachePort,\n type CachedJwt,\n} from \"../../ports/auth-cache\";\nimport { parseAuthSession, parseCachedJwt } from \"./serialization\";\n\nexport interface BrowserStorageShape {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nconst SESSION_KEY = \"capxul.session\";\nconst JWT_KEY = \"capxul.jwt\";\n\nexport class BrowserAuthCacheAdapter implements AuthCachePort {\n private readonly storage: BrowserStorageShape;\n\n constructor(storage: BrowserStorageShape) {\n this.storage = storage;\n }\n\n readonly getSession = authCacheTry(\"getSession\", () => {\n const raw = this.storage.getItem(SESSION_KEY);\n if (raw === null) return null;\n try {\n return parseAuthSession(JSON.parse(raw));\n } catch {\n return null;\n }\n });\n\n readonly setSession = (session: AuthSession) =>\n authCacheTry(\"setSession\", () => {\n this.storage.setItem(SESSION_KEY, JSON.stringify(session));\n });\n\n readonly clearSession = authCacheTry(\"clearSession\", () => {\n this.storage.removeItem(SESSION_KEY);\n });\n\n readonly getJwt = authCacheTry(\"getJwt\", () => {\n const raw = this.storage.getItem(JWT_KEY);\n if (raw === null) return null;\n try {\n return parseCachedJwt(JSON.parse(raw));\n } catch {\n return null;\n }\n });\n\n readonly setJwt = (jwt: CachedJwt) =>\n authCacheTry(\"setJwt\", () => {\n this.storage.setItem(JWT_KEY, JSON.stringify(jwt));\n });\n\n readonly clearJwt = authCacheTry(\"clearJwt\", () => {\n this.storage.removeItem(JWT_KEY);\n });\n}\n\nexport function BrowserAuthCacheLayer(input: {\n readonly storage: BrowserStorageShape;\n}): Layer.Layer<AuthCachePortTag, AuthCacheError> {\n return Layer.effect(\n AuthCachePortTag,\n Effect.sync(() => new BrowserAuthCacheAdapter(input.storage)).pipe(\n Effect.mapError((cause) => toAuthCacheError(\"initialize\", cause)),\n ),\n );\n}\n\nfunction toAuthCacheError(operation: string, cause: unknown): AuthCacheError {\n return new AuthCacheError({ operation, cause });\n}\n\nfunction authCacheTry<T>(operation: string, run: () => T): Effect.Effect<T, AuthCacheError> {\n return Effect.try({\n try: run,\n catch: (cause) => toAuthCacheError(operation, cause),\n });\n}\n","import { Effect, Layer } from \"effect\";\nimport type { AuthSession } from \"@capxul/types\";\n\nimport {\n AuthCacheError,\n AuthCachePortTag,\n type AuthCachePort,\n type CachedJwt,\n} from \"../../ports/auth-cache\";\n\nexport class InMemoryAuthCacheAdapter implements AuthCachePort {\n private session: AuthSession | null = null;\n private jwt: CachedJwt | null = null;\n\n readonly getSession = Effect.sync(() => this.session);\n\n readonly setSession = (session: AuthSession) =>\n Effect.sync(() => {\n this.session = session;\n });\n\n readonly clearSession = Effect.sync(() => {\n this.session = null;\n });\n\n readonly getJwt = Effect.sync(() => this.jwt);\n\n readonly setJwt = (jwt: CachedJwt) =>\n Effect.sync(() => {\n this.jwt = jwt;\n });\n\n readonly clearJwt = Effect.sync(() => {\n this.jwt = null;\n });\n}\n\nexport const InMemoryAuthCacheLayer = Layer.effect(\n AuthCachePortTag,\n Effect.sync(() => new InMemoryAuthCacheAdapter()).pipe(\n Effect.mapError((cause) => new AuthCacheError({ operation: \"initialize\", cause })),\n ),\n);\n"],"mappings":"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"}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { Hex } from "viem";
|
|
2
|
-
|
|
3
|
-
//#region ../errors/src/errors.d.ts
|
|
4
|
-
declare const CAPXUL_ERROR_CODES: readonly ["NOT_AUTHENTICATED", "EMAIL_DELIVERY_FAILED", "PROFILE_NOT_FOUND", "SMART_ACCOUNT_MISSING", "PLAYER_NOT_FOUND", "ACCOUNT_NOT_FOUND", "PROVIDER_ERROR", "INVALID_INPUT", "ENV_MISSING", "NOT_IMPLEMENTED", "VERIFICATION_REQUIRED", "INSUFFICIENT_BALANCE", "INVALID_RECIPIENT", "ROLE_PERMISSION_DENIED", "TRANSACTION_FAILED", "RATE_LIMITED", "NETWORK_ERROR", "UNKNOWN", "OTP_EXPIRED", "SIGNER_REJECTED", "CANCELLED", "WRONG_STATE"];
|
|
5
|
-
type CapxulErrorCode = (typeof CAPXUL_ERROR_CODES)[number];
|
|
6
|
-
/**
|
|
7
|
-
* Why an auth/provider call failed — a flat CAUSE enum. The *where* (which
|
|
8
|
-
* OpenFort operation) stays in the separate `operation` detail field; this
|
|
9
|
-
* names the root cause so a single `$exception` can be triaged without
|
|
10
|
-
* parsing the message. Five members, no free strings:
|
|
11
|
-
*
|
|
12
|
-
* - `auth-origin-mismatch`: OTP cookies live on `localhost:PORT` but OpenFort
|
|
13
|
-
* hits the Convex host → no session reaches the provider.
|
|
14
|
-
* - `stale-openfort-cache`: an old `userId` in scoped storage makes the SDK
|
|
15
|
-
* skip re-auth → 401 on `v2/accounts`.
|
|
16
|
-
* - `app-env-allowlist`: missing `VITE_CAPXUL_CONVEX_SITE_URL` / the origin is
|
|
17
|
-
* not allowlisted → 401.
|
|
18
|
-
* - `no-secure-context`: sandboxed/headless browser with no Web Crypto, so
|
|
19
|
-
* `getAddress`/`configure` can never produce an address. Previously vanished
|
|
20
|
-
* into `unknown`; the signer's secure-context probe now names it.
|
|
21
|
-
* - `unknown`: catch-all when no cause could be determined.
|
|
22
|
-
*/
|
|
23
|
-
type FailureMode = "auth-origin-mismatch" | "stale-openfort-cache" | "app-env-allowlist" | "no-secure-context" | "unknown";
|
|
24
|
-
type CapxulErrorDetails = Record<string, unknown>;
|
|
25
|
-
type CapxulErrorOptions = {
|
|
26
|
-
readonly cause?: unknown;
|
|
27
|
-
readonly details?: CapxulErrorDetails;
|
|
28
|
-
readonly correlationId?: string;
|
|
29
|
-
readonly layer?: string;
|
|
30
|
-
};
|
|
31
|
-
declare class CapxulError extends Error {
|
|
32
|
-
readonly code: CapxulErrorCode;
|
|
33
|
-
readonly details?: CapxulErrorDetails;
|
|
34
|
-
readonly correlationId?: string;
|
|
35
|
-
readonly layer?: string;
|
|
36
|
-
constructor(code: CapxulErrorCode, message: string, options?: CapxulErrorOptions);
|
|
37
|
-
}
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region ../types/src/brand.d.ts
|
|
40
|
-
/**
|
|
41
|
-
* Nominal type helper. `Brand<T, B>` is structurally a `T` at runtime but
|
|
42
|
-
* distinct at compile time, preventing accidental swaps between primitives.
|
|
43
|
-
*
|
|
44
|
-
* @internal
|
|
45
|
-
*/
|
|
46
|
-
declare const brand: unique symbol;
|
|
47
|
-
type Brand<T, B extends string> = T & {
|
|
48
|
-
readonly [brand]: B;
|
|
49
|
-
};
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region ../types/src/index.d.ts
|
|
52
|
-
type Address = Brand<string, "Address">;
|
|
53
|
-
type Email = Brand<string, "Email">;
|
|
54
|
-
type Profile = {
|
|
55
|
-
readonly authUserId: AuthUserId;
|
|
56
|
-
readonly email: Email;
|
|
57
|
-
readonly displayName: string | null;
|
|
58
|
-
readonly country: CountryCode | null;
|
|
59
|
-
readonly kycTier: KycTier;
|
|
60
|
-
readonly createdAt: EpochMs;
|
|
61
|
-
readonly updatedAt: EpochMs;
|
|
62
|
-
};
|
|
63
|
-
type SmartAccount = {
|
|
64
|
-
readonly authUserId: AuthUserId;
|
|
65
|
-
readonly signerAddress: Address | null;
|
|
66
|
-
readonly smartAccountAddress: Address;
|
|
67
|
-
readonly chainId: ChainId;
|
|
68
|
-
readonly deployedAt: EpochMs | null;
|
|
69
|
-
readonly claimedAt: EpochMs | null;
|
|
70
|
-
readonly createdAt: EpochMs;
|
|
71
|
-
};
|
|
72
|
-
type Money = {
|
|
73
|
-
readonly currency: CurrencyCode;
|
|
74
|
-
readonly value: string;
|
|
75
|
-
readonly decimals: number;
|
|
76
|
-
};
|
|
77
|
-
type Account$1 = {
|
|
78
|
-
readonly id: AccountId;
|
|
79
|
-
readonly balance: Money;
|
|
80
|
-
readonly available: Money;
|
|
81
|
-
};
|
|
82
|
-
/** Named bucket partitioning a logical Account (canon §9). */
|
|
83
|
-
type SubAccount = {
|
|
84
|
-
readonly id: SubAccountId;
|
|
85
|
-
readonly accountId: AccountId;
|
|
86
|
-
readonly name: string;
|
|
87
|
-
readonly balance: Money;
|
|
88
|
-
readonly createdAt: EpochMs;
|
|
89
|
-
};
|
|
90
|
-
type AuthUserId = Brand<string, "AuthUserId">;
|
|
91
|
-
type AnonymousDistinctId = Brand<string, "AnonymousDistinctId">;
|
|
92
|
-
type AccountId = Brand<string, "AccountId">;
|
|
93
|
-
type SubAccountId = Brand<string, "SubAccountId">;
|
|
94
|
-
type OrgId = Brand<string, "OrgId">;
|
|
95
|
-
type AppId = Brand<string, "AppId">;
|
|
96
|
-
type AllowedOrigin = Brand<string, "AllowedOrigin">;
|
|
97
|
-
type PublishableKey = Brand<string, "PublishableKey">;
|
|
98
|
-
type PublishableKeyId = Brand<string, "PublishableKeyId">;
|
|
99
|
-
type DurationMs = Brand<number, "DurationMs">;
|
|
100
|
-
type DeveloperApplication = {
|
|
101
|
-
readonly id: AppId;
|
|
102
|
-
readonly authUserId: AuthUserId;
|
|
103
|
-
readonly name: string;
|
|
104
|
-
readonly allowedOrigins: readonly AllowedOrigin[];
|
|
105
|
-
readonly createdAt: EpochMs;
|
|
106
|
-
readonly archivedAt: EpochMs | null;
|
|
107
|
-
};
|
|
108
|
-
type PublishableKeyRecord = {
|
|
109
|
-
readonly id: PublishableKeyId;
|
|
110
|
-
readonly applicationId: AppId;
|
|
111
|
-
readonly activeFromMs: EpochMs;
|
|
112
|
-
readonly gracePeriodEndsMs: EpochMs | null;
|
|
113
|
-
readonly revokedAt: EpochMs | null;
|
|
114
|
-
};
|
|
115
|
-
type TxHash = Brand<string, "TxHash">;
|
|
116
|
-
type DocumentHash = Brand<string, "DocumentHash">;
|
|
117
|
-
type EpochMs = Brand<number, "EpochMs">;
|
|
118
|
-
type EpochSeconds = Brand<number, "EpochSeconds">;
|
|
119
|
-
type ChainId = Brand<number, "ChainId">;
|
|
120
|
-
type CountryCode = Brand<string, "CountryCode">;
|
|
121
|
-
type CurrencyCode = Brand<SupportedCurrencyCode, "CurrencyCode">;
|
|
122
|
-
type KycTier = Brand<0 | 1 | 2 | 3, "KycTier">;
|
|
123
|
-
type BlockNumber = Brand<number, "BlockNumber">;
|
|
124
|
-
type RunId = Brand<string, "RunId">;
|
|
125
|
-
type RoleKey = Brand<string, "RoleKey">;
|
|
126
|
-
type SessionToken = Brand<string, "SessionToken">;
|
|
127
|
-
type JwtToken = Brand<string, "JwtToken">;
|
|
128
|
-
type AuthSession = {
|
|
129
|
-
readonly authUserId: AuthUserId;
|
|
130
|
-
readonly email: Email;
|
|
131
|
-
readonly token: SessionToken;
|
|
132
|
-
readonly expiresAt: EpochMs;
|
|
133
|
-
};
|
|
134
|
-
declare const SUPPORTED_CURRENCIES: readonly [{
|
|
135
|
-
readonly code: "USD";
|
|
136
|
-
readonly symbol: "$";
|
|
137
|
-
readonly name: "US Dollar";
|
|
138
|
-
}, {
|
|
139
|
-
readonly code: "NGN";
|
|
140
|
-
readonly symbol: "NGN";
|
|
141
|
-
readonly name: "Nigerian Naira";
|
|
142
|
-
}, {
|
|
143
|
-
readonly code: "GHS";
|
|
144
|
-
readonly symbol: "GHS";
|
|
145
|
-
readonly name: "Ghanaian Cedi";
|
|
146
|
-
}, {
|
|
147
|
-
readonly code: "KES";
|
|
148
|
-
readonly symbol: "KSh";
|
|
149
|
-
readonly name: "Kenyan Shilling";
|
|
150
|
-
}, {
|
|
151
|
-
readonly code: "UGX";
|
|
152
|
-
readonly symbol: "USh";
|
|
153
|
-
readonly name: "Ugandan Shilling";
|
|
154
|
-
}];
|
|
155
|
-
type SupportedCurrencyCode = (typeof SUPPORTED_CURRENCIES)[number]["code"];
|
|
156
|
-
//#endregion
|
|
157
|
-
export { SubAccount as A, PublishableKey as C, RunId as D, RoleKey as E, CapxulErrorDetails as F, FailureMode as I, TxHash as M, CapxulError as N, SessionToken as O, CapxulErrorCode as P, Profile as S, PublishableKeyRecord as T, EpochMs as _, AnonymousDistinctId as a, Money as b, AuthUserId as c, CountryCode as d, CurrencyCode as f, Email as g, DurationMs as h, AllowedOrigin as i, SubAccountId as j, SmartAccount as k, BlockNumber as l, DocumentHash as m, AccountId as n, AppId as o, DeveloperApplication as p, Address as r, AuthSession as s, Account$1 as t, ChainId as u, EpochSeconds as v, PublishableKeyId as w, OrgId as x, JwtToken as y };
|
|
158
|
-
//# sourceMappingURL=index-CTXgQ_xR.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-CTXgQ_xR.d.mts","names":[],"sources":["../../errors/src/errors.ts","../../types/src/brand.ts","../../types/src/index.ts"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { a as SafeDeploymentEvidence, c as SafeDeploymentPortTag, i as SafeDeploymentError, l as safeDeploymentErrorFromCapxul, n as SafeDeploymentConfig, o as SafeDeploymentInput, r as SafeDeploymentDeployedQuery, s as SafeDeploymentPort, t as PreparedSafeAccount } from "../safe-deployment-D3k9yndM.mjs";
|
|
2
|
-
export { PreparedSafeAccount, SafeDeploymentConfig, SafeDeploymentDeployedQuery, SafeDeploymentError, SafeDeploymentEvidence, SafeDeploymentInput, SafeDeploymentPort, SafeDeploymentPortTag, safeDeploymentErrorFromCapxul };
|