import { Schema } from "effect"; import { AuthSessionId, TrimmedNonEmptyString } from "./baseSchemas"; /** * Declares the server's overall authentication posture. * * This is a high-level policy label that tells clients how the environment is * expected to be accessed, not a transport detail and not an exhaustive list * of every accepted credential. * * Typical usage: * - rendered in auth/pairing UI so the user understands what kind of * environment they are connecting to * - used by clients to decide whether silent desktop bootstrap is expected or * whether an explicit pairing flow should be shown * * Meanings: * - `desktop-managed-local`: local desktop-managed environment with narrow * trusted bootstrap, intended to avoid login prompts on the same machine * - `loopback-browser`: standalone local server intended for browser pairing on * the same machine * - `remote-reachable`: environment intended to be reached from other devices * or networks, where explicit pairing/auth is expected * - `unsafe-no-auth`: intentionally unauthenticated mode; this is an explicit * unsafe escape hatch, not a normal deployment mode */export const ServerAuthPolicy = Schema.Literals([ "desktop-managed-local", "loopback-browser", "remote-reachable", "unsafe-no-auth",]);export type ServerAuthPolicy = typeof ServerAuthPolicy.Type; /** * A credential type that can be exchanged for a real authenticated session. * * Bootstrap methods are for establishing trust at the start of a connection or * pairing flow. They are not the long-lived credential used for ordinary * authenticated HTTP / WebSocket traffic after pairing succeeds. * * Current methods: * - `desktop-bootstrap`: a trusted local desktop handoff, used so the desktop * shell can pair the renderer without a login screen * - `one-time-token`: a short-lived pairing token, suitable for manual pairing * flows such as `/pair?token=...` */export const ServerAuthBootstrapMethod = Schema.Literals(["desktop-bootstrap", "one-time-token"]);export type ServerAuthBootstrapMethod = typeof ServerAuthBootstrapMethod.Type; /** * A credential type accepted for steady-state authenticated requests after a * client has already paired. * * These methods are used by the server-wide auth layer for privileged HTTP and * WebSocket access. They are distinct from bootstrap methods so clients can * reason clearly about "pair first, then use session auth". * * Current methods: * - `browser-session-cookie`: cookie-backed browser session, used by the web * app after bootstrap/pairing * - `bearer-session-token`: token-based session suitable for non-cookie or * non-browser clients */export const ServerAuthSessionMethod = Schema.Literals([ "browser-session-cookie", "bearer-session-token",]);export type ServerAuthSessionMethod = typeof ServerAuthSessionMethod.Type; export const AuthSessionRole = Schema.Literals(["owner", "client"]);export type AuthSessionRole = typeof AuthSessionRole.Type; /** * Server-advertised auth capabilities for a specific execution environment. * * Clients should treat this as the authoritative description of how that * environment expects to be paired and how authenticated requests should be * made afterward. * * Field meanings: * - `policy`: high-level auth posture for the environment * - `bootstrapMethods`: pairing/bootstrap methods the server is currently * willing to accept * - `sessionMethods`: authenticated request/session methods the server supports * once pairing is complete * - `sessionCookieName`: cookie name clients should expect when * `browser-session-cookie` is in use * * This descriptor is intentionally capability-oriented. It lets clients choose * the right UX without embedding server-specific auth logic or assuming a * single access method. */export const ServerAuthDescriptor = Schema.Struct({ policy: ServerAuthPolicy, bootstrapMethods: Schema.Array(ServerAuthBootstrapMethod), sessionMethods: Schema.Array(ServerAuthSessionMethod), sessionCookieName: TrimmedNonEmptyString,});export type ServerAuthDescriptor = typeof ServerAuthDescriptor.Type; export const AuthBootstrapInput = Schema.Struct({ credential: TrimmedNonEmptyString,});export type AuthBootstrapInput = typeof AuthBootstrapInput.Type; export const AuthBootstrapResult = Schema.Struct({ authenticated: Schema.Literal(true), role: AuthSessionRole, sessionMethod: ServerAuthSessionMethod, expiresAt: Schema.DateTimeUtc,});export type AuthBootstrapResult = typeof AuthBootstrapResult.Type; export const AuthBearerBootstrapResult = Schema.Struct({ authenticated: Schema.Literal(true), role: AuthSessionRole, sessionMethod: Schema.Literal("bearer-session-token"), expiresAt: Schema.DateTimeUtc, sessionToken: TrimmedNonEmptyString,});export type AuthBearerBootstrapResult = typeof AuthBearerBootstrapResult.Type; export const AuthWebSocketTokenResult = Schema.Struct({ token: TrimmedNonEmptyString, expiresAt: Schema.DateTimeUtc,});export type AuthWebSocketTokenResult = typeof AuthWebSocketTokenResult.Type; export const AuthPairingCredentialResult = Schema.Struct({ id: TrimmedNonEmptyString, credential: TrimmedNonEmptyString, label: Schema.optionalKey(TrimmedNonEmptyString), expiresAt: Schema.DateTimeUtc,});export type AuthPairingCredentialResult = typeof AuthPairingCredentialResult.Type; export const AuthPairingLink = Schema.Struct({ id: TrimmedNonEmptyString, credential: TrimmedNonEmptyString, role: AuthSessionRole, subject: TrimmedNonEmptyString, label: Schema.optionalKey(TrimmedNonEmptyString), createdAt: Schema.DateTimeUtc, expiresAt: Schema.DateTimeUtc,});export type AuthPairingLink = typeof AuthPairingLink.Type; export const AuthClientMetadataDeviceType = Schema.Literals([ "desktop", "mobile", "tablet", "bot", "unknown",]);export type AuthClientMetadataDeviceType = typeof AuthClientMetadataDeviceType.Type; export const AuthClientMetadata = Schema.Struct({ label: Schema.optionalKey(TrimmedNonEmptyString), ipAddress: Schema.optionalKey(TrimmedNonEmptyString), userAgent: Schema.optionalKey(TrimmedNonEmptyString), deviceType: AuthClientMetadataDeviceType, os: Schema.optionalKey(TrimmedNonEmptyString), browser: Schema.optionalKey(TrimmedNonEmptyString),});export type AuthClientMetadata = typeof AuthClientMetadata.Type; export const AuthClientSession = Schema.Struct({ sessionId: AuthSessionId, subject: TrimmedNonEmptyString, role: AuthSessionRole, method: ServerAuthSessionMethod, client: AuthClientMetadata, issuedAt: Schema.DateTimeUtc, expiresAt: Schema.DateTimeUtc, lastConnectedAt: Schema.NullOr(Schema.DateTimeUtc), connected: Schema.Boolean, current: Schema.Boolean,});export type AuthClientSession = typeof AuthClientSession.Type; export const AuthAccessSnapshot = Schema.Struct({ pairingLinks: Schema.Array(AuthPairingLink), clientSessions: Schema.Array(AuthClientSession),});export type AuthAccessSnapshot = typeof AuthAccessSnapshot.Type; export const AuthAccessStreamSnapshotEvent = Schema.Struct({ version: Schema.Literal(1), revision: Schema.Number, type: Schema.Literal("snapshot"), payload: AuthAccessSnapshot,});export type AuthAccessStreamSnapshotEvent = typeof AuthAccessStreamSnapshotEvent.Type; export const AuthAccessStreamPairingLinkUpsertedEvent = Schema.Struct({ version: Schema.Literal(1), revision: Schema.Number, type: Schema.Literal("pairingLinkUpserted"), payload: AuthPairingLink,});export type AuthAccessStreamPairingLinkUpsertedEvent = typeof AuthAccessStreamPairingLinkUpsertedEvent.Type; export const AuthAccessStreamPairingLinkRemovedEvent = Schema.Struct({ version: Schema.Literal(1), revision: Schema.Number, type: Schema.Literal("pairingLinkRemoved"), payload: Schema.Struct({ id: TrimmedNonEmptyString, }),});export type AuthAccessStreamPairingLinkRemovedEvent = typeof AuthAccessStreamPairingLinkRemovedEvent.Type; export const AuthAccessStreamClientUpsertedEvent = Schema.Struct({ version: Schema.Literal(1), revision: Schema.Number, type: Schema.Literal("clientUpserted"), payload: AuthClientSession,});export type AuthAccessStreamClientUpsertedEvent = typeof AuthAccessStreamClientUpsertedEvent.Type; export const AuthAccessStreamClientRemovedEvent = Schema.Struct({ version: Schema.Literal(1), revision: Schema.Number, type: Schema.Literal("clientRemoved"), payload: Schema.Struct({ sessionId: AuthSessionId, }),});export type AuthAccessStreamClientRemovedEvent = typeof AuthAccessStreamClientRemovedEvent.Type; export const AuthAccessStreamEvent = Schema.Union([ AuthAccessStreamSnapshotEvent, AuthAccessStreamPairingLinkUpsertedEvent, AuthAccessStreamPairingLinkRemovedEvent, AuthAccessStreamClientUpsertedEvent, AuthAccessStreamClientRemovedEvent,]);export type AuthAccessStreamEvent = typeof AuthAccessStreamEvent.Type; export const AuthRevokePairingLinkInput = Schema.Struct({ id: TrimmedNonEmptyString,});export type AuthRevokePairingLinkInput = typeof AuthRevokePairingLinkInput.Type; export const AuthRevokeClientSessionInput = Schema.Struct({ sessionId: AuthSessionId,});export type AuthRevokeClientSessionInput = typeof AuthRevokeClientSessionInput.Type; export const AuthCreatePairingCredentialInput = Schema.Struct({ label: Schema.optionalKey(TrimmedNonEmptyString),});export type AuthCreatePairingCredentialInput = typeof AuthCreatePairingCredentialInput.Type; export const AuthSessionState = Schema.Struct({ authenticated: Schema.Boolean, auth: ServerAuthDescriptor, role: Schema.optionalKey(AuthSessionRole), sessionMethod: Schema.optionalKey(ServerAuthSessionMethod), expiresAt: Schema.optionalKey(Schema.DateTimeUtc),});export type AuthSessionState = typeof AuthSessionState.Type;
import { Schema } from "effect";
import { AuthSessionId, TrimmedNonEmptyString } from "./baseSchemas";
/**
* Declares the server's overall authentication posture.
*
* This is a high-level policy label that tells clients how the environment is
* expected to be accessed, not a transport detail and not an exhaustive list
* of every accepted credential.
*
* Typical usage:
* - rendered in auth/pairing UI so the user understands what kind of
* environment they are connecting to
* - used by clients to decide whether silent desktop bootstrap is expected or
* whether an explicit pairing flow should be shown
*
* Meanings:
* - `desktop-managed-local`: local desktop-managed environment with narrow
* trusted bootstrap, intended to avoid login prompts on the same machine
* - `loopback-browser`: standalone local server intended for browser pairing on
* the same machine
* - `remote-reachable`: environment intended to be reached from other devices
* or networks, where explicit pairing/auth is expected
* - `unsafe-no-auth`: intentionally unauthenticated mode; this is an explicit
* unsafe escape hatch, not a normal deployment mode
*/
export const ServerAuthPolicy = Schema.Literals([
"desktop-managed-local",
"loopback-browser",
"remote-reachable",
"unsafe-no-auth",
]);
export type ServerAuthPolicy = typeof ServerAuthPolicy.Type;
/**
* A credential type that can be exchanged for a real authenticated session.
*
* Bootstrap methods are for establishing trust at the start of a connection or
* pairing flow. They are not the long-lived credential used for ordinary
* authenticated HTTP / WebSocket traffic after pairing succeeds.
*
* Current methods:
* - `desktop-bootstrap`: a trusted local desktop handoff, used so the desktop
* shell can pair the renderer without a login screen
* - `one-time-token`: a short-lived pairing token, suitable for manual pairing
* flows such as `/pair?token=...`
*/
export const ServerAuthBootstrapMethod = Schema.Literals(["desktop-bootstrap", "one-time-token"]);
export type ServerAuthBootstrapMethod = typeof ServerAuthBootstrapMethod.Type;
/**
* A credential type accepted for steady-state authenticated requests after a
* client has already paired.
*
* These methods are used by the server-wide auth layer for privileged HTTP and
* WebSocket access. They are distinct from bootstrap methods so clients can
* reason clearly about "pair first, then use session auth".
*
* Current methods:
* - `browser-session-cookie`: cookie-backed browser session, used by the web
* app after bootstrap/pairing
* - `bearer-session-token`: token-based session suitable for non-cookie or
* non-browser clients
*/
export const ServerAuthSessionMethod = Schema.Literals([
"browser-session-cookie",
"bearer-session-token",
]);
export type ServerAuthSessionMethod = typeof ServerAuthSessionMethod.Type;
export const AuthSessionRole = Schema.Literals(["owner", "client"]);
export type AuthSessionRole = typeof AuthSessionRole.Type;
/**
* Server-advertised auth capabilities for a specific execution environment.
*
* Clients should treat this as the authoritative description of how that
* environment expects to be paired and how authenticated requests should be
* made afterward.
*
* Field meanings:
* - `policy`: high-level auth posture for the environment
* - `bootstrapMethods`: pairing/bootstrap methods the server is currently
* willing to accept
* - `sessionMethods`: authenticated request/session methods the server supports
* once pairing is complete
* - `sessionCookieName`: cookie name clients should expect when
* `browser-session-cookie` is in use
*
* This descriptor is intentionally capability-oriented. It lets clients choose
* the right UX without embedding server-specific auth logic or assuming a
* single access method.
*/
export const ServerAuthDescriptor = Schema.Struct({
policy: ServerAuthPolicy,
bootstrapMethods: Schema.Array(ServerAuthBootstrapMethod),
sessionMethods: Schema.Array(ServerAuthSessionMethod),
sessionCookieName: TrimmedNonEmptyString,
});
export type ServerAuthDescriptor = typeof ServerAuthDescriptor.Type;
export const AuthBootstrapInput = Schema.Struct({
credential: TrimmedNonEmptyString,
});
export type AuthBootstrapInput = typeof AuthBootstrapInput.Type;
export const AuthBootstrapResult = Schema.Struct({
authenticated: Schema.Literal(true),
role: AuthSessionRole,
sessionMethod: ServerAuthSessionMethod,
expiresAt: Schema.DateTimeUtc,
});
export type AuthBootstrapResult = typeof AuthBootstrapResult.Type;
export const AuthBearerBootstrapResult = Schema.Struct({
authenticated: Schema.Literal(true),
role: AuthSessionRole,
sessionMethod: Schema.Literal("bearer-session-token"),
expiresAt: Schema.DateTimeUtc,
sessionToken: TrimmedNonEmptyString,
});
export type AuthBearerBootstrapResult = typeof AuthBearerBootstrapResult.Type;
export const AuthWebSocketTokenResult = Schema.Struct({
token: TrimmedNonEmptyString,
expiresAt: Schema.DateTimeUtc,
});
export type AuthWebSocketTokenResult = typeof AuthWebSocketTokenResult.Type;
export const AuthPairingCredentialResult = Schema.Struct({
id: TrimmedNonEmptyString,
credential: TrimmedNonEmptyString,
label: Schema.optionalKey(TrimmedNonEmptyString),
expiresAt: Schema.DateTimeUtc,
});
export type AuthPairingCredentialResult = typeof AuthPairingCredentialResult.Type;
export const AuthPairingLink = Schema.Struct({
id: TrimmedNonEmptyString,
credential: TrimmedNonEmptyString,
role: AuthSessionRole,
subject: TrimmedNonEmptyString,
label: Schema.optionalKey(TrimmedNonEmptyString),
createdAt: Schema.DateTimeUtc,
expiresAt: Schema.DateTimeUtc,
});
export type AuthPairingLink = typeof AuthPairingLink.Type;
export const AuthClientMetadataDeviceType = Schema.Literals([
"desktop",
"mobile",
"tablet",
"bot",
"unknown",
]);
export type AuthClientMetadataDeviceType = typeof AuthClientMetadataDeviceType.Type;
export const AuthClientMetadata = Schema.Struct({
label: Schema.optionalKey(TrimmedNonEmptyString),
ipAddress: Schema.optionalKey(TrimmedNonEmptyString),
userAgent: Schema.optionalKey(TrimmedNonEmptyString),
deviceType: AuthClientMetadataDeviceType,
os: Schema.optionalKey(TrimmedNonEmptyString),
browser: Schema.optionalKey(TrimmedNonEmptyString),
});
export type AuthClientMetadata = typeof AuthClientMetadata.Type;
export const AuthClientSession = Schema.Struct({
sessionId: AuthSessionId,
subject: TrimmedNonEmptyString,
role: AuthSessionRole,
method: ServerAuthSessionMethod,
client: AuthClientMetadata,
issuedAt: Schema.DateTimeUtc,
expiresAt: Schema.DateTimeUtc,
lastConnectedAt: Schema.NullOr(Schema.DateTimeUtc),
connected: Schema.Boolean,
current: Schema.Boolean,
});
export type AuthClientSession = typeof AuthClientSession.Type;
export const AuthAccessSnapshot = Schema.Struct({
pairingLinks: Schema.Array(AuthPairingLink),
clientSessions: Schema.Array(AuthClientSession),
});
export type AuthAccessSnapshot = typeof AuthAccessSnapshot.Type;
export const AuthAccessStreamSnapshotEvent = Schema.Struct({
version: Schema.Literal(1),
revision: Schema.Number,
type: Schema.Literal("snapshot"),
payload: AuthAccessSnapshot,
});
export type AuthAccessStreamSnapshotEvent = typeof AuthAccessStreamSnapshotEvent.Type;
export const AuthAccessStreamPairingLinkUpsertedEvent = Schema.Struct({
version: Schema.Literal(1),
revision: Schema.Number,
type: Schema.Literal("pairingLinkUpserted"),
payload: AuthPairingLink,
});
export type AuthAccessStreamPairingLinkUpsertedEvent =
typeof AuthAccessStreamPairingLinkUpsertedEvent.Type;
export const AuthAccessStreamPairingLinkRemovedEvent = Schema.Struct({
version: Schema.Literal(1),
revision: Schema.Number,
type: Schema.Literal("pairingLinkRemoved"),
payload: Schema.Struct({
id: TrimmedNonEmptyString,
}),
});
export type AuthAccessStreamPairingLinkRemovedEvent =
typeof AuthAccessStreamPairingLinkRemovedEvent.Type;
export const AuthAccessStreamClientUpsertedEvent = Schema.Struct({
version: Schema.Literal(1),
revision: Schema.Number,
type: Schema.Literal("clientUpserted"),
payload: AuthClientSession,
});
export type AuthAccessStreamClientUpsertedEvent = typeof AuthAccessStreamClientUpsertedEvent.Type;
export const AuthAccessStreamClientRemovedEvent = Schema.Struct({
version: Schema.Literal(1),
revision: Schema.Number,
type: Schema.Literal("clientRemoved"),
payload: Schema.Struct({
sessionId: AuthSessionId,
}),
});
export type AuthAccessStreamClientRemovedEvent = typeof AuthAccessStreamClientRemovedEvent.Type;
export const AuthAccessStreamEvent = Schema.Union([
AuthAccessStreamSnapshotEvent,
AuthAccessStreamPairingLinkUpsertedEvent,
AuthAccessStreamPairingLinkRemovedEvent,
AuthAccessStreamClientUpsertedEvent,
AuthAccessStreamClientRemovedEvent,
]);
export type AuthAccessStreamEvent = typeof AuthAccessStreamEvent.Type;
export const AuthRevokePairingLinkInput = Schema.Struct({
id: TrimmedNonEmptyString,
});
export type AuthRevokePairingLinkInput = typeof AuthRevokePairingLinkInput.Type;
export const AuthRevokeClientSessionInput = Schema.Struct({
sessionId: AuthSessionId,
});
export type AuthRevokeClientSessionInput = typeof AuthRevokeClientSessionInput.Type;
export const AuthCreatePairingCredentialInput = Schema.Struct({
label: Schema.optionalKey(TrimmedNonEmptyString),
});
export type AuthCreatePairingCredentialInput = typeof AuthCreatePairingCredentialInput.Type;
export const AuthSessionState = Schema.Struct({
authenticated: Schema.Boolean,
auth: ServerAuthDescriptor,
role: Schema.optionalKey(AuthSessionRole),
sessionMethod: Schema.optionalKey(ServerAuthSessionMethod),
expiresAt: Schema.optionalKey(Schema.DateTimeUtc),
});
export type AuthSessionState = typeof AuthSessionState.Type;