From 9cff87fe85468dad57c08d1be5768150ac357ad2 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Tue, 7 Jul 2026 11:03:26 -0400 Subject: [PATCH] docs(comments): strip internal task/milestone/bundle bookkeeping from code comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove project bookkeeping citations from shipped code comments across the solution: hyphenated task IDs (WP-14, StoreAndForward-025), milestone/task/ issue refs (M3, Task 4, Audit Log #23, #21), Bundle X task-bundle labels, and C/D/K/S/T phase labels. Comment text only — no code logic, string/log literals, or XML-doc structure changed. Genuine descriptions are preserved (only the citation is stripped), and technical lookalikes are retained (UTF-8, SHA-256, T00:00:00, M365, UTC-5, pre-C4/pre-C5 schema versions). Flagged by the new CommentChecker TaskReferenceInComment / TrackingReferenceInComment checks plus targeted grep passes; full solution builds clean, append-only guard tests pass. --- .../Central/AuditCentralHealthSnapshot.cs | 2 +- .../Central/AuditLogIngestActor.cs | 26 +- .../AuditLogPartitionMaintenanceOptions.cs | 2 +- .../AuditLogPartitionMaintenanceService.cs | 7 +- .../Central/AuditLogPurgeActor.cs | 14 +- .../Central/AuditLogPurgeOptions.cs | 6 +- .../Central/AuditLogPurgedEvent.cs | 4 +- .../CentralAuditRedactionFailureCounter.cs | 6 +- .../Central/CentralAuditWriter.cs | 22 +- .../Central/GrpcPullAuditEventsClient.cs | 2 +- .../Central/GrpcPullSiteCallsClient.cs | 2 +- .../Central/IAuditCentralHealthSnapshot.cs | 6 +- .../IAuditInboundCeilingHitsCounter.cs | 2 +- .../ICentralAuditWriteFailureCounter.cs | 4 +- .../Central/IPullSiteCallsClient.cs | 2 +- .../Central/SiteAuditReconciliationActor.cs | 27 +- .../Central/SiteAuditReconciliationOptions.cs | 4 +- .../SiteAuditTelemetryStalledTracker.cs | 4 +- .../Configuration/AuditLogOptions.cs | 4 +- .../Configuration/AuditLogOptionsValidator.cs | 4 +- .../PerTargetRedactionOverride.cs | 2 +- .../Kpi/AuditLogKpiSampleSource.cs | 4 +- .../Payload/AuditRedactionPrimitives.cs | 4 +- .../Payload/AuditRegexCache.cs | 2 +- .../Payload/IAuditRedactionFailureCounter.cs | 2 +- .../NoOpAuditRedactionFailureCounter.cs | 4 +- .../ServiceCollectionExtensions.cs | 94 ++++--- .../Site/FallbackAuditWriter.cs | 10 +- ...althMetricsAuditRedactionFailureCounter.cs | 15 +- .../HealthMetricsAuditWriteFailureCounter.cs | 2 +- .../Site/IAuditWriteFailureCounter.cs | 2 +- .../Site/NoOpAuditWriteFailureCounter.cs | 4 +- .../Site/RingBufferFallback.cs | 2 +- .../Site/SiteAuditBacklogReporter.cs | 4 +- .../Site/SqliteAuditWriter.cs | 60 ++--- .../Telemetry/CachedCallLifecycleBridge.cs | 22 +- .../Telemetry/CachedCallTelemetryForwarder.cs | 18 +- .../Telemetry/ClusterClientSiteAuditClient.cs | 4 +- .../Site/Telemetry/ISiteStreamAuditClient.cs | 2 +- .../Site/Telemetry/SiteAuditTelemetryActor.cs | 22 +- .../Telemetry/SiteAuditTelemetryOptions.cs | 2 +- .../ZB.MOM.WW.ScadaBridge.AuditLog.csproj | 2 +- .../AlarmTriggerConfigJson.cs | 4 +- src/ZB.MOM.WW.ScadaBridge.CLI/CliConfig.cs | 2 +- .../Commands/AuditBackfillHelpers.cs | 4 +- .../Commands/AuditCommands.cs | 6 +- .../Commands/AuditExportHelpers.cs | 4 +- .../Commands/AuditFormatter.cs | 2 +- .../Commands/AuditLogCommands.cs | 4 +- .../Commands/AuditQueryHelpers.cs | 4 +- .../Commands/BundleCommands.cs | 20 +- .../Commands/CommandHelpers.cs | 10 +- .../Commands/DebugCommands.cs | 6 +- .../Commands/DebugStreamHelpers.cs | 4 +- .../Commands/TableAuditFormatter.cs | 4 +- .../Commands/TemplateCommands.cs | 10 +- .../Commands/TemplateTableProjection.cs | 2 +- .../ManagementHttpClient.cs | 2 +- src/ZB.MOM.WW.ScadaBridge.CLI/Program.cs | 2 +- .../Audit/AuditExportEndpoints.cs | 4 +- .../Auth/AuthEndpoints.cs | 18 +- .../Auth/ClaimsPrincipalExtensions.cs | 4 +- .../Auth/CookieAuthenticationStateProvider.cs | 2 +- .../Auth/SiteScopeService.cs | 4 +- .../Audit/AuditDrilldownDrawer.razor | 2 +- .../Audit/AuditDrilldownDrawer.razor.cs | 2 +- .../Components/Audit/AuditEventDetail.razor | 2 +- .../Audit/AuditEventDetail.razor.cs | 8 +- .../Components/Audit/AuditFilterBar.razor.cs | 6 +- .../Components/Audit/AuditQueryModel.cs | 2 +- .../Audit/AuditResultsGrid.razor.cs | 12 +- .../Audit/ExecutionDetailModal.razor.cs | 4 +- .../Components/Audit/ExecutionTree.razor.cs | 2 +- .../Components/BrowserTime.cs | 2 +- .../Dialogs/NodeBrowserDialog.razor | 8 +- .../Forms/OpcUaEndpointEditor.razor | 4 +- .../Components/Health/AuditKpiTiles.razor | 2 +- .../Components/Health/AuditKpiTiles.razor.cs | 6 +- .../Components/Health/SiteCallKpiTiles.razor | 2 +- .../Health/SiteCallKpiTiles.razor.cs | 4 +- .../Components/Layout/MainLayout.razor | 2 +- .../Components/Layout/NavMenu.razor | 5 +- .../Components/Pages/Admin/ApiKeyForm.razor | 4 +- .../Components/Pages/Admin/ApiKeys.razor | 2 +- .../Components/Pages/Admin/SiteForm.razor | 2 +- .../Components/Pages/Audit/AuditLogPage.razor | 14 +- .../Pages/Audit/AuditLogPage.razor.cs | 25 +- .../Pages/Audit/ConfigurationAuditLog.razor | 6 +- .../Pages/Audit/ExecutionTreePage.razor.cs | 4 +- .../Pages/Deployment/DebugTreeBuilder.cs | 4 +- .../Pages/Deployment/DebugTreeNode.cs | 6 +- .../Pages/Deployment/InstanceConfigure.razor | 8 +- .../Deployment/InstanceConfigure.razor.cs | 2 +- .../Pages/Design/ApiMethodForm.razor | 2 +- .../Pages/Design/DataConnections.razor | 6 +- .../Pages/Design/ExternalSystemForm.razor | 2 +- .../Pages/Design/SchemaLibrary.razor | 4 +- .../Pages/Design/TemplateEdit.razor | 8 +- .../Components/Pages/Design/Templates.razor | 4 +- .../Pages/Design/TransportExport.razor | 8 +- .../Pages/Design/TransportExport.razor.cs | 30 +-- .../Pages/Design/TransportImport.razor.cs | 28 +- .../Components/Pages/Monitoring/Health.razor | 14 +- .../Notifications/NotificationKpis.razor | 10 +- .../Notifications/NotificationReport.razor | 2 +- .../Pages/Operations/SecuredWrites.razor | 2 +- .../Pages/SiteCalls/SiteCallsReport.razor | 2 +- .../Pages/SiteCalls/SiteCallsReport.razor.cs | 16 +- .../Shared/AlarmTriggerConfigCodec.cs | 6 +- .../Shared/AlarmTriggerEditor.razor | 6 +- .../Components/Shared/DarkModeToggle.razor | 2 +- .../Components/Shared/DialogService.cs | 2 +- .../Components/Shared/KpiTrendChart.razor | 2 +- .../Components/Shared/KpiTrendChart.razor.cs | 4 +- .../Components/Shared/OffsetPager.razor | 2 +- .../Components/Shared/PagerWindow.cs | 2 +- .../Shared/ScriptTriggerConfigCodec.cs | 6 +- .../Shared/ScriptTriggerEditor.razor | 6 +- .../Components/Shared/TemplateTreeNode.cs | 2 +- .../ScriptAnalysis/InboundScriptHost.cs | 2 +- .../ScriptAnalysis/SandboxConsoleCapture.cs | 4 +- .../ScriptAnalysis/SandboxScriptHost.cs | 2 +- .../ScriptAnalysis/ScriptAnalysisService.cs | 16 +- .../ServiceCollectionExtensions.cs | 34 +-- .../Services/AlarmSummaryService.cs | 2 +- .../Services/ApiMethodKeyScopeReconciler.cs | 2 +- .../Services/AuditEventView.cs | 4 +- .../Services/AuditLogExportService.cs | 4 +- .../Services/AuditLogQueryService.cs | 10 +- .../Services/CertManagementService.cs | 8 +- .../Services/IAlarmSummaryService.cs | 2 +- .../Services/IAuditLogQueryService.cs | 10 +- .../Services/ICertManagementService.cs | 4 +- .../Services/IConnectionHealthQueryService.cs | 2 +- .../Services/IDataConnectionMoveService.cs | 2 +- .../Services/IKpiHistoryQueryService.cs | 2 +- .../Services/ISchemaLibraryQueryService.cs | 4 +- .../Services/ISchemaLibraryService.cs | 2 +- .../Services/ISecuredWriteService.cs | 4 +- .../ITemplateInheritanceQueryService.cs | 4 +- .../Services/KpiHistoryQueryService.cs | 2 +- .../Services/SchemaLibraryQueryService.cs | 2 +- .../ZB.MOM.WW.ScadaBridge.CentralUI.csproj | 4 +- .../ClusterOptions.cs | 2 +- .../ClusterOptionsValidator.cs | 4 +- .../ServiceCollectionExtensions.cs | 6 +- .../Entities/Audit/SiteCall.cs | 2 +- .../Deployment/DeployedConfigSnapshot.cs | 2 +- .../Entities/Deployment/DeploymentRecord.cs | 2 +- .../Entities/Kpi/KpiSample.cs | 2 +- .../Entities/Notifications/Notification.cs | 4 +- .../Entities/Schemas/SharedSchema.cs | 8 +- .../SecuredWrites/PendingSecuredWrite.cs | 2 +- .../Interfaces/Kpi/IKpiSampleSource.cs | 2 +- .../Protocol/IAddressSpaceSearchable.cs | 2 +- .../Repositories/IAuditLogRepository.cs | 14 +- .../IDeploymentManagerRepository.cs | 2 +- .../Repositories/IExternalSystemRepository.cs | 7 +- .../Repositories/IInboundApiRepository.cs | 2 +- .../Repositories/IKpiHistoryRepository.cs | 2 +- .../Repositories/ISecuredWriteRepository.cs | 10 +- .../Repositories/ISharedSchemaRepository.cs | 6 +- .../Repositories/ISiteCallAuditRepository.cs | 6 +- .../Repositories/ITemplateEngineRepository.cs | 4 +- .../Interfaces/Services/IAuditWriter.cs | 4 +- .../Services/ICachedCallLifecycleObserver.cs | 14 +- .../Services/ICachedCallTelemetryForwarder.cs | 6 +- .../Interfaces/Services/IDatabaseGateway.cs | 12 +- .../Services/IExternalSystemClient.cs | 14 +- .../Services/IOperationTrackingStore.cs | 6 +- .../Services/IPartitionMaintenance.cs | 6 +- .../Interfaces/Services/ISiteAuditQueue.cs | 16 +- .../Transport/IAuditCorrelationContext.cs | 2 +- .../Interfaces/Transport/IBundleImporter.cs | 2 +- .../Transport/IStaleInstanceProbe.cs | 2 +- .../Audit/IngestAuditEventsCommand.cs | 4 +- .../Audit/IngestCachedTelemetryCommand.cs | 4 +- .../Messages/Audit/SiteCallQueries.cs | 2 +- .../Messages/Audit/SiteCallRelayMessages.cs | 2 +- .../Messages/Audit/UpsertSiteCallCommand.cs | 7 +- .../Messages/Audit/UpsertSiteCallReply.cs | 3 +- .../Messages/DebugView/DebugViewSnapshot.cs | 4 +- .../Messages/Health/SiteHealthReport.cs | 8 +- .../InboundApi/RouteToInstanceRequest.cs | 8 +- .../Integration/AuditTelemetryEnvelope.cs | 2 +- .../Integration/CachedCallTelemetry.cs | 12 +- .../Integration/PullAuditEventsRequest.cs | 2 +- .../Integration/PullAuditEventsResponse.cs | 2 +- .../Integration/PullSiteCallsResponse.cs | 2 +- .../Messages/Management/CertTrustCommands.cs | 4 +- .../Management/SchemaLibraryCommands.cs | 4 +- .../Management/SecuredWriteCommands.cs | 8 +- .../Messages/Management/TemplateCommands.cs | 6 +- .../Messages/Management/TransportCommands.cs | 14 +- .../Notification/NotificationMessages.cs | 4 +- .../ScriptExecution/ScriptCallRequest.cs | 2 +- .../Types/Audit/AuditDetails.cs | 2 +- .../Types/Audit/AuditDetailsCodec.cs | 1 - .../Types/Audit/AuditFieldBuilders.cs | 1 - .../Types/Audit/AuditOutcomeProjector.cs | 1 - .../Types/Audit/AuditRowProjection.cs | 9 +- .../Audit/ScadaBridgeAuditEventFactory.cs | 4 +- .../Types/Audit/SiteCallKpiSnapshot.cs | 2 +- .../Types/AuditLogKpiSnapshot.cs | 2 +- .../Types/Enums/AuditChannel.cs | 2 +- .../Types/Enums/AuditForwardState.cs | 2 +- .../Types/Enums/AuditKind.cs | 2 +- .../Types/Enums/AuditStatus.cs | 2 +- .../Types/Enums/StoreAndForwardCategory.cs | 2 +- .../Enums/StoreAndForwardMessageStatus.cs | 2 +- .../Types/Flattening/ConfigurationDiff.cs | 2 +- .../Types/Flattening/ValidationResult.cs | 4 +- .../Types/InboundApi/InboundApiSchema.cs | 14 +- .../Types/Kpi/KpiMetrics.cs | 10 +- .../Types/Kpi/KpiScopes.cs | 2 +- .../Types/Kpi/KpiSeriesBucketer.cs | 2 +- .../Types/Kpi/KpiSeriesPoint.cs | 2 +- .../Types/Kpi/KpiSources.cs | 10 +- .../Types/ScriptParameters.cs | 2 +- .../Types/SiteAuditBacklogSnapshot.cs | 2 +- .../Types/SiteCallOperational.cs | 2 +- .../Types/TrackedOperationId.cs | 2 +- .../Types/TrackingStatusSnapshot.cs | 4 +- .../Types/Transport/BundleNameMap.cs | 2 +- .../Types/Transport/BundleSession.cs | 2 +- .../Types/Transport/BundleSummary.cs | 6 +- .../Types/Transport/EncryptionMetadata.cs | 2 +- .../Types/Transport/ExportSelection.cs | 12 +- .../Types/Transport/ImportPreview.cs | 12 +- .../Types/Transport/ImportResult.cs | 2 +- .../Actors/CentralCommunicationActor.cs | 36 +-- .../Actors/DebugStreamBridgeActor.cs | 24 +- .../Actors/SiteCommunicationActor.cs | 28 +- .../CommunicationService.cs | 14 +- .../Grpc/AuditEventDtoMapper.cs | 6 +- .../Grpc/SiteCallDtoMapper.cs | 6 +- .../Grpc/SiteStreamGrpcClientFactory.cs | 4 +- .../Grpc/SiteStreamGrpcServer.cs | 30 +-- .../AuditLogEntityTypeConfiguration.cs | 4 +- .../Configurations/InboundApiConfiguration.cs | 2 +- .../KpiSampleEntityTypeConfiguration.cs | 4 +- .../NotificationConfiguration.cs | 2 +- .../NotificationOutboxConfiguration.cs | 8 +- ...dingSecuredWriteEntityTypeConfiguration.cs | 2 +- .../Configurations/SecurityConfiguration.cs | 2 +- .../SharedSchemaConfiguration.cs | 4 +- .../SiteCallEntityTypeConfiguration.cs | 6 +- .../Configurations/TemplateConfiguration.cs | 2 +- .../Entities/AuditLogRow.cs | 4 +- .../AuditLogPartitionMaintenance.cs | 2 +- .../20260520142214_AddAuditLogTable.cs | 8 +- ...60602174346_CollapseAuditLogToCanonical.cs | 2 +- .../20260619135543_AddSmsNotifications.cs | 2 +- .../Repositories/AuditLogRepository.cs | 22 +- .../DeploymentManagerRepository.cs | 6 +- .../Repositories/ExternalSystemRepository.cs | 6 +- .../Repositories/KpiHistoryRepository.cs | 2 +- .../NotificationOutboxRepository.cs | 2 +- .../Repositories/SecuredWriteRepository.cs | 2 +- .../Repositories/SharedSchemaRepository.cs | 2 +- .../Repositories/SiteCallAuditRepository.cs | 6 +- .../Repositories/TemplateEngineRepository.cs | 2 +- .../ScadaBridgeDbContext.cs | 10 +- .../ServiceCollectionExtensions.cs | 4 +- .../Services/AuditCorrelationContext.cs | 2 +- .../Actors/DataConnectionActor.cs | 160 ++++++------ .../Actors/DataConnectionManagerActor.cs | 8 +- .../Adapters/IOpcUaClient.cs | 10 +- .../Adapters/MxGatewayDataConnection.cs | 4 +- .../Adapters/OpcUaAlarmMapper.cs | 2 +- .../Adapters/OpcUaDataConnection.cs | 16 +- .../Adapters/RealOpcUaClient.cs | 50 ++-- .../AlarmConditionFilter.cs | 2 +- .../DataConnectionFactory.cs | 6 +- .../DataConnectionOptions.cs | 8 +- .../IDataConnectionFactory.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../ArtifactDeploymentService.cs | 40 +-- .../DeploymentManagerOptions.cs | 6 +- .../DeploymentService.cs | 128 +++++----- .../DeploymentStatusNotifier.cs | 2 +- .../FlatteningPipeline.cs | 8 +- .../IDeploymentStatusNotifier.cs | 2 +- .../OperationLockManager.cs | 6 +- .../ServiceCollectionExtensions.cs | 6 +- .../StateTransitionValidator.cs | 6 +- .../DatabaseGateway.cs | 60 +++-- .../ErrorClassifier.cs | 2 +- .../ExternalSystemClient.cs | 56 ++-- .../ServiceCollectionExtensions.cs | 6 +- .../SqlErrorClassifier.cs | 4 +- .../CentralHealthAggregator.cs | 2 +- .../CentralHealthReportLoop.cs | 10 +- .../HealthMonitoringOptionsValidator.cs | 2 +- .../HealthReportSender.cs | 5 +- .../ISiteHealthCollector.cs | 10 +- .../Kpi/SiteHealthKpiSampleSource.cs | 12 +- .../ServiceCollectionExtensions.cs | 8 +- .../SiteEventLogFailureCountReporter.cs | 2 +- .../SiteHealthCollector.cs | 2 +- .../Actors/AkkaHostedService.cs | 90 +++---- .../Components/App.razor | 2 +- .../Health/ActiveNodeGate.cs | 2 +- .../Health/RequiredSingletonsHealthCheck.cs | 2 +- .../LoggerConfigurationFactory.cs | 14 +- src/ZB.MOM.WW.ScadaBridge.Host/Program.cs | 62 ++--- .../SiteServiceRegistration.cs | 18 +- .../StartupRetry.cs | 10 +- .../StartupValidator.cs | 10 +- .../StoreAndForwardSiteContext.cs | 2 +- .../EndpointExtensions.cs | 36 +-- .../ForbiddenApiChecker.cs | 10 +- .../IActiveNodeGate.cs | 2 +- .../IInstanceRouter.cs | 2 +- .../InboundApiEndpointFilter.cs | 8 +- .../InboundApiOptions.cs | 6 +- .../InboundDatabaseHelper.cs | 10 +- .../InboundScriptExecutor.cs | 50 ++-- .../Middleware/AuditWriteMiddleware.cs | 38 +-- .../ParameterValidator.cs | 14 +- .../ReturnValueValidator.cs | 8 +- .../RouteHelper.cs | 34 +-- .../SchemaRefResolver.cs | 2 +- .../ServiceCollectionExtensions.cs | 6 +- .../KpiHistoryOptions.cs | 2 +- .../KpiHistoryRecorderActor.cs | 6 +- .../ServiceCollectionExtensions.cs | 10 +- .../ZB.MOM.WW.ScadaBridge.KpiHistory.csproj | 2 +- .../AuditEndpoints.cs | 14 +- .../AuditExportRow.cs | 4 +- .../ManagementActor.cs | 132 +++++----- .../ManagementEndpoints.cs | 8 +- .../EmailNotificationDeliveryAdapter.cs | 16 +- .../SmsNotificationDeliveryAdapter.cs | 8 +- .../Kpi/NotificationOutboxKpiSampleSource.cs | 6 +- .../NotificationOutboxActor.cs | 52 ++-- .../ServiceCollectionExtensions.cs | 4 +- ...M.WW.ScadaBridge.NotificationOutbox.csproj | 2 +- .../CredentialRedactor.cs | 6 +- .../EmailAddressValidator.cs | 2 +- .../ISmtpClientWrapper.cs | 8 +- .../MailKitSmtpClientWrapper.cs | 16 +- .../NotificationOptions.cs | 2 +- .../OAuth2TokenService.cs | 10 +- .../ServiceCollectionExtensions.cs | 2 +- .../SmtpErrorClassifier.cs | 6 +- .../SmtpTlsMode.cs | 4 +- .../RoslynScriptCompiler.cs | 2 +- .../ScriptCompileSurface.cs | 4 +- .../ScriptTrustPolicy.cs | 14 +- .../ScriptTrustValidator.cs | 6 +- .../TriggerCompileSurface.cs | 4 +- .../AuthorizationPolicies.cs | 19 +- .../CookieSessionValidator.cs | 2 +- .../JwtTokenService.cs | 6 +- .../LdapAuthFailureMessages.cs | 6 +- .../RoleMapper.cs | 4 +- src/ZB.MOM.WW.ScadaBridge.Security/Roles.cs | 12 +- .../ScadaBridgeGroupRoleMapper.cs | 2 +- .../SecurityOptions.cs | 6 +- .../ServiceCollectionExtensions.cs | 20 +- .../SessionClaimBuilder.cs | 8 +- .../ZB.MOM.WW.ScadaBridge.Security.csproj | 2 +- .../Kpi/SiteCallAuditKpiSampleSource.cs | 8 +- .../ServiceCollectionExtensions.cs | 8 +- .../SiteCallAuditActor.cs | 54 ++-- .../SiteCallAuditOptions.cs | 10 +- ...ZB.MOM.WW.ScadaBridge.SiteCallAudit.csproj | 2 +- .../EventLogPurgeService.cs | 6 +- .../EventLogQueryService.cs | 12 +- .../ISiteEventLogger.cs | 4 +- .../ServiceCollectionExtensions.cs | 2 +- .../SiteEventLogOptions.cs | 4 +- .../SiteEventLogger.cs | 20 +- .../Actors/AlarmActor.cs | 44 ++-- .../Actors/AlarmExecutionActor.cs | 22 +- .../Actors/CertStoreActor.cs | 4 +- .../Actors/DeploymentManagerActor.cs | 137 +++++----- .../Actors/InstanceActor.cs | 96 +++---- .../Actors/NativeAlarmActor.cs | 24 +- .../Actors/ScriptActor.cs | 20 +- .../Actors/ScriptExecutionActor.cs | 46 ++-- .../Actors/SiteReplicationActor.cs | 8 +- .../Messages/NativeAlarmDropped.cs | 2 +- .../Persistence/SiteStorageService.cs | 20 +- .../SiteExternalSystemRepository.cs | 4 +- .../SiteNotificationRepository.cs | 4 +- .../Repositories/SyntheticId.cs | 2 +- .../Scripts/AuditingDbCommand.cs | 22 +- .../Scripts/AuditingDbConnection.cs | 10 +- .../Scripts/AuditingDbDataReader.cs | 4 +- .../Scripts/ScopeAccessors.cs | 4 +- .../Scripts/ScriptCompilationService.cs | 8 +- .../Scripts/ScriptExecutionScheduler.cs | 2 +- .../Scripts/ScriptRuntimeContext.cs | 221 ++++++++-------- .../Scripts/SharedScriptLibrary.cs | 4 +- .../ServiceCollectionExtensions.cs | 6 +- .../SiteRuntimeOptions.cs | 2 +- .../Streaming/SiteStreamManager.cs | 6 +- .../Tracking/OperationTrackingOptions.cs | 2 +- .../Tracking/OperationTrackingStore.cs | 19 +- .../ZB.MOM.WW.ScadaBridge.SiteRuntime.csproj | 2 +- .../IStoreAndForwardSiteContext.cs | 4 +- .../NotificationForwarder.cs | 16 +- .../ParkedMessageHandlerActor.cs | 9 +- .../ReplicationService.cs | 22 +- .../ServiceCollectionExtensions.cs | 11 +- .../StoreAndForwardMessage.cs | 13 +- .../StoreAndForwardOptions.cs | 24 +- .../StoreAndForwardService.cs | 240 +++++------------- .../StoreAndForwardStorage.cs | 72 ++---- .../CollisionDetector.cs | 4 +- .../Flattening/DiffService.cs | 6 +- .../Flattening/FlatteningService.cs | 2 +- .../Flattening/RevisionHashService.cs | 6 +- .../LockEnforcer.cs | 4 +- .../Services/TemplateDeletionService.cs | 6 +- .../SharedScriptService.cs | 4 +- .../TemplateInheritanceResolver.cs | 2 +- .../TemplateResolver.cs | 4 +- .../TemplateService.cs | 82 +++--- .../Validation/ScriptCompiler.cs | 2 +- .../Validation/SemanticValidator.cs | 18 +- .../Validation/ValidationService.cs | 20 +- .../Export/BundleExporter.cs | 12 +- .../Export/DependencyResolver.cs | 22 +- .../Export/ResolvedExport.cs | 6 +- .../Import/ArtifactDiff.cs | 20 +- .../Import/BundleImporter.cs | 90 +++---- .../BundleUnlockRateLimitedException.cs | 2 +- .../Import/BundleUnlockRateLimiter.cs | 2 +- .../Serialization/BundleJsonOptions.cs | 2 +- .../Serialization/EntityDtos.cs | 31 +-- .../Serialization/EntitySerializer.cs | 24 +- .../Serialization/ManifestBuilder.cs | 2 +- 435 files changed, 2338 insertions(+), 2547 deletions(-) diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditCentralHealthSnapshot.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditCentralHealthSnapshot.cs index 68b6a814..e5ab7fb8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditCentralHealthSnapshot.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditCentralHealthSnapshot.cs @@ -4,7 +4,7 @@ using ZB.MOM.WW.ScadaBridge.AuditLog.Payload; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Audit Log (#23) M6 Bundle E (T8, T9) — central singleton implementation of +/// Central singleton implementation of /// . Owns thread-safe /// counters for /// CentralAuditWriteFailures + AuditRedactionFailure and a diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogIngestActor.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogIngestActor.cs index 8b800e61..725c0e81 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogIngestActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogIngestActor.cs @@ -71,7 +71,7 @@ public class AuditLogIngestActor : ReceiveActor _logger = logger; ReceiveAsync(OnIngestAsync); - // The single-repository test ctor cannot service the M3 dual-write — + // The single-repository test ctor cannot service the dual-write — // it has no SiteCalls repo and no DbContext. The handler still // registers (so callers don't dead-letter) but replies empty so the // test surface stays explicit about what this ctor supports. @@ -125,7 +125,7 @@ public class AuditLogIngestActor : ReceiveActor // InsertIfNotExistsAsync. The single-repository test ctor has no // service provider — it falls through with no redactor, which preserves // the small-payload assumptions baked into the existing fixtures. - // AuditLog-003: use CreateAsyncScope + await using so scoped EF Core + // Use CreateAsyncScope + await using so scoped EF Core // services (IAsyncDisposable DbContexts) dispose asynchronously // without blocking on sync Dispose() of pending connection cleanup. if (_injectedRepository is not null) @@ -135,7 +135,7 @@ public class AuditLogIngestActor : ReceiveActor } else { - // AuditLog-014: guard scope-creation + repository resolution in a + // Guard scope-creation + repository resolution in a // try/catch, mirroring OnCachedTelemetryAsync. A transient DI / // DbContext-factory fault (pooled-context init, SQL-connection // exhaustion, a resolution race during host churn) would otherwise @@ -151,7 +151,7 @@ public class AuditLogIngestActor : ReceiveActor await using var scope = _serviceProvider!.CreateAsyncScope(); var repository = scope.ServiceProvider.GetRequiredService(); var redactor = scope.ServiceProvider.GetService(); - // M6 Bundle E (T8): central health counter is best-effort — + // Central health counter is best-effort — // unregistered (test composition roots) means the per-row catch // simply logs without surfacing on the health dashboard. var failureCounter = scope.ServiceProvider.GetService(); @@ -194,11 +194,11 @@ public class AuditLogIngestActor : ReceiveActor // retry, reconciliation) is a silent no-op. // Redact BEFORE the IngestedAtUtc stamp so the redacted // copy carries the central-side ingest timestamp. The redactor - // is contract-bound to never throw. AuditLog-008: a null + // is contract-bound to never throw. A null // redactor (test composition root, no IAuditRedactor // registered) now falls back to the SafeDefault rather than // pass-through, so HTTP header redaction always runs. - // C3 transitional shim: IngestedAtUtc is a DetailsJson field on + // IngestedAtUtc is a DetailsJson field on // the canonical record, so stamp it via the projection helper. var safeRedactor = redactor ?? SafeDefaultAuditRedactor.Instance; var filtered = safeRedactor.Apply(evt); @@ -210,7 +210,7 @@ public class AuditLogIngestActor : ReceiveActor { // Per-row catch — one bad row never sinks the whole batch. // The row stays Pending at the site; the next drain retries. - // M6 Bundle E (T8): bump the central health counter so a + // Bump the central health counter so a // sustained insert-throw failure surfaces on the dashboard. try { failureCounter?.Increment(); } catch { /* counter must never throw — defence in depth */ } @@ -222,7 +222,7 @@ public class AuditLogIngestActor : ReceiveActor } /// - /// M3 dual-write handler. For every the + /// Dual-write handler. For every the /// actor opens a fresh MS SQL transaction, inserts the AuditLog row /// idempotently AND upserts the SiteCalls row monotonically. Both succeed /// or both roll back, so the audit and operational mirrors never drift @@ -248,13 +248,13 @@ public class AuditLogIngestActor : ReceiveActor var auditRepo = scope.ServiceProvider.GetRequiredService(); var siteCallRepo = scope.ServiceProvider.GetRequiredService(); var dbContext = scope.ServiceProvider.GetRequiredService(); - // Bundle C (M5-T6): resolve the redactor for the whole batch from + // Resolve the redactor for the whole batch from // the scope; null = SafeDefault for test composition roots that // skip the redactor registration. The redactor is contract-bound to // never throw, so we can apply it inside the per-entry try // without risking an unbounded blast radius. var redactor = scope.ServiceProvider.GetService(); - // M6 Bundle E (T8): same best-effort central health counter as + // Same best-effort central health counter as // the OnIngestAsync path — null on test composition roots that // skip the registration. var failureCounter = scope.ServiceProvider.GetService(); @@ -275,9 +275,9 @@ public class AuditLogIngestActor : ReceiveActor // Redact the audit half BEFORE the dual-write — only the // AuditLog row's payload columns are redactable; SiteCalls // carries operational state only (status, retry count) and - // is left untouched. AuditLog-008: null redactor falls back + // is left untouched. Null redactor falls back // to SafeDefault so header redaction always runs. - // C3 transitional shim: IngestedAtUtc is a DetailsJson field + // IngestedAtUtc is a DetailsJson field // on the canonical record, so stamp it via the projection helper. var safeRedactor = redactor ?? SafeDefaultAuditRedactor.Instance; var filteredAudit = safeRedactor.Apply(entry.Audit); @@ -298,7 +298,7 @@ public class AuditLogIngestActor : ReceiveActor // EventId is NOT added to `accepted` so the site keeps its // row Pending and retries on the next drain. Other entries // in the batch continue with their own transactions. - // M6 Bundle E (T8): bump the central health counter so a + // Bump the central health counter so a // sustained dual-write failure surfaces on the dashboard. try { failureCounter?.Increment(); } catch { /* counter must never throw — defence in depth */ } diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceOptions.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceOptions.cs index c7ef0892..defa12cb 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceOptions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceOptions.cs @@ -2,7 +2,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// Tuning knobs for the central -/// hosted service (M6-T5). +/// hosted service. /// Defaults: once every 24 hours, keep at least one future monthly /// boundary ahead of . /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs index dd000050..3a113436 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs @@ -7,7 +7,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Interfaces; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Central (M6-T5, Bundle D) that rolls +/// Central that rolls /// pf_AuditLog_Month forward once a day. Each tick opens a fresh DI /// scope, resolves , and calls /// to SPLIT any @@ -19,7 +19,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// /// -/// Why a hosted service, not an actor. Bundle C's +/// Why a hosted service, not an actor. /// sits inside the central singleton /// because it needs supervised lifecycle alongside the rest of the /// reconciliation / ingest pipeline. Roll-forward is genuinely a once-a-day @@ -33,8 +33,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// Failure containment. The tick body wraps the maintenance call in /// a try/catch so a transient SQL Server error never tears down the hosted /// service — the next tick simply retries. The exception is logged with -/// the original stack trace at Error level; ops surfaces (M6 Bundle -/// E's central health collector) can subscribe to the logger to alert on +/// the original stack trace at Error level; ops surfaces can subscribe to the logger to alert on /// repeated failures. /// /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeActor.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeActor.cs index e9c9d5e1..bb0553c4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeActor.cs @@ -9,7 +9,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Central singleton (M6 Bundle C) that drives the daily AuditLog partition +/// Central singleton that drives the daily AuditLog partition /// purge. On a configurable timer (default 24 hours) the actor: /// /// Queries @@ -19,7 +19,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// which runs /// the drop-and-rebuild dance around UX_AuditLog_EventId. /// Publishes on the actor-system -/// EventStream so the Bundle E central health collector + ops surfaces +/// EventStream so the central health collector + ops surfaces /// can subscribe without coupling to this actor. /// /// @@ -51,8 +51,8 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// EventStream. Publishing through /// the EventStream rather than direct messaging avoids coupling this actor -/// to its consumers; M6 Bundle E will subscribe a central health-counter -/// bridge that surfaces purge progress on the central health report. +/// to its consumers; a central health-counter bridge will subscribe to +/// surface purge progress on the central health report. /// /// public class AuditLogPurgeActor : ReceiveActor @@ -134,7 +134,7 @@ public class AuditLogPurgeActor : ReceiveActor // restart. var threshold = DateTime.UtcNow - TimeSpan.FromDays(_auditOptions.RetentionDays); - // AuditLog-003: use CreateAsyncScope + await using so scoped EF Core + // Use CreateAsyncScope + await using so scoped EF Core // services (IAsyncDisposable DbContexts) dispose asynchronously // without blocking on sync Dispose() of pending connection cleanup. await using var scope = _services.CreateAsyncScope(); @@ -206,7 +206,7 @@ public class AuditLogPurgeActor : ReceiveActor } } - // M5.5 (T3): after the channel-blind global partition switch-out, apply any + // After the channel-blind global partition switch-out, apply any // per-channel retention overrides that are SHORTER than the global window via // a bounded, batched row DELETE on the same maintenance path. The global // switch-out has already dropped whole months older than RetentionDays; these @@ -216,7 +216,7 @@ public class AuditLogPurgeActor : ReceiveActor } /// - /// M5.5 (T3): runs each per-channel retention override whose window is strictly + /// Runs each per-channel retention override whose window is strictly /// shorter than the global , deleting /// rows of that channel older than the channel-specific threshold via a bounded, /// batched maintenance-path DELETE. Each channel runs inside its own try/catch so diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeOptions.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeOptions.cs index 4c931cd4..e49324bd 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeOptions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgeOptions.cs @@ -4,7 +4,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// Tuning knobs for the central singleton. -/// Default cadence is 24 hours per the M6 plan; the retention window itself +/// Default cadence is 24 hours; the retention window itself /// is sourced from /// (default 365) so operators tune retention from a single section. /// @@ -31,7 +31,7 @@ public sealed class AuditLogPurgeOptions public int IntervalHours { get; set; } = 24; /// - /// M5.5 (T3): batch size for the per-channel retention-override row DELETE + /// Batch size for the per-channel retention-override row DELETE /// (). /// Each DELETE TOP (@batch) caps the transaction-log and lock footprint /// per statement; the repository loops batches until no rows remain. Default @@ -40,7 +40,7 @@ public sealed class AuditLogPurgeOptions /// . /// /// - /// AuditLog-013: the operator-facing config key is ChannelPurgeBatchSize + /// The operator-facing config key is ChannelPurgeBatchSize /// (per Component-AuditLog.md), so the binder maps that documented key onto this /// backing property via . The unattributed /// property name (ChannelPurgeBatchSizeConfigured) would otherwise have been diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgedEvent.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgedEvent.cs index 1ba6f41d..709c9c1c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgedEvent.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPurgedEvent.cs @@ -2,8 +2,8 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// Published on the actor-system EventStream by -/// after each successful partition switch-out. Downstream consumers (Bundle E -/// central health collector, ops dashboards, audit trails) subscribe so a +/// after each successful partition switch-out. Downstream consumers (central +/// health collector, ops dashboards, audit trails) subscribe so a /// purge action is observable without the actor needing to know about any /// specific subscriber. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditRedactionFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditRedactionFailureCounter.cs index 2d01d49a..14bd64b0 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditRedactionFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditRedactionFailureCounter.cs @@ -3,7 +3,7 @@ using ZB.MOM.WW.ScadaBridge.AuditLog.Payload; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Audit Log (#23) M6 Bundle E (T9) — bridges +/// Bridges /// (incremented by /// every time /// a header / body / SQL parameter redactor stage throws and the redactor has @@ -13,11 +13,11 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// /// -/// Site vs central. M5 Bundle C wired the SITE-side bridge +/// Site vs central. Wired the SITE-side bridge /// (), /// which routes increments into the site health report payload's /// AuditRedactionFailure field. That handles redactor failures on the -/// site SQLite hot-path (FallbackAuditWriter). M6 Bundle E (T9) adds the +/// site SQLite hot-path (FallbackAuditWriter). Adds the /// MIRROR bridge here so the same payload filter — when it runs on the /// central / /// paths — surfaces its failures on the diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditWriter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditWriter.cs index 64ac7c69..bebe7b17 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditWriter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditWriter.cs @@ -47,22 +47,22 @@ public sealed class CentralAuditWriter : ICentralAuditWriter private readonly INodeIdentityProvider? _nodeIdentity; /// - /// Bundle C (M5-T6) — the central direct-write path used by the + /// The central direct-write path used by the /// NotificationOutboxActor dispatch and the Inbound API middleware also /// needs to truncate + redact before the row hits MS SQL. The filter is - /// optional so the M4 test composition roots that don't pass one keep + /// optional so test composition roots that don't pass one keep /// working (they only ever write small payloads); production DI registers /// the real filter via . - /// M6 Bundle E (T8) — adds the optional + /// Adds the optional /// so a swallowed repository /// throw bumps the central health surface's /// CentralAuditWriteFailures counter. Defaults to a NoOp so test /// composition roots that don't wire the counter keep their current - /// behaviour. SourceNode-stamping (Task 12) — adds the optional + /// behaviour. SourceNode-stamping — adds the optional /// so central-origin rows (Notification /// Outbox dispatch, Inbound API) carry the writing central node's /// identifier when the caller hasn't already supplied one. Optional / - /// defaulting-to-null so M4 test composition roots that don't pass a + /// defaulting-to-null so test composition roots that don't pass a /// provider keep working — the caller-wins discipline means an absent /// provider simply leaves SourceNode at whatever the caller set (often /// null, which is the legacy behaviour). @@ -81,8 +81,8 @@ public sealed class CentralAuditWriter : ICentralAuditWriter { _services = services ?? throw new ArgumentNullException(nameof(services)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - // AuditLog-008: never default to null — over-redact instead. - // C3 (Task 2.5): wired via the canonical IAuditRedactor seam. + // Never default to null — over-redact instead. + // Wired via the canonical IAuditRedactor seam. // SafeDefaultAuditRedactor applies HTTP header redaction with // hard-coded sensitive defaults so a composition root that omits the // real redactor still scrubs Authorization / X-Api-Key / Cookie / @@ -106,13 +106,13 @@ public sealed class CentralAuditWriter : ICentralAuditWriter try { // Redact BEFORE stamping IngestedAtUtc + handing to the repo. The - // redactor contract is "never throws". AuditLog-008: _redactor is + // redactor contract is "never throws". _redactor is // now non-null (SafeDefaultAuditRedactor fallback) so header // redaction always runs even in composition roots that omit the // real redactor. var filtered = _redactor.Apply(evt); - // SourceNode-stamping (Task 12): caller-provided value wins + // SourceNode-stamping: caller-provided value wins // (supports any future direct-write callsite that already has its // own node id); otherwise stamp from the local // INodeIdentityProvider, when one is wired. Production DI on @@ -126,7 +126,7 @@ public sealed class CentralAuditWriter : ICentralAuditWriter await using var scope = _services.CreateAsyncScope(); var repo = scope.ServiceProvider.GetRequiredService(); - // C3 transitional shim: IngestedAtUtc is a DetailsJson field on the + // IngestedAtUtc is a DetailsJson field on the // canonical record, so stamp it via the projection helper. var stamped = AuditRowProjection.WithIngestedAtUtc(filtered, DateTime.UtcNow); await repo.InsertIfNotExistsAsync(stamped, ct).ConfigureAwait(false); @@ -134,7 +134,7 @@ public sealed class CentralAuditWriter : ICentralAuditWriter catch (Exception ex) { // Audit failure NEVER aborts the user-facing action — swallow and log. - // M6 Bundle E (T8): also surface the failure on the central health + // Also surface the failure on the central health // counter so a sustained audit-write outage is visible on the // health dashboard rather than disappearing into the log file. try diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullAuditEventsClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullAuditEventsClient.cs index bad3e88f..6d7d3297 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullAuditEventsClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullAuditEventsClient.cs @@ -12,7 +12,7 @@ using PullAuditEventsResponse = ZB.MOM.WW.ScadaBridge.Commons.Messages.Integrati namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Production (Audit Log #23, M6) that the +/// Production that the /// central uses to pull the next /// reconciliation batch from a site over the PullAuditEvents unary gRPC /// RPC served by SiteStreamGrpcServer. diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullSiteCallsClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullSiteCallsClient.cs index 350ee1ac..0a468d23 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullSiteCallsClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/GrpcPullSiteCallsClient.cs @@ -13,7 +13,7 @@ using PullSiteCallsResponse = ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Production (Site Call Audit #22) that the +/// Production (Site Call Audit) that the /// central reconciliation tick (a separate follow-up component) uses to pull the /// next batch of cached-call operational rows from a site over the /// PullSiteCalls unary gRPC RPC served by SiteStreamGrpcServer. diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditCentralHealthSnapshot.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditCentralHealthSnapshot.cs index 89bb4675..64f74449 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditCentralHealthSnapshot.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditCentralHealthSnapshot.cs @@ -3,7 +3,7 @@ using ZB.MOM.WW.ScadaBridge.AuditLog.Payload; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Audit Log (#23) M6 Bundle E read-side surface exposing the central-side +/// Read-side surface exposing the central-side /// audit-health counters: (every /// repository insert throw from / /// ), @@ -15,7 +15,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// Read-only contract. Implementations expose a point-in-time snapshot /// — increments and tracker updates happen through the dedicated counter / -/// tracker interfaces, not through this surface. Consumers (M7+ central +/// tracker interfaces, not through this surface. Consumers (central /// health pages) read these properties; they never mutate. /// /// @@ -25,7 +25,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// failure / redaction-failure counters originate ON central (no site report /// carries them), so they live on a dedicated snapshot rather than being /// retro-fitted into a per-site state. The two surfaces will be composed at -/// the M7 dashboard layer. +/// the dashboard layer. /// /// public interface IAuditCentralHealthSnapshot diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditInboundCeilingHitsCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditInboundCeilingHitsCounter.cs index 8768a1c2..346da4e7 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditInboundCeilingHitsCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IAuditInboundCeilingHitsCounter.cs @@ -1,7 +1,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Audit Log (#23) M5.3 (T7) counter sink incremented by +/// Audit Log counter sink incremented by /// /// whenever an inbound request or response body is truncated at the /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ICentralAuditWriteFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ICentralAuditWriteFailureCounter.cs index 129695d4..0181a0c6 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ICentralAuditWriteFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ICentralAuditWriteFailureCounter.cs @@ -1,7 +1,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Audit Log (#23) M6 Bundle E (T8) counter sink invoked by central-side audit +/// Counter sink invoked by central-side audit /// writers (, ) /// every time a repository InsertIfNotExistsAsync throws. Mirrors the /// site-side @@ -14,7 +14,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// instead. A NoOp default is the correct safe fallback while the central /// health surface is being wired in; /// is the production binding that routes increments into the aggregated -/// central health snapshot consumed by future M7+ pages. +/// central health snapshot, to be consumed by future central health pages. /// public interface ICentralAuditWriteFailureCounter { diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullSiteCallsClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullSiteCallsClient.cs index c22d5706..74dc9601 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullSiteCallsClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullSiteCallsClient.cs @@ -4,7 +4,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// Mockable abstraction over the central-side PullSiteCalls gRPC client -/// surface used by the Site Call Audit (#22) reconciliation tick to fetch the +/// surface used by the Site Call Audit reconciliation tick to fetch the /// next batch of cached-call operational rows from a specific site — the /// documented periodic self-heal pull that backfills the eventually-consistent /// central SiteCalls mirror when best-effort push telemetry is lost. diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationActor.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationActor.cs index 8c6a297b..217aba01 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationActor.cs @@ -8,7 +8,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Central singleton (M6 Bundle B) that drives the audit-log reconciliation +/// Central singleton that drives the audit-log reconciliation /// pull loop. On a configurable timer (default 5 minutes) the actor walks every /// known site, asks the site for any rows with /// >= the site's last reconciled @@ -23,7 +23,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// missed push (gRPC blip, central restart, site offline) is eventually /// repaired by central re-pulling whatever the site still has in /// Pending/Forwarded state. Idempotency on -/// (M2 Bundle A's race-fix) makes duplicate +/// makes duplicate /// arrivals from both paths a silent no-op. /// /// @@ -33,7 +33,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// the cursors reset to . That is conservative /// but correct — the next tick simply asks for everything the site still has, /// and idempotent ingest swallows the dupes. Persisting cursors to MS SQL was -/// considered and rejected for M6: the cost of a write per tick outweighs the +/// considered and rejected: the cost of a write per tick outweighs the /// rare benefit of avoiding one over-broad pull after a restart. /// /// @@ -41,7 +41,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// consecutive pull cycles BOTH return non-empty AND MoreAvailable=true /// — i.e. the backlog isn't draining. The actor publishes /// on the actor system's -/// EventStream so a future ICentralHealthCollector bridge (M6 Bundle E) +/// EventStream so a future ICentralHealthCollector bridge /// can flip the health metric without coupling this actor to the health /// collection surface today. /// @@ -97,7 +97,7 @@ public class SiteAuditReconciliationActor : ReceiveActor private readonly Dictionary _stalled = new(); /// - /// AuditLog-004: per-EventId retry counter for rows whose central insert + /// Per-EventId retry counter for rows whose central insert /// threw. While a row keeps failing AND is below /// , the cursor is held back so the /// next reconciliation tick re-pulls and retries the row. Crossing the @@ -110,7 +110,7 @@ public class SiteAuditReconciliationActor : ReceiveActor private readonly Dictionary _failedInsertAttempts = new(); /// - /// AuditLog-004: number of consecutive central-insert failures before a row + /// Number of consecutive central-insert failures before a row /// is permanently abandoned with a Critical log entry and the cursor is /// allowed to advance past it. Five attempts at the 5-minute default tick /// is ~25 min of retry budget before a stuck row stops blocking progress. @@ -199,7 +199,7 @@ public class SiteAuditReconciliationActor : ReceiveActor return; } - // AuditLog-003: use CreateAsyncScope + await using so scoped EF Core + // Use CreateAsyncScope + await using so scoped EF Core // services (IAsyncDisposable DbContexts) dispose asynchronously // without blocking on sync Dispose() of pending connection cleanup. await using var scope = _services.CreateAsyncScope(); @@ -260,9 +260,8 @@ public class SiteAuditReconciliationActor : ReceiveActor { // Idempotent repository write: duplicate EventIds (from a // concurrent push, or a retry of this very pull) collapse to - // a no-op courtesy of M2 Bundle A's race-fix on - // InsertIfNotExistsAsync. - // C3: IngestedAtUtc is a DetailsJson field on the canonical record — + // a no-op on InsertIfNotExistsAsync. + // IngestedAtUtc is a DetailsJson field on the canonical record — // stamp it via the projection helper. var ingested = AuditRowProjection.WithIngestedAtUtc(evt, nowUtc); await repository.InsertIfNotExistsAsync(ingested).ConfigureAwait(false); @@ -271,7 +270,7 @@ public class SiteAuditReconciliationActor : ReceiveActor } catch (Exception ex) { - // AuditLog-004: per-row catch so one bad event does not abandon + // Per-row catch so one bad event does not abandon // the rest of the batch. Track the failure count per EventId — // below MaxPermanentInsertAttempts the cursor is HELD BACK so // the next tick re-pulls and retries; at the threshold the row @@ -305,7 +304,7 @@ public class SiteAuditReconciliationActor : ReceiveActor } } - // C3: canonical OccurredAtUtc is a DateTimeOffset; the cursor is a UTC DateTime. + // Canonical OccurredAtUtc is a DateTimeOffset; the cursor is a UTC DateTime. var occurredUtc = evt.OccurredAtUtc.UtcDateTime; if (advanceForThisRow && occurredUtc > maxOccurred) { @@ -313,7 +312,7 @@ public class SiteAuditReconciliationActor : ReceiveActor } } - // AuditLog-004: only advance the persisted cursor if no event in this + // Only advance the persisted cursor if no event in this // batch is still being retried. Leaving the cursor at `since` re-pulls // the whole batch next tick — successful rows are no-ops thanks to // InsertIfNotExistsAsync's idempotency, and the failing row gets @@ -388,7 +387,7 @@ public class SiteAuditReconciliationActor : ReceiveActor /// /// Published on the actor system EventStream when a site's reconciliation /// puller transitions into or out of the "stalled" state (backlog not -/// draining across multiple cycles). The M6 Bundle E central health collector +/// draining across multiple cycles). The central health collector /// will subscribe to this and surface /// SiteAuditTelemetryStalled on the health-report payload. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationOptions.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationOptions.cs index b58b3fb4..33ae7c06 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationOptions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditReconciliationOptions.cs @@ -2,13 +2,13 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// /// Tuning knobs for the central singleton. -/// Defaults mirror the M6 Bundle B brief: pull every 5 minutes per site, 256 rows per +/// Defaults: pull every 5 minutes per site, 256 rows per /// batch, declare a site "stalled" after two consecutive pull cycles return non-empty /// AND MoreAvailable=true (the backlog is not draining). /// /// /// -/// Per the M6 plan the reconciliation actor is the fallback when push telemetry is +/// The reconciliation actor is the fallback when push telemetry is /// lost; it is intentionally low-frequency. Lowering /// in production trades MS SQL load for /// fresher self-healing — keep the default unless a deployment can prove the extra diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs index 51ec202c..dbf2ffbc 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs @@ -5,10 +5,10 @@ using Akka.Event; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Central; /// -/// Audit Log (#23) M6 Bundle E (T7) — central singleton that subscribes to the +/// Central singleton that subscribes to the /// actor system's EventStream for /// publications and maintains a per-site latched stalled-state map readable -/// via . Consumed by the M6 Bundle E +/// via . Consumed by the /// aggregator so the central health /// surface can surface per-site "reconciliation isn't draining" without /// coupling the publisher () to the diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptions.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptions.cs index 12369897..32e90a47 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptions.cs @@ -4,7 +4,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Configuration; /// -/// Configuration for Audit Log (#23). Bound from the AuditLog section of +/// Configuration for Audit Log. Bound from the AuditLog section of /// appsettings.json. Defaults reflect the design (alog.md §6, §10): an /// 8 KiB payload-summary cap, a 64 KiB cap on error rows, and a 365-day central /// retention window with monthly partition-switch purge. The default @@ -38,7 +38,7 @@ public sealed class AuditLogOptions public int RetentionDays { get; set; } = 365; /// - /// M5.5 (T3) per-channel retention overrides, keyed by the canonical channel name + /// Per-channel retention overrides, keyed by the canonical channel name /// (the enum name — e.g. ApiOutbound, /// DbOutbound, Notification, ApiInbound). The value is a /// retention window in days that MUST be SHORTER than or equal to the global diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptionsValidator.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptionsValidator.cs index 0406d99c..08ca8542 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptionsValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Configuration/AuditLogOptionsValidator.cs @@ -5,7 +5,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Configuration; /// /// Validates on startup. The caps drive payload -/// truncation in the M2+ writers, so an unset/zero cap would let arbitrarily +/// truncation in the writers, so an unset/zero cap would let arbitrarily /// large blobs into the central AuditLog table. /// must be at least as large as /// because the error cap is meant to capture more detail than the @@ -54,7 +54,7 @@ public sealed class AuditLogOptionsValidator : OptionsValidatorBase /// Opt-in SQL parameter redaction: case-insensitive regex matched against - /// each SQL parameter NAME in the M4 AuditingDbCommand RequestSummary + /// each SQL parameter NAME in the AuditingDbCommand RequestSummary /// JSON ({"sql":"...","parameters":{"@name":"value", ...}}); values /// whose name matches are replaced with <redacted>. Null (the /// default) means parameter values are captured verbatim. Only applied to diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs index 4e77a18d..8b4e333d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs @@ -6,7 +6,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Kpi; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Kpi; /// -/// Audit Log (#23) M6 "KPI History & Trends" (K8) — the +/// "KPI History & Trends" — the /// for the source. /// The central recorder singleton enumerates this provider once per sampling pass /// and persists its samples into the central KpiSample history table. @@ -38,7 +38,7 @@ public sealed class AuditLogKpiSampleSource : IKpiSampleSource // Metric catalog — the exact strings persisted in KpiSample.Metric. All three are // charted, so they share the public Commons catalog: source + UI trend page key off - // one symbol (#178). Stable identifiers; do not rename (values are persisted). + // one symbol. Stable identifiers; do not rename (values are persisted). private const string TotalEventsLastHourMetric = KpiMetrics.AuditLog.TotalEventsLastHour; private const string ErrorEventsLastHourMetric = KpiMetrics.AuditLog.ErrorEventsLastHour; private const string BacklogTotalMetric = KpiMetrics.AuditLog.BacklogTotal; diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs index dfbd0764..4f345964 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs @@ -11,7 +11,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Payload; /// Pure, stateless redaction + truncation primitives used by /// /// (which operates on ZB.MOM.WW.Audit.AuditEvent + its DetailsJson). -/// Extracted in ScadaBridge audit re-architecture stage C2 (Task 2.5) so the +/// Extracted in a ScadaBridge audit re-architecture so the /// byte-exact redaction logic lives in ONE place. /// /// @@ -193,7 +193,7 @@ internal static class AuditRedactionPrimitives } /// - /// Walk the M4 {"sql":"...","parameters":{...}} RequestSummary + /// Walk the {"sql":"...","parameters":{...}} RequestSummary /// shape; for each parameter whose NAME matches /// , replace its value with /// . Re-serialise. No-op pass-through when the diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs index 143e6624..ae5fc452 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs @@ -7,7 +7,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Payload; /// /// Per-instance compiled-regex cache for audit body / SQL-parameter redactors /// used by . -/// Extracted in ScadaBridge audit re-architecture stage C2 (Task 2.5) to +/// Extracted in ScadaBridge audit re-architecture to /// centralize compile rules (50 ms per-match timeout, 100 ms compile budget, /// invalid-pattern sentinel). /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/IAuditRedactionFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/IAuditRedactionFailureCounter.cs index 17ca9fcd..161be123 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/IAuditRedactionFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/IAuditRedactionFailureCounter.cs @@ -4,7 +4,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Payload; /// Counter sink invoked by /// every time a redactor (header / body regex / SQL parameter) throws and the /// redactor has to over-redact the offending field with the -/// <redacted: redactor error> marker. Bundle C bridges this into +/// <redacted: redactor error> marker. This is bridged into /// the Site Health Monitoring report payload as AuditRedactionFailure. /// /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/NoOpAuditRedactionFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/NoOpAuditRedactionFailureCounter.cs index cf29a451..3caf1c6c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/NoOpAuditRedactionFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/NoOpAuditRedactionFailureCounter.cs @@ -2,7 +2,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Payload; /// /// Default binding used when the -/// Site Health Monitoring bridge has not been wired yet. Bundle C replaces +/// Site Health Monitoring bridge has not been wired yet. Replaces /// this registration with the real counter that surfaces in the site health /// report payload as AuditRedactionFailure. /// @@ -11,7 +11,7 @@ public sealed class NoOpAuditRedactionFailureCounter : IAuditRedactionFailureCou /// public void Increment() { - // Intentionally empty — Bundle C overrides this binding with the real + // Intentionally empty — overrides this binding with the real // health-metric counter. } } diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/ServiceCollectionExtensions.cs index 87872164..10534063 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/ServiceCollectionExtensions.cs @@ -19,12 +19,12 @@ using IAuditWriter = ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services.IAuditWri namespace ZB.MOM.WW.ScadaBridge.AuditLog; /// -/// Composition root for the Audit Log (#23) component. +/// Composition root for the Audit Log component. /// /// /// -/// M1 registered + the validator. M2 Bundle E -/// extends the surface with the site-side writer chain +/// Registered + the validator. Extends the +/// surface with the site-side writer chain /// ( + + /// ) and the telemetry collaborators /// (, , @@ -32,8 +32,8 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog; /// ). /// /// -/// Audit Log (#23) sits alongside Notification Outbox (#21) and Site Call -/// Audit (#22). IAuditLogRepository is registered by +/// Audit Log sits alongside Notification Outbox and Site Call +/// Audit. IAuditLogRepository is registered by /// ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.ServiceCollectionExtensions.AddConfigurationDatabase, /// so the caller (the Host on the central node) must also call that. /// @@ -59,7 +59,7 @@ public static class ServiceCollectionExtensions public const string ReconciliationSectionName = "AuditLog:Reconciliation"; /// - /// Registers the Audit Log (#23) component services: options, the site + /// Registers the Audit Log component services: options, the site /// SQLite writer chain (primary + ring fallback + failure-counter sink), /// and the site-→central telemetry collaborators. Idempotent re-registration /// is not supported; call this exactly once per . @@ -72,7 +72,7 @@ public static class ServiceCollectionExtensions ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(config); - // M1: top-level AuditLogOptions + validator (redaction policy, payload caps, etc.). + // Top-level AuditLogOptions + validator (redaction policy, payload caps, etc.). // Collapsed onto the shared ZB.MOM.WW.Configuration helper: it binds the // "AuditLog" section, registers the validator, and enables ValidateOnStart in // one call. Same section path as before; AddAuditLog is call-once per @@ -80,20 +80,19 @@ public static class ServiceCollectionExtensions // validator (a strict improvement over the previous AddSingleton). services.AddValidatedOptions(config, ConfigSectionName); - // C3 (Task 2.5): the canonical IAuditRedactor is wired as + // The canonical IAuditRedactor is wired as // ScadaBridgeAuditRedactor — same truncation + header / body / // SQL-parameter redaction as the original pipeline, applied between // event construction and persistence. Singleton — stateless; the // IOptionsMonitor dependency picks up hot reloads on its own. services.AddSingleton(); - // M5 Bundle B: per-stage redactor-failure counter. NoOp default; - // Bundle C replaces this binding with the Site Health Monitoring - // bridge that surfaces failures as AuditRedactionFailure on the site - // health report. + // Per-stage redactor-failure counter. NoOp default; this binding is + // later replaced with the Site Health Monitoring bridge that surfaces + // failures as AuditRedactionFailure on the site health report. services.TryAddSingleton(); - // M2 Bundle E: site writer + telemetry options bindings. + // Site writer + telemetry options bindings. // BindConfiguration is not used because the configuration root supplied // by the caller may not be the application root — we go through the // section explicitly so a partial IConfiguration (e.g. a test stub @@ -113,18 +112,18 @@ public static class ServiceCollectionExtensions // RingBufferFallback: drop-oldest in-memory ring used by // FallbackAuditWriter when the primary SQLite writer throws. Default - // capacity is fine for M2 (1024). + // capacity is fine (1024). services.AddSingleton(); - // IAuditWriteFailureCounter: NoOp default. Bundle G overrides this - // binding with the real Site Health Monitoring counter. Registered + // IAuditWriteFailureCounter: NoOp default. This binding is later + // overridden with the real Site Health Monitoring counter. Registered // before FallbackAuditWriter so the factory can resolve it. services.AddSingleton(); // The script-thread surface is FallbackAuditWriter (primary + ring + // counter), not the raw SqliteAuditWriter — primary failures must NEVER // abort the user-facing action. - // C3 (Task 2.5): the canonical IAuditRedactor singleton above is wired + // The canonical IAuditRedactor singleton above is wired // through the factory so every event written through this surface is // truncated + redacted before it hits SQLite (and the ring on // failure). @@ -145,72 +144,71 @@ public static class ServiceCollectionExtensions // created during Akka bootstrap, not at DI-composition time). services.AddSingleton(); - // M3 Bundle F: site-side dual emitter for cached-call lifecycle + // Site-side dual emitter for cached-call lifecycle // telemetry. ScriptRuntimeContext.ExternalSystem.CachedCall / // Database.CachedWrite resolves this through DI and pushes one combined // packet per lifecycle event; the forwarder writes the audit half // through IAuditWriter and the operational half through the - // IOperationTrackingStore. The audit writer is always wired (the M2 + // IOperationTrackingStore. The audit writer is always wired (the // chain above); the operational tracking store is SITE-ONLY (registered // by ZB.MOM.WW.ScadaBridge.SiteRuntime). On a Central composition root the tracking // store has no registration, so the factory resolves it with GetService // (returning null) — the forwarder degrades to "audit-only" emission, - // mirroring the lazy IAuditWriter chain established in M2. + // mirroring the lazy IAuditWriter chain established above. services.AddSingleton(sp => new CachedCallTelemetryForwarder( sp.GetRequiredService(), sp.GetService(), sp.GetRequiredService>(), - // AuditLog-007: INodeIdentityProvider is now required across + // INodeIdentityProvider is now required across // every consumer in AddAuditLog. The Host's // SiteServiceRegistration registers it as a singleton on both - // site and central paths (InboundAPI-022 / Host registration - // sweep), and the AddAuditLogTests fixture provides a + // site and central paths, and the AddAuditLogTests fixture provides a // FakeNodeIdentityProvider; a silent GetService() that // returned null would mask a future composition root that // forgot to register the provider. sp.GetRequiredService())); - // M3 Bundle F: bridge the store-and-forward retry-loop observer hook + // Bridge the store-and-forward retry-loop observer hook // to the cached-call forwarder so per-attempt + terminal telemetry // emitted from the S&F retry sweep lands on the same SQLite hot-path // as the script-thread CachedSubmit row. Registered as a singleton // and also bound to ICachedCallLifecycleObserver so AddStoreAndForward - // can resolve it through DI (Bundle F StoreAndForward wiring change). - // SourceNode-stamping (Task 14): factory-resolved so the + // can resolve it through DI. + // SourceNode-stamping: factory-resolved so the // INodeIdentityProvider singleton can be threaded through — the // bridge stamps SiteCallOperational.SourceNode from // INodeIdentityProvider.NodeName on every cached-call lifecycle row. - // AuditLog-007: the provider is resolved with GetRequiredService — + // The provider is resolved with GetRequiredService — // SiteServiceRegistration.BindSharedOptions registers it on both // site and central paths, so a missing registration is a // composition-root bug, not a silent null-SourceNode degradation. services.AddSingleton(sp => new CachedCallLifecycleBridge( sp.GetRequiredService(), sp.GetRequiredService>(), - // AuditLog-007: required, matches the other consumers in this + // Required, matches the other consumers in this // composition root — the provider is always registered by // SiteServiceRegistration. sp.GetRequiredService())); services.AddSingleton( sp => sp.GetRequiredService()); - // M6 Bundle E (T8): central audit-write failure counter — NoOp default + // Central audit-write failure counter — NoOp default // for site/test composition roots that don't wire the central health // snapshot. AddAuditLogCentralMaintenance below replaces this binding // with the AuditCentralHealthSnapshot implementation so increments // surface on the central dashboard. services.TryAddSingleton(); - // M5.3 (T7): inbound body-ceiling hit counter — NoOp default for + // Inbound body-ceiling hit counter — NoOp default for // site/test roots. AddAuditLogCentralMaintenance replaces this binding // with the AuditCentralHealthSnapshot implementation so ceiling-hit // counts surface on the central dashboard alongside write-failure and // redaction-failure counters. services.TryAddSingleton(); - // M4 Bundle B: central direct-write audit writer used by - // NotificationOutboxActor (Bundle B) and Inbound API (Bundle C/D) to + // Central direct-write audit writer used by + // NotificationOutboxActor and Inbound API to // emit AuditLog rows that originate ON central, not via site telemetry. // Singleton — the writer is stateless; its per-call scope opens a fresh // IAuditLogRepository (a SCOPED EF Core service registered by @@ -218,17 +216,17 @@ public static class ServiceCollectionExtensions // is intentionally distinct from IAuditWriter so site composition roots // do not accidentally bind it; central composition roots that include // AddConfigurationDatabase get a working implementation transparently. - // C3 (Task 2.5): wire the canonical IAuditRedactor into the factory so + // Wire the canonical IAuditRedactor into the factory so // NotificationOutboxActor + Inbound API rows are truncated + redacted // before they hit MS SQL. - // M6 Bundle E (T8): also wire the ICentralAuditWriteFailureCounter + // Also wire the ICentralAuditWriteFailureCounter // so swallowed repo throws bump the central health counter. services.AddSingleton(sp => new CentralAuditWriter( sp, sp.GetRequiredService>(), sp.GetRequiredService(), sp.GetRequiredService(), - // SourceNode-stamping (Task 12): wire the local node identity so + // SourceNode-stamping: wire the local node identity so // central-origin rows (Notification Outbox dispatch, Inbound API) // carry the writing node's identifier when the caller hasn't // already supplied one. GetRequiredService — the production @@ -236,7 +234,7 @@ public static class ServiceCollectionExtensions // provider as a singleton on both site and central paths. sp.GetRequiredService())); - // M6 (K8) KPI History & Trends: the AuditLog source the central KPI + // KPI History & Trends: the AuditLog source the central KPI // recorder enumerates each sampling pass to snapshot Global-scope Audit // Log KPIs (volume / error rate / backlog) into the KpiSample history // table. Scoped to match its IAuditLogRepository dependency — a SCOPED @@ -252,7 +250,7 @@ public static class ServiceCollectionExtensions } /// - /// Audit Log (#23) M2 Bundle G + M5 Bundle C — swap the default + /// Swap the default /// and /// registrations for the /// real / @@ -282,10 +280,10 @@ public static class ServiceCollectionExtensions /// double-registered (AddHostedService has no TryAdd variant). /// /// - /// Site-side only for M5: the central composition root keeps the NoOp + /// Site-side only: the central composition root keeps the NoOp /// defaults; the central health-metric surface that would expose /// AuditRedactionFailure next to the existing central counters - /// ships in M6. + /// ships later. /// /// /// The service collection to register into. @@ -294,7 +292,7 @@ public static class ServiceCollectionExtensions { ArgumentNullException.ThrowIfNull(services); - // AuditLog-011: guard against double-registration. AddHostedService is + // Guard against double-registration. AddHostedService is // additive (no TryAdd variant) so a second call without this sentinel // would spin up a second SiteAuditBacklogReporter, doubling the 30 s // SQL probe rate and racing on the ISiteHealthCollector snapshot. The @@ -310,7 +308,7 @@ public static class ServiceCollectionExtensions ServiceDescriptor.Singleton()); services.Replace( ServiceDescriptor.Singleton()); - // M6 Bundle E (T6): the site-side backlog reporter polls the + // The site-side backlog reporter polls the // SqliteAuditWriter every 30 s and pushes the snapshot into the // collector so the next SiteHealthReport carries a fresh // SiteAuditBacklog field. Registered alongside the other site-only @@ -322,7 +320,7 @@ public static class ServiceCollectionExtensions } /// - /// Audit Log (#23) M6-T5 Bundle D — central-only registration for the + /// Central-only registration for the /// hosted service plus /// its binding. Must be /// called from the Central role's composition root (not from a site @@ -372,7 +370,7 @@ public static class ServiceCollectionExtensions services.AddOptions() .Bind(config.GetSection(ReconciliationSectionName)); - // M6 Bundle E (T8 + T9): central health snapshot — a single object + // Central health snapshot — a single object // that owns the CentralAuditWriteFailures + AuditRedactionFailure // Interlocked counters AND surfaces them on // IAuditCentralHealthSnapshot. The same instance is bound to BOTH @@ -391,7 +389,7 @@ public static class ServiceCollectionExtensions sp => sp.GetRequiredService()); services.Replace(ServiceDescriptor.Singleton( sp => sp.GetRequiredService())); - // M6 Bundle E (T9): override the NoOp IAuditRedactionFailureCounter + // Override the NoOp IAuditRedactionFailureCounter // (registered by AddAuditLog) with the CentralAuditRedactionFailureCounter // bridge so payload-filter throws on CentralAuditWriter / // AuditLogIngestActor paths surface on the central dashboard. The @@ -400,11 +398,11 @@ public static class ServiceCollectionExtensions // counter as CentralAuditWriteFailures. The site composition root // overrides this binding AGAIN via AddAuditLogHealthMetricsBridge — // central nodes do not call that bridge, so this is the final - // binding on a central host. Mirrors the M5 Bundle C + // binding on a central host. Mirrors the // HealthMetricsAuditRedactionFailureCounter shape one-for-one. services.Replace(ServiceDescriptor.Singleton()); - // M5.3 (T7): replace the NoOp IAuditInboundCeilingHitsCounter with the + // Replace the NoOp IAuditInboundCeilingHitsCounter with the // AuditCentralHealthSnapshot so ceiling-hit counts surface on the // central dashboard. Same singleton-forward pattern as // ICentralAuditWriteFailureCounter above. @@ -415,7 +413,7 @@ public static class ServiceCollectionExtensions } /// - /// Audit Log (#23) M6 — central-only registration of the production + /// Audit Log — central-only registration of the production /// () /// and its unary-call invoker () used /// by to pull reconciliation @@ -500,7 +498,7 @@ public static class ServiceCollectionExtensions sp.GetRequiredService(), sp.GetRequiredService>())); - // Site Call Audit (#22) reconciliation pull client — central-only, the + // Site Call Audit reconciliation pull client — central-only, the // sibling of the audit pull client above. Lives here (not in the // SiteCallAudit project) so it can reuse the central-only // ISiteEnumerator registered just above; SiteCallAudit does not diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/FallbackAuditWriter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/FallbackAuditWriter.cs index 2e697874..01994e9b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/FallbackAuditWriter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/FallbackAuditWriter.cs @@ -18,7 +18,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// /// Each primary failure increments so /// Site Health Monitoring can surface a sustained outage as -/// SiteAuditWriteFailures (Bundle G). +/// SiteAuditWriteFailures. /// /// /// Errors raised by the ring drain on recovery are logged and silently dropped @@ -36,7 +36,7 @@ public sealed class FallbackAuditWriter : IAuditWriter private readonly SemaphoreSlim _drainGate = new(1, 1); /// - /// Bundle C (M5-T6) wires the singleton + /// Wires the singleton /// here so every event written via the site hot path is truncated + /// header/body/SQL-param redacted before it hits both the primary SQLite /// writer AND the ring fallback. The parameter is optional (defaults to @@ -62,8 +62,8 @@ public sealed class FallbackAuditWriter : IAuditWriter _ring = ring ?? throw new ArgumentNullException(nameof(ring)); _failureCounter = failureCounter ?? throw new ArgumentNullException(nameof(failureCounter)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - // AuditLog-008: never default to a null redactor — over-redact instead. - // C3 (Task 2.5): wired via the canonical IAuditRedactor seam. + // Never default to a null redactor — over-redact instead. + // Wired via the canonical IAuditRedactor seam. // SafeDefaultAuditRedactor performs HTTP header redaction with the // hard-coded sensitive defaults (Authorization, X-Api-Key, Cookie, // Set-Cookie) on the DetailsJson summaries so a test composition root @@ -82,7 +82,7 @@ public sealed class FallbackAuditWriter : IAuditWriter // and (on failure) to the ring buffer — so a primary outage that // drains later still hands the SqliteAuditWriter a row that has // already been truncated and redacted. The redactor contract is - // "MUST NOT throw". AuditLog-008: _redactor is now non-null (defaults + // "MUST NOT throw". _redactor is now non-null (defaults // to SafeDefaultAuditRedactor so header redaction is always applied // even in composition roots that don't wire the real redactor). var filtered = _redactor.Apply(evt); diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditRedactionFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditRedactionFailureCounter.cs index f4e8e9ee..9796690b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditRedactionFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditRedactionFailureCounter.cs @@ -4,7 +4,7 @@ using ZB.MOM.WW.ScadaBridge.HealthMonitoring; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// -/// Audit Log (#23) M5 Bundle C — bridges +/// Bridges /// (incremented by /// every time /// a header / body / SQL parameter redactor stage throws and the redactor has @@ -22,16 +22,15 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// redaction failures must NEVER abort the user-facing action, alog.md §7). /// /// -/// Mirrors the M2 Bundle G +/// Mirrors the /// shape one-for-one so the two health-metric bridges age together. /// /// -/// Site-side only for M5: the redaction filter also runs on the central -/// writers (CentralAuditWriter + AuditLogIngestActor), but the central -/// health-metric surface that would expose AuditRedactionFailure -/// alongside the existing central counters ships in M6. Until then, the -/// central composition root keeps the NoOp default — the redactions still -/// happen, they just don't get counted into a health report. +/// Site-side only: the redaction filter also runs on the central +/// writers (CentralAuditWriter + AuditLogIngestActor); the central +/// health-metric surface exposing AuditRedactionFailure is bridged +/// separately by CentralAuditRedactionFailureCounter, which the +/// central composition root registers in place of the NoOp default. /// /// public sealed class HealthMetricsAuditRedactionFailureCounter : IAuditRedactionFailureCounter diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditWriteFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditWriteFailureCounter.cs index eba434ec..0062f06e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditWriteFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/HealthMetricsAuditWriteFailureCounter.cs @@ -3,7 +3,7 @@ using ZB.MOM.WW.ScadaBridge.HealthMonitoring; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// -/// Audit Log (#23) M2 Bundle G — bridges +/// Bridges /// (incremented by every time the primary /// SQLite writer throws) into so the count /// surfaces in the site health report payload as diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/IAuditWriteFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/IAuditWriteFailureCounter.cs index 40678189..a85daad5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/IAuditWriteFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/IAuditWriteFailureCounter.cs @@ -3,7 +3,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// /// Lightweight counter sink invoked by every /// time the primary throws on an audit write. -/// Bundle G (M2-T11) implements this as a thread-safe Interlocked counter +/// Implements this as a thread-safe Interlocked counter /// bridged into the Site Health Monitoring report payload as /// SiteAuditWriteFailures. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/NoOpAuditWriteFailureCounter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/NoOpAuditWriteFailureCounter.cs index 785b9ed1..de95b9b3 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/NoOpAuditWriteFailureCounter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/NoOpAuditWriteFailureCounter.cs @@ -3,7 +3,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// /// Default registered by /// on -/// every node. Bundle G replaces this binding with a real counter that bridges +/// every node. This binding will be replaced with a real counter that bridges /// into the Site Health Monitoring report payload as /// SiteAuditWriteFailures — until then, /// emits to a silent sink rather than NRE-ing @@ -19,7 +19,7 @@ public sealed class NoOpAuditWriteFailureCounter : IAuditWriteFailureCounter /// public void Increment() { - // Intentionally empty. Bundle G overrides this binding with the real + // Intentionally empty. This binding is replaced with the real // counter once Site Health Monitoring is wired. } } diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs index d54cf27d..1e6719ea 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs @@ -21,7 +21,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// count at capacity, exactly one event has been dropped. /// /// -/// Per the M2 plan: the ring is the absolute-last-resort buffer for the +/// The ring is the absolute-last-resort buffer for the /// hot-path; it is NOT a substitute for the bounded /// write queue. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs index ff0c5e23..6e597e55 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs @@ -6,7 +6,7 @@ using ZB.MOM.WW.ScadaBridge.HealthMonitoring; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// -/// Audit Log (#23) M6 Bundle E (T6) — site-side hosted service that +/// Site-side hosted service that /// periodically pulls a backlog snapshot from /// and pushes it into so the next /// emits a fresh @@ -26,7 +26,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// across many reports, fine enough that the central dashboard never lags by /// more than one health-report interval. Tunable via /// in a follow-up -/// if ops needs a different cadence; for M6 we hard-code the value because the +/// if ops needs a different cadence; for now we hard-code the value because the /// brief calls it out explicitly. /// /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs index 954282df..659b51fa 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs @@ -12,7 +12,7 @@ using AuditOutcome = ZB.MOM.WW.Audit.AuditOutcome; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// -/// Site-side SQLite hot-path writer for Audit Log (#23) events. Mirrors the +/// Site-side SQLite hot-path writer for Audit Log events. Mirrors the /// design — a single /// owned serialised behind a write lock, fed by a /// bounded drained on a dedicated background writer @@ -20,7 +20,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// /// /// -/// C4 (Task 2.5) — two-table schema. The site store is now two tables: +/// Two-table schema. The site store is now two tables: /// the append-only canonical audit_event (the 10 canonical /// fields stored directly — NO 24-column decompose) and /// the mutable operational audit_forward_state sidecar that carries the @@ -31,10 +31,10 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site; /// /// /// Ephemeral reset. The site SQLite store is ephemeral (≈7-day retention, -/// recreated per deployment), so C4's schema change is an in-place RESET: the new +/// recreated per deployment), so this schema change is an in-place RESET: the new /// tables are created and the old single 24-column AuditLog table is /// DROP-ped if present. No SQLite data migration is performed (and none is -/// needed) — any rows in a pre-C4 AuditLog table are within the retention +/// needed) — any rows in the old AuditLog table are within the retention /// window and are discarded by the drop. /// /// @@ -56,7 +56,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable private const int SqliteErrorConstraint = 19; private readonly SqliteConnection _connection; - // AuditLog-005: dedicated read-only connection used by GetBacklogStatsAsync, + // Dedicated read-only connection used by GetBacklogStatsAsync, // ReadPendingAsync, ReadPendingSinceAsync, and ReadForwardedAsync so a slow // backlog scan (COUNT(*) over hundreds of thousands of Pending rows under a // central outage) never parks the hot-path writer behind _writeLock. @@ -102,7 +102,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable InitializeSchema(); - // AuditLog-005: open a second connection for read-only callers + // Open a second connection for read-only callers // (GetBacklogStatsAsync, ReadPendingAsync, ReadPendingSinceAsync, // ReadForwardedAsync). InitializeSchema set journal_mode=WAL on the // writer connection, which is a database-level setting that persists @@ -128,7 +128,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable new BoundedChannelOptions(_options.ChannelCapacity) { // The hot-path enqueue must back-pressure if the background - // writer falls behind; a higher-level fallback (Bundle B-T4) + // writer falls behind; a higher-level fallback // handles truly catastrophic primary failure with a drop-oldest // ring buffer. FullMode = BoundedChannelFullMode.Wait, @@ -150,7 +150,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable pragmaCmd.ExecuteNonQuery(); } - // AuditLog-005: enable WAL so a second connection on the same file can + // Enable WAL so a second connection on the same file can // serve read-only callers (GetBacklogStatsAsync, ReadPendingAsync, // ReadPendingSinceAsync, ReadForwardedAsync) concurrently with the // batched writer, decoupling those reads from _writeLock. WAL is a @@ -185,14 +185,14 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable pragmaCmd.ExecuteNonQuery(); } - // C4 (Task 2.5) — in-place reset. The site store is EPHEMERAL (≈7-day + // In-place reset. The site store is EPHEMERAL (≈7-day // retention, recreated per deployment), so we do NOT migrate the old // single 24-column AuditLog table to the new two-table shape: any rows - // it holds are within the retention window and discarded. DROP it if a - // pre-C4 deployment left it behind, then CREATE the two new tables. This + // it holds are within the retention window and discarded. DROP it if an + // earlier deployment left it behind, then CREATE the two new tables. This // is safe precisely BECAUSE the site store is ephemeral — never do this // on a durable store (the central SQL Server side keeps its shim until - // C5 and is migrated, not reset). + // it is migrated, not reset). using (var dropCmd = _connection.CreateCommand()) { dropCmd.CommandText = "DROP TABLE IF EXISTS AuditLog;"; @@ -442,10 +442,10 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable } } - // AuditLog-001: cached-lifecycle audit kinds that ride the combined-telemetry + // Cached-lifecycle audit kinds that ride the combined-telemetry // drain (joined with the operational tracking row + pushed via // IngestCachedTelemetryAsync into the central dual-write transaction). - // C4: this is the SAME set the pre-C4 ReadPendingCachedTelemetryAsync query + // This is the SAME set the earlier ReadPendingCachedTelemetryAsync query // filtered on (Kind IN (...)); it is now precomputed into the sidecar's // IsCachedKind flag at INSERT (see IsCachedKind) so the read split is a cheap // integer predicate, not a JSON parse. ReadPendingAsync drains everything @@ -459,7 +459,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable }; /// - /// C4: precomputes the sidecar's IsCachedKind flag from a canonical + /// Precomputes the sidecar's IsCachedKind flag from a canonical /// row's DetailsJson. Parses the /// discriminator via and returns true /// iff it is one of the cached-lifecycle kinds @@ -489,14 +489,14 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable throw new ArgumentOutOfRangeException(nameof(limit), "limit must be > 0."); } - // AuditLog-005: read via the dedicated _readConnection so this scan + // Read via the dedicated _readConnection so this scan // (which can be expensive when the backlog grows under a central // outage) does not block the batched writer on _writeLock. WAL mode // gives us a stable snapshot of the tables while writes proceed on the // writer connection. _readLock serialises this connection across // multiple concurrent read callers since SqliteConnection itself is // not thread-safe. - // C4: JOIN the sidecar and filter on IsCachedKind=0 — the cached- + // JOIN the sidecar and filter on IsCachedKind=0 — the cached- // lifecycle kinds (IsCachedKind=1) flow through // ReadPendingCachedTelemetryAsync + the combined-telemetry drain. The // split is a precomputed integer predicate on the indexed sidecar, not @@ -539,7 +539,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable throw new ArgumentOutOfRangeException(nameof(limit), "limit must be > 0."); } - // AuditLog-001 / C4: dedicated read surface for the cached-call lifecycle + // Dedicated read surface for the cached-call lifecycle // drain — symmetric to ReadPendingAsync but filtered to IsCachedKind=1. // Same _readConnection + _readLock pattern so the hot-path writer is not // contended. @@ -586,9 +586,9 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable throw new ArgumentOutOfRangeException(nameof(limit), "limit must be > 0."); } - // AuditLog-005: mirror ReadPendingAsync — read via _readConnection / + // Mirror ReadPendingAsync — read via _readConnection / // _readLock so this query never contends with the batched writer on - // _writeLock. C4: JOIN the sidecar and filter on ForwardState='Forwarded' + // _writeLock. JOIN the sidecar and filter on ForwardState='Forwarded' // (no IsCachedKind split — both cached and non-cached Forwarded rows are // returned, as before). lock (_readLock) @@ -626,7 +626,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable ObjectDisposedException.ThrowIf(_disposed, this); using var cmd = _connection.CreateCommand(); - // C4: flip the sidecar — UPDATE audit_forward_state, not the canonical + // Flip the sidecar — UPDATE audit_forward_state, not the canonical // audit_event (which is append-only / write-once). Bump AttemptCount + // stamp LastAttemptUtc so operators can see how many drain passes a row // took to forward. Build a single IN (...) parameter list so we issue @@ -667,7 +667,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable /// /// Returns up to pending or forwarded audit events /// with >= , oldest first. - /// Used by the M6 reconciliation-pull handler. + /// Used by the reconciliation-pull handler. /// /// Lower bound timestamp (UTC) for event occurrence. /// Maximum number of rows to return. @@ -681,8 +681,8 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable throw new ArgumentOutOfRangeException(nameof(batchSize), "batchSize must be > 0."); } - // AuditLog-005: read via _readConnection / _readLock — same lock- - // decoupling as ReadPendingAsync. C4: JOIN the sidecar; the range scan + // Read via _readConnection / _readLock — same lock- + // decoupling as ReadPendingAsync. JOIN the sidecar; the range scan // is on the sidecar's duplicated OccurredAtUtc so it stays on IX_fwd. // Both Pending and Forwarded rows are returned (the central reconciliation // puller dedups on EventId; re-shipping a Forwarded-but-not-yet-ingested @@ -729,7 +729,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable ObjectDisposedException.ThrowIf(_disposed, this); using var cmd = _connection.CreateCommand(); - // C4: flip the sidecar from Pending/Forwarded → Reconciled. Rows + // Flip the sidecar from Pending/Forwarded → Reconciled. Rows // already Reconciled are left untouched (idempotent re-call), and the // canonical audit_event row is never modified. var sb = new System.Text.StringBuilder(); @@ -759,13 +759,13 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable int pendingCount; DateTime? oldestPending; - // AuditLog-005: read via the dedicated _readConnection (under + // Read via the dedicated _readConnection (under // _readLock) so this probe — polled every 30 s by SiteAuditBacklogReporter // — never blocks the batched hot-path writer on _writeLock. Under a // central outage the Pending backlog can grow to hundreds of thousands // of rows and the COUNT(*) scan correspondingly stretches; that no // longer adds tail latency to user-facing audit writes. - // C4: count over the sidecar (audit_forward_state) — the canonical + // Count over the sidecar (audit_forward_state) — the canonical // audit_event table carries no ForwardState. The IX_fwd index makes both // aggregates cheap (count is a covering scan, min is the first key). lock (_readLock) @@ -843,7 +843,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable } /// - /// C4: builds the canonical DIRECTLY from the 10 + /// Builds the canonical DIRECTLY from the 10 /// stored audit_event columns — no 24-column Recompose, because /// audit_event already holds the canonical fields + DetailsJson. /// Outcome is stored as the enum's name; the safe @@ -875,7 +875,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable /// Disposes the audit writer and releases resources. /// /// - /// AuditLog-006: prefer when possible (DI honours + /// Prefer when possible (DI honours /// on singletons). The sync path remains for /// callers that only know about (e.g. legacy /// composition roots, using statements without await). To @@ -938,7 +938,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable _connection.Dispose(); } - // AuditLog-005: dispose the dedicated read connection after the writer + // Dispose the dedicated read connection after the writer // is fully drained and closed. _readLock is taken to fence out any // in-flight read caller that grabbed the lock before _disposed flipped // — they observe ObjectDisposedException on the next attempt. diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallLifecycleBridge.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallLifecycleBridge.cs index 10a6c251..73e880a1 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallLifecycleBridge.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallLifecycleBridge.cs @@ -8,7 +8,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site.Telemetry; /// -/// Audit Log #23 (M3 Bundle E — Tasks E4/E5): translates per-attempt +/// Translates per-attempt /// notifications from the store-and-forward retry loop into one (or two) /// packets and pushes them through /// . @@ -40,7 +40,7 @@ public sealed class CachedCallLifecycleBridge : ICachedCallLifecycleObserver private readonly ILogger _logger; /// - /// SourceNode-stamping (Task 14): the local node identity provider used to + /// SourceNode-stamping: the local node identity provider used to /// stamp SiteCallOperational.SourceNode on every cached-call /// lifecycle row this bridge emits. Optional — when null (legacy hosts / /// tests that don't register the provider) SourceNode stays null and @@ -93,8 +93,8 @@ public sealed class CachedCallLifecycleBridge : ICachedCallLifecycleObserver // Per-attempt row: kind discriminates channel; status is always // Attempted regardless of outcome (success vs. failure is captured // by the companion HttpStatus / ErrorMessage fields, NOT by flipping - // the status — CachedResolve carries the terminal Status). Per the - // M3 brief and alog.md §4. + // the status — CachedResolve carries the terminal Status). Per + // alog.md §4. var kind = ChannelToAttemptKind(context.Channel); var status = AuditStatus.Attempted; @@ -148,22 +148,22 @@ public sealed class CachedCallLifecycleBridge : ICachedCallLifecycleObserver occurredAtUtc: DateTime.SpecifyKind(context.OccurredAtUtc, DateTimeKind.Utc), target: context.Target, correlationId: context.TrackedOperationId.Value, - // Audit Log #23 (ExecutionId Task 4): the originating script + // The originating script // execution's per-run correlation id, threaded through the S&F - // buffer; null on rows buffered before Task 4 (back-compat). + // buffer; null on rows buffered before ExecutionId support was added (back-compat). executionId: context.ExecutionId, - // Audit Log #23 (ParentExecutionId Task 6): the spawning + // The spawning // inbound-API request's ExecutionId, threaded through the S&F // buffer alongside ExecutionId so the retry-loop cached rows // correlate back to the cross-execution chain. Null for a - // non-routed run and on rows buffered before Task 6. + // non-routed run and on rows buffered before ParentExecutionId support was added. parentExecutionId: context.ParentExecutionId, sourceSiteId: string.IsNullOrEmpty(context.SourceSite) ? null : context.SourceSite, sourceInstanceId: context.SourceInstanceId, - // Audit Log #23 (ExecutionId Task 4): SourceScript is now + // SourceScript is now // threaded through the S&F buffer alongside ExecutionId — the // retry-loop cached rows carry the same provenance the - // script-side cached rows do. Null on pre-Task-4 buffered rows. + // script-side cached rows do. Null on rows buffered before ExecutionId support was added. sourceScript: context.SourceScript, httpStatus: httpStatus, durationMs: context.DurationMs, @@ -173,7 +173,7 @@ public sealed class CachedCallLifecycleBridge : ICachedCallLifecycleObserver Channel: context.Channel, Target: context.Target, SourceSite: context.SourceSite, - // SourceNode-stamping (Task 14): the local cluster node name + // SourceNode-stamping: the local cluster node name // (node-a/node-b on a site). Stamped from the injected // INodeIdentityProvider; null when no provider was wired so // central persists SiteCalls.SourceNode as NULL. diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallTelemetryForwarder.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallTelemetryForwarder.cs index e4562406..b376da08 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallTelemetryForwarder.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/CachedCallTelemetryForwarder.cs @@ -9,15 +9,15 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site.Telemetry; /// -/// Site-side dual emitter for cached-call lifecycle telemetry (Audit Log #23 / -/// M3). Sister to : where the M2 actor +/// Site-side dual emitter for cached-call lifecycle telemetry. Sister to +/// : where that actor /// drains audit-only events, this forwarder takes a combined /// packet and fans it out to the two /// site-local stores in a single call: /// /// The row is written via /// (the site FallbackAuditWriter + -/// SqliteAuditWriter chain established in M2). +/// SqliteAuditWriter chain). /// The operational half /// updates the site-local OperationTracking SQLite store via /// , with the per-lifecycle method @@ -54,7 +54,7 @@ public sealed class CachedCallTelemetryForwarder : ICachedCallTelemetryForwarder private readonly ILogger _logger; /// - /// SourceNode-stamping (Task 14): local node identity provider used to + /// SourceNode-stamping: local node identity provider used to /// stamp the tracking-store row's SourceNode column on /// RecordEnqueueAsync. Optional — when null (legacy / test hosts) /// the column stays NULL on the tracking row. @@ -64,11 +64,11 @@ public sealed class CachedCallTelemetryForwarder : ICachedCallTelemetryForwarder /// /// Construct the forwarder. is optional — /// when null only the audit half of the packet is emitted, which matches - /// the M3 Bundle F composition-root contract on Central nodes: the + /// the composition-root contract on Central nodes: the /// AuditLog DI surface registers the forwarder unconditionally (mirroring /// the IAuditWriter chain) but the site-only tracking store has no central /// registration. Production site nodes wire both — the central lazy - /// resolution is a no-op path kept symmetric with the M2 writer chain. + /// resolution is a no-op path kept symmetric with the writer chain. /// /// Writer used to persist audit events from the telemetry packet. /// Optional store for updating operation tracking state; null on central nodes. @@ -111,7 +111,7 @@ public sealed class CachedCallTelemetryForwarder : ICachedCallTelemetryForwarder // FallbackAuditWriter) handles transient writer failures upstream; // a throw bubbling up here means the writer's own swallow contract // failed, which is itself best-effort-handled. - // C3: Kind/Status are domain fields carried in DetailsJson — decompose to log them. + // Kind/Status are domain fields carried in DetailsJson — decompose to log them. var d = AuditRowProjection.Decompose(telemetry.Audit); _logger.LogWarning(ex, "CachedCallTelemetryForwarder: audit emission threw for EventId {EventId} (Kind {Kind}, Status {Status})", @@ -130,7 +130,7 @@ public sealed class CachedCallTelemetryForwarder : ICachedCallTelemetryForwarder return; } - // C3: the audit half's domain fields (Kind/SourceInstanceId/SourceScript) + // The audit half's domain fields (Kind/SourceInstanceId/SourceScript) // ride inside DetailsJson — decompose once for this packet. var audit = AuditRowProjection.Decompose(telemetry.Audit); try @@ -141,7 +141,7 @@ public sealed class CachedCallTelemetryForwarder : ICachedCallTelemetryForwarder // Enqueue — insert-if-not-exists with the operational // channel as the kind discriminator. RetryCount is fixed // at 0 by the tracking store's INSERT contract. - // SourceNode-stamping (Task 14): stamp the local node + // SourceNode-stamping: stamp the local node // name (node-a/node-b) from the injected // INodeIdentityProvider; null when no provider was wired // so the tracking row's SourceNode column stays NULL. diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs index 019f9611..dec53865 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs @@ -24,8 +24,8 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site.Telemetry; /// The drain loop treats a thrown /// exception as transient and leaves the rows Pending for the next tick. /// Swallowing the fault into an empty ack would be indistinguishable from "zero -/// rows accepted" and would silently lose the retry signal. Task 1 confirmed -/// the central receiving end does not collapse an ingest fault into an empty +/// rows accepted" and would silently lose the retry signal. It has been confirmed +/// that the central receiving end does not collapse an ingest fault into an empty /// ack either, so a site-side Ask through the whole path faults cleanly on a /// central-side timeout. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs index 7a17dd50..26d3c111 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs @@ -26,7 +26,7 @@ public interface ISiteStreamAuditClient Task IngestAuditEventsAsync(AuditEventBatch batch, CancellationToken ct); /// - /// Forwards the combined (Audit Log #23) + /// Forwards the combined /// to the central cached-telemetry ingest path. Each packet carries both the /// audit row and the operational SiteCalls upsert; central writes both /// in a single MS SQL transaction. Returns the same diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryActor.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryActor.cs index ed4c0f71..88169bce 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryActor.cs @@ -45,7 +45,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site.Telemetry; /// which case the cached-drain scheduler is never armed. /// /// -/// Per Bundle D's brief, audit-write paths must be fail-safe — a thrown +/// Audit-write paths must be fail-safe — a thrown /// exception inside the actor MUST NOT crash it. Both Drain handlers wrap /// their pipelines in a top-level try/catch that logs and re-schedules; the /// actor's defaults to @@ -54,7 +54,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site.Telemetry; /// matters. /// /// -/// AuditLog-001: wires the previously-unreachable combined-telemetry transport. +/// Wires the previously-unreachable combined-telemetry transport. /// Prior to this the cached audit rows flowed through the audit-only drain via /// IngestAuditEventsAsync and the central OnCachedTelemetryAsync /// dual-write handler was dead production code; the operational SiteCalls @@ -70,7 +70,7 @@ public class SiteAuditTelemetryActor : ReceiveActor private readonly ILogger _logger; private ICancelable? _pendingTick; private ICancelable? _pendingCachedTick; - // AuditLog-010: per-actor lifecycle CTS so an in-flight drain (queue read, + // Per-actor lifecycle CTS so an in-flight drain (queue read, // gRPC push, mark-forwarded write) is actually cancelled when the actor is // stopped — without it, a stuck IngestAuditEventsAsync would hold the // continuation through CoordinatedShutdown's actor-system terminate window. @@ -132,7 +132,7 @@ public class SiteAuditTelemetryActor : ReceiveActor { _pendingTick?.Cancel(); _pendingCachedTick?.Cancel(); - // AuditLog-010: cancel any in-flight drain so a stuck queue read or + // Cancel any in-flight drain so a stuck queue read or // gRPC push does not hold the continuation past actor stop. try { @@ -149,7 +149,7 @@ public class SiteAuditTelemetryActor : ReceiveActor private async Task OnDrainAsync() { var nextDelay = TimeSpan.FromSeconds(_options.BusyIntervalSeconds); - // AuditLog-010: route every async dependency call through the + // Route every async dependency call through the // per-actor lifecycle token so PostStop cancellation actually // propagates into the queue read, the gRPC push, and the // mark-forwarded write. OperationCanceledException is swallowed by @@ -178,7 +178,7 @@ public class SiteAuditTelemetryActor : ReceiveActor catch (Exception ex) { // gRPC fault — leave the rows in Pending so the next drain - // retries. Bundle D's brief: "On gRPC exception (any), log + // retries — "On gRPC exception (any), log // Warning, schedule next Drain in BusyIntervalSeconds." _logger.LogWarning(ex, "IngestAuditEvents push failed for {Count} pending events; will retry next drain.", @@ -201,7 +201,7 @@ public class SiteAuditTelemetryActor : ReceiveActor } finally { - // AuditLog-010: if the actor is already shutting down, do not + // If the actor is already shutting down, do not // arm another tick — the scheduler would fire after PostStop and // the message would land in dead letters. if (!_lifecycleCts.IsCancellationRequested) @@ -212,7 +212,7 @@ public class SiteAuditTelemetryActor : ReceiveActor } /// - /// AuditLog-001: combined-telemetry drain. Reads cached-lifecycle audit + /// Combined-telemetry drain. Reads cached-lifecycle audit /// rows, joins each with the matching /// snapshot, builds a , and pushes via /// . Rows @@ -354,7 +354,7 @@ public class SiteAuditTelemetryActor : ReceiveActor } /// - /// AuditLog-001: build the combined wire packet from one cached audit row + /// Build the combined wire packet from one cached audit row /// + its matching operational tracking snapshot. The operational state /// reflects the latest tracking row at emission time (not the per-event /// status the audit row implies) because central's SiteCalls @@ -364,7 +364,7 @@ public class SiteAuditTelemetryActor : ReceiveActor private static CachedTelemetryPacket BuildCachedPacket( AuditEvent auditRow, TrackingStatusSnapshot snapshot) { - // C3: SourceSiteId + Channel ride inside the canonical record's + // SourceSiteId + Channel ride inside the canonical record's // DetailsJson — decompose to read them. var audit = AuditRowProjection.Decompose(auditRow); var sourceSite = audit.SourceSiteId ?? string.Empty; @@ -457,7 +457,7 @@ public class SiteAuditTelemetryActor : ReceiveActor /// /// Self-tick message that triggers a combined-telemetry drain cycle. - /// AuditLog-001: introduced alongside the cached-drain to keep the two + /// Introduced alongside the cached-drain to keep the two /// paths' cadences independent — a stall on one does not block the other. /// private sealed class CachedDrain diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryOptions.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryOptions.cs index 2f724b97..e159e4c4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryOptions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/SiteAuditTelemetryOptions.cs @@ -2,7 +2,7 @@ namespace ZB.MOM.WW.ScadaBridge.AuditLog.Site.Telemetry; /// /// Tuning knobs for the site-side drain -/// loop. Defaults mirror Bundle D's plan: drain every 5 s while rows are +/// loop. Defaults: drain every 5 s while rows are /// flowing (busy), every 30 s when the queue is empty (idle). /// public sealed class SiteAuditTelemetryOptions diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/ZB.MOM.WW.ScadaBridge.AuditLog.csproj b/src/ZB.MOM.WW.ScadaBridge.AuditLog/ZB.MOM.WW.ScadaBridge.AuditLog.csproj index 83783ee9..122f2556 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/ZB.MOM.WW.ScadaBridge.AuditLog.csproj +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/ZB.MOM.WW.ScadaBridge.AuditLog.csproj @@ -8,7 +8,7 @@ - diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/AlarmTriggerConfigJson.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/AlarmTriggerConfigJson.cs index 11957481..dbc01c39 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/AlarmTriggerConfigJson.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/AlarmTriggerConfigJson.cs @@ -32,7 +32,7 @@ internal static class AlarmTriggerConfigJson /// HiLo: high-high setpoint. /// Expression: boolean trigger expression. /// - /// M9-T28b: optional analysis kind for Expression triggers ("strict" → emits + /// Optional analysis kind for Expression triggers ("strict" → emits /// "analysisKind":"Strict"; null/"advisory"/anything else → Advisory default, /// key omitted). Ignored for non-Expression trigger types. /// @@ -86,7 +86,7 @@ internal static class AlarmTriggerConfigJson break; case "expression": w.WriteString("expression", expression ?? ""); - // M9-T28b: emit "analysisKind":"Strict" only when the caller passes + // Emit "analysisKind":"Strict" only when the caller passes // --trigger-kind strict (case-insensitive); Advisory (the default) is // expressed by omitting the key, matching ValidationService.IsStrictAnalysis. if (string.Equals(analysisKind?.Trim(), "Strict", StringComparison.OrdinalIgnoreCase)) diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/CliConfig.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/CliConfig.cs index 8f319041..a28d95c5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/CliConfig.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/CliConfig.cs @@ -40,7 +40,7 @@ public class CliConfig ".scadabridge", "config.json"); if (File.Exists(configPath)) { - // CLI-021: a malformed (`JsonException`), unreadable + // A malformed (`JsonException`), unreadable // (`UnauthorizedAccessException`), or otherwise faulted // (`IOException`) config file must not crash the CLI before any // command runs — even a command that supplies everything via diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditBackfillHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditBackfillHelpers.cs index e59e21c1..3a94c2e4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditBackfillHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditBackfillHelpers.cs @@ -27,8 +27,8 @@ public sealed class AuditBackfillSourceNodeArgs } /// -/// Pure helpers for the audit backfill-source-node subcommand (Audit Log -/// #23 M5.6 T5). Builds the request body, POSTs to +/// Pure helpers for the audit backfill-source-node subcommand. Builds +/// the request body, POSTs to /// /api/audit/backfill-source-node, and renders the result. Kept separate /// from the command wiring so each piece is unit-testable without standing up the /// command tree. diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs index cdd43588..7510b371 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs @@ -4,8 +4,8 @@ using System.CommandLine.Parsing; namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// -/// The scadabridge audit command group (Audit Log #23 M8). Provides read access to -/// the centralized append-only Audit Log via the Bundle B REST endpoints +/// The scadabridge audit command group. Provides read access to +/// the centralized append-only Audit Log via the REST endpoints /// (GET /api/audit/query, GET /api/audit/export, /// GET /api/audit/tree), plus a v1 no-op verify-chain placeholder /// for the deferred hash-chain tamper-evidence feature. @@ -291,7 +291,7 @@ public static class AuditCommands } /// - /// Builds the audit backfill-source-node sub-command (Audit Log #23 M5.6 T5). + /// Builds the audit backfill-source-node sub-command. /// Sets SourceNode on historical pre-feature rows whose SourceNode IS NULL /// and OccurredAtUtc is older than --before, in batches. Admin-only. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs index 2e929ab6..72e76a3b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs @@ -6,7 +6,7 @@ namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// /// Filter + destination arguments for an audit export invocation. Mirrors the -/// Bundle B GET /api/audit/export parameters. +/// GET /api/audit/export parameters. /// /// /// are multi-valued — each supplied value becomes a repeated query-string param so /// the server's multi-value IN (…) filter sees the full set, exactly like @@ -150,7 +150,7 @@ public static class AuditExportHelpers if (!response.IsSuccessStatusCode) { var message = await response.Content.ReadAsStringAsync(); - // CLI-018: honour the documented "authorization failure → exit 2" + // Honour the documented "authorization failure → exit 2" // contract on the REST audit surface as well. HTTP 403 is the // primary signal; the server may also surface UNAUTHORIZED / // FORBIDDEN via the JSON error envelope on a non-403 status. diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs index 0bff72fb..8a6ff743 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs @@ -5,7 +5,7 @@ namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// /// Renders a page of audit-log events to a writer. The audit query command picks /// a formatter from the --format option. The default JSONL formatter is defined -/// here; the human-readable table formatter is supplied by Bundle C. +/// here; the human-readable table formatter is supplied by . /// public interface IAuditFormatter { diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs index cfe3acfa..8fa8948b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs @@ -10,7 +10,7 @@ namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// centralized append-only Audit Log served by ). /// /// -/// Renamed from audit-log in #23 M8-T7 to avoid confusion with the new +/// Renamed from audit-log to avoid confusion with the new /// scadabridge audit group. The old audit-log name is retained as a /// deprecated alias; still resolves the full subcommand /// tree, and Program.cs prints a deprecation warning when it is used. @@ -54,7 +54,7 @@ public static class AuditLogCommands public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("audit-config") { Description = "Query the configuration-change audit log" }; - // Backward-compatible alias for the pre-M8 `audit-log` name. The alias keeps + // Backward-compatible alias for the old `audit-log` name. The alias keeps // full subcommand parity automatically; the deprecation warning is emitted by // the args[0] check in Program.cs. command.Aliases.Add(DeprecatedAlias); diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs index 0dd4dbf9..51df8a76 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs @@ -6,7 +6,7 @@ using System.Text.RegularExpressions; namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// -/// Filter arguments for an audit query invocation. Mirrors the Bundle B +/// Filter arguments for an audit query invocation. Mirrors the /// GET /api/audit/query filter parameters; / /// are time-specs (relative like 1h/7d, or absolute ISO-8601). /// /// @@ -192,7 +192,7 @@ public static class AuditQueryHelpers { OutputFormatter.WriteError( response.Error ?? "Audit query failed.", response.ErrorCode ?? "ERROR"); - // CLI-018: surface the documented "authorization failure → exit 2" + // Surface the documented "authorization failure → exit 2" // contract for the audit REST surface too, not just /management. return CommandHelpers.IsAuthorizationFailure(response) ? 2 : 1; } diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs index 44beeac6..549522d5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs @@ -6,7 +6,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// -/// Transport (#24) bundle export / preview / import. The bundle bytes travel +/// Transport bundle export / preview / import. The bundle bytes travel /// through the management endpoint as base64 inside the standard JSON envelope /// so no transport plumbing diverges from the other commands; the CLI handles /// file I/O at the edges. @@ -61,14 +61,14 @@ public static class BundleCommands var dbConnectionsOption = NameListOption("--db-connections", "Comma-separated database-connection names"); var notificationListsOption = NameListOption("--notification-lists", "Comma-separated notification-list names"); var smtpConfigsOption = NameListOption("--smtp-configs", "Comma-separated SMTP host names"); - // SMS (S10b): SmsConfiguration is keyed by AccountSid (no Name column), so + // SMS: SmsConfiguration is keyed by AccountSid (no Name column), so // tokens are AccountSid values — mirrors --smtp-configs using Host. var smsConfigsOption = NameListOption("--sms-configs", "Comma-separated SMS provider account SIDs"); - // Inbound API keys are not transported between environments (re-arch C4) — no + // Inbound API keys are not transported between environments — no // --api-keys option. Re-create keys and re-grant their method scopes on the // destination via the admin UI/CLI. var apiMethodsOption = NameListOption("--api-methods", "Comma-separated API-method names"); - // M8 (B4): site/instance-scoped export. Sites accept a SiteIdentifier + // Site/instance-scoped export. Sites accept a SiteIdentifier // (preferred) or friendly Name per token; instances accept a UniqueName. var sitesOption = NameListOption("--sites", "Comma-separated site identifiers or names"); var instancesOption = NameListOption("--instances", "Comma-separated instance unique-names"); @@ -131,7 +131,7 @@ public static class BundleCommands timeout: BundleCommandTimeout, onSuccess: jsonOk => { - // CLI-020: previously the JSON envelope parse + property extraction + + // Previously the JSON envelope parse + property extraction + // base64 decode all ran unguarded — a server-side bug that omits one of // the two expected properties, returns a null base64 value, sends invalid // base64, or returns a malformed JSON envelope would surface as one of @@ -139,7 +139,7 @@ public static class BundleCommands // JsonException, i.e. an unhandled stack trace rather than the // documented "exit 1 with a clean INVALID_RESPONSE error". Wrap the // envelope parse and the streamed write in a single try/catch matching - // the graceful-degradation theme established by CLI-002 / CLI-003 / CLI-005. + // the graceful-degradation theme established elsewhere in this command group. string base64; int byteCount; try @@ -158,7 +158,7 @@ public static class BundleCommands return 1; } - // CLI-019: stream the base64 → file write so a 100 MB bundle + // Stream the base64 → file write so a 100 MB bundle // doesn't double-buffer through Convert.FromBase64String's // ~100 MB byte[] on the LOH plus a synchronous File.WriteAllBytes. // The management envelope's body is still buffered into the @@ -314,7 +314,7 @@ public static class BundleCommands Description = "Resolution policy applied to every Modified row: skip, overwrite, or rename. Default: overwrite.", DefaultValueFactory = _ => "overwrite", }; - // M8 (D3): site/connection name mapping. Repeatable. A token with no + // Site/connection name mapping. Repeatable. A token with no // "=dst" part, or "=" with an empty right-hand side, means CreateNew (the // destination is created from the bundle payload); otherwise the source // is mapped to the named existing destination. @@ -400,7 +400,7 @@ public static class BundleCommands // Shared HTTP plumbing // ==================================================================== // - // CLI-017: bundle commands previously routed through a private + // Bundle commands previously routed through a private // RunBundleCommandAsync that re-implemented URL/credential resolution and // skipped the IsAuthorizationFailure(...) check that ExecuteCommandAsync // enforces — a server that signalled FORBIDDEN/UNAUTHORIZED via the error @@ -409,7 +409,7 @@ public static class BundleCommands // the longer BundleCommandTimeout and a per-command success handler, so the // exit-code contract is unified across every command group. - // CLI-019: chunked base64 → file streaming. The management envelope's + // Chunked base64 → file streaming. The management envelope's // success body is a single buffered JSON string (the wire format does not // currently support response-body streaming), so we cannot remove the // ~base64-string + ~envelope-string allocation. What we CAN — and do — diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs index 83492f53..245dda85 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs @@ -27,13 +27,12 @@ internal static class CommandHelpers /// body instead of running the default rendering path — /// useful when the caller needs to capture the response (e.g. write a file) rather /// than print it. The authorization-failure exit-code contract - /// () is preserved on the error path either way, - /// closing CLI-017's regression. + /// () is preserved on the error path either way. /// /// /// Optional transform applied to the success JSON body only when the resolved /// format is table. Lets a command render a compact table projection (e.g. - /// template list dropping per-template attribute dumps, followup #6) while + /// template list dropping per-template attribute dumps) while /// leaving JSON output untouched for machine consumers. Ignored when /// is supplied. /// @@ -95,8 +94,7 @@ internal static class CommandHelpers // Caller-supplied success handler short-circuits the default rendering — but // the error path still routes through IsAuthorizationFailure so the documented - // exit-2 contract holds whether or not a custom handler is provided - // (CLI-017 unification of the bundle path). + // exit-2 contract holds whether or not a custom handler is provided. if (onSuccess is not null) { if (response.JsonData is not null) @@ -255,7 +253,7 @@ internal static class CommandHelpers // Derive the header set as the union of property names across *every* // element, in first-seen order. Using only items[0] would silently drop - // columns for any later element with a different shape (CLI-016). + // columns for any later element with a different shape. var objectItems = items.Where(i => i.ValueKind == JsonValueKind.Object).ToList(); string[] headers; if (objectItems.Count > 0) diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs index a936cd44..065b8959 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs @@ -100,7 +100,7 @@ public static class DebugCommands .WithAutomaticReconnect() .Build(); - // CLI-011: CancellationTokenSource owns a WaitHandle and must be disposed. + // CancellationTokenSource owns a WaitHandle and must be disposed. using var cts = new CancellationTokenSource(); var exitTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -199,7 +199,7 @@ public static class DebugCommands } catch (Exception ex) { - // CLI-010: Ctrl+C during connect throws OperationCanceledException — that is + // Ctrl+C during connect throws OperationCanceledException — that is // a graceful user cancellation, not a connection failure. var failure = DebugStreamHelpers.ClassifyConnectFailure(ex, cts.IsCancellationRequested); if (failure.IsCancellation) @@ -250,7 +250,7 @@ public static class DebugCommands await connection.DisposeAsync(); - // CLI-012: resolve the exit code from a single authoritative source. A result + // Resolve the exit code from a single authoritative source. A result // set by OnStreamTerminated/Closed always wins; a brief grace period covers a // termination racing with Ctrl+C. Pure Ctrl+C (no result) is a graceful exit 0. return await DebugStreamHelpers.ResolveStreamExitCodeAsync(exitTcs.Task); diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs index a5910e7e..5f3c5270 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs @@ -3,8 +3,8 @@ namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// /// Pure, testable helpers for the debug stream command. The SignalR-driven /// body itself cannot be unit-tested without a live hub, so -/// the decision logic — connect-failure classification (CLI-010) and exit-code -/// resolution after stream termination (CLI-012) — is extracted here. +/// the decision logic — connect-failure classification and exit-code +/// resolution after stream termination — is extracted here. /// internal static class DebugStreamHelpers { diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TableAuditFormatter.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TableAuditFormatter.cs index b4775723..36fd341e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TableAuditFormatter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TableAuditFormatter.cs @@ -3,8 +3,8 @@ using System.Text.Json; namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// -/// Human-readable table formatter for audit query --format table (Audit Log -/// #23 M8-T6). Renders each fetched page as a column-aligned text table with a fixed +/// Human-readable table formatter for audit query --format table. +/// Renders each fetched page as a column-aligned text table with a fixed /// column set (). Long free-text fields (Target, Actor) are /// truncated with an ellipsis so columns stay aligned regardless of payload size. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs index 9d501039..df94a89e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs @@ -446,7 +446,7 @@ public static class TemplateCommands /// /// Determines whether --trigger-kind was supplied without a --trigger-config. /// In that case has no JSON object to inject - /// into and silently drops the kind (#257) — the caller should warn the user. + /// into and silently drops the kind — the caller should warn the user. /// /// The raw --trigger-config JSON value, or null when absent. /// The raw --trigger-kind value, or null when absent. @@ -502,7 +502,7 @@ public static class TemplateCommands var hiOption = new Option("--hi") { Description = "HiLo: high setpoint" }; var hiHiOption = new Option("--hihi") { Description = "HiLo: high-high setpoint" }; var expressionOption = new Option("--expression") { Description = "Expression: boolean trigger expression" }; - // M9-T28b: analysis kind for Expression triggers (advisory|strict; default advisory). + // Analysis kind for Expression triggers (advisory|strict; default advisory). // Writes "analysisKind":"Strict" into the trigger config when set to strict. var triggerKindOption = new Option("--trigger-kind") { @@ -567,7 +567,7 @@ public static class TemplateCommands var updateTriggerConfigOption = new Option("--trigger-config") { Description = "Trigger configuration JSON" }; var updateLockedOption = new Option("--locked") { Description = "Lock status" }; updateLockedOption.DefaultValueFactory = _ => false; - // M9-T28b: --trigger-kind for update (same semantics as add) + // --trigger-kind for update (same semantics as add) var updateTriggerKindOption = new Option("--trigger-kind") { Description = AlarmTriggerKindOptionDescription @@ -699,7 +699,7 @@ public static class TemplateCommands var returnOption = new Option("--return-def") { Description = "Return definition JSON" }; var minTimeOption = new Option("--min-time-between-runs") { Description = MinTimeBetweenRunsOptionDescription }; var execTimeoutOption = new Option("--execution-timeout-seconds") { Description = ExecutionTimeoutOptionDescription }; - // M9-T28b: analysis kind for Expression triggers (advisory|strict; default advisory). + // Analysis kind for Expression triggers (advisory|strict; default advisory). var scriptTriggerKindOption = new Option("--trigger-kind") { Description = ScriptTriggerKindOptionDescription @@ -758,7 +758,7 @@ public static class TemplateCommands var updateReturnOption = new Option("--return-def") { Description = "Return definition JSON" }; var updateMinTimeOption = new Option("--min-time-between-runs") { Description = MinTimeBetweenRunsOptionDescription }; var updateExecTimeoutOption = new Option("--execution-timeout-seconds") { Description = ExecutionTimeoutOptionDescription }; - // M9-T28b: --trigger-kind for update (same semantics as add) + // --trigger-kind for update (same semantics as add) var updateScriptTriggerKindOption = new Option("--trigger-kind") { Description = ScriptTriggerKindOptionDescription diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateTableProjection.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateTableProjection.cs index 5fe567ec..107ec22a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateTableProjection.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateTableProjection.cs @@ -4,7 +4,7 @@ using System.Text.Json.Nodes; namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// -/// Compact table projection for template list / template get (followup #6). +/// Compact table projection for template list / template get. /// The management API returns full Template entities — every attribute, alarm, /// script, and composition inline — which the generic table renderer dumps as one giant /// cell per template (~171 KB for a real catalogue, unusable in a terminal). This diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/ManagementHttpClient.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/ManagementHttpClient.cs index afdcc822..e1b62e62 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/ManagementHttpClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/ManagementHttpClient.cs @@ -93,7 +93,7 @@ public class ManagementHttpClient : IDisposable /// /// Issues a plain HTTP GET against a REST endpoint (e.g. the audit - /// /api/audit/query endpoint introduced by Audit Log #23 M8) and returns the + /// /api/audit/query endpoint) and returns the /// response body. Unlike , this does not wrap the call /// in the POST /management command envelope — the audit endpoints are plain /// REST resources. Authentication (HTTP Basic) and the base address are shared. diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Program.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Program.cs index d2b44425..78af1213 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Program.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Program.cs @@ -41,7 +41,7 @@ rootCommand.SetAction(_ => Console.WriteLine("Use --help to see available commands."); }); -// Deprecation notice for the pre-M8 `audit-log` command name. The command itself +// Deprecation notice for the earlier `audit-log` command name. The command itself // still works (it is an alias of `audit-config`), but using the old name emits a // warning to stderr so scripts can be migrated. AuditLogCommands.WriteDeprecationWarningIfNeeded(args, Console.Error); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs index b0f71a03..97d334eb 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs @@ -11,7 +11,7 @@ using ZB.MOM.WW.ScadaBridge.Security; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Audit; /// -/// Minimal-API endpoint hosting the Audit Log CSV export (#23 M7-T14 / Bundle F). +/// Minimal-API endpoint hosting the Audit Log CSV export. /// /// /// CentralUI ships no MVC controllers (see @@ -24,7 +24,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Audit; /// /// /// The route is gated on the -/// policy (#23 M7-T15 / Bundle G) so only roles with the bulk-export +/// policy so only roles with the bulk-export /// permission can pull a CSV — the page-level /// gate is read-only /// and intentionally narrower. The query-string parser silently drops diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs index 81017590..fbfaec89 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs @@ -45,7 +45,7 @@ public static class AuthEndpoints } // Map LDAP groups to roles via the shared IGroupRoleMapper seam - // (Task 1.1 ScadaBridgeGroupRoleMapper, wrapping the DB-backed RoleMapper). + // (ScadaBridgeGroupRoleMapper, wrapping the DB-backed RoleMapper). // The full RoleMappingResult — including PermittedSiteIds and the // system-wide flag — is carried in the mapping's opaque Scope so the // site-scope→SiteId claims below are built exactly as before. @@ -63,7 +63,7 @@ public static class AuthEndpoints : new RoleMappingResult(roleMapping.Roles, [], IsSystemWideDeployment: false); // Build claims from LDAP auth + role mapping. - // CentralUI-005: no fixed "expires_at" absolute-cap claim is stamped + // No fixed "expires_at" absolute-cap claim is stamped // — session expiry is owned by the cookie middleware's sliding window // (ZB.MOM.WW.ScadaBridge.Security AddCookie: ExpireTimeSpan = idle timeout, // SlidingExpiration = true). A frozen absolute claim would contradict @@ -71,11 +71,11 @@ public static class AuthEndpoints var displayName = string.IsNullOrEmpty(authResult.DisplayName) ? username : authResult.DisplayName; var resolvedUsername = string.IsNullOrEmpty(authResult.Username) ? username : authResult.Username; - // M2.19 (#15): build the cookie principal through the shared + // Build the cookie principal through the shared // SessionClaimBuilder — the SINGLE source of truth that the mid-session // OnValidatePrincipal role-refresh path ALSO uses, so login and refresh can // never drift. It stamps the canonical identity/role/scope claims (with - // roleType/nameType pinned for IsInRole), PLUS the M2.19 additions: one + // roleType/nameType pinned for IsInRole), PLUS these additions: one // zb:group claim per raw LDAP group (the durable input the mid-session // RoleMapper re-run consumes) and a zb:lastrolerefresh anchor (login time, // UTC) that also seeds the LastActivity idle anchor. The refresh timestamp is @@ -147,7 +147,7 @@ public static class AuthEndpoints }); }).DisableAntiforgery(); - // Logout is a state-changing authenticated action (CentralUI-017): it + // Logout is a state-changing authenticated action: it // keeps antiforgery validation enabled so it cannot be triggered // cross-site. The NavMenu sign-out form includes the antiforgery token // (rendered by the component). There is deliberately @@ -159,9 +159,9 @@ public static class AuthEndpoints context.Response.Redirect("/login"); }); - // CentralUI-020: liveness probe for the client-side idle-logout check. + // Liveness probe for the client-side idle-logout check. // The Blazor circuit's CookieAuthenticationStateProvider serves a frozen - // constructor-time principal (CentralUI-004), so a circuit can never + // constructor-time principal, so a circuit can never // observe a server-side cookie expiry by polling the auth state. // SessionExpiry instead polls this endpoint via fetch(): being a normal // HTTP request, the cookie middleware re-validates (and slides) the @@ -178,7 +178,7 @@ public static class AuthEndpoints /// /// Handler for GET /auth/ping. Returns 200 while the caller's /// cookie session is still valid and 401 once it has lapsed - /// server-side. See CentralUI-020. + /// server-side. /// /// The current HTTP context used to check authentication state and write the response. /// A task that represents the asynchronous operation. @@ -192,7 +192,7 @@ public static class AuthEndpoints /// /// Builds the for the login sign-in. - /// CentralUI-005: deliberately does not set . + /// Deliberately does not set . /// Session expiry is owned by the cookie authentication middleware's sliding /// window (configured in ZB.MOM.WW.ScadaBridge.Security's AddCookie: /// ExpireTimeSpan = the idle timeout, SlidingExpiration = true). diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs index b7c0c9ed..814b102a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs @@ -5,7 +5,7 @@ using ZB.MOM.WW.ScadaBridge.Security; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Auth; /// -/// Claim-lookup helpers for the Central UI. CentralUI-024: claim types are owned +/// Claim-lookup helpers for the Central UI. Claim types are owned /// by (the single source of truth). These helpers /// resolve them through the JwtTokenService constants so a rename there /// propagates here instead of silently breaking ten copy-pasted call sites. @@ -36,7 +36,7 @@ public static class ClaimsPrincipalExtensions /// /// Resolves the current user's audit username from the auth state provider. /// Replaces the GetCurrentUserAsync helper that was copy-pasted into - /// ten components (CentralUI-024). + /// ten components. /// /// The Blazor authentication state provider to read from. /// A task that resolves to the current user's audit username, or if not authenticated. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/CookieAuthenticationStateProvider.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/CookieAuthenticationStateProvider.cs index 23537236..f5d4be26 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/CookieAuthenticationStateProvider.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/CookieAuthenticationStateProvider.cs @@ -17,7 +17,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Auth; /// /// /// We must NOT read on every -/// call (CentralUI-004): for the +/// call: for the /// lifetime of a long-lived SignalR circuit HttpContext is null /// (or, worse, a stale/foreign context), so a later re-evaluation — /// e.g. <AuthorizeView> re-rendering — would otherwise see an diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs index 143d7bde..3925f4f2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs @@ -6,7 +6,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Auth; /// /// Resolves the set of sites the current user is permitted to operate on, from -/// the SiteId claims attached at login (CentralUI-002). +/// the SiteId claims attached at login. /// /// The design (Component-CentralUI, CLAUDE.md "Security & Auth") makes the /// Deployment role site-scoped: a Deployment user mapped through an LDAP group @@ -93,7 +93,7 @@ public sealed class SiteScopeService } // No SiteId claims => system-wide. Absence of scope rules means an - // unrestricted deployer (Security-017 made this service the sole + // unrestricted deployer (this service is the sole // site-scoping mechanism — there is no separate handler to mirror). var result = (IsSystemWide: ids.Count == 0, Sites: (IReadOnlySet)ids); _cached = result; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor index 16c03826..a1cd3d66 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor @@ -1,7 +1,7 @@ @using ZB.MOM.WW.ScadaBridge.CentralUI.Services @using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums -@* Audit Log drilldown drawer (#23 M7 Bundle C / M7-T4..T8). +@* Audit Log drilldown drawer. Right-side Bootstrap offcanvas-style drawer hosted by the Audit Log page. The drawer owns only the offcanvas chrome (backdrop, header, Close buttons); the single-AuditEvent detail body is delegated to , which diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor.cs index 725cbf4f..740ce1a9 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditDrilldownDrawer.razor.cs @@ -4,7 +4,7 @@ using ZB.MOM.WW.ScadaBridge.CentralUI.Services; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// -/// Child component for the central Audit Log page (#23 M7 Bundle C / M7-T4..T8). +/// Child component for the central Audit Log page. /// Renders one in a right-side off-canvas drawer. /// The drawer owns only the offcanvas chrome — backdrop, header, and the two /// Close buttons; the single-row detail body (read-only fields, conditional diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor index 4f2de256..437ccc4a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor @@ -1,7 +1,7 @@ @using ZB.MOM.WW.ScadaBridge.CentralUI.Services @using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums -@* Reusable single-AuditEvent detail body (#23 M7 Bundle C / M7-T4..T8). +@* Reusable single-AuditEvent detail body. Extracted from AuditDrilldownDrawer so the drawer and the execution-tree node-detail modal share one rendering of a row's detail. All form/field rendering follows the form-layout memory: diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor.cs index 818677d5..0ab4ca30 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditEventDetail.razor.cs @@ -9,8 +9,8 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// -/// Reusable single- detail body (#23 M7 Bundle C / -/// M7-T4..T8). Extracted verbatim from so +/// Reusable single- detail body. Extracted verbatim +/// from so /// the drawer and the execution-tree node-detail modal render a row's detail /// identically. Renders the read-only field list, the conditional /// Error/Request/Response/Extra subsections, and the action buttons (Copy as @@ -54,7 +54,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// is set the "View parent /// execution" button navigates to /audit/log?executionId={parentId} /// — the spawner's id used as the per-run drill-in target. All are deep -/// links the Audit Log page deserializes on init (Bundle D) and auto-loads. +/// links the Audit Log page deserializes on init and auto-loads. /// /// public partial class AuditEventDetail @@ -281,7 +281,7 @@ public partial class AuditEventDetail /// /// Drill-in to the execution-chain TREE view (Audit Log ParentExecutionId - /// feature, Task 10). Navigates to + /// feature). Navigates to /// /audit/execution-tree?executionId={ExecutionId} — the tree page /// resolves the whole chain rooted at the topmost ancestor and renders it /// expandably, with this row's execution highlighted. The button is only diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditFilterBar.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditFilterBar.razor.cs index c136aa9b..0ea32b0b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditFilterBar.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditFilterBar.razor.cs @@ -6,7 +6,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// -/// Filter bar for the central Audit Log page (#23 M7-T2). Owns the +/// Filter bar for the central Audit Log page. Owns the /// binding state and renders the filter controls /// — Channel as a single-select (one channel at a time, so the Kind options /// narrow to it cleanly); Kind / Status / Site as compact @@ -55,7 +55,7 @@ public partial class AuditFilterBar [Parameter] public Func? NowUtcProvider { get; set; } /// - /// Bundle D drill-in seam (#23 M7-T10..T12). When set on first render, + /// When set on first render, /// pre-populates the Instance free-text input. Instance is UI-only — the /// repository filter contract has no instance column — so this flows in /// through a separate parameter rather than the @@ -167,7 +167,7 @@ public partial class AuditFilterBar private async Task Apply() { - // CentralUI-026: binds with DateTimeKind.Unspecified + // binds with DateTimeKind.Unspecified // — the value is the user's browser-local wall-clock. Tag it as Local then convert // to UTC before the model emits the filter, otherwise a non-UTC operator's window // is silently shifted by their UTC offset. Done on a swap-and-restore basis so the diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs index 512beec5..53b4ef1e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs @@ -5,7 +5,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// -/// UI-side binding model for (#23 M7-T2). +/// UI-side binding model for . /// /// /// The model mirrors but allows multi-select chip diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs index 8f082aca..b30bcd15 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs @@ -8,7 +8,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// -/// Keyset-paged results grid for the central Audit Log page (#23 M7-T3). +/// Keyset-paged results grid for the central Audit Log page. /// Renders the columns named in Component-AuditLog.md §10 — OccurredAtUtc, /// Site, Channel, Kind, Status, Target, Actor, DurationMs, HttpStatus, /// ErrorMessage — plus the ExecutionId per-run correlation column and the @@ -66,7 +66,7 @@ public partial class AuditResultsGrid : IAsyncDisposable private bool _loading; private string? _error; - // CentralUI-032: small in-component stack of prior-page cursors so the user + // Small in-component stack of prior-page cursors so the user // can step backwards through results. Each Next push captures the cursor // that produced the current page (null for page 1) before advancing; each // Previous pop reloads the page at the recovered cursor. Mirrors the @@ -108,7 +108,7 @@ public partial class AuditResultsGrid : IAsyncDisposable [Parameter] public IReadOnlyList? ColumnOrder { get; set; } /// - /// Raised when the user clicks a row. Bundle C wires this to the drilldown + /// Raised when the user clicks a row. Consumers wire this to the drilldown /// drawer. The event payload is the full . /// [Parameter] public EventCallback OnRowSelected { get; set; } @@ -228,15 +228,15 @@ public partial class AuditResultsGrid : IAsyncDisposable AfterOccurredAtUtc: last.OccurredAtUtc, AfterEventId: last.EventId); - // CentralUI-032: remember the cursor that produced the current page so - // a later Previous can navigate back to it. The page-1 entry is pushed + // Remember the cursor that produced the current page so + // a later Previous can navigate back to it. The first-page entry is pushed // as null — LoadAsync treats null as "first page" (PageSize-only). _cursorStack.Push(_currentPaging); await LoadAsync(cursor); _pageNumber++; } - // CentralUI-032: pops the previous-page cursor off the stack and reloads + // Pops the previous-page cursor off the stack and reloads // at that position. The pop only happens AFTER a successful reload — a // failed page-fetch leaves the user on the current page with the error // banner instead of stranding them between pages. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionDetailModal.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionDetailModal.razor.cs index d00370f2..e6c0a9a2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionDetailModal.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionDetailModal.razor.cs @@ -8,8 +8,8 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// -/// Execution-Tree Node Detail Modal (Execution-Tree Node Detail Modal feature, -/// Task 3). Opened from an execution-tree node double-click: given an +/// Execution-Tree Node Detail Modal. Opened from an execution-tree node +/// double-click: given an /// it loads that execution's audit rows via /// and shows a list → per-row detail. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionTree.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionTree.razor.cs index 0749bfcf..2d076c69 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionTree.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/ExecutionTree.razor.cs @@ -6,7 +6,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit; /// /// Recursive Blazor tree component for the execution-chain view (Audit Log -/// ParentExecutionId feature, Task 10). +/// ParentExecutionId feature). /// /// /// Flat list → tree. The repository / query service returns the chain as diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/BrowserTime.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/BrowserTime.cs index 029ea6b5..45f0c492 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/BrowserTime.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/BrowserTime.cs @@ -7,7 +7,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components; /// /// CLAUDE.md mandates UTC throughout the system, but a datetime-local /// value carries no offset, so it must be converted to UTC, not relabelled -/// as UTC. Relabelling (the CentralUI-008 bug) shifts every query window by the +/// as UTC. Relabelling shifts every query window by the /// user's offset for any non-UTC browser. /// /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor index c4b727fe..d104982c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/NodeBrowserDialog.razor @@ -134,7 +134,7 @@ private string _failureMessage = ""; private List _rootNodes = new(); - // Search state (T16): _searchActive distinguishes "ran a search that found + // Search state: _searchActive distinguishes "ran a search that found // nothing" from "never searched"; a blank query clears the panel entirely. private string _searchQuery = ""; private bool _searchActive; @@ -157,7 +157,7 @@ public bool HasChildren { get; } /// - /// Friendly DataType name for Variable nodes (T15 type column); null when + /// Friendly DataType name for Variable nodes; null when /// not a Variable or the type read failed. Rendered as a muted badge. /// public string? DataType { get; init; } @@ -261,7 +261,7 @@ node.Expanded = true; } - // Load-more / BrowseNext (T15): fetch the next page under a truncated node, + // Load-more / BrowseNext: fetch the next page under a truncated node, // APPEND the children (preserve what's already shown + expanded), and refresh // the stored token (null → exhausted → the button disappears). private async Task LoadMoreAsync(TreeNode node) @@ -297,7 +297,7 @@ private Task SearchOnEnter(KeyboardEventArgs e) => e.Key == "Enter" ? SearchAsync() : Task.CompletedTask; - // Address-space search (T16): a blank query clears the panel; otherwise run + // Address-space search: a blank query clears the panel; otherwise run // the bounded recursive search and render matches as a flat selectable list. private async Task SearchAsync() { diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor index 6d53e9a7..8cedaacd 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Forms/OpcUaEndpointEditor.razor @@ -349,7 +349,7 @@ [Parameter] public bool IsLegacy { get; set; } [Parameter] public ValidationResult? Errors { get; set; } - // Verify-endpoint context (M7 T17): the site + connection identity the verify + // Verify-endpoint context (M7): the site + connection identity the verify // probe targets. Supplied by DataConnectionForm (_formSiteId → SiteIdentifier, // _formName, _protocol). When SiteIdentifier is blank the connection has not been // assigned a site yet, so verification is unavailable. @@ -394,7 +394,7 @@ } } - // M7 T17: trust the captured untrusted server certificate at every node of the + // M7: trust the captured untrusted server certificate at every node of the // owning site, then re-run Verify (which should now succeed and clear the cert // panel). Administrator-gated by the AuthorizeView wrapping the button; the // CertManagementService enforces the same role server-side-of-the-trust-boundary. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor index 845154af..59b53c69 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor @@ -1,5 +1,5 @@ @* - Audit Log (#23) M7 Bundle E (T13) — three Health-dashboard KPI tiles for the + Three Health-dashboard KPI tiles for the Audit channel: Volume / Error rate / Backlog. Renders Bootstrap card tiles in a single row, each acting as a navigation link to a pre-filtered Audit Log view. The component is purely presentational — the parent page owns the diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor.cs index cfbdb84a..ded5f2d8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/AuditKpiTiles.razor.cs @@ -4,11 +4,11 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Health; /// -/// Audit Log (#23) M7 Bundle E (T13) code-behind for . +/// Code-behind for . /// Renders three KPI tiles — volume, error rate, backlog — from a /// the parent page supplies. Tiles act as /// drill-in links: clicking navigates to /audit/log with the relevant -/// query-string filter pre-applied (Bundle D already parses these params). +/// query-string filter pre-applied (the page already parses these params). /// /// /// @@ -94,7 +94,7 @@ public partial class AuditKpiTiles { return "—"; } - // Format to one decimal so a 1-error-in-2000 rate doesn't round to 0%. + // Format to one decimal so a rate of 1 error in 2000 doesn't round to 0%. return $"{ErrorRatePercent:0.0}%"; } } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor index 58c6a700..f45ae8d3 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor @@ -58,7 +58,7 @@ {
Site Call KPIs unavailable: @ErrorMessage
} -@* ── Per-node stuck/parked sub-table (T6: M5.2 per-node stuck-count KPIs) ── *@ +@* ── Per-node stuck/parked sub-table ── *@ @if (HasNodeBreakdown) {
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor.cs index 6a99e091..0f118185 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Health/SiteCallKpiTiles.razor.cs @@ -5,7 +5,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Health; /// -/// Site Call Audit (#22) Task 7 code-behind for . +/// Site Call Audit code-behind for . /// Renders three KPI tiles — Buffered, Stuck, Parked — from a /// the parent Health dashboard supplies. /// Tiles act as drill-in links: clicking navigates to /site-calls/report @@ -61,7 +61,7 @@ public partial class SiteCallKpiTiles [Parameter] public string? ErrorMessage { get; set; } /// - /// Optional per-node KPI breakdown (T6: M5.2 per-node stuck-count KPIs). + /// Optional per-node KPI breakdown. /// When non-null and non-empty, a compact node-level stuck/parked sub-table /// is rendered below the main tiles. null means the parent has not /// loaded it yet or has opted out — the sub-table is suppressed entirely. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/MainLayout.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/MainLayout.razor index a65c2607..8647a44c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/MainLayout.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/MainLayout.razor @@ -8,7 +8,7 @@ - @* T34b: dark-mode toggle sits in the rail footer alongside the session + @* Dark-mode toggle sits in the rail footer alongside the session block. It is auth-agnostic (pure client-side theme) so it renders even on the login page. *@ diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/NavMenu.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/NavMenu.razor index 07d9e221..6519fd1b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/NavMenu.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/NavMenu.razor @@ -85,7 +85,7 @@ - @* Operations — Secured Writes (M7 T14b). Two-person MxGateway write workflow: + @* Operations — Secured Writes. Two-person MxGateway write workflow: Operator submits, a different Verifier approves/rejects. The section must show for Operator OR Verifier. There is no combined policy, so the OR is expressed as: Operator → render; otherwise (NotAuthorized) fall through to a Verifier @@ -124,8 +124,7 @@ - @* Audit — gated on the OperationalAudit policy (#23 M7-T15 - / Bundle G). Hosts the Audit Log page (#23 M7) and the + @* Audit — gated on the OperationalAudit policy. Hosts the Audit Log page (#23 M7) and the Configuration Audit Log (IAuditService config-change viewer). The whole section sits inside the policy block: a non-audit user does not even see the heading. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeyForm.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeyForm.razor index 66d4fe3f..8d2aae0f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeyForm.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeyForm.razor @@ -29,7 +29,7 @@ @:Add API Key } - @* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit Log + @* Drill-in: deep-link into the central Audit Log pre-filtered to this API key's inbound calls. Inbound audit rows record the key Name as Actor and live on the ApiInbound channel. *@ @if (IsEditMode && !string.IsNullOrWhiteSpace(_formName)) @@ -112,7 +112,7 @@
@code { - // Inbound-API key re-arch (C3): this form drives the IInboundApiKeyAdmin seam. + // Inbound-API key re-arch: this form drives the IInboundApiKeyAdmin seam. // Keys are identified by an opaque string KeyId; method access is a set of method // NAMES (scopes) carried on the key, replacing the old ApiMethod.ApprovedApiKeyIds CSV. // The list of all methods still comes from IInboundApiRepository (methods stay in SQL). diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeys.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeys.razor index a0adf48a..6d677e4a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeys.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeys.razor @@ -97,7 +97,7 @@ @code { - // Inbound-API key re-arch (C3): this page reads keys from the IInboundApiKeyAdmin seam + // Inbound-API key re-arch: this page reads keys from the IInboundApiKeyAdmin seam // (string KeyId, method-scopes) rather than the SQL Server ApiKey entity. The seam has no // retrievable hash, so the old masked Key-Hash column is gone; KeyId identifies each row. private List _keys = new(); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/SiteForm.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/SiteForm.razor index ce570613..631d279d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/SiteForm.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/SiteForm.razor @@ -22,7 +22,7 @@
@(IsEditMode ? "Edit Site" : "Add Site")
- @* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit + @* Drill-in: deep-link into the central Audit Log pre-filtered to this site's events. AuditEvent.SourceSiteId stores the SiteIdentifier (string), so we pass that through. *@ @if (IsEditMode && !string.IsNullOrWhiteSpace(_formIdentifier)) diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor index bbf9e444..1e492af4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor @@ -12,7 +12,7 @@

Audit Log

- @* Trends panel (M6 / K15). A best-effort collapsible Bootstrap card sitting + @* Trends panel. A best-effort collapsible Bootstrap card sitting above the audit query UI: one KpiTrendChart per AuditLog global metric over a 24h (default) / 7d window. Series are fetched independently in the code-behind — a failed fetch degrades only that chart to the unavailable @@ -62,22 +62,22 @@ }
- @* Filter bar (Bundle B / M7-T2). Apply hands the collapsed filter to the grid. - Bundle D (M7-T10..T12) threads a query-string instance prefill through + @* Filter bar. Apply hands the collapsed filter to the grid. + Threads a query-string instance prefill through InitialInstanceSearch — UI-only because the filter contract has no instance column. *@
- @* Export button (Bundle F / M7-T14). A plain link triggers the + @* Export button. A plain link triggers the streaming CSV endpoint at /api/centralui/audit/export — chosen over a SignalR-driven download because the request can stream 100k rows directly to the response body without buffering through the Blazor circuit. The href reflects the most recently applied filter; before Apply is clicked, an unconstrained export is exposed. - Bundle G (#23 M7-T15) gates the button on the AuditExport policy so an + Gates the button on the AuditExport policy so an OperationalAudit-only operator (read access without bulk export) sees the page + filters but cannot trigger the CSV pull. The endpoint itself is gated separately, so a hand-crafted URL still 403s — the AuthorizeView @@ -96,7 +96,7 @@ - @* Results grid (Bundle B / M7-T3). Row clicks emit OnRowSelected for Bundle C's + @* Results grid. Row clicks emit OnRowSelected for the drilldown drawer; the grid stays in "no events" mode until the user applies a filter so the page does not auto-load the full audit table on first render. *@
@@ -104,7 +104,7 @@
-@* Drilldown drawer (Bundle C / M7-T4..T8). Hosted at the page level so the +@* Drilldown drawer. Hosted at the page level so the off-canvas overlay sits above the grid / filter bar irrespective of scroll. *@ -/// Code-behind for the central Audit Log page (#23 M7). Bundle B (M7-T2 + M7-T3) -/// wires up AuditFilterBar and AuditResultsGrid: the page owns the +/// Code-behind for the central Audit Log page. Wires up AuditFilterBar +/// and AuditResultsGrid: the page owns the /// active and re-pushes a fresh instance to the /// grid on every Apply (the grid uses reference identity as its "reload" /// trigger). Row clicks land in , which pins /// the selected row and opens the drilldown drawer. /// /// -/// Bundle D (M7-T10..T12) adds query-string drill-in parsing so other pages can +/// Adds query-string drill-in parsing so other pages can /// deep-link to a pre-filtered Audit Log: ?correlationId=, ?target=, /// ?actor=, ?site=, ?channel=, ?kind=, and the UI-only -/// ?instance= are read on initialization. Bundle E (M7-T13) extends -/// this with ?status= so the Health-dashboard Audit error-rate tile can +/// ?instance= are read on initialization. This extends +/// with ?status= so the Health-dashboard Audit error-rate tile can /// drill in to ?status=Failed. The ExecutionId follow-up adds /// ?executionId= for the "View this execution" drill-in, and the /// ParentExecutionId follow-up adds ?parentExecutionId= for the @@ -51,7 +51,7 @@ public partial class AuditLogPage : IDisposable [Inject] private NavigationManager Navigation { get; set; } = null!; /// - /// KPI-history facade for the M6 (K15) Trends panel — fetched per metric, + /// KPI-history facade for the Trends panel — fetched per metric, /// per window. Best-effort: a failed series fetch degrades that one chart to /// the unavailable placeholder and never breaks the audit query UI. /// @@ -187,7 +187,7 @@ public partial class AuditLogPage : IDisposable IReadOnlyList? kinds = AuditQueryParamParsers.ParseEnumList(Raw(query, "kind")); - // Bundle E (M7-T13): the Health-dashboard Audit error-rate tile drills in + // The Health-dashboard Audit error-rate tile drills in // with ?status=Failed (and operators may craft URLs with Parked/Discarded). // Unknown values are silently dropped — the page still renders without // the constraint. @@ -248,7 +248,7 @@ public partial class AuditLogPage : IDisposable private void HandleRowSelected(AuditEventView row) { - // Bundle C: a grid row click hands us the full AuditEvent. We pin it as + // A grid row click hands us the full AuditEvent. We pin it as // the selected row and open the drilldown drawer — the drawer is fully // presentational so we do not need to refetch the row. _selectedEvent = row; @@ -263,7 +263,7 @@ public partial class AuditLogPage : IDisposable } // ───────────────────────────────────────────────────────────────────────── - // M6 (K15) — Audit Log trend charts. + // Audit Log trend charts. // // A best-effort Trends panel that sits above the audit query UI: one // KpiTrendChart per AuditLog global metric, over a 24h (default) or 7d @@ -278,8 +278,7 @@ public partial class AuditLogPage : IDisposable /// /// True while a window's series are being (re)fetched — disables the 24h/7d - /// window toggle buttons so a mid-flight click cannot stack overlapping loads - /// (mirrors the K13/K14 trend pages). + /// window toggle buttons so a mid-flight click cannot stack overlapping loads. /// private bool _trendsLoading; @@ -367,7 +366,7 @@ public partial class AuditLogPage : IDisposable } /// - /// Bundle F (M7-T14): URL the Export-CSV link points at. Renders the most + /// URL the Export-CSV link points at. Renders the most /// recently applied filter as query-string params so the server-side /// streaming endpoint reproduces the user's current view. With no filter /// applied yet, returns the bare endpoint — i.e. an unconstrained export. @@ -394,7 +393,7 @@ public partial class AuditLogPage : IDisposable // No capacity hint: the dimensions are multi-value, so the part count is // unbounded by the number of filter fields. var parts = new List>(); - // Task 9: the filter dimensions are multi-value end-to-end. Emit ONE + // The filter dimensions are multi-value end-to-end. Emit ONE // repeated query-string key per selected value (channel=A&channel=B); the // export endpoint's ParseFilter reads the full repeated set. if (filter.Channels is { Count: > 0 } channels) diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor index 19690234..59017d60 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor @@ -13,7 +13,7 @@ - @* Bundle Import filter chip (T24). Set via ?bundleImportId={guid} query + @* Bundle Import filter chip. Set via ?bundleImportId={guid} query string so drill-ins from the Import wizard / other pages can scope this page to a single import run. Cleared via the × button, which navigates back to the page without the query param so the user sees all rows. *@ @@ -192,7 +192,7 @@ @code { /// - /// T24 (Transport). When non-null, scopes the page to a single bundle + /// When non-null, scopes the page to a single bundle /// import run. Set via the ?bundleImportId= query string from /// drill-ins (Import wizard summary, future BundleImported row links). /// @@ -256,7 +256,7 @@ protected override async Task OnParametersSetAsync() { - // T24: when the BundleImportId query param is set (or cleared), refetch + // When the BundleImportId query param is set (or cleared), refetch // automatically so the user lands on a pre-filtered page from a drill-in // link without having to click Search. if (BundleImportId != _lastFetchedBundleImportId) diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ExecutionTreePage.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ExecutionTreePage.razor.cs index 5cecac96..5b583d13 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ExecutionTreePage.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ExecutionTreePage.razor.cs @@ -6,7 +6,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Audit; /// /// Code-behind for the execution-chain tree page (Audit Log ParentExecutionId -/// feature, Task 10). Route /audit/execution-tree, reached via the Audit +/// feature). Route /audit/execution-tree, reached via the Audit /// Log drilldown drawer's "View execution chain" action with /// ?executionId={guid}. /// @@ -40,7 +40,7 @@ public partial class ExecutionTreePage private bool _loading; private string? _error; - // Execution-Tree Node Detail Modal feature (Task 4) — state backing the + // Execution-Tree Node Detail Modal feature — state backing the // . A double-click on a tree node sets // _modalExecutionId + flips _modalOpen true; the modal loads that // execution's audit rows on the closed → open transition. _modalOpen is the diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeBuilder.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeBuilder.cs index 6448e1a3..6d2c22fe 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeBuilder.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeBuilder.cs @@ -4,8 +4,8 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Deployment; /// -/// Pure (no Blazor/DI) builder that turns a flat list of streamed attribute (and, -/// in DV-4, alarm) events into a collapsible composition forest of +/// Pure (no Blazor/DI) builder that turns a flat list of streamed attribute (and +/// alarm) events into a collapsible composition forest of /// . Path-qualified canonical names are split on /// '.' to derive branch nodes; the terminal segment carries the payload. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeNode.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeNode.cs index 157361ed..b2db31e6 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeNode.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugTreeNode.cs @@ -4,7 +4,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; // AlarmState namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Deployment; /// -/// A node in a Debug View composition tree. Attribute (and, in DV-4, alarm) +/// A node in a Debug View composition tree. Attribute (and alarm) /// names are path-qualified canonical names (e.g. Motor1.Compressor.Pump); /// the tree is derived by splitting those names on '.'. A node is either a /// branch (composition member, no payload, has children) or a leaf (one attribute @@ -22,9 +22,9 @@ public sealed class DebugTreeNode // Leaf payloads — exactly one is set on a leaf; both null on a pure branch. public AttributeValueChanged? Attribute { get; init; } - public AlarmStateChanged? Alarm { get; init; } // computed leaf, native condition, or placeholder (DV-4) + public AlarmStateChanged? Alarm { get; init; } // computed leaf, native condition, or placeholder - public bool IsNativeBinding { get; init; } // branch grouping native conditions (DV-4) + public bool IsNativeBinding { get; init; } // branch grouping native conditions // Roll-up (set by the builder for branch nodes). public AlarmState WorstState { get; set; } = AlarmState.Normal; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor index 41aa22cf..84270fc4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor @@ -25,7 +25,7 @@

Configure Instance

- @* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit Log + @* Drill-in: deep-link into the central Audit Log pre-filtered to this instance. Instance is UI-only on the filter bar (AuditEvent has no Instance column), so we use the ?instance= UI-text seam — the filter bar's Instance free-text input is pre-populated. *@ @@ -178,7 +178,7 @@
Attribute Overrides - @* M7-T16: bulk import of attribute overrides from a CSV + @* Bulk import of attribute overrides from a CSV (AttributeName,Value[,ElementType]). Selecting a file parses + validates it against this instance's overridable attributes and — all-or-nothing — applies every row through the SAME @@ -598,7 +598,7 @@ // un-parseable List element caught on the pre-submit round-trip). private Dictionary _overrideErrors = new(); - // M7-T16: CSV bulk-import result summary. _csvImportResult is the headline + // CSV bulk-import result summary. _csvImportResult is the headline // ("Imported N overrides." or "Import rejected — N error(s)."); on failure the // per-line messages are listed from _csvImportErrors. Null until an import runs. private string? _csvImportResult; @@ -1047,7 +1047,7 @@ _saving = false; } - // ── M7-T16: CSV bulk override import ──────────────────── + // ── CSV bulk override import ──────────────────── /// /// Handles a selected override CSV. Reads the file text (size-capped), parses it diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor.cs index d71302c6..17f7a130 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor.cs @@ -6,7 +6,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Deployment; /// /// Code-behind for InstanceConfigure.razor — hosts the pure, side-effect-free -/// core of the CSV bulk-override import (M7-T16) so it can be unit-pinned without +/// core of the CSV bulk-override import so it can be unit-pinned without /// standing up the page's ≈7 injected services. The Razor side reads the uploaded /// file's text, calls , then feeds the result /// here; on success it applies the returned dict through the SAME diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor index 67067d8e..f1077f7a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor @@ -198,7 +198,7 @@ private IReadOnlyList _markers = Array.Empty(); - // Inbound-API key re-arch (C3): the approved-keys list is driven by the IInboundApiKeyAdmin + // Inbound-API key re-arch: the approved-keys list is driven by the IInboundApiKeyAdmin // seam, not ApiMethod.ApprovedApiKeyIds. The ApiMethod entity itself (name/script/params/etc.) // still lives on IInboundApiRepository — only the key↔method approval relationship moved to // per-key method-scopes. Keys are identified by an opaque string KeyId. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/DataConnections.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/DataConnections.razor index 7e23f80c..b69f207b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/DataConnections.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/DataConnections.razor @@ -213,7 +213,7 @@ private ToastNotification _toast = default!; - // M9-T25: live per-connection health, keyed by DataConnection.Id. Sourced from + // Live per-connection health, keyed by DataConnection.Id. Sourced from // the existing site→central health transport via IConnectionHealthQueryService // and refreshed on a ~10s poll, mirroring the Health dashboard's timer pattern. // A connection absent from the map renders an "Unknown" badge (tolerates a site @@ -419,7 +419,7 @@ } } - // ── M9-T24b / T33b: Move connection to another site ── + // ── Move connection to another site ── // Opened via IDialogService.ShowAsync. The body dispatches MoveDataConnectionCommand // through the guard-running ManagementActor path (IDataConnectionMoveService) — NOT // a direct repository write — so the server enforces the Designer gate and every @@ -451,7 +451,7 @@ .Select(r => (r.SiteId!.Value, r.Label)) .ToList(); - // M9-T25: enum → Bootstrap badge class. Mirrors the Health dashboard's + // Enum → Bootstrap badge class. Mirrors the Health dashboard's // GetConnectionHealthBadge (Components/Pages/Monitoring/Health.razor) so the // design page surfaces the same colour coding for the same status. Kept as a // small local mirror — the Health helper is a private page-local method, not a diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ExternalSystemForm.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ExternalSystemForm.razor index 6ed84a38..35acb1f5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ExternalSystemForm.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ExternalSystemForm.razor @@ -12,7 +12,7 @@

@(Id.HasValue ? "Edit External System" : "Add External System")

- @* Bundle D (#23 M7-T12) drill-in: deep-link into the central Audit Log + @* Drill-in: deep-link into the central Audit Log pre-filtered to this external system's outbound API events. Audit rows record the target by external-system name, so we filter on Target. *@ @if (Id.HasValue && !string.IsNullOrWhiteSpace(_name)) diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SchemaLibrary.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SchemaLibrary.razor index aaecdb6e..65e89849 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SchemaLibrary.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SchemaLibrary.razor @@ -6,9 +6,9 @@ @inject ISchemaLibraryService SchemaLibraryService @inject IDialogService Dialog -@* Schema Library (M9-T32c): list + create/edit (via SchemaBuilder) + delete the +@* Schema Library: list + create/edit (via SchemaBuilder) + delete the reusable named JSON-Schema library entries that the {"$ref":"lib:Name"} resolver - (T32b) resolves against. Every mutation is dispatched through ISchemaLibraryService + resolves against. Every mutation is dispatched through ISchemaLibraryService — the guard-running ManagementActor path — never a direct repo write. *@
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TemplateEdit.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TemplateEdit.razor index 74933952..1d35d9c2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TemplateEdit.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TemplateEdit.razor @@ -64,7 +64,7 @@ private Template? _ownerTemplate; private TemplateComposition? _ownerComposition; - // M9-T26b: the FULL transitively-resolved inherited member set (multi-level + // M9: the FULL transitively-resolved inherited member set (multi-level // chain + post-creation base additions) + staleness, fetched read-only via // GetResolvedTemplateMembersCommand. Populated only for derived templates; // null when the read failed (editor falls back to the stored-row view). @@ -228,7 +228,7 @@ } } - // M9-T26b: resolve the FULL inherited member set (whole chain + + // M9: resolve the FULL inherited member set (whole chain + // post-creation base additions) read-only. The stored-row tables // above only carry the IMMEDIATE base; this surfaces the rest with // origin annotation + a base-changed staleness banner. Read-only: @@ -314,7 +314,7 @@
} - @* M9-T26b: the FULL transitively-resolved inherited member set — the whole + @* M9: the FULL transitively-resolved inherited member set — the whole chain (grandparent + further ancestors) plus base members added after this template was created, which the immediate-base tables below cannot show. Read-only preview; each row carries its origin template + lock @@ -473,7 +473,7 @@ } }; - // ---- M9-T26b: full resolved inherited set (read-only preview) ---- + // ---- M9: full resolved inherited set (read-only preview) ---- /// /// Renders the FULL transitively-resolved effective member set (attributes, diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/Templates.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/Templates.razor index bbab8839..459a47d9 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/Templates.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/Templates.razor @@ -425,7 +425,7 @@ } } - // ---- Sibling reorder (T23b) ---- + // ---- Sibling reorder ---- // Dispatches the reorder the same way Move/Rename do — directly through // TemplateFolderService (the backend swaps SortOrder with the adjacent // same-parent sibling, no-op at the ends) — then reloads so the new order @@ -471,7 +471,7 @@ .ToList(); } - // ---- Root-level context menu (T23b) ---- + // ---- Root-level context menu ---- // Right-click on the tree zone (empty space or below the tree) offers // New Folder / New Template at root. Node right-clicks are handled by the // TreeView's own context menu and never reach here. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor index 1b58a542..847f4b2f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor @@ -9,7 +9,7 @@ @attribute [Authorize(Policy = AuthorizationPolicies.RequireDesign)] @* - TransportExport wizard (Component #24, Task T21). + TransportExport wizard (Component #24). A 4-step linear wizard: Step 1 — Select : templates (tree, checkbox-mode) + flat artifact lists. @@ -138,7 +138,7 @@ @RenderCheckboxList(_smtpConfigs, s => s.Id, s => s.Host, _selectedSmtpConfigs) - @* S10c: SMS provider configs, mirroring the SMTP section above. Labelled by + @* SMS provider configs, mirroring the SMTP section above. Labelled by AccountSid (the bundle key); the secret AuthToken is never rendered. *@
SMS Configurations @@ -361,12 +361,12 @@ {
  • SmtpConfig: @s.Host
  • } - @* S10c: SMS configs in the closure, mirroring SmtpConfig above; AccountSid only, never AuthToken. *@ + @* SMS configs in the closure, mirroring SmtpConfig above; AccountSid only, never AuthToken. *@ @foreach (var s in _resolved.SmsConfigs.OrderBy(s => s.AccountSid, StringComparer.OrdinalIgnoreCase)) {
  • SmsConfig: @s.AccountSid
  • } - @* Inbound API keys are not transported (re-arch C4) — methods only. *@ + @* Inbound API keys are not transported — methods only. *@ @foreach (var m in _resolved.ApiMethods.OrderBy(m => m.Name, StringComparer.OrdinalIgnoreCase)) {
  • ApiMethod: @m.Name
  • diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs index ade47607..77d7a5e3 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs @@ -20,7 +20,7 @@ using ZB.MOM.WW.ScadaBridge.Transport.Export; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Design; /// -/// Code-behind for the TransportExport wizard (Transport feature, Task T21). +/// Code-behind for the TransportExport wizard (Transport feature). /// /// Four-step state machine: /// @@ -72,12 +72,12 @@ public partial class TransportExport : ComponentBase private List _dbConnections = new(); private List _notificationLists = new(); private List _smtpConfigs = new(); - // S10c: SMS provider configs, mirroring _smtpConfigs. Keyed by AccountSid in the + // SMS provider configs, mirroring _smtpConfigs. Keyed by AccountSid in the // bundle; the wizard selects by entity id (same as SMTP) and never surfaces AuthToken. private List _smsConfigs = new(); - // Inbound API keys are not transported between environments (re-arch C4); only methods. + // Inbound API keys are not transported between environments; only methods. private List _apiMethods = new(); - // M8 (E1): site/instance-scoped export. Sites are listed flat; each site's + // Site/instance-scoped export. Sites are listed flat; each site's // instances hang off it (loaded eagerly via ISiteRepository.GetInstancesBySiteIdAsync) // so the operator can pick a whole site or drill into individual instances. private List _sites = new(); @@ -93,11 +93,11 @@ public partial class TransportExport : ComponentBase private readonly HashSet _selectedDbConnections = new(); private readonly HashSet _selectedNotificationLists = new(); private readonly HashSet _selectedSmtpConfigs = new(); - // S10c: SMS provider config selection, mirroring _selectedSmtpConfigs. + // SMS provider config selection, mirroring _selectedSmtpConfigs. private readonly HashSet _selectedSmsConfigs = new(); - // No _selectedApiKeys: inbound API keys are not transported (re-arch C4). + // No _selectedApiKeys: inbound API keys are not transported. private readonly HashSet _selectedApiMethods = new(); - // M8 (E1): site/instance selection backed by entity primary keys, matching the + // Site/instance selection backed by entity primary keys, matching the // DependencyResolver's SiteIds/InstanceIds (NOT names — the resolver fetches by id). private readonly HashSet _selectedSites = new(); private readonly HashSet _selectedInstances = new(); @@ -143,12 +143,12 @@ public partial class TransportExport : ComponentBase _dbConnections = (await ExternalRepo.GetAllDatabaseConnectionsAsync()).ToList(); _notificationLists = (await NotificationRepo.GetAllNotificationListsAsync()).ToList(); _smtpConfigs = (await NotificationRepo.GetAllSmtpConfigurationsAsync()).ToList(); - // S10c: SMS provider configs, mirroring the SMTP load path above. + // SMS provider configs, mirroring the SMTP load path above. _smsConfigs = (await NotificationRepo.GetAllSmsConfigurationsAsync()).ToList(); - // Inbound API keys are not transported (re-arch C4) — only methods are loaded. + // Inbound API keys are not transported — only methods are loaded. _apiMethods = (await InboundApiRepo.GetAllApiMethodsAsync()).ToList(); - // M8 (E1): sites + their instances for site/instance-scoped export. Each + // Sites + their instances for site/instance-scoped export. Each // site's instances are loaded eagerly so the expandable picker has them // without a per-click round-trip; sites are ordered by identifier to match // the bundle's deterministic site ordering. @@ -245,17 +245,17 @@ public partial class TransportExport : ComponentBase DatabaseConnectionIds: _selectedDbConnections.ToList(), NotificationListIds: _selectedNotificationLists.ToList(), SmtpConfigurationIds: _selectedSmtpConfigs.ToList(), - // Inbound API keys are not transported (re-arch C4) — methods only. + // Inbound API keys are not transported — methods only. ApiMethodIds: _selectedApiMethods.ToList(), IncludeDependencies: _includeDependencies) { - // M8 (E1): site/instance ids feed the resolver's SiteIds/InstanceIds. + // Site/instance ids feed the resolver's SiteIds/InstanceIds. // Set via init-only properties so the positional ctor stays the documented // additive shape; the resolver dedups a selected instance against its // already-selected owning site. SiteIds = _selectedSites.ToList(), InstanceIds = _selectedInstances.ToList(), - // S10c: SMS provider config ids feed the resolver's SmsConfigurationIds, + // SMS provider config ids feed the resolver's SmsConfigurationIds, // exactly as SmtpConfigurationIds above (init-only, trailing additive shape). SmsConfigurationIds = _selectedSmsConfigs.ToList(), }; @@ -325,7 +325,7 @@ public partial class TransportExport : ComponentBase { if (!string.IsNullOrEmpty(smtp.Credentials)) count++; } - // S10c: SMS provider AuthToken is a secret, mirroring SMTP Credentials above. + // SMS provider AuthToken is a secret, mirroring SMTP Credentials above. foreach (var sms in resolved.SmsConfigs) { if (!string.IsNullOrEmpty(sms.AuthToken)) count++; @@ -485,7 +485,7 @@ public partial class TransportExport : ComponentBase else set.Remove(id); } - // ---- Step 1 site/instance helpers (M8 E1) ---- + // ---- Step 1 site/instance helpers ---- /// Instances loaded for a site, or an empty list when the site has none. private IReadOnlyList InstancesFor(int siteId) => diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportImport.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportImport.razor.cs index 1b8b2d0e..f81f3582 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportImport.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportImport.razor.cs @@ -17,7 +17,7 @@ using ZB.MOM.WW.ScadaBridge.Transport.Import; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Design; /// -/// Code-behind for the TransportImport wizard (Transport feature, Task T22). +/// Code-behind for the TransportImport wizard (Transport feature). /// /// Five-step state machine: /// @@ -42,7 +42,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Design; /// /// Cached bundle bytes: because currently /// peeks the manifest by attempting decryption, encrypted bundles require two -/// LoadAsync invocations. CentralUI-031: we previously cached the raw bytes in a +/// LoadAsync invocations. We previously cached the raw bytes in a /// byte[] _bundleBytes field, which buffered the full upload (default cap /// 100 MB) in the component's per-circuit state — multiplied across concurrent /// operator sessions, that produced real central-node memory pressure. The @@ -71,7 +71,7 @@ public partial class TransportImport : ComponentBase, IDisposable [Inject] private IAuditService AuditService { get; set; } = default!; [Inject] private ScadaBridgeDbContext DbContext { get; set; } = default!; - // M8 E2: the Map step needs the destination environment's sites + each + // The Map step needs the destination environment's sites + each // site's connections to populate the "map to existing target" dropdowns. [Inject] private ISiteRepository SiteRepo { get; set; } = default!; @@ -80,7 +80,7 @@ public partial class TransportImport : ComponentBase, IDisposable private string? _errorMessage; // ---- Session + cached bundle path ---- - // CentralUI-031: the upload is streamed to a per-session temp file and only + // The upload is streamed to a per-session temp file and only // the path is retained on the component, so we don't hold an entire bundle // (up to MaxBundleSizeMb, default 100 MB) in per-circuit memory across the // wizard's lifetime. The file is deleted on every wizard reset path and on @@ -105,7 +105,7 @@ public partial class TransportImport : ComponentBase, IDisposable // Keyed by (EntityType, Name) — matches BundleImporter.ApplyAsync's lookup. private Dictionary<(string EntityType, string Name), ImportResolution>? _resolutions; - // ---- Step 3 (Map sub-section, M8 E2): name mapping ---- + // ---- Step 3 (Map sub-section): name mapping ---- // The sentinel dropdown value for "Create new" — empty string can't collide // with a real SiteIdentifier / connection Name (both are non-empty). private const string CreateNewValue = ""; @@ -160,7 +160,7 @@ public partial class TransportImport : ComponentBase, IDisposable return; } - // CentralUI-031: stream the upload directly to a per-session temp + // Stream the upload directly to a per-session temp // file so the central node's working set is bounded by the // FileStream buffer (~80 KB) rather than the full bundle bytes. // OpenReadStream's MaxAllowedSize defaults to 500_000 bytes — bump @@ -209,7 +209,7 @@ public partial class TransportImport : ComponentBase, IDisposable } try { - // CentralUI-031: read the staged bundle straight off disk; the + // Read the staged bundle straight off disk; the // importer's LoadAsync only walks the stream forward, so a plain // FileStream is sufficient (no need to buffer it back into memory). using var stream = new FileStream( @@ -435,7 +435,7 @@ public partial class TransportImport : ComponentBase, IDisposable } /// - /// M8 E2: prepares the Map sub-section state for a freshly loaded preview. + /// Prepares the Map sub-section state for a freshly loaded preview. /// When the preview carries no required site/connection mappings this is a /// no-op (the Map section is hidden) and we skip the site/connection reads /// entirely — central-config-only bundles never touch the destination's @@ -564,7 +564,7 @@ public partial class TransportImport : ComponentBase, IDisposable } /// - /// M8 E2: folds the operator's Map-step choices into a . + /// Folds the operator's Map-step choices into a . /// A concrete chosen target → with that /// target identifier/name; the "Create new" sentinel → /// with a null target. Iterates the preview's required mappings so the map's shape @@ -607,7 +607,7 @@ public partial class TransportImport : ComponentBase, IDisposable } /// - /// M8 E2: parses a Modified item's FieldDiffJson and returns the + /// Parses a Modified item's FieldDiffJson and returns the /// lineDiff object for the first code field that carries one, or null /// when the diff has no line-level payload (ordinary fields render as a coarse /// summary instead). Tolerant of malformed/absent JSON — a parse failure @@ -772,7 +772,7 @@ public partial class TransportImport : ComponentBase, IDisposable try { var user = await Auth.GetCurrentUsernameAsync(); - // M8 E2: fold the operator's Map-step choices into the name map. For + // Fold the operator's Map-step choices into the name map. For // central-config-only bundles (no required mappings) this is // BundleNameMap.Empty, which the importer normalises away. var nameMap = BuildNameMap(); @@ -814,7 +814,7 @@ public partial class TransportImport : ComponentBase, IDisposable _confirmEnvironmentText = string.Empty; _result = null; _validationErrors = null; - // M8 E2: clear the Map sub-section state too. + // Clear the Map sub-section state too. _targetSites = Array.Empty(); _targetConnections.Clear(); _siteChoices.Clear(); @@ -822,7 +822,7 @@ public partial class TransportImport : ComponentBase, IDisposable } /// - /// CentralUI-031: deletes the staged bundle temp file if any. Swallows IO + /// Deletes the staged bundle temp file if any. Swallows IO /// failures — an undeletable temp file is best-effort cleanup and must not /// block the wizard. /// @@ -852,7 +852,7 @@ public partial class TransportImport : ComponentBase, IDisposable } /// - /// CentralUI-031: ensures the staged temp file does not survive circuit + /// Ensures the staged temp file does not survive circuit /// teardown. Blazor invokes Dispose when the user navigates away or the /// circuit ends, so an abandoned wizard cleans up automatically. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor index f237283f..2cc8fc12 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor @@ -72,13 +72,13 @@ PerNodeSnapshots="@_siteCallNodeKpis" PerNodeAvailable="@_siteCallNodeKpiAvailable" /> - @* Audit Log (#23) M7 Bundle E — three KPI tiles for the Audit channel + @* Three KPI tiles for the Audit channel (volume / error rate / backlog). Refreshed alongside the site states. *@ - @* Site Health Trends (M6 K16) — per-site Site Health KPI history. Loads on a + @* Site Health Trends (M6) — per-site Site Health KPI history. Loads on a separate path from the 10s tile-refresh timer so a trend-query fault can never disturb the live dashboard or its polling loop. The site selector reuses the site keys already loaded into _siteStates; the window toggle @@ -438,7 +438,7 @@ private bool _outboxKpiAvailable; private string? _outboxKpiError; - // Audit Log (#23) M7 Bundle E — Audit KPI tiles. Volume + error rate come + // Audit KPI tiles. Volume + error rate come // from a 1h aggregate over the central AuditLog table; backlog sums the // per-site SiteAuditBacklog.PendingCount via the health aggregator. private AuditLogKpiSnapshot? _auditKpi; @@ -452,13 +452,13 @@ private bool _siteCallKpiAvailable; private string? _siteCallKpiError; - // Per-node Site Call KPI breakdown (T6: M5.2 per-node stuck-count KPIs). + // Per-node Site Call KPI breakdown (M5.2 per-node stuck-count KPIs). // Passed to SiteCallKpiTiles as an optional sub-table. private IReadOnlyList _siteCallNodeKpis = Array.Empty(); private bool _siteCallNodeKpiAvailable; - // ── Site Health Trends (M6 K16) ─────────────────────────────────────────── + // ── Site Health Trends (M6) ─────────────────────────────────────────────── // Per-site Site Health KPI history, loaded on a path entirely separate from // the 10s tile-refresh timer (LoadSiteHealthTrendsAsync, never called from // the timer tick). The site keys are a snapshot of the dashboard's site set, @@ -512,7 +512,7 @@ await RefreshNow(); - // Site Health Trends (M6 K16) load on their own path — never from the + // Site Health Trends (M6) load on their own path — never from the // timer tick below — so a trend-query fault can't disturb the live tile // refresh. Seed the selector from the sites just loaded into _siteStates // and query the default site. @@ -694,7 +694,7 @@ } } - // Per-node site-call KPI loader (T6: M5.2). Best-effort; a fault silently + // Per-node site-call KPI loader (M5.2). Best-effort; a fault silently // suppresses the per-node sub-table rather than degrading the dashboard. private async Task LoadSiteCallNodeKpis() { diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor index f87c7747..6c06347d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor @@ -72,7 +72,7 @@
    } - @* ── Per-node breakdown (T6: additive) ── *@ + @* ── Per-node breakdown (additive) ── *@
    Per-node breakdown
    @if (_perNodeError != null) { @@ -162,7 +162,7 @@
    } - @* ── Trends (T11: first KPI-history consumer) ── *@ + @* ── Trends (first KPI-history consumer) ── *@
    Trends
    @@ -205,15 +205,15 @@ private IReadOnlyList _perSite = Array.Empty(); private string? _perSiteError; - // ── Per-node (T6: M5.2 per-node stuck-count KPIs) ── + // ── Per-node (M5.2 per-node stuck-count KPIs) ── private IReadOnlyList _perNode = Array.Empty(); private string? _perNodeError; private bool _loading; - // ── Trends (T11: first KPI-history consumer) ── + // ── Trends (first KPI-history consumer) ── // Window in hours: 24h (default) or 168h (7d). Toggling re-queries. - // Per-metric isolation (mirrors the K14 SiteCallsReport pattern): each metric + // Per-metric isolation (mirrors the SiteCallsReport pattern): each metric // carries its own series + availability + error, each loaded via its own // try/catch so one metric's failure only blanks that one chart and the others // still render their already-fetched data. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor index 0f809f1f..53743a8c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor @@ -172,7 +172,7 @@ - @* Bundle D (#23 M7-T10) drill-in: NotificationId is the audit + @* NotificationId is the audit CorrelationId, so the link deep-links into the central Audit Log pre-filtered to this notification's lifecycle events. *@ Logger -@* Secured Writes (M7 OPC UA / MxGateway UX, Task C5 / T14b). Two-person workflow: +@* Secured Writes. Two-person workflow: an Operator submits a write against an MxGateway connection; a DIFFERENT Verifier approves (which relays the write to the device) or rejects. This page only SUBMITS commands — the server (ManagementActor) enforces roles, the no-self-approval guard, diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor index 5e811128..02abf21f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor @@ -224,7 +224,7 @@ OnNext="NextPage" /> } - @* ── Trends (K14: collapsible KPI-history charts) ── + @* ── Trends (collapsible KPI-history charts) ── A best-effort section — each chart's GetSeriesAsync is wrapped so a KPI backend hiccup renders the chart unavailable rather than breaking the grid above. The series load lazily on first expand (and re-load on the diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs index 69c14e95..2b38a4af 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs @@ -11,7 +11,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Kpi; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.SiteCalls; /// -/// Code-behind for the central Site Calls report page (Site Call Audit #22). A +/// Code-behind for the central Site Calls report page. A /// near-mirror of : /// it queries the central SiteCalls table via /// , @@ -60,7 +60,7 @@ public partial class SiteCallsReport private ToastNotification _toast = default!; private List _sites = new(); - // CentralUI-028: unfiltered site list so a permitted-site lookup resolves + // Unfiltered site list so a permitted-site lookup resolves // correctly for a SourceSite whose Site was filtered out of the dropdown. private List _allSites = new(); private bool _siteScopeSystemWide; @@ -96,7 +96,7 @@ public partial class SiteCallsReport private DateTime? _fromFilter; private DateTime? _toFilter; - // ── Trends (K14) ────────────────────────────────────────────────────────── + // ── Trends ────────────────────────────────────────────────────────────── // Collapsible KPI-history charts for the SiteCallAudit / Global series. The // section is collapsed on init and the series load lazily on first expand // (and on each 24h/7d window toggle), so the page's primary job — the call @@ -127,7 +127,7 @@ public partial class SiteCallsReport try { _allSites = (await SiteRepository.GetAllSitesAsync()).ToList(); - // CentralUI-028: restrict the source-site dropdown to the user's + // Restrict the source-site dropdown to the user's // permitted set. System-wide users see the full list back unchanged. _sites = await SiteScope.FilterSitesAsync(_allSites); _siteScopeSystemWide = await SiteScope.IsSystemWideAsync(); @@ -249,7 +249,7 @@ public partial class SiteCallsReport var response = await CommunicationService.QuerySiteCallsAsync(request); if (response.Success) { - // CentralUI-028: drop any row whose source site is outside the + // Drop any row whose source site is outside the // user's permitted set, as a row-level safety net behind the // dropdown restriction. _siteCalls = await FilterPermittedAsync(response.SiteCalls); @@ -278,7 +278,7 @@ public partial class SiteCallsReport private async Task RetrySiteCall(SiteCallSummary c) { - // CentralUI-028: server-side re-check before relaying — a Retry relay must + // Server-side re-check before relaying — a Retry relay must // not fire for a site outside the caller's permitted set, even if the row // somehow appeared in the grid. if (!await IsRowSiteAllowedAsync(c.SourceSite)) @@ -473,7 +473,7 @@ public partial class SiteCallsReport private static string? NullIfEmpty(string s) => string.IsNullOrWhiteSpace(s) ? null : s.Trim(); /// - /// CentralUI-027: <input type="datetime-local"> binds with + /// <input type="datetime-local"> binds with /// and the value is the operator's /// browser-local wall-clock. Tag it and /// convert to UTC before the value enters the wire query — otherwise the @@ -547,7 +547,7 @@ public partial class SiteCallsReport return Task.FromResult(_permittedSiteIds.Contains(resolved.Id)); } - // ── Trends (K14) ────────────────────────────────────────────────────────── + // ── Trends ────────────────────────────────────────────────────────────── /// /// Expand/collapse the Trends section. The series load on first expand (and diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerConfigCodec.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerConfigCodec.cs index 8d27cf06..70f92074 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerConfigCodec.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerConfigCodec.cs @@ -100,7 +100,7 @@ internal static class AlarmTriggerConfigCodec case AlarmTriggerType.Expression: model.Expression = TryReadString(root, "expression"); - // M9-T28b: read optional analysisKind discriminator ("Strict" → strict; + // Read optional analysisKind discriminator ("Strict" → strict; // absent/"Advisory"/anything else → Advisory default, preserving // today's behavior exactly — matches ValidationService.IsStrictAnalysis). if (root.TryGetProperty("analysisKind", out var ak) @@ -181,7 +181,7 @@ internal static class AlarmTriggerConfigCodec case AlarmTriggerType.Expression: w.WriteString("expression", model.Expression ?? ""); - // M9-T28b: emit "analysisKind":"Strict" only when explicitly set; + // Emit "analysisKind":"Strict" only when explicitly set; // Advisory is the default so the key is omitted to keep the payload // minimal and backward-compatible with older ValidationService versions. if (model.IsStrictAnalysisKind) @@ -357,7 +357,7 @@ internal sealed class AlarmTriggerModel /// public string? Expression { get; set; } - // M9-T28b: per-trigger analysis kind (Expression only). When true the + // Per-trigger analysis kind (Expression only). When true the // codec serializes "analysisKind":"Strict"; when false (Advisory, the // default) the key is omitted. Matches ValidationService.IsStrictAnalysis. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerEditor.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerEditor.razor index 64187daf..8f39e9ef 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerEditor.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/AlarmTriggerEditor.razor @@ -538,7 +538,7 @@ _thresholdText = FormatNullable(_model.ThresholdPerSecond); _windowText = FormatNullable(_model.WindowSeconds); _directionText = _model.Direction; - // M9-T28b: sync the analysis-kind selector from the loaded model. + // Sync the analysis-kind selector from the loaded model. _analysisKindValue = _model.IsStrictAnalysisKind ? "Strict" : "Advisory"; _loLoText = FormatNullable(_model.LoLo); _loText = FormatNullable(_model.Lo); @@ -589,7 +589,7 @@
    A boolean C# expression — e.g. Attributes["Temperature"] > 80.
    - @* M9-T28b: analysis-kind selector — Advisory (default) keeps the blank-expression + @* Analysis-kind selector — Advisory (default) keeps the blank-expression finding as a non-blocking warning; Strict escalates it to a deploy-blocking error. *@
    public DialogState? Current { get; private set; } - // CentralUI-015: the pending dialog result is held in a typed TCS that the + // The pending dialog result is held in a typed TCS that the // host completes directly via Resolve(). The previous implementation // projected the result through Task.ContinueWith(..., TaskScheduler.Default), // which ran the projection lambda on a thread-pool thread. Completing a diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor index cda351cb..c58ace81 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor @@ -1,6 +1,6 @@ @namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared -@* M6 (K12) reusable KPI trend chart. Dependency-free inline SVG inside a +@* M6 reusable KPI trend chart. Dependency-free inline SVG inside a Bootstrap card, styled to sit beside the AuditKpiTiles / SiteCallKpiTiles KPI cards (card + card-body, small text-muted labels, muted single stroke). Three states: a ≥2-point polyline chart, a single-sample note, and an diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor.cs index 56e19117..8316d1e8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/KpiTrendChart.razor.cs @@ -6,8 +6,8 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Kpi; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared; /// -/// Reusable dependency-free SVG trend chart for M6 "KPI History & Trends" -/// (Task K12). Renders a series as a single muted +/// Reusable dependency-free SVG trend chart for "KPI History & Trends". +/// Renders a series as a single muted /// polyline inside a Bootstrap card, with a baseline (x-axis) and value/time /// labels. No third-party charting library — the project rule is custom Blazor /// components on Bootstrap CSS only. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/OffsetPager.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/OffsetPager.razor index 90b309e5..6cbdf4b8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/OffsetPager.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/OffsetPager.razor @@ -1,6 +1,6 @@ @namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared -@* T35a — reusable offset-pagination bar. Purely presentational: the host page +@* Reusable offset-pagination bar. Purely presentational: the host page owns page-number state, query execution, and the HasNextPage decision. Parameters: Page, PageChanged, HasNextPage, TotalCount, PageSize, Disabled. *@ diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/PagerWindow.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/PagerWindow.cs index e1405c14..e8af439d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/PagerWindow.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/PagerWindow.cs @@ -1,7 +1,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared; /// -/// Pure helper for windowed pagination (CentralUI-016). Computes the set of +/// Pure helper for windowed pagination. Computes the set of /// page numbers a pager should render: always the first and last page plus a /// small range around the current page, with the rest elided. Keeps the /// rendered button count bounded regardless of the total page count, instead diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs index 146e69bb..9258482b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs @@ -43,7 +43,7 @@ internal sealed class ScriptTriggerModel /// Fire mode (Conditional + Expression). Defaults to . public ScriptTriggerMode Mode { get; set; } = ScriptTriggerMode.OnTrue; - // M9-T28b: per-trigger analysis kind (Expression only). When true the + // Per-trigger analysis kind (Expression only). When true the // codec serializes "analysisKind":"Strict"; when false (Advisory, the // default) the key is omitted. Matches ValidationService.IsStrictAnalysis. /// @@ -158,7 +158,7 @@ internal static class ScriptTriggerConfigCodec case ScriptTriggerKind.Expression: model.Expression = root.TryGetProperty("expression", out var e) ? e.GetString() : null; model.Mode = ReadMode(root); - // M9-T28b: read optional analysisKind discriminator (matches + // Read optional analysisKind discriminator (matches // ValidationService.IsStrictAnalysis — "Strict" case-insensitive → strict; // absent/"Advisory"/anything else → Advisory default). if (root.TryGetProperty("analysisKind", out var ak) @@ -215,7 +215,7 @@ internal static class ScriptTriggerConfigCodec case ScriptTriggerKind.Expression: w.WriteString("expression", model.Expression ?? ""); w.WriteString("mode", model.Mode.ToString()); - // M9-T28b: emit "analysisKind":"Strict" only when explicitly set; + // Emit "analysisKind":"Strict" only when explicitly set; // Advisory is the default so the key is omitted to stay backward-compatible. if (model.IsStrictAnalysisKind) w.WriteString("analysisKind", "Strict"); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerEditor.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerEditor.razor index 650f3b58..88836536 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerEditor.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerEditor.razor @@ -136,7 +136,7 @@ _operator = _model.Operator; _thresholdText = _model.Threshold?.ToString("R", CultureInfo.InvariantCulture); (_intervalText, _intervalUnit) = SplitInterval(_model.IntervalMs); - // M9-T28b: sync the analysis-kind selector from the loaded model. + // Sync the analysis-kind selector from the loaded model. _analysisKindValue = _model.IsStrictAnalysisKind ? "Strict" : "Advisory"; } @@ -274,7 +274,7 @@
    A boolean C# expression — e.g. Attributes["Temperature"] > 80.
    - @* M9-T28b: analysis-kind selector — Advisory keeps the blank-expression finding + @* Analysis-kind selector — Advisory keeps the blank-expression finding as a non-blocking warning; Strict escalates it to a deploy-blocking error. *@