chore: import upstream snapshot with attribution
govulncheck / govulncheck (push) Has been cancelled
Lint / golangci-lint (push) Has been cancelled
Run Tests / Unit Tests (push) Has been cancelled
Run Tests / Etcd Integration Tests (push) Has been cancelled
Harness (E2E) / Harnesses (mock LLM) (push) Has been cancelled
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Has been cancelled
govulncheck / govulncheck (push) Has been cancelled
Lint / golangci-lint (push) Has been cancelled
Run Tests / Unit Tests (push) Has been cancelled
Run Tests / Etcd Integration Tests (push) Has been cancelled
Harness (E2E) / Harnesses (mock LLM) (push) Has been cancelled
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
# ADR-001: Plugin Architecture
|
||||
|
||||
## Status
|
||||
**Accepted**
|
||||
|
||||
## Context
|
||||
|
||||
Microservices frameworks need to support multiple infrastructure backends (registries, brokers, transports, stores). Different teams have different preferences and existing infrastructure.
|
||||
|
||||
Hard-coding specific implementations:
|
||||
- Limits framework adoption
|
||||
- Forces migration of existing infrastructure
|
||||
- Prevents innovation and experimentation
|
||||
|
||||
## Decision
|
||||
|
||||
Go Micro uses a **pluggable architecture** where:
|
||||
|
||||
1. Core interfaces define contracts (Registry, Broker, Transport, Store, etc.)
|
||||
2. Multiple implementations live in the same repository under interface directories
|
||||
3. Plugins are imported directly and passed via options
|
||||
4. Default implementations work without any infrastructure
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
go-micro/
|
||||
├── registry/ # Interface definition
|
||||
│ ├── registry.go
|
||||
│ ├── mdns.go # Default implementation
|
||||
│ ├── consul/ # Plugin
|
||||
│ ├── etcd/ # Plugin
|
||||
│ └── nats/ # Plugin
|
||||
├── broker/
|
||||
├── transport/
|
||||
└── store/
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- **No version hell**: Plugins versioned with core framework
|
||||
- **Discovery**: Users browse available plugins in same repo
|
||||
- **Consistency**: All plugins follow same patterns
|
||||
- **Testing**: Plugins tested together
|
||||
- **Zero config**: Default implementations require no setup
|
||||
|
||||
### Negative
|
||||
|
||||
- **Repo size**: More code in one repository
|
||||
- **Plugin maintenance**: Core team responsible for plugin quality
|
||||
- **Breaking changes**: Harder to evolve individual plugins independently
|
||||
|
||||
### Neutral
|
||||
|
||||
- Plugins can be extracted to separate repos if they grow complex
|
||||
- Community can contribute plugins via PR
|
||||
- Plugin-specific issues easier to triage
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Separate Plugin Repositories
|
||||
Used by go-kit and other frameworks. Rejected because:
|
||||
- Version compatibility becomes user's problem
|
||||
- Discovery requires documentation
|
||||
- Testing integration harder
|
||||
- Splitting community
|
||||
|
||||
### Single Implementation
|
||||
Like standard `net/http`. Rejected because:
|
||||
- Forces infrastructure choices
|
||||
- Limits adoption
|
||||
- Can't leverage existing infrastructure
|
||||
|
||||
### Dynamic Plugin Loading
|
||||
Using Go plugins or external processes. Rejected because:
|
||||
- Complexity for users
|
||||
- Compatibility issues
|
||||
- Performance overhead
|
||||
- Debugging difficulty
|
||||
|
||||
## Related
|
||||
|
||||
- ADR-002: Interface-First Design (planned)
|
||||
- ADR-005: Registry Plugin Scope (planned)
|
||||
@@ -0,0 +1,119 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
# ADR-004: mDNS as Default Registry
|
||||
|
||||
## Status
|
||||
**Accepted**
|
||||
|
||||
## Context
|
||||
|
||||
Service discovery is critical for microservices. Common approaches:
|
||||
|
||||
1. **Central registry** (Consul, Etcd) - Requires infrastructure
|
||||
2. **DNS-based** (Kubernetes DNS) - Platform-specific
|
||||
3. **Static configuration** - Doesn't scale
|
||||
4. **Multicast DNS (mDNS)** - Zero-config, local network
|
||||
|
||||
For local development and getting started, requiring infrastructure setup is a barrier. Production deployments typically have existing service discovery infrastructure.
|
||||
|
||||
## Decision
|
||||
|
||||
Use **mDNS as the default registry** for service discovery.
|
||||
|
||||
- Works immediately on local networks
|
||||
- No external dependencies
|
||||
- Suitable for development and simple deployments
|
||||
- Easily swapped for production registries (Consul, Etcd, Kubernetes)
|
||||
|
||||
## Implementation
|
||||
|
||||
```go
|
||||
// Default - uses mDNS automatically
|
||||
svc := micro.NewService("myservice")
|
||||
|
||||
// Production - swap to Consul
|
||||
reg := consul.NewConsulRegistry()
|
||||
svc := micro.NewService("myservice",
|
||||
micro.Registry(reg),
|
||||
)
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- **Zero setup**: `go run main.go` just works
|
||||
- **Fast iteration**: No infrastructure for local dev
|
||||
- **Learning curve**: Newcomers start immediately
|
||||
- **Progressive complexity**: Add infrastructure as needed
|
||||
|
||||
### Negative
|
||||
|
||||
- **Local network only**: mDNS doesn't cross subnets/VLANs
|
||||
- **Not for production**: Needs proper registry in production
|
||||
- **Port 5353**: May conflict with existing mDNS services
|
||||
- **Discovery delay**: Can take 1-2 seconds
|
||||
|
||||
### Mitigations
|
||||
|
||||
- Clear documentation on production alternatives
|
||||
- Environment variables for easy swapping (`MICRO_REGISTRY=consul`)
|
||||
- Examples for all major registries
|
||||
- Health checks and readiness probes for production
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Good for mDNS
|
||||
- Local development
|
||||
- Testing
|
||||
- Simple internal services on same network
|
||||
- Learning and prototyping
|
||||
|
||||
### Need Production Registry
|
||||
- Cross-datacenter communication
|
||||
- Cloud deployments
|
||||
- Large service mesh (100+ services)
|
||||
- Require advanced features (health checks, metadata filtering)
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### No Default (Force Configuration)
|
||||
Rejected because:
|
||||
- Poor first-run experience
|
||||
- Increases barrier to entry
|
||||
- Users must setup infrastructure before trying framework
|
||||
|
||||
### Static Configuration
|
||||
Rejected because:
|
||||
- Doesn't support dynamic service discovery
|
||||
- Manual configuration doesn't scale
|
||||
- Doesn't reflect real microservices usage
|
||||
|
||||
### Consul as Default
|
||||
Rejected because:
|
||||
- Requires running Consul for "Hello World"
|
||||
- Platform-specific
|
||||
- Adds complexity for beginners
|
||||
|
||||
## Migration Path
|
||||
|
||||
Start with mDNS, migrate to production registry:
|
||||
|
||||
```bash
|
||||
# Development
|
||||
go run main.go
|
||||
|
||||
# Staging
|
||||
MICRO_REGISTRY=consul MICRO_REGISTRY_ADDRESS=consul:8500 go run main.go
|
||||
|
||||
# Production (Kubernetes)
|
||||
MICRO_REGISTRY=nats MICRO_REGISTRY_ADDRESS=nats://nats:4222 ./service
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [ADR-001: Plugin Architecture](adr-001-plugin-architecture.md)
|
||||
- [ADR-009: Progressive Configuration](adr-009-progressive-configuration.md)
|
||||
- [Registry Documentation](../registry.md)
|
||||
@@ -0,0 +1,152 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
# ADR-009: Progressive Configuration
|
||||
|
||||
## Status
|
||||
**Accepted**
|
||||
|
||||
## Context
|
||||
|
||||
Microservices frameworks face a paradox:
|
||||
- Beginners want "Hello World" to work immediately
|
||||
- Production needs sophisticated configuration
|
||||
|
||||
Too simple: Framework is toy, not production-ready
|
||||
Too complex: High barrier to entry, discourages adoption
|
||||
|
||||
## Decision
|
||||
|
||||
Implement **progressive configuration** where:
|
||||
|
||||
1. **Zero config** works for development
|
||||
2. **Environment variables** provide simple overrides
|
||||
3. **Code-based options** enable fine-grained control
|
||||
4. **Defaults are production-aware** but not production-ready
|
||||
|
||||
## Levels of Configuration
|
||||
|
||||
### Level 1: Zero Config (Development)
|
||||
```go
|
||||
svc := micro.NewService("hello")
|
||||
svc.Run()
|
||||
```
|
||||
|
||||
Uses defaults:
|
||||
- mDNS registry (local)
|
||||
- HTTP transport
|
||||
- Random available port
|
||||
- Memory broker/store
|
||||
|
||||
### Level 2: Environment Variables (Staging)
|
||||
```bash
|
||||
MICRO_REGISTRY=consul \
|
||||
MICRO_REGISTRY_ADDRESS=consul:8500 \
|
||||
MICRO_BROKER=nats \
|
||||
MICRO_BROKER_ADDRESS=nats://nats:4222 \
|
||||
./service
|
||||
```
|
||||
|
||||
No code changes, works with CLI flags.
|
||||
|
||||
### Level 3: Code Options (Production)
|
||||
```go
|
||||
reg := consul.NewConsulRegistry(
|
||||
registry.Addrs("consul1:8500", "consul2:8500"),
|
||||
registry.TLSConfig(tlsConf),
|
||||
)
|
||||
|
||||
b := nats.NewNatsBroker(
|
||||
broker.Addrs("nats://nats1:4222", "nats://nats2:4222"),
|
||||
nats.DrainConnection(),
|
||||
)
|
||||
|
||||
svc := micro.NewService("myservice",
|
||||
micro.Version("1.2.3"),
|
||||
micro.Registry(reg),
|
||||
micro.Broker(b),
|
||||
micro.Address(":8080"),
|
||||
)
|
||||
```
|
||||
|
||||
Full control over initialization and configuration.
|
||||
|
||||
### Level 4: External Config (Enterprise)
|
||||
```go
|
||||
cfg := config.NewConfig(
|
||||
config.Source(file.NewSource("config.yaml")),
|
||||
config.Source(env.NewSource()),
|
||||
config.Source(vault.NewSource()),
|
||||
)
|
||||
|
||||
// Use cfg to initialize plugins with complex configs
|
||||
```
|
||||
|
||||
## Environment Variable Patterns
|
||||
|
||||
Standard vars for all plugins:
|
||||
```bash
|
||||
MICRO_REGISTRY=<type> # consul, etcd, nats, mdns
|
||||
MICRO_REGISTRY_ADDRESS=<addrs> # Comma-separated
|
||||
MICRO_BROKER=<type>
|
||||
MICRO_BROKER_ADDRESS=<addrs>
|
||||
MICRO_TRANSPORT=<type>
|
||||
MICRO_TRANSPORT_ADDRESS=<addrs>
|
||||
MICRO_STORE=<type>
|
||||
MICRO_STORE_ADDRESS=<addrs>
|
||||
MICRO_STORE_DATABASE=<name>
|
||||
MICRO_STORE_TABLE=<name>
|
||||
```
|
||||
|
||||
Plugin-specific vars:
|
||||
```bash
|
||||
ETCD_USERNAME=user
|
||||
ETCD_PASSWORD=pass
|
||||
CONSUL_TOKEN=secret
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- **Fast start**: Beginners productive immediately
|
||||
- **Easy deployment**: Env vars for different environments
|
||||
- **Power when needed**: Full programmatic control available
|
||||
- **Learn incrementally**: Complexity introduced as required
|
||||
|
||||
### Negative
|
||||
|
||||
- **Three config sources**: Environment, code, and CLI flags can conflict
|
||||
- **Documentation**: Must explain all levels clearly
|
||||
- **Testing**: Need to test all configuration methods
|
||||
|
||||
### Mitigations
|
||||
|
||||
- Clear precedence: Code options > Environment > Defaults
|
||||
- Comprehensive examples for each level
|
||||
- Validation and helpful error messages
|
||||
|
||||
## Validation Example
|
||||
|
||||
```go
|
||||
func (s *service) Init() error {
|
||||
if s.opts.Name == "" {
|
||||
return errors.New("service name required")
|
||||
}
|
||||
|
||||
// Warn about development defaults in production
|
||||
if isProduction() && usingDefaults() {
|
||||
log.Warn("Using development defaults in production")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [ADR-004: mDNS as Default Registry](adr-004-mdns-default-registry.md)
|
||||
- ADR-008: Environment Variable Support (planned)
|
||||
- [Getting Started Guide](../getting-started.md) - Configuration examples
|
||||
- [Configuration Guide](../config.md)
|
||||
@@ -0,0 +1,180 @@
|
||||
# ADR-010: Unified Gateway Architecture
|
||||
|
||||
**Status:** Accepted
|
||||
**Date:** 2026-02-11
|
||||
**Authors:** Go Micro Team
|
||||
|
||||
## Context
|
||||
|
||||
Previously, the go-micro CLI had two separate gateway implementations:
|
||||
|
||||
1. **`micro run`** gateway (`cmd/micro/run/gateway/`) - Simple HTTP-to-RPC proxy for development
|
||||
2. **`micro server`** gateway (`cmd/micro/server/`) - Production gateway with authentication, web UI, and API documentation
|
||||
|
||||
This duplication created several problems:
|
||||
|
||||
- **Code maintenance**: Gateway logic (HTTP-to-RPC translation, service discovery, health checks) was implemented twice
|
||||
- **Feature parity**: Improvements to one gateway didn't automatically benefit the other
|
||||
- **Complexity**: New features (like MCP integration) would need to be implemented twice
|
||||
- **Testing burden**: Each gateway required separate testing
|
||||
|
||||
## Decision
|
||||
|
||||
We unified the gateway implementation by:
|
||||
|
||||
1. **Extracting reusable gateway module** (`cmd/micro/server/gateway.go`):
|
||||
- `GatewayOptions` struct for configuration
|
||||
- `StartGateway()` function that returns a `*Gateway` immediately
|
||||
- `RunGateway()` function that blocks until shutdown
|
||||
- Configurable authentication (enabled/disabled)
|
||||
|
||||
2. **Refactoring `micro server`**:
|
||||
- Gateway logic remains in `cmd/micro/server/`
|
||||
- `registerHandlers()` now uses instance-specific `*http.ServeMux` instead of global mux
|
||||
- Authentication middleware is conditional based on `GatewayOptions.AuthEnabled`
|
||||
- Auth routes only register when authentication is enabled
|
||||
|
||||
3. **Updating `micro run`**:
|
||||
- Removed duplicate gateway implementation (`cmd/micro/run/gateway/`)
|
||||
- Now calls `server.StartGateway()` with `AuthEnabled: true`
|
||||
- Retains process management and hot reload functionality
|
||||
- Same auth, scopes, and token management as `micro server`
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Unified Gateway │
|
||||
│ (cmd/micro/server/gateway.go) │
|
||||
│ │
|
||||
│ • HTTP → RPC translation │
|
||||
│ • Service discovery via registry │
|
||||
│ • Web UI (dashboard, logs, API docs) │
|
||||
│ • Health checks │
|
||||
│ • Configurable authentication │
|
||||
│ • Endpoint scopes for access control │
|
||||
│ • MCP tool integration with scope enforcement │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
▲ ▲
|
||||
│ │
|
||||
┌──────┴──────┐ ┌────────┴────────┐
|
||||
│ micro run │ │ micro server │
|
||||
│ │ │ │
|
||||
│ + Process │ │ + Auth enabled │
|
||||
│ mgmt │ │ + JWT tokens │
|
||||
│ + Hot │ │ + Scopes │
|
||||
│ reload │ │ + Production │
|
||||
│ + Auth │ │ │
|
||||
│ + Scopes │ │ │
|
||||
└─────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Development Mode (`micro run`)
|
||||
|
||||
```bash
|
||||
# Start services with gateway (auth enabled, default admin/micro)
|
||||
micro run
|
||||
|
||||
# Gateway provides:
|
||||
# - HTTP API at /api/{service}/{endpoint}
|
||||
# - Web dashboard at /
|
||||
# - JWT authentication (admin/micro default)
|
||||
# - Endpoint scopes at /auth/scopes
|
||||
```
|
||||
|
||||
### Production Mode (`micro server`)
|
||||
|
||||
```bash
|
||||
# Start gateway with authentication
|
||||
micro server --address :8080
|
||||
|
||||
# Gateway provides:
|
||||
# - HTTP API at /api/{service}/{endpoint} (auth required)
|
||||
# - Web dashboard with login
|
||||
# - JWT-based authentication
|
||||
# - User/token management UI
|
||||
# - Endpoint scopes at /auth/scopes
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Single Source of Truth**: Gateway logic lives in one place
|
||||
2. **Automatic Feature Propagation**: New features (like MCP) added to the unified gateway benefit both commands
|
||||
3. **Simplified Testing**: Test gateway once, works everywhere
|
||||
4. **Reduced Code Size**: Eliminated ~300 lines of duplicate code
|
||||
5. **Clear Separation**:
|
||||
- `micro server` = API gateway (HTTP + future MCP)
|
||||
- `micro run` = Development tool (gateway + process management + hot reload)
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### GatewayOptions
|
||||
|
||||
```go
|
||||
type GatewayOptions struct {
|
||||
Address string // Listen address (e.g., ":8080")
|
||||
AuthEnabled bool // Enable JWT authentication
|
||||
Store store.Store // Storage for auth data
|
||||
Context context.Context // Cancellation context
|
||||
}
|
||||
```
|
||||
|
||||
### Starting the Gateway
|
||||
|
||||
```go
|
||||
// Non-blocking start
|
||||
gw, err := server.StartGateway(server.GatewayOptions{
|
||||
Address: ":8080",
|
||||
AuthEnabled: false,
|
||||
})
|
||||
|
||||
// Blocking start
|
||||
err := server.RunGateway(server.GatewayOptions{
|
||||
Address: ":8080",
|
||||
AuthEnabled: true,
|
||||
})
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
When `AuthEnabled: true`:
|
||||
- Auth middleware checks JWT tokens on all requests
|
||||
- Auth routes are registered: `/auth/login`, `/auth/logout`, `/auth/tokens`, `/auth/users`
|
||||
- Web UI requires login
|
||||
- API endpoints require `Authorization: Bearer <token>` header
|
||||
|
||||
When `AuthEnabled: false` (dev mode):
|
||||
- No authentication middleware
|
||||
- Auth routes are not registered
|
||||
- All endpoints are publicly accessible
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Easier to add new features (only implement once)
|
||||
- Better code maintainability
|
||||
- Consistent behavior between development and production
|
||||
- Foundation for MCP integration
|
||||
|
||||
### Negative
|
||||
|
||||
- `cmd/micro/run` now depends on `cmd/micro/server` (acceptable for CLI tools)
|
||||
- Slightly more complex initialization in `micro run` (but cleaner overall)
|
||||
|
||||
## Future Work
|
||||
|
||||
With unified gateway architecture, we can now add:
|
||||
|
||||
1. **MCP Integration**: Add `mcp.go` to server package, both commands get MCP support
|
||||
2. **GraphQL API**: Single implementation serves both dev and prod
|
||||
3. **gRPC Gateway**: Expose services via gRPC alongside HTTP
|
||||
4. **API Versioning**: Consistent versioning strategy across all deployments
|
||||
|
||||
## References
|
||||
|
||||
- Original issue: Gateway duplication between `micro run` and `micro server`
|
||||
- Implementation: PR #XXX (gateway unification)
|
||||
- Related: ADR-001 (Plugin Architecture), ADR-009 (Progressive Configuration)
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
# ADR-XXX: Title
|
||||
|
||||
Status: Proposed
|
||||
Date: YYYY-MM-DD
|
||||
|
||||
## Context
|
||||
|
||||
Describe the problem, forces, and constraints leading to the decision.
|
||||
|
||||
## Decision
|
||||
|
||||
State the decision clearly and precisely.
|
||||
|
||||
## Consequences
|
||||
|
||||
Positive and negative outcomes, trade-offs introduced by this decision.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
1. Alternative A - why rejected
|
||||
2. Alternative B - why rejected
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
High-level steps or rollout plan if accepted.
|
||||
|
||||
## Related
|
||||
|
||||
- Link other ADRs, documentation, or issues.
|
||||
|
||||
## References
|
||||
|
||||
External resources, prior art, research.
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
# Architecture Decision Records
|
||||
|
||||
Documentation of architectural decisions made in Go Micro, following the ADR pattern.
|
||||
|
||||
## What are ADRs?
|
||||
|
||||
Architecture Decision Records (ADRs) capture important architectural decisions along with their context and consequences. They help understand why certain design choices were made.
|
||||
|
||||
## Index
|
||||
|
||||
### Available
|
||||
- [ADR-001: Plugin Architecture](adr-001-plugin-architecture.md)
|
||||
- [ADR-004: mDNS as Default Registry](adr-004-mdns-default-registry.md)
|
||||
- [ADR-009: Progressive Configuration](adr-009-progressive-configuration.md)
|
||||
|
||||
### Planned
|
||||
|
||||
**Core Design**
|
||||
- ADR-002: Interface-First Design
|
||||
- ADR-003: Default Implementations
|
||||
|
||||
**Service Discovery**
|
||||
- ADR-005: Registry Plugin Scope
|
||||
|
||||
**Communication**
|
||||
- ADR-006: HTTP as Default Transport
|
||||
- ADR-007: Content-Type Based Codecs
|
||||
|
||||
**Configuration**
|
||||
- ADR-008: Environment Variable Support
|
||||
|
||||
## Status Values
|
||||
|
||||
- **Proposed**: Under consideration
|
||||
- **Accepted**: Decision approved
|
||||
- **Deprecated**: No longer recommended
|
||||
- **Superseded**: Replaced by another ADR
|
||||
|
||||
## Contributing
|
||||
|
||||
To propose a new ADR:
|
||||
|
||||
1. Number it sequentially (check existing ADRs)
|
||||
2. Follow the structure of existing ADRs
|
||||
3. Include: Status, Context, Decision, Consequences, Alternatives
|
||||
4. Submit a PR for discussion
|
||||
5. Update status based on review
|
||||
|
||||
ADRs are immutable once accepted. To change a decision, create a new ADR that supersedes the old one.
|
||||
Reference in New Issue
Block a user