feat: Phase II auto-write (WriteGuard, audit, auth) + WO-2~7 완료
Phase II:
- FfOperatorAction entity + ff_operator_action DDL/DbSet
- IFeedforwardWriteGuard + FeedforwardWriteGuard (SP bounds, grade C, transient, NaN)
- IFeedforwardAuditService + FeedforwardAuditService (raw ADO insert/query)
- FeedforwardSupervisor.AutoWriteAsync (per-stream OPC UA after Tick, rate-limited)
- FeedforwardConfigStore: advisory_only now read/writes DB, sp_node_id column
- FeedforwardController: auth (X-Kb-Token) on config/delete/write/audit;
POST write/{id}/{key} manual SP write; GET audit; write results in MapColumn
- ff.js: token header, auto-write badge, per-stream write result, spNodeId, advisoryOnly
- ff.css: .ff-write-badge, .ff-write, .ff-write-err, .ff-wg-blocked
- Program.cs: register audit (Scoped) + write guard (Singleton)
WO-2~7 (build 0W/0E, test 22/22):
- PCT monitor, θ auto-tune, slow bias, front position indicator,
total reflux recovery, config form expansion
This commit is contained in:
48
AGENTS.md
48
AGENTS.md
@@ -7,7 +7,7 @@
|
||||
| Build | `dotnet build src/Web/ExperionCrawler.csproj` | repo root |
|
||||
| Run (dev) | `dotnet run` | `src/Web/` |
|
||||
| Publish | `dotnet publish -c Release -o /opt/ExperionCrawler` | `src/Web/` |
|
||||
| Tests | `dotnet test` | repo root |
|
||||
| Tests | `dotnet test tests/ExperionCrawler.Tests/ExperionCrawler.Tests.csproj` | repo root |
|
||||
|
||||
Single project: `src/Web/ExperionCrawler.csproj`. Core and Infrastructure are included via `<Compile Include>` globs — there are no separate projects to build. Runtime target is `linux-arm64`.
|
||||
|
||||
@@ -144,3 +144,49 @@ wwwroot/
|
||||
### Phase 4 pending — CSS 분리
|
||||
|
||||
`style.css`(2,230줄)에서 탭별 스타일 분할 미완료. `docs.css`가 선례. `웹UI-개선플랜-byOPUS.md` §11 참조.
|
||||
|
||||
---
|
||||
|
||||
## Anchored Summary — Phase II (Auto-Write, WriteGuard, Audit, Auth)
|
||||
|
||||
### Done
|
||||
- WO-2 (PCT monitor), WO-3 (θ auto-tune), WO-4 (slow bias), WO-5 (front position indicator), WO-6 (total reflux recovery), WO-7 (config form expansion): all **built, tested (22/22), JS OK, sign-off: windpacer 2026-05-31**.
|
||||
- **Phase II auto-write (23 files)**:
|
||||
- `FfOperatorAction` entity (`src/Core/Domain/Entities/FfOperatorAction.cs`)
|
||||
- `ff_operator_action` DDL + `DbSet` + `OnModelCreating` in `ExperionDbContext.cs`
|
||||
- `IFeedforwardWriteGuard` + `FeedforwardWriteGuard` (SP bounds, grade C, transient, NaN checks)
|
||||
- `IFeedforwardAuditService` + `FeedforwardAuditService` (raw ADO.NET insert/query)
|
||||
- `FeedforwardSupervisor.AutoWriteAsync` — per-stream OPC UA write after Tick (rate-limited, guarded, logged)
|
||||
- `FeedforwardConfigStore` — `advisory_only` no longer hardcoded; reads/writes DB; `sp_node_id` column added
|
||||
- `FeedforwardController` — auth (X-Kb-Token) on config/delete/write/audit; `POST /api/ff/write/{id}/{key}` manual SP write; `GET /api/ff/audit` audit query; write results merged in `MapColumn`
|
||||
- `Program.cs` — `IFeedforwardAuditService` (Scoped), `IFeedforwardWriteGuard` (Singleton) registered
|
||||
- `ff.js` — `ffToken()` + X-Kb-Token header; auto-write badge; per-stream write result; `spNodeId` field in stream table; `advisoryOnly` checkbox in form
|
||||
- `ff.css` — `.ff-write-badge`, `.ff-write`, `.ff-write-err`, `.ff-wg-blocked`
|
||||
- **Build 0W/0E, test 22/22, JS OK. Sign-off: windpacer 2026-05-31.**
|
||||
|
||||
### Key Design Decisions
|
||||
- `IFeedforwardWriteGuard` is **Singleton** (stateless pure check functions) — no per-request instance needed.
|
||||
- `IFeedforwardAuditService` is **Scoped** (depends on `ExperionDbContext` which is Scoped). Supervisor resolves it from `IServiceScopeFactory` scope.
|
||||
- SP writes go through `IExperionOpcWriteClient` (Scoped) — each call creates + destroys an OPC UA session (acceptable for low-frequency writes).
|
||||
- `sp_node_id` is stored per-stream in `ff_stream_config`. If null, auto-write is skipped for that stream (no write).
|
||||
- Rate-limit: minimum `ScanSec * 2` between writes to the same stream (avoids double-writes on rapid ticks).
|
||||
- Auth: `X-Kb-Token` header validated via `IKbAuthService.ValidateAsync()` — same mechanism as RAG KB admin. Token stored in `sessionStorage` by `kbadmin.js`.
|
||||
- `AdvisoryResult.AutoWriteActive` is set by the Supervisor after Tick (not by the Engine). Engine remains pure computaton.
|
||||
- `WriteGuardBlockedSp` / `WriteGuardReason` on `AdvisoryResult` are informative only — set when streams exist but all are blocked.
|
||||
|
||||
### Relevant Files
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `src/Infrastructure/Control/FeedforwardWriteGuard.cs` | New — SP safety checks |
|
||||
| `src/Infrastructure/Control/FeedforwardAuditService.cs` | New — operator action log |
|
||||
| `src/Core/Domain/Entities/FfOperatorAction.cs` | New — audit log entity |
|
||||
| `src/Infrastructure/Control/FeedforwardSupervisor.cs` | Modified — `AutoWriteAsync` + `GetLastWrite` + IConfiguration |
|
||||
| `src/Infrastructure/Control/FeedforwardConfigStore.cs` | Modified — reads/writes `advisory_only` from DB, `sp_node_id` |
|
||||
| `src/Web/Controllers/FeedforwardController.cs` | Modified — auth, write, audit endpoints; write results in MapColumn |
|
||||
| `src/Web/Program.cs` | Modified — register audit + write guard |
|
||||
| `src/Web/wwwroot/js/ff.js` | Modified — token, write status, spNodeId, advisoryOnly form |
|
||||
| `src/Web/wwwroot/css/ff.css` | Modified — auto-write/blocked styles |
|
||||
| `src/Infrastructure/Database/ExperionDbContext.cs` | Modified — FfOperatorAction DbSet + DDL + OnModelCreating |
|
||||
|
||||
### Next Steps
|
||||
- Phase II complete. Consider Phase III (operator dashboard, write confirmation dialog, trend overlay) when ordered.
|
||||
|
||||
Reference in New Issue
Block a user