{"version":3,"file":"session-native-stateful.mjs","names":[],"sources":["../../src/internal/session-native-stateful.ts"],"sourcesContent":["import type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport { AuthenticationClock } from \"@yielded/auth/Operations\";\nimport {\n  SessionConflict,\n  SessionInvalid,\n  PendingAuthenticationInvalid,\n  StaleAuthentication,\n  SessionMetadata,\n  SessionId,\n  snapshotSessionAuthenticationProvenance,\n  type StatefulSessionPersistence,\n  type StatefulSessionRecord,\n  type SessionRepository,\n  type SessionUnavailable,\n} from \"@yielded/auth/Sessions\";\nimport * as Cause from \"effect/Cause\";\nimport * as DateTime from \"effect/DateTime\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\nimport type * as SqlClient from \"effect/sql/SqlClient\";\nimport type * as Statement from \"effect/sql/Statement\";\n\nimport { sqlBatchAssertion } from \"./d1-planning\";\nimport { PersistenceMappingError, isMappedConstraintConflict } from \"./mapping-error\";\nimport type { StatefulSessionMapping } from \"./models/session-model\";\nimport type { NativeSqlTables } from \"./native-sql-table\";\nimport { sessionEvidenceDeadline } from \"./session-native-authority\";\nimport { makeNativeSessionPending, prepareNativeSession } from \"./session-native-pending\";\nimport {\n  makeConditionalSqlInsert,\n  makeNativeSessionRecords,\n  sameSessionRecord,\n} from \"./session-native-record\";\nimport {\n  makeNativeSessionAuthorityState,\n  sameSessionRevision,\n  normalizeSessionOperation,\n  invalidSessionState,\n  sessionUnavailable,\n} from \"./session-native-state\";\nimport { allocateSessionValue, preservesRevision } from \"./session-policy\";\nimport { exactSqlText, executeSqlChange } from \"./sql-change\";\nimport {\n  CurrentSqlCommit,\n  makeSqlCommitExecutor,\n  SqlBatchCommit,\n  appendSqlBatchStatement,\n  registerSqlBatchPostcondition,\n  registerSqlPostcondition,\n} from \"./sql-commit\";\nimport { canJoinTextColumns, withStorageValidation } from \"./storage-validation\";\nimport type { AnyTableModel } from \"./table-model\";\n\nexport type NativeStatefulSessionMapping<Claims> = StatefulSessionMapping<\n  Claims,\n  AnyTableModel,\n  AnyTableModel,\n  AnyTableModel,\n  AnyTableModel,\n  unknown,\n  unknown\n>;\n\nexport const makeNativeStatefulSessionServices = Effect.fnUntraced(function* <Claims>(\n  tables: NativeSqlTables,\n  mapping: NativeStatefulSessionMapping<Claims>,\n): Effect.fn.Return<\n  {\n    readonly statefulSessionPersistence: StatefulSessionPersistence<Claims>;\n    readonly sessionRepository: SessionRepository;\n  },\n  SessionUnavailable,\n  SqlClient.SqlClient | LifecycleHooks | SqlBatchCommit\n> {\n  const batch = yield* SqlBatchCommit;\n\n  const state = yield* normalizeSessionOperation(\n    makeNativeSessionAuthorityState(tables, mapping, batch !== undefined),\n  );\n\n  const conditionalInsert = yield* makeConditionalSqlInsert();\n  const records = yield* makeNativeSessionRecords(tables, mapping);\n  const executor = yield* makeSqlCommitExecutor(sessionUnavailable);\n  const external = yield* Effect.serviceOption(CurrentSqlCommit);\n\n  const pending =\n    mapping.pending === undefined\n      ? undefined\n      : yield* makeNativeSessionPending(\n          tables,\n          { ...mapping, ...mapping.pending },\n          batch !== undefined,\n        );\n\n  const { sql, s, table, now, exact, live } = records;\n\n  const native = <A, E, R>(\n    work: Effect.Effect<A, E, R>,\n    mode: \"transaction\" | \"statement\" = \"transaction\",\n  ) =>\n    (batch === undefined\n      ? executor.operation(normalizeSessionOperation(work), mode)\n      : executor\n          .operationBatch(normalizeSessionOperation(work))\n          .pipe(Effect.provideService(SqlBatchCommit, batch))\n    ).pipe(Effect.provideService(AuthenticationClock, state.clockPolicy));\n\n  const stage = Effect.fnUntraced(function* (statement: Statement.Fragment, expected?: number) {\n    if (batch !== undefined) {\n      yield* appendSqlBatchStatement(sql`${statement}`);\n      if (expected !== undefined)\n        yield* appendSqlBatchStatement(sqlBatchAssertion(sql, sql`changes() = ${expected}`));\n\n      return expected;\n    }\n\n    return yield* executeSqlChange(sql, statement);\n  });\n\n  const finalCondition = Effect.fnUntraced(function* (name: string, condition: Statement.Fragment) {\n    if (batch !== undefined)\n      yield* registerSqlBatchPostcondition({ name, statement: sqlBatchAssertion(sql, condition) });\n    else if (Option.isSome(external))\n      yield* registerSqlPostcondition({\n        name,\n        check: Effect.gen(function* () {\n          const rows = yield* sql`select 1 where ${condition}`;\n\n          if (!(rows.length === 1)) return yield* invalidSessionState();\n        }).pipe(\n          Effect.provideService(AuthenticationClock, state.clockPolicy),\n          Effect.catchCause((cause) =>\n            Effect.failCause(\n              Cause.map(cause, (error) =>\n                PersistenceMappingError.make({ operation: \"decode\", cause: error }),\n              ),\n            ),\n          ),\n        ),\n      });\n  });\n\n  const recordCondition = Effect.fnUntraced(function* (\n    record: StatefulSessionRecord<Claims>,\n    values: Readonly<Record<string, unknown>>,\n  ) {\n    return sql`exists(select 1 from ${table.name} where ${yield* records.owner(record)} and ${exact(table, s.securityRevision, record.securityRevision)} and ${records.millis(table, s.expiresAt)} = ${DateTime.toEpochMillis(record.expiresAt)} and ${records.millis(table, s.absoluteExpiresAt)} = ${DateTime.toEpochMillis(record.absoluteExpiresAt)} and ${records.encodedCondition(values)} and ${live(table)})`;\n  });\n\n  const classify = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n    effect.pipe(\n      Effect.catchCause((cause) =>\n        Effect.failCause<E | SessionConflict>(\n          isMappedConstraintConflict(mapping.isConstraintConflict, cause)\n            ? Cause.map(cause, () => SessionConflict.make({}))\n            : cause,\n        ),\n      ),\n    );\n\n  const [joinedIds, joinedRevisions] = yield* Effect.forEach(\n    [\n      [\n        table.unencodedTextColumn?.(s.subjectId),\n        state.subject.unencodedTextColumn?.(mapping.subject.id),\n      ],\n      [\n        table.unencodedTextColumn?.(s.securityRevision),\n        state.subject.unencodedTextColumn?.(mapping.subject.securityRevision),\n      ],\n    ],\n    canJoinTextColumns,\n  ).pipe(\n    withStorageValidation,\n    Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, sessionUnavailable))),\n  );\n\n  const subject = state.subject.as(\"verified_subject\"),\n    session = table.as(\"verified_session\"),\n    owner = mapping.subject,\n    subjectKeys = [...new Set([owner.id, owner.status, owner.securityRevision])],\n    verifiedSessionFields = session.fields(\"session_\"),\n    verifiedSubjectFields = subject.fields(\"subject_\", subjectKeys),\n    sessionFields = table.fields(\"session_\"),\n    st = state.subject.as(\"listed_subject\"),\n    list = table.as(\"listed_session\"),\n    listedSessionFields = list.fields(\"session_\"),\n    listedSubjectFields = st.fields(\"subject_\", subjectKeys);\n\n  const verify = Effect.fnUntraced(function* (digest: StatefulSessionRecord<Claims>[\"digest\"]) {\n    let discoveredSubjectId: StatefulSessionRecord<Claims>[\"subjectId\"] | undefined;\n    let nativeSubject: unknown;\n\n    if (!joinedIds) {\n      const discovered = yield* records.read(digest);\n\n      if (discovered === undefined) return undefined;\n      discoveredSubjectId = discovered.subjectId;\n      nativeSubject = yield* mapping.subjectId.toNative(discoveredSubjectId);\n    }\n\n    const owns = joinedIds\n      ? exactSqlText(sql, subject.column(owner.id), session.column(s.subjectId))\n      : sql`${state.id(subject, owner.id, nativeSubject)} and ${state.id(session, s.subjectId, nativeSubject)}`;\n\n    const revision = joinedRevisions\n      ? exactSqlText(\n          sql,\n          subject.column(owner.securityRevision),\n          session.column(s.securityRevision),\n        )\n      : sql`true`;\n\n    const rows =\n      yield* sql`select ${verifiedSessionFields}, ${verifiedSubjectFields} from ${session.name} join ${subject.name} on ${owns} and ${state.activeSubject(subject)} and ${revision} where ${exact(session, s.digest, digest)} and ${live(session)} limit 2`;\n\n    if (!(rows.length <= 1)) return yield* invalidSessionState();\n    if (rows[0] === undefined) return undefined;\n    const record = yield* records.decode(session.decode(rows[0], \"session_\"));\n    const decoded = subject.decode(rows[0], \"subject_\", subjectKeys);\n\n    if (\n      !(\n        (joinedIds || record.subjectId === discoveredSubjectId) &&\n        (yield* mapping.subjectId.toSubject(decoded[owner.id])) === record.subjectId &&\n        owner.isActiveStatus(decoded[owner.status])\n      )\n    )\n      return yield* invalidSessionState();\n\n    return decoded[owner.securityRevision] === record.securityRevision ? record : undefined;\n  });\n\n  const persistence: StatefulSessionPersistence<Claims> = {\n    establish: (input, project) =>\n      native(\n        classify(\n          Effect.gen(function* () {\n            const current = yield* state.read(input.evidence.revision.subjectId, true);\n\n            if (\n              current === undefined ||\n              !sameSessionRevision(current.revision, input.evidence.revision)\n            )\n              return yield* StaleAuthentication.make({});\n\n            const assessment = yield* sessionEvidenceDeadline(\n              input.evidence,\n              current.requirement,\n              current.now,\n            );\n\n            const issued = Math.max(\n                current.now,\n                DateTime.toEpochMillis(input.now),\n                DateTime.toEpochMillis(input.session.issuedAt),\n                ...input.evidence.proofs.map((proof) => DateTime.toEpochMillis(proof.verifiedAt)),\n              ),\n              expires = DateTime.toEpochMillis(input.session.expiresAt),\n              absolute = DateTime.toEpochMillis(input.session.absoluteExpiresAt);\n\n            if (\n              issued - current.now > state.clockPolicy.futureToleranceMillis ||\n              issued >= expires ||\n              current.now >= expires ||\n              expires > absolute\n            )\n              return yield* StaleAuthentication.make({});\n            let pendingExpiry = Infinity;\n\n            if (input.pending !== undefined) {\n              if (pending === undefined || mapping.pending === undefined)\n                return yield* PendingAuthenticationInvalid.make({});\n              const found = yield* pending.read(\"Login\", input.pending.digest);\n\n              if (\n                found === undefined ||\n                found.record.version !== input.pending.version ||\n                found.record.subjectId !== current.revision.subjectId ||\n                found.record.flowId !== input.pending.flowId ||\n                found.record.bindingDigest !== input.pending.bindingDigest\n              )\n                return yield* PendingAuthenticationInvalid.make({});\n              const original = yield* mapping.pending.login.decode(found.record.snapshot);\n\n              if (\n                original.digest !== input.pending.digest ||\n                original.version !== input.pending.version ||\n                !preservesRevision(input.evidence, original.evidence) ||\n                DateTime.toEpochMillis(original.expiresAt) !== found.record.expiresAtMillis ||\n                original.attemptLimit !== found.record.attemptLimit\n              )\n                return yield* PendingAuthenticationInvalid.make({});\n              pendingExpiry = found.record.expiresAtMillis;\n              yield* pending.consume(\"Login\", input.pending, current.native);\n            }\n\n            const nativeSession = yield* allocateSessionValue(\n              \"interactive\",\n              s.allocateId,\n              s.allocateIdSync,\n            );\n\n            const sessionId = yield* mapping.sessionId.toSession(nativeSession);\n\n            if (sessionId === input.handoffSourceSessionId) return yield* SessionConflict.make({});\n\n            const record: StatefulSessionRecord<Claims> = {\n              ...input.session,\n              sessionId,\n              subjectId: current.revision.subjectId,\n              securityRevision: current.revision.securityRevision,\n              provenance: yield* snapshotSessionAuthenticationProvenance({\n                evidence: input.evidence,\n              }),\n              issuedAt: DateTime.makeUnsafe(issued),\n            };\n\n            const deadline = Math.min(expires, assessment.validUntil, pendingExpiry);\n\n            yield* state.guardPolicy(current);\n            const condition = sql`${state.authorityCondition(current.revision, current.native)} and ${now} >= ${current.now} and ${now} < ${deadline}`;\n\n            const values = {\n              ...s.encodeInsert(record, { subjectId: current.native, sessionId: nativeSession }),\n              [s.sessionId]: nativeSession,\n              [s.subjectId]: current.native,\n              [s.digest]: record.digest,\n              [s.securityRevision]: record.securityRevision,\n              [s.issuedAt]: s.encodeInstant(record.issuedAt),\n              [s.expiresAt]: s.encodeInstant(record.expiresAt),\n              [s.absoluteExpiresAt]: s.encodeInstant(record.absoluteExpiresAt),\n            };\n\n            const changed = yield* stage(yield* conditionalInsert(table, values, condition), 1);\n\n            if (changed !== 1) return yield* StaleAuthentication.make({});\n            const final = sql`${condition} and ${yield* recordCondition(record, values)}${input.pending === undefined || pending === undefined ? sql`` : sql` and ${pending.consumedCondition(\"Login\", input.pending, current.native)}`}`;\n\n            yield* finalCondition(\"stateful-session-issuance\", final);\n            if (batch === undefined && Option.isSome(external))\n              yield* registerSqlPostcondition({\n                name: \"stateful-session-issued-metadata\",\n                check: Effect.gen(function* () {\n                  const finalRecord = yield* records.read(record.digest);\n\n                  if (!(finalRecord !== undefined && sameSessionRecord(finalRecord, record)))\n                    return yield* invalidSessionState();\n                  const authority = yield* state.read(record.subjectId);\n\n                  if (\n                    !(\n                      authority !== undefined &&\n                      sameSessionRevision(authority.revision, input.evidence.revision)\n                    )\n                  )\n                    return yield* invalidSessionState();\n                  yield* sessionEvidenceDeadline(\n                    input.evidence,\n                    authority.requirement,\n                    authority.now,\n                  );\n                }).pipe(\n                  Effect.provideService(AuthenticationClock, state.clockPolicy),\n                  Effect.catchCause((cause) =>\n                    Effect.failCause(\n                      Cause.map(cause, (error) =>\n                        PersistenceMappingError.make({ operation: \"decode\", cause: error }),\n                      ),\n                    ),\n                  ),\n                ),\n              });\n\n            return yield* prepareNativeSession(record, project);\n          }),\n        ),\n      ),\n    verify: ({ digest }) =>\n      executor.verify(verify(digest)).pipe(\n        Effect.filterOrFail(\n          (record) => !(record === undefined),\n          () => SessionInvalid.make({}),\n        ),\n      ),\n    rotate: (input, project) =>\n      native(\n        classify(\n          Effect.gen(function* () {\n            const absolute = DateTime.toEpochMillis(input.record.absoluteExpiresAt),\n              expires = DateTime.toEpochMillis(input.nextExpiresAt),\n              preparedAt = Math.max(\n                DateTime.toEpochMillis(input.now),\n                DateTime.toEpochMillis(input.record.issuedAt),\n              );\n\n            if (\n              expires > absolute ||\n              preparedAt >= expires ||\n              input.nextDigest === input.record.digest ||\n              input.nextCredentialVersion === input.record.credentialVersion\n            )\n              return yield* SessionConflict.make({});\n\n            const needsSample =\n              batch !== undefined ||\n              sql.onDialectOrElse({ mysql: () => true, orElse: () => false });\n\n            const sampled = needsSample\n              ? Number((yield* sql`select ${now} as engine_now`)[0]?.engine_now)\n              : DateTime.toEpochMillis(input.record.issuedAt);\n\n            if (!Number.isSafeInteger(sampled)) return yield* invalidSessionState();\n\n            const prepared = {\n              ...input.record,\n              digest: input.nextDigest,\n              credentialVersion: input.nextCredentialVersion,\n              expiresAt: input.nextExpiresAt,\n              issuedAt: DateTime.makeUnsafe(Math.max(sampled, preparedAt)),\n            };\n\n            const values = {\n              ...s.encodeRotation(prepared),\n              [s.digest]: prepared.digest,\n              [s.issuedAt]: tables.expression(\n                mapping.clock.fromMillis(\n                  sql`case when ${now} >= ${preparedAt} then ${now} else ${preparedAt} end`,\n                ),\n              ),\n              [s.expiresAt]: s.encodeInstant(prepared.expiresAt),\n            };\n\n            const condition = sql`${yield* records.owner(input.record)} and ${live(table)} and ${preparedAt} <= ${now} + ${state.clockPolicy.futureToleranceMillis} and ${now} < ${expires} and ${records.millis(table, s.absoluteExpiresAt)} = ${absolute}`;\n            const update = sql`${table.update(values)} where ${condition}`;\n            let record = prepared;\n\n            if (needsSample) {\n              // Batch receipts are prepared before execution. The exact sampled time is\n              // written and checked; no speculative UPDATE result is treated as committed.\n              const statement = sql`${table.update({ ...values, [s.issuedAt]: s.encodeInstant(prepared.issuedAt) })} where ${condition} and ${now} >= ${sampled}`;\n              const changed = yield* stage(statement, 1);\n\n              if (changed !== 1) return yield* SessionConflict.make({});\n            } else {\n              const rows = yield* sql`${update} returning ${sessionFields}`;\n\n              if (rows.length !== 1) return yield* SessionConflict.make({});\n              record = yield* records.decode(table.decode(rows[0]!, \"session_\"));\n            }\n            yield* finalCondition(\n              \"stateful-session-rotation\",\n              yield* recordCondition(record, {\n                ...values,\n                [s.issuedAt]: s.encodeInstant(record.issuedAt),\n              }),\n            );\n\n            return yield* prepareNativeSession(record, project);\n          }),\n        ),\n        \"statement\",\n      ),\n    revokeDigest: (digest, project) =>\n      native(\n        Effect.gen(function* () {\n          let expected: number | undefined;\n\n          if (batch !== undefined)\n            expected =\n              (yield* sql`select 1 from ${table.name} where ${exact(table, s.digest, digest)} limit 2`)\n                .length;\n\n          const changed = yield* stage(\n            sql`delete from ${table.name} where ${exact(table, s.digest, digest)}`,\n            expected,\n          );\n\n          if (!(changed !== undefined && changed <= 1)) return yield* invalidSessionState();\n          yield* finalCondition(\n            \"stateful-session-digest-revocation\",\n            sql`not exists(select 1 from ${table.name} where ${exact(table, s.digest, digest)})`,\n          );\n\n          return yield* prepareNativeSession(changed === 1, project);\n        }),\n        \"statement\",\n      ),\n    revoke: (input, project) =>\n      native(\n        Effect.gen(function* () {\n          const subject = yield* mapping.subjectId.toNative(input.subjectId),\n            session = yield* mapping.sessionId.toNative(input.sessionId);\n\n          const condition = sql`${state.id(table, s.subjectId, subject)} and ${state.id(table, s.sessionId, session)}`;\n\n          yield* stage(sql`delete from ${table.name} where ${condition}`);\n          yield* finalCondition(\n            \"stateful-session-revocation\",\n            sql`not exists(select 1 from ${table.name} where ${condition})`,\n          );\n\n          return yield* prepareNativeSession(undefined, project);\n        }),\n        \"statement\",\n      ),\n    revokeAll: (input, project) =>\n      native(\n        Effect.gen(function* () {\n          const nativeSubject = yield* mapping.subjectId.toNative(input.subjectId),\n            owner = mapping.subject;\n\n          const next = yield* allocateSessionValue(\n            \"interactive\",\n            owner.nextSecurityRevision?.(input.expectedSecurityRevision),\n            owner.nextSecurityRevisionSync === undefined\n              ? undefined\n              : () => owner.nextSecurityRevisionSync!(input.expectedSecurityRevision),\n          );\n\n          if (!(next !== input.expectedSecurityRevision)) return yield* invalidSessionState();\n\n          const changed = yield* stage(\n            sql`${state.subject.update({ [owner.securityRevision]: next })} where ${state.id(state.subject, owner.id, nativeSubject)} and ${state.activeSubject(state.subject)} and ${state.exact(state.subject, owner.securityRevision, input.expectedSecurityRevision)}`,\n            1,\n          );\n\n          if (changed !== 1) return yield* StaleAuthentication.make({});\n          yield* finalCondition(\n            \"all-session-revocation\",\n            sql`exists(select 1 from ${state.subject.name} where ${state.id(state.subject, owner.id, nativeSubject)} and ${state.exact(state.subject, owner.securityRevision, next)})`,\n          );\n\n          return yield* prepareNativeSession(undefined, project);\n        }),\n        \"statement\",\n      ),\n  };\n\n  const sessionRepository: SessionRepository = {\n    list: (input) =>\n      executor.read(\n        Effect.gen(function* () {\n          if (!(Number.isSafeInteger(input.limit) && input.limit > 0 && input.limit <= 1000))\n            return yield* invalidSessionState();\n\n          const nativeSubject = yield* mapping.subjectId.toNative(input.subjectId);\n\n          const cursor =\n            input.cursor === undefined\n              ? undefined\n              : yield* mapping.sessionId.toNative(\n                  yield* Schema.decodeEffect(SessionId)(input.cursor),\n                );\n\n          let revision: StatefulSessionRecord<Claims>[\"securityRevision\"] | undefined;\n\n          // Bind both revisions in SQL so stale rows cannot consume a page.\n          if (!joinedRevisions) {\n            const subjects =\n              yield* sql`select ${listedSubjectFields} from ${st.name} where ${state.id(st, owner.id, nativeSubject)} and ${state.activeSubject(st)} limit 2`;\n\n            if (!(subjects.length <= 1)) return yield* invalidSessionState();\n            if (subjects[0] === undefined) return { sessions: [] };\n            const subject = st.decode(subjects[0], \"subject_\", subjectKeys);\n\n            if (!((yield* mapping.subjectId.toSubject(subject[owner.id])) === input.subjectId))\n              return yield* invalidSessionState();\n            revision = yield* Schema.decodeUnknownEffect(SessionMetadata.fields.securityRevision)(\n              subject[owner.securityRevision],\n            );\n          }\n\n          // Keep the owner in the page snapshot even when its discovered revision changed.\n          // Retry that read once; continued authority changes are not pagination exhaustion.\n          for (let attempt = 0; attempt < 2; attempt++) {\n            const currentRevision = joinedRevisions\n              ? exactSqlText(\n                  sql,\n                  st.column(owner.securityRevision),\n                  list.column(s.securityRevision),\n                )\n              : sql`${state.exact(st, owner.securityRevision, revision)} and ${exact(list, s.securityRevision, revision)}`;\n\n            const rows =\n              yield* sql`select ${listedSessionFields}, ${listedSubjectFields}, ${list.column(s.subjectId)} as session_owner from ${st.name} left join ${list.name} on ${state.id(list, s.subjectId, nativeSubject)} and ${currentRevision} and ${live(list)}${cursor === undefined ? sql`` : sql` and ${list.column(s.sessionId)} > ${list.value(s.sessionId, cursor)}`} where ${state.id(st, owner.id, nativeSubject)} and ${state.activeSubject(st)} order by ${list.column(s.sessionId)} limit ${input.limit + 1}`;\n\n            const first = rows[0];\n\n            if (first === undefined) return { sessions: [] };\n            if (!joinedRevisions) {\n              const subject = st.decode(first, \"subject_\", subjectKeys);\n\n              if (!((yield* mapping.subjectId.toSubject(subject[owner.id])) === input.subjectId))\n                return yield* invalidSessionState();\n\n              const current = yield* Schema.decodeUnknownEffect(\n                SessionMetadata.fields.securityRevision,\n              )(subject[owner.securityRevision]);\n\n              if (current !== revision) {\n                revision = current;\n                continue;\n              }\n            }\n            if (first.session_owner === null) return { sessions: [] };\n\n            const decoded = yield* Effect.forEach(rows.slice(0, input.limit), (row) =>\n              Effect.gen(function* () {\n                const record = yield* records.decode(list.decode(row, \"session_\"));\n                const subject = st.decode(row, \"subject_\", subjectKeys);\n\n                if (\n                  !(\n                    record.subjectId === input.subjectId &&\n                    (yield* mapping.subjectId.toSubject(subject[owner.id])) === input.subjectId &&\n                    subject[owner.securityRevision] === record.securityRevision\n                  )\n                )\n                  return yield* invalidSessionState();\n\n                return yield* Schema.decodeEffect(Schema.toType(SessionMetadata))(record);\n              }),\n            );\n\n            const nextCursor = rows.length > input.limit ? decoded.at(-1)?.sessionId : undefined;\n\n            return { sessions: decoded, ...(nextCursor === undefined ? {} : { nextCursor }) };\n          }\n\n          return yield* sessionUnavailable();\n        }),\n      ),\n  };\n\n  return { statefulSessionPersistence: persistence, sessionRepository };\n});\n"],"mappings":"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"}