api

package
v0.36.0 Latest Latest
Warning

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

Go to latest
Published: Feb 14, 2026 License: MIT Imports: 29 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AdminScopeReadServer    = "admin:read:server"
	AdminScopeReadProjects  = "admin:read:projects"
	AdminScopeReadEvents    = "admin:read:events"
	AdminScopeReadSnapshots = "admin:read:snapshots"
	AdminScopeExport        = "admin:export"
)

Admin scope constants for the admin API.

View Source
const (
	ErrCodeBadRequest             = "bad_request"
	ErrCodeNotFound               = "not_found"
	ErrCodeInternal               = "internal"
	ErrCodeUnauthorized           = "unauthorized"
	ErrCodeForbidden              = "forbidden"
	ErrCodeInsufficientAdminScope = "insufficient_admin_scope"
	ErrCodeRateLimited            = "rate_limited"
	ErrCodeSignupDisabled         = "signup_disabled"
	ErrCodeExpired                = "expired"
	ErrCodeAlreadyUsed            = "already_used"
	ErrCodeNoEvents               = "no_events"
	ErrCodeNotImplemented         = "not_implemented"
	// New codes for sections 9.5, 10
	ErrCodeProjectDeleted      = "project_deleted"
	ErrCodeSnapshotUnavailable = "snapshot_unavailable"
	ErrCodeExportTooLarge      = "export_too_large"
	ErrCodeInvalidQuery        = "invalid_query"
)

Error code constants for structured API error responses.

Variables

ValidAdminScopes contains all recognized admin scopes.

Functions

func HasScope added in v0.32.0

func HasScope(scopes string, required string) bool

HasScope reports whether the comma-separated scopes string contains the required scope.

func ValidateScopes added in v0.32.0

func ValidateScopes(scopes string) error

ValidateScopes checks that every comma-separated scope is either "sync" or a recognized admin scope. Returns an error listing the first invalid scope.

Types

type APIError

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

APIError represents a structured error returned by the API.

type AckResponse

type AckResponse struct {
	ClientActionID int64 `json:"client_action_id"`
	ServerSeq      int64 `json:"server_seq"`
}

AckResponse is a single acknowledged event.

type AddMemberRequest

type AddMemberRequest struct {
	UserID string `json:"user_id"`
	Email  string `json:"email"`
	Role   string `json:"role"`
}

AddMemberRequest is the JSON body for POST /v1/projects/{id}/members.

type AuthUser

type AuthUser struct {
	UserID  string
	Email   string
	KeyID   string
	Scopes  []string
	IsAdmin bool
}

AuthUser holds the authenticated user information extracted from the API key.

type Config

type Config struct {
	ListenAddr      string
	ServerDBPath    string
	ProjectDataDir  string
	ShutdownTimeout time.Duration
	AllowSignup     bool
	BaseURL         string
	LogFormat       string // "json" (default) or "text"
	LogLevel        string // "debug", "info" (default), "warn", "error"

	RateLimitAuth  int // /auth/* per IP per minute (default: 10)
	RateLimitPush  int // /sync/push per API key per minute (default: 60)
	RateLimitPull  int // /sync/pull per API key per minute (default: 120)
	RateLimitOther int // all other per API key per minute (default: 300)

	CORSAllowedOrigins []string // allowed origins for admin CORS; empty = disabled

	AuthEventRetention      time.Duration // retention period for auth events (default: 90 days)
	RateLimitEventRetention time.Duration // retention period for rate limit events (default: 30 days)
}

Config holds the server configuration, loaded from environment variables.

func LoadConfig

func LoadConfig() Config

LoadConfig reads configuration from environment variables with sensible defaults.

type CreateProjectRequest

type CreateProjectRequest struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

CreateProjectRequest is the JSON body for POST /v1/projects.

type ErrorResponse

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

ErrorResponse wraps an APIError for JSON serialization.

type EventInput

type EventInput struct {
	ClientActionID  int64           `json:"client_action_id"`
	ActionType      string          `json:"action_type"`
	EntityType      string          `json:"entity_type"`
	EntityID        string          `json:"entity_id"`
	Payload         json.RawMessage `json:"payload"`
	ClientTimestamp string          `json:"client_timestamp"`
}

EventInput represents a single event in a push request.

type MemberResponse

type MemberResponse struct {
	ProjectID string `json:"project_id"`
	UserID    string `json:"user_id"`
	Role      string `json:"role"`
	InvitedBy string `json:"invited_by"`
	CreatedAt string `json:"created_at"`
}

MemberResponse is the JSON representation of a membership.

type Metrics

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

Metrics collects in-memory server metrics using atomic counters.

func NewMetrics

func NewMetrics() *Metrics

NewMetrics creates a new Metrics instance with the current time as start.

func (*Metrics) RecordClientError

func (m *Metrics) RecordClientError()

RecordClientError increments the client error (4xx) counter.

func (*Metrics) RecordError

func (m *Metrics) RecordError()

RecordError increments the server error (5xx) counter.

func (*Metrics) RecordPullRequest

func (m *Metrics) RecordPullRequest()

RecordPullRequest increments the pull request counter.

func (*Metrics) RecordPushEvents

func (m *Metrics) RecordPushEvents(n int64)

RecordPushEvents adds n to the accepted push events counter.

func (*Metrics) RecordRequest

func (m *Metrics) RecordRequest()

RecordRequest increments the total request counter.

func (*Metrics) Snapshot

func (m *Metrics) Snapshot() MetricsSnapshot

Snapshot returns a point-in-time copy of the metrics.

type MetricsSnapshot

type MetricsSnapshot struct {
	UptimeSeconds      float64 `json:"uptime_seconds"`
	Requests           int64   `json:"requests"`
	ServerErrors       int64   `json:"server_errors"`
	ClientErrors       int64   `json:"client_errors"`
	PushEventsAccepted int64   `json:"push_events_accepted"`
	PullRequests       int64   `json:"pull_requests"`
}

MetricsSnapshot is a point-in-time view of server metrics.

type ProjectDBPool

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

ProjectDBPool manages per-project SQLite connections for event logs.

func NewProjectDBPool

func NewProjectDBPool(dataDir string) *ProjectDBPool

NewProjectDBPool creates a new pool that stores project databases under dataDir.

func (*ProjectDBPool) CloseAll

func (p *ProjectDBPool) CloseAll()

CloseAll closes all open project database connections.

func (*ProjectDBPool) Create

func (p *ProjectDBPool) Create(projectID string) (*sql.DB, error)

Create creates a new project database directory and initializes the event log.

func (*ProjectDBPool) Get

func (p *ProjectDBPool) Get(projectID string) (*sql.DB, error)

Get returns the database connection for the given project, opening it lazily and initializing the event log schema if needed.

type ProjectResponse

type ProjectResponse struct {
	ID          string  `json:"id"`
	Name        string  `json:"name"`
	Description string  `json:"description"`
	CreatedAt   string  `json:"created_at"`
	UpdatedAt   string  `json:"updated_at"`
	DeletedAt   *string `json:"deleted_at,omitempty"`
}

ProjectResponse is the JSON representation of a project.

type PullEvent

type PullEvent struct {
	ServerSeq       int64           `json:"server_seq"`
	DeviceID        string          `json:"device_id"`
	SessionID       string          `json:"session_id"`
	ClientActionID  int64           `json:"client_action_id"`
	ActionType      string          `json:"action_type"`
	EntityType      string          `json:"entity_type"`
	EntityID        string          `json:"entity_id"`
	Payload         json.RawMessage `json:"payload"`
	ClientTimestamp string          `json:"client_timestamp"`
}

PullEvent is a single event in a pull response.

type PullResponse

type PullResponse struct {
	Events        []PullEvent `json:"events"`
	LastServerSeq int64       `json:"last_server_seq"`
	HasMore       bool        `json:"has_more"`
}

PullResponse is the JSON response for a pull request.

type PushRequest

type PushRequest struct {
	DeviceID  string       `json:"device_id"`
	SessionID string       `json:"session_id"`
	Events    []EventInput `json:"events"`
}

PushRequest is the JSON body for POST /v1/projects/{id}/sync/push.

type PushResponse

type PushResponse struct {
	Accepted int              `json:"accepted"`
	Acks     []AckResponse    `json:"acks"`
	Rejected []RejectResponse `json:"rejected,omitempty"`
}

PushResponse is the JSON response for a push request.

type RateLimiter

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

RateLimiter implements per-key fixed-window rate limiting.

func NewRateLimiter

func NewRateLimiter() *RateLimiter

NewRateLimiter creates a RateLimiter and starts background cleanup.

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow(key string, limit int) bool

Allow checks if the key is within the rate limit (limit per 1-minute window).

type RejectResponse

type RejectResponse struct {
	ClientActionID int64  `json:"client_action_id"`
	Reason         string `json:"reason"`
	ServerSeq      int64  `json:"server_seq,omitempty"`
}

RejectResponse is a single rejected event.

type Server

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

Server is the HTTP API server for td-sync.

func NewServer

func NewServer(cfg Config, store *serverdb.ServerDB) (*Server, error)

NewServer creates a new Server with the given config and store.

func (*Server) CORSMiddleware added in v0.32.0

func (s *Server) CORSMiddleware(next http.Handler) http.Handler

CORSMiddleware handles CORS for admin routes. If no allowed origins are configured, it passes through without setting headers.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops the server and closes all project databases.

func (*Server) Start

func (s *Server) Start() error

Start begins listening for HTTP requests (non-blocking).

type SnapshotQuerySource added in v0.32.0

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

SnapshotQuerySource implements query.QuerySource for read-only snapshot databases. It runs SQL directly against a snapshot *sql.DB (same schema as the client-side DB).

func NewSnapshotQuerySource added in v0.32.0

func NewSnapshotQuerySource(sqlDB *sql.DB) *SnapshotQuerySource

NewSnapshotQuerySource wraps a read-only *sql.DB as a QuerySource.

func (*SnapshotQuerySource) GetComments added in v0.32.0

func (s *SnapshotQuerySource) GetComments(issueID string) ([]models.Comment, error)

GetComments retrieves comments for an issue.

func (*SnapshotQuerySource) GetDependencies added in v0.32.0

func (s *SnapshotQuerySource) GetDependencies(issueID string) ([]string, error)

GetDependencies returns IDs of issues that issueID depends on.

func (*SnapshotQuerySource) GetIssue added in v0.32.0

func (s *SnapshotQuerySource) GetIssue(id string) (*models.Issue, error)

GetIssue retrieves a single issue by ID.

func (*SnapshotQuerySource) GetIssuesWithOpenDeps added in v0.32.0

func (s *SnapshotQuerySource) GetIssuesWithOpenDeps() (map[string]bool, error)

GetIssuesWithOpenDeps returns issue IDs that have at least one non-closed dependency.

func (*SnapshotQuerySource) GetLatestHandoff added in v0.32.0

func (s *SnapshotQuerySource) GetLatestHandoff(issueID string) (*models.Handoff, error)

GetLatestHandoff retrieves the latest handoff for an issue.

func (*SnapshotQuerySource) GetLinkedFiles added in v0.32.0

func (s *SnapshotQuerySource) GetLinkedFiles(issueID string) ([]models.IssueFile, error)

GetLinkedFiles returns files linked to an issue.

func (*SnapshotQuerySource) GetLogs added in v0.32.0

func (s *SnapshotQuerySource) GetLogs(issueID string, limit int) ([]models.Log, error)

GetLogs retrieves logs for an issue, including work session logs.

func (*SnapshotQuerySource) GetRejectedInProgressIssueIDs added in v0.32.0

func (s *SnapshotQuerySource) GetRejectedInProgressIssueIDs() (map[string]bool, error)

GetRejectedInProgressIssueIDs returns IDs of in_progress issues that have a recent reject action without a subsequent review action (needs rework).

func (*SnapshotQuerySource) ListIssues added in v0.32.0

func (s *SnapshotQuerySource) ListIssues(opts db.ListIssuesOptions) ([]models.Issue, error)

ListIssues queries the issues table with filters from ListIssuesOptions.

type SyncStatusResponse

type SyncStatusResponse struct {
	EventCount    int64  `json:"event_count"`
	LastServerSeq int64  `json:"last_server_seq"`
	LastEventTime string `json:"last_event_time,omitempty"`
}

SyncStatusResponse is the JSON response for GET /v1/projects/{id}/sync/status.

type UpdateMemberRequest

type UpdateMemberRequest struct {
	Role string `json:"role"`
}

UpdateMemberRequest is the JSON body for PATCH /v1/projects/{id}/members/{userID}.

type UpdateProjectRequest

type UpdateProjectRequest struct {
	Name        *string `json:"name"`
	Description *string `json:"description"`
}

UpdateProjectRequest is the JSON body for PATCH /v1/projects/{id}.

Jump to

Keyboard shortcuts

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