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

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:33 +08:00
commit e071084ebe
982 changed files with 160368 additions and 0 deletions
@@ -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.