Files
gh-cubical6-melly/skills/c4model-observations/examples.md
2025-11-29 18:17:07 +08:00

33 KiB

Observation Examples

30+ real-world examples across C1, C2, and C3 levels.


Table of Contents

  1. C1 System Context Examples
  2. C2 Container Examples
  3. C3 Component Examples

C1 System Context Examples

Example 1: Event-Driven Architecture

{
  "id": "obs-event-driven-arch",
  "category": "architecture",
  "severity": "info",
  "title": "Event-driven architecture with message queues",
  "description": "The system uses event-driven architecture with RabbitMQ message queues for asynchronous processing between services. This enables loose coupling and improved scalability.",
  "evidence": [
    {
      "type": "config",
      "location": "docker-compose.yml",
      "snippet": "rabbitmq:\n  image: rabbitmq:3-management\n  ports:\n    - '5672:5672'\n    - '15672:15672'",
      "note": "RabbitMQ configured as message broker"
    },
    {
      "type": "dependency",
      "location": "backend/package.json",
      "snippet": "\"amqplib\": \"^0.10.3\"",
      "note": "AMQP library for queue integration"
    }
  ],
  "tags": ["architecture", "messaging", "async", "rabbitmq"],
  "impact": "Enables horizontal scaling and system resilience. Services can process events asynchronously without blocking."
}

Example 2: Third-Party Payment Dependency

{
  "id": "obs-third-party-payment",
  "category": "external-dependencies",
  "severity": "warning",
  "title": "Critical dependency on third-party payment gateway",
  "description": "System has a hard dependency on Stripe payment gateway with no fallback mechanism. Stripe outages directly impact payment processing capability.",
  "evidence": [
    {
      "type": "code",
      "location": "src/services/payment.ts:23",
      "snippet": "const stripe = new Stripe(process.env.STRIPE_KEY);",
      "note": "Direct Stripe integration with no abstraction layer"
    },
    {
      "type": "file",
      "location": "src/services/payment.ts",
      "note": "Single payment provider implementation, no interface"
    }
  ],
  "tags": ["external-dependency", "payments", "stripe", "resilience"],
  "impact": "System unavailable for payments during Stripe outages. No ability to switch payment providers.",
  "recommendation": "Implement payment gateway abstraction layer to support multiple providers (Stripe, PayPal, Square) with failover capability."
}

Example 3: Microservices Architecture

{
  "id": "obs-microservices-pattern",
  "category": "architecture",
  "severity": "info",
  "title": "Microservices architecture with API gateway",
  "description": "System follows microservices architecture pattern with Kong API gateway routing requests to independent services (user-service, product-service, order-service).",
  "evidence": [
    {
      "type": "config",
      "location": "kong/kong.yml",
      "snippet": "services:\n  - name: user-service\n    url: http://user-api:3000\n  - name: product-service\n    url: http://product-api:3001",
      "note": "Kong gateway configuration"
    },
    {
      "type": "pattern",
      "location": "repos/",
      "note": "Separate repositories for each service: user-service/, product-service/, order-service/"
    }
  ],
  "tags": ["architecture", "microservices", "api-gateway", "kong"],
  "impact": "Enables independent deployment and scaling of services. Increases operational complexity."
}

Example 4: Public API Without Rate Limiting

{
  "id": "obs-no-rate-limiting",
  "category": "security",
  "severity": "critical",
  "title": "Public API lacks rate limiting",
  "description": "REST API is publicly accessible without rate limiting, making it vulnerable to denial-of-service attacks and API abuse.",
  "evidence": [
    {
      "type": "file",
      "location": "src/middleware/",
      "note": "No rate limiting middleware found"
    },
    {
      "type": "config",
      "location": "package.json",
      "note": "No rate limiting library installed (express-rate-limit, rate-limiter-flexible)"
    }
  ],
  "tags": ["security", "rate-limiting", "dos", "api"],
  "impact": "System vulnerable to denial-of-service attacks, API abuse, and resource exhaustion.",
  "recommendation": "Implement rate limiting using express-rate-limit or API gateway rate limiting policies."
}

Example 5: OAuth2 Authentication

{
  "id": "obs-oauth2-integration",
  "category": "integration",
  "severity": "info",
  "title": "OAuth2 authentication via Auth0",
  "description": "System integrates with Auth0 for OAuth2 authentication, supporting social login (Google, Facebook, GitHub) and enterprise SSO.",
  "evidence": [
    {
      "type": "config",
      "location": ".env.example",
      "snippet": "AUTH0_DOMAIN=example.auth0.com\nAUTH0_CLIENT_ID=xxx\nAUTH0_CALLBACK_URL=https://app.example.com/callback"
    },
    {
      "type": "dependency",
      "location": "frontend/package.json",
      "snippet": "\"@auth0/auth0-react\": \"^2.0.1\""
    }
  ],
  "tags": ["authentication", "oauth2", "auth0", "sso"],
  "impact": "Enables enterprise SSO and social login. Reduces authentication implementation complexity."
}

Example 6: Multi-Tenant Architecture

{
  "id": "obs-multi-tenant-saas",
  "category": "architecture",
  "severity": "info",
  "title": "Multi-tenant SaaS architecture with tenant isolation",
  "description": "System implements multi-tenant architecture with database-per-tenant isolation strategy. Each customer organization has a dedicated PostgreSQL schema.",
  "evidence": [
    {
      "type": "code",
      "location": "src/db/tenant.ts:34-38",
      "snippet": "const schema = `tenant_${tenantId}`;\nawait db.raw(`SET search_path TO ${schema}`);\nreturn db;",
      "note": "Schema-based tenant isolation"
    },
    {
      "type": "pattern",
      "location": "src/middleware/tenant-context.ts",
      "note": "Middleware extracts tenant from subdomain and sets context"
    }
  ],
  "tags": ["architecture", "multi-tenant", "saas", "isolation"],
  "impact": "Strong tenant data isolation. Schema-per-tenant approach may limit scalability with thousands of tenants."
}

Example 7: Cloud-Native Deployment

{
  "id": "obs-cloud-native-aws",
  "category": "deployment",
  "severity": "info",
  "title": "Cloud-native deployment on AWS with auto-scaling",
  "description": "System deployed on AWS using ECS Fargate for container orchestration with auto-scaling based on CPU and memory metrics.",
  "evidence": [
    {
      "type": "config",
      "location": "infrastructure/terraform/ecs.tf",
      "snippet": "resource \"aws_appautoscaling_target\" \"ecs_target\" {\n  max_capacity = 10\n  min_capacity = 2\n  resource_id = aws_ecs_service.main.id\n}",
      "note": "Terraform configuration for ECS auto-scaling"
    },
    {
      "type": "file",
      "location": "infrastructure/terraform/",
      "note": "Infrastructure as code using Terraform"
    }
  ],
  "tags": ["deployment", "aws", "ecs", "auto-scaling", "cloud-native"],
  "impact": "Enables automatic scaling based on demand. Reduces infrastructure management overhead."
}

Example 8: Data Lake Integration

{
  "id": "obs-data-lake-snowflake",
  "category": "data-flow",
  "severity": "info",
  "title": "Batch data export to Snowflake data lake",
  "description": "System exports operational data to Snowflake data lake nightly for analytics and reporting. ETL pipeline implemented using Apache Airflow.",
  "evidence": [
    {
      "type": "file",
      "location": "airflow/dags/export-to-snowflake.py",
      "note": "Airflow DAG for nightly data export"
    },
    {
      "type": "config",
      "location": "airflow/config/connections.yml",
      "snippet": "snowflake_conn:\n  conn_type: snowflake\n  account: xy12345\n  database: analytics_db"
    }
  ],
  "tags": ["data-flow", "etl", "snowflake", "analytics", "airflow"],
  "impact": "Enables advanced analytics and reporting without impacting operational database performance."
}

Example 9: Service Mesh Implementation

{
  "id": "obs-istio-service-mesh",
  "category": "integration",
  "severity": "info",
  "title": "Istio service mesh for service-to-service communication",
  "description": "Microservices communicate through Istio service mesh providing mTLS encryption, traffic management, and observability.",
  "evidence": [
    {
      "type": "config",
      "location": "k8s/istio/virtual-service.yml",
      "snippet": "apiVersion: networking.istio.io/v1beta1\nkind: VirtualService\nmetadata:\n  name: user-service"
    },
    {
      "type": "pattern",
      "location": "k8s/",
      "note": "Istio sidecar proxies injected into all service pods"
    }
  ],
  "tags": ["integration", "service-mesh", "istio", "mtls", "microservices"],
  "impact": "Provides mTLS encryption, circuit breaking, and distributed tracing without application code changes."
}

Example 10: Geographic Distribution

{
  "id": "obs-multi-region-active-active",
  "category": "scalability",
  "severity": "info",
  "title": "Multi-region active-active deployment for global users",
  "description": "System deployed in active-active configuration across US-East, US-West, and EU-Central regions with Route53 latency-based routing.",
  "evidence": [
    {
      "type": "config",
      "location": "infrastructure/terraform/route53.tf",
      "snippet": "routing_policy = \"latency\"\nset_identifier = \"us-east-1\""
    },
    {
      "type": "pattern",
      "location": "infrastructure/",
      "note": "Three Terraform workspaces: us-east, us-west, eu-central"
    }
  ],
  "tags": ["scalability", "multi-region", "global", "high-availability"],
  "impact": "Reduces latency for global users. Provides regional failover capability. Increases infrastructure cost and complexity."
}

C2 Container Examples

Example 11: React SPA with State Management

{
  "id": "obs-spa-state-mgmt",
  "category": "technology",
  "severity": "info",
  "title": "Redux Toolkit for state management in React SPA",
  "description": "Frontend SPA uses Redux Toolkit for global state management, following best practices with feature-based slices and RTK Query for API calls.",
  "evidence": [
    {
      "type": "dependency",
      "location": "frontend/package.json",
      "snippet": "\"@reduxjs/toolkit\": \"^1.9.5\",\n\"react-redux\": \"^8.1.1\""
    },
    {
      "type": "file",
      "location": "frontend/src/store/",
      "note": "Well-organized store structure with feature slices: authSlice, userSlice, productSlice"
    },
    {
      "type": "code",
      "location": "frontend/src/store/index.ts",
      "snippet": "import { configureStore } from '@reduxjs/toolkit';\nimport authReducer from './authSlice';"
    }
  ],
  "tags": ["state-management", "redux", "frontend", "react"],
  "impact": "Provides predictable state updates, improved debugging with Redux DevTools, and type-safe API calls."
}

Example 12: Database Connection Pool Missing

{
  "id": "obs-db-no-connection-pool",
  "category": "performance",
  "severity": "warning",
  "title": "Database connections not pooled",
  "description": "Backend API creates new database connections for each request instead of using connection pooling, leading to performance degradation under load.",
  "evidence": [
    {
      "type": "code",
      "location": "src/db/connection.ts:12-15",
      "snippet": "export async function getConnection() {\n  return await mysql.createConnection(config);\n}",
      "note": "New connection created for every query"
    },
    {
      "type": "code",
      "location": "src/routes/users.ts:23",
      "snippet": "const conn = await getConnection();\nconst users = await conn.query('SELECT * FROM users');",
      "note": "Pattern repeated throughout codebase"
    }
  ],
  "tags": ["performance", "database", "connection-pool", "scalability"],
  "impact": "High latency for database queries. Connection exhaustion under concurrent load. Potential database server overload.",
  "recommendation": "Implement connection pooling using mysql2/pool with min 5, max 20 connections."
}

Example 13: Container Health Checks

{
  "id": "obs-health-check-implemented",
  "category": "deployment",
  "severity": "info",
  "title": "Comprehensive health check endpoints",
  "description": "Container implements /health (liveness) and /ready (readiness) endpoints with dependency checks for database, cache, and message queue.",
  "evidence": [
    {
      "type": "code",
      "location": "src/routes/health.ts:10-25",
      "snippet": "app.get('/health', async (req, res) => {\n  const dbOk = await checkDatabase();\n  const redisOk = await checkRedis();\n  const queueOk = await checkQueue();\n  res.status(dbOk && redisOk && queueOk ? 200 : 503).json({...});\n});"
    },
    {
      "type": "config",
      "location": "k8s/deployment.yml:45-52",
      "snippet": "livenessProbe:\n  httpGet:\n    path: /health\n    port: 3000\nreadinessProbe:\n  httpGet:\n    path: /ready\n    port: 3000"
    }
  ],
  "tags": ["deployment", "health-check", "kubernetes", "reliability"],
  "impact": "Kubernetes can detect and restart unhealthy containers. Prevents routing traffic to containers not ready to serve requests."
}

Example 14: WebSocket Real-Time Communication

{
  "id": "obs-websocket-notifications",
  "category": "communication",
  "severity": "info",
  "title": "WebSocket server for real-time notifications",
  "description": "Container implements WebSocket server using Socket.io for real-time push notifications to connected clients.",
  "evidence": [
    {
      "type": "dependency",
      "location": "backend/package.json",
      "snippet": "\"socket.io\": \"^4.6.1\""
    },
    {
      "type": "code",
      "location": "src/websocket/server.ts:15-20",
      "snippet": "const io = new Server(httpServer, {\n  cors: { origin: process.env.CORS_ORIGIN },\n  transports: ['websocket', 'polling']\n});"
    }
  ],
  "tags": ["communication", "websocket", "real-time", "socket.io"],
  "impact": "Enables instant notifications without polling. Maintains persistent connections, increasing server memory usage."
}

Example 15: Docker Multi-Stage Build

{
  "id": "obs-docker-multi-stage",
  "category": "deployment",
  "severity": "info",
  "title": "Multi-stage Docker build for optimized image size",
  "description": "Container uses multi-stage Dockerfile separating build and runtime stages, reducing final image size from 1.2GB to 180MB.",
  "evidence": [
    {
      "type": "config",
      "location": "Dockerfile:1-15",
      "snippet": "# Build stage\nFROM node:18-alpine AS builder\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\n# Runtime stage\nFROM node:18-alpine\nWORKDIR /app\nCOPY --from=builder /app/dist ./dist\nCOPY package*.json ./\nRUN npm ci --production"
    }
  ],
  "tags": ["deployment", "docker", "optimization", "image-size"],
  "impact": "Reduces image size by 84%, faster deployments, lower storage costs, smaller attack surface."
}

Example 16: Redis Session Storage

{
  "id": "obs-redis-sessions",
  "category": "data-storage",
  "severity": "info",
  "title": "Redis for session storage with TTL",
  "description": "Container stores user sessions in Redis with 24-hour TTL, enabling horizontal scaling and fast session lookups.",
  "evidence": [
    {
      "type": "code",
      "location": "src/config/session.ts:8-14",
      "snippet": "app.use(session({\n  store: new RedisStore({ client: redisClient }),\n  secret: process.env.SESSION_SECRET,\n  resave: false,\n  saveUninitialized: false,\n  cookie: { maxAge: 24 * 60 * 60 * 1000 }\n}));"
    },
    {
      "type": "dependency",
      "location": "package.json",
      "snippet": "\"connect-redis\": \"^7.1.0\",\n\"redis\": \"^4.6.5\""
    }
  ],
  "tags": ["data-storage", "redis", "sessions", "caching"],
  "impact": "Enables stateless application design. Session data survives container restarts. Fast session access (~1ms)."
}

Example 17: Environment Variable Overload

{
  "id": "obs-env-var-overload",
  "category": "configuration",
  "severity": "warning",
  "title": "Excessive environment variables (42 required)",
  "description": "Container requires 42 environment variables to start, making configuration error-prone and deployment complex.",
  "evidence": [
    {
      "type": "file",
      "location": ".env.example",
      "note": "42 environment variables listed"
    },
    {
      "type": "code",
      "location": "src/config/index.ts:5-50",
      "snippet": "export const config = {\n  dbHost: required('DB_HOST'),\n  dbPort: required('DB_PORT'),\n  // ... 40 more",
      "note": "Long list of required config values"
    }
  ],
  "tags": ["configuration", "environment-variables", "complexity"],
  "impact": "High configuration complexity. Prone to misconfiguration errors. Difficult onboarding for new developers.",
  "recommendation": "Consolidate configuration using a config server (e.g., Spring Cloud Config) or use sensible defaults with override capability."
}

Example 18: No Distributed Tracing

{
  "id": "obs-no-distributed-tracing",
  "category": "monitoring",
  "severity": "warning",
  "title": "Missing distributed tracing in microservices",
  "description": "Container has logging but no distributed tracing instrumentation, making it difficult to debug cross-service request flows.",
  "evidence": [
    {
      "type": "file",
      "location": "package.json",
      "note": "No OpenTelemetry, Jaeger, or Zipkin dependencies"
    },
    {
      "type": "pattern",
      "location": "src/middleware/",
      "note": "No trace context propagation middleware"
    }
  ],
  "tags": ["monitoring", "distributed-tracing", "observability", "microservices"],
  "impact": "Difficult to trace requests across service boundaries. Hard to identify performance bottlenecks in multi-service flows.",
  "recommendation": "Implement OpenTelemetry instrumentation with Jaeger or Tempo backend for distributed tracing."
}

Example 19: gRPC Inter-Service Communication

{
  "id": "obs-grpc-communication",
  "category": "communication",
  "severity": "info",
  "title": "gRPC for high-performance inter-service communication",
  "description": "Container uses gRPC with Protocol Buffers for efficient inter-service communication, providing better performance than REST for internal APIs.",
  "evidence": [
    {
      "type": "dependency",
      "location": "package.json",
      "snippet": "\"@grpc/grpc-js\": \"^1.8.14\",\n\"@grpc/proto-loader\": \"^0.7.6\""
    },
    {
      "type": "file",
      "location": "proto/user-service.proto",
      "snippet": "service UserService {\n  rpc GetUser (GetUserRequest) returns (User);\n  rpc ListUsers (ListUsersRequest) returns (UserList);\n}",
      "note": "Protocol Buffer service definition"
    }
  ],
  "tags": ["communication", "grpc", "protobuf", "performance"],
  "impact": "Lower latency and bandwidth usage vs REST. Type-safe service contracts. Requires gRPC-compatible clients."
}

Example 20: JWT Authentication with Refresh Tokens

{
  "id": "obs-jwt-refresh-tokens",
  "category": "authentication",
  "severity": "info",
  "title": "JWT authentication with refresh token rotation",
  "description": "Container implements JWT access tokens (15min TTL) with refresh tokens (7 days) stored in httpOnly cookies, following OAuth2 best practices.",
  "evidence": [
    {
      "type": "code",
      "location": "src/auth/jwt.ts:45-52",
      "snippet": "const accessToken = jwt.sign(payload, secret, { expiresIn: '15m' });\nconst refreshToken = jwt.sign({ userId }, refreshSecret, { expiresIn: '7d' });\nres.cookie('refreshToken', refreshToken, { httpOnly: true, secure: true });",
      "note": "Token generation with appropriate TTLs"
    }
  ],
  "tags": ["authentication", "jwt", "refresh-tokens", "security"],
  "impact": "Balances security (short-lived access tokens) with UX (long refresh window). Refresh tokens in httpOnly cookies prevent XSS theft."
}

C3 Component Examples

Example 21: JWT in localStorage (Security Issue)

{
  "id": "obs-auth-jwt-localstorage",
  "category": "security",
  "severity": "critical",
  "title": "JWT tokens stored in localStorage",
  "description": "Authentication component stores JWT tokens in browser localStorage, making them accessible to JavaScript and vulnerable to XSS attacks. Tokens should be stored in httpOnly cookies.",
  "evidence": [
    {
      "type": "code",
      "location": "src/features/auth/authSlice.ts:45",
      "snippet": "localStorage.setItem('authToken', action.payload.token);",
      "note": "Token persisted in localStorage"
    },
    {
      "type": "code",
      "location": "src/features/auth/authSlice.ts:52",
      "snippet": "const token = localStorage.getItem('authToken');\nif (token) { setAuthHeader(token); }",
      "note": "Token retrieved from localStorage on app init"
    }
  ],
  "tags": ["security", "authentication", "xss", "jwt"],
  "impact": "High security risk - Any XSS vulnerability can lead to token theft and account takeover. Tokens persist across browser sessions.",
  "recommendation": "Migrate to httpOnly cookies for token storage. Tokens will be automatically included in requests and inaccessible to JavaScript."
}

Example 22: Repository Pattern Implementation

{
  "id": "obs-repository-pattern",
  "category": "design-patterns",
  "severity": "info",
  "title": "Repository pattern for data access layer",
  "description": "UserService component implements the repository pattern to abstract database operations, improving testability and separation of concerns.",
  "evidence": [
    {
      "type": "file",
      "location": "src/repositories/UserRepository.ts",
      "note": "Dedicated repository class implementing IUserRepository interface"
    },
    {
      "type": "code",
      "location": "src/services/UserService.ts:23",
      "snippet": "constructor(private userRepo: IUserRepository) {}",
      "note": "Dependency injection of repository interface, not concrete implementation"
    },
    {
      "type": "code",
      "location": "src/repositories/UserRepository.ts:15-20",
      "snippet": "async findById(id: string): Promise<User | null> {\n  const row = await this.db('users').where({ id }).first();\n  return row ? this.mapToEntity(row) : null;\n}",
      "note": "Repository handles ORM queries and entity mapping"
    }
  ],
  "tags": ["design-pattern", "repository", "data-access", "separation-of-concerns"],
  "impact": "Improved testability through dependency injection. Clean separation between business logic and data access. Easier to swap database implementations."
}

Example 23: Missing Error Handling

{
  "id": "obs-no-error-handling",
  "category": "error-handling",
  "severity": "warning",
  "title": "Missing error handling in async operations",
  "description": "PaymentService component performs async Stripe operations without proper error handling, risking unhandled promise rejections and application crashes.",
  "evidence": [
    {
      "type": "code",
      "location": "src/features/payment/PaymentService.ts:78-82",
      "snippet": "async processPayment(amount: number) {\n  const charge = await stripe.charges.create({ amount });\n  await this.recordPayment(charge.id);\n  return charge.id;\n}",
      "note": "No try-catch block or .catch() handler"
    },
    {
      "type": "code",
      "location": "src/features/payment/PaymentService.ts:95-98",
      "snippet": "async refundPayment(chargeId: string) {\n  const refund = await stripe.refunds.create({ charge: chargeId });\n  return refund;\n}",
      "note": "Same pattern - no error handling"
    }
  ],
  "tags": ["error-handling", "async", "reliability", "payment"],
  "impact": "Application crashes or silent failures when Stripe API errors occur. No user feedback on payment failures. Potential data inconsistency.",
  "recommendation": "Add try-catch blocks to all async operations. Handle specific error types (network, API errors, validation). Log errors and return user-friendly messages."
}

Example 24: High Cyclomatic Complexity

{
  "id": "obs-high-complexity-validation",
  "category": "complexity",
  "severity": "warning",
  "title": "High cyclomatic complexity in validation function",
  "description": "FormValidator.validate() function has cyclomatic complexity of 45, making it difficult to understand, test, and maintain.",
  "evidence": [
    {
      "type": "metric",
      "location": "src/utils/FormValidator.ts:validate",
      "snippet": "Cyclomatic complexity: 45",
      "note": "Measured with ESLint complexity rule"
    },
    {
      "type": "code",
      "location": "src/utils/FormValidator.ts:25-180",
      "snippet": "function validate(form: Form): ValidationResult {\n  if (form.email) {\n    if (!isEmail(form.email)) {\n      if (form.email.includes('@')) {\n        // 150+ lines of nested conditions...",
      "note": "Deep nesting (7 levels) with many branches"
    }
  ],
  "tags": ["complexity", "code-quality", "maintainability", "testing"],
  "impact": "Difficult to understand control flow. Hard to achieve full test coverage. High risk of bugs when modifying. New developers struggle to maintain.",
  "recommendation": "Refactor into smaller functions, each validating one field. Extract common validation logic. Consider using validation library like Joi or Yup."
}

Example 25: Comprehensive Unit Tests

{
  "id": "obs-good-test-coverage",
  "category": "testing",
  "severity": "info",
  "title": "High unit test coverage with quality tests",
  "description": "AuthService component has 95% unit test coverage with well-structured tests covering happy paths, edge cases, and error scenarios.",
  "evidence": [
    {
      "type": "metric",
      "location": "coverage/auth/AuthService.ts.html",
      "snippet": "Lines: 95.2% (120/126)\nBranches: 92.5% (37/40)",
      "note": "Jest coverage report"
    },
    {
      "type": "file",
      "location": "src/features/auth/__tests__/AuthService.test.ts",
      "note": "12 test cases covering login, logout, token refresh, error scenarios"
    },
    {
      "type": "code",
      "location": "src/features/auth/__tests__/AuthService.test.ts:45-52",
      "snippet": "describe('login', () => {\n  it('should return tokens on valid credentials', async () => {...});\n  it('should throw on invalid credentials', async () => {...});\n  it('should lock account after 5 failed attempts', async () => {...});\n});"
    }
  ],
  "tags": ["testing", "unit-tests", "coverage", "quality"],
  "impact": "High confidence in component behavior. Early bug detection. Safe refactoring. Good documentation through tests."
}

Example 26: N+1 Query Problem

{
  "id": "obs-n-plus-one-queries",
  "category": "performance",
  "severity": "warning",
  "title": "N+1 query problem in dashboard data loading",
  "description": "DashboardController loads user posts in a loop, executing one query per post (N+1 problem). For a user with 100 posts, this results in 101 database queries.",
  "evidence": [
    {
      "type": "code",
      "location": "src/controllers/DashboardController.ts:78-82",
      "snippet": "const posts = await Post.find({ userId });\nfor (const post of posts) {\n  post.comments = await Comment.find({ postId: post.id }); // N queries\n  post.likes = await Like.count({ postId: post.id });      // N queries\n}",
      "note": "Separate query for each post's comments and likes"
    }
  ],
  "tags": ["performance", "database", "n+1", "orm"],
  "impact": "Dashboard load time scales linearly with number of posts. 100 posts = 201 queries = ~2 seconds. Severe performance degradation with large datasets.",
  "recommendation": "Use eager loading or JOIN queries to load related data in single query. Example: Post.find({ userId }).populate('comments likes')"
}

Example 27: Tight Coupling to ORM

{
  "id": "obs-tight-orm-coupling",
  "category": "coupling",
  "severity": "warning",
  "title": "Business logic tightly coupled to Sequelize ORM",
  "description": "Service layer components directly use Sequelize models and queries throughout, making it difficult to test or switch ORMs.",
  "evidence": [
    {
      "type": "code",
      "location": "src/services/OrderService.ts:34-38",
      "snippet": "async createOrder(data: OrderData) {\n  const order = await Order.create(data);\n  const items = await OrderItem.bulkCreate(order.id, data.items);\n  return order;\n}",
      "note": "Direct Sequelize model usage in service"
    },
    {
      "type": "pattern",
      "location": "src/services/",
      "note": "All 15 service files directly import and use Sequelize models"
    }
  ],
  "tags": ["coupling", "orm", "architecture", "testability"],
  "impact": "Difficult to unit test services (requires database). Hard to switch ORM. Business logic mixed with data access concerns.",
  "recommendation": "Introduce repository layer to abstract ORM. Services depend on repository interfaces, not concrete ORM implementations."
}

Example 28: Factory Pattern for Service Creation

{
  "id": "obs-factory-pattern-services",
  "category": "design-patterns",
  "severity": "info",
  "title": "Factory pattern for creating service instances",
  "description": "ServiceFactory component uses factory pattern to create service instances with appropriate dependencies, improving modularity and testability.",
  "evidence": [
    {
      "type": "code",
      "location": "src/factories/ServiceFactory.ts:12-25",
      "snippet": "class ServiceFactory {\n  createUserService(): UserService {\n    const repo = new UserRepository(this.db);\n    const cache = new RedisCache(this.redis);\n    const notifier = new EmailNotifier(this.mailer);\n    return new UserService(repo, cache, notifier);\n  }\n}",
      "note": "Factory encapsulates complex service construction"
    }
  ],
  "tags": ["design-pattern", "factory", "dependency-injection", "modularity"],
  "impact": "Centralized service creation logic. Easy to swap implementations. Supports testing with mock dependencies."
}

Example 29: Missing Input Validation

{
  "id": "obs-no-input-validation",
  "category": "security",
  "severity": "critical",
  "title": "No input validation in API controllers",
  "description": "UserController accepts user input without validation, allowing malformed data to reach the database and potentially causing SQL injection or data corruption.",
  "evidence": [
    {
      "type": "code",
      "location": "src/controllers/UserController.ts:23-27",
      "snippet": "async createUser(req: Request, res: Response) {\n  const user = await userService.create(req.body);\n  res.json(user);\n}",
      "note": "req.body used directly without validation"
    },
    {
      "type": "pattern",
      "location": "src/controllers/",
      "note": "No validation middleware (joi, class-validator, zod) found in any controller"
    }
  ],
  "tags": ["security", "validation", "input-validation", "api"],
  "impact": "Critical security vulnerability. Risk of SQL injection, NoSQL injection, data corruption. Invalid data can crash application.",
  "recommendation": "Implement input validation using Joi, class-validator, or Zod. Validate all inputs at controller level before processing."
}

Example 30: Code Documentation with TSDoc

{
  "id": "obs-tsdoc-documentation",
  "category": "documentation",
  "severity": "info",
  "title": "Comprehensive TSDoc documentation for public APIs",
  "description": "All public methods and classes in the API layer have comprehensive TSDoc comments including descriptions, parameter types, return values, and usage examples.",
  "evidence": [
    {
      "type": "code",
      "location": "src/api/UserAPI.ts:15-24",
      "snippet": "/**\n * Creates a new user account.\n * @param userData - User registration data\n * @param userData.email - User email (must be unique)\n * @param userData.password - Password (min 8 characters)\n * @returns Newly created user object (password excluded)\n * @throws {ValidationError} If email already exists\n * @example\n * const user = await userAPI.createUser({ email: 'test@example.com', password: 'secret123' });\n */\nasync createUser(userData: UserRegistrationData): Promise<User>"
    }
  ],
  "tags": ["documentation", "tsdoc", "api", "code-quality"],
  "impact": "Excellent developer experience. IntelliSense shows detailed information. Easier onboarding for new developers. Reduced need for external documentation."
}

Summary

This examples document provides 30 real-world observation examples:

  • C1 System Context: 10 examples covering architecture, integration, security, scalability, deployment
  • C2 Container: 10 examples covering technology, performance, communication, monitoring, authentication
  • C3 Component: 10 examples covering design patterns, security, testing, complexity, code quality

Each example demonstrates:

  • Proper structure with all required fields
  • Concrete evidence with file paths and code snippets
  • Appropriate severity levels
  • Clear impact and recommendations
  • Relevant tags for searchability

Use these examples as templates when documenting your own architectural observations.