Files
goplt/docs/requirements.md
0x1d 6a17236474 docs: add implementation plan, ADRs, and task tracking system
- Add comprehensive 8-phase implementation plan (docs/plan.md)
- Add 28 Architecture Decision Records (docs/adr/) covering all phases
- Add task tracking system with 283+ task files (docs/stories/)
- Add task generator script for automated task file creation
- Add reference playbooks and requirements documentation

This commit establishes the complete planning foundation for the Go
Platform implementation, documenting all architectural decisions and
providing detailed task breakdown for Phases 0-8.
2025-11-04 22:05:37 +01:00

19 KiB
Raw Blame History

Requirements

1 HIGHLEVEL ARCHITECTURAL PRINCIPLES

Principle Why it matters for a modular platform How to enforce it
Separation of Concerns (SoC) Keeps core services (auth, audit, config) independent from business modules. Use layered or hexagonal/cleanarchitecture boundaries.
DomainDriven Design (DDD) Bounded Contexts Allows each module to own its own model & rules while sharing a common identity kernel. Define a Core Context (Identity, Security, Infrastructure) and Feature Contexts (Billing, CMS, Chat, …).
Modular Monolith → Microserviceready Start simple (single process) but keep each module in its own package so you can later split to services if needed. Package each module as an independent library with its own DI containermodule and routing.
Plugin / Extensionpoint model Enables customers or internal teams to drop new features without touching core code. Export welldefined interfaces (e.g., IUserProvider, IPermissionResolver, IModuleInitializer).
APIFirst Guarantees that any UI (web, mobile, CLI) can be built on top of the same contract. Publish OpenAPI/GraphQL schema as part of the build artefact.
SecuritybyDesign The platform will hold user credentials, roles and possibly PII. Centralize authentication, authorization, audit, ratelimiting, CORS, CSP, secure defaults.
Observability You need to know when a plugin crashes or misbehaves. Provide structured logging, metrics, tracing, healthchecks, central error bus.
CI/CDReady Boilerplate Keeps the framework maintainable and encourages bestpractice adoption. Include GitHub Actions / GitLab CI pipelines that run lint, unit, integration, contract tests, and a publish step.
ConfigurationasCode Each module may need its own settings but you want a single source of truth. Use a hierarchical config system (environment > file > secret store).
Multitenancy (optional) If you plan SaaS, the core must be ready to isolate data per tenant. Provide tenantaware repository abstractions and tenantscoped middlewares.
Versioning & Compatibility Modules evolve; the core should never break existing plugins. Adopt semantic versioning + backwardscompatibility shim layer (e.g., deprecation warnings).

2 LAYERED / HEXAGONAL BLUEPRINT

+---------------------------------------------------+
|                     Presentation                  |
| (REST/GraphQL/ gRPC Controllers, UI SDKs, CLI)    |
+-------------------+-------------------------------+
|        Application Services (Usecases)          |
|  - orchestrate core & feature modules            |
|  - enforce policies (RBAC, ratelimit)           |
+-------------------+-------------------------------+
|            Domain (Business Logic)               |
|  - Core Entities (User, Role, Permission)       |
|  - Domain Services (PasswordPolicy, TokenMgr)   |
+-------------------+-------------------------------+
|           Infrastructure / Adapters              |
|  - Persistence (ORM/NoSQL Repositories)         |
|  - External services (Email, SMS, OIDC)         |
|  - Event bus (Kafka/Rabbit, Inprocess)         |
|  - File storage, Cache, Search                  |
+---------------------------------------------------+
|                Platform Core (Kernel)            |
|  - DI container, Module loader, Config manager   |
|  - Crosscutting concerns (Logging, Metrics)    |
|  - Security subsystem (AuthN/AuthZ, Token Issuer)|
+---------------------------------------------------+

All layers talk to each other through interfaces defined in the Core kernel. Feature modules implement those interfaces and register themselves at startup.


3 REQUIRED BASE MODULES (THE “CORE KERNEL”)

Module Core responsibilities Public API / Extension points
IdentityManagement - User CRUD (local + federation)
- Password hashing, reset flow
- Email/Phone verification
IUserRepository, IUserService, IExternalIdpProvider
Roles & Permissions - Role hierarchy (role → permission set)
- Permission definitions (string, enum, policy)
- Dynamic permission evaluation (ABAC)
IPermissionResolver, IRoleService
Authentication - JWT / OAuth2 Access & Refresh tokens
- OpenID Connect Provider (optional)
- Session Management (stateless + optional stateful)
IAuthService, ITokenProvider
Authorization Middleware - Enforce RBAC/ABAC on each request
- Policy DSL (e.g., hasPermission('project.read') && resource.ownerId == user.id)
IAuthorizationHandler
Audit & Activity Log - Immutable log of securityrelevant actions
- Correlation IDs, actor, target, timestamp
IAuditSink, IAuditService
Configuration - Hierarchical sources (env, files, secret manager)
- Validation schema (JSONSchema / Yup / JSR380)
IConfigProvider
Health & Metrics - /healthz, /ready, /metrics endpoints
- Export to Prometheus, Grafana, CloudWatch
IHealthCheck, IMetricsRegistry
Error Handling - Centralized error objects, stacktrace masking
- Automatic mapping to HTTP status
- Exceptiontoevent publishing
IErrorMapper, IErrorBus
Logging - Structured JSON logs (level, requestId, userId)
- pluggable sinks (stdout, file, ELK, Cloud Logging)
ILoggerFactory
Notification - Email, SMS, Push (FCM/APNs), Webhooks
- Queuebacked delivery, retries
INotificationService
File / Blob Storage - Abstracted bucket API (upload, version, signed URLs) IBlobStore
Scheduler / Background Jobs - Cronlike tasks, queue workers, retry/backoff policies IJobScheduler, IJobProcessor
Internationalization (i18n) - Message catalog, locale negotiation, runtime translation I18nService
API Gateway (optional) - Ratelimit, request/response transformation, APIkey handling, request routing to modules IGatewayPlugin
Multitenancy (optional) - Tenant identification (subdomain, header, JWT claim)
- Tenantscoped data isolation primitives
ITenantResolver, ITenantContext

Tip: Pack each module as a separate NPM/ Maven / NuGet / Go module with its own package.json / pom.xml etc. The platforms bootstrapper loads every module that implements IModuleInitializer (or similar) and calls ConfigureServices / RegisterRoutes.


4 EXTENSIONPOINT DESIGN (HOW PLUGINS HOOK IN)

  1. Module Manifest a tiny JSON/YAML file (module.yaml) that declares:

    • Module name, version, dependencies (core ≥ 1.2.0, other modules)
    • Public routes (e.g., /api/v1/blog/**)
    • Required permissions (autogenerated from source annotations)
    • UI assets (static folder, React component entry point)
  2. Bootstrap Interface

    export interface IModuleInitializer {
        /**
         * Called during platform startup.
         * Register services, routes, policies, background jobs.
         */
        init(app: IApplicationBuilder, container: IServiceContainer): Promise<void>;
    }
    
  3. Dependency Injection (DI) Conventions

    • Core registers contracts (IUserRepository, IPermissionResolver) as singletons.
    • Modules register implementations with a named scope (e.g., UserRepository:Local).
    • Override is possible via module ordering or explicit container.override(...).
  4. Policy/Permission Extension

    // core lib
    export type Permission = `${string}.${string}`; // e.g., "blog.post.create"
    
    // module
    export const BLOG_PERMS = {
        POST_CREATE: 'blog.post.create',
        POST_READ:   'blog.post.read',
        POST_UPDATE: 'blog.post.update',
        POST_DELETE: 'blog.post.delete',
    } as const;
    
  5. Event Bus & Hooks

    • Central topic: platform.* (user.created, role.assigned, tenant.created)
    • Modules can publish and subscribe via IEventBus.
    • Provide synchronous guard hooks (beforeUserCreate, afterRoleDelete) for validation & sideeffects.
  6. UI Plugin System

    • Serve a manifest at /modules that frontend bundles read to render navigation.
    • Encourage Web Component / Module Federation pattern for SPA integration.

5 SAMPLE REPOSITORY LAYOUT (languageagnostic)

/platform-root
│
├─ /core                                   # ---- Kernel / Base modules ----
│   ├─ /auth
│   │   ├─ src/
│   │   └─ package.json
│   ├─ /identity
│   ├─ /authorization
│   ├─ /audit
│   ├─ /config
│   ├─ /logging
│   ├─ /metrics
│   └─ index.ts (exports all core APIs)
│
├─ /modules                                # ---- Feature plugins ----
│   ├─ /blog
│   │   ├─ module.yaml                     # manifest
│   │   ├─ src/
│   │   │   ├─ BlogController.ts
│   │   │   ├─ BlogService.ts
│   │   │   └─ BlogModule.ts (implements IModuleInitializer)
│   │   └─ package.json
│   │
│   ├─ /billing
│   └─ /chat
│
├─ /infra                                   # ---- Infrastructure adapters ----
│   ├─ /orm (typeorm/hibernate/EFCore etc.)
│   ├─ /cache (redis)
│   ├─ /queue (rabbit/kafka)
│   └─ /storage (s3/azureblob)
│
├─ /gateway (optional APIgateway layer)
│
├─ /scripts                                 # build / lint / test helpers
│
├─ /ci
│   └─ github-actions.yml
│
├─ /docs
│   └─ architecture.md
│
├─ package.json (or pom.xml / go.mod)
└─ README.md

How it boots

// platform-root/src/main.ts
import { createApp } from '@core/app';
import { loadModules } from '@core/module-loader';
import { CoreModule } from '@core';

async function bootstrap() {
  const app = await createApp();

  // 1⃣ Load core kernel (DI, config, logger)
  await app.register(CoreModule);

  // 2⃣ Dynamically discover all `module.yaml` under /modules
  const modules = await loadModules(__dirname + '/modules');

  // 3⃣ Initialise each module (order can be defined in manifest)
  for (const mod of modules) {
    await mod.instance.init(app.builder, app.container);
  }

  // 4⃣ Start HTTP / gRPC server
  await app.listen(process.env.PORT || 3000);
}

bootstrap().catch(err => {
  console.error('❌ Platform failed to start', err);
  process.exit(1);
});

6 KEY DECISIONS YOU MUST TAKE EARLY

Decision Options Implications
Language / Runtime Node.js (NestJS, Fastify), Java (Spring Boot), .NET (ASP.NET Core), Go (Gin/Fiber), Python (FastAPI) Affects DI framework, module packaging, community libs for auth/OIDC, testing.
Persistence Strategy Relational (PostgreSQL, MySQL) + optional NoSQL (Mongo, Dynamo) Choose an ORM/Repository pattern that can be swapped per module.
Auth Protocol JWT + Refresh, OAuth2 Authorization Server, OpenID Connect Provider, or integrate with external IdP (Keycloak, Auth0) Influences token lifetimes, revocation strategy, multitenant support.
Event Bus Inprocess EventEmitter (for monolith) → Kafka/Rabbit for scaling Must expose both sync and async hooks.
Module Packaging NPM packages (private registry) / Maven artifacts / Docker images (for microservice extraction) Define a semantic version policy (core ≥1.0.0 never forces breaking changes on plugins).
Multitenancy Model Single DB with tenant_id column (shared), Schemapertenant, or DBpertenant Affects repository base class and migrations tooling.
Internationalisation i18next (frontend) + ICU messages in backend, or .NET Resource files Choose a format that can be merged from modules at build time.
CI/CD GitHub Actions + Docker Buildx + semanticrelease Automate publishing of core + modules to same artifact registry.
Testing Strategy Unit (Jest, JUnit, xUnit), Integration (Testcontainers), Contract (Pact) Provide a core testing harness that loads a dummy module and asserts the contract of each extension point.

7 COMMON PITFALLS & HOW TO AVOID THEM

Pitfall Symptoms Fix / Guardrail
Tight coupling of modules to core implementation Module imports internal ORM classes, fails on core upgrade. Expose only interfaces (IUserRepository) from core and keep the concrete implementation as a private package.
Hardcoded permission strings Duplicate names across modules, typos cause silent authorisation bypass. Provide a Permission Builder DSL (Permission.define('blog.post', ['create', 'read'])) that generates constants and registers them automatically.
Global state in modules Tests interfere with each other, memory leaks when hotreloading. Enforce stateless services; keep perrequest scoped data (e.g., via DI context).
Schema migrations clash Two modules try to add the same column or foreign key. Adopt a central migration orchestrator (e.g., Flyway/DBMate) that loads migration scripts from each module in alphabetical order.
Authorization checks omitted in new routes Security hole for new plugin routes. Provide a base controller class that autoapplies Authorize filter, or a compiletime lint rule that checks every exported route for a permission annotation.
Vendor lockin to a particular IdP Hard to replace Keycloak later. Keep IdP adapters behind a IIdentityProvider interface; ship at least two (local DB + OIDC).
Unbounded background jobs Queue overflow, OOM, duplicate processing. Use a jobscheduler abstraction that caps concurrency, persists state, and provides @Retry decorator.
Insufficient observability You cant tell which module caused latency spikes. Tag every log/metric with module=<moduleName> automatically via middleware.
Version drift between core and modules Module built against core1.0 fails on core1.5. Publish a core compatibility matrix and enforce peerDependencies in package.json; CI should fail on mismatched ranges.

8 QUICK START GUIDE (What to Build First)

  1. Create the Core Kernel

    • Set up DI container, config loader, logger, health/metrics endpoint.
    • Scaffold IUserRepository, IPermissionResolver, ITokenProvider.
  2. Implement Identity & Auth

    • Choose JWT + Refresh + optional OpenID Connect.
    • Add password hashing (bcrypt/argon2) and email verification flow.
  3. Add Role/Permission Engine

    • Simple RBAC matrix with an extensible Permission type.
    • Provide a UI admin UI (or API only) to manage roles.
  4. Set Up Event Bus & Audit

    • Publish user.created, role.granted events.
    • Store audit entries in an appendonly table (or log to Elastic).
  5. Build the Module Loader

    • Scan modules/*/module.yaml, load via require()/classpath.
    • Register each IModuleInitializer.
  6. Create a Sample Feature Module e.g., Blog

    • Define its own entities (Post, Comment).
    • Register routes (/api/v1/blog/posts).
    • Declare required permissions (blog.post.create).
  7. Write Integration Tests

    • Spin up an inmemory DB (SQLite or H2).
    • Load core + blog module, assert that a user without blog.post.create receives 403.
  8. Add CI Pipeline

    • Lint → Unit → Integration (Docker Compose with DB + Redis).
    • On tag, publish core and blog packages to your private registry.
  9. Document Extension Points

    • Provide a Developer Handbook (README + docs/extension-points.md).
  10. Iterate add Notification, Scheduler, Multitenancy, APIGateway as needed.


9 TOOLS & LIBRARIES (starter suggestions per stack)

Stack Core Auth DI / Module Event Bus ORM Validation Testing
Node (TypeScript) NestJS (or Fastify + awilix) @nestjs/passport, passport-jwt, openid-client NestJS dynamic modules or @nestjs-modules/mailer @nestjs/event-emitter or KafkaJS TypeORM / Prisma class-validator + class-transformer Jest + supertest, Testcontainers
Java Spring Boot Spring Security + spring-boot-starter-oauth2-resource-server Spring Boot @Configuration + ImportBeanDefinitionRegistrar Spring Cloud Stream (Kafka) JPA / Hibernate Bean Validation (Hibernate Validator) JUnit5 + Testcontainers
.NET 8 ASP.NET Core Microsoft.AspNetCore.Authentication.JwtBearer IHostedService + Scrutor for module discovery MassTransit (Rabbit/Kafka) EF Core FluentValidation xUnit + DockerTestContainers
Go Echo / Fiber golang.org/x/oauth2 + github.com/golang-jwt/jwt/v5 uber-go/fx for DI, module registration segmentio/kafka-go GORM / Ent go-playground/validator Testify + Dockertest
Python FastAPI fastapi-users / Authlib pluggy (pytest plugins) or custom loader aiokafka SQLModel / Tortoise ORM Pydantic Pytest + pytestasyncio, Testcontainers

Pick the stack youre most comfortable with; the concepts stay identical.


🎉 TL;DR What You Must Deliver

Layer Musthave components Why
Core Kernel Config, Logger, DI, Health, Metrics, Error Bus Foundation for any module.
Security Auth (JWT/OIDC), Authorization (RBAC + ABAC), Audit Guarantees secure, traceable access.
User & Role Management User CRUD, Password reset, Role ↔ Permission matrix The “identity” piece everyone will reuse.
Extension System IModuleInitializer, module.yaml, EventBus, Permission DSL Enables plugins without touching core.
Infrastructure Adapters DB repo, Cache, Queue, Blob storage, Email/SMS Keeps core agnostic to any concrete tech.
Observability Structured logs, Prometheus metrics, OpenTelemetry traces You can monitor each module individually.
DevOps Boilerplate CI pipelines, Dockerfiles, Semanticrelease, Docs Makes the framework productionready outofthebox.
Sample Feature Module (e.g., Blog) to show how to add routes, permissions, DB entities Provides a reference implementation for future developers.

When you scaffold those pieces once, any downstream team can drop a new folder that follows the module.yaml contract, implement the initializer, add its own tables & APIs, and instantly get:

  • secure authentication,
  • rolebased authorization,
  • logging/metrics,
  • unified config,
  • CIready testing,
  • optional multitenant isolation.

Thats the foundation of a robust, futureproof platform boilerplate. Happy building! 🚀