Add PHP Analyzer Plugin and Composer Lock Data Handling
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Implemented the PhpAnalyzerPlugin to analyze PHP projects.
- Created ComposerLockData class to represent data from composer.lock files.
- Developed ComposerLockReader to load and parse composer.lock files asynchronously.
- Introduced ComposerPackage class to encapsulate package details.
- Added PhpPackage class to represent PHP packages with metadata and evidence.
- Implemented PhpPackageCollector to gather packages from ComposerLockData.
- Created PhpLanguageAnalyzer to perform analysis and emit results.
- Added capability signals for known PHP frameworks and CMS.
- Developed unit tests for the PHP language analyzer and its components.
- Included sample composer.lock and expected output for testing.
- Updated project files for the new PHP analyzer library and tests.
This commit is contained in:
StellaOps Bot
2025-11-22 14:02:49 +02:00
parent a7f3c7869a
commit b6b9ffc050
158 changed files with 16272 additions and 809 deletions

View File

@@ -1,6 +1,7 @@
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using StellaOps.Findings.Ledger.Domain;
using StellaOps.Findings.Ledger.Infrastructure.Exports;
namespace StellaOps.Findings.Ledger.Observability;
@@ -12,6 +13,8 @@ internal static class LedgerTimeline
{
private static readonly EventId LedgerAppended = new(6101, "ledger.event.appended");
private static readonly EventId ProjectionUpdated = new(6201, "ledger.projection.updated");
private static readonly EventId OrchestratorExport = new(6301, "ledger.export.recorded");
private static readonly EventId AirgapImport = new(6401, "ledger.airgap.imported");
public static void EmitLedgerAppended(ILogger logger, LedgerEventRecord record, string? evidenceBundleRef = null)
{
@@ -62,4 +65,38 @@ internal static class LedgerTimeline
traceId,
evidenceBundleRef ?? record.EvidenceBundleReference ?? string.Empty);
}
public static void EmitOrchestratorExport(ILogger logger, OrchestratorExportRecord record)
{
if (logger is null)
{
return;
}
logger.LogInformation(
OrchestratorExport,
"timeline ledger.export.recorded tenant={Tenant} run={RunId} artifact={ArtifactHash} policy={PolicyHash} status={Status} merkle_root={MerkleRoot}",
record.TenantId,
record.RunId,
record.ArtifactHash,
record.PolicyHash,
record.Status,
record.MerkleRoot);
}
public static void EmitAirgapImport(ILogger logger, string tenantId, string bundleId, string merkleRoot, Guid? ledgerEventId)
{
if (logger is null)
{
return;
}
logger.LogInformation(
AirgapImport,
"timeline ledger.airgap.imported tenant={Tenant} bundle={BundleId} merkle_root={MerkleRoot} ledger_event={LedgerEvent}",
tenantId,
bundleId,
merkleRoot,
ledgerEventId?.ToString() ?? string.Empty);
}
}