Assistant Guide
This page is a consolidated guide for assistants, AI tooling, and docs consumers working with@anikitenko/fdo-sdk.
It summarizes the current documented contract across:
- README.md
- docs/ARCHITECTURE.md
- docs/RENDER_RUNTIME_CONTRACT.md
- docs/SAFE_PLUGIN_AUTHORING.md
- docs/EXTENSION_POINTS.md
- docs/HOST_PRIVILEGED_ACTIONS_CONTRACT.md
- docs/QUICK_REFERENCE.md
- docs/INJECTED_LIBRARIES.md
- docs/SHAREPOINT_PROVIDER_HOST_CONTRACT.md
- docs/API_STABILITY.md
What This SDK Is
@anikitenko/fdo-sdk is an SDK for building plugins for the FlexDevOps desktop application ecosystem.
The SDK spans two distinct runtimes:
- Backend/plugin runtime
- plugin lifecycle
- handler registration
- storage
- logging
- diagnostics
- host IPC
- Iframe UI runtime
- UI returned by
render() - browser DOM access
- host-injected helpers and UI libraries
- sandboxed iframe execution managed by FDO
- UI returned by
Source Of Truth Order
When answering questions or generating code, prefer these sources in this order:- README.md
- docs/RENDER_RUNTIME_CONTRACT.md
- docs/ARCHITECTURE.md
- docs/API_STABILITY.md
- Root package exports from
src/index.ts
Runtime Model
Backend Runtime
Use backend runtime for:init()- handler registration
- storage
- logging
- diagnostics
- host-mediated privileged actions
Iframe UI Runtime
Use iframe runtime for:- DOM access
- event binding
window.createBackendReq(...)- host-injected helpers
- host-injected UI libraries
window.createBackendReq(...)window.waitForElement(...)window.executeInjectedScript(...)window.addGlobalEventListener(...)window.removeGlobalEventListener(...)window.applyClassToSelector(...)
- Notyf
- Highlight.js
- ACE
- Split Grid
- FontAwesome
- Pure CSS
Core Render Mental Model
Treatrender() output as UI source for the FDO iframe render pipeline, not as arbitrary raw HTML inserted into the host DOM.
That means:
render()synchronously returns a stringrenderOnLoad()may synchronously return:- a string
- a function
- a
defineRenderOnLoad(...)payload
- the SDK serializes render and on-load transport separately
- UI code runs later in the sandboxed iframe
- “plain HTML string” is an incomplete mental model
- “React component source” is also not quite right
- the safest description is: JSX-compatible UI source for the FDO iframe host pipeline
Minimal Plugin Shape
Every plugin should provide:metadatainit()render()
Metadata Rules
Rules:- define full metadata:
name,version,author,description,icon metadata.iconmust be a valid BlueprintJS v6 icon name- prefer a stable
metadata.idwhen your host/plugin flow supports it
Markup And Render Safety
The FDO iframe render pipeline is JSX-like and stricter than unconstrained browser HTML parsing. Important rules:- prefer JSX-safe void tags like
<br /> - avoid raw
<style>blocks inrender() - escape literal
{and}in code samples - avoid embedding raw JSON or object literals directly into JSX-visible markup
- avoid guard-sensitive runtime tokens in display text when plain text works
- use
DOMTexthelpers - do not pass unsanitized text as raw child markup into generic DOM helpers
DOM Helper Rules
SDK DOM helpers are the preferred pattern for general structured UI. Compatibility aliases are accepted on input:classNamehtmlForreadOnly
classforreadonly
renderHTML(...) Rule
If render() uses SDK DOM helpers and expects helper-generated styling/classes to work, wrap the final helper output with renderHTML(...).
This is mandatory for styled helper output because helper-generated class names require emitted CSS.
Example:
Recommended renderOnLoad() Pattern
Prefer defineRenderOnLoadActions(...) for non-trivial UI event wiring.
Why:
- typed handler map
- declarative bindings
- clearer failure behavior
- easier editor/template integration
Handler Model
UsePluginRegistry.registerHandler(name, handler) for UI-to-backend calls.
Good handler design:
- stable names
- explicit payload expectations
- validation at handler boundaries when needed
- deterministic error paths
- hidden side effects
- transport shape drift
- treating tests as the only contract source
Storage Model
Supported stores:PluginRegistry.useStore("default")- plugin-scoped in-memory store
PluginRegistry.useStore("json")- plugin-scoped persistent store
- requires configured storage root
- requires host capability grants
PluginRegistry.configureStorage({ rootDir })orFDO_SDK_STORAGE_ROOT- host-granted capabilities:
storagestorage.json
- do not call
PluginRegistry.useStore(...)in class-field initializers - acquire stores lazily or in
init()/handlers
Logging And Diagnostics
Preferred plugin logging APIs:this.log(...)this.info(...)this.warn(...)this.debug(...)this.verbose(...)this.silly(...)this.error(error)this.event(name, payload)
Capability Model
Privileged features are host-gated. Plugins may declare expected capabilities, but the host remains authoritative. Common capability families:storagestorage.jsonsystem.networksystem.network.httpssystem.network.httpsystem.network.websocketsystem.network.tcpsystem.network.udpsystem.network.dnssystem.network.scope.<scope-id>system.clipboard.readsystem.clipboard.writesystem.hosts.writesystem.fs.scope.<scope-id>system.process.execsystem.process.scope.<scope-id>sudo.prompt
- declare expected capabilities in
declareCapabilities() - still perform runtime checks when authorization matters
Privileged Actions
Host-mediated privileged operations are the supported path for actions outside normal plugin boundaries. Current action families:system.clipboard.readsystem.clipboard.writesystem.hosts.writesystem.fs.mutatesystem.process.execsystem.workflow.run
validateHostPrivilegedActionRequest(...)requestPrivilegedAction(...)requestPrivilegedActionFromEnvelope(...)formatPrivilegedActionError(...)createClipboardReadRequest(...)createClipboardWriteRequest(...)createFilesystemMutateActionRequest(...)createProcessExecActionRequest(...)
response.error.
Use formatPrivilegedActionError(...) so users get:
- correlation ID
- error code
- stderr/stdout when available
- exit code
- command and cwd when available
Extension Points
Supported extension points:- lifecycle methods
init()render()renderOnLoad()
PluginRegistry.registerHandler(...)PluginRegistry.useStore(...)PluginRegistry.registerStore(...)QuickActionMixinSidePanelMixin- DOM helper modules
- private registry internals
- communicator internals
_-prefixed internals- undocumented host implementation details
Stable Vs Provisional Guidance
From docs/API_STABILITY.md:Stable
Safe to depend on:- root package exports from
src/index.ts FDO_SDKlifecycle methods- documented
PluginRegistrypublic methods - documented public types and helpers
- documented render-on-load authoring helpers
- documented privileged action helper exports
Provisional
Usable but evolving:- advanced store lifecycle metadata shape
- some migration/version hook behavior
- example plugin implementations under
examples/
Internal
Do not depend on:- private/static registry fields
- communicator transport plumbing
- store internals
- logger backend wiring details
- unexported files/functions
Examples Guidance
Recommended learning order:examples/fixtures/minimal-plugin.fixture.tsexamples/fixtures/error-handling-plugin.fixture.tsexamples/fixtures/storage-plugin.fixture.ts- production-oriented fixtures under
examples/fixtures/ - numbered learning examples under
examples/
- examples are useful and documented
- examples are still considered provisional API-stability surface
- do not treat example implementation details as stronger than the main docs and public exports
Connector And SharePoint Pattern
Example 13 is a connector-style plugin pattern. Architectural rule:- host owns session transport and request execution
- plugin owns provider-specific parsing and UX behavior
- host stores session/auth state
- plugin interprets provider responses
- plugin decides pending vs authenticated UI state
- plugin explicitly persists parsed credentials/session auth into the host
- host stays API-agnostic
Security Guidance
Key expectations:- plugin UI runs in a sandboxed iframe
- privileged operations are explicit and validated
- network access is capability-gated and scope-gated
- host/plugin boundaries should stay explicit
- prefer explicit contracts over convenience inference
- keep provider-specific semantics in the plugin unless the host contract explicitly owns them
Assistant Guidance
When helping users with this SDK:- distinguish backend runtime from iframe runtime immediately
- recommend fixture-first guidance for new plugin authors
- prefer
defineRenderOnLoadActions(...)for UI wiring - prefer host-mediated privileged APIs over ad hoc shell/filesystem escape patterns
- recommend capability declarations plus runtime checks
- keep host generic and move provider-specific behavior into plugins
- treat
renderHTML(...)as mandatory for styled DOM-helper output - do not recommend arbitrary npm imports inside iframe runtime unless the host explicitly injects and documents them