notify

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: EUPL-1.2 Imports: 13 Imported by: 0

Documentation

Overview

Package notify implements infrastructure adapters for notification operations.

The notify package provides concrete implementations of the OperationProvider port defined in the domain layer, enabling workflow steps to send notifications through multiple backends (desktop, webhook) without shell scripting. The provider supports built-in notification backends with 10-second HTTP timeout for network-based backends and platform detection for desktop notifications.

Architecture Role

In the hexagonal architecture:

  • Implements domain/ports.OperationProvider (NotifyOperationProvider adapter)
  • Registers 1 notification operation (notify.send) via OperationRegistry at startup
  • Application layer orchestrates notification steps via the OperationProvider port
  • Domain layer defines operation contracts without notification backend coupling

All notification-specific types remain internal to this infrastructure adapter. The domain layer reuses existing OperationSchema, OperationResult, and InputSchema types without requiring new entities. This prevents domain layer pollution while maintaining full compile-time type safety.

Operation Types

## Declarative Operations (operations.go)

Supported notification operations:

  • notify.send: Send notification via configured backend (desktop, webhook)

Each operation is registered as an OperationSchema with input validation, output schema, and backend selection support.

Provider Implementation

## NotifyOperationProvider (provider.go)

Operation execution and dispatch:

  • ListOperations: Enumerate registered notification operations
  • GetOperation: Retrieve operation schema by name
  • Execute: Dispatch to backend based on backend input parameter

The provider uses a map-based dispatch with Backend interface to route to the appropriate notification backend. This keeps all notification logic in one cohesive package without requiring interface-per-backend abstractions (ADR-003).

Notification Backends

## Backend Interface (types.go)

All backends implement a common Send interface:

  • Send(ctx context.Context, payload NotificationPayload) (*BackendResult, error)

## DesktopBackend (desktop.go)

Platform-native desktop notifications:

  • Linux: Uses notify-send via libnotify
  • macOS: Uses osascript with 'display notification' AppleScript
  • Detects platform at runtime and fails gracefully on unsupported systems

## WebhookBackend (webhook.go)

Generic HTTP webhook integration:

  • JSON POST with standard AWF payload structure
  • Supports any webhook-compatible service (Discord, Teams, PagerDuty, etc.)
  • Fields: workflow, status, duration, message, outputs

Configuration

## NotifyConfig (types.go)

Configuration resolution from .awf/config.yaml:

  • default_backend: Backend to use when not specified in operation inputs

Configuration values are loaded at provider initialization and injected into backend instances.

Error Handling

Operations return standard Go errors via fmt.Errorf with contextual messages.

Common error patterns:

  • notify_missing_config: Required configuration value not provided
  • notify_backend_not_found: Requested backend not available
  • notify_missing_input: Required backend-specific input not provided
  • notify_http_error: HTTP backend returned non-2xx status
  • notify_timeout: Backend request exceeded 10-second timeout
  • notify_platform_unsupported: Desktop backend unavailable on platform

All errors are wrapped with fmt.Errorf for error chain support.

Integration Points

## CLI Wiring (internal/interfaces/cli/run.go)

Provider registration at startup:

  • Create NotifyOperationProvider instance with config
  • Create CompositeOperationProvider wrapping GitHub + Notify providers
  • Connect to ExecutionService via SetOperationProvider()
  • Follows F054 GitHub plugin wiring pattern

The provider is instantiated in the composition root (run.go) and injected into the application layer via dependency inversion. This enables compile-time wiring without RPC overhead (ADR-001).

Performance and Security

Performance characteristics:

  • HTTP timeout: 10 seconds for network-based backends (webhook)
  • Desktop notifications: Platform-specific, typically <100ms
  • No retries: Failed notifications return error immediately

Security measures:

  • webhook URLs and tokens never logged
  • Input validation prevents command injection in desktop backend
  • Context cancellation propagated to all backends
  • HTTP client follows redirects only for same-host (prevents SSRF)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AllOperations

func AllOperations() []pluginmodel.OperationSchema

Types

type Backend

type Backend interface {
	// Send delivers a notification using this backend.
	// Returns BackendResult on success or error on failure.
	// The context is used for cancellation and timeout control.
	Send(ctx context.Context, payload NotificationPayload) (*BackendResult, error)
}

Backend defines how a notification is delivered. Each backend implementation (desktop, webhook) implements this interface with backend-specific delivery logic.

func NewDesktopBackend

func NewDesktopBackend() Backend

NewDesktopBackend creates a new desktop notification backend (exported). No configuration is required for desktop notifications. This is the public API used for CLI wiring in run.go.

func NewWebhookBackend

func NewWebhookBackend() Backend

NewWebhookBackend creates a new webhook notification backend (exported). Webhook URLs are provided per-request via metadata rather than at construction time. This is the public API used for CLI wiring in run.go.

type BackendResult

type BackendResult struct {
	// Backend identifies which backend handled the notification
	Backend string

	// StatusCode is the HTTP status code for network backends (0 for desktop)
	StatusCode int

	// Response is the response body or confirmation message
	Response string
}

BackendResult contains the outcome of a notification delivery. It is returned by backend implementations after successful or failed sends.

type NotificationPayload

type NotificationPayload struct {
	// Title is the notification title (optional, defaults to "AWF Workflow")
	Title string

	// Message is the notification body (required)
	Message string

	// Priority indicates the notification urgency: "low", "default", or "high"
	// (optional, defaults to "default")
	Priority string

	// Metadata contains additional context like workflow name, status, duration
	Metadata map[string]string
}

NotificationPayload contains the data sent to a notification backend. It is an immutable value object constructed by the provider and passed to backend implementations.

type NotifyConfig

type NotifyConfig struct {
	// DefaultBackend is the backend to use when not specified in operation inputs
	// (valid values: "desktop", "webhook")
	DefaultBackend string
}

NotifyConfig holds notification plugin configuration from .awf/config.yaml. These values are loaded at provider initialization and used by backends to resolve configuration like URLs and default backend selection.

type NotifyOperationProvider

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

NotifyOperationProvider implements ports.OperationProvider for notification operations. Dispatches notify.send operation to backend-specific handlers (desktop, webhook).

The provider manages:

  • Operation schema registry (notify.send)
  • Backend dispatch via Backend interface
  • Dynamic backend registration via RegisterBackend
  • Input validation and payload construction

func NewNotifyOperationProvider

func NewNotifyOperationProvider(logger ports.Logger) *NotifyOperationProvider

NewNotifyOperationProvider creates a new notification operation provider.

The provider starts with an empty backend registry. Use RegisterBackend to add notification backends dynamically. This enables the open/closed principle: new backends can be added without modifying the provider implementation.

Parameters:

  • logger: structured logger for operation tracing

Returns:

  • *NotifyOperationProvider: configured provider ready for backend registration

func (*NotifyOperationProvider) Execute

Execute runs a notification operation by name with the given inputs. Dispatches to backend-specific handlers based on the 'backend' input.

Implements ports.OperationProvider.

func (*NotifyOperationProvider) GetOperation

GetOperation returns an operation schema by name. Implements ports.OperationProvider.

func (*NotifyOperationProvider) ListOperations

func (p *NotifyOperationProvider) ListOperations() []*pluginmodel.OperationSchema

ListOperations returns all available notification operations. Implements ports.OperationProvider.

func (*NotifyOperationProvider) RegisterBackend

func (p *NotifyOperationProvider) RegisterBackend(name string, backend Backend) error

RegisterBackend registers a notification backend with the provider.

Backends are registered by name (e.g., "desktop", "webhook") and must implement the Backend interface. Registration is idempotent: duplicate registrations for the same name return an error.

Parameters:

  • name: backend identifier (must be unique)
  • backend: implementation of the Backend interface

Returns:

  • error: non-nil if name is already registered or backend is nil

func (*NotifyOperationProvider) SetDefaultBackend

func (p *NotifyOperationProvider) SetDefaultBackend(name string)

SetDefaultBackend configures the fallback backend name.

The default backend is used when Execute is called without an explicit 'backend' input parameter. If no default is set and no backend is specified in inputs, Execute returns an error.

Parameters:

  • name: backend identifier to use as default

Jump to

Keyboard shortcuts

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