Add unit tests for RabbitMq and Udp transport servers and clients
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
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.
This commit is contained in:
346
docs/contracts/scanner-php-analyzer.md
Normal file
346
docs/contracts/scanner-php-analyzer.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user