Back to Skills

cross-context

majiayu000
Updated Today
1 views
58
9
58
View on GitHub
Othergeneral

About

This skill handles cross-Bounded Context dependencies in domain-driven design, triggered when features involve multiple contexts like permissions or payments. It helps design Anti-Corruption Layers and Context Mapping strategies to manage integration patterns while protecting domain models from external corruption. Developers use it to define clear boundaries and contracts between collaborating contexts.

Quick Install

Claude Code

Recommended
Plugin CommandRecommended
/plugin add https://github.com/majiayu000/claude-skill-registry
Git CloneAlternative
git clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/cross-context

Copy and paste this command in Claude Code to install this skill

Documentation

Cross-Context Skill

觸發時機

  • analyze-frame 識別出 cross_context_dependencies
  • 需求涉及多個 Bounded Context 的協作
  • 設計 Anti-Corruption Layer (ACL) 時
  • 定義 Context Mapping 策略時

核心任務

  1. 識別跨 BC 依賴的類型與方向
  2. 設計適當的整合模式 (ACL, Open Host, Shared Kernel, etc.)
  3. 定義跨 BC 的契約規格
  4. 確保當前 BC 不被外部 BC 污染

Context Mapping 模式

上游/下游關係

模式說明適用場景
Customer-Supplier下游需求驅動上游開發緊密合作的團隊
Conformist下游完全遵循上游模型無法影響上游時
Anti-Corruption Layer下游建立隔離層保護自身模型
Open Host Service上游提供標準化 API多下游消費者
Published Language共享交換格式跨組織整合

對等關係

模式說明適用場景
Shared Kernel共享部分模型高度協作
Partnership雙方共同演進緊密合作
Separate Ways完全獨立無需整合

cross-context/{context-name}.yaml 格式

# docs/specs/{feature-name}/cross-context/{context-name}.yaml
cross_context:
  id: XC1
  name: "Authorization"
  
  # ---------------------------------------------------------------------------
  # Context 關係
  # ---------------------------------------------------------------------------
  
  relationship:
    source_context: "AccessControl"     # 提供服務的 BC
    target_context: "WorkflowManagement" # 當前 BC
    direction: "upstream-downstream"     # | symmetric | separate
    pattern: "AntiCorruptionLayer"       # | Conformist | OpenHostService | SharedKernel
  
  # ---------------------------------------------------------------------------
  # 介面契約(需求層:只描述「需要什麼」)
  # ---------------------------------------------------------------------------
  
  required_capability:
    name: "AuthorizationCheck"
    description: |
      Check if the operator has permission to perform the action on the resource.
    
    # 這是「需求」,不是「實作」
    operations:
      - name: "canExecute"
        input:
          - name: "operatorId"
            type: "string"
            description: "The ID of the operator"
          - name: "action"
            type: "string"
            description: "The action to perform (e.g., 'create', 'update', 'delete')"
          - name: "resourceType"
            type: "string"
            description: "The type of resource (e.g., 'Workflow', 'Board')"
          - name: "resourceId"
            type: "string"
            description: "The ID of the resource"
        output:
          type: "boolean"
          description: "true if authorized, false otherwise"
        
        # Design by Contract
        pre_conditions:
          - "operatorId must not be empty"
          - "action must be a valid action type"
        post_conditions:
          - "returns true or false, never throws for authorization check"
        
        # 異常情況
        errors:
          - name: "OperatorNotFoundError"
            when: "operatorId does not exist"
  
  # ---------------------------------------------------------------------------
  # ACL 設計(實作層)
  # ---------------------------------------------------------------------------
  
  acl_design:
    adapter_interface:
      name: "AuthorizationService"
      location: "src/domain/services/"
      
    adapter_implementation:
      name: "AccessControlAuthorizationAdapter"
      location: "src/infrastructure/acl/"
      
    # 模型轉換
    translation:
      - source_model: "AccessControl.Permission"
        target_model: "WorkflowManagement.AuthorizationResult"
        mapping: |
          Permission.isGranted → AuthorizationResult.authorized
          Permission.denialReason → AuthorizationResult.reason
  
  # ---------------------------------------------------------------------------
  # 容錯策略
  # ---------------------------------------------------------------------------
  
  fault_tolerance:
    timeout: "3s"
    retry:
      max_attempts: 3
      backoff: "exponential"
    fallback:
      strategy: "deny-by-default"  # | allow-by-default | cached
      description: "If authorization service is unavailable, deny the request"
    circuit_breaker:
      enabled: true
      failure_threshold: 5
      reset_timeout: "30s"
  
  # ---------------------------------------------------------------------------
  # 可追溯性
  # ---------------------------------------------------------------------------
  
  satisfied_by:
    - machine/controller.yaml#authorization_check
    - "src/infrastructure/acl/AccessControlAuthorizationAdapter.ts"
  
  validates_concerns:
    - FC1  # 若有 Frame Concern 與權限相關

TypeScript 範例

Domain Service Interface (在 Domain 層)

// src/domain/services/AuthorizationService.ts

/**
 * Authorization Service Interface
 * 
 * 這是 Domain 層的介面,不依賴任何外部實作
 * Anti-Corruption Layer 的入口點
 */
export interface AuthorizationService {
  /**
   * Check if the operator can execute the action
   * 
   * @pre operatorId must not be empty
   * @pre action must be a valid action type
   * @post returns AuthorizationResult, never throws for check
   */
  canExecute(
    operatorId: string,
    action: ActionType,
    resourceType: ResourceType,
    resourceId: string
  ): Promise<AuthorizationResult>;
}

export interface AuthorizationResult {
  readonly authorized: boolean;
  readonly reason?: string;
}

export type ActionType = 'create' | 'read' | 'update' | 'delete';
export type ResourceType = 'Workflow' | 'Board' | 'Stage' | 'SwimLane';

ACL Adapter (在 Infrastructure 層)

// src/infrastructure/acl/AccessControlAuthorizationAdapter.ts

import { AuthorizationService, AuthorizationResult, ActionType, ResourceType } 
  from '../../domain/services/AuthorizationService';
import { AccessControlClient } from '../clients/AccessControlClient';
import { CircuitBreaker } from '../resilience/CircuitBreaker';

/**
 * Anti-Corruption Layer Adapter
 * 
 * 將 AccessControl BC 的模型轉換為當前 BC 的模型
 * 包含容錯策略:timeout, retry, circuit breaker
 */
export class AccessControlAuthorizationAdapter implements AuthorizationService {
  constructor(
    private readonly client: AccessControlClient,
    private readonly circuitBreaker: CircuitBreaker,
  ) {}

  async canExecute(
    operatorId: string,
    action: ActionType,
    resourceType: ResourceType,
    resourceId: string
  ): Promise<AuthorizationResult> {
    // ===== Pre-conditions =====
    if (!operatorId) {
      throw new Error('operatorId must not be empty');
    }

    try {
      // 透過 Circuit Breaker 呼叫外部服務
      const permission = await this.circuitBreaker.execute(
        () => this.client.checkPermission({
          userId: operatorId,
          action: this.mapAction(action),
          resource: `${resourceType}:${resourceId}`,
        }),
        {
          timeout: 3000,
          fallback: () => ({ isGranted: false, denialReason: 'Service unavailable' }),
        }
      );

      // ===== Model Translation (ACL 核心) =====
      return this.translateToAuthorizationResult(permission);

    } catch (error) {
      // Fallback: deny by default
      return {
        authorized: false,
        reason: 'Authorization service unavailable',
      };
    }
  }

  /**
   * 模型轉換:將外部 BC 的 Permission 轉換為當前 BC 的 AuthorizationResult
   */
  private translateToAuthorizationResult(
    permission: ExternalPermission
  ): AuthorizationResult {
    return {
      authorized: permission.isGranted,
      reason: permission.denialReason,
    };
  }

  private mapAction(action: ActionType): string {
    // 若外部 BC 使用不同的 action 命名,在此轉換
    const mapping: Record<ActionType, string> = {
      create: 'CREATE',
      read: 'READ',
      update: 'UPDATE',
      delete: 'DELETE',
    };
    return mapping[action];
  }
}

Go 範例

Domain Service Interface

// domain/services/authorization.go
package services

type ActionType string
type ResourceType string

const (
    ActionCreate ActionType = "create"
    ActionRead   ActionType = "read"
    ActionUpdate ActionType = "update"
    ActionDelete ActionType = "delete"
)

type AuthorizationResult struct {
    Authorized bool
    Reason     string
}

// AuthorizationService - Domain layer interface
// This is the Anti-Corruption Layer entry point
type AuthorizationService interface {
    // CanExecute checks if the operator can perform the action
    // @pre operatorId must not be empty
    // @post returns AuthorizationResult, never returns error for check
    CanExecute(
        ctx context.Context,
        operatorID string,
        action ActionType,
        resourceType ResourceType,
        resourceID string,
    ) (*AuthorizationResult, error)
}

ACL Adapter

// infrastructure/acl/access_control_adapter.go
package acl

import (
    "context"
    "time"
    
    "myapp/domain/services"
    "myapp/infrastructure/clients"
    "myapp/infrastructure/resilience"
)

type AccessControlAuthorizationAdapter struct {
    client         *clients.AccessControlClient
    circuitBreaker *resilience.CircuitBreaker
    timeout        time.Duration
}

func NewAccessControlAuthorizationAdapter(
    client *clients.AccessControlClient,
    cb *resilience.CircuitBreaker,
) *AccessControlAuthorizationAdapter {
    return &AccessControlAuthorizationAdapter{
        client:         client,
        circuitBreaker: cb,
        timeout:        3 * time.Second,
    }
}

func (a *AccessControlAuthorizationAdapter) CanExecute(
    ctx context.Context,
    operatorID string,
    action services.ActionType,
    resourceType services.ResourceType,
    resourceID string,
) (*services.AuthorizationResult, error) {
    // ===== Pre-conditions =====
    if operatorID == "" {
        return nil, errors.New("operatorId must not be empty")
    }

    // Context with timeout
    ctx, cancel := context.WithTimeout(ctx, a.timeout)
    defer cancel()

    // Execute through circuit breaker
    result, err := a.circuitBreaker.Execute(ctx, func() (interface{}, error) {
        return a.client.CheckPermission(ctx, &clients.PermissionRequest{
            UserID:   operatorID,
            Action:   a.mapAction(action),
            Resource: fmt.Sprintf("%s:%s", resourceType, resourceID),
        })
    })

    if err != nil {
        // Fallback: deny by default
        return &services.AuthorizationResult{
            Authorized: false,
            Reason:     "Authorization service unavailable",
        }, nil
    }

    // ===== Model Translation (ACL 核心) =====
    permission := result.(*clients.Permission)
    return a.translateToAuthorizationResult(permission), nil
}

func (a *AccessControlAuthorizationAdapter) translateToAuthorizationResult(
    permission *clients.Permission,
) *services.AuthorizationResult {
    return &services.AuthorizationResult{
        Authorized: permission.IsGranted,
        Reason:     permission.DenialReason,
    }
}

func (a *AccessControlAuthorizationAdapter) mapAction(action services.ActionType) string {
    mapping := map[services.ActionType]string{
        services.ActionCreate: "CREATE",
        services.ActionRead:   "READ",
        services.ActionUpdate: "UPDATE",
        services.ActionDelete: "DELETE",
    }
    return mapping[action]
}

Use Case 整合範例

// 在 Use Case 中使用 AuthorizationService

export class CreateWorkflowUseCase {
  constructor(
    private readonly authorizationService: AuthorizationService,
    private readonly workflowRepository: WorkflowRepository,
    private readonly eventPublisher: EventPublisher,
  ) {}

  async execute(input: CreateWorkflowInput): Promise<CreateWorkflowOutput> {
    // ===== Cross-Context: Authorization Check =====
    const authResult = await this.authorizationService.canExecute(
      input.operatorId,
      'create',
      'Workflow',
      input.boardId,
    );

    if (!authResult.authorized) {
      throw new UnauthorizedError(
        `Not authorized to create workflow: ${authResult.reason}`
      );
    }

    // ===== Domain Logic =====
    const workflow = Workflow.create({
      boardId: new BoardId(input.boardId),
      name: input.name,
      createdBy: new UserId(input.operatorId),
    });

    await this.workflowRepository.save(workflow);
    await this.eventPublisher.publish(new WorkflowCreatedEvent(workflow));

    return {
      workflowId: workflow.id.value,
      status: workflow.status,
      createdAt: workflow.createdAt,
    };
  }
}

常見的跨 BC 場景

場景Source BCPattern說明
權限檢查AccessControlACL檢查操作權限
用戶資訊UserManagementACL取得用戶詳情
付款處理PaymentACL + Saga處理付款流程
通知發送NotificationOpen Host發送通知
審計日誌AuditPublished Language記錄操作

品質檢查清單

  • 是否明確識別上下游關係?
  • ACL 是否在 Infrastructure 層,介面在 Domain 層?
  • 模型轉換是否完整,不洩漏外部 BC 概念?
  • 是否有適當的容錯策略(timeout, retry, circuit breaker)?
  • Fallback 策略是否符合業務需求?
  • 是否有明確的 pre/post-conditions?
  • 是否可追溯到 Frame Concerns?

與其他 Skills 的協作

analyze-frame
    │
    ├── 識別 cross_context_dependencies
    │
    └── cross-context (本 Skill)
        │
        ├── 設計 ACL 規格
        │
        ├── 連結到 arch-guard (確保層次正確)
        │
        └── 連結到 command-sub-agent / query-sub-agent
            └── 在 Use Case 中整合 ACL

GitHub Repository

majiayu000/claude-skill-registry
Path: skills/cross-context

Related Skills

algorithmic-art

Meta

This Claude Skill creates original algorithmic art using p5.js with seeded randomness and interactive parameters. It generates .md files for algorithmic philosophies, plus .html and .js files for interactive generative art implementations. Use it when developers need to create flow fields, particle systems, or other computational art while avoiding copyright issues.

View skill

subagent-driven-development

Development

This skill executes implementation plans by dispatching a fresh subagent for each independent task, with code review between tasks. It enables fast iteration while maintaining quality gates through this review process. Use it when working on mostly independent tasks within the same session to ensure continuous progress with built-in quality checks.

View skill

executing-plans

Design

Use the executing-plans skill when you have a complete implementation plan to execute in controlled batches with review checkpoints. It loads and critically reviews the plan, then executes tasks in small batches (default 3 tasks) while reporting progress between each batch for architect review. This ensures systematic implementation with built-in quality control checkpoints.

View skill

cost-optimization

Other

This Claude Skill helps developers optimize cloud costs through resource rightsizing, tagging strategies, and spending analysis. It provides a framework for reducing cloud expenses and implementing cost governance across AWS, Azure, and GCP. Use it when you need to analyze infrastructure costs, right-size resources, or meet budget constraints.

View skill