Skip to content

Danitello123/stellabill-backend

 
 

Repository files navigation

Stellabill Backend

Go (Gin) API backend for Stellabill — subscription and billing plans API. This repo is backend-only; a separate frontend consumes these APIs.


Table of contents


Tech stack

  • Language: Go 1.22+
  • Framework: Gin
  • Config: Environment variables (no config files required for default dev)

What this backend provides (for the frontend)

This service is the backend only. A separate frontend (or any client) can:

  • Health checkGET /api/health to verify the API is up.
  • PlansGET /api/plans to list billing plans (id, name, amount, currency, interval, description). Currently returns an empty list; DB integration is planned.
  • SubscriptionsGET /api/subscriptions to list subscriptions and GET /api/subscriptions/:id to fetch one. Responses include plan_id, customer, status, amount, interval, next_billing. Currently placeholder/mock data; DB integration is planned.

CORS is enabled for all origins in development so a frontend on another port or domain can call these endpoints.


Background Worker

The backend includes a production-ready background worker system for automated billing job scheduling and execution.

Key Features

  • Job Scheduling: Schedule billing operations (charges, invoices, reminders) with configurable execution times
  • Distributed Locking: Prevents duplicate processing when running multiple worker instances
  • Retry Policy: Automatic retry with exponential backoff (1s, 4s, 9s) for failed jobs
  • Dead-Letter Queue: Failed jobs after max attempts are moved for manual review
  • Graceful Shutdown: Workers complete in-flight jobs before shutting down
  • Metrics Tracking: Monitor job processing statistics (processed, succeeded, failed, dead-lettered)
  • Concurrent Workers: Multiple workers can run safely without duplicate processing

Documentation

  • internal/worker/README.md - Complete worker documentation
  • internal/worker/INTEGRATION.md - Integration guide with examples
  • internal/worker/SECURITY.md - Security analysis and threat model
  • WORKER_IMPLEMENTATION.md - Implementation summary

Quick Example

store := worker.NewMemoryStore()
executor := worker.NewBillingExecutor()
config := worker.DefaultConfig()

w := worker.NewWorker(store, executor, config)
w.Start()
defer w.Stop()

scheduler := worker.NewScheduler(store)
job, _ := scheduler.ScheduleCharge("sub-123", time.Now(), 3)

Local setup

Prerequisites

  • Go 1.22 or later

  • Git (for cloning and contributing)

  • PostgreSQL (optional for now; app runs without it using default config; DB will be used when persistence is added)

1. Clone the repository

git clone https://github.com/YOUR_ORG/stellabill-backend.git
cd stellabill-backend

2. Install dependencies

go mod download

3. (Optional) Environment variables

Create a .env file in the project root (do not commit it; it’s in .gitignore):

# Optional — defaults shown
ENV=development
PORT=8080
DATABASE_URL=postgres://localhost/stellarbill?sslmode=disable
JWT_SECRET=change-me-in-production

Or export them in your shell. The app will run with the defaults if you don’t set anything.

4. Run the server

go run ./cmd/server

Server listens on http://localhost:8080 (or the port you set via PORT).

5. Verify

curl http://localhost:8080/api/health
# Expected: {"service":"stellarbill-backend","status":"ok"}

Configuration

Variable Default Description
ENV development Environment (e.g. production)
PORT 8080 HTTP server port
DATABASE_URL postgres://localhost/stellarbill?sslmode=disable PostgreSQL connection string
JWT_SECRET change-me-in-production Secret for JWT (change in prod)
FF_DEFAULT_ENABLED false Default state for unknown flags
FF_LOG_DISABLED true Log when flags block requests
FF_CONFIG_FILE "" Path to feature flags config file

Feature Flags Configuration

Feature flags can be configured using environment variables in several ways:

1. Individual Flags (Recommended)

Use the FF_ prefix for individual flags:

# Enable/disable specific features
FF_SUBSCRIPTIONS_ENABLED=true
FF_PLANS_ENABLED=false
FF_NEW_BILLING_FLOW=true
FF_ADVANCED_ANALYTICS=false

2. JSON Configuration

Use the FEATURE_FLAGS environment variable for bulk configuration:

export FEATURE_FLAGS='{"subscriptions_enabled": true, "plans_enabled": true, "new_billing_flow": false}'

3. Priority Order

The system uses the following priority (highest to lowest):

  1. FF_* individual environment variables
  2. FEATURE_FLAGS JSON configuration
  3. Default flag values

Available Feature Flags

Flag Name Default Description
subscriptions_enabled true Enable subscription management endpoints
plans_enabled true Enable billing plans endpoints
new_billing_flow false Enable new billing flow feature
advanced_analytics false Enable advanced analytics endpoints

In production, set these via your host’s environment or secrets manager; do not commit secrets.


Using Feature Flags in Code

import "stellarbill-backend/internal/middleware"
import "stellarbill-backend/internal/featureflags"

// Method 1: Middleware (recommended for endpoints)
router.GET("/feature", middleware.FeatureFlag("my_feature"), handler)

// Method 2: With default value
router.GET("/feature", middleware.FeatureFlagWithDefault("my_feature", true), handler)

// Method 3: Direct check in code
if featureflags.IsEnabled("my_feature") {
    // Feature code here
}

// Method 4: Multiple flags requirement
router.GET("/feature", middleware.RequireAllFeatureFlags("flag1", "flag2"), handler)
router.GET("/feature", middleware.RequireAnyFeatureFlags("flag1", "flag2"), handler)

API reference

Base URL (local): http://localhost:8080

Method Path Feature Flag Required Description
GET /api/health None Health check
GET /api/plans plans_enabled (default: true) List billing plans
GET /api/subscriptions subscriptions_enabled (default: true) List subscriptions
GET /api/subscriptions/:id subscriptions_enabled (default: true) Get one subscription
GET /api/billing/new-flow new_billing_flow (default: false) New billing flow feature
GET /api/analytics/advanced advanced_analytics AND subscriptions_enabled Advanced analytics

All JSON responses. CORS allowed for * origin with common methods and headers.

Feature Flag Responses: When a feature flag blocks a request, the API returns:

{
  "error": "feature_unavailable",
  "message": "This feature is currently unavailable",
  "feature_flag": "flag_name"
}

Database migrations

Migrations live in migrations/ and are applied with:

go run ./cmd/migrate up

See docs/migrations.md for conventions and a production runbook.


CI / Quality gates

Every push and pull request runs the following checks automatically via GitHub Actions (.github/workflows/ci.yml):

Step Command
Build go build ./...
Vet go vet ./...
Test + coverage go test ./internal/... -covermode=atomic -coverpkg=./internal/...
Coverage threshold ./scripts/check-coverage.sh coverage.out 95 (≥ 95 % on internal/)

Coverage artifacts (coverage.out) are uploaded and retained for 14 days on every run.

Run checks locally before opening a PR

# 1. Build
go build ./...

# 2. Vet
go vet ./...

# 3. Test with coverage (internal packages only — cmd/server is the process entrypoint)
go test ./internal/... \
  -covermode=atomic \
  -coverpkg=./internal/... \
  -coverprofile=coverage.out \
  -count=1 \
  -timeout=60s

# 4. Enforce the 95 % threshold
./scripts/check-coverage.sh coverage.out 95

# 5. (Optional) Browse the HTML report
go tool cover -html=coverage.out

Why ./internal/... and not ./...?
cmd/server/main.go is the process entry point (main()). Go cannot instrument it as a unit-testable package, so it always reports 0 % and would drag the total below the threshold. All business logic lives in internal/, which is what the threshold enforces.

Security note: Never commit .env, JWT secrets, or database credentials. The CI workflow contains no secrets; configure them via your host's environment or a secrets manager.


Contributing (open source)

We welcome contributions from the community. Below is a short guide to get you from “first look” to “merged change”.

Code of conduct

  • Be respectful and inclusive.
  • Focus on constructive feedback and clear, factual communication.

How to contribute

  1. Open an issue

    • Bug: describe what you did, what you expected, and what happened.
    • Feature: describe the goal and why it helps.
  2. Fork and clone

    • Fork the repo on GitHub, then clone your fork locally.
  3. Create a branch

    git checkout -b fix/your-fix   # or feature/your-feature
  4. Make changes

    • Follow existing style (format with go fmt).
    • Keep commits logical and messages clear (e.g. “Add validation for plan ID”).
  5. Run checks

    go build ./...
    go vet ./...
    go fmt ./...

    Add or run tests if the project has them.

  6. Commit

    • Prefer small, atomic commits (one logical change per commit).
  7. Push and open a PR

    git push origin fix/your-fix
    • Open a Pull Request against the main branch.
    • Fill in the PR template (if any).
    • Link related issues.
    • Describe what you changed and why.
  8. Review

    • Address review comments. Maintainers will merge when everything looks good.

Development workflow

  • Use the Local setup steps to run the server.
  • Change code, restart the server (or use a tool like air for live reload if the project adds it).
  • Test with curl or the frontend that consumes this API.

Project standards

  • Go: go fmt, go vet, no unnecessary dependencies.
  • APIs: Keep JSON shape stable; document breaking changes in PRs.
  • Secrets: Never commit .env, keys, or passwords.

Project layout

stellabill-backend/
├── .github/
│   └── workflows/
│       └── ci.yml           # CI: build, vet, test, coverage threshold
├── cmd/
│   └── server/
│       └── main.go          # Entry point, Gin router, server start
├── internal/
│   ├── config/
│   │   └── config.go        # Loads ENV, PORT, DATABASE_URL, JWT_SECRET, feature flags
│   ├── featureflags/
│   │   ├── featureflags.go   # Feature flag management system
│   │   └── featureflags_test.go # Unit tests for feature flags
│   ├── middleware/
│   │   ├── featureflags.go   # Feature flag middleware for endpoint gating
│   │   └── featureflags_test.go # Middleware tests
│   ├── handlers/
│   │   ├── health.go        # GET /api/health
│   │   ├── plans.go         # GET /api/plans
│   │   └── subscriptions.go # GET /api/subscriptions, /api/subscriptions/:id
│   ├── routes/
│       └── routes.go        # Registers routes and CORS middleware
│   └── worker/
│       ├── job.go           # Job model and JobStore interface
│       ├── store_memory.go  # In-memory JobStore implementation
│       ├── worker.go        # Background worker with scheduler loop
│       ├── executor.go      # Billing job executor
│       ├── scheduler.go     # Job scheduling utilities
│       ├── *_test.go        # Comprehensive test suite (95%+ coverage)
│       ├── README.md        # Worker documentation
│       ├── SECURITY.md      # Security analysis and threat model
│       └── INTEGRATION.md   # Integration guide with examples
├── go.mod
├── go.sum
├── .gitignore
├── README.md
└── WORKER_IMPLEMENTATION.md # Implementation summary

Security Considerations

Feature Flags Security

  • Environment Variables: Feature flags are configured via environment variables, which are secure and not committed to version control
  • Default Behavior: Unknown flags default to false for security (fail-safe)
  • No Dynamic Loading: Flags are loaded at startup only, preventing runtime injection attacks
  • Thread Safety: All flag operations are thread-safe with proper mutex locking
  • Validation: Invalid flag values are safely ignored and logged

Best Practices

  1. Production Flags: Always set explicit flag values in production; don't rely on defaults
  2. Secret Management: Use your cloud provider's secret manager for sensitive flag configurations
  3. Monitoring: Monitor flag usage and access patterns
  4. Audit Trail: Flag changes are tracked with timestamps for auditing
  5. Testing: Test both enabled and disabled states in your test suite

Testing Security

The feature flag system includes comprehensive tests covering:

  • Concurrent access and race conditions
  • Invalid input handling
  • Memory leak prevention
  • Environment variable injection attempts
  • Edge cases and error conditions

Run tests with: go test ./...


License

See the LICENSE file in the repository (if present). If none, assume proprietary until stated otherwise.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Go 98.5%
  • Shell 1.5%