7spade/black-tortoise

No description

0 stars0 forksUpdated Jan 26, 2026
npx skills add 7spade/black-tortoise

README

Architecture Gate CI - Implementation Guide

Comment ID 3796470142 Implementation

This document describes the implementation of the Architecture Gate CI system for enforcing event-sourcing and DDD architectural invariants.

Files Created/Modified

1. Script: comprehensive-audit.js

The main architecture enforcement script that validates:

  • Presentation layer isolation: No EventBus/EventStore/DomainEvent imports from domain
  • Event publishing control: Only PublishEventUseCase and event handlers can call publish/append
  • Store layer placement: All stores MUST be in application layer
  • Sequential append-before-publish: No Promise.all with event operations
  • Event causality propagation: Handlers MUST propagate correlationId and set causationId
  • Signal-first architecture: Minimal RxJS in presentation layer

2. Package Script: package.json

Already configured with script command:

"architecture:gate": "node comprehensive-audit.js"

3. Documentation: .architectural-rules.md

Updated with:

  • CI gate implementation details
  • Detailed rule descriptions
  • GitHub Actions workflow specification
  • Local testing instructions
  • Exit code documentation
  • Workflow security features

4. GitHub Actions Workflow: .github/workflows/architecture-gate.yml

IMPORTANT: Create this file manually with the following content:

name: Architecture Gate

on:
  push:
    branches: ['**']
    paths:
      - 'src/**/*.ts'
      - 'comprehensive-audit.js'
      - '.github/workflows/architecture-gate.yml'
  pull_request:
    branches: ['**']
    paths:
      - 'src/**/*.ts'
      - 'comprehensive-audit.js'
      - '.github/workflows/architecture-gate.yml'

# Least-privilege permissions (security best practice)
permissions:
  contents: read

# Prevent concurrent runs, cancel outdated PR builds
concurrency:
  group: architecture-gate-${{ github.ref }}
  cancel-in-progress: true

jobs:
  enforce-architecture:
    name: Enforce Event-Sourcing Invariants
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 1
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Run Architecture Gate
        run: node comprehensive-audit.js
        env:
          NODE_ENV: production

Manual Steps Required

  1. Create the workflow directory (if it doesn't exist):

    mkdir -p .github/workflows
    
  2. Create the workflow file: Copy the workflow YAML above into .github/workflows/architecture-gate.yml

  3. Test locally:

    npm run architecture:gate
    
  4. Commit and push:

    git add .
    git commit -m "feat: add architecture gate CI per comment_id 3796470142"
    git push
    

Architecture Rules Enforced

Rule 1: Presentation Layer Isolation

Forbidden in src/app/presentation/**:

  • from '@domain/event-bus'
  • from '@domain/event-store'
  • from '@domain/event'

Must use:

  • ✅ Application facades
  • ✅ Application stores

Rule 2: Event Publishing Control

Only these can call eventBus.publish() or eventStore.append():

  • publish-event.use-case.ts
  • ✅ Event handlers (in application/*/handlers/*event-handler*.ts)

All other files:

  • ❌ Cannot call eventBus.publish()
  • ❌ Cannot call eventStore.append()

Rule 3: Store Layer Placement

Stores (*.store.ts) MUST:

  • ✅ Be in src/app/application/**
  • ❌ NOT be in presentation or domain layers

Rule 4: Sequential Append-Before-Publish

Forbidden:

  • Promise.all([eventStore.append(...), ...])
  • Promise.all([eventBus.publish(...), ...])

Required:

  • ✅ Sequential: await eventStore.append() then await eventBus.publish()

Rule 5: Event Causality Propagation

Event handlers creating events MUST:

  • ✅ Propagate correlationId from parent event
  • ✅ Set causationId to parent eventId

Rule 6: Signal-First Architecture

Presentation layer should:

  • ✅ Use Angular Signals
  • ⚠️ Minimize RxJS usage (warning, not error)

Allowlist (Exceptions)

Only these files are exempt from Rule 2:

  1. publish-event.use-case.ts

    • Can call eventBus.publish()
    • Can call eventStore.append()
  2. Event Handlers (application/*/handlers/*event-handler*.ts)

    • Can call use cases that trigger events

Testing the Gate

Test Case 1: Forbidden Import in Presentation

// ❌ This will FAIL the gate
// src/app/presentation/some-component.ts
import { EventBus } from '@domain/event-bus';

Test Case 2: Direct Event Publishing

// ❌ This will FAIL the gate (unless in PublishEventUseCase)
// src/app/application/some-use-case.ts
await eventBus.publish(event);

Test Case 3: Store in Wrong Layer

// ❌ This will FAIL the gate
// src/app/presentation/stores/some.store.ts  <-

...
Read full README

Publisher

7spade7spade

Statistics

Stars0
Forks0
Open Issues1
CreatedJan 21, 2026