import type { AuthPairingLink, ServerAuthBootstrapMethod } from "@t3tools/contracts"; import * as Data from "effect/Data"; import * as DateTime from "effect/DateTime"; import * as Duration from "effect/Duration"; import * as Context from "effect/Context"; import type * as Effect from "effect/Effect"; import type * as Stream from "effect/Stream"; export type BootstrapCredentialRole = "owner" | "client"; export interface BootstrapGrant { readonly method: ServerAuthBootstrapMethod; readonly role: BootstrapCredentialRole; readonly subject: string; readonly label?: string; readonly expiresAt: DateTime.DateTime; } export class BootstrapCredentialError extends Data.TaggedError("BootstrapCredentialError")<{ readonly message: string; readonly status?: 401 | 500; readonly cause?: unknown; }> {} export interface IssuedBootstrapCredential { readonly id: string; readonly credential: string; readonly label?: string; readonly expiresAt: DateTime.Utc; } export type BootstrapCredentialChange = | { readonly type: "pairingLinkUpserted"; readonly pairingLink: AuthPairingLink; } | { readonly type: "pairingLinkRemoved"; readonly id: string; }; export interface BootstrapCredentialServiceShape { readonly issueOneTimeToken: (input?: { readonly ttl?: Duration.Duration; readonly role?: BootstrapCredentialRole; readonly subject?: string; readonly label?: string; }) => Effect.Effect; readonly listActive: () => Effect.Effect< ReadonlyArray, BootstrapCredentialError >; readonly streamChanges: Stream.Stream; readonly revoke: (id: string) => Effect.Effect; readonly consume: (credential: string) => Effect.Effect; } export class BootstrapCredentialService extends Context.Service< BootstrapCredentialService, BootstrapCredentialServiceShape >()("t3/auth/Services/BootstrapCredentialService") {}