httpapi

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2026 License: AGPL-3.0 Imports: 42 Imported by: 0

Documentation

Overview

Package httpapi (piece ①) serves the REST API (huma, OpenAPI 3.1), live events (SSE), the MCP endpoint, health checks and the embedded web UI.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ICal

func ICal(cal app.CalendarView, name string, now time.Time) string

ICal renders events as an iCalendar document (RFC 5545): all-day events, stable UIDs so calendar apps update instead of duplicating.

func New

func New(svc *app.Service, cfg Config) (http.Handler, huma.API, error)

New returns the HTTP handler and the huma API (for exporting OpenAPI).

Types

type AssistantOutcome

type AssistantOutcome assistant.Outcome

The API names its schemas after the Go types. These give the assistant's their own names in the OpenAPI document ("AssistantStatus", not "Status").

type AssistantSettings

type AssistantSettings assistant.Settings

The API names its schemas after the Go types. These give the assistant's their own names in the OpenAPI document ("AssistantStatus", not "Status").

type AssistantStatus

type AssistantStatus assistant.Status

The API names its schemas after the Go types. These give the assistant's their own names in the OpenAPI document ("AssistantStatus", not "Status").

type AssistantTerms

type AssistantTerms assistant.TermsProposal

AssistantTerms is what a document says about a subscription's contract.

type AssistantTest

type AssistantTest assistant.TestResult

The API names its schemas after the Go types. These give the assistant's their own names in the OpenAPI document ("AssistantStatus", not "Status").

type AssistantTurn

type AssistantTurn assistant.Turn

The API names its schemas after the Go types. These give the assistant's their own names in the OpenAPI document ("AssistantStatus", not "Status").

type AssistantUsage

type AssistantUsage assistant.UsageList

The API names its schemas after the Go types. These give the assistant's their own names in the OpenAPI document ("AssistantStatus", not "Status").

type AuthSession

type AuthSession struct {
	SetupRequired  bool         `json:"setupRequired" doc:"nobody can sign in yet: show the setup wizard"`
	SetupNeedsCode bool         `json:"setupNeedsCode" doc:"the wizard must ask for the setup code (request not from the server's machine)"`
	HasHousehold   bool         `json:"hasHousehold" doc:"a household exists (made with exhale init); setup only creates the owner's login"`
	User           *SessionUser `json:"user,omitempty"`
	Language       string       `json:"language,omitempty" doc:"the language to show the signed-in person: their own, else the household's"`
	TelegramBot    string       `json:"telegramBot,omitempty" doc:"username of the Telegram bot, when Telegram is enabled"`
	SSO            *SSOInfo     `` /* 133-byte string literal not displayed */
	// PasswordLoginDisabled hides the password forms: sign-in, sign-up and
	// join only go through the provider.
	PasswordLoginDisabled bool `json:"passwordLoginDisabled" doc:"password sign-in is turned off: only show single sign-on"`
	Assistant             bool `json:"assistant" doc:"the built-in assistant is on: show Ask Exhale"`
	// TwoFactor is set by a sign-in whose password was right and that now
	// needs a code (ADR 0025).
	TwoFactor *TwoFactorStep `json:"twoFactor,omitempty" doc:"the password was right; send a code to /api/v1/auth/login/two-factor to finish signing in"`
}

AuthSession tells the web what to show: the setup wizard, the sign-in page or the app.

type Config

type Config struct {
	Version string
	// TrustLocal lets requests from this machine act as the household owner
	// without signing in (development and scripts). Off by default since web
	// sign-in shipped.
	TrustLocal bool
	// SecureCookies marks the session cookie Secure; set it when Exhale is
	// served over HTTPS (behind a reverse proxy).
	SecureCookies bool
	// Telegram configures and reports the household's bot (nil when not
	// available, e.g. in tests).
	Telegram TelegramControl
	// Channels runs the notify-only channels: email, ntfy and webhooks
	// (nil when not available, e.g. when exporting the OpenAPI document).
	Channels *notifiers.Manager
	// Slack configures and reports the team's Slack app (nil when not
	// available, e.g. in tests).
	Slack SlackControl
	// Assistant is the model Exhale itself uses (ADR 0018, part B). When
	// nil, one is made that is off until an owner sets it up in the web.
	Assistant *assistant.Assistant
	Log       *slog.Logger
	// PublicURL is the address people reach Exhale at, e.g.
	// https://exhale.example.com. Single sign-on builds its redirect URI
	// from it; without it only this machine's own address works.
	PublicURL string
	// OIDC enables sign-in with an OpenID Connect provider (nil: off).
	OIDC *auth.OIDC
	// DisablePasswordLogin turns password sign-in off. Only honoured when
	// OIDC is set.
	DisablePasswordLogin bool
	// OAuth is the authorization server of remote MCP (ADR 0024). When nil
	// one is made over the service's store; tests pass their own clock.
	OAuth *oauth.Service
}

Config configures the HTTP server.

type ConnectedApps

type ConnectedApps struct {
	Apps []oauth.App `json:"apps"`
	// MCPURL is the address to give a cloud assistant; empty when the
	// server has no public URL.
	MCPURL string `json:"mcpUrl" doc:"the MCP address to give Claude.ai, ChatGPT or Grok; empty without EXHALE_PUBLIC_URL"`
}

ConnectedApps lists the applications connected over OAuth.

type FeedStatus

type FeedStatus struct {
	Enabled   bool   `json:"enabled"`
	CreatedAt string `json:"createdAt,omitempty"`
	// Path is returned only when the link is created: Exhale keeps a hash.
	Path string `json:"path,omitempty" doc:"Path of the feed, shown once. Prefix it with the address of this Exhale."`
}

FeedStatus says whether the member has a calendar link.

type ImportReviewOut

type ImportReviewOut struct {
	Waiting bool              `json:"waiting"`
	Review  *assistant.Review `json:"review,omitempty"`
}

ImportReviewOut is the import waiting from a chat, if any.

type MemberDone

type MemberDone struct {
	OK bool `json:"ok"`
}

MemberDone confirms a change to the members.

type OAuthRequestInfo

type OAuthRequestInfo struct {
	ClientName   string `json:"clientName"`
	Verified     bool   `` /* 146-byte string literal not displayed */
	ClientHost   string `json:"clientHost,omitempty" doc:"host of that address, when verified"`
	ClientURI    string `json:"clientUri,omitempty" doc:"the application's home page, as it describes itself"`
	RedirectHost string `json:"redirectHost" doc:"where the browser goes after the answer"`
	Loopback     bool   `json:"loopback" doc:"the answer goes to a program on this computer"`
	MaxScope     string `json:"maxScope" enum:"read,write" doc:"the most the application asked for; the person may give less"`
	MemberName   string `json:"memberName" doc:"the application will act as this member"`
}

OAuthRequestInfo is what the consent screen shows.

type SSOInfo

type SSOInfo struct {
	Name string `json:"name" doc:"what the sign-in button says after \"Continue with\""`
}

SSOInfo describes the configured OpenID Connect provider.

type SessionUser

type SessionUser struct {
	ID          string      `json:"id"`
	Name        string      `json:"name"`
	Email       string      `json:"email"`
	Role        domain.Role `json:"role"`
	HasPassword bool        `json:"hasPassword" doc:"the account has a password (accounts made through single sign-on have none)"`
	SSOHost     string      `json:"ssoHost,omitempty" doc:"host of the identity provider this account is linked to, if any"`
	Locale      string      `json:"locale,omitempty" doc:"the language this person chose; empty: the household's"`
}

SessionUser is the signed-in person.

type SlackConfig

type SlackConfig slack.Config

SlackStatus and SlackConfig name the Slack types in the API contract.

type SlackControl

type SlackControl interface {
	Status(ctx context.Context) slack.Status
	Configure(ctx context.Context, in slack.Config) (slack.Status, error)
	Remove(ctx context.Context) (slack.Status, error)
}

SlackControl configures the team's own Slack app from the web (ADR 0007, 0019). Like the Telegram endpoints it is not in the op catalog: agents never handle tokens.

type SlackLinkCode

type SlackLinkCode struct {
	Code    string    `json:"code"`
	Command string    `json:"command" doc:"what to type in Slack, anywhere"`
	URL     string    `json:"url,omitempty" doc:"link that opens the app in Slack, when it is connected"`
	Expires time.Time `json:"expiresAt"`
}

SlackLinkCode is a one-time code that links a Slack account to a member.

type SlackStatus

type SlackStatus slack.Status

SlackStatus and SlackConfig name the Slack types in the API contract.

type TelegramControl

type TelegramControl interface {
	Status(ctx context.Context) telegram.BotStatus
	Configure(ctx context.Context, token string) (telegram.BotStatus, error)
	Remove(ctx context.Context) (telegram.BotStatus, error)
	Username() string
}

TelegramControl configures the household's own Telegram bot from the web (ADR 0019). Like the auth endpoints it is not in the op catalog: agents never handle bot tokens.

type TwoFactorStep

type TwoFactorStep struct {
	Token     string    `json:"token" doc:"send it back with the code; it works for a few minutes"`
	ExpiresAt time.Time `json:"expiresAt"`
}

TwoFactorStep is the pending login a code finishes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL