Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- 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.
347 lines
7.9 KiB
Markdown
347 lines
7.9 KiB
Markdown
# 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
|
|
|
|
```csharp
|
|
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
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
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:
|
|
|
|
```csharp
|
|
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
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
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 |
|