// tools/challenge-spec/resilience-challenge-scenarios-b.ts — SPEC-034
// Rate limit bypass + concurrency model-specific + distributed saga scenarios
/**
 * Generate rate limit bypass challenge scenarios.
 */
export function generateRateLimitBypassScenarios(spec) {
    return [
        {
            scenario: `[${spec.id}] Rate Limit Bypass — Distributed Attack: ` +
                'The rate limit is configured per-IP. An attacker uses 1000 different IPs (botnet or distributed scraper) ' +
                'to bypass the per-IP limit. What is the effective global rate of requests the system receives? ' +
                'Does the system have any IP-independent rate limiting (per-account, global circuit breaker) to handle this?',
            probability: 'medium',
            impact: 'high',
            currentHandling: 'Per-IP rate limiting is ineffective against distributed attacks — an attacker with 1000 IPs gets 1000x the per-IP limit.',
            requiredHandling: 'Layer rate limits: per-IP (coarse), per-account/API-key (fine-grained), and global per-endpoint. ' +
                'For authentication endpoints: per-account lockout after N failed attempts (regardless of source IP). ' +
                'Use Redis-backed distributed rate limiting for consistency across multiple instances.',
            dataConsistency: 'In-memory rate limiting (local to one instance) allows the effective limit to be multiplied by the number of instances.',
            userExperience: 'Rate limit responses must include Retry-After header so legitimate clients can back off gracefully.',
        },
    ];
}
/**
 * Generate concurrency model-specific challenge scenarios.
 */
export function generateConcurrencyScenarios(spec, concurrencyModel) {
    const modelScenarios = {
        goroutines: {
            scenario: `[${spec.id}] Concurrency — Go Race Condition: ` +
                'If this feature reads and writes shared state (counter, map, cache) from multiple goroutines simultaneously, ' +
                'is the access protected by sync.Mutex, sync.RWMutex, or sync/atomic? ' +
                'Run with `go test -race` to verify. ' +
                'A map accessed concurrently without a lock is undefined behavior in Go (runtime panic possible).',
            probability: 'high',
            impact: 'critical',
            currentHandling: 'Without mutex protection, concurrent map writes in Go cause a runtime panic or silent data corruption.',
            requiredHandling: 'Use sync.RWMutex for read-heavy maps (multiple concurrent reads, exclusive writes). ' +
                'Use sync/atomic for simple counters. ' +
                'Always run `go test -race ./...` in CI to detect race conditions before production.',
            dataConsistency: 'Race conditions on shared state lead to inconsistent reads and corrupted writes that are hard to reproduce.',
            userExperience: 'A runtime panic from a race condition kills the entire goroutine group, causing an unexpected 500.',
        },
        'async-await': {
            scenario: `[${spec.id}] Concurrency — Event Loop Blocking: ` +
                'Does this feature perform any synchronous CPU-intensive or I/O-blocking operation inside an async function? ' +
                'Examples: JSON.parse on large payloads (> 1MB), crypto operations (bcrypt without async), ' +
                'RegExp with catastrophic backtracking. ' +
                'These block the single-threaded event loop and degrade ALL concurrent requests, not just this one.',
            probability: 'medium',
            impact: 'high',
            currentHandling: 'Synchronous operations inside async handlers block the Node.js event loop, causing latency spikes for all concurrent requests.',
            requiredHandling: 'Move CPU-intensive operations to worker threads (worker_threads module). ' +
                'Use async crypto APIs (bcrypt.hash not bcrypt.hashSync). ' +
                'Test with clinic.js or --inspect + async_hooks to identify event loop blocking before production.',
            dataConsistency: 'No data consistency impact — performance issue only.',
            userExperience: 'Event loop blocking causes P99 latency spikes that affect all users, not just those using the slow feature.',
        },
        'threads-locks': {
            scenario: `[${spec.id}] Concurrency — Deadlock Risk: ` +
                'If this feature acquires multiple locks (e.g., lock on resource A, then lock on resource B), ' +
                'is there another code path that acquires the same locks in the opposite order (B first, then A)? ' +
                'This is the classic deadlock condition. ' +
                'Test by running the two paths simultaneously with a short sleep between lock acquisitions.',
            probability: 'medium',
            impact: 'critical',
            currentHandling: 'Inconsistent lock ordering causes deadlocks that hang threads indefinitely, eventually exhausting the thread pool.',
            requiredHandling: 'Establish a canonical lock ordering (always A before B, never B before A). Document this ordering. ' +
                'Use tryLock(timeout) in tests to detect deadlocks: if the lock is not acquired in N seconds, the test fails. ' +
                'Consider using ReentrantLock over synchronized blocks for more control.',
            dataConsistency: 'Deadlocked threads hold locks, preventing other threads from accessing the protected resources.',
            userExperience: 'A deadlock causes the request to hang until the timeout is reached, resulting in a 503 or 504 for the user.',
        },
        'rust-ownership': {
            scenario: `[${spec.id}] Concurrency — Rust Logical Deadlock: ` +
                'Rust prevents data races at compile time via the borrow checker. ' +
                'However, logical deadlocks (two async tasks waiting for each other via Mutex or channel) are still possible at runtime. ' +
                'If this feature acquires Arc<Mutex<T>> guards in multiple futures, is the acquisition order consistent? ' +
                'The Rust compiler will not catch this — it must be tested with deadlock timeout tests.',
            probability: 'low',
            impact: 'high',
            currentHandling: 'Rust eliminates data races at compile time, but logical deadlocks between async tasks holding Mutex guards are runtime errors.',
            requiredHandling: 'Use tokio::time::timeout to wrap Mutex acquisitions in async code. ' +
                'If the lock is not acquired within the timeout, return an error instead of hanging. ' +
                'Document the lock acquisition order and enforce it via code review.',
            dataConsistency: 'Deadlocked async tasks hold Mutex guards, blocking other tasks from accessing the protected data.',
            userExperience: 'Logical deadlocks in Rust async code cause requests to timeout rather than return an error — prefer explicit timeout.',
        },
        'actor-model': {
            scenario: `[${spec.id}] Concurrency — Mailbox Overflow: ` +
                'If the producer sends messages to this actor faster than the actor processes them, ' +
                'the mailbox grows unboundedly. ' +
                'What is the configured mailbox size limit? What happens when the limit is reached: ' +
                'back-pressure (producer blocks), message drop (with which strategy), or unbounded growth (memory risk)?',
            probability: 'medium',
            impact: 'high',
            currentHandling: 'Unbounded mailboxes cause memory exhaustion under load. Message drops without metrics cause silent data loss.',
            requiredHandling: 'Configure a bounded mailbox with a drop strategy (drop-oldest or drop-newest). ' +
                'Emit a metric when mailbox exceeds 80% capacity. ' +
                'Consider back-pressure: if the producer is too fast, slow it down at the source instead of dropping at the destination.',
            dataConsistency: 'Dropped messages cause data loss that is not recoverable without event sourcing or DLQ.',
            userExperience: 'Mailbox overflow is invisible to users until they notice missing data or failed operations.',
        },
        'reactive-streams': {
            scenario: `[${spec.id}] Concurrency — Backpressure Strategy: ` +
                'This spec uses a reactive stream. If the publisher emits faster than the subscriber processes, ' +
                'what backpressure strategy is in use? ' +
                'BUFFER (memory risk), DROP (data loss), ERROR (stream terminates), LATEST (only last value), or MISSING (unbounded)? ' +
                'The strategy must match the business requirements: can messages be dropped or is each one required?',
            probability: 'medium',
            impact: 'high',
            currentHandling: 'Without explicit backpressure strategy, fast publishers overflow the subscriber buffer, causing OutOfMemoryError or silent drops.',
            requiredHandling: 'Choose the backpressure strategy explicitly based on business requirements. ' +
                'For critical events: use ERROR or bounded BUFFER to prevent loss. ' +
                'For metrics/logging: DROP or LATEST is acceptable. ' +
                'Test with a producer that emits 10x faster than the subscriber to verify the strategy holds.',
            dataConsistency: 'Backpressure strategy determines whether data loss is acceptable or whether the stream must be slowed down.',
            userExperience: 'Backpressure overflow can cause request failures for the publisher, which surfaces as 503 or timeout.',
        },
    };
    const scenario = modelScenarios[concurrencyModel];
    return scenario ? [scenario] : [];
}
/**
 * Generate distributed saga failure scenarios.
 */
export function generateSagaFailureScenarios(spec) {
    return [
        {
            scenario: `[${spec.id}] Distributed Saga — Partial Failure at Step N: ` +
                'If step 3 of 5 in the saga fails after steps 1 and 2 already executed in external services, ' +
                'how long do the compensation events (rollback for steps 1 and 2) take to complete? ' +
                'How is it verified that the system is in a consistent state after compensation, ' +
                'rather than in a partially-reverted state (step 1 rolled back but step 2 not yet)?',
            probability: 'medium',
            impact: 'critical',
            currentHandling: 'Partial saga failures without compensation leave the system in an inconsistent state ' +
                '(some external services have committed while others have not).',
            requiredHandling: 'Each saga step must have a defined compensation operation. ' +
                'Compensation must be idempotent (can be retried safely). ' +
                'Track saga state in a durable store: if the orchestrator crashes mid-saga, it must resume from the last known state. ' +
                'Add a saga status endpoint: GET /sagas/{id} returns the current step, status, and any failed compensations.',
            dataConsistency: 'Partial compensation leaves distributed state inconsistent. The saga log must be the source of truth for rollback status.',
            userExperience: 'Users must receive a clear error explaining that the operation was rolled back and what state the system is in. ' +
                'If rollback also failed, the user must be told that manual resolution is required.',
        },
    ];
}
//# sourceMappingURL=resilience-challenge-scenarios-b.js.map