Files
dd0c/products/04-lightweight-idp/test-architecture/test-architecture.md
Max Mayfield 5ee95d8b13 dd0c: full product research pipeline - 6 products, 8 phases each
Products: route, drift, alert, portal, cost, run
Phases: brainstorm, design-thinking, innovation-strategy, party-mode,
        product-brief, architecture, epics (incl. Epic 10 TF compliance),
        test-architecture (TDD strategy)

Brand strategy and market research included.
2026-02-28 17:35:02 +00:00

27 KiB

dd0c/portal — Test Architecture & TDD Strategy

Product: Lightweight Internal Developer Portal Phase: 6 — Architecture Design Date: 2026-02-28 Status: Draft


1. Testing Philosophy & TDD Workflow

Core Principle

dd0c/portal's most critical logic — ownership inference, discovery reconciliation, and confidence scoring — is pure algorithmic code with well-defined inputs and outputs. This is ideal TDD territory. The test suite is the specification.

The product's >80% discovery accuracy target is not a QA metric — it's a product promise. Tests enforce it continuously.

Red-Green-Refactor Adapted to This Product

RED   → Write a failing test that encodes a discovery heuristic or ownership rule
GREEN → Write the minimum code to pass it (no clever abstractions yet)
REFACTOR → Clean up once the rule is proven correct against real-world fixtures

Adapted cycle for discovery heuristics:

  1. Capture a real-world failure case (e.g., "Lambda functions named payment-* were not grouped into a service")
  2. Write a unit test encoding the expected grouping behavior using a fixture of that Lambda response
  3. Fix the heuristic
  4. Add the fixture to the regression suite permanently

This means every production accuracy bug becomes a permanent test. The test suite grows as a living record of every edge case the discovery engine has encountered.

When to Write Tests First vs. Integration Tests Lead

Scenario Approach Rationale
Ownership scoring algorithm Unit-first TDD Pure function, deterministic, no I/O
Discovery heuristics (CFN → service mapping) Unit-first TDD Deterministic logic over fixture data
GitHub GraphQL query construction Unit-first TDD Query builder logic is pure
AWS API pagination handling Integration-first Behavior depends on real API shape
Meilisearch index sync Integration-first Depends on Meilisearch document model
DynamoDB schema migrations Integration-first Requires real DynamoDB Local behavior
WebSocket progress events E2E-first Requires full pipeline to be meaningful
Stripe webhook handling Integration-first Depends on Stripe event payload shape

Test Naming Conventions

All tests follow the pattern: [unit under test]_[scenario]_[expected outcome]

TypeScript/Node.js (Jest):

describe('OwnershipInferenceEngine', () => {
  describe('scoreOwnership', () => {
    it('returns_primary_owner_when_codeowners_present_with_high_confidence', () => {})
    it('marks_service_unowned_when_top_score_below_threshold', () => {})
    it('marks_service_ambiguous_when_top_two_scores_within_tolerance', () => {})
  })
})

Python (pytest):

class TestOwnershipScorer:
    def test_codeowners_signal_weighted_highest_among_all_signals(self): ...
    def test_git_blame_frequency_used_when_codeowners_absent(self): ...
    def test_confidence_below_threshold_flags_service_as_unowned(self): ...

File naming:

  • Unit tests: *.test.ts / test_*.py co-located with source
  • Integration tests: *.integration.test.ts / test_*_integration.py in tests/integration/
  • E2E tests: tests/e2e/*.spec.ts (Playwright)

2. Test Pyramid

         ┌─────────────┐
         │   E2E / Smoke│  10%  (~30 tests)
         │  (Playwright)│       Critical user journeys only
         ├─────────────┤
         │ Integration  │  20%  (~80 tests)
         │  (real deps) │       Service boundaries, API contracts
         ├─────────────┤
         │    Unit      │  70%  (~280 tests)
         │  (pure logic)│       All heuristics, scoring, parsing
         └─────────────┘

Unit Test Targets (per component)

Component Language Test Framework Target Coverage
AWS Scanner (heuristics) Python pytest 90%
GitHub Scanner (parsers) Node.js Jest 90%
Reconciliation Engine Node.js Jest 85%
Ownership Inference Python pytest 95%
Portal API (route handlers) Node.js Jest + Supertest 80%
Search proxy + cache logic Node.js Jest 85%
Slack Bot command handlers Node.js Jest 80%
Feature flag evaluation Node.js/Python Jest/pytest 95%
Governance policy engine Node.js Jest 95%
Schema migration validators Node.js Jest 100%

Integration Test Boundaries

Boundary What to Test Tool
Discovery → GitHub API GraphQL query shape, pagination, rate limit handling MSW (mock service worker) or nock
Discovery → AWS APIs boto3 call sequences, pagination, error handling moto (AWS mock library)
Reconciler → PostgreSQL Upsert logic, conflict resolution, RLS enforcement Testcontainers (PostgreSQL)
Inference → PostgreSQL Ownership write, confidence update, correction propagation Testcontainers (PostgreSQL)
API → Meilisearch Index sync, search query construction, tenant filter injection Meilisearch test instance (Docker)
API → Redis Cache set/get/invalidation, TTL behavior ioredis-mock or Testcontainers (Redis)
Slack Bot → Portal API Command → search → format response Supertest against local API
Stripe webhook → API Subscription activation, plan change, cancellation Stripe CLI webhook forwarding

E2E / Smoke Test Scenarios

  1. Full onboarding: GitHub OAuth → AWS connection → discovery trigger → catalog populated
  2. Cmd+K search returns results in <200ms after discovery
  3. Ownership correction propagates to similar services
  4. Slack /dd0c who owns returns correct owner
  5. Discovery accuracy: synthetic org with known ground truth scores >80%
  6. Governance strict mode: discovery populates pending queue, not catalog directly
  7. Panic mode: all catalog writes return 503

3. Unit Test Strategy (Per Component)

3.1 AWS Scanner (Python / pytest)

What to test:

  • Resource-to-service grouping heuristics (the core logic)
  • Confidence score assignment per signal type
  • Pagination handling for each AWS API
  • Cross-region scan aggregation
  • Error handling for throttling, missing permissions, empty accounts

Key test cases:

# tests/unit/test_cfn_scanner.py

class TestCloudFormationScanner:
    def test_stack_name_becomes_service_name_with_high_confidence(self):
        # Given a CFN stack named "payment-api"
        # Expect service entity with name="payment-api", confidence=0.95

    def test_stack_tags_extracted_as_service_metadata(self):
        # Given stack with tags {"service": "payment", "team": "payments"}
        # Expect service.metadata includes both tags

    def test_stacks_in_multiple_regions_deduplicated_by_name(self):
        # Given same stack name in us-east-1 and us-west-2
        # Expect single service entity with both regions in infrastructure

    def test_deleted_stacks_excluded_from_results(self):
        # Given stack with status DELETE_COMPLETE
        # Expect it is not included in discovered services

    def test_pagination_fetches_all_stacks_beyond_first_page(self):
        # Given mock returning 2 pages of stacks
        # Expect all stacks from both pages are processed

class TestLambdaScanner:
    def test_lambdas_with_shared_prefix_grouped_into_single_service(self):
        # Given ["payment-webhook", "payment-processor", "payment-refund"]
        # Expect single service "payment" with confidence=0.60

    def test_lambda_with_apigw_trigger_gets_higher_confidence(self):
        # Given Lambda with API Gateway event source mapping
        # Expect confidence=0.85 (not 0.60)

    def test_standalone_lambda_without_prefix_pattern_kept_as_individual(self):
        # Given Lambda named "data-export-job" with no siblings
        # Expect individual service entity, not grouped

class TestServiceGroupingHeuristics:
    def test_cfn_stack_takes_priority_over_ecs_service_for_same_name(self):
        # Given CFN stack "payment-api" AND ECS service "payment-api"
        # Expect single service entity (not duplicate), source=cloudformation

    def test_explicit_github_repo_tag_overrides_name_matching(self):
        # Given AWS resource with tag github_repo="acme/payments-v2"
        # Expect repo_link="acme/payments-v2" with confidence=0.95
        # (not fuzzy name match result)

Mocking strategy:

  • Use moto to mock all boto3 calls — no real AWS calls in unit tests
  • Fixture files in tests/fixtures/aws/ contain realistic API response payloads
  • Each fixture named after the scenario: cfn_stacks_multi_region.json, lambda_functions_with_apigw.json
@pytest.fixture
def mock_aws(aws_credentials):
    with mock_cloudformation(), mock_ecs(), mock_lambda_():
        yield

def test_full_scan_produces_expected_service_count(mock_aws, cfn_fixture):
    setup_mock_cfn_stacks(cfn_fixture)
    result = AWSScanner(tenant_id="test", role_arn="arn:aws:iam::123:role/test").scan()
    assert len(result.services) == cfn_fixture["expected_service_count"]

3.2 GitHub Scanner (Node.js / Jest)

What to test:

  • GraphQL query construction and batching
  • CODEOWNERS file parsing (all valid formats)
  • README first-paragraph extraction
  • Deploy workflow target extraction
  • Rate limit detection and backoff

Key test cases:

// tests/unit/github-scanner/codeowners-parser.test.ts

describe('CODEOWNERSParser', () => {
  it('parses_simple_wildcard_ownership_to_team', () => {
    const input = '* @acme/platform-team'
    expect(parse(input)).toEqual([{ pattern: '*', owners: ['@acme/platform-team'] }])
  })

  it('parses_path_specific_ownership', () => {
    const input = '/src/payments/ @acme/payments-team'
    expect(parse(input)).toEqual([{ pattern: '/src/payments/', owners: ['@acme/payments-team'] }])
  })

  it('handles_multiple_owners_per_pattern', () => {
    const input = '*.ts @acme/frontend @acme/platform'
    expect(parse(input).owners).toHaveLength(2)
  })

  it('ignores_comment_lines', () => {
    const input = '# This is a comment\n* @acme/team'
    expect(parse(input)).toHaveLength(1)
  })

  it('returns_empty_array_for_missing_codeowners_file', () => {
    expect(parse(null)).toEqual([])
  })

  it('handles_individual_user_ownership_not_just_teams', () => {
    const input = '* @sarah-chen'
    expect(parse(input)[0].owners[0]).toBe('@sarah-chen')
  })
})

describe('READMEExtractor', () => {
  it('extracts_first_non_heading_non_badge_paragraph', () => {
    const readme = `# Payment Gateway\n\n![build](badge.svg)\n\nHandles Stripe checkout flows.`
    expect(extractDescription(readme)).toBe('Handles Stripe checkout flows.')
  })

  it('returns_null_when_readme_has_only_headings_and_badges', () => {
    const readme = `# Title\n\n![badge](url)`
    expect(extractDescription(readme)).toBeNull()
  })
})

describe('WorkflowTargetExtractor', () => {
  it('extracts_ecs_service_name_from_deploy_workflow', () => {
    const yaml = loadFixture('deploy-workflow-ecs.yml')
    expect(extractDeployTarget(yaml)).toEqual({
      type: 'ecs_service',
      name: 'payment-api',
      cluster: 'production'
    })
  })

  it('extracts_lambda_function_name_from_serverless_deploy', () => {
    const yaml = loadFixture('deploy-workflow-lambda.yml')
    expect(extractDeployTarget(yaml)).toEqual({
      type: 'lambda_function',
      name: 'payment-webhook-handler'
    })
  })
})

Mocking strategy:

  • Use nock or msw to intercept GitHub GraphQL API calls
  • Fixture files in tests/fixtures/github/ for realistic API responses
  • Test the GraphQL query builder separately from the HTTP client

3.3 Reconciliation Engine (Node.js / Jest)

What to test:

  • Cross-referencing AWS resources with GitHub repos (all 5 matching rules)
  • Deduplication when multiple signals point to the same service
  • Conflict resolution when signals disagree
  • Batch processing of SQS messages

Key test cases:

describe('ReconciliationEngine', () => {
  describe('matchAWSToGitHub', () => {
    it('explicit_tag_match_takes_highest_priority', () => {
      const awsService = buildAWSService({ tags: { github_repo: 'acme/payment-gateway' } })
      const ghRepo = buildGHRepo({ name: 'payment-gateway', org: 'acme' })
      const result = reconcile([awsService], [ghRepo])
      expect(result[0].repoLinkSource).toBe('explicit_tag')
      expect(result[0].repoLinkConfidence).toBe(0.95)
    })

    it('deploy_workflow_match_used_when_no_explicit_tag', () => {
      const awsService = buildAWSService({ name: 'payment-api' })
      const ghRepo = buildGHRepo({ deployTarget: 'payment-api' })
      const result = reconcile([awsService], [ghRepo])
      expect(result[0].repoLinkSource).toBe('deploy_workflow')
    })

    it('fuzzy_name_match_used_as_fallback', () => {
      const awsService = buildAWSService({ name: 'payment-service' })
      const ghRepo = buildGHRepo({ name: 'payment-svc' })
      const result = reconcile([awsService], [ghRepo])
      expect(result[0].repoLinkSource).toBe('name_match')
      expect(result[0].repoLinkConfidence).toBe(0.75)
    })

    it('no_match_produces_aws_only_service_entity', () => {
      const awsService = buildAWSService({ name: 'legacy-monolith' })
      const result = reconcile([awsService], [])
      expect(result[0].repoUrl).toBeNull()
      expect(result[0].discoverySources).toContain('cloudformation')
      expect(result[0].discoverySources).not.toContain('github_repo')
    })

    it('deduplicates_cfn_stack_and_ecs_service_with_same_name', () => {
      const cfnService = buildAWSService({ source: 'cloudformation', name: 'payment-api' })
      const ecsService = buildAWSService({ source: 'ecs_service', name: 'payment-api' })
      const result = reconcile([cfnService, ecsService], [])
      expect(result).toHaveLength(1)
      expect(result[0].discoverySources).toContain('cloudformation')
      expect(result[0].discoverySources).toContain('ecs_service')
    })
  })
})

3.4 Ownership Inference Engine (Python / pytest)

This is the highest-value unit test target. Ownership inference is the most complex logic and the most likely source of accuracy failures.

Key test cases:

class TestOwnershipScorer:
    def test_codeowners_weighted_highest_at_0_40(self):
        signals = [Signal(type='codeowners', team='payments', raw_score=1.0)]
        result = score_ownership(signals)
        assert result['payments'].weighted_score == pytest.approx(0.40)

    def test_multiple_signals_summed_correctly(self):
        signals = [
            Signal(type='codeowners', team='payments', raw_score=1.0),      # 0.40
            Signal(type='cfn_tag', team='payments', raw_score=1.0),          # 0.20
            Signal(type='git_blame_frequency', team='payments', raw_score=1.0), # 0.25
        ]
        result = score_ownership(signals)
        assert result['payments'].total_score == pytest.approx(0.85)

    def test_primary_owner_is_highest_scoring_team(self):
        signals = [
            Signal(type='codeowners', team='payments', raw_score=1.0),
            Signal(type='git_blame_frequency', team='platform', raw_score=1.0),
        ]
        result = score_ownership(signals)
        assert result.primary_owner == 'payments'

    def test_service_marked_unowned_when_top_score_below_0_50(self):
        signals = [Signal(type='git_blame_frequency', team='unknown', raw_score=0.3)]
        result = score_ownership(signals)
        assert result.status == 'unowned'

    def test_service_marked_ambiguous_when_top_two_within_0_10(self):
        signals = [
            Signal(type='codeowners', team='payments', raw_score=0.8),
            Signal(type='codeowners', team='platform', raw_score=0.75),
        ]
        result = score_ownership(signals)
        assert result.status == 'ambiguous'

    def test_user_correction_overrides_all_inference_with_score_1_00(self):
        signals = [
            Signal(type='codeowners', team='payments', raw_score=1.0),
            Signal(type='user_correction', team='platform', raw_score=1.0),
        ]
        result = score_ownership(signals)
        assert result.primary_owner == 'platform'
        assert result.primary_confidence == 1.00
        assert result.primary_source == 'user_correction'

    def test_correction_propagation_applies_to_matching_repo_prefix(self):
        correction = Correction(repo='payment-gateway', team='payments')
        candidates = ['payment-processor', 'payment-webhook', 'auth-service']
        propagated = propagate_correction(correction, candidates)
        assert 'payment-processor' in propagated
        assert 'payment-webhook' in propagated
        assert 'auth-service' not in propagated

3.5 Portal API — Route Handlers (Node.js / Jest + Supertest)

What to test:

  • Tenant isolation enforcement (tenant_id injected into every query)
  • Search endpoint proxies to Meilisearch with mandatory tenant filter
  • PATCH /services enforces correction logging
  • Auth middleware rejects unauthenticated requests
describe('GET /api/v1/services/search', () => {
  it('injects_tenant_id_filter_into_meilisearch_query', async () => {
    const spy = jest.spyOn(meilisearchClient, 'search')
    await request(app).get('/api/v1/services/search?q=payment').set('Authorization', `Bearer ${tenantAToken}`)
    expect(spy).toHaveBeenCalledWith(expect.objectContaining({
      filter: expect.stringContaining(`tenant_id = '${TENANT_A_ID}'`)
    }))
  })

  it('returns_401_when_no_auth_token_provided', async () => {
    const res = await request(app).get('/api/v1/services/search?q=payment')
    expect(res.status).toBe(401)
  })

  it('tenant_a_cannot_see_tenant_b_services', async () => {
    // Seed Meilisearch with services for both tenants
    // Query as tenant A, assert no tenant B results
  })
})

describe('PATCH /api/v1/services/:id', () => {
  it('stores_correction_in_corrections_table', async () => {
    await request(app)
      .patch(`/api/v1/services/${SERVICE_ID}`)
      .send({ team_id: NEW_TEAM_ID })
      .set('Authorization', `Bearer ${adminToken}`)
    const correction = await db.corrections.findFirst({ where: { service_id: SERVICE_ID } })
    expect(correction).toBeDefined()
    expect(correction.new_value).toMatchObject({ team_id: NEW_TEAM_ID })
  })

  it('sets_confidence_to_1_00_on_user_correction', async () => {
    await request(app).patch(`/api/v1/services/${SERVICE_ID}`).send({ team_id: NEW_TEAM_ID })
    const ownership = await db.service_ownership.findFirst({ where: { service_id: SERVICE_ID } })
    expect(ownership.confidence).toBe(1.00)
    expect(ownership.source).toBe('user_correction')
  })
})

3.6 Slack Bot Command Handlers (Node.js / Jest)

What to test:

  • Command parsing (/dd0c who owns <service>)
  • Typo tolerance matching logic (delegated to search, but bot needs to handle 0 results)
  • Block kit message formatting
  • Error handling (unauthorized workspace, missing service)

3.7 Feature Flags & Governance Policy (Node.js / Jest)

What to test:

  • Flag evaluation (openfeature provider)
  • Governance strict vs. audit mode
  • Panic mode blocking writes

4. Integration Test Strategy

Integration tests verify that our code correctly interacts with external boundaries: databases, caches, search indices, and third-party APIs.

4.1 Service Boundary Tests

  • Discovery ↔ GitHub/GitLab: Use nock or MSW to mock the GitHub GraphQL endpoint. Assert that the Node.js scanner constructs the correct query and handles rate limits (HTTP 403/429) via retries.
  • Catalog ↔ PostgreSQL: Use Testcontainers for PostgreSQL to verify complex upsert queries, foreign key constraints, and RLS (Row-Level Security) tenant isolation.
  • API ↔ Meilisearch: Use a Meilisearch Docker container. Assert that document syncing (PostgreSQL -> SQS -> Meilisearch) completes and search queries with tenant_id filters return the expected subset of data.

4.2 Git Provider API Contract Tests

  • Write scheduled "contract tests" that run against the live GitHub API daily using a dedicated test org.
  • These detect if GitHub changes their GraphQL schema or rate limit behavior.
  • Assert that HEAD:CODEOWNERS blob extraction still works.

4.3 Testcontainers for Local Infrastructure

  • Database: testcontainers-node spinning up postgres:15-alpine.
  • Search: getmeili/meilisearch:latest.
  • Cache: redis:7-alpine.
  • Run these in GitHub Actions via Docker-in-Docker.

5. E2E & Smoke Tests

E2E tests treat the system as a black box, interacting only through the API and the React UI. We keep these fast and focused on the "5-Minute Miracle" critical path.

5.1 Critical User Journeys (Playwright)

  1. The Onboarding Flow: Mock GitHub OAuth login -> Connect AWS (mock CFN role ARN validation) -> Trigger Discovery -> Wait for WebSocket completion -> Verify 147 services appear in catalog.
  2. Cmd+K Search: Open modal (Cmd+K) -> type "pay" -> assert "payment-gateway" is highlighted in < 200ms -> press Enter -> assert service detail card opens.
  3. Correcting Ownership: Open service detail -> Click "Correct Owner" -> select new team -> assert badge changes to 100% confidence -> assert Meilisearch is updated.

5.2 The >80% Auto-Discovery Accuracy Validation

  • The "Party Mode" Org: Maintain a real GitHub org and a mock AWS environment with exactly 100 known services, 10 known teams, and specific chaotic naming conventions.
  • The Assertion: Run discovery. Assert that > 80 of the services are correctly inferred with the right primary owner and repo link.
  • This is the most important test in the suite. If a PR drops this below 80%, it cannot be merged.

5.3 Synthetic Topology Generation

  • Script to generate N mock CFN stacks, M ECS services, and K GitHub repos to feed the E2E environment without hitting AWS/GitHub limits.

6. Performance & Load Testing

Load tests ensure the serverless architecture scales correctly and the Cmd+K search remains instantaneous.

6.1 Discovery Scan Benchmarks

  • Target: 500 AWS resources + 500 GitHub repos scanned and reconciled in < 120 seconds.
  • Tooling: K6 or Artillery. Push 5,000 synthetic SQS messages into the Reconciler queue and measure Lambda batch processing throughput.

6.2 Catalog Query Latency

  • Target: API search endpoint returns in < 100ms at the 99th percentile.
  • Test: Load Meilisearch with 10,000 service documents. Fire 50 concurrent Cmd+K search requests per second. Assert p99 latency.

6.3 Concurrent Scorecard Evaluation

  • Ensure the Python inference Lambda can evaluate 1,000 services concurrently without database connection exhaustion (using Aurora Serverless v2 connection pooling).

7. CI/CD Pipeline Integration

The test pyramid is enforced through GitHub Actions.

7.1 Test Stages

  • Pre-commit: Husky runs ESLint, Prettier, and fast unit tests (Jest/pytest) for changed files only.
  • PR Gate: Runs the full Unit and Integration test suites. Blocks merge if coverage drops or tests fail.
  • Merge (Main): Deploys to Staging. Runs E2E Critical User Journeys and the 80% Accuracy Validation suite against the Party Mode org.
  • Post-Deploy: Smoke tests verify health endpoints and ALB routing in production.

7.2 Coverage Thresholds

  • Global Unit Test Coverage: 80%
  • Ownership Inference & Reconciliation Logic: 95%
  • Feature Flag & Governance Evaluators: 100%

7.3 Test Parallelization

  • Jest tests run with --maxWorkers=50% locally, 100% in CI.
  • Integration tests using Testcontainers run serially per file to avoid database port conflicts, or use dynamic port binding and separate schemas for parallel execution.

8. Transparent Factory Tenet Testing

Testing the governance and compliance features of the IDP itself.

8.1 Feature Flag Circuit Breakers

  • Test: Enable a flagged discovery heuristic that generates 10 phantom services.
  • Assert: The system detects the threshold (>5 unconfirmed), auto-disables the flag, and marks the 10 services as status: quarantined.

8.2 Schema Migration Validation

  • Test: Attempt to apply a PR that drops a column from the services table.
  • Assert: CI migration validator script fails the build (additive-only rule).

8.3 Decision Log Enforcement

  • Test: Run a discovery scan where service ownership is inferred from git blame.
  • Assert: A decision_log entry is written to PostgreSQL with the prompt/reasoning, alternatives, and confidence.

8.4 OTEL Span Assertions

  • Test: Run the Reconciler Lambda.
  • Assert: The catalog_scan parent span contains child spans for ownership_inference with attributes for catalog.service_id, catalog.ownership_signals, and catalog.confidence_score. Use an in-memory OTEL exporter for testing.

8.5 Governance Policy Enforcement

  • Test: Set tenant policy to strict mode. Simulate auto-discovery finding a new service.
  • Assert: Service is placed in the "pending review" queue and NOT visible in the main catalog.
  • Test: Set panic_mode: true. Attempt a PATCH /api/v1/services/123.
  • Assert: HTTP 503 Service Unavailable.

9. Test Data & Fixtures

High-quality fixtures are the lifeblood of this TDD strategy.

9.1 GitHub/GitLab API Response Factories

  • JSON files containing real obfuscated GraphQL responses for Repositories, CODEOWNERS blobs, and Team memberships.
  • Use factories (e.g., fishery or custom functions) to easily override fields: buildGHRepo({ name: 'auth-service', languages: ['Go'] }).

9.2 Synthetic Topology Generators

  • Scripts that generate interconnected AWS resources (e.g., a CFN stack containing an API Gateway routing to 3 Lambdas interacting with 1 RDS instance).

9.3 CODEOWNERS and Git Blame Mocks

  • Diverse CODEOWNERS files covering edge cases: wildcard matching, deep path matching, invalid syntax, user-vs-team owners.

10. TDD Implementation Order

To bootstrap the platform efficiently, testing and development should follow this sequence based on Epic dependencies:

  1. Epic 2 (GitHub Parsers): Write pure unit tests for CODEOWNERS parser and README extractor. Value: High ROI, zero dependencies.
  2. Epic 1 (AWS Heuristics): Write unit tests for mapping CFN stacks and Tags to Service entities. Value: Core product logic.
  3. Epic 2 (Ownership Inference): TDD the scoring algorithm. Build the weighting math. Value: The brain of the platform.
  4. Epic 3 (Service Catalog Schema): Integration tests for PostgreSQL RLS and upserting services. Value: Data durability.
  5. Epic 2 (Reconciliation): Unit tests merging AWS and GitHub mock entities. Value: Pipeline glue.
  6. Epic 4 (Search Sync): Integration tests for pushing DB updates to Meilisearch.
  7. Epic 5 (API & UI): E2E test for the Cmd+K search flow.
  8. Epic 10 (Governance & Flags): Unit tests for feature flag circuit breakers and strict mode.
  9. Epic 9 (Onboarding): Playwright E2E for the 5-Minute Miracle flow.

This sequence ensures the most complex algorithmic logic is proven before it is wired to databases and APIs.