SAMA is a service availability monitoring and alerting system built as a containerizable .NET 10 application following KISS principles with a simple layered architecture.
┌─────────────────────────────────────────────────────────────┐
│ SAMA Main Application │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Web Layer (Razor Pages + HTMX) │ │
│ │ - Dashboard, Check Management, Alert Configuration │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Service Layer │ │
│ │ - Business Logic, Orchestration │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Background Services (Quartz.NET) │ │
│ │ - Check Scheduler, Built-in Check Executor │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Agent API (REST) │ │
│ │ - Agent Registration, Check Assignment, Result Collection│
│ └────────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Data Access Layer (EF Core) │ │
│ │ - PostgreSQL Support │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
├─── Database (PostgreSQL)
│
┌───────────────────┴───────────────────┐
│ │
┌───────▼────────┐ ┌────────▼────────┐
│ SAMA Agent 1 │ │ SAMA Agent N │
│ (Region: US) │ │ (Region: EU) │
│ │ │ │
│ - Check Exec │ │ - Check Exec │
│ - Advanced │ │ - Advanced │
│ Checks │ │ Checks │
└────────────────┘ └─────────────────┘
SAMA/
├── SAMA.Web/ # Main ASP.NET Core application
│ ├── Pages/ # Razor Pages
│ ├── Services/ # Business logic services
│ ├── Models/ # Domain models
│ ├── BackgroundServices/ # Quartz.NET jobs
│ ├── Middleware/ # Custom middleware
│ ├── Program.cs
│ └── Dockerfile # Web app Dockerfile
│
├── SAMA.Data/ # Data access layer
│ ├── Entities/ # EF Core entities
│ ├── Migrations/ # Database migrations
│ └── SamaDbContext.cs
│
├── SAMA.Shared/ # Shared library (referenced by agents)
│ ├── Checks/ # Check implementations
│ │ ├── HttpCheck.cs
│ │ ├── TcpCheck.cs
│ │ ├── PingCheck.cs
│ │ ├── DnsCheck.cs
│ │ ├── TlsCertificateCheck.cs
│ │ └── ScriptCheck.cs
│ ├── Alerts/ # Notification channel implementations
│ │ ├── EmailAlert.cs
│ │ ├── SlackAlert.cs
│ │ ├── TeamsAlert.cs
│ │ ├── DiscordAlert.cs
│ │ ├── ScriptAlert.cs
│ │ └── EventGridAlert.cs
│ ├── Models/ # Shared DTOs and models
│ └── Utilities/ # Common utilities
│
├── SAMA.Agent/ # Distributed agent application
│ ├── Services/ # Agent-specific services
│ ├── Checks/ # Advanced checks
│ │ ├── PlaywrightCheck.cs
│ │ └── DatabaseCheck.cs
│ ├── Program.cs
│ └── Dockerfile # Agent Dockerfile
│
├── SAMA.Tests.Unit/ # Unit tests (MSTest)
├── SAMA.Tests.Integration/ # Integration tests
├── SAMA.Tests.System/ # System/E2E tests
│
├── docker-compose.yml # Compose for deployment
├── SAMA.slnx # Solution file
│
└── docs/
├── ARCHITECTURE.md
├── DATABASE_SCHEMA.md
└── ROADMAP.md
- .NET 10: Latest LTS version
- ASP.NET Core: Web framework with Razor Pages
- Entity Framework Core: ORM with PostgreSQL support
- Quartz.NET: Job scheduling
- Serilog: Structured logging
- MSTest: Unit testing framework
- NSubstitute: Mocking framework for test doubles
- Razor Pages: Server-side rendering
- HTMX: Dynamic UI updates via polling
- Chart.js: Response time visualization
- Bootstrap 5: Responsive UI framework
- PostgreSQL (development and production)
- ASP.NET Core Identity: User management with passkey support
- LDAP/Active Directory: On-premises directory integration
- OIDC: Integration with Azure AD/Entra, Okta, Auth0, etc.
Simple architecture with clear separation:
- Presentation & Business Logic (SAMA.Web): UI, API endpoints, services, and domain logic
- Data Access (SAMA.Data): EF Core entities and DbContext
- Shared (SAMA.Shared): Cross-cutting concerns and check implementations
- Executed by main application via Quartz.NET
- Check types: HTTP/HTTPS, TCP, Ping, DNS, TLS Certificate, Script
- Scheduled based on configured intervals
- Runs in background worker threads
- Executed by remote agents
- Check types: All built-in + Playwright, Database connectivity
- Enables geo-distributed monitoring
- Agents poll for assigned checks via REST API
- Administrator creates agent in SAMA UI
- System generates random API key
- Administrator provides API key to agent via configuration
- Agent authenticates using API key in Authorization header
- Main app validates API key against registered agents
- Agents poll
/api/agents/{agentId}/checks/assignedendpoint - Authorization header:
Bearer {apiKey} - Returns list of checks to execute with configuration
- Polling interval: configurable (default 30 seconds)
- Agents POST results to
/api/agents/{agentId}/checks/{checkId}/results - Authorization header:
Bearer {apiKey} - Payload includes status, response time, error details
- Main app processes results and triggers alerts if needed
- All check configuration data encrypted at rest using AES-256
- Symmetric key provided via environment variable:
SAMA_ENCRYPTION_KEY - Encryption handled transparently in data layer
- Sensitive fields: passwords, API keys, webhook URLs, connection strings
SAMA provides two complementary notification systems:
- Per-check alerts with threshold-based triggering
- Notification channels defined per workspace (reusable across checks)
- Many-to-many relationship: One alert can notify multiple channels simultaneously
- All channels receive the same alert with identical threshold and trigger conditions
- Alerts trigger based on: status (Degraded/Down), consecutive failure count
- Recovery notifications sent when check returns to Up state
- Simple boolean flags and integer thresholds (no complex JSON conditions)
- Default behavior: If no channels selected, sends to all enabled workspace channels
- Safe because alerts are already filtered by thresholds (prevents spam)
- Designed for human notification with fail-safe defaults
Example: Create one alert that notifies Email, Slack, and Teams when a check fails 3 consecutive times. All three channels receive notifications with the same conditions.
- Workspace-level event routing for operational automation
- Subscribe to lifecycle events: CheckCreated, CheckUpdated, CheckDeleted
- Subscribe to status change events: CheckStatusChanged (Up→Degraded, Up→Down, Degraded→Down, Down→Degraded, Degraded→Up, Down→Up)
- Route events to any notification channel (Email, Slack, Teams, Discord, Webhook, Script, EventGrid)
- Enable external workflow integrations via Azure Event Grid or custom webhooks
- Use cases: Change tracking, compliance auditing, CI/CD integration, CMDB synchronization, real-time status streaming, external incident management integration
- Default behavior: If no channels selected, events are not sent anywhere
- Intentional to prevent accidental spam (especially for high-volume CheckStatusChanged events)
- Designed for integration/automation with explicit opt-in
Unlike Alerts (which have thresholds and filtering), EventSubscriptions send raw events immediately with no filtering.
- Dashboard uses HTMX polling for updates (default: 5 seconds)
- Polls
/api/dashboard/statusfor current state - Partial page updates via HTMX swaps
- Future: SSE support for true push updates
- PostgreSQL as the only supported database
- EF Core migrations for PostgreSQL
- Automatic migration on startup: Migrations are applied automatically when the application starts
- Application will fail to start if migrations cannot be applied
- Default: PostgreSQL container for development
Local Accounts:
- ASP.NET Core Identity
- Passphrase-friendly password policy: minimum 14 characters, no complexity requirements
- Account lockout protection
- Future enhancement: Passkey support
LDAP/Active Directory:
- Direct bind and search+bind authentication modes
- SSL/TLS and StartTLS support with custom Root CA certificates
- Admin UI for LDAP server configuration and test login
- JIT user provisioning on successful LDAP login
- Account linking: existing local users matched by email are linked to LDAP; local password login is then disabled
- Group membership queries for role/workspace auto-provisioning
Future:
- OIDC integration (Azure AD/Entra, Okta, Auth0, etc.)
- SAML2 SSO support may be added based on demand
- Role-based access control (RBAC)
- Global Role: Admin (full system access)
- Can be assigned manually via ASP.NET Identity
- Can be auto-provisioned via LDAP/OIDC group mappings
- Workspace Roles: Editor, Viewer (scoped per workspace via UserWorkspaces)
- Guest: Unauthenticated users can view public workspaces
- External Group Mapping: Auto-provision Admin or workspace access via LDAP/OIDC group mappings
- Agent API: API key-based authentication (Bearer token)
- Future REST API: JWT tokens or API keys
- Sensitive data encrypted at rest
- HTTPS enforced
- Secrets via environment variables
- Audit logging for all modifications
- 50 monitored endpoints
- 25 concurrent checks
- 10 users
- No sub-second check intervals
- Async/parallel check execution
- Agent-based horizontal scaling for checks
- Database indexing strategy for performance
- Resource prioritization (UI > built-in checks)
- Agents: Multiple instances per region
- Main app: Single instance (HA out of scope for MVP)
- Database: Standard backup/restore procedures
- PostgreSQL in Docker container
- Automatic migration application on startup
- Appsettings.Development.json for config
- Docker containers via Docker Compose
- Environment variables for configuration
- Volume mounts for persistent data
- Health check endpoints for monitoring
- Automatic database migrations on container startup
- Application fails fast if migrations cannot be applied
sama-web: Main application + built-in checkssama-agent: Distributed agent- Images published to GitHub Container Registry (GHCR)
- Multi-stage builds for optimized images
- Dockerfiles located in respective project directories
- Automatic on startup: No manual intervention required
- Fail-fast behavior: Application will not start if migrations fail
- Deployment simplicity: Just start the container, migrations handled automatically
- Rollback: Use database backups and restore to previous version if needed
- Zero-downtime migrations: Not supported in MVP (requires HA setup)
- Serilog with structured logging
- Log levels: Debug, Information, Warning, Error, Critical
- Console sink for development
- File/persistent sink for production
- Migration status logged on startup
- ASP.NET Core health check endpoint at
/health - Database connectivity check
- Background service status check
- Migration status included in startup logs
- Framework: MSTest with NSubstitute for mocking
- Location:
SAMA.Tests.Unit/ - Naming Convention:
{ClassName}Tests.cs(e.g.,TcpCheckExecutorTests.cs) - Test Naming:
{Method}Should{ExpectedBehavior}When{Condition}(e.g.,ExecuteAsyncShouldReturnDownWhenHostNotConfigured) - Mocking Strategy:
- Use wrapper classes with virtual methods for external dependencies (e.g.,
TcpClientWrapper,TcpClientFactory) - Mock wrappers using NSubstitute in tests
- Avoid real network I/O in unit tests
- Use wrapper classes with virtual methods for external dependencies (e.g.,
- Pattern: Arrange-Act-Assert (AAA) with shared mock setup in
[TestInitialize] - Coverage Target: Business logic and check executors
- Location:
SAMA.Tests.Integration/ - Strategy: Real PostgreSQL database with per-test-class schema isolation
- Scope: Database interactions, service workflows, entity relationships
- Execution: Parallel across test classes, sequential within a class
- Location:
SAMA.Tests.System/ - Scope: End-to-end scenarios, UI workflows
- Future: Playwright for browser automation
- Keep unit tests fast (< 100ms each)
- Use mocks to eliminate external dependencies
- Test edge cases and error handling
- Follow KISS principle - simple, readable tests
- Monolith with local authentication
- Built-in checks only
- Basic alerting
- Core dashboard
- Automatic migrations on startup
- LDAP/Active Directory authentication
- Group-based workspace provisioning (LDAP)
- Agent support with advanced checks (Playwright, Database)
- OIDC authentication
- Enhanced alerting rules
- Advanced reporting
- Alert acknowledgment workflow
- SSE for real-time updates
- SAML SSO (if demand warrants)
- REST API for external integrations
- Alert escalation
- Maintenance windows
- Public status pages
- Multi-tenancy
- Alert suppression/throttling