diff --git a/CLAUDE.md b/CLAUDE.md index 21a8476f..0f345c03 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -229,6 +229,7 @@ spec for each is `docs/requirements/Component-.md`, and `README.md` carrie - Host readiness gating: `/health/ready` endpoint, no traffic until operational. - EF Core migrations: auto-apply in dev, manual SQL scripts for production. Gotcha: `dotnet ef migrations add … --no-build` scaffolds off the previously-built DLL and can emit an **empty** migration — build first (drop the `--no-build`), and delete the empty `Migrations/` files if it happens (`migrations remove` needs a live DB). - Audit logging absorbed into Configuration Database component (IAuditService). The config `AuditLogEntries` table stores **summaries** (a script body is recorded as length + SHA-256), caps `AfterStateJson` at 256 K chars, pages deterministically on `(Timestamp DESC, Id DESC)`, and has an optional purge: `ScadaBridge:ConfigAudit:RetentionDays` (default `0` = retained indefinitely), `PurgeBatchSize` 5000, `MaxBatchesPerTick` 200, `PurgeInterval` (bound with `ValidateOnStart` on Central). +- **Search is prefix by default (ScadaBridge#50, register row 36).** The Deployments page search (instance name, deployment id, revision hash, user) and the config-audit `EntityName` filter are `LIKE 'term%'` (index-seekable); a substring match is an explicit opt-in (`DeploymentListFilter.SearchMode = Contains` / the page's "Match anywhere" checkbox; `GetAuditLogEntriesAsync(entityNameContains: true)`) that is ALWAYS bounded to a `DeployedAt`/`Timestamp` window (explicit `DeployedFrom`/`from`, else the last 30 days). Migration `PrefixSearchIndexes` (script `docs/plans/sql/PrefixSearchIndexes.sql`; not applied to QA/prod) adds the `DeployedBy`, `RevisionHash` and `AuditLogEntries.EntityName` indexes. Tests: `SearchPrefixQueryTests` (SQL-shape via `ToQueryString`). - **Review remediation 2026-10-21** (8-slice system review, ~107 findings, 4 High; record `docs/plans/2026-10-21-system-review-remediation.md`). Decisions: CLI uses bearer-per-invocation (see Security); the never-read `Database:MachineDataDb` option was **removed** (it was a required boot key); config audit stores summaries + retention (above); a **bound Test Run** (Test Run against a deployed instance) now needs Deployer + site scope and writes an audit row; persisted static overrides **seed** script state at actor start without firing scripts (alarms still evaluate). Also changed: site deploy gate rejects non-actor-safe (`ActorNameRules`) instance/script/alarm/native-source names and Data Connection actor names are ASCII-sanitised with collision rejection; site gRPC addresses are validated on every write path (management + Transport import); artifact applies are serialised per site with a 10-min stuck-apply watchdog; `IDataConnection.WriteBatchAndWaitAsync` is **gone** (the script-level handshake composes `WriteTagBatchRequest` + waiter); `instance list --search` is a **prefix** match paged in SQL; command-plane failback probes readiness with a real RPC (probation 5 min); `Transport:SchemaVersionMajor` removed; migration `ReviewRemediationIndexes` (script `docs/plans/sql/ReviewRemediationIndexes.sql`; **QA/prod not yet applied**). New register rows 128-135; row 117 closed. ### Akka.NET Conventions diff --git a/docs/plans/sql/PrefixSearchIndexes.sql b/docs/plans/sql/PrefixSearchIndexes.sql new file mode 100644 index 00000000..ebd06890 --- /dev/null +++ b/docs/plans/sql/PrefixSearchIndexes.sql @@ -0,0 +1,26 @@ +-- PrefixSearchIndexes (2026-11-09, ScadaBridge#50). Indexes backing the prefix search on the +-- Deployments page (DeployedBy, RevisionHash) and the config-audit EntityName filter. +BEGIN TRANSACTION; +ALTER TABLE [TemplateNativeAlarmSources] ADD [IsMesReportable] bit NOT NULL DEFAULT CAST(0 AS bit); + +ALTER TABLE [InstanceNativeAlarmSourceOverrides] ADD [IsMesReportableOverride] bit NULL; + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'20261109200211_AddNativeAlarmSourceMesReportable', N'10.0.13'); + +COMMIT; +GO + +BEGIN TRANSACTION; +CREATE INDEX [IX_DeploymentRecords_DeployedBy] ON [DeploymentRecords] ([DeployedBy]); + +CREATE INDEX [IX_DeploymentRecords_RevisionHash] ON [DeploymentRecords] ([RevisionHash]); + +CREATE INDEX [IX_AuditLogEntries_EntityName] ON [AuditLogEntries] ([EntityName]); + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'20261109203753_PrefixSearchIndexes', N'10.0.13'); + +COMMIT; +GO + diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Deployments.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Deployments.razor index c2a7a40c..4dca5892 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Deployments.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Deployments.razor @@ -75,6 +75,15 @@ data-test="deploy-search" value="@_searchInput" @oninput="OnSearchInput" /> +
+ + +