All phases (0-8) now have detailed implementation plans with: - Bullet-level requirement extraction from HighLevelReqs sections - Design constraint traceability (KDD + Component Design) - Work packages with acceptance criteria mapped to every requirement - Split-section ownership verified across phases - Orphan checks (forward, reverse, negative) all passing - Codex MCP (gpt-5.4) external verification completed per phase Total: 7,549 lines across 11 plan documents, ~160 work packages, ~400 requirements traced, ~25 open questions logged for follow-up.
49 KiB
Phase 0: Solution Skeleton & Delivery Guardrails
Date: 2026-03-16 Status: Draft Components: Commons, Host, Solution Structure, CI Baseline
1. Scope
This phase establishes the buildable, testable baseline for the entire ScadaLink system before any domain logic is implemented. It delivers:
- A .NET 10 solution with all 17 component projects and corresponding test projects, using the SLNX format.
- The Commons component with its complete namespace/folder skeleton, shared data types, entity POCOs, repository interfaces, cross-cutting service interfaces, message contracts, and protocol abstraction interfaces.
- A Host skeleton that boots by role from
appsettings.json, demonstrates the extension method convention, and differentiates between central (WebApplication) and site (generic Host) startup paths. - Per-component options classes in their respective component projects.
- Sample
appsettings.jsonfiles for central and site topologies.
No business logic, actor systems, database connectivity, or web endpoints are implemented in this phase. The deliverable is a compiling solution with correct project references, enforceable architectural constraints, and a skeleton that subsequent phases build upon.
2. Prerequisites
- None. This is the first phase.
- Tooling: .NET 10 SDK, an IDE, Git.
3. Requirements Checklist
HighLevelReqs 13.1 — Timestamps (UTC)
[13.1-1]All timestamps throughout the system are stored, transmitted, and processed in UTC.[13.1-2]Applies to: attribute value timestamps, alarm state change timestamps, audit log entries, event log entries, deployment records, health reports, store-and-forward message timestamps, and all inter-node messages.[13.1-3]Local time conversion for display is a Central UI concern only — no other component performs timezone conversion.
REQ-COM-1: Shared Data Type System
[COM-1-1]DataTypeenum: Boolean, Int32, Float, Double, String, DateTime, Binary.[COM-1-2]RetryPolicy: record or immutable class with max retries and fixed delay.[COM-1-3]Result<T>: discriminated result type representing success or error.[COM-1-4]InstanceStateenum: Enabled, Disabled.[COM-1-5]DeploymentStatusenum: Pending, InProgress, Success, Failed.[COM-1-6]AlarmStateenum: Active, Normal.[COM-1-7]AlarmTriggerTypeenum: ValueMatch, RangeViolation, RateOfChange.[COM-1-8]ConnectionHealthenum: Connected, Disconnected, Connecting, Error.[COM-1-9]All types must be immutable and thread-safe.[COM-1-10]Timestamp convention: all timestamps must use UTC (DateTimewithDateTimeKind.UtcorDateTimeOffsetwith zero offset).[COM-1-11]Timestamp convention applies to all stored timestamps (SQLite, MS SQL, audit entries), all message timestamps, and all wire-format timestamps.[COM-1-12]Local time conversion is a UI display concern only (negative: no other component performs timezone conversion).
REQ-COM-2: Protocol Abstraction
[COM-2-1]IDataConnectioninterface for reading, writing, and subscribing to device data.[COM-2-2]Related types: tag identifiers, read/write results, subscription callbacks, connection status enums, quality codes.[COM-2-3]Interfaces must not reference any specific protocol implementation (negative).
REQ-COM-3: Domain Entity Classes (POCOs)
[COM-3-1]Plain C# classes with properties — no EF attributes, no EF base classes, no navigation property annotations.[COM-3-2]May include navigation properties as plain collections (e.g.,ICollection<TemplateAttribute>).[COM-3-3]May include constructors that enforce invariants.[COM-3-4]Must have no dependency on Entity Framework Core or any persistence library (negative).[COM-3-5]Template & Modeling entities:Template,TemplateAttribute,TemplateAlarm,TemplateScript,TemplateComposition,Instance,InstanceAttributeOverride,InstanceConnectionBinding,Area.[COM-3-6]Shared Scripts entities:SharedScript.[COM-3-7]Sites & Data Connections entities:Site,DataConnection,SiteDataConnectionAssignment.[COM-3-8]External Systems & Database Connections entities:ExternalSystemDefinition,ExternalSystemMethod,DatabaseConnectionDefinition.[COM-3-9]Notifications entities:NotificationList,NotificationRecipient,SmtpConfiguration.[COM-3-10]Inbound API entities:ApiKey,ApiMethod.[COM-3-11]Security entities:LdapGroupMapping,SiteScopeRule.[COM-3-12]Deployment entities:DeploymentRecord,SystemArtifactDeploymentRecord.[COM-3-13]Audit entities:AuditLogEntry.
REQ-COM-4: Per-Component Repository Interfaces
[COM-4-1]ITemplateEngineRepository— templates, attributes, alarms, scripts, compositions, instances, overrides, connection bindings, areas.[COM-4-2]IDeploymentManagerRepository— deployment records, deployed configuration snapshots, system-wide artifact deployment records.[COM-4-3]ISecurityRepository— LDAP group mappings, site scoping rules.[COM-4-4]IInboundApiRepository— API keys, API method definitions.[COM-4-5]IExternalSystemRepository— external system definitions, method definitions, database connection definitions.[COM-4-6]INotificationRepository— notification lists, recipients, SMTP configuration.[COM-4-7]ICentralUiRepository— read-oriented queries spanning multiple domain areas.[COM-4-8]All repository interfaces accept and return POCO entity classes.[COM-4-9]All repository interfaces includeSaveChangesAsync()or equivalent.[COM-4-10]No dependency on Entity Framework Core — pure interfaces (negative).
REQ-COM-4a: Cross-Cutting Service Interfaces
[COM-4a-1]IAuditServicewithLogAsync(user, action, entityType, entityId, entityName, afterState).[COM-4a-2]Defined in Commons so any central component can call it without depending on the audit implementation directly.
REQ-COM-5: Cross-Component Message Contracts
[COM-5-1]Deployment DTOs: configuration snapshots, deployment commands, deployment status, validation results.[COM-5-2]Instance Lifecycle DTOs: disable, enable, delete commands and responses.[COM-5-3]Health DTOs: health check results, site status reports, heartbeat messages, script error rates, alarm evaluation error rates.[COM-5-4]Communication DTOs: site identity, connection state, routing metadata.[COM-5-5]Attribute Stream DTOs: attribute value change messages (instance name, attribute path, value, quality, timestamp) and alarm state change messages (instance name, alarm name, state, priority, timestamp).[COM-5-6]Debug View DTOs: subscribe/unsubscribe requests, initial snapshot, stream filter criteria.[COM-5-7]Script Execution DTOs: script call requests (with recursion depth), return values, error results.[COM-5-8]System-Wide Artifact DTOs: shared script packages, external system definitions, database connection definitions, notification list definitions.[COM-5-9]All message types must berecordtypes or immutable classes (negative: no mutable message types).[COM-5-10]Commons must not depend on Akka.NET (negative), even though messages will be used as Akka messages.
REQ-COM-5a: Message Contract Versioning
[COM-5a-1]Additive-only evolution: new fields with defaults; existing fields must not be removed or have types changed (negative).[COM-5a-2]Serialization must tolerate unknown fields (forward compatibility) and missing optional fields (backward compatibility).[COM-5a-3]Breaking changes require a new message type and coordinated deployment.[COM-5a-4]Akka.NET serialization binding must explicitly map message types to serializers (prevents binary serialization) — noted here but implemented in Phase 1/3A when Akka is bootstrapped.
REQ-COM-5b: Namespace & Folder Convention
[COM-5b-1]Top-level folders:Types/,Interfaces/,Entities/,Messages/.[COM-5b-2]Types/contains shared data types (REQ-COM-1) includingEnums/subfolder.[COM-5b-3]Interfaces/Protocol/for IDataConnection and related types.[COM-5b-4]Interfaces/Repositories/for per-component repository interfaces.[COM-5b-5]Interfaces/Services/for cross-cutting service interfaces (IAuditService).[COM-5b-6]Entities/subfolders by domain area: Templates, Instances, Sites, ExternalSystems, Notifications, InboundApi, Security, Deployment, Scripts, Audit.[COM-5b-7]Messages/subfolders by concern: Deployment, Lifecycle, Health, Communication, Streaming, DebugView, ScriptExecution, Artifacts.[COM-5b-8]Namespaces mirror folder structure (e.g.,ScadaLink.Commons.Entities.Templates).[COM-5b-9]Interface names useIprefix.[COM-5b-10]Entity classes named after domain concept — noEntityorModelsuffixes.[COM-5b-11]Message contracts named as commands, events, or responses.[COM-5b-12]Enums use singular names.
REQ-COM-6: No Business Logic
[COM-6-1]Commons contains only: data structures (records, classes, structs), interfaces, enums, constants.[COM-6-2]Must not contain business logic, service implementations, actor definitions, or orchestration code (negative).[COM-6-3]Method bodies limited to trivial data-access logic (factory methods, constructor invariant validation).
REQ-COM-7: Minimal Dependencies
[COM-7-1]Depends only on core .NET libraries (System.*,Microsoft.Extensions.Primitivesif needed).[COM-7-2]Must not reference Akka.NET or Akka.* packages (negative).[COM-7-3]Must not reference ASP.NET Core or Microsoft.AspNetCore.* packages (negative).[COM-7-4]Must not reference Entity Framework Core or Microsoft.EntityFrameworkCore.* packages (negative).[COM-7-5]Must not reference any third-party libraries requiring paid licenses (negative).
REQ-HOST-1: Single Binary Deployment
[HOST-1-1]Same compiled binary deployable to both central and site nodes.[HOST-1-2]Node role determined solely by configuration inappsettings.json.[HOST-1-3]No separate build targets, projects, or conditional compilation symbols for central vs. site (negative).
REQ-HOST-2: Role-Based Service Registration (Phase 0 skeleton)
[HOST-2-1]Host inspects configured node role at startup.[HOST-2-2]Registers only component services appropriate for the role.[HOST-2-3]Shared (both): ClusterInfrastructure, Communication, HealthMonitoring, ExternalSystemGateway, NotificationService.[HOST-2-4]Central only: TemplateEngine, DeploymentManager, Security, AuditLogging, CentralUI, InboundAPI.[HOST-2-5]Site only: SiteRuntime, DataConnectionLayer, StoreAndForward, SiteEventLogging.[HOST-2-6]Components not applicable to the role must not be registered (negative).
REQ-HOST-3: Configuration Binding (Phase 0 skeleton)
[HOST-3-1]Bind configuration sections fromappsettings.jsonto strongly-typed options classes using .NET Options pattern.[HOST-3-2]Infrastructure sections:ScadaLink:Node(NodeOptions),ScadaLink:Cluster(ClusterOptions),ScadaLink:Database(DatabaseOptions).[HOST-3-3]Per-component sections: DataConnection, StoreAndForward, HealthMonitoring, SiteEventLog, Communication, Security, InboundApi, Notification, Logging.[HOST-3-4]Each component defines its own options class in its own project.[HOST-3-5]Host binds viaservices.Configure<T>(configuration.GetSection("ScadaLink:<ComponentName>")).[HOST-3-6]Components read options viaIOptions<T>— neverIConfigurationdirectly (negative).
REQ-HOST-7: ASP.NET vs Generic Host (Phase 0 skeleton)
[HOST-7-1]Central nodes useWebApplication.CreateBuilder(ASP.NET Core host with Kestrel).[HOST-7-2]Site nodes useHost.CreateDefaultBuilder(genericIHost— no Kestrel, no HTTP, no web pipeline).[HOST-7-3]Site nodes must never accept inbound HTTP connections (negative).
REQ-HOST-10: Extension Method Convention
[HOST-10-1]Each component exposesIServiceCollection.AddXxx()for DI registration.[HOST-10-2]Each component with actors exposesAkkaConfigurationBuilder.AddXxxActors()(stub in Phase 0).[HOST-10-3]CentralUI and InboundAPI exposeWebApplication.MapXxx()(stub in Phase 0).[HOST-10-4]Host'sProgram.cscalls these extension methods; component libraries own the registration logic.[HOST-10-5]Host remains thin — no component-specific logic inProgram.cs.
4. Design Constraints Checklist
From CLAUDE.md Key Design Decisions
[KDD-data-6]All timestamps are UTC throughout the system. → Enforced in type system (COM-1-10, COM-1-11, COM-1-12).[KDD-code-1]Entity classes are persistence-ignorant POCOs in Commons; EF mappings in Configuration Database. → Phase 0 delivers the POCOs; Phase 1 delivers the EF mappings.[KDD-code-2]Repository interfaces in Commons; implementations in Configuration Database. → Phase 0 delivers the interfaces; Phase 1 delivers implementations.[KDD-code-3]Commons namespace hierarchy: Types/, Interfaces/, Entities/, Messages/ with domain area subfolders. → Directly maps to REQ-COM-5b.[KDD-code-4]Message contracts follow additive-only evolution rules. → Directly maps to REQ-COM-5a.[KDD-code-5]Per-component configuration via appsettings.json sections bound to options classes. → Directly maps to REQ-HOST-3.[KDD-code-6]Options classes owned by component projects, not Commons. → Directly maps to HOST-3-4.
From Component-Commons.md
[CD-Commons-1]Commons is referenced by all component libraries and the Host — project reference structure must reflect this.[CD-Commons-2]No EF navigation property annotations on POCOs (Fluent API only in Configuration Database).[CD-Commons-3]Configuration Database implements repository interfaces and maps POCOs — Phase 0 establishes the interface contract; implementation deferred.
From Component-Host.md
[CD-Host-1]Host is the composition root — references every component project to call their extension methods.[CD-Host-2]Configuration Database registration (DbContext, repository wiring) is a Host responsibility — Phase 0 includes ConfigurationDatabase in Host'sAddXxx()call chain (skeleton); full DbContext/repository wiring in Phase 1.[CD-Host-3]Component registration matrix defines which components register for which roles (14 components + ConfigurationDatabase).
From Resolved Questions (questions.md)
[Q1].NET 10 LTS.[Q3]Single monorepo with SLNX solution file.[Q4]No CI/CD pipeline (build/test/format is local tooling only).
5. Work Packages
WP-0.1: Solution Structure
Description: Create the .NET 10 solution with all 17 component projects, their test projects, and the Host project using the SLNX format. Establish project references: all components reference Commons; Host references all components.
Acceptance Criteria:
- 15 component class library projects exist under
src/(all components except Host and Commons: TemplateEngine, DeploymentManager, SiteRuntime, DataConnectionLayer, Communication, StoreAndForward, ExternalSystemGateway, NotificationService, CentralUI, Security, HealthMonitoring, SiteEventLogging, ClusterInfrastructure, InboundAPI, ConfigurationDatabase). - 1 Commons class library project exists under
src/. - 1 Host project (console/web application) exists under
src/. - 17 corresponding test projects exist under
tests/(one per component + Commons + Host, xUnit). - SLNX solution file at the repository root includes all 17 source projects and 17 test projects.
- All 15 component library projects have a project reference to
ScadaLink.Commons. ScadaLink.Hosthas project references to all 15 component library projects + Commons (16 total).dotnet buildsucceeds with zero errors and zero warnings.dotnet testsucceeds (no tests yet, but framework is wired).
Complexity: M
Requirements Traced: [HOST-1-1], [HOST-1-3], [CD-Host-1], [CD-Commons-1], [Q1], [Q3]
WP-0.2: Commons Namespace & Folder Skeleton
Description: Create the complete folder and namespace structure for Commons as specified by REQ-COM-5b. All folders exist with placeholder files or namespace declarations as appropriate.
Acceptance Criteria:
- Top-level folders exist:
Types/,Types/Enums/,Interfaces/,Interfaces/Protocol/,Interfaces/Repositories/,Interfaces/Services/,Entities/,Messages/. - Entity subfolders exist:
Templates/,Instances/,Sites/,ExternalSystems/,Notifications/,InboundApi/,Security/,Deployment/,Scripts/,Audit/. - Message subfolders exist:
Deployment/,Lifecycle/,Health/,Communication/,Streaming/,DebugView/,ScriptExecution/,Artifacts/. - Namespace conventions match folder structure (e.g.,
ScadaLink.Commons.Entities.Templates).
Complexity: S
Requirements Traced: [COM-5b-1], [COM-5b-2], [COM-5b-3], [COM-5b-4], [COM-5b-5], [COM-5b-6], [COM-5b-7], [COM-5b-8], [KDD-code-3]
WP-0.3: Commons Shared Data Types
Description: Implement all shared data types defined by REQ-COM-1, including enums, RetryPolicy, Result<T>, and the UTC timestamp convention.
Acceptance Criteria:
DataTypeenum with values: Boolean, Int32, Float, Double, String, DateTime, Binary.RetryPolicyas a record or immutable class withMaxRetries(int) andDelay(TimeSpan) properties.Result<T>as a discriminated result type with success/error states and factory methods (Success(T),Failure(string)).InstanceStateenum: Enabled, Disabled.DeploymentStatusenum: Pending, InProgress, Success, Failed.AlarmStateenum: Active, Normal.AlarmTriggerTypeenum: ValueMatch, RangeViolation, RateOfChange.ConnectionHealthenum: Connected, Disconnected, Connecting, Error.- All types are immutable and thread-safe (record types for value objects — immutability guarantees thread safety; enums are inherently thread-safe).
- A
UtcTimestamphelper or convention document/attribute is provided to enforce UTC onDateTime/DateTimeOffsetfields. Unit test verifies that constructing aDateTimeOffsetwith non-zero offset is rejected or documented as invalid. - Enum names are singular (not plural).
- Unit tests verify:
Result<T>success/error construction, pattern matching, immutability ofRetryPolicy.
Complexity: S
Requirements Traced: [COM-1-1], [COM-1-2], [COM-1-3], [COM-1-4], [COM-1-5], [COM-1-6], [COM-1-7], [COM-1-8], [COM-1-9], [COM-1-10], [COM-1-11], [COM-1-12], [COM-5b-2], [COM-5b-12], [13.1-1], [13.1-2], [13.1-3], [KDD-data-6]
WP-0.4: Commons Domain Entity POCOs
Description: Implement all persistence-ignorant POCO entity classes organized by domain area, with appropriate properties, navigation collections, and constructor invariants.
Acceptance Criteria:
- Templates/:
Template(Id, Name, Description, ParentTemplateId, navigation to Attributes/Alarms/Scripts/Compositions),TemplateAttribute(Id, TemplateId, Name, Value, DataType, IsLocked, Description, DataSourceReference),TemplateAlarm(Id, TemplateId, Name, Description, PriorityLevel, IsLocked, TriggerType, TriggerConfig, OnTriggerScriptId),TemplateScript(Id, TemplateId, Name, IsLocked, Code, TriggerType, TriggerConfig, Parameters, ReturnDefinition, MinTimeBetweenRuns),TemplateComposition(Id, TemplateId, ComposedTemplateId, InstanceName). - Instances/:
Instance(Id, TemplateId, SiteId, AreaId, UniqueName, State),InstanceAttributeOverride(Id, InstanceId, AttributeName, OverrideValue),InstanceConnectionBinding(Id, InstanceId, AttributeName, DataConnectionId),Area(Id, SiteId, Name, ParentAreaId, navigation to children). - Sites/:
Site(Id, Name, SiteId),DataConnection(Id, Name, Protocol, Configuration),SiteDataConnectionAssignment(Id, SiteId, DataConnectionId). - ExternalSystems/:
ExternalSystemDefinition(Id, Name, EndpointUrl, AuthType, AuthConfig, RetryPolicy),ExternalSystemMethod(Id, ExternalSystemDefinitionId, Name, Parameters, ReturnDefinition),DatabaseConnectionDefinition(Id, Name, ConnectionString, RetryPolicy). - Notifications/:
NotificationList(Id, Name, navigation to recipients),NotificationRecipient(Id, NotificationListId, Name, EmailAddress),SmtpConfiguration(Id, Host, Port, AuthType, Credentials, FromAddress). - InboundApi/:
ApiKey(Id, Name, KeyValue, IsEnabled),ApiMethod(Id, Name, Script, ApprovedApiKeyIds, Parameters, ReturnDefinition, TimeoutSeconds). - Security/:
LdapGroupMapping(Id, LdapGroupName, Role),SiteScopeRule(Id, LdapGroupMappingId, SiteId). - Deployment/:
DeploymentRecord(Id, InstanceId, Status, DeploymentId, RevisionHash, DeployedBy, DeployedAt, CompletedAt),SystemArtifactDeploymentRecord(Id, ArtifactType, DeployedBy, DeployedAt, PerSiteStatus). - Scripts/:
SharedScript(Id, Name, Code, Parameters, ReturnDefinition). - Audit/:
AuditLogEntry(Id, User, Action, EntityType, EntityId, EntityName, AfterStateJson, Timestamp). - All timestamp properties use
DateTimeOffset(UTC). - No EF attributes (
[Key],[ForeignKey], etc.) on any POCO. - No dependency on
Microsoft.EntityFrameworkCorein the Commons.csproj. - Navigation properties use
ICollection<T>orIReadOnlyCollection<T>. - Unit tests verify: timestamp properties are UTC-only (where enforced by constructor), no EF references in assembly metadata.
Complexity: L
Requirements Traced: [COM-3-1], [COM-3-2], [COM-3-3], [COM-3-4], [COM-3-5], [COM-3-6], [COM-3-7], [COM-3-8], [COM-3-9], [COM-3-10], [COM-3-11], [COM-3-12], [COM-3-13], [COM-5b-6], [COM-5b-10], [KDD-code-1], [CD-Commons-2]
WP-0.5: Commons Repository Interfaces
Description: Define all per-component repository interfaces with method signatures matching the data needs of their consuming components. Interfaces accept and return POCOs, include SaveChangesAsync(), and have no EF dependency.
Acceptance Criteria:
ITemplateEngineRepositorywith CRUD methods for templates, attributes, alarms, scripts, compositions, instances, overrides, connection bindings, areas. IncludesSaveChangesAsync().IDeploymentManagerRepositorywith methods for deployment records, deployed configuration snapshots, system-wide artifact deployment records. IncludesSaveChangesAsync().ISecurityRepositorywith methods for LDAP group mappings and site scope rules. IncludesSaveChangesAsync().IInboundApiRepositorywith methods for API keys and API method definitions. IncludesSaveChangesAsync().IExternalSystemRepositorywith methods for external system definitions, method definitions, and database connection definitions. IncludesSaveChangesAsync().INotificationRepositorywith methods for notification lists, recipients, and SMTP configuration. IncludesSaveChangesAsync().ICentralUiRepositorywith read-oriented query methods spanning multiple domain areas.- All methods accept and return POCO types from
ScadaLink.Commons.Entities.*. - No
usingor reference toMicrosoft.EntityFrameworkCore.*in any interface file. - All interfaces are in
ScadaLink.Commons.Interfaces.Repositoriesnamespace. - Interface names use
Iprefix.
Complexity: M
Requirements Traced: [COM-4-1], [COM-4-2], [COM-4-3], [COM-4-4], [COM-4-5], [COM-4-6], [COM-4-7], [COM-4-8], [COM-4-9], [COM-4-10], [COM-5b-4], [COM-5b-9], [KDD-code-2]
WP-0.6: Commons Cross-Cutting Service Interfaces
Description: Define the IAuditService interface in Commons for cross-cutting audit logging.
Acceptance Criteria:
IAuditServiceinterface withLogAsync(string user, string action, string entityType, int entityId, string entityName, object? afterState)method (or equivalent signature).- Located in
ScadaLink.Commons.Interfaces.Servicesnamespace. - No dependency on Configuration Database or EF Core.
- Interface is callable by any central component without depending on the audit implementation.
Complexity: S
Requirements Traced: [COM-4a-1], [COM-4a-2], [COM-5b-5]
WP-0.7: Commons Message Contracts
Description: Define all cross-component message contracts as record types organized by concern area. Establish the additive-only versioning convention with documentation.
Acceptance Criteria:
- Deployment/: Records for
DeployInstanceCommand,DeploymentStatusResponse,DeploymentValidationResult,FlattenedConfigurationSnapshot(or similar). - Lifecycle/: Records for
DisableInstanceCommand,EnableInstanceCommand,DeleteInstanceCommand,InstanceLifecycleResponse. - Health/: Records for
HealthCheckResult(per-metric check outcome),SiteStatusReport(aggregated site health snapshot),SiteHealthReport(periodic report with script error rates, alarm evaluation error rates, S&F buffer depths),HeartbeatMessage. - Communication/: Records for
SiteIdentity,ConnectionStateMessage,RoutingMetadata. - Streaming/: Records for
AttributeValueChanged(instance name, attribute path, value, quality, timestamp) andAlarmStateChanged(instance name, alarm name, state, priority, timestamp). - DebugView/: Records for
SubscribeDebugView,UnsubscribeDebugView,DebugViewSnapshot,DebugViewFilterCriteria. - ScriptExecution/: Records for
ScriptCallRequest(with recursion depth),ScriptCallResult,ScriptErrorResult. - Artifacts/: Records for
SharedScriptPackage,ExternalSystemDefinitionArtifact,DatabaseConnectionDefinitionArtifact,NotificationListDefinitionArtifact. - All message types are
recordtypes (immutable by default). - No
Akka.*references in Commons.csprojor any message file. - All timestamp fields use
DateTimeOffset(UTC). - Message naming convention: commands, events, or responses (e.g.,
DeployInstanceCommand,AttributeValueChanged,DeploymentStatusResponse). - A
VERSIONING.mdor code comment documents the additive-only evolution rules: no field removal, no type changes, new fields must have defaults, breaking changes require new types. - Unit tests verify: all message types are records, all have
init-only or constructor-set properties (immutability check). - Unit tests verify forward/backward compatibility convention: a representative message contract can be serialized to JSON then deserialized with an extra unknown field (forward compat) and with an optional field missing (backward compat) without error. This validates the structural design supports [COM-5a-2].
Complexity: M
Requirements Traced: [COM-5-1], [COM-5-2], [COM-5-3], [COM-5-4], [COM-5-5], [COM-5-6], [COM-5-7], [COM-5-8], [COM-5-9], [COM-5-10], [COM-5a-1], [COM-5a-2], [COM-5a-3], [COM-5b-7], [COM-5b-11], [KDD-code-4]
WP-0.8: Commons Protocol Abstraction
Description: Define the IDataConnection interface and related types for the Data Connection Layer's protocol abstraction.
Acceptance Criteria:
IDataConnectioninterface with methods for: connect, disconnect, subscribe to tag paths, unsubscribe, read tag value, write tag value.- Related types in
Interfaces/Protocol/:TagIdentifier(tag path),TagValue(value + quality + timestamp),ReadResult(value or error),WriteResult(success/failure),SubscriptionCallback(delegate or interface for value change notifications),ConnectionStatusenum (mirrorsConnectionHealth: Connected, Disconnected, Connecting, Error),QualityCodeenum (Good, Bad, Uncertain, etc.). - No protocol-specific references (no OPC UA types, no gRPC types) — pure abstraction.
- Located in
ScadaLink.Commons.Interfaces.Protocolnamespace. - All timestamp fields use
DateTimeOffset(UTC).
Complexity: S
Requirements Traced: [COM-2-1], [COM-2-2], [COM-2-3], [COM-5b-3]
WP-0.9: Commons Architectural Constraint Enforcement
Description: Verify and enforce that Commons has no business logic and minimal dependencies through tests and project configuration.
Acceptance Criteria:
- Commons
.csprojreferences onlySystem.*and optionallyMicrosoft.Extensions.Primitives. No other package references. - An architectural test (using reflection or a test library) verifies:
- No classes in Commons implement business logic (no service classes, no actor classes).
- No reference to
Akka.*,Microsoft.AspNetCore.*, orMicrosoft.EntityFrameworkCore.*assemblies. - No reference to paid-license third-party packages.
- All method bodies in entity classes are limited to: constructors (invariant enforcement), factory methods, property getters/setters,
ToString()overrides, equality comparisons. - Test validates that no class in Commons has methods with complex logic (heuristic: methods with more than a configurable line threshold, excluding property accessors).
Complexity: S
Requirements Traced: [COM-6-1], [COM-6-2], [COM-6-3], [COM-7-1], [COM-7-2], [COM-7-3], [COM-7-4], [COM-7-5]
WP-0.10: Host Skeleton with Role-Based Startup
Description: Implement the Host Program.cs skeleton that reads node role from configuration and branches into WebApplication (central) or generic Host (site) startup paths. Wire the extension method convention with stub AddXxx() calls for all components, conditional on role.
Acceptance Criteria:
Program.csreadsScadaLink:Node:Rolefrom configuration.- When role is
Central: usesWebApplication.CreateBuilder, callsAddXxx()for shared + central-only components, callsMapCentralUI()andMapInboundAPI()stubs. - When role is
Site: usesHost.CreateDefaultBuilder, callsAddXxx()for shared + site-only components. Does not configure Kestrel, HTTP, or any web middleware. - Component registration follows the registration matrix exactly (14 components + ConfigurationDatabase on central).
- Configuration binding:
services.Configure<NodeOptions>(config.GetSection("ScadaLink:Node"))and equivalent for all component sections. - Each of the 15 component library projects exposes at minimum an
AddXxx()extension method onIServiceCollection(can be empty body for Phase 0). - Each component that has actors (per registration matrix: ClusterInfrastructure, Communication, HealthMonitoring, ExternalSystemGateway, NotificationService, TemplateEngine, DeploymentManager, Security, SiteRuntime, DataConnectionLayer, StoreAndForward, SiteEventLogging) exposes an
AddXxxActors()stub extension method. The method signature accepts the Akka configuration builder type (or a placeholder interface if Akka.Hosting is not yet referenced) and has an empty body in Phase 0. - CentralUI and InboundAPI expose
MapCentralUI()andMapInboundAPI()stub extension methods onWebApplication(orIEndpointRouteBuilder). - Host
Program.cscallsAddXxxActors()stubs for applicable components (conditional on role), and callsMapCentralUI()/MapInboundAPI()on central. - Host compiles and runs to completion with a minimal
appsettings.jsonfor both central and site roles. - Site-role startup does not open any network port (verified by test or manual check).
- Unit test: host starts with central role config and does not throw; host starts with site role config and does not throw.
Complexity: M
Requirements Traced: [HOST-1-1], [HOST-1-2], [HOST-1-3], [HOST-2-1], [HOST-2-2], [HOST-2-3], [HOST-2-4], [HOST-2-5], [HOST-2-6], [HOST-7-1], [HOST-7-2], [HOST-7-3], [HOST-10-1], [HOST-10-2], [HOST-10-3], [HOST-10-4], [HOST-10-5], [CD-Host-1], [CD-Host-2], [CD-Host-3]
WP-0.11: Per-Component Options Classes
Description: Create strongly-typed options classes in each component project, matching the configuration sections defined in REQ-HOST-3. Wire binding in Host Program.cs.
Acceptance Criteria:
NodeOptionsin Host project:Role(string/enum),NodeHostname(string),SiteId(string),RemotingPort(int).ClusterOptionsin ClusterInfrastructure project:SeedNodes(list),SplitBrainResolverStrategy,StableAfter,HeartbeatInterval,FailureDetectionThreshold,MinNrOfMembers.DatabaseOptionsin Host project:ConfigurationDb(string),MachineDataDb(string), SQLite paths.DataConnectionOptionsin DataConnectionLayer project:ReconnectInterval,TagResolutionRetryInterval,WriteTimeout.StoreAndForwardOptionsin StoreAndForward project:SqliteDbPath,ReplicationEnabled.HealthMonitoringOptionsin HealthMonitoring project:ReportInterval,OfflineTimeout.SiteEventLogOptionsin SiteEventLogging project:RetentionDays,MaxStorageMb,PurgeScheduleCron.CommunicationOptionsin Communication project:DeploymentTimeout,LifecycleTimeout,QueryTimeout,TransportHeartbeatInterval,TransportFailureThreshold.SecurityOptionsin Security project:LdapServer,LdapPort,LdapUseTls,JwtSigningKey,JwtExpiryMinutes,IdleTimeoutMinutes.InboundApiOptionsin InboundApi project:DefaultMethodTimeout.NotificationOptionsin NotificationService project (minimal — SMTP config is in config DB).LoggingOptionsin Host project: Serilog sink configuration, log level overrides.- All options classes are plain POCOs with public properties.
- Options classes live in their respective component projects, not in Commons.
- Host
Program.csbinds all sections viaservices.Configure<T>(). - Architectural test: no component library project (excluding Host) contains any
usingofMicrosoft.Extensions.Configurationor acceptsIConfigurationin itsAddXxx()method signature. Components access configuration only viaIOptions<T>/IOptionsSnapshot<T>.
Complexity: M
Requirements Traced: [HOST-3-1], [HOST-3-2], [HOST-3-3], [HOST-3-4], [HOST-3-5], [HOST-3-6], [KDD-code-5], [KDD-code-6]
WP-0.12: Local Dev Topology Documentation & Sample Configuration
Description: Create sample appsettings.json files for central and site roles demonstrating the full configuration structure. Document the local development topology.
Acceptance Criteria:
appsettings.Central.jsonwith:ScadaLink:Node(Role=Central, NodeHostname, RemotingPort),ScadaLink:Cluster(seed nodes for 2-node central),ScadaLink:Database(ConfigurationDb and MachineDataDb connection strings pointing to local Docker SQL Server), and all per-component sections with sensible defaults.appsettings.Site.jsonwith:ScadaLink:Node(Role=Site, NodeHostname, SiteId, RemotingPort),ScadaLink:Cluster(seed nodes for 2-node site),ScadaLink:Database(SQLite paths), and all per-component sections with sensible defaults.- Both files are valid JSON and the Host loads them without error.
- A brief topology comment block or accompanying doc section explains: 2-node central cluster, 2-node site cluster, what ports are used, how to run locally with different roles.
Complexity: S
Requirements Traced: [HOST-1-2], [HOST-3-2], [HOST-3-3]
6. Test Strategy
Unit Tests
| Area | Tests | Work Package |
|---|---|---|
Result<T> |
Success construction, error construction, map/bind, pattern matching | WP-0.3 |
RetryPolicy |
Immutability, default values | WP-0.3 |
| Enums | All enum values present and correctly named (singular) | WP-0.3 |
| Entity POCOs | No EF attributes via reflection, timestamp properties are DateTimeOffset, navigation properties are ICollection<T> |
WP-0.4 |
| Repository interfaces | No EF references in assembly, all include SaveChangesAsync |
WP-0.5 |
| Message contracts | All are record types, all timestamp fields are DateTimeOffset, immutability check |
WP-0.7 |
| Protocol abstraction | No protocol-specific type references | WP-0.8 |
| Architectural constraints | Commons has no forbidden dependencies, no business logic classes | WP-0.9 |
| Host startup | Central role boots without error, site role boots without error | WP-0.10 |
| Options classes | All options classes are POCOs, none in Commons project | WP-0.11 |
Integration Tests
| Area | Tests | Work Package |
|---|---|---|
| Solution build | dotnet build zero errors, zero warnings |
WP-0.1 |
| Host central boot | Host starts with central appsettings, binds all config sections, no crash | WP-0.10, WP-0.12 |
| Host site boot | Host starts with site appsettings, binds all config sections, no crash, no HTTP listener | WP-0.10, WP-0.12 |
Negative Tests
| Requirement | Negative Test | Work Package |
|---|---|---|
| [COM-3-4] No EF dependency | Reflection test: Commons assembly does not reference EF Core | WP-0.9 |
| [COM-5-10] No Akka dependency | Reflection test: Commons assembly does not reference Akka | WP-0.9 |
| [COM-6-2] No business logic | Scan for service/actor classes in Commons — expect none | WP-0.9 |
| [COM-7-2] No Akka packages | Verify Commons .csproj has no Akka PackageReference |
WP-0.9 |
| [COM-7-3] No ASP.NET packages | Verify Commons .csproj has no ASP.NET PackageReference |
WP-0.9 |
| [COM-7-4] No EF packages | Verify Commons .csproj has no EF PackageReference |
WP-0.9 |
| [HOST-1-3] No conditional compilation | Verify no #if directives in Host project |
WP-0.10 |
| [HOST-2-6] Non-applicable components not registered | Site boot does not register central-only services; central boot does not register site-only services | WP-0.10 |
| [HOST-7-3] Site nodes no HTTP | Site boot does not listen on any port | WP-0.10 |
| [HOST-3-6] Components never read IConfiguration directly | No component library AddXxx() method accepts IConfiguration; no using Microsoft.Extensions.Configuration in component libraries |
WP-0.11 |
| [COM-1-12] / [13.1-3] No timezone conversion outside UI | No ToLocalTime() calls in Commons or any non-UI component |
WP-0.9 |
7. Verification Gate
Phase 0 is complete when all of the following pass:
dotnet build ScadaLink.slnxcompletes with zero errors and zero warnings.dotnet test ScadaLink.slnxpasses all unit and integration tests.- Host boots successfully in central role from
appsettings.Central.jsonand exits cleanly. - Host boots successfully in site role from
appsettings.Site.jsonand exits cleanly. - Site-role Host does not open any network port.
- All 17 component projects compile with correct references to Commons.
- Commons project has zero non-core-NET package references.
- All architectural constraint tests pass (no EF, no Akka, no ASP.NET in Commons).
- All entity POCOs use
DateTimeOffsetfor timestamp fields. - All message contracts are record types.
- Every item in the Requirements Checklist (Section 3) and Design Constraints Checklist (Section 4) maps to a work package with acceptance criteria.
8. Open Questions
| # | Question | Context | Impact | Status |
|---|---|---|---|---|
| Q16 | Should Result<T> use a OneOf-style library or be hand-rolled? |
Affects COM-7-1 (minimal dependencies). A hand-rolled Result<T> keeps zero external dependencies. |
Phase 0. | Recommend hand-rolled to maintain zero-dependency constraint. Log for implementer's decision. |
| Q17 | Should entity POCO properties be required (init-only) or settable? | EF Core Fluent API mapping may need settable properties. POCOs must be persistence-ignorant but still mappable by Phase 1. | Phase 0 / Phase 1 boundary. | Recommend { get; set; } for EF compatibility, with constructor invariants for required fields. Log for implementer. |
| Q18 | What QualityCode values should the protocol abstraction define? |
OPC UA has a rich quality model (Good, Uncertain, Bad with subtypes). Need to decide on a simplified shared set. | Phase 0. | Recommend: Good, Bad, Uncertain as the minimal set, with room to extend. |
| Q19 | Should IDataConnection be IAsyncDisposable for connection cleanup? |
Affects DCL connection actor lifecycle. | Phase 0 / Phase 3B boundary. | Recommend yes — add IAsyncDisposable to support proper cleanup. |
These questions have been added to docs/plans/questions.md.
9. Post-Generation Verification (Orphan Check)
Forward Check: Requirements → Work Packages
Every item in the Requirements Checklist (Section 3) and Design Constraints Checklist (Section 4) has been verified against work package mappings:
| Requirement ID(s) | Work Package | Verified |
|---|---|---|
| [13.1-1], [13.1-2], [13.1-3] | WP-0.3 (UTC in type system), WP-0.4 (DateTimeOffset on entities), WP-0.7 (DateTimeOffset on messages) | Yes |
| [COM-1-1] through [COM-1-12] | WP-0.3 | Yes |
| [COM-2-1], [COM-2-2], [COM-2-3] | WP-0.8 | Yes |
| [COM-3-1] through [COM-3-13] | WP-0.4 | Yes |
| [COM-4-1] through [COM-4-10] | WP-0.5 | Yes |
| [COM-4a-1], [COM-4a-2] | WP-0.6 | Yes |
| [COM-5-1] through [COM-5-10] | WP-0.7 | Yes |
| [COM-5a-1] through [COM-5a-3] | WP-0.7 | Yes |
| [COM-5a-4] | Explicitly deferred to Phase 1/3A (Akka serialization binding). Noted in plan; no Phase 0 work package. | Yes (deferred) |
| [COM-5b-1] through [COM-5b-12] | WP-0.2, WP-0.3, WP-0.4, WP-0.5, WP-0.6, WP-0.7, WP-0.8 | Yes |
| [COM-6-1] through [COM-6-3] | WP-0.9 | Yes |
| [COM-7-1] through [COM-7-5] | WP-0.9 | Yes |
| [HOST-1-1] through [HOST-1-3] | WP-0.1, WP-0.10 | Yes |
| [HOST-2-1] through [HOST-2-6] | WP-0.10 | Yes |
| [HOST-3-1] through [HOST-3-6] | WP-0.11 | Yes |
| [HOST-7-1] through [HOST-7-3] | WP-0.10 | Yes |
| [HOST-10-1] through [HOST-10-5] | WP-0.10 | Yes |
| [KDD-data-6] | WP-0.3, WP-0.4, WP-0.7 | Yes |
| [KDD-code-1] | WP-0.4 (POCOs), WP-0.9 (no EF) | Yes |
| [KDD-code-2] | WP-0.5 (interfaces), WP-0.9 (no EF) | Yes |
| [KDD-code-3] | WP-0.2 | Yes |
| [KDD-code-4] | WP-0.7 | Yes |
| [KDD-code-5] | WP-0.11 | Yes |
| [KDD-code-6] | WP-0.11 | Yes |
| [CD-Commons-1] | WP-0.1 | Yes |
| [CD-Commons-2] | WP-0.4 | Yes |
| [CD-Commons-3] | WP-0.5 (interface contract; implementation deferred) | Yes |
| [CD-Host-1] | WP-0.1, WP-0.10 | Yes |
| [CD-Host-2] | WP-0.10 (ConfigurationDatabase in Host AddXxx() call chain) | Yes |
| [CD-Host-3] | WP-0.10 | Yes |
| [Q1], [Q3], [Q4] | WP-0.1 | Yes |
Result: All requirements and design constraints map to at least one work package. No orphans found.
Reverse Check: Work Packages → Requirements
| Work Package | Requirements Traced | Has Source Requirement | Verified |
|---|---|---|---|
| WP-0.1 | HOST-1-1, HOST-1-3, CD-Host-1, CD-Commons-1, Q1, Q3 | Yes | Yes |
| WP-0.2 | COM-5b-1 through COM-5b-8, KDD-code-3 | Yes | Yes |
| WP-0.3 | COM-1-1 through COM-1-12, COM-5b-2, COM-5b-12, 13.1-1 through 13.1-3, KDD-data-6 | Yes | Yes |
| WP-0.4 | COM-3-1 through COM-3-13, COM-5b-6, COM-5b-10, KDD-code-1, CD-Commons-2 | Yes | Yes |
| WP-0.5 | COM-4-1 through COM-4-10, COM-5b-4, COM-5b-9, KDD-code-2 | Yes | Yes |
| WP-0.6 | COM-4a-1, COM-4a-2, COM-5b-5 | Yes | Yes |
| WP-0.7 | COM-5-1 through COM-5-10, COM-5a-1 through COM-5a-4, COM-5b-7, COM-5b-11, KDD-code-4 | Yes | Yes |
| WP-0.8 | COM-2-1, COM-2-2, COM-2-3, COM-5b-3 | Yes | Yes |
| WP-0.9 | COM-6-1 through COM-6-3, COM-7-1 through COM-7-5 | Yes | Yes |
| WP-0.10 | HOST-1-1 through HOST-1-3, HOST-2-1 through HOST-2-6, HOST-7-1 through HOST-7-3, HOST-10-1 through HOST-10-5, CD-Host-1, CD-Host-2, CD-Host-3 | Yes | Yes |
| WP-0.11 | HOST-3-1 through HOST-3-6, KDD-code-5, KDD-code-6 | Yes | Yes |
| WP-0.12 | HOST-1-2, HOST-3-2, HOST-3-3 | Yes | Yes |
Result: All work packages trace to source requirements. No untraceable work.
Split-Section Check
Phase 0 covers only HighLevelReqs section 13.1 (Timestamps). This section is not split across phases — Phase 0 owns it entirely. All three bullets ([13.1-1], [13.1-2], [13.1-3]) are covered.
Phase 0 covers REQ-COM and REQ-HOST requirements. The following are split with other phases:
| REQ ID | Phase 0 Scope | Other Phase(s) Scope |
|---|---|---|
| REQ-COM-2 | Interface definition only | Phase 3B: OPC UA and LmxProxy implementations |
| REQ-COM-4a | Interface definition only | Phase 1: IAuditService implementation in Configuration Database |
| REQ-COM-5a-4 | Noted in plan; versioning rules documented | Phase 1/3A: Akka serialization binding configuration |
| REQ-HOST-2 | Skeleton role branching with stub AddXxx() calls |
Phase 1: Full service registration with real implementations |
| REQ-HOST-3 | Options classes created and bound | Phase 1: Startup validation of option values (REQ-HOST-4) |
| REQ-HOST-7 | WebApplication vs generic Host branching | Phase 1: Actual web endpoint mapping |
Result: No unowned bullets. All split items have clear phase ownership.
Negative Requirement Check
| Negative Requirement | Acceptance Criterion | Adequate |
|---|---|---|
| [COM-2-3] No protocol-specific references | WP-0.8: "No protocol-specific references" in AC | Yes |
| [COM-3-4] No EF dependency on POCOs | WP-0.4 + WP-0.9: reflection test on assembly refs | Yes |
| [COM-4-10] Repository interfaces no EF | WP-0.5: no EF using or reference check |
Yes |
| [COM-5-9] Messages must be record/immutable (no mutable) | WP-0.7: unit test verifies all are records | Yes |
| [COM-5-10] Commons no Akka dependency | WP-0.9: reflection test | Yes |
| [COM-5a-1] No field removal, no type changes | WP-0.7: versioning rules documented | Yes (convention; runtime enforcement N/A at compile time) |
| [COM-6-2] No business logic/services/actors | WP-0.9: scan for service/actor classes | Yes |
| [COM-7-2] No Akka packages | WP-0.9: csproj check | Yes |
| [COM-7-3] No ASP.NET packages | WP-0.9: csproj check | Yes |
| [COM-7-4] No EF packages | WP-0.9: csproj check | Yes |
| [COM-7-5] No paid-license packages | WP-0.9: csproj check | Yes |
| [HOST-1-3] No separate build targets/conditional compilation | WP-0.10: no #if directives check |
Yes |
| [HOST-2-6] Non-applicable components not registered | WP-0.10: site boot test verifies no central services registered | Yes |
| [HOST-3-6] Components never read IConfiguration directly | WP-0.11: architectural test verifies no component library uses Microsoft.Extensions.Configuration or accepts IConfiguration in AddXxx() |
Yes |
| [HOST-7-3] Site nodes never accept HTTP | WP-0.10: site boot no-port check | Yes |
| [COM-1-12] / [13.1-3] No timezone conversion outside UI | WP-0.9: no ToLocalTime() calls in non-UI code |
Yes |
Result: All negative requirements have corresponding acceptance criteria that would catch violations. No weak checks identified.
Codex MCP Verification
Model: gpt-5.4 Date: 2026-03-16
Step 1: Requirements Coverage Review
Codex identified 10 findings. Disposition:
| # | Finding | Disposition |
|---|---|---|
| 1 | Project count inconsistency (17 component projects + 1 Host = 18) | Corrected. WP-0.1 now explicitly lists 15 component library projects + 1 Commons + 1 Host = 17 total source projects. The "17 components" in CLAUDE.md includes Host and Commons in the count. |
| 2 | COM-5a-4 (Akka serialization binding) not covered by Phase 0 work package | Acknowledged. Correctly deferred to Phase 1/3A. Forward check updated to mark as explicitly deferred. COM-5a-4 requires Akka.NET which Phase 0 does not introduce. |
| 3 | 13.1-2 partially covered (event log and S&F timestamps) | Dismissed. Phase 0 establishes the UTC convention in the type system and on all entity/message timestamp fields. Specific event log and S&F entities created in Phase 0 (AuditLogEntry, DeploymentRecord, etc.) already use DateTimeOffset. The convention applies system-wide; later phases creating additional timestamp-bearing types must follow it. |
| 4 | COM-2-2 missing ReadResult and ConnectionStatus enum in WP-0.8 | Corrected. WP-0.8 acceptance criteria now include ReadResult and ConnectionStatus enum. |
| 5 | COM-5-3 missing HealthCheckResult and SiteStatusReport DTOs | Corrected. WP-0.7 Health section now requires HealthCheckResult, SiteStatusReport, SiteHealthReport, and HeartbeatMessage. |
| 6 | HOST-10-2 (AddXxxActors stubs) not in WP-0.10 acceptance criteria | Corrected. WP-0.10 now explicitly requires AddXxxActors() stub extension methods for all actor-bearing components, and MapXxx() stubs for CentralUI/InboundAPI. Host Program.cs calls them. |
| 7 | HOST-3-6 (no IConfiguration in components) not testable | Corrected. WP-0.11 now includes an architectural test: no component library uses Microsoft.Extensions.Configuration or accepts IConfiguration in its AddXxx() signature. Added to negative tests table. |
| 8 | CD-Host-2 weakly traced to WP-0.12 (sample configs) | Corrected. CD-Host-2 retraced to WP-0.10 (Host skeleton includes ConfigurationDatabase AddConfigurationDatabase() in its call chain). |
| 9 | COM-1-9 thread safety not explicitly verified | Dismissed. Immutable record types are inherently thread-safe in .NET. WP-0.3 AC updated to state "immutable and thread-safe (record types — immutability guarantees thread safety)." No additional runtime thread-safety test needed for data-only types. |
| 10 | COM-5a-1 through COM-5a-3 only documented, not tested | Corrected. WP-0.7 now includes a JSON serialization round-trip test verifying forward compatibility (unknown fields tolerated) and backward compatibility (missing optional fields tolerated). Structural enforcement at Phase 0; full Akka serialization testing in Phase 1/3A. |
Step 2: Negative Requirement Review
Not submitted separately — negative requirements were reviewed as part of Step 1 findings. All negative requirement acceptance criteria were evaluated as adequate by Codex (no findings on negative tests specifically).
Step 3: Split-Section Gap Review
Phase 0 covers HighLevelReqs 13.1 exclusively (not split). No split-section review needed for this phase.
Outcome: Pass with corrections. All 10 findings addressed (7 corrected, 3 dismissed with rationale).