Documentation
¶
Overview ¶
Package watchdaemon hosts DataTug's independently composable Watch roles.
Index ¶
- func ValidateEndpoint(endpoint string) error
- type Authenticator
- type Client
- type Config
- type CoordinatorStore
- type Credential
- type EmailMessage
- type EmailSender
- type Executor
- type ExecutorFunc
- type FileEmailSink
- type FileSMSSink
- type Limits
- type Runner
- type SMSMessage
- type SMSSender
- type SMTPConfig
- type SMTPSender
- type Server
- type TelegramBotConfig
- type TwilioSMSSender
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValidateEndpoint ¶
ValidateEndpoint permits TLS, or explicit loopback HTTP for local operation. Credentials, fragments and query strings never belong in manifest endpoints.
Types ¶
type Authenticator ¶
type Authenticator struct {
// contains filtered or unexported fields
}
func NewAuthenticator ¶
func NewAuthenticator(credentials []Credential) (*Authenticator, error)
func (*Authenticator) Authenticate ¶
func (a *Authenticator) Authenticate(r *http.Request, kind string) (Credential, bool)
type Config ¶
type Config struct {
Namespace string `json:"namespace"`
Listen string `json:"listen,omitempty"`
TLSCertFile string `json:"tlsCertFile,omitempty"`
TLSKeyFile string `json:"tlsKeyFile,omitempty"`
Credentials []Credential `json:"credentials"`
AllowedOrigins []string `json:"allowedOrigins,omitempty"`
PublicUIURL string `json:"publicUIURL,omitempty"`
ProjectUIURLs map[string]string `json:"projectUIURLs,omitempty"`
Limits Limits `json:"limits,omitempty"`
Storage struct {
DALGOConnectionEnv string `json:"dalgoConnectionEnv"`
} `json:"storage"`
Runner struct {
TokenEnv string `json:"tokenEnv"`
CoordinatorEndpoint string `json:"coordinatorEndpoint"`
ProjectDir string `json:"projectDir"`
Environment string `json:"environment"`
Principal string `json:"principal"`
EvidenceDir string `json:"evidenceDir"`
AllowOpaqueSQL bool `json:"allowOpaqueSQL,omitempty"`
Telegram *TelegramBotConfig `json:"telegram,omitempty"`
} `json:"runner"`
Notifications struct {
EmailSink string `json:"emailSink,omitempty"`
SMTP *SMTPConfig `json:"smtp,omitempty"`
SMSSink string `json:"smsSink,omitempty"`
Twilio bool `json:"twilio,omitempty"`
} `json:"notifications"`
}
Config belongs to the daemon deployment. Projects carry only coordination endpoint and namespace; credentials and storage are never read from a project.
func LoadConfig ¶
type CoordinatorStore ¶
type CoordinatorStore interface {
Health(context.Context) error
ListDefinitions(context.Context, watch.Actor) ([]watch.Definition, error)
GetDefinition(context.Context, watch.Actor, string) (watch.Definition, error)
PutDefinition(context.Context, watch.Actor, watch.Definition, string, int64) (watch.Definition, error)
DeleteDefinition(context.Context, watch.Actor, string, string, int64) error
SetLifecycle(context.Context, watch.Actor, string, string, string, int64) (watch.Definition, error)
ResetBaseline(context.Context, watch.Actor, string, string, int64) (watch.Definition, error)
Subscribe(context.Context, watch.Actor, watch.Subscription) error
GetSubscription(context.Context, watch.Actor, string) (watch.Subscription, error)
ListRuns(context.Context, watch.Actor, string) ([]watch.Run, error)
ListDeliveries(context.Context, watch.Actor, string) ([]watch.Delivery, error)
RetryNotification(context.Context, watch.Actor, string) error
RegisterRunner(context.Context, watch.RunnerIdentity) error
ClaimDue(context.Context, watch.RunnerIdentity) (*watch.Claim, error)
Heartbeat(context.Context, watch.RunnerIdentity, string, int64) error
FinishRun(context.Context, watch.RunnerIdentity, watch.Completion) (watch.Run, error)
Inbox(context.Context, watch.Actor) ([]watch.Notification, error)
MarkRead(context.Context, watch.Actor, string) error
Status(context.Context, watch.Actor) (watch.Status, error)
Reconcile(context.Context) error
ClaimNotifications(context.Context) (*watch.Delivery, error)
FinishNotification(context.Context, string, int64, string) error
}
CoordinatorStore owns all transactional state; transports never implement scheduling, state transitions, visibility or lease decisions themselves.
type Credential ¶
type Credential struct {
TelegramBotID string `json:"telegramBotId,omitempty"`
TokenEnv string `json:"tokenEnv"`
Kind string `json:"kind"` // user or runner
ID string `json:"id"`
AccountID string `json:"accountId,omitempty"`
Namespace string `json:"namespace"`
Project string `json:"project"`
Environment string `json:"environment"`
Capabilities []string `json:"capabilities,omitempty"`
Email string `json:"email,omitempty"`
Tier string `json:"tier,omitempty"`
Phone string `json:"phone,omitempty"`
}
Credential is deployment-owned authority. Tokens are resolved from the environment at startup, never accepted from a project or a request body.
type EmailMessage ¶
type EmailMessage struct {
ID string `json:"id"`
To string `json:"to"`
Subject string `json:"subject"`
Body string `json:"body"`
}
EmailMessage contains only notification metadata, never query rows or inputs.
type EmailSender ¶
type EmailSender interface {
Send(context.Context, EmailMessage) error
}
type ExecutorFunc ¶
func (ExecutorFunc) Execute ¶
func (f ExecutorFunc) Execute(ctx context.Context, c watch.Claim) (watch.Completion, error)
type FileEmailSink ¶
type FileEmailSink struct {
Path string
// contains filtered or unexported fields
}
FileEmailSink is a persistent development mailbox. Stable message IDs make retries idempotent, including after a daemon restart. Use one coordinator.
func (*FileEmailSink) Send ¶
func (s *FileEmailSink) Send(ctx context.Context, message EmailMessage) error
type FileSMSSink ¶
type FileSMSSink struct{ Sink *FileEmailSink }
FileSMSSink shares the crash-safe, ID-deduplicated development mailbox kernel. Its To field ends in @sms.test and preserves the verified E.164 recipient.
func (FileSMSSink) Send ¶
func (s FileSMSSink) Send(ctx context.Context, m SMSMessage) error
type Limits ¶
type Limits struct {
EmailPerDay int `json:"emailPerDay,omitempty"`
EmailPerMinute int `json:"emailPerMinute,omitempty"`
SMSPerDay int `json:"smsPerDay,omitempty"`
SMSPerMinute int `json:"smsPerMinute,omitempty"`
TelegramPerDay int `json:"telegramPerDay,omitempty"`
TelegramPerMinute int `json:"telegramPerMinute,omitempty"`
WatchesPerUser int `json:"watchesPerUser,omitempty"`
MinIntervalSeconds int `json:"minIntervalSeconds,omitempty"`
}
type Runner ¶
type SMSMessage ¶
type SMSMessage struct{ ID, To, Body string }
type SMTPConfig ¶
type SMTPConfig struct {
Address string `json:"address"`
From string `json:"from"`
UsernameEnv string `json:"usernameEnv,omitempty"`
PasswordEnv string `json:"passwordEnv,omitempty"`
// AllowLoopbackPlaintext is only for a local development SMTP receiver.
AllowLoopbackPlaintext bool `json:"allowLoopbackPlaintext,omitempty"`
}
type SMTPSender ¶
type SMTPSender struct{ Config SMTPConfig }
func (SMTPSender) Send ¶
func (s SMTPSender) Send(ctx context.Context, m EmailMessage) error
type Server ¶
type Server struct {
Store CoordinatorStore
Auth *Authenticator
AllowedOrigins []string
Email EmailSender
SMS SMSSender
PublicUIURL string
ProjectUIURLs map[string]string
Limits Limits
}
func (*Server) RunCoordinator ¶
RunCoordinator reconciles due schedules separately from assignment and drains the durable delivery outbox. A failed delivery never changes evaluation truth.
type TelegramBotConfig ¶
type TelegramBotConfig struct {
BotID string `json:"botID"`
SecretEnv string `json:"secretEnv,omitempty"`
TokenEnv string `json:"tokenEnv,omitempty"`
}
TelegramBotConfig is runner-only deployment configuration. Neither token nor secret is sent to the coordinator or saved in a project.
type TwilioSMSSender ¶
type TwilioSMSSender struct {
Credentials twiliosms.Credentials
Transport http.RoundTripper
}
TwilioSMSSender reuses the ecosystem's shared SMS provider kernel. Credentials remain deployment-owned. Provider errors are deliberately reduced to a code.
func (TwilioSMSSender) Send ¶
func (s TwilioSMSSender) Send(ctx context.Context, m SMSMessage) error