Files
attune/docs/sensors/SUMMARY-database-driven-detection.md

15 KiB

Database-Driven Sensor Runtime Detection - Feature Summary

Date: 2026-02-02
Status: COMPLETE AND TESTED
Enhancement: Sensor Worker Registration

⚠️ Note: This document was written before the runtime_type column was removed from the runtime table. SQL examples referencing WHERE runtime_type = 'sensor', INSERT ... runtime_type, and 3-part refs like core.sensor.python are outdated. The current architecture uses unified runtimes with 2-part refs (core.python, core.shell) and determines executability by the presence of execution_config. See docs/QUICKREF-unified-runtime-detection.md for the current model.


Overview

The sensor service now uses database-driven runtime detection instead of hardcoded checks. Runtime verification is configured in the runtime table, making the sensor service completely independent and self-configuring. Adding new sensor runtimes requires zero code changes—just database configuration.


What Changed

Before (Hardcoded)

// Hardcoded runtime checks in sensor_worker_registration.rs
fn auto_detect_runtimes() -> Vec<String> {
    let mut runtimes = vec!["shell".to_string()];
    
    // Hardcoded check for Python
    if Command::new("python3").arg("--version").output().is_ok() {
        runtimes.push("python".to_string());
    }
    
    // Hardcoded check for Node.js
    if Command::new("node").arg("--version").output().is_ok() {
        runtimes.push("node".to_string());
    }
    
    runtimes.push("native".to_string());
    runtimes
}

Problems:

  • Code changes required to add new runtimes
  • Verification logic scattered in code
  • No version validation
  • No fallback commands

After (Database-Driven)

// Query runtimes from database
let runtimes = sqlx::query_as::<_, Runtime>(
    "SELECT * FROM runtime WHERE runtime_type = 'sensor'"
).fetch_all(&pool).await?;

// Verify each runtime using its metadata
for runtime in runtimes {
    if verify_runtime_available(&runtime).await {
        available.push(runtime.name);
    }
}

Benefits:

  • No code changes to add runtimes
  • Centralized configuration
  • Version validation via regex patterns
  • Multiple fallback commands
  • Priority ordering

How It Works

1. Runtime Table Configuration

Each sensor runtime has verification metadata in runtime.distributions:

{
  "verification": {
    "commands": [
      {
        "binary": "python3",
        "args": ["--version"],
        "exit_code": 0,
        "pattern": "Python 3\\.",
        "priority": 1
      },
      {
        "binary": "python",
        "args": ["--version"],
        "exit_code": 0,
        "pattern": "Python 3\\.",
        "priority": 2
      }
    ]
  },
  "min_version": "3.8",
  "recommended_version": "3.11"
}

2. Verification Process

Sensor Service Startup
    ↓
Query: SELECT * FROM runtime WHERE runtime_type = 'sensor'
    ↓
For each runtime:
  - Check if "always_available" (shell, native)
  - Try verification commands in priority order
  - Execute binary with args
  - Check exit code matches expected
  - Validate output matches regex pattern
  - If success: add to available runtimes
    ↓
Register with detected runtimes

3. Example: Python Detection

1. Query runtime table
   → Found: core.sensor.python

2. Get verification commands
   → Command 1: python3 --version (priority 1)
   → Command 2: python --version (priority 2)

3. Try command 1
   $ python3 --version
   Output: "Python 3.11.6"
   Exit code: 0 ✓
   Pattern: "Python 3\." ✓
   
4. Result: Python AVAILABLE ✓

Configured Runtimes

Core Sensor Runtimes

Runtime Reference Verification Always Available
Python core.sensor.python python3 --version OR python --version No
Node.js core.sensor.nodejs node --version No
Shell core.sensor.shell N/A Yes
Native core.sensor.native N/A Yes
Built-in core.sensor.builtin N/A Yes

Adding New Runtimes

Example: Add Ruby runtime

INSERT INTO runtime (ref, pack, pack_ref, description, runtime_type, name, distributions)
VALUES (
    'core.sensor.ruby',
    (SELECT id FROM pack WHERE ref = 'core'),
    'core',
    'Ruby sensor runtime',
    'sensor',
    'Ruby',
    jsonb_build_object(
        'verification', jsonb_build_object(
            'commands', jsonb_build_array(
                jsonb_build_object(
                    'binary', 'ruby',
                    'args', jsonb_build_array('--version'),
                    'exit_code', 0,
                    'pattern', 'ruby \\d+\\.\\d+',
                    'priority', 1
                )
            )
        )
    )
);

That's it! Next sensor service restart will automatically detect Ruby.


Verification Results

Test System (with Python, Node.js, Ruby installed)

2026-02-02T17:21:32.735038Z  INFO Detecting available sensor runtimes from database...
2026-02-02T17:21:32.735038Z  INFO Found 7 sensor runtime(s) in database

2026-02-02T17:21:32.735083Z  INFO ✓ Runtime available: Built-in Sensor (core.sensor.builtin)
2026-02-02T17:21:32.735111Z  INFO ✓ Runtime available: Native (core.sensor.native)
2026-02-02T17:21:32.744845Z  INFO ✓ Runtime available: Node.js (core.sensor.nodejs)
2026-02-02T17:21:32.746642Z  INFO ✓ Runtime available: Python (core.sensor.python)
2026-02-02T17:21:32.746682Z  INFO ✓ Runtime available: Shell (core.sensor.shell)
2026-02-02T17:21:32.772068Z  INFO ✓ Runtime available: Ruby (test.sensor.ruby)
2026-02-02T17:21:32.772068Z  DEBUG ✗ Runtime not available: Haskell (test.sensor.haskell)

2026-02-02T17:21:32.772127Z  INFO Detected available runtimes: 
    ["built-in sensor", "native", "node.js", "python", "shell", "ruby"]

Database verification:

SELECT name, capabilities->>'runtimes' 
FROM worker 
WHERE worker_role = 'sensor';

         name          |                          runtimes
-----------------------+-------------------------------------------------------------
 sensor-family-desktop | ["built-in sensor", "native", "node.js", "python", "shell", "ruby"]

Configuration Override

Priority System

  1. Environment Variable (highest - skips database)

    export ATTUNE_SENSOR_RUNTIMES="python,shell"
    
  2. Config File (medium - skips database)

    sensor:
      capabilities:
        runtimes: ["python", "shell"]
    
  3. Database Detection (lowest - queries runtime table)

    # No sensor.capabilities.runtimes specified
    # Auto-detects from database
    

Example: Override for Development

# Fast startup for development (skip verification)
export ATTUNE_SENSOR_RUNTIMES="shell,python"
cargo run --bin attune-sensor

# Result: Only shell and python reported (no database query)

Files Created/Modified

New Files (3)

  1. migrations/20260202000001_add_sensor_runtimes.sql

    • Adds 5 sensor runtimes with verification metadata
    • Python, Node.js, Shell, Native, Built-in
    • ~200 lines
  2. docs/sensors/database-driven-runtime-detection.md

    • Complete documentation
    • Verification process, examples, troubleshooting
    • ~650 lines
  3. docs/sensors/SUMMARY-database-driven-detection.md

    • This summary document

Modified Files (2)

  1. crates/sensor/src/sensor_worker_registration.rs

    • Replaced auto_detect_runtimes() with detect_capabilities_async()
    • Added verify_runtime_available() method
    • Added try_verification_command() method
    • Queries runtime table and uses verification metadata
    • ~150 lines changed
  2. work-summary/sensor-worker-registration.md

    • Updated with database-driven enhancement details
    • Added verification examples and test results

Dependencies Added

  • regex = "1.x" to crates/sensor/Cargo.toml (for pattern matching)

Performance Impact

Startup Time Comparison

Hardcoded detection:  ~50-100ms  (4-6 binary checks)
Database-driven:      ~100-300ms (query + verification)

Difference: +50-200ms (acceptable for better maintainability)

Breakdown

  • Database query: ~10-20ms (5-10 runtimes)
  • Verification per runtime: ~10-50ms per runtime
  • Pattern matching: <1ms per pattern

Optimization

  • always_available runtimes skip verification (shell, native)
  • Commands tried in priority order (stop on first success)
  • Failed verifications logged at debug level only

Security Considerations

Safe Command Execution

// Safe: No shell interpretation
Command::new("python3")
    .args(&["--version"])  // Separate args, not shell-parsed
    .output()

No Injection Risk

  • Binary name and args are separate parameters
  • No shell (sh -c) used
  • Regex patterns validated before use

Database Access Control

  • Runtime table accessible only to svc_attune user
  • Verification commands run with sensor service privileges
  • No privilege escalation possible

Testing

Manual Testing

# Test 1: Database-driven detection
unset ATTUNE_SENSOR_RUNTIMES
./target/debug/attune-sensor
# Result: Detected all available runtimes from database

# Test 2: Environment override
export ATTUNE_SENSOR_RUNTIMES="shell,python"
./target/debug/attune-sensor
# Result: Only shell and python (skipped database)

# Test 3: Unavailable runtime filtered
# Added Haskell runtime to database (ghc not installed)
./target/debug/attune-sensor
# Result: Haskell NOT in detected runtimes (correctly filtered)

# Test 4: Available runtime detected
# Added Ruby runtime to database (ruby is installed)
./target/debug/attune-sensor
# Result: Ruby included in detected runtimes

Database Queries

-- Verify runtimes configured
SELECT ref, name, runtime_type 
FROM runtime 
WHERE runtime_type = 'sensor';
-- Result: 5 runtimes (python, nodejs, shell, native, builtin)

-- Check sensor worker capabilities
SELECT capabilities->>'runtimes' 
FROM worker 
WHERE worker_role = 'sensor';
-- Result: ["built-in sensor", "native", "node.js", "python", "shell"]

Migration Guide

For Existing Deployments

Step 1: Apply Migration

export DATABASE_URL="postgresql://attune:attune@localhost:5432/attune"
psql $DATABASE_URL < migrations/20260202000001_add_sensor_runtimes.sql

Step 2: Restart Sensor Services

systemctl restart attune-sensor
# Or for Docker:
docker compose restart sensor

Step 3: Verify Detection

# Check logs
journalctl -u attune-sensor | grep "Detected available runtimes"

# Check database
psql $DATABASE_URL -c "SELECT capabilities FROM worker WHERE worker_role = 'sensor';"

Adding Custom Runtimes

-- Example: Add PHP runtime
INSERT INTO runtime (ref, pack, pack_ref, description, runtime_type, name, distributions)
VALUES (
    'mypack.sensor.php',
    (SELECT id FROM pack WHERE ref = 'mypack'),
    'mypack',
    'PHP sensor runtime',
    'sensor',
    'PHP',
    jsonb_build_object(
        'verification', jsonb_build_object(
            'commands', jsonb_build_array(
                jsonb_build_object(
                    'binary', 'php',
                    'args', jsonb_build_array('--version'),
                    'exit_code', 0,
                    'pattern', 'PHP \\d+\\.\\d+',
                    'priority', 1
                )
            )
        )
    )
);

-- Restart sensor service
-- PHP will be automatically detected if installed

Troubleshooting

Runtime Not Detected

Check database configuration:

SELECT distributions->'verification' 
FROM runtime 
WHERE ref = 'core.sensor.python';

Test verification manually:

python3 --version
# Should output: Python 3.x.x

Check sensor logs:

journalctl -u attune-sensor | grep "Runtime available"

Pattern Not Matching

Test regex:

python3 --version | grep -E "Python 3\."
# Should match if Python 3.x

Fix pattern in database:

UPDATE runtime
SET distributions = jsonb_set(
    distributions,
    '{verification,commands,0,pattern}',
    '"Python 3\\."'
)
WHERE ref = 'core.sensor.python';

Key Benefits

For Operators

  • Add runtimes without rebuilding sensor service
  • Centralized runtime configuration in database
  • Version validation via regex patterns
  • Flexible verification with fallback commands
  • Override capability for testing/development

For Developers

  • No code changes to support new runtimes
  • Maintainable verification logic in one place
  • Testable via database queries
  • Extensible with custom verification commands
  • Self-documenting via database metadata

For Pack Authors

  • No deployment coordination to add runtime support
  • Version requirements documented in runtime record
  • Installation instructions can be stored in metadata
  • Fallback commands for different distributions

Future Enhancements

Planned

  1. Runtime Version Parsing

    • Extract version from verification output
    • Store detected version in worker capabilities
    • Compare against min_version requirement
  2. Cached Verification Results

    • Cache verification results for 5-10 minutes
    • Reduce verification overhead on frequent restarts
    • Configurable cache TTL
  3. Periodic Re-verification

    • Background job to re-verify runtimes
    • Auto-update capabilities if runtime installed/removed
    • Emit events on capability changes
  4. Runtime Installation Hints

    • Store installation instructions in runtime.installation
    • Emit helpful messages for missing runtimes
    • Link to documentation for setup

Possible Extensions

  1. Dependency Checking

    • Verify runtime dependencies (e.g., pip for Python)
    • Check for required system packages
    • Validate runtime configuration
  2. Health Checks

    • Periodic runtime health verification
    • Detect runtime degradation
    • Alert on runtime failures
  3. Multi-Version Support

    • Support multiple versions of same runtime
    • Select best available version
    • Pin sensors to specific versions

Conclusion

The sensor service is now completely independent of hardcoded runtime checks. Runtime verification is configured in the database, making it trivial to add new sensor runtimes without code changes or redeployment.

Key Achievement: Sensor runtime detection is now data-driven, maintainable, and extensible—aligned with the goal of making the sensor service a relatively independent process that doesn't need too much configuration to operate.


Documentation

  • Full Guide: docs/sensors/database-driven-runtime-detection.md
  • Worker Registration: docs/sensors/sensor-worker-registration.md
  • Quick Reference: docs/QUICKREF-sensor-worker-registration.md
  • Implementation Summary: work-summary/sensor-worker-registration.md

Status: Complete and Production Ready
Tested: Manual testing + database verification
Performance: Acceptable overhead (~50-200ms startup increase)
Maintainability: Excellent (zero code changes to add runtimes)