# Aphoria Configuration for cachewrap Dogfood Project
# Purpose: Validate multi-domain flywheel (httpclient + dbpool + msgqueue → cache)

[project]
name = "cachewrap-dogfood"
version = "0.1.0"

[scan]
# Include all Rust source files
include = ["src/**/*.rs"]

# Exclude test files and build artifacts from scanning
exclude = ["tests/**/*.rs", "target/**"]

[episteme]
# CRITICAL: Use persistent mode (not ephemeral) for pattern learning
# This enables the flywheel - pattern aggregation across scans
mode = "persistent"

# Corpus database location (matches API's STEMEDB_CORPUS_DB_DIR)
corpus_db = "/home/jml/.aphoria/corpus-db"

[corpus]
# Enable pattern aggregation (flywheel mechanism)
aggregation_enabled = true

# Include corpus sources for pattern reuse
sources = [
    "httpclient",  # Async patterns: timeout, TLS, retry
    "dbpool",      # Connection patterns: max_connections, lifecycle
    "msgqueue",    # Messaging patterns: backpressure, metrics
]

# Include all corpus types
include_rfc = true      # RFC normative statements
include_owasp = true    # OWASP cheat sheets (security claims)
include_vendor = true   # Vendor docs (Redis, AWS ElastiCache)
use_community = true    # Community-learned patterns

# Cache directory for downloaded sources
cache_dir = "/home/jml/.aphoria/cache"

# ============================================================================
# EXTRACTORS CONFIGURATION
# ============================================================================
# By default, all 42 built-in extractors run (security patterns: TLS, secrets,
# injection, timeouts, etc.). Custom extractors will be created on Day 3 via
# /aphoria-custom-extractor-creator skill.
#
# Built-in extractors that may detect violations:
# - hardcoded_secrets: Detects violation 3 (plaintext password)
# - tls_config: Detects violation 2 (verify_tls = false)
# - timeout_config: May detect violation 8 (timeout = 0)
#
# Custom extractors needed (created on Day 3):
# - key_validation: Violation 1 (no validate_key call)
# - ttl_presence: Violation 4 (SET without EX/PX)
# - max_size_check: Violation 5 (max_size = None)
# - async_check: Violation 6 (blocking calls in async)
# - eviction_policy_check: Violation 7 (eviction_policy = None)
# - connection_pool_check: Violation 9 (no pooling)
# - metrics_check: Violation 10 (metrics_enabled = false)
# ============================================================================

[extractors]

[extractors.inline_markers]
# Enable @aphoria:claim comments
enabled = true
sync_to_pending = true

# ============================================================================
# CUSTOM DECLARATIVE EXTRACTORS (Day 3)
# ============================================================================

# Extractor 1: Detect missing key validation
[[extractors.declarative]]
name = "cache_key_validation_missing"
description = "Detects get() method accepting raw &str keys without validation (enables injection attacks)"
languages = ["rust"]
pattern = 'pub\s+async\s+fn\s+get\s*\(&self,\s*key:\s*&str\)'
claim.subject = "cache/key_validation"
claim.predicate = "required"
claim.value = false
confidence = 0.9

# Extractor 2: Detect TLS verification disabled
[[extractors.declarative]]
name = "tls_verification_disabled"
description = "Detects verify_tls: false in cache config (enables MITM attacks)"
languages = ["rust"]
pattern = 'verify_tls:\s*false'
claim.subject = "cache/tls/certificate_validation"
claim.predicate = "required"
claim.value = false
confidence = 0.95

# Extractor 3: Detect hardcoded passwords
[[extractors.declarative]]
name = "hardcoded_password"
description = "Detects hardcoded password strings in cache config"
languages = ["rust"]
pattern = 'password:\s*"[^"]+"\.to_string\(\)'
claim.subject = "cache/credentials/password"
claim.predicate = "hardcoded"
claim.value = true
confidence = 0.9

# Extractor 4: Detect missing TTL
[[extractors.declarative]]
name = "ttl_missing"
description = "Detects SET commands without TTL (causes memory leak)"
languages = ["rust"]
pattern = 'conn\.set::<[^>]+>\([^)]+\)\.await\?;'
claim.subject = "cache/ttl"
claim.predicate = "required"
claim.value = false
confidence = 0.85

# Extractor 5: Detect unbounded max_size
[[extractors.declarative]]
name = "max_size_unbounded"
description = "Detects max_size: None (unbounded cache allows OOM)"
languages = ["rust"]
pattern = 'max_size:\s*None'
claim.subject = "cache/max_size"
claim.predicate = "bounded"
claim.value = false
confidence = 0.95

# Extractor 6: Detect blocking in async
[[extractors.declarative]]
name = "async_blocking"
description = "Detects blocking get_connection() in async functions"
languages = ["rust"]
pattern = 'self\.client\.get_connection\(\)'
claim.subject = "cache/async/blocking_forbidden"
claim.predicate = "required"
claim.value = false
confidence = 0.9

# Extractor 7: Detect missing eviction policy
[[extractors.declarative]]
name = "eviction_policy_missing"
description = "Detects eviction_policy: None (undefined behavior when cache full)"
languages = ["rust"]
pattern = 'eviction_policy:\s*None'
claim.subject = "cache/eviction_policy"
claim.predicate = "required"
claim.value = false
confidence = 0.95

# Extractor 8: Detect zero timeout
[[extractors.declarative]]
name = "timeout_zero"
description = "Detects Duration::from_secs(0) timeout (indefinite blocking)"
languages = ["rust"]
pattern = 'timeout:\s*Duration::from_secs\(0\)'
claim.subject = "cache/timeout"
claim.predicate = "max_value"
claim.value_from_match = false
claim.value = 0.0
confidence = 1.0

# Extractor 9: Detect missing connection pooling
[[extractors.declarative]]
name = "connection_pool_missing"
description = "Detects get_multiplexed_async_connection() per request (resource exhaustion)"
languages = ["rust"]
pattern = 'let\s+mut\s+conn\s*=\s*self\.client\.get_multiplexed_async_connection\(\)\.await'
claim.subject = "cache/connection/max_connections"
claim.predicate = "bounded"
claim.value = false
confidence = 0.85

# Extractor 10: Detect metrics disabled
[[extractors.declarative]]
name = "metrics_disabled"
description = "Detects metrics_enabled: false (prevents production debugging)"
languages = ["rust"]
pattern = 'metrics_enabled:\s*false'
claim.subject = "cache/metrics/enabled"
claim.predicate = "required"
claim.value = false
confidence = 0.95

# Thresholds for conflict severity verdicts
[thresholds]
block_threshold = 0.7    # Conflict score >= 0.7 → BLOCK (critical violations)
flag_threshold = 0.5     # Conflict score >= 0.5 → FLAG (warnings)
