using ZB.MOM.WW.OtOpcUa.Commons.Browsing; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Browsing; /// /// Outcome of . On success /// is and is the /// registry handle; on failure carries a human-readable /// diagnostic for the UI's error chip. /// /// True iff the browse session was opened and registered. /// Failure diagnostic, or on success. /// Registry handle on success; on failure. public sealed record BrowseOpenResult(bool Ok, string? Message, Guid Token); /// /// Scoped Razor-page facade over the in-process browse-session machinery. Owns /// driver-type dispatch on open and per-call timeout enforcement on expand/attributes. /// public interface IBrowserSessionService { /// Opens a session against the named driver type using the given JSON config. /// Never throws — all errors are surfaced via . /// The driver type to open a browse session against. /// The driver configuration as JSON. /// Cancellation token for the operation. /// The result of opening the session, including the registry token on success. Task OpenAsync(string driverType, string configJson, CancellationToken ct); /// Returns the root nodes of an open session. Throws /// if the token is unknown. /// Registry handle for the open browse session. /// Cancellation token for the operation. /// The top-level browse nodes. Task> RootAsync(Guid token, CancellationToken ct); /// Returns the direct children of in an open session. /// Throws if the token is unknown. /// Registry handle for the open browse session. /// The node whose direct children are returned. /// Cancellation token for the operation. /// The direct children of the node. Task> ExpandAsync(Guid token, string nodeId, CancellationToken ct); /// Returns the attributes of in an open session. Throws /// if the token is unknown. /// Registry handle for the open browse session. /// The node whose attributes are returned. /// Cancellation token for the operation. /// The attributes of the node. Task> AttributesAsync(Guid token, string nodeId, CancellationToken ct); /// /// Asks the remote peer(s) addressed by to re-announce themselves, on /// a session whose driver offers that action (today: MQTT in Sparkplug B mode, where it is a /// Sparkplug rebirth-request NCMD). /// /// Registry handle for the open browse session. /// The driver-specific target — for Sparkplug, a browse node id from the /// session's own tree, or a bare {group}/{edgeNode}. /// Cancellation token for the operation. /// The number of request messages published. /// /// The only browse operation that writes to the device network, and therefore the only /// one carrying an authorization check: the caller must satisfy the same /// DriverOperator policy that gates the picker's Browse affordance. Everything else on /// this facade is read-only. /// /// The token is unknown (or was reaped). /// The caller is not a DriverOperator. /// This session's driver has no re-announce action. Task RequestRebirthAsync(Guid token, string scope, CancellationToken ct); /// /// True when the open session behind can actually re-announce — i.e. /// is worth offering. Cheap (no I/O); never throws; false for /// an unknown/reaped token. /// /// Registry handle for the open browse session. /// True when the picker should draw a Request-rebirth affordance. /// /// A capability probe, not an authorization check — the DriverOperator gate lives on /// and fails closed there. The picker gates on both: this /// decides whether the action exists at all (a plain-MQTT window has none), the policy decides /// whether this operator may fire it. /// bool CanRequestRebirth(Guid token); /// Removes the session from the registry and disposes it. No-op for unknown tokens. /// Registry handle for the browse session to close. /// A task that represents the asynchronous operation. Task CloseAsync(Guid token); /// True when a browse affordance exists for this driver type: a bespoke browser /// is registered, or the universal browser can serve it. Cheap (no connect); never throws. /// Drives the picker's Browse-button visibility. /// The driver type name. /// The authoring DriverConfig JSON (may be mid-edit). /// True when the picker should offer a Browse affordance for this driver. bool CanBrowse(string driverType, string configJson); } /// /// Raised by the service layer when a caller references a token that is not /// (or no longer) in the registry — typically because the reaper evicted it /// between calls. /// public sealed class BrowseSessionNotFoundException(Guid token) : InvalidOperationException($"Browse session {token} not found (may have been reaped).");