# ADR-0031: Service Repository Structure

## Status
Accepted

## Context
The platform follows a microservices architecture where each service (Auth, Identity, Authz, Audit, and feature modules) is an independent service. We need to decide how to organize these services in the codebase:

- **Option 1**: Monorepo with service directories (all services in one repository)
- **Option 2**: Separate repositories (each service in its own repository)

The decision affects:

- Code sharing and dependencies
- Development workflow
- CI/CD complexity
- Team autonomy and ownership
- Deployment strategies
- Code discoverability and navigation

## Decision
Use a **monorepo structure with service directories** for all services:

1. **Repository Structure**: Single repository (`goplt/`) containing:
   - Core Kernel (shared infrastructure)
   - All core services (Auth, Identity, Authz, Audit)
   - All feature modules (Blog, Billing, etc.)
   - Shared interfaces and utilities

2. **Service Organization**: Each service lives in `cmd/` directory:
   ```
   goplt/
   ├── cmd/
   │   ├── platform/          # Core kernel entry point (minimal, infrastructure only)
   │   ├── api-gateway/        # API Gateway service entry point
   │   ├── auth-service/       # Auth Service entry point
   │   ├── identity-service/   # Identity Service entry point
   │   ├── authz-service/      # Authz Service entry point
   │   ├── audit-service/      # Audit Service entry point
   │   └── blog-service/       # Blog feature service entry point
   ├── services/              # Service implementations (optional alternative)
   │   ├── auth/
   │   │   ├── internal/      # Service implementation
   │   │   └── api/           # gRPC/HTTP definitions
   │   ├── identity/
   │   ├── authz/
   │   └── audit/
   ├── internal/              # Core kernel implementation (shared)
   │   ├── config/
   │   ├── logger/
   │   └── di/
   ├── pkg/                   # Public interfaces
   │   ├── config/            # ConfigProvider interface
   │   ├── logger/            # Logger interface
   │   ├── services/          # Service client interfaces
   │   └── module/            # IModule interface
   └── modules/               # Feature modules (optional structure)
       └── blog/
   ```

3. **Service Independence**: Each service maintains:
   - Own `go.mod` module (or shared workspace)
   - Own internal implementation (`internal/` or `services/{service}/internal/`)
   - Own gRPC/HTTP API definitions
   - Own database schema and migrations
   - Own entry point in `cmd/{service-name}/`

4. **Shared Code**: Core kernel infrastructure shared across all services:
   - Configuration management (`internal/config/`, `pkg/config/`)
   - Logging system (`internal/logger/`, `pkg/logger/`)
   - Dependency injection (`internal/di/`)
   - Service client implementations (`internal/services/`)
   - Common utilities and interfaces

5. **Development Mode**: All services can run from same repository:
   - Single `go.work` workspace file (Go 1.18+)
   - Shared dependencies and versioning
   - Easy local development with `docker-compose`
   - Atomic changes across services when needed

## Rationale

### Why Monorepo?

1. **Code Sharing**: Core kernel (config, logger, DI) is shared across all services. Monorepo makes this easy.

2. **Atomic Changes**: Changes to shared interfaces can be updated across all services in a single commit.

3. **Simplified CI/CD**: Single CI pipeline can test all services and their interactions.

4. **Easier Development**: Developers can run all services locally from one repository.

5. **Version Consistency**: Shared dependencies (like core kernel) are always in sync.

6. **Cross-Service Refactoring**: Easier to refactor shared code across services.

7. **Unified Documentation**: All documentation in one place.

### Why Not Separate Repositories?

1. **Code Duplication**: Shared core kernel would need to be published as a library or duplicated.

2. **Version Management**: Core kernel changes would require coordinated releases across repositories.

3. **Development Complexity**: Developers would need to clone multiple repositories.

4. **CI/CD Complexity**: Multiple pipelines to manage and coordinate.

5. **Breaking Changes**: Harder to coordinate breaking changes to shared interfaces.

## Consequences

### Positive

- **Simplified Development**: Single repository to clone and work with
- **Code Reuse**: Easy sharing of core kernel and utilities
- **Atomic Changes**: Update shared interfaces and all services together
- **Consistent Dependencies**: All services use same versions of core kernel
- **Unified CI/CD**: Single pipeline for all services
- **Easier Onboarding**: New developers work with one repository
- **Cross-Service Testing**: Can test service interactions easily
- **Shared Documentation**: All docs in one place
- **Go Workspace Support**: Can use `go.work` for multi-module development

### Negative

- **Repository Size**: Repository grows as more services are added
- **Permission Granularity**: Harder to restrict access to specific services (Git permissions)
- **Build Time**: CI/CD may take longer as it builds all services
- **Deployment Coupling**: Services are in same repo (but can still deploy independently)
- **Merge Conflicts**: More likely with multiple teams working on same repo
- **Git History**: History can become cluttered with changes from many services

### Mitigations

1. **Repository Size**: Use Git LFS for large files, sparse checkout for large repos
2. **Permissions**: Use CODEOWNERS file and branch protection rules
3. **Build Time**: Use build caching and parallel builds in CI/CD
4. **Deployment**: Services are independently deployable despite shared repo
5. **Merge Conflicts**: Use feature branches, code review, and clear ownership
6. **Git History**: Use conventional commits and clear service prefixes

## Implementation Strategy

### Phase 1: Core Kernel (Epic 0-1) - Current
- Core kernel in `internal/` and `pkg/`
- Single entry point `cmd/platform/`
- Shared infrastructure established

### Phase 2: Service Structure (Epic 1-2)
- **Epic 1**: Create API Gateway service:
  - `cmd/api-gateway/` - API Gateway entry point
  - Service discovery integration
  - Request routing to backend services
- **Epic 2**: Create core service directories:
  - `cmd/auth-service/` - Auth Service entry point
  - `cmd/identity-service/` - Identity Service entry point
  - `cmd/authz-service/` - Authz Service entry point
  - `cmd/audit-service/` - Audit Service entry point
- Create service implementations:
  - Option A: `services/{service}/internal/` for each service (recommended)
  - Option B: `internal/{service}/` for each service
  - Each service has its own database connection pool
- Define service client interfaces in `pkg/services/`:
  - `AuthServiceClient`, `IdentityServiceClient`, `AuthzServiceClient`, `AuditServiceClient`
- Implement gRPC/HTTP clients in `internal/services/`

### Phase 3: Module Services (Epic 4+)
- Feature modules follow same pattern:
  - `cmd/blog-service/` for blog module
  - Module implementation in `modules/blog/` or `services/blog/`

### Directory Structure Decision

**Recommended**: Use `cmd/{service}/` for entry points and `services/{service}/` for implementations:

```
goplt/
├── cmd/
│   ├── platform/          # Core kernel (minimal, infrastructure only)
│   ├── api-gateway/       # API Gateway entry point
│   ├── auth-service/      # Auth entry point
│   ├── identity-service/  # Identity entry point
│   ├── authz-service/     # Authz entry point
│   ├── audit-service/     # Audit entry point
│   └── blog-service/      # Blog feature service entry point
├── services/              # Service implementations
│   ├── gateway/
│   │   ├── internal/      # Gateway implementation
│   │   └── api/           # Routing logic
│   ├── auth/
│   │   ├── internal/      # Service implementation
│   │   └── api/           # gRPC/HTTP definitions
│   ├── identity/
│   ├── authz/
│   ├── audit/
│   └── blog/
├── internal/              # Core kernel (shared infrastructure)
├── pkg/                   # Public interfaces
└── modules/               # Feature modules (optional structure)
```

This provides:
- Clear separation between entry points and implementations
- Easy to find service entry points
- Service code is organized together
- Consistent with Go best practices

## Alternative: Go Workspace (Go 1.18+)

For maximum service independence while maintaining monorepo benefits:

```go
// go.work
go 1.24

use (
    .                    # Core kernel
    ./services/auth      # Auth service module
    ./services/identity  # Identity service module
    ./cmd/auth-service   # Auth service entry
    ./cmd/identity-service # Identity service entry
)
```

Each service can have its own `go.mod` while sharing the workspace.

## Migration Path

If we later need to split into separate repositories:
1. Core kernel can be extracted to a shared library
2. Services can be moved to separate repos with git history
3. Service client interfaces remain in shared package
4. CI/CD can be adapted to multi-repo workflows

## References

- [ADR-0007: Project Directory Structure](./0007-project-directory-structure.md)
- [ADR-0029: Microservices Architecture](./0029-microservices-architecture.md)
- [ADR-0030: Service Communication Strategy](./0030-service-communication-strategy.md)
- [Go Workspaces](https://go.dev/doc/tutorial/workspaces)
- [Monorepo vs. Multi-repo](https://www.atlassian.com/git/tutorials/monorepos)
- [Google's Monorepo Strategy](https://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository/fulltext)

