Files
git.stella-ops.org/docs/contracts/scanner-php-analyzer.md
master cc69d332e3
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Add unit tests for RabbitMq and Udp transport servers and clients
- Implemented comprehensive unit tests for RabbitMqTransportServer, covering constructor, disposal, connection management, event handlers, and exception handling.
- Added configuration tests for RabbitMqTransportServer to validate SSL, durable queues, auto-recovery, and custom virtual host options.
- Created unit tests for UdpFrameProtocol, including frame parsing and serialization, header size validation, and round-trip data preservation.
- Developed tests for UdpTransportClient, focusing on connection handling, event subscriptions, and exception scenarios.
- Established tests for UdpTransportServer, ensuring proper start/stop behavior, connection state management, and event handling.
- Included tests for UdpTransportOptions to verify default values and modification capabilities.
- Enhanced service registration tests for Udp transport services in the dependency injection container.
2025-12-05 19:01:12 +02:00

7.9 KiB

CONTRACT-SCANNER-PHP-ANALYZER-013: PHP Language Analyzer Bootstrap

Status: Published Version: 1.0.0 Published: 2025-12-05 Owners: PHP Analyzer Guild, Scanner Guild Unblocks: SCANNER-ANALYZERS-PHP-27-001

Overview

This contract defines the PHP language analyzer bootstrap specification, including composer manifest parsing, VFS (Virtual File System) schema, and offline kit target requirements for deterministic PHP project analysis.

Scope

The PHP analyzer will:

  1. Parse composer.json and composer.lock files
  2. Build virtual file system from source trees, vendor directories, and configs
  3. Detect framework/CMS fingerprints (Laravel, Symfony, WordPress, Drupal, etc.)
  4. Emit SBOM components with PHP-specific PURLs
  5. Support offline analysis via cached dependencies

Input Normalization

Source Tree Merge

The analyzer merges these sources into a unified VFS:

Priority (highest to lowest):
1. /app (mounted application source)
2. /vendor (composer dependencies)
3. /etc/php* (PHP configuration)
4. Container layer filesystem

File Discovery

public interface IPhpSourceDiscovery
{
    IAsyncEnumerable<PhpSourceFile> DiscoverAsync(
        string rootPath,
        PhpDiscoveryOptions options,
        CancellationToken ct);
}

public record PhpDiscoveryOptions
{
    public bool IncludeVendor { get; init; } = true;
    public bool IncludeTests { get; init; } = false;
    public string[] ExcludePatterns { get; init; } = ["*.min.php", "cache/*"];
}

Composer Schema

composer.json Parsing

{
  "name": "vendor/package",
  "version": "1.2.3",
  "type": "library|project|metapackage|composer-plugin",
  "require": {
    "php": ">=8.1",
    "vendor/dependency": "^2.0"
  },
  "require-dev": { },
  "autoload": {
    "psr-4": { "App\\": "src/" },
    "classmap": ["database/"],
    "files": ["helpers.php"]
  }
}

composer.lock Parsing

Extract exact versions and content hashes:

public record ComposerLockPackage
{
    public string Name { get; init; }
    public string Version { get; init; }
    public string Source { get; init; }  // type: git|hg|svn
    public string Dist { get; init; }    // type: zip|tar
    public string Reference { get; init; } // commit hash or tag
    public string ContentHash { get; init; } // SHA256 of package contents
}

PURL Format

pkg:composer/vendor/package@version
pkg:composer/laravel/framework@10.0.0
pkg:composer/symfony/http-kernel@6.3.0

VFS Schema

Virtual File System Model

public record PhpVirtualFileSystem
{
    public string RootPath { get; init; }
    public IReadOnlyList<VfsEntry> Entries { get; init; }
    public PhpConfiguration PhpConfig { get; init; }
    public ComposerManifest Composer { get; init; }
    public string ContentHash { get; init; } // BLAKE3 of sorted entries
}

public record VfsEntry
{
    public string RelativePath { get; init; }
    public VfsEntryType Type { get; init; }
    public long Size { get; init; }
    public string ContentHash { get; init; }
    public DateTimeOffset ModifiedAt { get; init; }
}

public enum VfsEntryType
{
    PhpSource,
    PhpConfig,
    ComposerJson,
    ComposerLock,
    Vendor,
    Asset,
    Config
}

Deterministic Ordering

VFS entries MUST be sorted by:

  1. RelativePath (case-sensitive, lexicographic)
  2. Stable hash computation across runs

Framework Detection

Fingerprint Rules

Framework Detection Method Confidence
Laravel artisan file + Illuminate\ namespace High
Symfony symfony.lock or config/bundles.php High
WordPress wp-config.php + wp-includes/ High
Drupal core/lib/Drupal.php High
Magento app/etc/env.php + Magento\ namespace High
CodeIgniter system/core/CodeIgniter.php Medium
Yii yii or yii2 in composer Medium
CakePHP cakephp/cakephp in composer Medium

Fingerprint Output

public record PhpFrameworkFingerprint
{
    public string Name { get; init; }
    public string Version { get; init; }
    public ConfidenceLevel Confidence { get; init; }
    public IReadOnlyList<string> IndicatorFiles { get; init; }
}

PHP Configuration

Config File Discovery

/etc/php/*/php.ini
/etc/php/*/conf.d/*.ini
/etc/php-fpm.d/*.conf
/usr/local/etc/php/php.ini (Alpine)

Security-Relevant Settings

Extract and report:

public record PhpSecurityConfig
{
    public bool AllowUrlFopen { get; init; }
    public bool AllowUrlInclude { get; init; }
    public string OpenBasedir { get; init; }
    public string DisableFunctions { get; init; }
    public string DisableClasses { get; init; }
    public bool ExposePhp { get; init; }
    public bool DisplayErrors { get; init; }
}

Output Schema

SBOM Component

{
  "type": "library",
  "bom-ref": "pkg:composer/vendor/package@1.2.3",
  "purl": "pkg:composer/vendor/package@1.2.3",
  "name": "vendor/package",
  "version": "1.2.3",
  "properties": [
    { "name": "stellaops:php:framework", "value": "laravel" },
    { "name": "stellaops:php:phpVersion", "value": ">=8.1" },
    { "name": "stellaops:php:autoload", "value": "psr-4" }
  ],
  "evidence": {
    "identity": {
      "field": "purl",
      "confidence": 1.0,
      "methods": [{ "technique": "manifest-analysis", "value": "composer.lock" }]
    }
  }
}

Analysis Store Keys

public static class PhpAnalysisKeys
{
    public const string VirtualFileSystem = "php.vfs";
    public const string ComposerManifest = "php.composer";
    public const string FrameworkFingerprints = "php.frameworks";
    public const string SecurityConfig = "php.security-config";
    public const string Autoload = "php.autoload";
}

Offline Kit Target

Bundle Structure

offline/php-analyzer/
├── manifests/
│   └── php-analyzer-manifest.json
├── fixtures/
│   ├── laravel-app/
│   ├── symfony-app/
│   └── wordpress-site/
├── vendor-cache/
│   └── packages.json (Packagist mirror index)
└── SHA256SUMS

Air-Gap Operation

public interface IOfflineComposerRepository
{
    Task<ComposerPackage?> ResolveAsync(string name, string version, CancellationToken ct);
    Task<bool> IsAvailableOfflineAsync(string name, string version, CancellationToken ct);
}

Test Fixtures

Required Fixtures

Fixture Purpose
laravel-10-app/ Laravel 10.x application with mix/vite
symfony-6-app/ Symfony 6.x with Doctrine
wordpress-6-site/ WordPress 6.x with plugins
drupal-10-site/ Drupal 10.x with modules
composer-only/ Pure library project
legacy-php56/ PHP 5.6 compatibility test

Golden Output Format

fixtures/<name>/
├── composer.json
├── composer.lock
├── src/
├── EXPECTED.sbom.json    # Expected SBOM output
├── EXPECTED.vfs.json     # Expected VFS structure
└── EXPECTED.meta.json    # Expected fingerprints

Implementation Path

Phase 1: Core Parser

  1. Implement ComposerJsonParser
  2. Implement ComposerLockParser
  3. Add PURL generation
  4. Basic VFS construction

Phase 2: Framework Detection

  1. Implement fingerprint rules
  2. Add confidence scoring
  3. Version detection

Phase 3: Offline Support

  1. Implement vendor cache
  2. Add offline repository
  3. Bundle generation

Project Location

src/Scanner/StellaOps.Scanner.Analyzers.Lang.Php/
├── StellaOps.Scanner.Analyzers.Lang.Php.csproj
├── ComposerJsonParser.cs
├── ComposerLockParser.cs
├── PhpVirtualFileSystem.cs
├── PhpFrameworkDetector.cs
├── PhpLanguageAnalyzer.cs
├── PhpAnalyzerPlugin.cs
└── README.md

Changelog

Version Date Author Changes
1.0.0 2025-12-05 PHP Analyzer Guild Initial contract