The LFX v2 Meeting Service is a comprehensive microservice that handles all meeting-related operations for the Linux Foundation's LFX platform. Built with Go and the Goa framework, it provides robust CRUD operations for meetings and registrants with NATS JetStream persistence and JWT authentication.
If you just need to run the service without developing on the service, use the Helm chart:
# Install the meeting service
helm upgrade --install lfx-v2-meeting-service ./charts/lfx-v2-meeting-service \
--namespace lfx \
--create-namespace \
--set image.tag=latest
-
Prerequisites
- Go 1.24+ installed
- Make installed
- Docker (optional, for containerized development)
- NATS server running (for local testing)
-
Clone and Setup
git clone https://github.com/linuxfoundation/lfx-v2-meeting-service.git cd lfx-v2-meeting-service # Install dependencies and generate API code make deps make apigen
-
Configure Environment (Optional)
# Copy the example environment file and configure it cp .env.example .env # Edit .env with your local settings
-
Run the Service
# Run with default settings make run # Or run with debug logging make debug
The service is built using a clean architecture pattern with the following layers:
- API Layer: Goa-generated HTTP handlers and OpenAPI specifications
- Service Layer: Business logic and orchestration
- Domain Layer: Core business models and interfaces
- Infrastructure Layer: NATS persistence, JWT authentication, and messaging
- Meeting Management: Complete CRUD operations with platform integration (Zoom support)
- Registrant Management: Registration handling with email uniqueness validation
- Historical Tracking: Past meeting records with session tracking and participant attendance
- Webhook Integration: Platform event processing for real-time meeting state updates
- NATS JetStream Storage: Scalable and resilient data persistence across 5 KV buckets
- NATS Messaging: Event-driven communication with other services
- JWT Authentication: Secure API access via Heimdall integration
- OpenAPI Documentation: Auto-generated API specifications
- Comprehensive Testing: Full unit test coverage with mocks
lfx-v2-meeting-service/
βββ cmd/ # Application entry points
β βββ meeting-api/ # Main API server
βββ charts/ # Helm chart for Kubernetes deployment
β βββ lfx-v2-meeting-service/
βββ design/ # Goa API design files
β βββ meeting-svc.go # Main service definition
β βββ meeting_types.go # Meeting type definitions
β βββ registrant_types.go # Registrant type definitions
β βββ types.go # Common type definitions
βββ gen/ # Generated code (DO NOT EDIT)
β βββ http/ # HTTP transport layer
β βββ meeting_service/ # Service interfaces
βββ internal/ # Private application code
β βββ domain/ # Business domain layer
β β βββ models/ # Domain models and conversions
β β βββ errors.go # Domain-specific errors
β β βββ messaging.go # Messaging abstractions
β β βββ repository.go # Repository interfaces
β βββ infrastructure/ # Infrastructure layer
β β βββ auth/ # JWT authentication
β β βββ messaging/ # NATS messaging implementation
β β βββ store/ # NATS KV store repositories
β βββ middleware/ # HTTP middleware
β βββ service/ # Service layer implementation
βββ pkg/ # Public packages
β βββ constants/ # Application constants
β βββ utils/ # Utility functions
βββ Dockerfile # Container build configuration
βββ Makefile # Build and development commands
βββ go.mod # Go module definition
- Go 1.24+
- Make
- Git
-
Install Dependencies
make deps
This installs:
- Go module dependencies
- Goa CLI for code generation
- golangci-lint for code linting
-
Generate API Code
make apigen
Generates HTTP transport, client, and OpenAPI documentation from design files.
-
Build the Application
make build
Creates the binary in
bin/meeting-api
.
# Run with auto-regeneration
make run
# Run with debug logging
make debug
# Build and run binary
make build
./bin/meeting-api
Always run these before committing:
# Format code
make fmt
# Run linter
make lint
# Run all tests
make test
# Check everything (format + lint + tests)
make check
# Run all tests with race detection and coverage
make test
# Run tests with verbose output
make test-verbose
# Generate HTML coverage report
make test-coverage
# Opens coverage/coverage.html
Writing Tests:
- Place test files alongside source files with
_test.go
suffix - Use table-driven tests for multiple test cases
- Mock external dependencies using the provided mock interfaces
- Achieve high test coverage (aim for >80%)
- Test both happy path and error cases
When modifying the API:
-
Update Design Files in
design/
directory -
Regenerate Code:
make apigen
-
Verify Generation:
make verify
-
Run Tests to ensure nothing breaks:
make test
The Zoom integration follows a layered architecture pattern:
Adding New Zoom API Endpoints:
-
Add API Methods in
internal/infrastructure/zoom/api/
:- Add new methods to appropriate API client interfaces
- Implement the methods with proper error handling
- Add corresponding mock implementations for testing
-
Update Provider Layer in
internal/infrastructure/zoom/provider.go
:- Add business logic methods that orchestrate API calls
- Handle Zoom-specific data transformations
- Implement domain interfaces
-
Add Tests:
# Test the new API methods go test ./internal/infrastructure/zoom/api/... # Test the provider integration go test ./internal/infrastructure/zoom/...
Zoom Package Structure:
internal/infrastructure/zoom/
βββ api/ # Low-level Zoom API clients
β βββ client.go # HTTP client and auth
β βββ meetings.go # Meetings API endpoints
β βββ users.go # Users API endpoints
β βββ mocks/ # Mock implementations
βββ provider.go # Business logic layer
βββ provider_test.go # Integration tests
Environment Variables:
ZOOM_ACCOUNT_ID
: OAuth Server-to-Server Account IDZOOM_CLIENT_ID
: OAuth App Client IDZOOM_CLIENT_SECRET
: OAuth App Client Secret
For local development, copy .env.example
to .env
and fill in your Zoom credentials from 1Password.
Target | Description |
---|---|
make all |
Complete build pipeline (clean, deps, apigen, fmt, lint, test, build) |
make deps |
Install dependencies and tools |
make apigen |
Generate API code from design files |
make build |
Build the binary |
make run |
Run the service locally |
make debug |
Run with debug logging |
make test |
Run unit tests |
make test-verbose |
Run tests with verbose output |
make test-coverage |
Generate HTML coverage report |
make lint |
Run code linter |
make fmt |
Format code |
make check |
Verify formatting and run linter |
make verify |
Ensure generated code is up to date |
make clean |
Remove build artifacts |
make docker-build |
Build Docker image |
make helm-install |
Install Helm chart |
make helm-uninstall |
Uninstall Helm chart |
# Run all tests
make test
# Run with verbose output
make test-verbose
# Generate coverage report
make test-coverage
The project follows Go testing best practices:
- Unit Tests: Test individual components in isolation
- Integration Tests: Test component interactions
- Mock Interfaces: Located in
internal/domain/mock.go
and other mock files - Test Coverage: Aim for high coverage with meaningful tests
When adding new functionality:
- Write tests first (TDD approach recommended)
- Use table-driven tests for multiple scenarios
- Mock external dependencies using provided interfaces
- Test error conditions not just happy paths
- Keep tests focused and independent
Example test structure:
func TestServiceMethod(t *testing.T) {
tests := []struct {
name string
input InputType
setupMocks func(*MockRepository)
expected ExpectedType
expectError bool
}{
// Test cases here
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test implementation
})
}
}
The service includes a Helm chart for Kubernetes deployment:
# Install with default values
make helm-install
# Install with custom values
helm upgrade --install lfx-v2-meeting-service ./charts/lfx-v2-meeting-service \
--namespace lfx \
--values custom-values.yaml
# Install with Zoom integration
helm upgrade --install lfx-v2-meeting-service ./charts/lfx-v2-meeting-service \
--namespace lfx \
--set zoom.accountId="your-zoom-account-id" \
--set zoom.clientId="your-zoom-client-id" \
--set zoom.clientSecret="your-zoom-client-secret"
# View templates
make helm-templates
# Build Docker image
make docker-build
# Run with Docker
docker run -p 8080:8080 linuxfoundation/lfx-v2-meeting-service:latest
The service uses NATS for event-driven communication with other LFX platform services.
The service publishes messages to the following NATS subjects:
Subject | Purpose | Message Schema |
---|---|---|
lfx.index.meeting |
Meeting indexing events | MeetingIndexerMessage |
lfx.index.meeting_settings |
Meeting settings indexing events | MeetingIndexerMessage |
lfx.index.meeting_registrant |
Registrant indexing events | MeetingIndexerMessage |
lfx.update_access.meeting |
Meeting access control updates | MeetingAccessMessage |
lfx.delete_all_access.meeting |
Meeting access control deletion | MeetingAccessMessage |
lfx.put_registrant.meeting |
Registrant access control updates | MeetingRegistrantAccessMessage |
lfx.remove_registrant.meeting |
Registrant access control deletion | MeetingRegistrantAccessMessage |
lfx.meetings-api.meeting_deleted |
Meeting deletion events (internal) | MeetingDeletedMessage |
The service handles incoming messages on these subjects:
Subject | Purpose | Handler |
---|---|---|
lfx.meetings-api.get_title |
Meeting title requests | HandleMeetingGetTitle |
lfx.meetings-api.meeting_deleted |
Meeting deletion cleanup | HandleMeetingDeleted |
All message schemas are defined in internal/domain/models/messaging.go
. Key schemas include:
- MeetingIndexerMessage: For search indexing operations
- MeetingAccessMessage: For meeting-level access control
- MeetingRegistrantAccessMessage: For registrant-level access control
- MeetingDeletedMessage: For internal cleanup when meetings are deleted
When meetings or registrants are modified, the service automatically:
- Updates NATS KV storage for persistence
- Publishes indexing messages for search services
- Publishes access control messages for permission services
- Handles cleanup messages for cascading deletions
The service automatically generates OpenAPI documentation:
- OpenAPI 2.0:
gen/http/openapi.yaml
- OpenAPI 3.0:
gen/http/openapi3.yaml
- JSON formats: Also available in
gen/http/
Access the documentation at: http://localhost:8080/openapi.json
Endpoint | Method | Description |
---|---|---|
/livez |
GET | Health check |
/readyz |
GET | Readiness check |
/meetings |
GET, POST | List/create meetings |
/meetings/{uid} |
GET, PUT, DELETE | Get/update/delete meeting |
/meetings/{uid}/registrants |
GET, POST | List/create registrants |
/meetings/{uid}/registrants/{id} |
GET, PUT, DELETE | Get/update/delete registrant |
The service can be configured via environment variables:
Variable | Description | Default |
---|---|---|
NATS_URL |
NATS server URL | nats://lfx-platform-nats.lfx.svc.cluster.local:4222 |
LOG_LEVEL |
Log level (debug, info, warn, error) | info |
LOG_ADD_SOURCE |
Add source location to logs | true |
JWKS_URL |
JWKS URL for JWT verification | http://lfx-platform-heimdall.lfx.svc.cluster.local:4457/.well-known/jwks |
JWT_AUDIENCE |
JWT token audience | lfx-v2-meeting-service |
SKIP_ETAG_VALIDATION |
Skip ETag validation (dev only) | false |
JWT_AUTH_DISABLED_MOCK_LOCAL_PRINCIPAL |
Mock principal for local dev (dev only) | "" |
Variable | Description | Default |
---|---|---|
ZOOM_ACCOUNT_ID |
Zoom OAuth Server-to-Server Account ID | "" |
ZOOM_CLIENT_ID |
Zoom OAuth App Client ID | "" |
ZOOM_CLIENT_SECRET |
Zoom OAuth App Client Secret | "" |
When all three Zoom variables are configured, the service will automatically integrate with Zoom API for meetings where platform="Zoom"
.
For webhook development, add this additional environment variable:
Variable | Description | Default |
---|---|---|
ZOOM_WEBHOOK_SECRET_TOKEN |
Webhook secret token for signature validation | "" |
To test Zoom webhooks locally, you'll need to expose your local service to receive webhook events from Zoom:
-
Install ngrok: Download from ngrok.com or use package manager:
brew install ngrok # macOS # or download from https://ngrok.com/download
-
Start your local service:
make run # Starts service on localhost:8080
-
Expose your service with ngrok (in a separate terminal):
ngrok http 8080
This creates a public URL like
https://abc123.ngrok.io
that forwards to your local service. -
Configure Zoom webhook URL: In your Zoom App settings, set webhook endpoint to:
https://abc123.ngrok.io/webhooks/zoom
-
Set webhook secret: Copy the webhook secret from Zoom App settings to your environment:
export ZOOM_WEBHOOK_SECRET_TOKEN="your_webhook_secret_here"
Supported Zoom Webhook Events:
meeting.started
- Meeting beginsmeeting.ended
- Meeting concludesmeeting.deleted
- Meeting is deletedmeeting.participant_joined
- Participant joinsmeeting.participant_left
- Participant leavesrecording.completed
- Recording is readyrecording.transcript_completed
- Transcript is readymeeting.summary_completed
- AI summary is ready
Webhook Processing Flow:
- HTTP webhook endpoint validates Zoom signature
- Event published to NATS for async processing
- Service handlers process business logic (no reply expected)
For local development, you may want to override these settings:
export NATS_URL="nats://localhost:4222"
export LOG_LEVEL="debug"
export SKIP_ETAG_VALIDATION="true"
export JWT_AUTH_DISABLED_MOCK_LOCAL_PRINCIPAL="local-dev-user"
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make changes and ensure tests pass (
make test
) - Run quality checks (
make check
) - Commit changes (
git commit -m 'Add amazing feature'
) - Push to branch (
git push origin feature/amazing-feature
) - Create a Pull Request
- Follow Go conventions and best practices
- Maintain high test coverage
- Write clear, self-documenting code
- Update documentation for API changes
- Run
make check
before committing
This project is licensed under the MIT License - see the LICENSE file for details.