#1719

Add GPU-resident RDP OCR processing

Openracerxdlwants to merge intofrom

📝 Description

Adds a session-scoped GPU-resident OCR framebuffer that decompresses and composites raw RDP bitmap tiles on-device for OCR, exact-change detection, and cache reuse. The enforcing Rust guard retains a trusted CPU shadow canvas needed to synthesize redaction PDUs and recover fail-closed sequence conflicts; it no longer materializes or transfers full BMP windows to the CUDA sidecar.

📣 User-facing impact

GPU-backed RDP data masking avoids full-window BMP encoding, transfer, decode, and redundant OCR work, reducing masking latency for unchanged or partially changed screens.

🔗 Related Issue

Linear DEP-102. Depends on #1717. Paired enterprise guard: hoophq/libhoop#109.

🚀 Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature which causes existing functionality not to work as expected)
  • 📚 Documentation update
  • 🎨 Style/UI update
  • ♻️ Code refactor
  • ⚡ Performance improvement
  • ✅ Test update
  • 🔧 Build configuration change
  • 🧹 Chore

📋 Changes Made

  • Add a sequenced raw-RDP resident OCR transport with CUDA decompression/composition, dirty-region reuse, bounded per-session caches, and fail-closed sequence recovery.
  • Move the enforcing Rust guard to libhoop, retain an API-compatible OSS passthrough stub, and fail release builds when enforcement is unavailable.
  • Pin and validate the GPU OCR runtime, advertise the raw-RDP capability only when healthy, and require it before selecting agent-side RDP masking.
  • Bound frame geometry, decoded work, result cardinality, redaction output, active detections, and terminal cancellation paths.

🧪 Testing

Test Configuration:

  • Browser(s): N/A
  • OS: macOS 26 arm64; Linux NVIDIA T4 GPU host

Tests performed:

  • Unit tests pass

  • Integration tests pass

  • Manual testing completed

  • go test ./gateway/broker ./gateway/rdp/... ./gateway/transport ./gateway/models: 7 packages passed; 1 package had no tests.

  • cargo test --features require-enforcement in agentrs: 70 tests passed across 4 suites.

  • OSS guard_surface plus cargo check: 2 tests passed and the stub build completed.

  • pytest -q scripts/dev/ocr-poc/test_raw_image.py: 53 tests passed.

  • Production CUDA image tests on the T4 host: 54 tests passed, including real CUDA RDP decoder parity and resident cache behavior.

📸 Screenshots (if applicable)

N/A.

✅ Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes
  • I have checked my code and corrected any misspellings

📄 Additional Notes

Merge after #1717. Presidio remains the CPU/network policy stage. The trusted guard deliberately keeps CPU shadow compositing for redaction PDU synthesis and sequence recovery; removing it safely requires a GPU diff-reporting and pixel-export protocol. This change removes full-window BMP marshaling and sidecar host preprocessing, not every host bitmap operation.


Automated by MisterMal

Activity

21
github-actions[bot]2mo ago

Migration Safety Analysis

No database migrations were changed in this PR. Safe to deploy to sandbox.

github-actions[bot]2mo ago

📋 API Changelog

API Changelog unknown vs. unknown

API Changes

GET /serverinfo

  • removed the alcatraz enum value from the redact_provider response property for the response status 200
qodo-code-review[bot]2mo ago

PR Summary by Qodo

Add GPU-resident RDP OCR processing

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

AI Description

• Decode and composite RDP bitmap tiles in GPU-resident session framebuffers.
• Reuse unchanged OCR results while bounding caches, queues, and sensitive-data lifetimes.
• Enforce guard availability and durable violation reporting across agent releases.
Diagram

sequenceDiagram
    participant RDP as RDP Server
    participant Agent as Rust Agent
    participant Guard as RDP Guard
    participant OCR as OCR Sidecar
    participant GPU as GPU Store
    participant Gateway as Gateway
    participant DB as Audit DB
    RDP->>Agent: Bitmap updates
    Agent->>Guard: Guarded stream
    Guard->>OCR: Sequenced RDP tiles
    OCR->>GPU: Decode and composite
    GPU-->>OCR: Cached OCR results
    OCR-->>Guard: Words and sequence
    Guard->>Gateway: Violation report
    Gateway->>DB: Atomic persistence
    DB-->>Gateway: Commit
    Gateway-->>Guard: Report acknowledgement
High-Level Assessment

The following are alternative approaches to this PR:

1. Send decoded RGBA dirty tiles
  • ➕ Avoids implementing RDP bitmap decoding in CUDA.
  • ➕ Keeps the sidecar protocol simpler.
  • ➖ Retains CPU decoding and RGBA expansion costs.
  • ➖ Transfers more data and weakens GPU-resident performance.
2. Embed CUDA OCR in the Rust guard
  • ➕ Eliminates HTTP transport and cross-process sequencing.
  • ➕ Shares lifecycle directly with enforcement.
  • ➖ Requires complex Rust, CUDA, and ONNX integration.
  • ➖ Couples transport enforcement to GPU runtime dependencies.
3. Maintain GPU state in the gateway
  • ➕ Centralizes state and audit persistence.
  • ➕ Avoids report acknowledgement machinery.
  • ➖ Moves high-volume screen data away from GPU agents.
  • ➖ Recreates gateway latency and memory pressure.

Recommendation: Keep the raw-RDP sidecar design. It preserves the existing process boundary while removing full-window encoding, transfer, and decode work, and the CPU shadow remains available for redaction PDU synthesis. The CUDA decoder parity and fail-closed sequence recovery deserve the deepest review.

Files changed (68) +7432 / -1217

Enhancement (19) +4902 / -713
gw.rsMark example relay frames as raw +4/-4

Mark example relay frames as raw

• Updates example frame construction for the control/data discriminator.

agentrs/examples/gw.rs

proxy.rsIntegrate acknowledged guard events +242/-132

Integrate acknowledged guard events

• Uses the external gate, routes read-ahead through enforcement, and settles reports during teardown.

agentrs/src/proxy.rs

rdp_proxy.rsHarden RDP activation and credentials +283/-82

Harden RDP activation and credentials

• Pins guarded capabilities, preserves buffered bytes, and zeroizes credentials after CredSSP.

agentrs/src/rdp_proxy.rs

session.rsAdd typed frame headers +55/-8

Add typed frame headers

• Uses the length word's high bit for frame kind and validates exact payload lengths.

agentrs/src/session.rs

client.rsAdvertise guard capabilities safely +251/-51

Advertise guard capabilities safely

• Builds capabilities from the linked guard, tracks report acknowledgements, and joins connection tasks.

agentrs/src/ws/client.rs

control.rsDefine frame protocol v2 +7/-0

Define frame protocol v2

• Adds capability constants for negotiated typed framing.

agentrs/src/ws/control.rs

message.rsEncode explicitly typed controls +45/-4

Encode explicitly typed controls

• Sets and validates the control discriminator and rejects malformed control envelopes.

agentrs/src/ws/message.rs

message_types.rsAdd violation acknowledgement messages +12/-4

Add violation acknowledgement messages

• Defines serialization and parsing for persisted-report acknowledgements.

agentrs/src/ws/message_types.rs

proxy.rsBound reporting and relay tasks +259/-92

Bound reporting and relay tasks

• Retries stable report IDs, bounds response forwarding, owns child cancellation, and transfers zeroizing credentials.

agentrs/src/ws/proxy.rs

rdp_message_processor.rsHarden multiplexed RDP sessions +367/-159

Harden multiplexed RDP sessions

• Negotiates typed frames, bounds inputs, isolates instances, resolves guards, and matches report acknowledgements.

agentrs/src/ws/rdp_message_processor.rs

headers.goImplement typed agent framing +81/-18

Implement typed agent framing

• Adds frame-kind encoding, exact validation, negotiated v2 controls, and acknowledgement constants.

gateway/broker/headers.go

protocol_rdp.goBind sessions to agent and audit identities +18/-15

Bind sessions to agent and audit identities

• Propagates relay errors, records instance and database IDs, retains audit routes, and negotiates controls.

gateway/broker/protocol_rdp.go

session.goAttach IDs to guardrail reports +3/-0

Attach IDs to guardrail reports

• Adds an optional report ID for deduplicating agent retries.

gateway/models/session.go

rdp_guardrail.goPersist guardrail evidence transactionally +73/-0

Persist guardrail evidence transactionally

• Locks sessions, deduplicates report IDs, and atomically appends audit data and detections.

gateway/services/rdp_guardrail.go

websocket.goHarden agent routing and audit delivery +432/-126

Harden agent routing and audit delivery

• Bounds frames and workers, isolates instances, validates controls, persists reports, and acknowledges commits.

gateway/transport/websocket.go

bucket_rec.pyExpose cached detector sessions +11/-4

Expose cached detector sessions

• Separates detector lookup from CPU preprocessing for direct CUDA input binding.

scripts/dev/ocr-poc/bucket_rec.py

gpu_pipeline.pyImplement GPU-resident RDP OCR +1928/-0

Implement GPU-resident RDP OCR

• Adds CUDA decoding, compositing, hashing, OCR binding, bounded caches, sequencing, eviction, and scrubbing.

scripts/dev/ocr-poc/gpu_pipeline.py

raw_image.pyDefine strict resident frame decoders +456/-0

Define strict resident frame decoders

• Validates bounded RGBA and RDP bodies, patches, geometry, bitmap depth, chunks, and wire versions.

scripts/dev/ocr-poc/raw_image.py

server_rapidocr.pyExpose resident GPU OCR APIs +375/-14

Expose resident GPU OCR APIs

• Adds raw and resident endpoints, serialized admission, health capabilities, reaping, release, and conflict handling.

scripts/dev/ocr-poc/server_rapidocr.py

Bug fix (4) +507 / -234
stream.rsBound RDP stream queues +165/-60

Bound RDP stream queues

• Uses poll-aware channels, preserves unread tails, chunks output, and enforces a strict byte limit.

agentrs/src/ws/stream.rs

communicators.goSerialize and bound agent writes +15/-1

Serialize and bound agent writes

• Protects WebSocket writes with a mutex and deadline.

gateway/broker/communicators.go

session.goIsolate relay and teardown state +310/-166

Isolate relay and teardown state

• Makes admission nonblocking, fixes deadline accounting, scopes instances, and retains audit routes.

gateway/broker/session.go

irongw.goPreserve post-handshake RDP connections +17/-7

Preserve post-handshake RDP connections

• Passes the durable session ID and clears the temporary TLS handshake deadline.

gateway/rdp/irongw.go

Refactor (7) +295 / -27
lib.rsProvide a fail-closed OSS guard surface +241/-0

Provide a fail-closed OSS guard surface

• Implements an API-compatible passthrough stub that advertises no enforcement and rejects delegated guarded sessions.

_libhoop/rdp-guard/src/lib.rs

guard.rsDefine the agent guard boundary +41/-0

Define the agent guard boundary

• Re-exports the selected guard crate and rejects enforcement-required stub builds.

agentrs/src/guard.rs

lib.rsExpose the extracted guard module +1/-1

Expose the extracted guard module

• Replaces the in-tree piigate export with the guard facade.

agentrs/src/lib.rs

main.rsWire the extracted guard into agentrs +1/-1

Wire the extracted guard into agentrs

• Replaces the local piigate module with the swappable guard facade.

agentrs/src/main.rs

session.rsZeroize stored session credentials +5/-18

Zeroize stored session credentials

• Removes unnecessary cloning and switches session guard configuration to the external crate.

agentrs/src/ws/session.rs

types.rsSimplify channels and track acknowledgements +5/-7

Simplify channels and track acknowledgements

• Stores one bounded sender per session and adds pending violation waiters.

agentrs/src/ws/types.rs

rdp.goAdapt native RDP creation +1/-0

Adapt native RDP creation

• Supplies an empty durable ID for the native unguarded path.

gateway/rdp/rdp.go

Documentation (5) +14 / -9
0002-rdp-pii-guard-line-ocr-cache.mdRecord the guard's move to libhoop +8/-3

Record the guard's move to libhoop

• Clarifies that historical agent guard paths now live in libhoop with an OSS stub.

docs/adr/0002-rdp-pii-guard-line-ocr-cache.md

worker.goUpdate benchmark references +4/-4

Update benchmark references

• Refers analyzer documentation to the external benchmark harness.

gateway/rdp/analyzer/worker.go

piigate_metrics.goUpdate guard metrics documentation +1/-1

Update guard metrics documentation

• Points agent-side redaction ownership to libhoop.

gateway/rdp/piigate_metrics.go

server.pyUpdate benchmark terminology +1/-1

Update benchmark terminology

• Replaces references to the deleted benchmark with the external harness.

scripts/dev/ocr-poc/server.py

index.jsUpdate canvas security references +0/-0

Update canvas security references

• Points the desktop-size contract to the extracted guard implementation.

webapp/resources/public/rdpclient/index.js

Other (33) +1714 / -234
.env.sampleDocument resident GPU OCR settings +13/-0

Document resident GPU OCR settings

• Documents resident-RDP transport and session, VRAM, TTL, and cache bounds.

.env.sample

agent-ocr-build.ymlTrack GPU OCR pipeline build inputs +3/-0

Track GPU OCR pipeline build inputs

• Adds bucket, raw transport, and GPU pipeline modules to OCR image path filters.

.github/workflows/agent-ocr-build.yml

pullrequest-release.ymlBuild PR artifacts with paired libhoop +67/-0

Build PR artifacts with paired libhoop

• Resolves a paired libhoop branch and checks its pinned revision out for Rust artifact builds.

.github/workflows/pullrequest-release.yml

pullrequest.ymlTest OSS and enterprise guard integrations +88/-0

Test OSS and enterprise guard integrations

• Adds dual-flavor Rust jobs, enforcement linkage validation, and a FreeRDP plumbing test.

.github/workflows/pullrequest.yml

release.ymlRequire libhoop in Rust release jobs +39/-0

Require libhoop in Rust release jobs

• Checks out private libhoop so enforcement-required releases cannot resolve to the OSS stub.

.github/workflows/release.yml

.gitignoreAlign ignored artifacts with guard extraction +4/-10

Align ignored artifacts with guard extraction

• Ignores the OSS guard lockfile and removes exclusions for the deleted RDP benchmark.

.gitignore

Dockerfile.agent-ocrKeep CPU OCR on BMP transport +5/-0

Keep CPU OCR on BMP transport

• Packages shared transport helpers and explicitly selects BMP compatibility mode.

Dockerfile.agent-ocr

Dockerfile.agent-ocr-gpuEnable resident CUDA OCR by default +23/-11

Enable resident CUDA OCR by default

• Pins CuPy, packages the GPU pipeline, selects resident-RDP processing, and enforces one worker.

Dockerfile.agent-ocr-gpu

Dockerfile.localbuildSupport swappable guard crates locally +45/-5

Support swappable guard crates locally

• Copies either guard flavor and supports enforcement-required Cargo builds without breaking Go mappings.

Dockerfile.localbuild

MakefileAdd guard-aware builds and RDP tests +101/-7

Add guard-aware builds and RDP tests

• Adds non-destructive libhoop resolution, dual-flavor tests, enforcement-required releases, and FreeRDP validation.

Makefile

Cargo.tomlDefine the OSS RDP guard crate +15/-0

Define the OSS RDP guard crate

• Creates a package-compatible path dependency for the OSS guard replacement.

_libhoop/rdp-guard/Cargo.toml

Cargo.lockResolve extracted guard dependencies +159/-67

Resolve extracted guard dependencies

• Adds hoop-rdp-guard and updates transitive dependencies after extracting the guard implementation.

agentrs/Cargo.lock

Cargo.tomlDepend on the swappable guard +18/-6

Depend on the swappable guard

• Adds the path-based guard crate and compile-time enforcement feature while removing moved dependencies.

agentrs/Cargo.toml

rdp_caps_probe.rsProbe bitmap-only RDP negotiation +79/-23

Probe bitmap-only RDP negotiation

• Adds an empty-codec mode verifying the Fast-Path bitmap stream required by redaction.

agentrs/examples/rdp_caps_probe.rs

guard_surface.rsContract-test guard implementations +132/-0

Contract-test guard implementations

• Type-checks the guard seam and verifies delegated enforcement never silently disappears.

agentrs/tests/guard_surface.rs

docker-compose.gcp-gpu-agent.env.sampleDocument production GPU limits +18/-2

Document production GPU limits

• Recommends one worker and documents resident framebuffer, VRAM, TTL, and cache sizing.

deploy/docker-compose/docker-compose.gcp-gpu-agent.env.sample

docker-compose.gcp-gpu-agent.ymlConfigure resident GPU OCR +18/-3

Configure resident GPU OCR

• Enables raw RDP GPU processing with bounded resident-store settings and single-process ownership.

deploy/docker-compose/docker-compose.gcp-gpu-agent.yml

agent_capabilities_test.goTest replacement capability isolation +59/-0

Test replacement capability isolation

• Verifies superseded sockets close and stale instances cannot affect replacements.

gateway/broker/agent_capabilities_test.go

headers_test.goTest frame validation and negotiation +122/-0

Test frame validation and negotiation

• Covers malformed lengths, explicit kinds, and legacy-to-v2 transitions.

gateway/broker/headers_test.go

session_bench_test.goBenchmark nonblocking admission +3/-8

Benchmark nonblocking admission

• Updates slow-consumer expectations for per-session rejection instead of shared backpressure.

gateway/broker/session_bench_test.go

session_queue_test.goExpand relay lifecycle tests +202/-88

Expand relay lifecycle tests

• Tests byte bounds, deadlines, unread tails, shared-agent safety, instance routing, and audit retention.

gateway/broker/session_queue_test.go

rdp_entity_detection_test.goTest idempotent guardrail persistence +83/-0

Test idempotent guardrail persistence

• Verifies report retries create one audit entry and one detection set.

gateway/models/rdp_entity_detection_test.go

irongw_test.goTest TLS deadline cleanup +85/-0

Test TLS deadline cleanup

• Confirms reads continue after the temporary handshake deadline expires.

gateway/rdp/irongw_test.go

agent_guardrails_test.goTest bounded agent reports +271/-0

Test bounded agent reports

• Covers report limits, queue saturation, framing negotiation, malformed inputs, and acknowledgement ordering.

gateway/transport/agent_guardrails_test.go

Dockerfile.rapidocrPackage raw transport helpers +1/-1

Package raw transport helpers

• Includes bucket and raw image modules in the CPU PoC image.

scripts/dev/ocr-poc/Dockerfile.rapidocr

Dockerfile.rapidocr-gpuBuild resident GPU OCR runtime +31/-2

Build resident GPU OCR runtime

• Adds CuPy, packages the GPU pipeline, and prebuilds FP16 recognition models.

scripts/dev/ocr-poc/Dockerfile.rapidocr-gpu

device_policy.pyEnforce single-process ownership +21/-0

Enforce single-process ownership

• Rejects multi-worker startup when process-local GPU framebuffers are enabled.

scripts/dev/ocr-poc/device_policy.py

entrypoint-embedded.shLaunch configured OCR workers +9/-1

Launch configured OCR workers

• Validates WEB_CONCURRENCY and passes it to Uvicorn.

scripts/dev/ocr-poc/entrypoint-embedded.sh

test_gpu_pipeline.pyTest resident GPU processing +0/-0

Test resident GPU processing

• Covers sequencing, eviction, cache reuse, scrubbing, decoder parity, compositing, and failure cleanup.

scripts/dev/ocr-poc/test_gpu_pipeline.py

test_raw_image.pyTest resident transport decoding +0/-0

Test resident transport decoding

• Covers body bounds, media types, geometry, patch budgets, depths, chunks, and malformed data.

scripts/dev/ocr-poc/test_raw_image.py

test_resolve_device.pyTest worker topology validation +0/-0

Test worker topology validation

• Verifies resident mode requires one process and validates positive worker counts.

scripts/dev/ocr-poc/test_resolve_device.py

DockerfileAdd an NLA-capable test server +0/-0

Add an NLA-capable test server

• Builds a FreeRDP shadow server for TLS, CredSSP, capability, and bitmap tests.

scripts/dev/rdp-testserver/Dockerfile

start.shServe deterministic RDP test content +0/-0

Serve deterministic RDP test content

• Starts a headless PII display, configures NLA credentials, and launches FreeRDP.

scripts/dev/rdp-testserver/start.sh

qodo-code-review[bot]2mo ago

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (2) 📎 Requirement gaps (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


1. Header.Encode panics on overflow 📘 Rule violation ☼ Reliability ⭐ New
Description
Header.Encode terminates the process when a frame exceeds the wire-length limit instead of
returning an error to its caller. A malformed or oversized frame can therefore crash the gateway
rather than fail the affected operation safely.
Code

gateway/broker/headers.go[R83-84]

+	if h.Len > headerLengthMask {
+		panic("frame payload exceeds wire limit")
Relevance

●●● Strong

Panic in non-main helper on overflow is a clear reliability bug; team fixes such issues per rule
1807202.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 1807202 prohibits panic in non-main helpers. The newly added overflow branch in
Header.Encode directly panics instead of returning a recoverable encoding error.

Rule 1807202: Do not terminate the process in library/command helpers; return errors to caller gateway/broker/headers.go[79-94]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Header.Encode` panics when the payload length exceeds the wire limit, allowing a helper failure to terminate the gateway process.

## Issue Context
Compliance rule 1807202 requires non-main helpers to return errors rather than panic. Update the encoding API and propagate or handle the resulting error at all callers.

## Fix Focus Areas
- gateway/broker/headers.go[79-94]
- gateway/broker/session.go[260-265]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Proxy discards shutdown error ✓ Resolved 📘 Rule violation ☼ Reliability ⭐ New
Description
The client-to-server relay explicitly discards the asynchronous stream shutdown error without
documenting why that failure is safe to ignore. Shutdown failures can consequently be treated as
successful session closure with no error propagated to the proxy owner.
Code

agentrs/src/proxy.rs[161]

+                let _ = server_wr.shutdown().await;
Relevance

●●● Strong

Ignoring IO shutdown error unjustified matches accepted pattern of handling discarded IO errors
(rule 1807206).

PR-#1724 PR-#1658

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 1807206 requires I/O errors to be handled, propagated, or explicitly justified when ignored.
The new relay executes let _ = server_wr.shutdown().await and provides no justification or error
path.

Rule 1807206: Do not ignore errors from OS/exec/IO calls; handle or propagate them agentrs/src/proxy.rs[150-162]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The guarded proxy relay discards the result of `server_wr.shutdown().await`, silently swallowing an I/O failure.

## Issue Context
Compliance rule 1807206 requires OS and I/O errors to be handled or propagated. Return the shutdown error through the relay outcome, or explicitly document why it is safe to ignore after ensuring cleanup remains correct.

## Fix Focus Areas
- agentrs/src/proxy.rs[150-162]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Graphics bypass enterprise guard ✗ Dismissed 🔗 Cross-repo conflict ⛨ Security ⭐ New
Description
The new activation interceptor forwards every frame for which libhoop's capability pinning returns
None, even though None only means the frame is not the target capability PDU. A slow-path
graphics update received before both capabilities are pinned therefore reaches the client before
Gate::spawn, bypassing libhoop OCR and redaction.
Code

agentrs/src/rdp_proxy.rs[R765-768]

+                client_framed
+                    .write_all(patched.as_deref().unwrap_or(frame.as_ref()))
+                    .await
+                    .context("relay server activation PDU to client")?;
Relevance

●● Moderate

Complex security/architectural gap in enterprise guard forwarding; no close precedent found either
way.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR forwards the original server frame whenever libhoop returns no patched frame, and the
enterprise library documents and implements None for any valid frame that is not Demand Active.
The libhoop gate is only spawned afterward, so such bytes cannot be inspected or redacted.

agentrs/src/rdp_proxy.rs[732-768] agentrs/src/rdp_proxy.rs[185-207] agentrs/src/proxy.rs[133-143] External repo: hoophq/libhoop, rdp-guard/src/lib.rs [98-114] External repo: hoophq/libhoop, rdp-guard/src/piigate/capabilities.rs [156-168]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The guarded activation interceptor forwards non-capability server frames before the enterprise `Gate` exists. Because libhoop returns `Ok(None)` for any valid non-Demand-Active frame, a graphics update can bypass OCR and redaction.

## Issue Context
Continue relaying activation control traffic required for negotiation, but classify server traffic during interception and fail closed or safely retain any graphics/update PDU until both capability frames are pinned and the gate is active.

## Fix Focus Areas
- agentrs/src/rdp_proxy.rs[732-802]
- agentrs/src/proxy.rs[138-143]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (1)
4. Full snapshot sequence rollback ✓ Resolved 🐞 Bug ≡ Correctness
Description
GpuResidentStore.process accepts full snapshots without validating them against an existing
session's expected sequence, allowing a delayed or replayed snapshot to replace newer framebuffer
state and move the sequence backward. Subsequent valid incremental requests then fail with HTTP 409
after the newer state has already been discarded.
Code

scripts/dev/ocr-poc/gpu_pipeline.py[R1825-1829]

+        if full_snapshot:
+            # Preserve the agent's globally monotonic sequence when state
+            # moves between Uvicorn workers. Resetting to zero can make stale,
+            # divergent worker framebuffers alias the same later sequence.
+            self._drop(session_key)
Relevance

●● Moderate

The rollback race is a substantive correctness concern, but no comparable historical precedent was
found for this GPU snapshot sequencing design.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The full-snapshot branch drops and recreates an existing session without comparing the supplied
sequence to state.sequence, while only incremental requests receive an equality check. The
accepted sequence later becomes the session's new expected sequence, and the HTTP layer exposes
resulting mismatches as 409 conflicts.

scripts/dev/ocr-poc/gpu_pipeline.py[1818-1839] scripts/dev/ocr-poc/gpu_pipeline.py[1893-1903] scripts/dev/ocr-poc/server_rapidocr.py[683-684] scripts/dev/ocr-poc/server_rapidocr.py[736-737]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Full snapshots unconditionally replace existing resident state, even when their sequence precedes the session's expected sequence. Reject stale full snapshots before dropping the current framebuffer while still allowing a newer full snapshot to resynchronize missing state.

## Issue Context
The accepted request sets `state.sequence = sequence + 1`, so accepting an older snapshot rolls sequence state backward and causes later legitimate incremental requests to conflict.

## Fix Focus Areas
- scripts/dev/ocr-poc/gpu_pipeline.py[1818-1839]
- scripts/dev/ocr-poc/gpu_pipeline.py[1893-1897]
- scripts/dev/ocr-poc/test_gpu_pipeline.py[492-511]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



5. Write deadline is ineffective ✗ Dismissed 🐞 Bug ☼ Reliability ⭐ New
Description
sessionConnWrapper.Write checks the deadline only before calling SendRawDataToAgent, so a write
started just before expiry can continue beyond the configured deadline. During the RDP handshake
this defeats the two-second connection deadline because agentCommunicator.Send replaces it with
its independent ten-second WebSocket deadline.
Code

gateway/broker/session.go[R622-625]

+	if !deadline.IsZero() && !time.Now().UTC().Before(deadline) {
+		return 0, context.DeadlineExceeded
+	}
+	if err := s.session.SendRawDataToAgent(b); err != nil {
Relevance

●● Moderate

Subtle semantic deadline-handling bug across files; no directly matching precedent found for this
pattern.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The wrapper only compares the deadline before sending, while the invoked communicator applies a
fresh fixed ten-second deadline to the underlying WebSocket. The RDP gateway deliberately installs a
two-second deadline that remains active through handshakeAgentTLS, so this implementation does not
enforce that handshake write bound.

gateway/broker/session.go[618-628] gateway/broker/communicators.go[12-36] gateway/rdp/irongw.go[378-400]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`sessionConnWrapper.Write` only checks whether the write deadline has already expired. It does not apply that deadline to the actual agent WebSocket write, which instead receives the communicator's fixed ten-second timeout.

## Issue Context
The RDP gateway sets a two-second deadline before reading the X224 response and performing the TLS handshake. A write beginning before that deadline can therefore block until the longer communicator timeout.

## Fix Focus Areas
- gateway/broker/session.go[618-628]
- gateway/broker/communicators.go[30-36]
- gateway/rdp/irongw.go[378-400]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Deadlines use non-UTC clock ✓ Resolved 📘 Rule violation ≡ Correctness
Description
New agent WebSocket and session write-deadline logic uses time.Now() rather than
time.Now().UTC(). This violates the required UTC convention for gateway deadlines and deadline
comparisons.
Code

gateway/broker/communicators.go[R33-35]

+	if err := a.conn.SetWriteDeadline(time.Now().Add(agentWriteTimeout)); err != nil {
+		return err
+	}
Relevance

●●● Strong

UTC deadline convention is a deterministic correctness fix, and repository history accepts closely
related time normalization.

PR-#1188

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
agentCommunicator.Send calculates a WebSocket deadline with time.Now().Add(...), and
sessionConnWrapper.Write compares its deadline against another non-UTC time.Now() value.

Rule 1807215: Use UTC time for persisted timestamps, expirations, and deadlines gateway/broker/communicators.go[31-35] gateway/broker/session.go[619-624]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New gateway deadline calculations and comparisons use local `time.Now()` values.

## Issue Context
PR Compliance ID 1807215 requires gateway and agent deadline handling to consistently use `time.Now().UTC()`.

## Fix Focus Areas
- gateway/broker/communicators.go[31-35]
- gateway/broker/session.go[619-624]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. OCR env vars lack sample ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new OCR resident-pipeline environment variables are not mirrored in the root .env.sample.
Missing keys include OCR_GPU_PREPROCESS, OCR_RESIDENT_MAX_SESSIONS, OCR_RESIDENT_VRAM_MB,
OCR_RESIDENT_TTL_SECONDS, OCR_RESIDENT_CACHE_ENTRIES, OCR_RESIDENT_RECOGNITION_CACHE_ENTRIES,
and RDP_OCR_TRANSPORT.
Code

scripts/dev/ocr-poc/server_rapidocr.py[R103-104]

+GPU_PREPROCESS = os.environ.get("OCR_GPU_PREPROCESS", "") == "1"
+resolve_worker_concurrency(os.environ.get("WEB_CONCURRENCY"), GPU_PREPROCESS)
Relevance

●●● Strong

Repository history explicitly accepted mirroring newly introduced OCR environment variables in a
sample environment file.

PR-#1658

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Python server newly reads the GPU and resident-capacity variables, and the agent images
introduce RDP_OCR_TRANSPORT; a repository-wide check of the root .env.sample shows none of these
keys.

Rule 1800927: New env vars must be mirrored in .env.sample scripts/dev/ocr-poc/server_rapidocr.py[100-104] scripts/dev/ocr-poc/server_rapidocr.py[418-427] Dockerfile.agent-ocr-gpu[142-148] .env.sample[1-109]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New environment variables used by the resident OCR pipeline are absent from the repository-root `.env.sample`.

## Issue Context
PR Compliance ID 1800927 requires every newly introduced environment-variable key in changed code or configuration to be mirrored exactly in `.env.sample`.

## Fix Focus Areas
- scripts/dev/ocr-poc/server_rapidocr.py[103-104]
- scripts/dev/ocr-poc/server_rapidocr.py[418-427]
- Dockerfile.agent-ocr-gpu[142-148]
- Dockerfile.agent-ocr[61-64]
- .env.sample[1-109]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (2)
8. Persistence workflow lives in models ✓ Resolved 📘 Rule violation ⌂ Architecture
Description
gateway/models/rdp_entity_detection.go now coordinates session locking, duplicate-report
decisions, session updates, and detection insertion in one workflow. This business orchestration
belongs under gateway/services, leaving models limited to entity and ORM definitions.
Code

gateway/models/rdp_entity_detection.go[R46-49]

+	return DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+		var lockedSessionID string
+		lock := tx.Raw(
+			`SELECT id FROM private.sessions WHERE org_id = ? AND id = ? FOR UPDATE`,
Relevance

●●● Strong

Repository history explicitly accepted moving business/domain workflow out of gateway/models into
services.

PR-#1709

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added model function starts a transaction and coordinates operations across the sessions and RDP
detection tables, including the domain decision that duplicate report IDs are successful no-ops.

Rule 1800917: Keep business logic out of gateway/models and in gateway/services gateway/models/rdp_entity_detection.go[36-46] gateway/models/rdp_entity_detection.go[60-96]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A multi-entity guardrail persistence and idempotency workflow has been added under `gateway/models`.

## Issue Context
The workflow locks a session, checks domain-level report duplication, updates session audit data, and inserts detection records transactionally. PR Compliance ID 1800917 requires this orchestration to reside in `gateway/services` rather than model files.

## Fix Focus Areas
- gateway/models/rdp_entity_detection.go[36-98]
- gateway/services/[1-1]
- gateway/transport/websocket.go[297-335]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. GuardrailsViolationAck constant is misplaced ✗ Dismissed 📘 Rule violation ≡ Correctness
Description
The new guardrails_violation_ack packet type is declared independently in gateway and agent
modules, and the parser also compares a raw literal. Protocol packet identifiers must come from the
permitted shared common/proto/... definitions.
Code

gateway/broker/headers.go[36]

+	MessageTypeGuardrailsViolationAck = "guardrails_violation_ack"
Relevance

●● Moderate

Protocol-constant policy supports the concern, but no close accepted or rejected precedent confirms
this cross-module placement requirement.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The gateway introduces the packet type directly in gateway/broker/headers.go, while the Rust agent
separately defines the same string and compares another raw copy during parsing instead of consuming
a permitted shared protocol definition.

Rule 1800908: Use protocol packet type constants instead of raw string literals gateway/broker/headers.go[34-36] agentrs/src/ws/message_types.rs[27-30] agentrs/src/ws/message_types.rs[52-55]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new `guardrails_violation_ack` protocol packet identifier is declared outside the required shared protocol modules and is also used as a raw parser literal.

## Issue Context
PR Compliance ID 1800908 requires packet type identifiers to be defined under `common/proto/...` and referenced through shared constants.

## Fix Focus Areas
- gateway/broker/headers.go[34-36]
- agentrs/src/ws/message_types.rs[27-30]
- agentrs/src/ws/message_types.rs[52-55]
- common/proto/agent/[1-1]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



10. PersistRDPGuardrailViolation uses global DB ⊘ Outdated 📘 Rule violation ⌂ Architecture
Description
The new model function performs its transaction through package-global DB without accepting a
*gorm.DB parameter. This prevents callers from explicitly controlling the database or transaction
context.
Code

gateway/models/rdp_entity_detection.go[46]

+	return DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
Relevance

● Weak

A closely matching global-DB dependency-injection suggestion was explicitly rejected in PR #1649.

PR-#1649

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The function signature has no database parameter, but its first database operation invokes
DB.WithContext(ctx).Transaction, directly violating the required dependency-injection pattern.

Rule 1800914: Gateway model functions must accept *gorm.DB via parameter, not global gateway/models/rdp_entity_detection.go[40-46]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`PersistRDPGuardrailViolation` directly accesses the package-global `DB` while performing GORM operations.

## Issue Context
PR Compliance ID 1800914 requires gateway model functions that perform database operations to accept and use a `*gorm.DB` parameter.

## Fix Focus Areas
- gateway/models/rdp_entity_detection.go[40-46]
- gateway/transport/websocket.go[297-335]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. HandleConnection lacks Swagger annotations 📘 Rule violation ⚙ Maintainability
Description
The /ws Gin handler is modified without an attached Swagger comment block or matching `@Router /ws
[get]` directive. Consequently, the modified gateway HTTP/WebSocket entry point is not represented
by the required API annotations.
Code

gateway/transport/websocket.go[R84-85]

	defer wsConn.Close()
+	wsConn.SetReadLimit(int64(maxAgentWebSocketMessageBytes))
Relevance

● Weak

A closely matching Swagger requirement for a modified gateway handler was explicitly rejected in PR
#1711.

PR-#1711

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
HandleConnection processes a Gin HTTP request and is registered as GET /ws, but its declaration
has no preceding Swagger block while this PR changes its request-processing behavior.

Rule 1800918: Require Swagger annotations on new or modified gateway API handlers gateway/transport/websocket.go[64-85] gateway/api/server.go[1324-1324]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The modified `HandleConnection` Gin handler has no adjacent Swagger annotations, including no `@Router` directive.

## Issue Context
The handler is registered as `GET /ws` in the gateway API server. PR Compliance ID 1800918 requires new or modified gateway API handlers to carry an attached Swagger block identifying their route and method.

## Fix Focus Areas
- gateway/transport/websocket.go[64-85]
- gateway/api/openapi/autogen/docs.go[1-1]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Context sources
✅ Compliance rules (platform): 63 rules
✅ Cross-repo context — repo relationships
  Explored: repo: hoophq/libhoop (branch: dep-102, sha: 7531aff1)
Tip of the day
💡 Did you know, you can copy the agent prompt from any finding and feed it to your IDE agent

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Previous reviews

Review updated until commit a4dc9db

Results up to commit 3b63d4c ⚖️ Balanced


🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


1. Full snapshot sequence rollback ✓ Resolved 🐞 Bug ≡ Correctness
Description
GpuResidentStore.process accepts full snapshots without validating them against an existing
session's expected sequence, allowing a delayed or replayed snapshot to replace newer framebuffer
state and move the sequence backward. Subsequent valid incremental requests then fail with HTTP 409
after the newer state has already been discarded.
Code

scripts/dev/ocr-poc/gpu_pipeline.py[R1825-1829]

+        if full_snapshot:
+            # Preserve the agent's globally monotonic sequence when state
+            # moves between Uvicorn workers. Resetting to zero can make stale,
+            # divergent worker framebuffers alias the same later sequence.
+            self._drop(session_key)
Relevance

●● Moderate

The rollback race is a substantive correctness concern, but no comparable historical precedent was
found for this GPU snapshot sequencing design.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The full-snapshot branch drops and recreates an existing session without comparing the supplied
sequence to state.sequence, while only incremental requests receive an equality check. The
accepted sequence later becomes the session's new expected sequence, and the HTTP layer exposes
resulting mismatches as 409 conflicts.

scripts/dev/ocr-poc/gpu_pipeline.py[1818-1839] scripts/dev/ocr-poc/gpu_pipeline.py[1893-1903] scripts/dev/ocr-poc/server_rapidocr.py[683-684] scripts/dev/ocr-poc/server_rapidocr.py[736-737]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Full snapshots unconditionally replace existing resident state, even when their sequence precedes the session's expected sequence. Reject stale full snapshots before dropping the current framebuffer while still allowing a newer full snapshot to resynchronize missing state.

## Issue Context
The accepted request sets `state.sequence = sequence + 1`, so accepting an older snapshot rolls sequence state backward and causes later legitimate incremental requests to conflict.

## Fix Focus Areas
- scripts/dev/ocr-poc/gpu_pipeline.py[1818-1839]
- scripts/dev/ocr-poc/gpu_pipeline.py[1893-1897]
- scripts/dev/ocr-poc/test_gpu_pipeline.py[492-511]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



2. Deadlines use non-UTC clock ✓ Resolved 📘 Rule violation ≡ Correctness
Description
New agent WebSocket and session write-deadline logic uses time.Now() rather than
time.Now().UTC(). This violates the required UTC convention for gateway deadlines and deadline
comparisons.
Code

gateway/broker/communicators.go[R33-35]

+	if err := a.conn.SetWriteDeadline(time.Now().Add(agentWriteTimeout)); err != nil {
+		return err
+	}
Relevance

●●● Strong

UTC deadline convention is a deterministic correctness fix, and repository history accepts closely
related time normalization.

PR-#1188

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
agentCommunicator.Send calculates a WebSocket deadline with time.Now().Add(...), and
sessionConnWrapper.Write compares its deadline against another non-UTC time.Now() value.

Rule 1807215: Use UTC time for persisted timestamps, expirations, and deadlines gateway/broker/communicators.go[31-35] gateway/broker/session.go[619-624]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New gateway deadline calculations and comparisons use local `time.Now()` values.

## Issue Context
PR Compliance ID 1807215 requires gateway and agent deadline handling to consistently use `time.Now().UTC()`.

## Fix Focus Areas
- gateway/broker/communicators.go[31-35]
- gateway/broker/session.go[619-624]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. OCR env vars lack sample ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new OCR resident-pipeline environment variables are not mirrored in the root .env.sample.
Missing keys include OCR_GPU_PREPROCESS, OCR_RESIDENT_MAX_SESSIONS, OCR_RESIDENT_VRAM_MB,
OCR_RESIDENT_TTL_SECONDS, OCR_RESIDENT_CACHE_ENTRIES, OCR_RESIDENT_RECOGNITION_CACHE_ENTRIES,
and RDP_OCR_TRANSPORT.
Code

scripts/dev/ocr-poc/server_rapidocr.py[R103-104]

+GPU_PREPROCESS = os.environ.get("OCR_GPU_PREPROCESS", "") == "1"
+resolve_worker_concurrency(os.environ.get("WEB_CONCURRENCY"), GPU_PREPROCESS)
Relevance

●●● Strong

Repository history explicitly accepted mirroring newly introduced OCR environment variables in a
sample environment file.

PR-#1658

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Python server newly reads the GPU and resident-capacity variables, and the agent images
introduce RDP_OCR_TRANSPORT; a repository-wide check of the root .env.sample shows none of these
keys.

Rule 1800927: New env vars must be mirrored in .env.sample scripts/dev/ocr-poc/server_rapidocr.py[100-104] scripts/dev/ocr-poc/server_rapidocr.py[418-427] Dockerfile.agent-ocr-gpu[142-148] .env.sample[1-109]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New environment variables used by the resident OCR pipeline are absent from the repository-root `.env.sample`.

## Issue Context
PR Compliance ID 1800927 requires every newly introduced environment-variable key in changed code or configuration to be mirrored exactly in `.env.sample`.

## Fix Focus Areas
- scripts/dev/ocr-poc/server_rapidocr.py[103-104]
- scripts/dev/ocr-poc/server_rapidocr.py[418-427]
- Dockerfile.agent-ocr-gpu[142-148]
- Dockerfile.agent-ocr[61-64]
- .env.sample[1-109]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Persistence workflow lives in models ✓ Resolved 📘 Rule violation ⌂ Architecture
Description
gateway/models/rdp_entity_detection.go now coordinates session locking, duplicate-report
decisions, session updates, and detection insertion in one workflow. This business orchestration
belongs under gateway/services, leaving models limited to entity and ORM definitions.
Code

gateway/models/rdp_entity_detection.go[R46-49]

+	return DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+		var lockedSessionID string
+		lock := tx.Raw(
+			`SELECT id FROM private.sessions WHERE org_id = ? AND id = ? FOR UPDATE`,
Relevance

●●● Strong

Repository history explicitly accepted moving business/domain workflow out of gateway/models into
services.

PR-#1709

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added model function starts a transaction and coordinates operations across the sessions and RDP
detection tables, including the domain decision that duplicate report IDs are successful no-ops.

Rule 1800917: Keep business logic out of gateway/models and in gateway/services gateway/models/rdp_entity_detection.go[36-46] gateway/models/rdp_entity_detection.go[60-96]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A multi-entity guardrail persistence and idempotency workflow has been added under `gateway/models`.

## Issue Context
The workflow locks a session, checks domain-level report duplication, updates session audit data, and inserts detection records transactionally. PR Compliance ID 1800917 requires this orchestration to reside in `gateway/services` rather than model files.

## Fix Focus Areas
- gateway/models/rdp_entity_detection.go[36-98]
- gateway/services/[1-1]
- gateway/transport/websocket.go[297-335]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
5. GuardrailsViolationAck constant is misplaced ✗ Dismissed 📘 Rule violation ≡ Correctness
Description
The new guardrails_violation_ack packet type is declared independently in gateway and agent
modules, and the parser also compares a raw literal. Protocol packet identifiers must come from the
permitted shared common/proto/... definitions.
Code

gateway/broker/headers.go[36]

+	MessageTypeGuardrailsViolationAck = "guardrails_violation_ack"
Relevance

●● Moderate

Protocol-constant policy supports the concern, but no close accepted or rejected precedent confirms
this cross-module placement requirement.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The gateway introduces the packet type directly in gateway/broker/headers.go, while the Rust agent
separately defines the same string and compares another raw copy during parsing instead of consuming
a permitted shared protocol definition.

Rule 1800908: Use protocol packet type constants instead of raw string literals gateway/broker/headers.go[34-36] agentrs/src/ws/message_types.rs[27-30] agentrs/src/ws/message_types.rs[52-55]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new `guardrails_violation_ack` protocol packet identifier is declared outside the required shared protocol modules and is also used as a raw parser literal.

## Issue Context
PR Compliance ID 1800908 requires packet type identifiers to be defined under `common/proto/...` and referenced through shared constants.

## Fix Focus Areas
- gateway/broker/headers.go[34-36]
- agentrs/src/ws/message_types.rs[27-30]
- agentrs/src/ws/message_types.rs[52-55]
- common/proto/agent/[1-1]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



6. PersistRDPGuardrailViolation uses global DB ⊘ Outdated 📘 Rule violation ⌂ Architecture
Description
The new model function performs its transaction through package-global DB without accepting a
*gorm.DB parameter. This prevents callers from explicitly controlling the database or transaction
context.
Code

gateway/models/rdp_entity_detection.go[46]

+	return DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
Relevance

● Weak

A closely matching global-DB dependency-injection suggestion was explicitly rejected in PR #1649.

PR-#1649

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The function signature has no database parameter, but its first database operation invokes
DB.WithContext(ctx).Transaction, directly violating the required dependency-injection pattern.

Rule 1800914: Gateway model functions must accept *gorm.DB via parameter, not global gateway/models/rdp_entity_detection.go[40-46]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`PersistRDPGuardrailViolation` directly accesses the package-global `DB` while performing GORM operations.

## Issue Context
PR Compliance ID 1800914 requires gateway model functions that perform database operations to accept and use a `*gorm.DB` parameter.

## Fix Focus Areas
- gateway/models/rdp_entity_detection.go[40-46]
- gateway/transport/websocket.go[297-335]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. HandleConnection lacks Swagger annotations 📘 Rule violation ⚙ Maintainability
Description
The /ws Gin handler is modified without an attached Swagger comment block or matching `@Router /ws
[get]` directive. Consequently, the modified gateway HTTP/WebSocket entry point is not represented
by the required API annotations.
Code

gateway/transport/websocket.go[R84-85]

	defer wsConn.Close()
+	wsConn.SetReadLimit(int64(maxAgentWebSocketMessageBytes))
Relevance

● Weak

A closely matching Swagger requirement for a modified gateway handler was explicitly rejected in PR
#1711.

PR-#1711

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
HandleConnection processes a Gin HTTP request and is registered as GET /ws, but its declaration
has no preceding Swagger block while this PR changes its request-processing behavior.

Rule 1800918: Require Swagger annotations on new or modified gateway API handlers gateway/transport/websocket.go[64-85] gateway/api/server.go[1324-1324]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The modified `HandleConnection` Gin handler has no adjacent Swagger annotations, including no `@Router` directive.

## Issue Context
The handler is registered as `GET /ws` in the gateway API server. PR Compliance ID 1800918 requires new or modified gateway API handlers to carry an attached Swagger block identifying their route and method.

## Fix Focus Areas
- gateway/transport/websocket.go[64-85]
- gateway/api/openapi/autogen/docs.go[1-1]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


qodo-code-review[bot]reviewed2mo ago
sandromello2mo ago

✅ Build Completed with Success, Version=1719.0.0-ge0ad64d

sandromello2mo ago

✅ Build Completed with Success, Version=1719.0.0-g6603904

racerxdlreviewed2mo ago
sandromello2mo ago

✅ Build Completed with Success, Version=1719.0.0-gdcf9497

qodo-code-review[bot]reviewed2mo ago
qodo-code-review[bot]2mo ago
racerxdlreviewed2mo ago
racerxdlreviewed2mo ago
racerxdlreviewed2mo ago
racerxdlreviewed2mo ago
sandromello2mo ago

✅ Build Completed with Success, Version=1719.0.0-ga4dc9db