api

package
v0.0.0-...-797efe3 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: GPL-3.0 Imports: 45 Imported by: 0

README

API Package

The internal/api package provides HTTP API utilities for the Subcults API server, including standardized error handling.

Error Handling

Overview

All API errors return a standardized JSON format:

{
  "error": {
    "code": "error_code",
    "message": "Human-readable error message"
  }
}

This ensures consistent error handling across all API endpoints and simplifies client-side error processing.

Usage
Basic Error Response
package main

import (
    "net/http"
    "github.com/onnwee/subcults/internal/api"
    "github.com/onnwee/subcults/internal/middleware"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Set error code in context for logging middleware
    ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeNotFound)
    
    // Write error response
    api.WriteError(w, ctx, http.StatusNotFound, api.ErrCodeNotFound, "Scene not found")
}
Common Error Codes

The package provides the following predefined error codes:

Constant Code HTTP Status Description
ErrCodeValidation validation_error 400 Input validation failure
ErrCodeBadRequest bad_request 400 Malformed request
ErrCodeInvalidTimeRange invalid_time_range 400 Event start time not before end time
ErrCodeAuthFailed auth_failed 401 Authentication failure
ErrCodeForbidden forbidden 403 Request is forbidden
ErrCodeNotFound not_found 404 Resource not found
ErrCodeConflict conflict 409 Conflict with current state
ErrCodeRateLimited rate_limited 429 Rate limit exceeded
ErrCodeInternal internal_error 500 Internal server error
Status Code Mapping

Use StatusCodeMapping() to get the recommended HTTP status code for a given error code:

status := api.StatusCodeMapping(api.ErrCodeValidation)
// Returns http.StatusBadRequest (400)
Integration with Logging Middleware

The error handling system integrates seamlessly with the logging middleware:

  1. Set error code in context using middleware.SetErrorCode()
  2. Write error response using api.WriteError()
  3. Logging middleware automatically captures the error code for 4xx and 5xx responses

Example:

func handler(w http.ResponseWriter, r *http.Request) {
    // Error code is set in context
    ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeValidation)
    
    // WriteError sends the response
    api.WriteError(w, ctx, http.StatusBadRequest, api.ErrCodeValidation, "Invalid email format")
    
    // Logging middleware will automatically log:
    // - status: 400
    // - error_code: validation_error
    // - request_id, user_did (if present)
}
Security Considerations
  • Never expose internal stack traces in error messages
  • Avoid leaking sensitive information in error details
  • Use generic messages for internal errors (e.g., "Internal server error")
  • Provide specific messages for client errors (e.g., "Invalid email format")
Examples
Validation Error
ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeValidation)
api.WriteError(w, ctx, http.StatusBadRequest, api.ErrCodeValidation, "Email field is required")

Response:

{
  "error": {
    "code": "validation_error",
    "message": "Email field is required"
  }
}
Authentication Error
ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeAuthFailed)
api.WriteError(w, ctx, http.StatusUnauthorized, api.ErrCodeAuthFailed, "Invalid or expired token")

Response:

{
  "error": {
    "code": "auth_failed",
    "message": "Invalid or expired token"
  }
}
Not Found Error
ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeNotFound)
api.WriteError(w, ctx, http.StatusNotFound, api.ErrCodeNotFound, "Scene not found")

Response:

{
  "error": {
    "code": "not_found",
    "message": "Scene not found"
  }
}
Internal Error
// Log detailed error internally
slog.Error("database query failed", "error", err, "query", query)

// Return generic error to client
ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeInternal)
api.WriteError(w, ctx, http.StatusInternalServerError, api.ErrCodeInternal, "Internal server error")

Response:

{
  "error": {
    "code": "internal_error",
    "message": "Internal server error"
  }
}

Testing

The package includes comprehensive unit tests covering:

  • Basic error response formatting
  • All error code constants
  • Content-Type headers
  • JSON structure validation
  • Integration with logging middleware
  • Request ID propagation
  • Special characters in error messages
  • Empty messages
  • Full end-to-end integration tests

Run tests:

go test -v -race -cover ./internal/api/...

Future Enhancements

  • Error code validation in CI (grep check or lint rule)
  • Additional error codes as needed
  • Error response localization (i18n)
  • Structured error details (e.g., field-level validation errors)

Documentation

Overview

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for canary deployment management.

Package api provides HTTP API utilities including standardized error handling.

Package api provides HTTP API utilities including standardized error handling.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP API handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for stream participant WebSocket subscriptions.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for the Subcults API.

Package api provides HTTP handlers for upload operations.

Index

Constants

View Source
const (
	// ErrCodeValidation indicates input validation failure.
	ErrCodeValidation = "validation_error"

	// ErrCodeAuthFailed indicates authentication failure.
	ErrCodeAuthFailed = "auth_failed"

	// ErrCodeNotFound indicates the requested resource was not found.
	ErrCodeNotFound = "not_found"

	// ErrCodeRateLimited indicates rate limit exceeded.
	ErrCodeRateLimited = "rate_limited"

	// ErrCodeInternal indicates an internal server error.
	ErrCodeInternal = "internal_error"

	// ErrCodeForbidden indicates the request is forbidden.
	ErrCodeForbidden = "forbidden"

	// ErrCodeConflict indicates a conflict with the current state.
	ErrCodeConflict = "conflict"

	// ErrCodeBadRequest indicates a malformed request.
	ErrCodeBadRequest = "bad_request"

	// ErrCodeInvalidPalette indicates an invalid palette configuration.
	ErrCodeInvalidPalette = "invalid_palette"

	// ErrCodeSceneDeleted indicates the scene has been deleted.
	ErrCodeSceneDeleted = "scene_deleted"

	// ErrCodeInvalidSceneName indicates scene name validation failure.
	ErrCodeInvalidSceneName = "invalid_scene_name"

	// ErrCodeDuplicateSceneName indicates scene name already exists for owner.
	ErrCodeDuplicateSceneName = "duplicate_scene_name"

	// ErrCodeInvalidTimeRange indicates event start time is not before end time.
	ErrCodeInvalidTimeRange = "invalid_time_range"

	// ErrCodeMissingTarget indicates post must have at least one of scene_id or event_id.
	ErrCodeMissingTarget = "missing_target"

	// ErrCodeUnsupportedType indicates an unsupported content type for upload.
	ErrCodeUnsupportedType = "unsupported_type"

	// ErrCodeInvalidWeight indicates alliance weight must be between 0.0 and 1.0.
	ErrCodeInvalidWeight = "invalid_weight"

	// ErrCodeAllianceDeleted indicates the alliance has been deleted.
	ErrCodeAllianceDeleted = "alliance_deleted"

	// ErrCodeSelfAlliance indicates attempt to create alliance where from_scene_id == to_scene_id.
	ErrCodeSelfAlliance = "self_alliance"

	// ErrCodeSceneNotFound indicates the scene was not found.
	ErrCodeSceneNotFound = "scene_not_found"

	// ErrCodeUnauthorized is an alias of ErrCodeAuthFailed for 401-style auth errors.
	ErrCodeUnauthorized = ErrCodeAuthFailed

	// ErrCodePaymentNotFound indicates the payment record was not found.
	ErrCodePaymentNotFound = "payment_not_found"
)

Common error codes used throughout the API.

View Source
const (
	ErrCodeInvalidModerationStatus = "invalid_moderation_status"
	ErrCodeModerationExists        = "moderation_already_exists"
)

Moderation-specific error codes.

View Source
const (
	ErrCodeAlreadyOnboarded = "already_onboarded"
	ErrCodeNotOnboarded     = "not_onboarded"
)

Payment-specific error codes.

View Source
const (
	MaxBboxAreaDegrees = 10.0 // Max bbox area in square degrees (~1000km x 1000km at equator)
	MaxSearchLimit     = 50   // Max results per page
	DefaultSearchLimit = 20   // Default results if not specified
	MaxGlobalLimit     = 25
)

Constants for bbox validation

Variables

This section is empty.

Functions

func CSPReportHandler

func CSPReportHandler() http.HandlerFunc

CSPReportHandler returns an http.HandlerFunc that accepts Content-Security-Policy violation reports and logs them via structured logging.

func MapDomainError

func MapDomainError(err error) (int, string, string, bool)

MapDomainError looks up a domain sentinel error in the registered mappings. It uses errors.Is to walk the error chain, so wrapped errors match their sentinels. Returns (status, code, message, true) if found, or zero values and false otherwise.

func RegisterATProtoRoutes

func RegisterATProtoRoutes(mux *http.ServeMux, deps *RouteDeps, h *ATProtoOAuthHandlers, identityService *identity.Service)

RegisterATProtoRoutes registers all AT Protocol OAuth routes on the given mux. Should only be called when atprotoOAuthHandlers is non-nil. identityService is required for RequireCreator middleware on publish endpoint.

func RegisterAllianceRoutes

func RegisterAllianceRoutes(mux *http.ServeMux, deps *RouteDeps, h *AllianceHandlers)

RegisterAllianceRoutes registers all alliance-related routes on the given mux.

func RegisterDomainError

func RegisterDomainError(target error, status int, code string, message string)

RegisterDomainError adds a sentinel error to the centralized mapping table. Callers should register errors at init time or early in main().

func RegisterEventRoutes

func RegisterEventRoutes(mux *http.ServeMux, deps *RouteDeps, h *EventHandlers, rsvpH *RSVPHandlers, postH *PostHandlers, protectedLocationH *ProtectedLocationHandlers)

RegisterEventRoutes registers all event-related routes on the given mux.

func RegisterIdentityRoutes

func RegisterIdentityRoutes(mux *http.ServeMux, deps *RouteDeps, h *IdentityAuthHandlers)

RegisterIdentityRoutes registers all identity/auth-related routes on the given mux.

func RegisterPostRoutes

func RegisterPostRoutes(mux *http.ServeMux, deps *RouteDeps, h *PostHandlers)

RegisterPostRoutes registers all post-related routes on the given mux.

func RegisterSceneRoutes

func RegisterSceneRoutes(mux *http.ServeMux, deps *RouteDeps, h *SceneHandlers, postH *PostHandlers, membershipH *MembershipHandlers)

RegisterSceneRoutes registers all scene-related routes on the given mux.

func RegisterSearchRoutes

func RegisterSearchRoutes(mux *http.ServeMux, deps *RouteDeps, h *SearchHandlers, eventH *EventHandlers)

RegisterSearchRoutes registers all search-related routes on the given mux.

func RegisterSignalRoutes

func RegisterSignalRoutes(mux *http.ServeMux, deps *RouteDeps, h *SignalHandlers)

RegisterSignalRoutes registers all signal-related routes on the given mux.

func RegisterStreamRoutes

func RegisterStreamRoutes(mux *http.ServeMux, deps *RouteDeps, h *StreamHandlers)

RegisterStreamRoutes registers all stream-related routes on the given mux.

func RegisterTouringRoutes

func RegisterTouringRoutes(mux *http.ServeMux, deps *RouteDeps, h *TouringHandlers, identityService *identity.Service)

RegisterTouringRoutes registers all touring-related routes on the given mux. identityService is required for RequireCreator middleware on studio routes.

func RequireCreator

func RequireCreator(identityService *identity.Service) func(http.HandlerFunc) http.HandlerFunc

RequireCreator returns middleware that ensures the authenticated user has creator or admin role.

func StatusCodeMapping

func StatusCodeMapping(code string) int

StatusCodeMapping returns the recommended HTTP status code for common error codes. This is a convenience function to map error codes to HTTP status codes.

func WriteAPIError

func WriteAPIError(w http.ResponseWriter, ctx context.Context, err error)

WriteAPIError maps a domain error to its HTTP equivalent and writes the response. When the error is a registered domain sentinel, it uses the pre-configured status, code, and message. Unknown errors produce a generic 500 Internal Server Error.

Handlers that need the mapped values directly (e.g. conditional logging) should use MapDomainError instead.

func WriteError

func WriteError(w http.ResponseWriter, ctx context.Context, status int, code, message string)

WriteError writes a standardized JSON error response. It writes the appropriate HTTP status code and returns a JSON error body.

Format: {"error": {"code": "error_code", "message": "Error description"}}

The error_code will be automatically logged by the logging middleware for all 4xx and 5xx responses if you call SetErrorCode on the context and pass the updated context to WriteError.

Example:

ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeNotFound)
WriteError(w, ctx, http.StatusNotFound, api.ErrCodeNotFound, "Scene not found")

Or in a handler with middleware:

func handler(w http.ResponseWriter, r *http.Request) {
    ctx := middleware.SetErrorCode(r.Context(), api.ErrCodeNotFound)
    api.WriteError(w, ctx, http.StatusNotFound, api.ErrCodeNotFound, "Scene not found")
}

Types

type ATProtoOAuthHandlers

type ATProtoOAuthHandlers struct {
	// contains filtered or unexported fields
}

ATProtoOAuthHandlers exposes metadata and authenticated linking operations.

func NewATProtoOAuthHandlers

func NewATProtoOAuthHandlers(service *atprotocol.OAuthService, provisioning *atprotocol.ProvisioningService) *ATProtoOAuthHandlers

NewATProtoOAuthHandlers creates AT Protocol OAuth HTTP handlers.

func (*ATProtoOAuthHandlers) Callback

Callback completes the PDS authorization redirect.

func (*ATProtoOAuthHandlers) ClientMetadata

func (h *ATProtoOAuthHandlers) ClientMetadata(w http.ResponseWriter, r *http.Request)

ClientMetadata serves the OAuth client metadata document.

func (*ATProtoOAuthHandlers) JWKS

JWKS serves the confidential client's public signing key.

func (*ATProtoOAuthHandlers) Projection

func (h *ATProtoOAuthHandlers) Projection(w http.ResponseWriter, r *http.Request)

Projection returns public indexing state for a canonical AT URI.

func (*ATProtoOAuthHandlers) Provision

func (h *ATProtoOAuthHandlers) Provision(w http.ResponseWriter, r *http.Request)

Provision issues a guarded single-use invitation without receiving a password.

func (*ATProtoOAuthHandlers) Publish

Publish writes a server-serialized Studio entity to the linked creator PDS.

func (*ATProtoOAuthHandlers) SetSyncPassword

func (h *ATProtoOAuthHandlers) SetSyncPassword(password string)

SetSyncPassword enables the private Tap webhook using HTTP Basic auth.

func (*ATProtoOAuthHandlers) Start

Start begins identity linking.

func (*ATProtoOAuthHandlers) Status

Status returns the current link without exposing session secrets.

func (*ATProtoOAuthHandlers) Sync

Sync accepts authenticated Tap webhook events and acknowledges only after a durable observation or quarantine record has been committed.

Unlink revokes the OAuth session while preserving local drafts.

func (*ATProtoOAuthHandlers) Upgrade

Upgrade requests the exact canonical repository scopes.

type AccountHandlers

type AccountHandlers struct {
	// contains filtered or unexported fields
}

AccountHandlers provides endpoints for user account data export and deletion.

func NewAccountHandlers

func NewAccountHandlers(repo retention.Repository, gracePeriod time.Duration) *AccountHandlers

NewAccountHandlers creates new account handler instances.

func (*AccountHandlers) DeleteAccount

func (h *AccountHandlers) DeleteAccount(w http.ResponseWriter, r *http.Request)

DeleteAccount handles POST /api/account/delete Schedules account deletion with a grace period.

func (*AccountHandlers) ExportAccountData

func (h *AccountHandlers) ExportAccountData(w http.ResponseWriter, r *http.Request)

ExportAccountData handles GET /api/account/export Returns all personal data for the authenticated user as JSON.

type AllianceHandlers

type AllianceHandlers struct {
	// contains filtered or unexported fields
}

AllianceHandlers holds dependencies for alliance HTTP handlers.

func NewAllianceHandlers

func NewAllianceHandlers(
	allianceService *alliance.Service,
	sceneRepo scene.SceneRepository,
	trustDataSource trust.DataSource,
	trustDirtyTracker *trust.DirtyTracker,
) *AllianceHandlers

NewAllianceHandlers creates a new AllianceHandlers instance.

func (*AllianceHandlers) CreateAlliance

func (h *AllianceHandlers) CreateAlliance(w http.ResponseWriter, r *http.Request)

CreateAlliance handles POST /alliances - creates a new alliance.

func (*AllianceHandlers) DeleteAlliance

func (h *AllianceHandlers) DeleteAlliance(w http.ResponseWriter, r *http.Request)

DeleteAlliance handles DELETE /alliances/{id} - soft-deletes an alliance.

func (*AllianceHandlers) GetAlliance

func (h *AllianceHandlers) GetAlliance(w http.ResponseWriter, r *http.Request)

GetAlliance handles GET /alliances/{id} - retrieves an alliance by ID.

func (*AllianceHandlers) UpdateAlliance

func (h *AllianceHandlers) UpdateAlliance(w http.ResponseWriter, r *http.Request)

UpdateAlliance handles PATCH /alliances/{id} - updates an existing alliance.

type CanaryHandler

type CanaryHandler struct {
	// contains filtered or unexported fields
}

CanaryHandler handles canary deployment management endpoints.

func NewCanaryHandler

func NewCanaryHandler(router *middleware.CanaryRouter, logger *slog.Logger) *CanaryHandler

NewCanaryHandler creates a new canary handler.

func (*CanaryHandler) GetMetrics

func (h *CanaryHandler) GetMetrics(w http.ResponseWriter, r *http.Request)

GetMetrics returns current canary deployment metrics. GET /canary/metrics

func (*CanaryHandler) ResetMetrics

func (h *CanaryHandler) ResetMetrics(w http.ResponseWriter, r *http.Request)

ResetMetrics resets the canary metrics window. POST /canary/metrics/reset

func (*CanaryHandler) Rollback

func (h *CanaryHandler) Rollback(w http.ResponseWriter, r *http.Request)

Rollback triggers a manual rollback of the canary deployment. POST /canary/rollback

type CancelEventRequest

type CancelEventRequest struct {
	Reason *string `json:"reason,omitempty"`
}

CancelEventRequest represents the request body for cancelling an event.

type CheckoutItemRequest

type CheckoutItemRequest struct {
	PriceID  string `json:"price_id"`
	Quantity int64  `json:"quantity"`
}

CheckoutItemRequest represents a line item in the checkout.

type CheckoutSessionRequest

type CheckoutSessionRequest struct {
	SceneID    string                `json:"scene_id"`
	EventID    *string               `json:"event_id,omitempty"`
	Items      []CheckoutItemRequest `json:"items"`
	SuccessURL string                `json:"success_url"`
	CancelURL  string                `json:"cancel_url"`
}

CheckoutSessionRequest represents the request body for creating a Stripe Checkout Session.

type CheckoutSessionResponse

type CheckoutSessionResponse struct {
	SessionURL string `json:"session_url"`
	SessionID  string `json:"session_id"`
}

CheckoutSessionResponse represents the response for a successful checkout session creation.

type CreateAllianceRequest

type CreateAllianceRequest struct {
	FromSceneID string  `json:"from_scene_id"`
	ToSceneID   string  `json:"to_scene_id"`
	Weight      float64 `json:"weight"`
	Reason      *string `json:"reason,omitempty"`
}

CreateAllianceRequest represents the request body for creating an alliance.

type CreateEventRequest

type CreateEventRequest struct {
	SceneID        string       `json:"scene_id"`
	Title          string       `json:"title"`
	Description    string       `json:"description,omitempty"`
	AllowPrecise   bool         `json:"allow_precise"`
	PrecisePoint   *scene.Point `json:"precise_point,omitempty"`
	CoarseGeohash  string       `json:"coarse_geohash"`
	Tags           []string     `json:"tags,omitempty"`
	StartsAt       time.Time    `json:"starts_at"`
	EndsAt         *time.Time   `json:"ends_at,omitempty"`
	LocationAccess string       `json:"location_access,omitempty"`
	PlaceID        *string      `json:"place_id,omitempty"`
	VenueID        *string      `json:"venue_id,omitempty"`
	Kind           string       `json:"kind,omitempty"`
}

CreateEventRequest represents the request body for creating an event.

type CreatePostRequest

type CreatePostRequest struct {
	SceneID     *string           `json:"scene_id,omitempty"`
	EventID     *string           `json:"event_id,omitempty"`
	Text        string            `json:"text"`
	Attachments []post.Attachment `json:"attachments,omitempty"`
	Labels      []string          `json:"labels,omitempty"`
}

CreatePostRequest represents the request body for creating a post.

type CreateSceneRequest

type CreateSceneRequest struct {
	Name          string         `json:"name"`
	Description   string         `json:"description,omitempty"`
	OwnerDID      string         `json:"owner_did"`
	AllowPrecise  bool           `json:"allow_precise"`
	PrecisePoint  *scene.Point   `json:"precise_point,omitempty"`
	CoarseGeohash string         `json:"coarse_geohash"`
	Tags          []string       `json:"tags,omitempty"`
	Visibility    string         `json:"visibility,omitempty"`
	Palette       *scene.Palette `json:"palette,omitempty"`
}

CreateSceneRequest represents the request body for creating a scene.

type CreateSignalRequest

type CreateSignalRequest struct {
	ID                 string          `json:"id"`
	OwnerType          string          `json:"owner_type"`
	OwnerID            string          `json:"owner_id"`
	TargetType         string          `json:"target_type"`
	TargetID           string          `json:"target_id"`
	Subject            string          `json:"subject"`
	Body               string          `json:"body"`
	DeepLink           string          `json:"deep_link,omitempty"`
	AudienceDefinition json.RawMessage `json:"audience_definition"`
	ConsentScopeIDs    []string        `json:"consent_scope_ids,omitempty"`
}

type CreateStreamRequest

type CreateStreamRequest struct {
	SceneID *string `json:"scene_id,omitempty"`
	EventID *string `json:"event_id,omitempty"`
}

CreateStreamRequest represents the request body for creating a stream session.

type DeleteAccountRequest

type DeleteAccountRequest struct {
	Confirm bool `json:"confirm"`
}

DeleteAccountRequest represents the request to delete an account.

type DomainErrorMapping

type DomainErrorMapping struct {
	// Target is the sentinel error to match against using errors.Is.
	Target error
	// Status is the HTTP status code.
	Status int
	// Code is the machine-readable error code returned in the JSON body.
	Code string
	// Message is the human-readable description returned in the JSON body.
	Message string
}

DomainErrorMapping associates a sentinel error with its HTTP representation.

type ErrorDetail

type ErrorDetail struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

ErrorDetail contains the error code and human-readable message.

type ErrorLoggerHandlers

type ErrorLoggerHandlers struct {
	// contains filtered or unexported fields
}

ErrorLoggerHandlers provides the endpoint for client-side error collection.

func NewErrorLoggerHandlers

func NewErrorLoggerHandlers(store telemetry.Store, metrics *telemetry.Metrics) *ErrorLoggerHandlers

NewErrorLoggerHandlers creates a new error logger handler.

func (*ErrorLoggerHandlers) HandleClientError

func (h *ErrorLoggerHandlers) HandleClientError(w http.ResponseWriter, r *http.Request)

HandleClientError handles POST /api/log/client-error. Accepts client-side error reports with optional session replay data. Always returns 200 OK — error logging must never fail the client.

type ErrorResponse

type ErrorResponse struct {
	Error ErrorDetail `json:"error"`
}

ErrorResponse represents the standard error response format. All API errors return JSON in this structure: {"error": {"code": "...", "message": "..."}}

type EventHandlers

type EventHandlers struct {
	// contains filtered or unexported fields
}

EventHandlers holds dependencies for event HTTP handlers.

func NewEventHandlers

func NewEventHandlers(sceneService *scene.Service, auditRepo audit.Repository, streamRepo stream.SessionRepository, trustScoreStore TrustScoreStore) *EventHandlers

NewEventHandlers creates a new EventHandlers instance.

func (*EventHandlers) CancelEvent

func (h *EventHandlers) CancelEvent(w http.ResponseWriter, r *http.Request)

CancelEvent handles POST /events/{id}/cancel - cancels an event.

func (*EventHandlers) CreateEvent

func (h *EventHandlers) CreateEvent(w http.ResponseWriter, r *http.Request)

CreateEvent handles POST /events - creates a new event.

func (*EventHandlers) GetEvent

func (h *EventHandlers) GetEvent(w http.ResponseWriter, r *http.Request)

GetEvent handles GET /events/{id} - retrieves an event.

func (*EventHandlers) SearchEvents

func (h *EventHandlers) SearchEvents(w http.ResponseWriter, r *http.Request)

SearchEvents handles GET /search/events - searches events by bbox and time range.

func (*EventHandlers) UpdateEvent

func (h *EventHandlers) UpdateEvent(w http.ResponseWriter, r *http.Request)

UpdateEvent handles PATCH /events/{id} - updates an existing event.

type EventWithRSVPCounts

type EventWithRSVPCounts struct {
	*scene.Event
	RSVPCounts   *scene.RSVPCounts        `json:"rsvp_counts"`
	Scene        *SceneSearchResult       `json:"scene,omitempty"`
	ActiveStream *stream.ActiveStreamInfo `json:"active_stream,omitempty"`
	Occurrence   *PublicOccurrence        `json:"occurrence,omitempty"`
}

EventWithRSVPCounts represents an event with aggregated RSVP counts and active stream info.

type FeedResponse

type FeedResponse struct {
	Posts      []*post.Post     `json:"posts"`
	NextCursor *post.FeedCursor `json:"next_cursor,omitempty"`
}

FeedResponse represents the JSON response for feed endpoints.

type GlobalEventSearchResult

type GlobalEventSearchResult struct {
	ID        string `json:"id"`
	SceneID   string `json:"scene_id"`
	Title     string `json:"title"`
	StartsAt  string `json:"starts_at"`
	CreatedAt string `json:"created_at"`
}

GlobalEventSearchResult represents a minimal event result for global search.

type GlobalSearchResponse

type GlobalSearchResponse struct {
	Results    []*GlobalSearchResult `json:"results"`
	NextCursor string                `json:"next_cursor,omitempty"`
	Count      int                   `json:"count"`
}

GlobalSearchResponse represents the response for global search.

type GlobalSearchResult

type GlobalSearchResult struct {
	Type  string                   `json:"type"`
	Scene *SceneSearchResult       `json:"scene,omitempty"`
	Event *GlobalEventSearchResult `json:"event,omitempty"`
	Post  *PostSearchResult        `json:"post,omitempty"`
}

GlobalSearchResult represents one item in mixed global search results.

type HealthChecker

type HealthChecker interface {
	HealthCheck(ctx context.Context) error
}

HealthChecker defines the interface for components that can be health checked.

type HealthHandlers

type HealthHandlers struct {
	// contains filtered or unexported fields
}

HealthHandlers provides health and readiness check endpoints for Kubernetes probes.

func NewHealthHandlers

func NewHealthHandlers(config HealthHandlersConfig) *HealthHandlers

NewHealthHandlers creates a new health check handler.

func (*HealthHandlers) Health

func (h *HealthHandlers) Health(w http.ResponseWriter, r *http.Request)

Health handles GET /health/live (liveness probe). Returns 200 if the application is running and can serve requests. This is a basic check that the process is alive - no external dependencies checked.

func (*HealthHandlers) Ready

func (h *HealthHandlers) Ready(w http.ResponseWriter, r *http.Request)

Ready handles GET /health/ready (readiness probe). Returns 200 if the application is ready to serve traffic. Checks external dependencies and returns 503 if any critical service is unavailable.

type HealthHandlersConfig

type HealthHandlersConfig struct {
	LiveKitChecker HealthChecker
	StripeChecker  HealthChecker
	DBChecker      HealthChecker
	RedisChecker   HealthChecker
	MetricsEnabled bool
}

HealthHandlersConfig configures the health check handlers.

type HealthResponse

type HealthResponse struct {
	Status  string            `json:"status"`
	Checks  map[string]string `json:"checks,omitempty"`
	UptimeS int64             `json:"uptime_s,omitempty"`
}

HealthResponse represents the JSON response for health checks.

type IdentityAuthHandlers

type IdentityAuthHandlers struct {
	// contains filtered or unexported fields
}

func NewIdentityAuthHandlers

func NewIdentityAuthHandlers(service *identity.Service, secureCookie bool) *IdentityAuthHandlers

func (*IdentityAuthHandlers) CompleteProfile

func (h *IdentityAuthHandlers) CompleteProfile(w http.ResponseWriter, r *http.Request)

func (*IdentityAuthHandlers) CreatorAccess

func (h *IdentityAuthHandlers) CreatorAccess(w http.ResponseWriter, r *http.Request)

func (*IdentityAuthHandlers) ListCreatorAccess

func (h *IdentityAuthHandlers) ListCreatorAccess(w http.ResponseWriter, r *http.Request)

func (*IdentityAuthHandlers) Logout

func (*IdentityAuthHandlers) Me

func (*IdentityAuthHandlers) Refresh

func (h *IdentityAuthHandlers) RequestMagicLink(w http.ResponseWriter, r *http.Request)

func (*IdentityAuthHandlers) ReviewCreatorAccess

func (h *IdentityAuthHandlers) ReviewCreatorAccess(w http.ResponseWriter, r *http.Request)

func (*IdentityAuthHandlers) SetATProtoStatusResolver

func (h *IdentityAuthHandlers) SetATProtoStatusResolver(resolver func(context.Context, string) (map[string]any, error))

SetATProtoStatusResolver adds optional external identity fields to authenticated user responses without coupling passwordless login to AT Protocol availability.

func (h *IdentityAuthHandlers) VerifyMagicLink(w http.ResponseWriter, r *http.Request)

type JoinStreamRequest

type JoinStreamRequest struct {
	TokenIssuedAt string  `json:"token_issued_at"`          // RFC3339 timestamp from token issuance
	GeohashPrefix *string `json:"geohash_prefix,omitempty"` // Optional 4-char geohash for geographic tracking
}

JoinStreamRequest represents the request body for recording a join event.

type LiveKitHandlers

type LiveKitHandlers struct {
	// contains filtered or unexported fields
}

LiveKitHandlers holds dependencies for LiveKit HTTP handlers.

func NewLiveKitHandlers

func NewLiveKitHandlers(tokenService *livekit.TokenService, auditRepo audit.Repository) *LiveKitHandlers

NewLiveKitHandlers creates a new LiveKitHandlers instance.

func (*LiveKitHandlers) IssueToken

func (h *LiveKitHandlers) IssueToken(w http.ResponseWriter, r *http.Request)

IssueToken handles POST /livekit/token requests. Generates a short-lived LiveKit access token for authenticated users. Requires valid JWT authentication and associates the user's DID with the LiveKit session.

type LiveKitTokenRequest

type LiveKitTokenRequest struct {
	RoomID  string  `json:"room_id"`            // Required: Room identifier
	SceneID *string `json:"scene_id,omitempty"` // Optional: Associated scene ID
	EventID *string `json:"event_id,omitempty"` // Optional: Associated event ID
}

LiveKitTokenRequest represents the request body for generating a LiveKit token.

type LiveKitTokenResponse

type LiveKitTokenResponse struct {
	Token     string `json:"token"`      // The JWT access token
	ExpiresAt string `json:"expires_at"` // Token expiration time in RFC3339 format
}

LiveKitTokenResponse represents the response for a LiveKit token request.

type LockStreamRequest

type LockStreamRequest struct {
	Locked bool `json:"locked"` // True to lock, false to unlock
}

LockStreamRequest represents the request body for locking/unlocking a stream.

type MembershipHandlers

type MembershipHandlers struct {
	// contains filtered or unexported fields
}

MembershipHandlers holds dependencies for membership HTTP handlers.

func NewMembershipHandlers

func NewMembershipHandlers(
	membershipService *membership.Service,
	sceneRepo scene.SceneRepository,
	auditRepo audit.Repository,
) *MembershipHandlers

NewMembershipHandlers creates a new MembershipHandlers instance.

func (*MembershipHandlers) ApproveMembership

func (h *MembershipHandlers) ApproveMembership(w http.ResponseWriter, r *http.Request)

ApproveMembership handles POST /scenes/{id}/membership/{userId}/approve Approves a pending membership request (scene owner only).

func (*MembershipHandlers) RejectMembership

func (h *MembershipHandlers) RejectMembership(w http.ResponseWriter, r *http.Request)

RejectMembership handles POST /scenes/{id}/membership/{userId}/reject Rejects a pending membership request (scene owner only).

func (*MembershipHandlers) RequestMembership

func (h *MembershipHandlers) RequestMembership(w http.ResponseWriter, r *http.Request)

RequestMembership handles POST /scenes/{id}/membership/request Creates a pending membership request for the authenticated user.

type ModerationHandlers

type ModerationHandlers struct {
	// contains filtered or unexported fields
}

ModerationHandlers holds dependencies for moderation-related HTTP handlers.

func NewModerationHandlers

func NewModerationHandlers(
	sceneRepo scene.SceneRepository,
	adminDIDs []string,
) *ModerationHandlers

NewModerationHandlers creates a new ModerationHandlers instance.

func (*ModerationHandlers) MuteScene

func (h *ModerationHandlers) MuteScene(w http.ResponseWriter, r *http.Request)

MuteScene hides a scene from public view due to policy violation. POST /internal/moderation/scenes/{sceneID}/mute

func (*ModerationHandlers) UnmuteScene

func (h *ModerationHandlers) UnmuteScene(w http.ResponseWriter, r *http.Request)

UnmuteScene restores a muted scene to visible status. POST /internal/moderation/scenes/{sceneID}/unmute

type MuteParticipantRequest

type MuteParticipantRequest struct {
	Muted bool `json:"muted"` // True to mute, false to unmute
}

MuteParticipantRequest represents the request body for muting a participant.

type MuteSceneRequest

type MuteSceneRequest struct {
	Reason string `json:"reason"`
}

MuteSceneRequest represents the request body for muting a scene.

type MuteSceneResponse

type MuteSceneResponse struct {
	SceneID             string `json:"scene_id"`
	ModerationStatus    string `json:"moderation_status"`
	ModerationReason    string `json:"moderation_reason"`
	ModerationTimestamp string `json:"moderation_timestamp"`
}

MuteSceneResponse represents the response for a successful mute operation.

type NotificationHandlers

type NotificationHandlers struct {
	// contains filtered or unexported fields
}

func NewNotificationHandlers

func NewNotificationHandlers(service *notification.Service) *NotificationHandlers

func (*NotificationHandlers) Subscribe

func (h *NotificationHandlers) Subscribe(w http.ResponseWriter, r *http.Request)

type OnboardSceneRequest

type OnboardSceneRequest struct {
	SceneID string `json:"scene_id"`
}

OnboardSceneRequest represents the request body for creating a Stripe onboarding link.

type OnboardSceneResponse

type OnboardSceneResponse struct {
	URL       string `json:"url"`
	ExpiresAt string `json:"expires_at"`
}

OnboardSceneResponse represents the response for a successful onboarding link creation.

type OnboardingStatusResponse

type OnboardingStatusResponse struct {
	SceneID                string  `json:"scene_id"`
	ConnectedAccountID     *string `json:"connected_account_id,omitempty"`
	ConnectedAccountStatus string  `json:"connected_account_status"` // pending, active, restricted
	AccountOnboardedAt     *string `json:"account_onboarded_at,omitempty"`
}

OnboardingStatusResponse represents the current onboarding status for a scene.

type OwnedSceneSummary

type OwnedSceneSummary struct {
	ID              string     `json:"id"`
	Name            string     `json:"name"`
	Description     string     `json:"description,omitempty"`
	CoarseGeohash   string     `json:"coarse_geohash"`
	Tags            []string   `json:"tags,omitempty"`
	Visibility      string     `json:"visibility"`
	CreatedAt       *time.Time `json:"created_at,omitempty"`
	UpdatedAt       *time.Time `json:"updated_at,omitempty"`
	MembersCount    int        `json:"members_count"`
	HasActiveStream bool       `json:"has_active_stream"`
}

OwnedSceneSummary represents a summary of a scene owned by the user.

type ParticipantWebSocketHandlers

type ParticipantWebSocketHandlers struct {
	// contains filtered or unexported fields
}

ParticipantWebSocketHandlers holds dependencies for WebSocket handlers.

func NewParticipantWebSocketHandlers

func NewParticipantWebSocketHandlers(
	streamRepo stream.SessionRepository,
	eventBroadcaster *stream.EventBroadcaster,
) *ParticipantWebSocketHandlers

NewParticipantWebSocketHandlers creates a new ParticipantWebSocketHandlers instance.

func (*ParticipantWebSocketHandlers) SubscribeToParticipantEvents

func (h *ParticipantWebSocketHandlers) SubscribeToParticipantEvents(w http.ResponseWriter, r *http.Request)

SubscribeToParticipantEvents handles WebSocket connections for real-time participant updates. GET /streams/{id}/participants/ws Requires authentication - only authenticated users can subscribe to participant events.

type PaymentHandlers

type PaymentHandlers struct {
	// contains filtered or unexported fields
}

PaymentHandlers holds dependencies for payment-related HTTP handlers.

func NewPaymentHandlers

func NewPaymentHandlers(
	sceneRepo scene.SceneRepository,
	paymentRepo payment.PaymentRepository,
	stripeClient payment.Client,
	returnURL string,
	refreshURL string,
	applicationFeePercent float64,
) *PaymentHandlers

NewPaymentHandlers creates a new PaymentHandlers instance.

func (*PaymentHandlers) CreateCheckoutSession

func (h *PaymentHandlers) CreateCheckoutSession(w http.ResponseWriter, r *http.Request)

CreateCheckoutSession creates a Stripe Checkout Session for event ticket or merch with application fee. POST /payments/checkout

func (*PaymentHandlers) GetOnboardingStatus

func (h *PaymentHandlers) GetOnboardingStatus(w http.ResponseWriter, r *http.Request)

GetOnboardingStatus returns the current Stripe onboarding status for a scene. GET /payments/onboarding/{sceneID}

func (*PaymentHandlers) GetPaymentStatus

func (h *PaymentHandlers) GetPaymentStatus(w http.ResponseWriter, r *http.Request)

GetPaymentStatus retrieves the current status of a payment by checkout session ID. GET /payments/status?sessionId=...

func (*PaymentHandlers) OnboardScene

func (h *PaymentHandlers) OnboardScene(w http.ResponseWriter, r *http.Request)

OnboardScene creates a Stripe Connect onboarding link for a scene owner. POST /payments/onboard

type PaymentStatusResponse

type PaymentStatusResponse struct {
	Status      string     `json:"status"`
	AmountCents int64      `json:"amount_cents"`
	FeeCents    int64      `json:"fee_cents"`
	Currency    string     `json:"currency"`
	UpdatedAt   *time.Time `json:"updated_at,omitempty"`
}

PaymentStatusResponse represents the response for payment status query.

type PerformanceMetric

type PerformanceMetric struct {
	Name           string  `json:"name"`
	Value          float64 `json:"value"`
	Rating         string  `json:"rating"`
	Delta          float64 `json:"delta"`
	ID             string  `json:"id"`
	NavigationType string  `json:"navigationType"`
	Timestamp      int64   `json:"timestamp"`
}

PerformanceMetric represents a single web vitals metric from the frontend.

type PostHandlers

type PostHandlers struct {
	// contains filtered or unexported fields
}

PostHandlers holds dependencies for post HTTP handlers.

func NewPostHandlers

func NewPostHandlers(postService *post.Service, sceneRepo scene.SceneRepository, membershipRepo membership.MembershipRepository, metadataService *attachment.MetadataService) *PostHandlers

NewPostHandlers creates a new PostHandlers instance. metadataService is optional and can be nil if attachment enrichment is not configured.

func (*PostHandlers) CreatePost

func (h *PostHandlers) CreatePost(w http.ResponseWriter, r *http.Request)

CreatePost handles POST /posts - creates a new post.

func (*PostHandlers) DeletePost

func (h *PostHandlers) DeletePost(w http.ResponseWriter, r *http.Request)

DeletePost handles DELETE /posts/{id} - soft-deletes a post.

func (*PostHandlers) GetEventFeed

func (h *PostHandlers) GetEventFeed(w http.ResponseWriter, r *http.Request)

GetEventFeed handles GET /events/{id}/feed - retrieves posts for an event with pagination.

func (*PostHandlers) GetSceneFeed

func (h *PostHandlers) GetSceneFeed(w http.ResponseWriter, r *http.Request)

GetSceneFeed handles GET /scenes/{id}/feed - retrieves posts for a scene with pagination.

func (*PostHandlers) UpdatePost

func (h *PostHandlers) UpdatePost(w http.ResponseWriter, r *http.Request)

UpdatePost handles PATCH /posts/{id} - updates an existing post.

type PostSearchResponse

type PostSearchResponse struct {
	Results    []*PostSearchResult `json:"results"`
	NextCursor string              `json:"next_cursor,omitempty"`
	Count      int                 `json:"count"`
}

PostSearchResponse represents the response for post search.

type PostSearchResult

type PostSearchResult struct {
	ID         string   `json:"id"`
	Excerpt    string   `json:"excerpt"` // First 160 chars
	SceneID    *string  `json:"scene_id,omitempty"`
	TrustScore *float64 `json:"trust_score,omitempty"` // Only if trust ranking enabled
	CreatedAt  string   `json:"created_at"`            // ISO 8601 format
}

PostSearchResult represents a minimal post result for search.

type ProtectedLocationHandlers

type ProtectedLocationHandlers struct {
	// contains filtered or unexported fields
}

func (*ProtectedLocationHandlers) ServeHTTP

type PublicOccurrence

type PublicOccurrence struct {
	CoarseGeohash string       `json:"coarse_geohash"`
	DisplayPoint  *scene.Point `json:"display_point,omitempty"`
	Precision     string       `json:"precision"`
}

PublicOccurrence is the only location projection map clients should use for Events.

type QualityMetricsHandler

type QualityMetricsHandler struct {
	// contains filtered or unexported fields
}

QualityMetricsHandler handles quality metrics API endpoints.

func NewQualityMetricsHandler

func NewQualityMetricsHandler(
	roomService *livekitservice.RoomService,
	metricsRepo stream.QualityMetricsRepository,
	streamRepo stream.SessionRepository,
	streamMetrics *stream.Metrics,
) *QualityMetricsHandler

NewQualityMetricsHandler creates a new QualityMetricsHandler.

func (*QualityMetricsHandler) CollectStreamQualityMetrics

func (h *QualityMetricsHandler) CollectStreamQualityMetrics(w http.ResponseWriter, r *http.Request)

CollectStreamQualityMetrics collects quality metrics from LiveKit for all participants in a stream. POST /streams/{id}/quality-metrics/collect This endpoint is typically called periodically by a background job or external monitor.

func (*QualityMetricsHandler) GetHighPacketLossParticipants

func (h *QualityMetricsHandler) GetHighPacketLossParticipants(w http.ResponseWriter, r *http.Request)

GetHighPacketLossParticipants returns participants with recent high packet loss. GET /streams/{id}/quality-metrics/high-packet-loss

func (*QualityMetricsHandler) GetParticipantQualityMetrics

func (h *QualityMetricsHandler) GetParticipantQualityMetrics(w http.ResponseWriter, r *http.Request)

GetParticipantQualityMetrics retrieves quality metrics for a specific participant. GET /streams/{id}/participants/{participant_id}/quality-metrics

func (*QualityMetricsHandler) GetStreamQualityMetrics

func (h *QualityMetricsHandler) GetStreamQualityMetrics(w http.ResponseWriter, r *http.Request)

GetStreamQualityMetrics retrieves quality metrics for a stream session. GET /streams/{id}/quality-metrics

type RSVPHandlers

type RSVPHandlers struct {
	// contains filtered or unexported fields
}

RSVPHandlers holds dependencies for RSVP HTTP handlers.

func NewRSVPHandlers

func NewRSVPHandlers(rsvpRepo scene.RSVPRepository, eventRepo scene.EventRepository) *RSVPHandlers

NewRSVPHandlers creates a new RSVPHandlers instance.

func (*RSVPHandlers) CreateOrUpdateRSVP

func (h *RSVPHandlers) CreateOrUpdateRSVP(w http.ResponseWriter, r *http.Request)

CreateOrUpdateRSVP handles POST /events/{id}/rsvp - creates or updates an RSVP.

func (*RSVPHandlers) DeleteRSVP

func (h *RSVPHandlers) DeleteRSVP(w http.ResponseWriter, r *http.Request)

DeleteRSVP handles DELETE /events/{id}/rsvp - removes an RSVP.

type RSVPRequest

type RSVPRequest struct {
	Status string `json:"status"` // "going" or "maybe"
}

RSVPRequest represents the request body for creating/updating an RSVP.

type RSVPResponse

type RSVPResponse struct {
	EventID   string     `json:"event_id"`
	Status    string     `json:"status"`
	CreatedAt *time.Time `json:"created_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`
}

RSVPResponse represents the response body for RSVP operations. Note: UserID is intentionally omitted to protect user privacy.

type RouteDeps

type RouteDeps struct {
	RateLimitStore   middleware.RateLimitStore
	RateLimitMetrics *middleware.Metrics
}

RouteDeps holds infrastructure dependencies shared across route registrars.

func (*RouteDeps) RateLimit

func (d *RouteDeps) RateLimit(handler http.HandlerFunc, config middleware.RateLimitConfig, keyFunc middleware.KeyFunc) http.Handler

RateLimit wraps a handler with rate limiting using the given config and key function.

type SceneHandlers

type SceneHandlers struct {
	// contains filtered or unexported fields
}

SceneHandlers holds dependencies for scene HTTP handlers.

func NewSceneHandlers

func NewSceneHandlers(sceneService *scene.Service, membershipRepo membership.MembershipRepository, streamRepo stream.SessionRepository) *SceneHandlers

NewSceneHandlers creates a new SceneHandlers instance.

func (*SceneHandlers) CreateScene

func (h *SceneHandlers) CreateScene(w http.ResponseWriter, r *http.Request)

CreateScene handles POST /scenes - creates a new scene.

func (*SceneHandlers) DeleteScene

func (h *SceneHandlers) DeleteScene(w http.ResponseWriter, r *http.Request)

DeleteScene handles DELETE /scenes/{id} - soft-deletes a scene.

func (*SceneHandlers) GetScene

func (h *SceneHandlers) GetScene(w http.ResponseWriter, r *http.Request)

GetScene handles GET /scenes/{id} - retrieves a scene with visibility enforcement.

func (*SceneHandlers) ListOwnedScenes

func (h *SceneHandlers) ListOwnedScenes(w http.ResponseWriter, r *http.Request)

ListOwnedScenes handles GET /scenes/owned - lists all scenes owned by the authenticated user.

func (*SceneHandlers) UpdateScene

func (h *SceneHandlers) UpdateScene(w http.ResponseWriter, r *http.Request)

UpdateScene handles PATCH /scenes/{id} - updates an existing scene.

func (*SceneHandlers) UpdateScenePalette

func (h *SceneHandlers) UpdateScenePalette(w http.ResponseWriter, r *http.Request)

UpdateScenePalette handles PATCH /scenes/{id}/palette - updates scene color palette.

type SceneSearchResponse

type SceneSearchResponse struct {
	Results    []*SceneSearchResult `json:"results"`
	NextCursor string               `json:"next_cursor,omitempty"`
	Count      int                  `json:"count"`
}

SceneSearchResponse represents the response for scene search.

type SceneSearchResult

type SceneSearchResult struct {
	ID            string       `json:"id"`
	Name          string       `json:"name"`
	Description   string       `json:"description,omitempty"`
	JitteredPoint *scene.Point `json:"jittered_centroid,omitempty"` // Always jittered for privacy
	CoarseGeohash string       `json:"coarse_geohash"`
	Tags          []string     `json:"tags,omitempty"`
	Visibility    string       `json:"visibility"`
	TrustScore    *float64     `json:"trust_score,omitempty"` // Only if trust ranking enabled
}

SceneSearchResult represents a minimal scene result for search.

type SearchEventsResponse

type SearchEventsResponse struct {
	Events     []*EventWithRSVPCounts `json:"events"`
	NextCursor string                 `json:"next_cursor,omitempty"`
}

SearchEventsResponse represents the response for event search with active stream info.

type SearchHandlers

type SearchHandlers struct {
	// contains filtered or unexported fields
}

SearchHandlers holds dependencies for search HTTP handlers.

func NewSearchHandlers

func NewSearchHandlers(sceneRepo scene.SceneRepository, postRepo post.PostRepository, trustStore TrustScoreStore, eventRepo scene.EventRepository) *SearchHandlers

NewSearchHandlers creates a new SearchHandlers instance.

func (*SearchHandlers) SearchGlobal

func (h *SearchHandlers) SearchGlobal(w http.ResponseWriter, r *http.Request)

SearchGlobal handles GET /search/global - unified search across scenes, events, and posts.

func (*SearchHandlers) SearchPosts

func (h *SearchHandlers) SearchPosts(w http.ResponseWriter, r *http.Request)

SearchPosts handles GET /search/posts - searches for posts with text relevance and scene filter.

func (*SearchHandlers) SearchScenes

func (h *SearchHandlers) SearchScenes(w http.ResponseWriter, r *http.Request)

SearchScenes handles GET /search/scenes - searches for scenes with ranking and pagination.

type SetFeaturedParticipantRequest

type SetFeaturedParticipantRequest struct {
	ParticipantID *string `json:"participant_id"` // Participant ID to feature, or null to clear
}

SetFeaturedParticipantRequest represents the request body for setting a featured participant.

type SignUploadRequest

type SignUploadRequest struct {
	ContentType string  `json:"contentType"`
	SizeBytes   int64   `json:"sizeBytes"`
	PostID      *string `json:"postId,omitempty"`
}

SignUploadRequest represents the request body for POST /uploads/sign.

type SignUploadResponse

type SignUploadResponse struct {
	URL       string `json:"url"`
	Key       string `json:"key"`
	ExpiresAt string `json:"expiresAt"` // ISO 8601 format
}

SignUploadResponse represents the response for POST /uploads/sign.

type SignalHandlers

type SignalHandlers struct {
	// contains filtered or unexported fields
}

SignalHandlers exposes only draft creation, publication, and public revision metadata. Delivery execution is intentionally not reachable from this HTTP boundary.

func NewSignalHandlers

func NewSignalHandlers(service *signal.Service, audienceServices ...*audience.Service) *SignalHandlers

func (*SignalHandlers) CreateDraft

func (h *SignalHandlers) CreateDraft(w http.ResponseWriter, r *http.Request)

func (*SignalHandlers) Get

func (*SignalHandlers) MutateConsent

func (h *SignalHandlers) MutateConsent(w http.ResponseWriter, r *http.Request)

MutateConsent resolves the authenticated DID through verified, revocable link evidence. The request never accepts a caller-supplied contact ID.

func (*SignalHandlers) Publish

func (h *SignalHandlers) Publish(w http.ResponseWriter, r *http.Request)

type StreamHandlers

type StreamHandlers struct {
	// contains filtered or unexported fields
}

StreamHandlers holds dependencies for stream session HTTP handlers.

func NewStreamHandlers

func NewStreamHandlers(
	streamService *stream.Service,
	sceneRepo scene.SceneRepository,
	eventRepo scene.EventRepository,
	auditRepo audit.Repository,
	streamMetrics *stream.Metrics,
	eventBroadcaster *stream.EventBroadcaster,
	roomService *livekitpkg.RoomService,
) *StreamHandlers

NewStreamHandlers creates a new StreamHandlers instance.

func (*StreamHandlers) CreateStream

func (h *StreamHandlers) CreateStream(w http.ResponseWriter, r *http.Request)

CreateStream handles POST /streams - creates a new stream session.

func (*StreamHandlers) EndStream

func (h *StreamHandlers) EndStream(w http.ResponseWriter, r *http.Request)

EndStream handles POST /streams/{id}/end - ends a stream session.

func (*StreamHandlers) GetActiveParticipants

func (h *StreamHandlers) GetActiveParticipants(w http.ResponseWriter, r *http.Request)

GetActiveParticipants handles GET /streams/{id}/participants - retrieves active participants. Returns minimal participant info (no PII) for UI display.

func (*StreamHandlers) GetStream

func (h *StreamHandlers) GetStream(w http.ResponseWriter, r *http.Request)

GetStream handles GET /streams/{id} - retrieves stream session details.

func (*StreamHandlers) GetStreamAnalytics

func (h *StreamHandlers) GetStreamAnalytics(w http.ResponseWriter, r *http.Request)

GetStreamAnalytics handles GET /streams/{id}/analytics - retrieves analytics for a stream session. Only accessible by the stream host (scene/event owner).

func (*StreamHandlers) JoinStream

func (h *StreamHandlers) JoinStream(w http.ResponseWriter, r *http.Request)

JoinStream handles POST /streams/{id}/join - records a join event and metrics.

func (*StreamHandlers) KickParticipant

func (h *StreamHandlers) KickParticipant(w http.ResponseWriter, r *http.Request)

KickParticipant handles POST /streams/{stream_id}/participants/{participant_id}/kick Removes a participant from the stream. Only the stream host (organizer) can perform this action.

func (*StreamHandlers) LeaveStream

func (h *StreamHandlers) LeaveStream(w http.ResponseWriter, r *http.Request)

LeaveStream handles POST /streams/{id}/leave - records a leave event and metrics.

func (*StreamHandlers) LockStream

func (h *StreamHandlers) LockStream(w http.ResponseWriter, r *http.Request)

LockStream handles PATCH /streams/{stream_id}/lock Locks or unlocks the stream to prevent new participants from joining. Only the stream host (organizer) can perform this action.

func (*StreamHandlers) MuteParticipant

func (h *StreamHandlers) MuteParticipant(w http.ResponseWriter, r *http.Request)

MuteParticipant handles POST /streams/{stream_id}/participants/{participant_id}/mute Mutes or unmutes a participant's audio in the stream. Only the stream host (organizer) can perform this action.

func (*StreamHandlers) SetFeaturedParticipant

func (h *StreamHandlers) SetFeaturedParticipant(w http.ResponseWriter, r *http.Request)

SetFeaturedParticipant handles PATCH /streams/{stream_id}/featured_participant Sets or clears the featured (spotlighted) participant in the stream. Only the stream host (organizer) can perform this action.

func (*StreamHandlers) UpdateStream

func (h *StreamHandlers) UpdateStream(w http.ResponseWriter, r *http.Request)

UpdateStream handles PATCH /streams/{id} - updates stream metadata.

type StreamSessionResponse

type StreamSessionResponse struct {
	ID       string  `json:"id"`
	RoomName string  `json:"room_name"`
	SceneID  *string `json:"scene_id,omitempty"`
	EventID  *string `json:"event_id,omitempty"`
	Status   string  `json:"status"` // "active" or "ended"
}

StreamSessionResponse represents the response for stream session operations.

type TelemetryEventsRequest

type TelemetryEventsRequest struct {
	Events []telemetry.TelemetryEvent `json:"events"`
}

TelemetryEventsRequest represents the request payload for POST /api/telemetry.

type TelemetryHandlers

type TelemetryHandlers struct {
	// contains filtered or unexported fields
}

TelemetryHandlers provides endpoints for frontend performance telemetry and event batch collection.

func NewTelemetryHandlers

func NewTelemetryHandlers(store telemetry.Store, metrics *telemetry.Metrics) *TelemetryHandlers

NewTelemetryHandlers creates a new telemetry handler.

func (*TelemetryHandlers) PostEvents

func (h *TelemetryHandlers) PostEvents(w http.ResponseWriter, r *http.Request)

PostEvents handles POST /api/telemetry. Accepts batched telemetry events from the frontend telemetry service.

func (*TelemetryHandlers) PostMetrics

func (h *TelemetryHandlers) PostMetrics(w http.ResponseWriter, r *http.Request)

PostMetrics handles POST /api/telemetry/metrics. Accepts web vitals performance metrics from the frontend.

type TelemetryMetricsRequest

type TelemetryMetricsRequest struct {
	Metrics   []PerformanceMetric `json:"metrics"`
	UserAgent string              `json:"userAgent"`
	URL       string              `json:"url"`
}

TelemetryMetricsRequest represents the request payload for POST /api/telemetry/metrics.

type TouringHandlers

type TouringHandlers struct {
	// contains filtered or unexported fields
}

TouringHandlers exposes additive, read-only touring resources. Business logic lives in the touring.Service layer; the handler handles HTTP decoding/encoding.

func NewTouringHandlers

func NewTouringHandlers(touringService *touring.Service, eventRepo scene.EventRepository, sceneRepo scene.SceneRepository) *TouringHandlers

func (*TouringHandlers) CreateAppearance

func (h *TouringHandlers) CreateAppearance(w http.ResponseWriter, r *http.Request)

func (*TouringHandlers) CreatePlace

func (h *TouringHandlers) CreatePlace(w http.ResponseWriter, r *http.Request)

func (*TouringHandlers) CreateProfile

func (h *TouringHandlers) CreateProfile(w http.ResponseWriter, r *http.Request)

CreateProfile handles creator-authorized Studio profile creation. Authorization is applied by the route wrapper so the domain handler can stay testable.

func (*TouringHandlers) CreateTour

func (h *TouringHandlers) CreateTour(w http.ResponseWriter, r *http.Request)

func (*TouringHandlers) CreateVenue

func (h *TouringHandlers) CreateVenue(w http.ResponseWriter, r *http.Request)

func (*TouringHandlers) Profile

func (h *TouringHandlers) Profile(w http.ResponseWriter, r *http.Request)

Profile handles GET /profiles/{id}.

func (*TouringHandlers) SearchAppearances

func (h *TouringHandlers) SearchAppearances(w http.ResponseWriter, r *http.Request)

SearchAppearances handles GET /search/appearances. All filters are applied before response construction, and the only returned location is the shared server-approved occurrence projection.

func (*TouringHandlers) Tour

Tour handles GET /tours/{id}.

func (*TouringHandlers) UpdateAppearance

func (h *TouringHandlers) UpdateAppearance(w http.ResponseWriter, r *http.Request)

func (*TouringHandlers) UpdatePlace

func (h *TouringHandlers) UpdatePlace(w http.ResponseWriter, r *http.Request)

func (*TouringHandlers) UpdateProfile

func (h *TouringHandlers) UpdateProfile(w http.ResponseWriter, r *http.Request)

func (*TouringHandlers) UpdateTour

func (h *TouringHandlers) UpdateTour(w http.ResponseWriter, r *http.Request)

type TrustHandlers

type TrustHandlers struct {
	// contains filtered or unexported fields
}

TrustHandlers holds dependencies for trust HTTP handlers.

func NewTrustHandlers

func NewTrustHandlers(
	sceneRepo scene.SceneRepository,
	dataSource trust.DataSource,
	scoreStore trust.ScoreStore,
	dirtyTracker *trust.DirtyTracker,
) *TrustHandlers

NewTrustHandlers creates a new TrustHandlers instance.

func (*TrustHandlers) GetTrustScore

func (h *TrustHandlers) GetTrustScore(w http.ResponseWriter, r *http.Request)

GetTrustScore handles GET /trust/{sceneId} - retrieves trust score and breakdown.

type TrustScore

type TrustScore struct {
	SceneID string
	Score   float64
}

TrustScore represents a trust score value.

type TrustScoreBreakdown

type TrustScoreBreakdown struct {
	AverageAllianceWeight        float64 `json:"average_alliance_weight"`
	AverageMembershipTrustWeight float64 `json:"average_membership_trust_weight"`
	RoleMultiplierAggregate      float64 `json:"role_multiplier_aggregate"`
}

TrustScoreBreakdown represents the detailed breakdown of trust score computation.

type TrustScoreResponse

type TrustScoreResponse struct {
	SceneID     string               `json:"scene_id"`
	TrustScore  float64              `json:"trust_score"`
	Breakdown   *TrustScoreBreakdown `json:"breakdown,omitempty"`
	Stale       bool                 `json:"stale"`
	LastUpdated string               `json:"last_updated,omitempty"`
}

TrustScoreResponse represents the response for trust score endpoint.

type TrustScoreStore

type TrustScoreStore interface {
	GetScore(sceneID string) (score *TrustScore, err error)
}

TrustScoreStore defines the interface for retrieving trust scores.

func NewTrustScoreStoreAdapter

func NewTrustScoreStoreAdapter(store *trust.InMemoryScoreStore) TrustScoreStore

NewTrustScoreStoreAdapter creates an adapter for the trust score store.

type UnmuteSceneResponse

type UnmuteSceneResponse struct {
	SceneID          string `json:"scene_id"`
	ModerationStatus string `json:"moderation_status"`
}

UnmuteSceneResponse represents the response for a successful unmute operation.

type UpdateAllianceRequest

type UpdateAllianceRequest struct {
	Weight *float64 `json:"weight,omitempty"`
	Reason *string  `json:"reason,omitempty"`
}

UpdateAllianceRequest represents the request body for updating an alliance.

type UpdateEventRequest

type UpdateEventRequest struct {
	Version        int64        `json:"version"`
	Title          *string      `json:"title,omitempty"`
	Description    *string      `json:"description,omitempty"`
	Tags           []string     `json:"tags,omitempty"`
	AllowPrecise   *bool        `json:"allow_precise,omitempty"`
	PrecisePoint   *scene.Point `json:"precise_point,omitempty"`
	CoarseGeohash  *string      `json:"coarse_geohash,omitempty"`
	StartsAt       *time.Time   `json:"starts_at,omitempty"`
	EndsAt         *time.Time   `json:"ends_at,omitempty"`
	LocationAccess *string      `json:"location_access,omitempty"`
}

UpdateEventRequest represents the request body for updating an event.

type UpdatePostRequest

type UpdatePostRequest struct {
	Text        *string            `json:"text,omitempty"`
	Attachments *[]post.Attachment `json:"attachments,omitempty"`
	Labels      *[]string          `json:"labels,omitempty"`
}

UpdatePostRequest represents the request body for updating a post.

type UpdateScenePaletteRequest

type UpdateScenePaletteRequest struct {
	Palette scene.Palette `json:"palette"`
}

UpdateScenePaletteRequest represents the request body for updating scene palette.

type UpdateSceneRequest

type UpdateSceneRequest struct {
	Version      int64          `json:"version"`
	Name         *string        `json:"name,omitempty"`
	Description  *string        `json:"description,omitempty"`
	Tags         []string       `json:"tags,omitempty"`
	Visibility   *string        `json:"visibility,omitempty"`
	Palette      *scene.Palette `json:"palette,omitempty"`
	AllowPrecise *bool          `json:"allow_precise,omitempty"`
	PrecisePoint *scene.Point   `json:"precise_point,omitempty"`
}

UpdateSceneRequest represents the request body for updating a scene. Only includes mutable fields (owner is immutable).

type UpdateStreamRequest

type UpdateStreamRequest struct {
	Metadata map[string]interface{} `json:"metadata,omitempty"`
}

UpdateStreamRequest represents the request body for updating stream metadata.

type UploadHandlers

type UploadHandlers struct {
	// contains filtered or unexported fields
}

UploadHandlers holds dependencies for upload HTTP handlers.

func NewUploadHandlers

func NewUploadHandlers(uploadService *upload.Service) *UploadHandlers

NewUploadHandlers creates a new UploadHandlers instance.

func (*UploadHandlers) SignUpload

func (h *UploadHandlers) SignUpload(w http.ResponseWriter, r *http.Request)

SignUpload handles POST /uploads/sign - generates a pre-signed upload URL.

type WebhookHandlers

type WebhookHandlers struct {
	// contains filtered or unexported fields
}

WebhookHandlers holds dependencies for webhook-related HTTP handlers.

func NewWebhookHandlers

func NewWebhookHandlers(
	webhookSecret string,
	paymentRepo payment.PaymentRepository,
	webhookRepo payment.WebhookRepository,
	sceneRepo scene.SceneRepository,
) *WebhookHandlers

NewWebhookHandlers creates a new WebhookHandlers instance.

func (*WebhookHandlers) HandleStripeWebhook

func (h *WebhookHandlers) HandleStripeWebhook(w http.ResponseWriter, r *http.Request)

HandleStripeWebhook processes Stripe webhook events with signature verification. POST /internal/stripe

Jump to

Keyboard shortcuts

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