{"version":3,"file":"session-native-step-up.mjs","names":[],"sources":["../../src/internal/session-native-step-up.ts"],"sourcesContent":["import type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport { AuthenticationClock } from \"@yielded/auth/Operations\";\nimport {\n  SessionConflict,\n  SessionStepUpInvalid,\n  StaleAuthentication,\n  type SessionStepUpPersistence,\n  type SessionStepUpIntent,\n  type StatefulSessionRecord,\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 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 { SessionStepUpMapping } from \"./models/step-up-model\";\nimport type { NativeSqlTables } from \"./native-sql-table\";\nimport { sessionEvidenceDeadline } from \"./session-native-authority\";\nimport { prepareNativeSession, type StoredSessionPending } from \"./session-native-pending\";\nimport { makeNativeSessionPendingReader } from \"./session-native-pending-read\";\nimport {\n  makeNativeSessionRecords,\n  sameSessionRecord,\n  makeConditionalSqlInsert,\n} from \"./session-native-record\";\nimport {\n  sameSessionRevision,\n  normalizeSessionOperation,\n  invalidSessionState,\n  sessionUnavailable,\n} from \"./session-native-state\";\nimport { allocateSessionValue } from \"./session-policy\";\nimport {\n  CurrentSqlCommit,\n  makeSqlCommitExecutor,\n  SqlBatchCommit,\n  registerSqlPostcondition,\n  registerSqlBatchPostcondition,\n} from \"./sql-commit\";\nimport {\n  encodeStepUpIntent,\n  decodeStepUpIntent,\n  stepUpIntentLive,\n  validateStepUpPlan,\n} from \"./step-up-state\";\nimport type { AnyTableModel } from \"./table-model\";\n\nexport type NativeSessionStepUpMapping<Claims> = SessionStepUpMapping<\n  Claims,\n  AnyTableModel,\n  AnyTableModel,\n  AnyTableModel,\n  AnyTableModel,\n  AnyTableModel,\n  unknown,\n  unknown\n>;\n\nexport const makeNativeSessionStepUpServices = Effect.fnUntraced(function* <Claims>(\n  tables: NativeSqlTables,\n  mapping: NativeSessionStepUpMapping<Claims>,\n): Effect.fn.Return<\n  { readonly sessionStepUpPersistence: SessionStepUpPersistence<Claims> },\n  SessionUnavailable,\n  SqlClient.SqlClient | LifecycleHooks | SqlBatchCommit\n> {\n  const batch = yield* SqlBatchCommit;\n\n  const {\n    state,\n    pending,\n    read: readPending,\n  } = yield* normalizeSessionOperation(\n    makeNativeSessionPendingReader(tables, mapping, batch !== undefined),\n  );\n\n  const conditionalInsert = yield* makeConditionalSqlInsert();\n\n  const records =\n    mapping.source.kind === \"Stateful\"\n      ? yield* makeNativeSessionRecords(tables, { ...mapping, ...mapping.source })\n      : undefined;\n\n  const executor = yield* makeSqlCommitExecutor(sessionUnavailable),\n    external = yield* Effect.serviceOption(CurrentSqlCommit);\n\n  const { sql, now } = state;\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 decode = Effect.fnUntraced(function* (stored: StoredSessionPending) {\n    const intent = yield* decodeStepUpIntent(stored.snapshot);\n\n    if (\n      !(\n        intent.digest === stored.digest &&\n        intent.version === stored.version &&\n        intent.flowId === stored.flowId &&\n        intent.bindingDigest === stored.bindingDigest &&\n        intent.revision.subjectId === stored.subjectId &&\n        DateTime.toEpochMillis(intent.expiresAt) === stored.expiresAtMillis &&\n        intent.attemptLimit === stored.attemptLimit\n      )\n    )\n      return yield* invalidSessionState();\n\n    return intent;\n  });\n\n  const source = Effect.fnUntraced(function* (\n    intent: Omit<SessionStepUpIntent, \"version\">,\n    instant: number,\n  ) {\n    if (!(yield* stepUpIntentLive(intent, mapping.source.kind, DateTime.makeUnsafe(instant))))\n      return undefined;\n    const subject = yield* mapping.subjectId.toNative(intent.revision.subjectId);\n\n    if (mapping.source.kind === \"Stateful\") {\n      if (!(records !== undefined)) return yield* invalidSessionState();\n\n      const nativeSession = yield* mapping.source.sessionId.toNative(intent.sourceSessionId),\n        { s, table } = records;\n\n      const rows =\n        yield* sql`select ${table.fields(\"source_\")} from ${table.name} where ${state.id(table, s.subjectId, subject)} and ${state.id(table, s.sessionId, nativeSession)} and ${records.live(table)} limit 2`;\n\n      if (!(rows.length <= 1)) return yield* invalidSessionState();\n      if (rows[0] === undefined) return undefined;\n      const record = yield* records.decode(table.decode(rows[0], \"source_\"));\n\n      if (\n        record.credentialVersion !== intent.sourceCredentialVersion ||\n        record.subjectId !== intent.revision.subjectId ||\n        record.sessionId !== intent.sourceSessionId ||\n        record.securityRevision !== intent.revision.securityRevision ||\n        DateTime.toEpochMillis(record.assurance.authenticatedAt) !==\n          DateTime.toEpochMillis(intent.sourceAuthenticatedAt) ||\n        DateTime.toEpochMillis(record.expiresAt) !==\n          DateTime.toEpochMillis(intent.sourceExpiresAt) ||\n        DateTime.toEpochMillis(record.absoluteExpiresAt) !==\n          DateTime.toEpochMillis(intent.sourceAbsoluteExpiresAt)\n      )\n        return undefined;\n\n      return {\n        record,\n        condition: sql`exists(select 1 from ${table.name} where ${yield* records.owner(record)} and ${records.live(table)})`,\n      };\n    }\n    if (mapping.source.kind === \"StateAssistedSigned\") {\n      const t = mapping.source.tombstone,\n        table = tables(t.table),\n        session = yield* mapping.source.sessionId.toNative(intent.sourceSessionId);\n\n      const condition = sql`not exists(select 1 from ${table.name} where ${state.exact(table, t.moduleId, mapping.moduleId)} and ${state.id(table, t.subjectId, subject)} and ${state.id(table, t.sessionId, session)})`;\n\n      if ((yield* sql`select 1 where ${condition}`).length !== 1) return undefined;\n\n      return { record: undefined, condition };\n    }\n\n    return { record: undefined, condition: sql`1 = 1` };\n  });\n\n  const final = 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          if (!((yield* sql`select 1 where ${condition}`).length === 1))\n            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 snapshotCondition = (intent: SessionStepUpIntent, snapshot: string) =>\n    sql.and([\n      state.exact(pending.table, pending.p.snapshot, snapshot),\n      sql`${tables.expression(mapping.clock.toMillis(pending.table.column(pending.p.expiresAt)))} = ${DateTime.toEpochMillis(intent.expiresAt)}`,\n      sql`${pending.table.column(pending.p.attemptLimit)} = ${pending.table.value(pending.p.attemptLimit, intent.attemptLimit)}`,\n    ]);\n\n  const sessionStepUpPersistence: SessionStepUpPersistence<Claims> = {\n    create: (input, _now, project) =>\n      native(\n        Effect.gen(function* () {\n          const current = yield* state.read(input.revision.subjectId, true);\n\n          if (current === undefined || !sameSessionRevision(current.revision, input.revision))\n            return yield* StaleAuthentication.make({});\n          const original = yield* source(input, current.now);\n\n          if (original === undefined) return yield* StaleAuthentication.make({});\n\n          const version = yield* allocateSessionValue(\n            \"interactive\",\n            mapping.pending.allocateVersion,\n            mapping.pending.allocateVersionSync,\n          );\n\n          const intent = { ...input, version },\n            snapshot = yield* encodeStepUpIntent(intent);\n\n          yield* state.guardPolicy(current);\n          const condition = sql`${state.authorityCondition(intent.revision, current.native)} and ${original.condition} and ${now} >= ${current.now} and ${DateTime.toEpochMillis(intent.sourceAuthenticatedAt)} <= ${now} + ${state.clockPolicy.futureToleranceMillis} and ${now} < ${DateTime.toEpochMillis(intent.expiresAt)}`;\n\n          yield* pending\n            .insert(\n              {\n                moduleId: mapping.moduleId,\n                kind: \"StepUp\",\n                digest: intent.digest,\n                version,\n                flowId: intent.flowId,\n                subjectId: current.native,\n                bindingDigest: intent.bindingDigest,\n                snapshot,\n                expiresAt: intent.expiresAt,\n                attemptLimit: intent.attemptLimit,\n              },\n              condition,\n            )\n            .pipe(\n              Effect.catchCause((cause) =>\n                Effect.failCause<SessionConflict | Cause.Cause.Error<typeof cause>>(\n                  isMappedConstraintConflict(mapping.isConstraintConflict, cause)\n                    ? Cause.map(cause, () => SessionConflict.make({}))\n                    : cause,\n                ),\n              ),\n            );\n          yield* final(\n            \"session-step-up-issuance\",\n            sql`${condition} and exists(select 1 from ${pending.table.name} where ${pending.predicate(pending.table, \"StepUp\", intent.digest)} and ${state.exact(pending.table, pending.p.version, version)} and ${snapshotCondition(intent, snapshot)})`,\n          );\n\n          return yield* prepareNativeSession(intent, project);\n        }),\n      ),\n    read: ({ digest }) =>\n      executor\n        .read(\n          Effect.gen(function* () {\n            const selected = yield* readPending(\"StepUp\", digest);\n\n            if (selected === undefined) return undefined;\n\n            const intent = yield* decode(selected.record),\n              current = selected.authority;\n\n            if (\n              !sameSessionRevision(current.revision, intent.revision) ||\n              !(yield* stepUpIntentLive(\n                intent,\n                mapping.source.kind,\n                DateTime.makeUnsafe(current.now),\n              ))\n            )\n              return undefined;\n\n            // The detached source stays original. Its live digest and metadata\n            // are rechecked by complete before any replacement is committed.\n            return { intent, requirement: current.requirement };\n          }),\n        )\n        .pipe(\n          Effect.provideService(AuthenticationClock, state.clockPolicy),\n          Effect.filterOrFail(\n            (value) => !(value === undefined),\n            () => SessionStepUpInvalid.make({}),\n          ),\n        ),\n    reject: ({ digest }, project) =>\n      native(\n        Effect.gen(function* () {\n          yield* pending.reject(\"StepUp\", digest);\n\n          return yield* prepareNativeSession({ _tag: \"Rejected\" } as const, project);\n        }),\n        \"statement\",\n      ),\n    complete: (plan, project) =>\n      native(\n        Effect.gen(function* () {\n          yield* validateStepUpPlan(plan);\n          const { intent, evidence, replacement } = plan;\n          const current = yield* state.read(intent.revision.subjectId, true);\n\n          if (\n            current === undefined ||\n            !sameSessionRevision(current.revision, evidence.revision) ||\n            !sameSessionRevision(current.revision, intent.revision)\n          )\n            return yield* StaleAuthentication.make({});\n          const original = yield* source(intent, current.now);\n\n          if (original === undefined) return yield* SessionStepUpInvalid.make({});\n          if (plan.source.guard._tag === \"Stateful\") {\n            if (\n              original.record === undefined ||\n              original.record.digest !== plan.source.guard.digest ||\n              !sameSessionRecord(original.record, {\n                ...plan.source.inspection.session,\n                provenance: plan.source.inspection.provenance,\n                credentialVersion: plan.source.inspection.credentialVersion,\n                digest: plan.source.guard.digest,\n              })\n            )\n              return yield* SessionStepUpInvalid.make({});\n          }\n\n          const prepared = yield* sessionEvidenceDeadline(\n              evidence,\n              plan.baseRequirement,\n              current.now,\n            ),\n            base = yield* sessionEvidenceDeadline(evidence, current.requirement, current.now),\n            profile = yield* sessionEvidenceDeadline(evidence, intent.requirement, current.now);\n\n          const deadline = Math.min(\n            prepared.validUntil,\n            base.validUntil,\n            profile.validUntil,\n            DateTime.toEpochMillis(intent.expiresAt),\n            DateTime.toEpochMillis(replacement.inspection.session.expiresAt),\n          );\n\n          if (\n            current.now >= deadline ||\n            DateTime.toEpochMillis(replacement.inspection.session.issuedAt) - current.now >\n              state.clockPolicy.futureToleranceMillis ||\n            DateTime.toEpochMillis(replacement.inspection.session.expiresAt) >\n              DateTime.toEpochMillis(intent.sourceAbsoluteExpiresAt)\n          )\n            return yield* SessionStepUpInvalid.make({});\n          const snapshot = yield* encodeStepUpIntent(intent);\n\n          yield* state.guardPolicy(current);\n          const authority = sql`${state.authorityCondition(evidence.revision, current.native)} and ${now} >= ${current.now} and ${now} < ${deadline}`;\n\n          yield* pending.consume(\n            \"StepUp\",\n            intent,\n            current.native,\n            sql`${snapshotCondition(intent, snapshot)} and ${authority} and ${original.condition}`,\n          );\n          let replacementCondition: Statement.Fragment = sql`1 = 1`;\n          let replacementRecord: StatefulSessionRecord<Claims> | undefined;\n\n          if (replacement._tag === \"Stateful\" && mapping.source.kind === \"Stateful\") {\n            if (!(records !== undefined && original.record !== undefined))\n              return yield* invalidSessionState();\n\n            const next: StatefulSessionRecord<Claims> = {\n              ...replacement.inspection.session,\n              digest: replacement.nextDigest,\n              credentialVersion: replacement.inspection.credentialVersion,\n              provenance: replacement.inspection.provenance,\n            };\n\n            if (\n              next.digest === original.record.digest ||\n              next.credentialVersion === original.record.credentialVersion\n            )\n              return yield* SessionStepUpInvalid.make({});\n            const { s, table } = records;\n\n            const values = {\n              ...s.encodeRotation(next),\n              [s.digest]: next.digest,\n              [s.issuedAt]: s.encodeInstant(next.issuedAt),\n              [s.expiresAt]: s.encodeInstant(next.expiresAt),\n              [s.absoluteExpiresAt]: s.encodeInstant(next.absoluteExpiresAt),\n              [s.securityRevision]: next.securityRevision,\n            };\n\n            yield* pending.stage(\n              sql`${table.update(values)} where ${yield* records.owner(original.record)} and ${records.live(table)} and ${authority}`,\n              1,\n            );\n            replacementCondition = sql`exists(select 1 from ${table.name} where ${yield* records.owner(next)} and ${records.encodedCondition(values)} and ${records.live(table)})`;\n            replacementRecord = next;\n          } else if (\n            replacement._tag === \"StateAssistedSigned\" &&\n            mapping.source.kind === \"StateAssistedSigned\"\n          ) {\n            const t = mapping.source.tombstone,\n              table = tables(t.table),\n              session = yield* mapping.source.sessionId.toNative(intent.sourceSessionId);\n\n            const values = {\n              ...t.encodeInsert({\n                moduleId: mapping.moduleId,\n                subjectId: current.native,\n                sessionId: session,\n                absoluteExpiresAt: intent.sourceAbsoluteExpiresAt,\n              }),\n              [t.moduleId]: mapping.moduleId,\n              [t.subjectId]: current.native,\n              [t.sessionId]: session,\n              [t.absoluteExpiresAt]: t.encodeInstant(intent.sourceAbsoluteExpiresAt),\n            };\n\n            yield* pending.stage(\n              yield* conditionalInsert(table, values, sql`${authority} and ${original.condition}`),\n              1,\n            );\n            replacementCondition = sql`exists(select 1 from ${table.name} where ${state.exact(table, t.moduleId, mapping.moduleId)} and ${state.id(table, t.subjectId, current.native)} and ${state.id(table, t.sessionId, session)} and ${tables.expression(mapping.clock.toMillis(table.column(t.absoluteExpiresAt)))} >= ${DateTime.toEpochMillis(intent.sourceAbsoluteExpiresAt)})`;\n          } else if (\n            replacement._tag !== \"StatelessSigned\" ||\n            mapping.source.kind !== \"StatelessSigned\"\n          )\n            return yield* SessionStepUpInvalid.make({});\n          yield* final(\n            \"session-step-up-completion\",\n            sql`${authority} and ${pending.consumedCondition(\"StepUp\", intent, current.native)} and ${replacementCondition}`,\n          );\n          if (batch === undefined && Option.isSome(external))\n            yield* registerSqlPostcondition({\n              name: \"session-step-up-current-policy\",\n              check: Effect.gen(function* () {\n                const actual = yield* state.read(intent.revision.subjectId);\n\n                if (\n                  !(actual !== undefined && sameSessionRevision(actual.revision, evidence.revision))\n                )\n                  return yield* invalidSessionState();\n                yield* sessionEvidenceDeadline(evidence, plan.baseRequirement, actual.now);\n                yield* sessionEvidenceDeadline(evidence, actual.requirement, actual.now);\n                yield* sessionEvidenceDeadline(evidence, intent.requirement, actual.now);\n                if (replacementRecord !== undefined && records !== undefined) {\n                  const row = yield* records.read(replacementRecord.digest);\n\n                  if (!(row !== undefined && sameSessionRecord(row, replacementRecord)))\n                    return yield* invalidSessionState();\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(replacement.inspection, project);\n        }),\n      ),\n  };\n\n  return { sessionStepUpPersistence };\n});\n"],"mappings":"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"}