DC-UI: DataCollector User Interface Deep Dive
The comprehensive technical manual covering every DC-UI capability: inventories monitoring, entities explorer, analytics, configuration designers, entity badges, health checks, and more.
π₯οΈ DC-UI Overview & Capabilities
DC-UI is the web-based Experience Platform plugin that provides the complete interface for managing DataCollector. All configuration edits happen through either visual forms or direct YAML editing with validation. DC-UI manages configuration, triggers and monitors inventory runs, tests configurations before deploying, browses collected entities, analyzes past runs, and tracks administrative events.
What DC-UI Can Do
| Area | Capabilities |
|---|---|
| Configuration Management | Strategy-specific visual designers (systems, system types), connector-specific designers (credentials), reusable YAML editors (schema mappings), Python plugin management (strategies, connectors) |
| Inventory Operations | Triggers and monitors inventory runs with live status updates, polled on the interval declared in the plugin manifest (currently 2 seconds) |
| Testing & Validation | Tests configurations with real-time event streaming (SSE) before deploying to production using DETACHED_READONLY_INVENTORY |
| Data Exploration | Browses collected entities with filtering and inspection via Entities Explorer |
| Analytics | Analyzes past inventory runs through detailed event tabs (connector calls, changes, logs, templates, diffs) |
| Administration | Tracks administrative events (health checks, config changes, triggers) with filtering and audit trails |
High-Level Areas (Navigation)
- Inventories β Real-time system status, trigger runs, system management
- Entities Explorer β Browse collected entities with server-side filtering
- Past Inventory Runs Analytics β Detailed event analysis per run
- Cross-Inventory View β Multi-run analysis across time
- Admin Events β Track operations, health checks, config changes
- Configuration β Systems, System Types, Strategies, Connectors, Schemas, Credentials
Access & Integration
DC-UI is loaded as an Experience Platform plugin. Access via the Experience shell at the configured route (typically /dc-ui). The plugin is located in experience/plugins/dc-ui/ and integrates with DataCollector's REST API for all operations.
Platform Integration Update
In current deployments, DC-UI driven inventory runs often feed both analytics and search enrichment paths. When troubleshooting delayed visibility in downstream dashboards or universal search, validate DC run health first, then verify analytics/search consumers.
Keyboard Shortcuts
DC-UI implements Blue Steel animations and keyboard shortcuts for power users:
- Ctrl+1 through Ctrl+4 β Navigate between main sections
- Ctrl+R β Refresh current data (e.g., Admin Events)
- Ctrl+S β Save (where applicable)
- Escape β Close modals or cancel actions
π‘ Designer vs YAML Mode
Always prefer the Designer tab for guided configuration with validation. Use the YAML tab when you need to preserve comments, bulk edit, or work with advanced configuration. Switching from YAML back to Designer auto-serializes and may lose comments or unknown properties.
π¦ Inventories Page
The Inventories page displays systems grouped by organization with real-time monitoring and full system management capabilities. It is the primary operational dashboard for data collection.
Grouped Layout, Streams as Sub-Rows
Systems are grouped by their group field (or Ungrouped when missing). Each group has a collapsible header row; group expansion is persisted in localStorage:
- Group header row β chevron / system count / aggregated stream-status counts / aggregated inventory-status counts / aggregated health success-failure tags / sum of entity counts
- Single-stream system β one row containing the system + its stream's controls inline; the system name is bold with no expand chevron
- Multi-stream system β a clickable parent row that toggles inline expansion (state persisted), shows aggregated status counts and the entity total, and exposes only system-level actions. Per-stream sub-rows render indented below when expanded, each with its own status, lifecycle, and per-stream actions.
Real-Time Status Polling
Status polls on the interval declared in the plugin manifest (sdk.config.polling.intervalMs β currently 2 seconds in the shipped manifest, but it's whatever the deployment sets). The page throws at construction time if the manifest doesn't supply it. Polling uses AbortController and an in-flight flag to prevent overlapping requests, and only the systems list refreshes on each tick. Health timeline is fetched once via getHealthTimeline(24, 'system_name') and refreshed every 5 minutes independently.
Stream-level status tags:
- enabled (success), disabled (warning), gone (default), error (error)
- A blue State Exists tag appears alongside when
inventory_state_existsis true
Stream-level inventory status (live execution):
- RUNNING (green, play icon) β also surfaces the holding
instance_idas a blue tag, a Started: timestamp line, and a View Diagram link to/dc-ui/inventory-diagram/:systemName/:streamName - STOPPING (orange, stop icon)
- UNRESPONSIVE (red, "Unresponsive, expiring") β instance lease about to expire
- NOT_RUNNING (default)
Trigger Modes
DC has five engine-level trigger modes (day 26 covers the underlying execution-mode semantics). The Trigger Type modal presents them as four cards β Replay and Readonly Replay share one card with a Mode Switch (Writable publishes; Readonly previews only), since they share all other parameters:
| Mode | Description | Use Case |
|---|---|---|
| New Writable | Production with database persistence | Normal scheduled runs that persist all changes |
| Existing Readonly | Resume from database in read-only mode | Inspect an interrupted inventory without further changes |
| Detached Readonly | In-memory test with optional use_db_entities toggle |
Test configuration changes without affecting production; toggle use_db_entities to reference real entities for FK lookups |
| Replay | Re-publish stored entity data to destinations | Recover from consumer drift; system-wide (acquires all stream leases) |
| Readonly Replay | Like Replay but no destination publishing | Preview what a replay would publish without actually publishing |
Each mode allows selecting inventory_input source: from previous run, empty, custom JSON, or (when the strategy declares them) a named trigger profile via get_trigger_profiles().
Trigger Type Modal β choosing a mode
Clicking Trigger on a stream opens the Trigger Type modal. The header carries the system + stream context; the body offers four mode cards plus an optional Commands card:
- New Writable β production inventory: persists to the DB and publishes diffs
- Detached Readonly β in-memory inventory; no DB writes, no publishing
- Existing Readonly β attach to whatever inventory state is already in the database; results stay in memory
- Replay β re-publish stored entity data through the diff pipeline; no connector calls
The modal also shows a Commands card whenever the strategy publishes commands applicable to the current scope (system-level commands when no stream is selected; stream-level commands when a stream is selected; both for single-stream systems). Clicking the Commands card slides out a right panel listing each command as a small card with name, description, and stream label; clicking a command card runs it immediately and closes the modal β commands modify the stream's next_inventory_input via CAS without starting an inventory.
Trigger Inventory Modal β per-mode contents
Clicking a mode card opens the Trigger Inventory modal with mode-specific options:
| Mode | Modal contents |
|---|---|
| New Writable | Quick Trigger Profiles tiles when the stream's trigger_profiles is non-empty (clicking a tile pre-populates Custom JSON); Inventory Input radio (From previous run / Empty {} / Custom JSON); a Custom JSON TextArea when Custom is selected. The OK button is labeled by mode. |
| Detached Readonly | A Use Database Entities Switch (off = purely detached, on = read existing DB entities for relation resolution / FK lookups). Same Quick Trigger Profile tiles + Inventory Input radio + Custom JSON textarea as Writable. |
| Existing Readonly | No Inventory Input radio and no Custom JSON textarea β this mode attaches to whatever the DB has. Quick Trigger Profile tiles still render when the stream has profiles (they're effectively cosmetic for this mode). OK button starts the read-only attach. |
| Replay | A Profile Select (loaded from getReplayProfiles; label format name (store_name)); a profile description block (description, store_name, entity_types); a Mode Switch (Readonly = monitoring only / Writable = publishes to destinations); an optional Since ISO datetime input controlling how far back to re-publish. OK is disabled until a profile is selected. |
Why Replay decomposes Readonly vs Writable inside the modal
Replay is one mode card, but the engine maps it to two trigger types β REPLAY (Writable) and READONLY_REPLAY (Readonly) β depending on the Mode Switch. Day 26 covers the underlying execution-mode semantics; system-admins/04-replay.md covers the profile shape and the since behavior.
System-wide vs per-stream triggers
Most modes target one stream. Replay and Readonly Replay are system-wide: they re-publish across all streams of a system, and acquire all stream leases at once via CompoundLeaseInfo. The UI surfaces this with system-level vs stream-level button placement.
Per-Stream vs Per-System Actions
Action sets are contextual β they appear on the row whose scope they apply to:
| Action | Where it appears | Description |
|---|---|---|
| Trigger | Single-stream row or stream sub-row, only when status is NOT_RUNNING and not gone / error |
Opens the Trigger Type modal |
| Stop | Single-stream row or stream sub-row, only when RUNNING | Graceful cancellation; step in progress completes before shutdown |
| Enable / Disable | Single-stream row or stream sub-row | Toggle a stream's participation in scheduling |
| Cleanup | Single-stream row or stream sub-row (inventory cleanup); multi-stream parent row (entity-purge only) | Two-purpose modal β see Cleanup modal below |
| Enable All / Disable All | Multi-stream parent row, with Popconfirm | Bulk toggle every stream of the system |
| Disable All (system-wide) | Breadcrumb action button (gated by dc-ui:system manage) |
Disable every stream across every system; Popconfirm-protected |
| Edit next_inventory_input | Per-stream row; on multi-stream parent rows the column collapses to a Commands button when system-level commands exist | Modify JSON passed to the stream's next inventory; see Edit NII Modal below |
| View Diagram | Stream row, only while RUNNING | Full-screen Mermaid view of the running inventory's state |
All actions gate through withAuth('dc-ui:system', 'manage', β¦); per-row loading replaces the row's tags with a spinner while an operation is pending. Click events on actions stopPropagation so they don't toggle the row's expansion.
Filtering, Grouping, Search
The filter row sits above the table; preferences are persisted in localStorage:
- Search β multi-term, AND, case-insensitive; tree filter β a system stays visible when every term matches the group, the system, or any of its stream names
- Existing only β Switch; filters out systems whose every stream is GONE
- Running only β Switch; keeps systems with any non-NOT_RUNNING stream
The breadcrumb shows a DC is live Badge (green) or DC is offline (red). Ctrl+R triggers a refresh.
Health Column & Entity Counts
The Health column renders a HealthCheckMiniGraph per system (not per stream sub-row), filtered by system name from the shared timeline data. Double-click a graph to navigate to Admin Events filtered to that system's health checks β the path from "this looks unhealthy" to "here's the failing event in detail."
The Entity Counts column lists each entity type with its total. A small bar-chart icon opens a Popover with an EntityCountsGrid (lazy-loaded granular counts per entity type, broken down by visibility and store dimensions). An arrow icon navigates to the Entity Explorer scoped to (systemName, entityType); the granular grid's filter clicks navigate to the explorer with pre-applied filters.
Next Inventory Input Column
The Next Inventory Input column shows the strategy-supplied display string when present (with eye-icon Popover for the full JSON), otherwise falls back to a JSON preview with truncation. An edit pencil opens the Edit Next Inventory Input modal: a JSON textarea preloaded with the current NII, an Empty shortcut button that resets to {}, Save / Cancel β and below the textarea, applicable commands as clickable command cards (clicking executes the command immediately and closes the modal).
Cleanup Modal
The Cleanup button is the only place that gates DC's destructive operations. The modal is radio-switched between two cleanup types β only one is enabled at a time, depending on the scope from which Cleanup was opened:
| Cleanup type | Scope | Effect |
|---|---|---|
| Cleanup Ongoing Inventory | Stream-level (only enabled when a stream context is present) | Cancels the stream's running execution and clears its in-flight inventory state β reversible (the stream can be re-triggered immediately) |
| Purge All Entities | System-level (only enabled when the cleanup was opened at system level) | Permanently deletes entity tracking data β irreversible |
For the entity-purge variant, an optional Scope selector lazy-loads store names via getSystemEntityCounts and lets the user pick a single store (or leave empty for full purge). When a store is picked, an additional checkbox appears: Also delete entities left with no remaining store tracking.
β οΈ Two-step confirmation
Both purge variants demand two matching inputs before OK enables:
- Type the exact phrase:
purge all entities,purge store, or skip (for inventory cleanup) - Type the system name exactly
OK stays disabled until both inputs match and the store-names load has settled. The page surfaces a Progress modal during the operation; the systems list refreshes when it completes.
Inventory Execution Flow
The following diagram illustrates the complete execution flow when an inventory is triggered, showing interactions between UI, engine, strategy, connectors, and destinations:
π― Key Flow Points
Entry Step: Strategy defines the starting point via get_entry_step_name()
Step Dispatch: Each step can trigger new steps dynamically
Transform Pipeline: pre_transform β schema_mapping β entity creation
Persistence: Each step commits independently for crash recovery
Publishing: Diffs sent to destinations only after successful completion
π Entities Explorer
Entities Explorer browses entities collected and stored in PostgreSQL per-system with server-side filtering and pagination. Select a system to see available entity types with counts.
Selecting a Scope
Entity Explorer is scoped by system and entity type together β both must be chosen before the table renders:
- System selector β searchable dropdown ordered by total entity count (with-entities first, then alphabetical). Labels show the count when non-zero, e.g.
prod-sap (1,234). - Entity type selector β radio button group, each labeled with the entity type and a purple count Tag. Auto-selects the first entity type when none is chosen.
The URL reflects the current scope (/dc-ui/entities-explorer/:systemName/:entityType) and updates without a full navigation, so any view is bookmarkable. Per-entity-type arrow icons on the Inventories page deep-link straight here.
Granular Counts Grid
Once a scope is chosen, a granular counts grid appears under the selectors, summarizing the entity population across visibility and store dimensions (deleted, visible-in-store-X, no remaining store tracking, etc.). Clicking any cell drops you into the table pre-filtered to that slice β for example, "deleted entities", "entities visible only in store eid", or "orphan entities with no store tracking left".
Toolbar & Filters
The toolbar (visible after selection) drives every filter dimension. Aside from a scope-spanning Reset, Refresh (also Ctrl+R), Column Picker, and Export, the controls split into "always shown" and a "More Filters" panel:
| Control | Where | What it does |
|---|---|---|
| Store Select | Toolbar | Filters to a single store; labels include per-store entity counts (storeName (count)); allowClear; disabled when has_stores=false. Switches per-store column filters and per-store sort. |
| Status | Toolbar | All / Active / Deleted (maps to the is_deleted filter) |
| Updated On, Last Confirmed, Created, Store Updated | More Filters panel | Four independent date ranges (from / to). Store Updated is only meaningful when a store is selected. |
| has_stores, has_alive_stores, has_visible_stores, has_invisible_stores, store_exists | More Filters panel | Five tri-state boolean selectors (Any / Yes / No). store_exists appears only when a store is selected. |
| store_visibility | More Filters panel (only when a store is selected) | Per-store visibility selector |
The More Filters button shows a small Badge with the count of active advanced filters, and auto-expands when any of these were set from URL query params (store, is_deleted, has_alive_stores, has_visible_stores, has_invisible_stores, has_stores, store_visibility). Choosing or clearing a store automatically clears the per-store filters and sorts that no longer apply; setting has_stores=false automatically clears the selected store and per-store filters / sorts (orphan branch).
Fixed and Per-Store Columns
The table mixes a fixed set of entity-level columns with dynamic per-store columns built from the rows currently on screen.
- Fixed entity columns: Key1, Key2, Key3, Relation 1/2/3, Attribute 1/2/3, Updated On, Created On (default hidden), Last Confirmed, Is Deleted, Stores summary
- Per-store columns for each store name
Sseen in the current rows:S.status(Visible / Invisible / Deleted, default hidden)S.hash(default hidden)S.store_updated_onS.store_created_or_resurrected_on(default hidden)S.transformed_data.<attr>per attribute key seen inattribute_transformed_dataS.hashes.<attr>per attribute key seen inattribute_hashes(default hidden)S.ts.<attr>per attribute key seen inattribute_timestamps(default hidden)
Per-column filter dropdown: text input with Contains / Equals radio plus Reset / Search; pressing Enter or clicking Search applies it. Sorting is server-side, default updated_on desc; for store-prefixed columns the prefix is stripped before sending to the API.
Column Picker, Page Size, Persistence
The Column Picker Popover offers Show All / Keys Only preset buttons plus per-column checkboxes (the last visible column is disabled to prevent hiding everything). Page size options are 20 / 50 / 100 with default 50. All three preferences β hidden columns, page size, and the active store β are persisted per system+entityType in localStorage so your layout sticks across sessions.
Cell Rendering
The grid uses explicit, non-collapsing renderers so empty / missing data is unambiguous:
nullβ grey "null" Tagundefinedβ grey "β" Tag- empty string β grey
""Tag - objects β
<code>with the full JSON in a Tooltip
Entity Details Modal
Clicking the eye icon on a row (Actions column, fixed right) opens an 800px-wide tabbed modal:
- Overview β Descriptions grid for keys (Key1, Key2 / Key3 / relation keys only when present), Status (Active / Deleted), Last Confirmed, Created, Updated, plus a Stores summary table (per-store rows with status tag β green Visible / orange Invisible / red Deleted β hash 16-char preview, updated_on, created_or_resurrected_on). When the entity has no stores, the table reads "No stores (orphan entity)".
- Per-store tabs β one per store the entity has, with a status tag in the tab label. Body shows hash, updated_on, created_or_resurrected_on, plus a JsonViewer for
attribute_transformed_data(when non-empty), a JsonViewer forattribute_hashes(when non-empty), and a Descriptions grid forattribute_timestamps. - Raw JSON β the entire entity record dumped through JsonViewer.
Default active tab is the per-store tab matching the toolbar's current store selection (when that store exists on the entity), otherwise Overview.
Export
| Format | Scope | Details |
|---|---|---|
| CSV (visible columns) | Current Page or All Data | Headers from column titles; commas / quotes / newlines escaped; per-store fields resolved from each row's stores[].store_name matching the column's prefix |
| JSON (all columns) | Current Page or All Data | Full record dump β no field filtering, all hidden columns included |
"All Data" re-fetches with pageSize=total using the same filters and sort. Filename pattern: {systemName}_{entityType}_{YYYY-MM-DD_HH-mm-ss}.{csv|json}.
π‘ Debugging Entity Collection Issues
Missing entities? Check the four date ranges β Updated On, Last Confirmed, Created, Store Updated β one of them may be filtering them out
Unexpected values? Click the eye icon to inspect the full per-store record (Overview + per-store tabs + Raw JSON)
Visibility issues? Use the granular counts grid cell links to jump to "invisible" or "deleted" slices, or use the boolean filters in More Filters
Performance concerns? Use column filters to narrow results before exporting; CSV exports only the visible columns, so trim the column picker first
π Past Inventory Runs Analytics
Lists all inventory runs with server-side pagination and filtering. Click any run to drill down into 12 detailed tabs with event-level analysis.
List-Level Filtering
- System, strategy, time range, trigger mode
- Execution statistics in columns: duration, step counts by outcome, connector calls, changes, diffs, instance
12 Drill-Down Tabs
| Tab | Content |
|---|---|
| Overview | Statistics and inventory metadata (trigger mode, instance, duration, step outcomes); renders structured_output from finish_inventory() in a JSON viewer panel |
| Steps | Execution timeline with all step lifecycle events (start, finish, outcome, parameters); per-step structured_output from finish_step() |
| Logs | Filterable by severity (DEBUG, INFO, WARNING, ERROR) |
| Changes | Entity modifications with full transformed data (old/new) |
| Diffs | Change decisions with old/new hash comparison and decision reasoning |
| Connector Calls | API requests/responses with expandable raw data (params, response body) |
| Diff Publications | Publish events per destination (EmpowerID, Kafka, File) with success/failure |
| Template Evaluations | Expression evaluations with context (input variables, evaluation results). The visible tab label is Template Evaluations; some other places call this just "Templates". |
| Diagrams | Mermaid state visualization of execution flow |
| Performance | Gantt chart showing step timing and overlap |
| Step Dispatch Chain | Execution flow showing how steps dispatched to each other |
| Next Inventory Input Changes | Per-stream NII writes captured during the run: timestamp, target stream, command (when triggered by a command), step name, plus old / new value with a collapsible diff. Useful for auditing how the run mutated state for the next run. |
Tab Features
Each tab provides:
- Filtering β Tab-specific filters
- Sorting β By any column
- Column choosers β Show/hide columns with localStorage persistence
- Query statistics β Rows read, bytes read, elapsed time for performance insight
Overview Tab Details
The Overview tab displays aggregated statistics: total duration, step count by outcome (SUCCESS, EXPECTED_FAILURE, FATAL_FAILURE, RETRYABLE_FAILURE), connector call count, changes count, diffs published, instance that ran it, trigger mode, strategy name. Metadata includes inventory_input summary and next_inventory_input if available.
Steps Tab Details
Shows execution timeline with columns: step name, step parameter (for generic execute steps), outcome, start time, duration, instance. Each step lifecycle event (started, finished) is captured. Filter by step name or outcome to find failures quickly.
Connector Calls Tab Details
Expandable rows show request params (connector name, method, endpoint, query), response status, duration, and raw response body. Useful for debugging API issuesβverify request structure and inspect error responses.
Diffs Tab Details
The Diffs tab shows every change-decision the engine emitted during the run. Decisions split into two families based on whether they produce a diff:
Change-detection-only (no diff produced)
These tags are emitted by the ChangeProcessor (CP) and never reach the DiffPublisher. They explain why an entity was inspected but no diff was routed:
- Unchanged β same hash as last inventory; no work to do
- Deferred β purge-unseen scheduled, but
min_absent_inventoriesthreshold not yet reached - NotFound β entity didn't exist in the previous state
- Invisible β entity exists but visibility rules (AttributeCheck / ForeignKeyCheck) suppress it
- InvisibleDataChanged β invisible entity's data changed (still suppressed)
- InvisibleUnchanged β invisible entity's data unchanged
- KeysChanged β composite key changed; treated as a new entity
Diff produced and routed through StoreDelta
These tags drive the Diff Publications tab β every diff in this family was sent to one or more destinations:
- Created, Updated, Deleted, Purged β standard lifecycle transitions
- BecameInvisible / BecameVisible β visibility-rule transitions (entity itself was already tracked)
- CascadeBecameInvisible / CascadeBecameVisible β backward-cascade transitions (visibility flipped because of a related entity)
Per-row context: store, destination, attribute_name, deletion_context, doc_id, doc_type_id, old/new hash 8-char preview, dynamic Data.* columns, and an eye icon that opens DetailsModal with the full record. See strategies-development/050-changes-processing-pipeline.md for the decision logic.
Performance Tab (Gantt Chart)
Visual timeline of step executionβsee parallelism, bottlenecks, and overlap. Steps that ran in parallel appear as concurrent bars. Identify slow steps that block others.
Step Dispatch Chain
Execution flow showing how steps dispatched to each other (e.g., entry β execute:list_users β execute:list_groups). Complements the Steps tab by showing the logical flow rather than chronological order.
π‘ Debugging Failed Runs
Start with Overview to see which steps failed, then Steps to find the failure point, Logs for error messages, and Connector Calls for API-level details. Use Diffs to verify change logic when entities aren't publishing as expected.
π Cross-Inventory View
Analyzes data across multiple inventory runs with 8 tabs. Each view has date range picker, specific search filters, and charts visualizing trends. All use server-side pagination and query statistics display.
| Tab | Purpose |
|---|---|
| Entity History | Tracks entity changes over time by entity key with hash changes and decisions (added/updated/deleted) |
| Step Performance | Trends showing execution counts, success rates, and duration charts by step name |
| Instance Load | Stacked area chart showing active inventories per DC instance over time |
| Changes | Entity change dispatches filtered by entity type and keys |
| Connector Calls | API call history with duration and status across runs |
| Diffs | Change decisions with explanations and transformed data (the data type internally is "change decisions"; the visible tab label is Diffs, matching the per-run Diffs tab) |
| Diff Publications | Publish events filtered by doc_type_id with success/failure status |
| Next Inventory Input Changes | Cross-run NII writes β same shape as the per-run version, with extra system / stream filters and a date range so you can see how a stream's NII evolved over time |
Entity History Deep Dive
For a given entity key, Entity History shows every inventory run that touched that entity: when it was added, when it was updated (with hash changes), when it was deleted. Enables tracking drift or debugging why an entity disappeared.
Step Performance Deep Dive
Charts show trends over time: execution count per step, success rate (%), average duration. Identify degrading performanceβe.g., a step that used to take 2s now takes 10s as data volume grew.
Instance Load Deep Dive
Stacked area chart: X-axis is time, Y-axis is active inventory count. Each DC instance has a band. Use to verify load balancingβinventories should distribute across instances rather than pile up on one.
Date Range Picker
All tabs support date range selection. Default may be last 24 hours or 7 days. Narrow range for focused investigation; widen for trend analysis.
π Admin Events
Tracks administrative operations across all DC instances. Filter by time range, category, action, instance, system, or user to investigate issues or track changes.
Event Categories Tracked
- Health check results β Automatic scheduled checks and manual testing
- Configuration changes β Full before/after YAML diffs for audit
- Inventory triggers β Who triggered what and when
- System management operations β Enable/disable/cleanup
- DC lifecycle events β Instance start/stop with config snapshots
Filter Preset Tiles
Quick-filter preset tiles for common investigations:
| Preset | Filters Applied |
|---|---|
| DC Starts | category=lifecycle, action=start, past_hours=24 |
| Failed Health Checks | category=health_check, success=false, past_hours=24 |
| Config Changes | category=config_change, past_hours=24 |
| Recent Errors | success=false, past_hours=6 |
| Manual Actions | has_user=true, past_hours=24 |
Details Modal
Clicking the eye icon on any event opens the Details modal β a tabbed view of the full record:
- Overview β primary fields grid (timestamp, category, action, system, success, duration, user, instance, error message)
- Details β additional fields + JSON viewers for nested data
- Changes β side-by-side YAML diff for
config_changeevents (Before panel with red header, After panel with green header); theme-aware styling
URL Sync
Filters sync to URL using history.replaceState(). Page loads with filters from URL if present. Supports: category, action, past_hours, system_name, credential_pointer, success, has_user, instance_id, user_id.
Filter Dropdown Options
Dropdown options are loaded from distinct API calls: getDistinctCategories(), getDistinctActions(category), getDistinctInstances(), getDistinctUsers(), getDistinctSystemNames(), getDistinctCredentialPointers(). Category dropdown uses colored tags with icons. Active filters show blue border highlight. Clear Filters button appears when any non-default filter is set.
Past Hours Options
| Option | Value |
|---|---|
| Last 1 hour | 1 |
| Last 6 hours | 6 |
| Last 24 hours | 24 |
| Last 7 days | 168 |
| Last 30 days | 720 |
βοΈ Configuration Management
Systems
Instance configurations using strategy-specific visual designers. Each strategy has a dedicated designer with tab-based layout:
System and system-type edit pages are tab-organized; the exact tab list depends on whether the strategy is Universal (configured entirely in YAML) or one of the specific strategies (each with its own designer). The four canonical lists below are the source of truth β they reappear in the Quick Reference further down.
Universal System tabs
| Tab | Content |
|---|---|
| General | System-type selector, monitoring, group; designer content (CredentialPointerInput) |
| Connection | Circuit-breaker overrides |
| Variables | VariablesValuesEditor β form generated from the system type's variables_schema |
| Stores | Three-mode inheritance (Inherit / Lightweight Override / Full Replacement) |
| Storage | Override-toggle for StorageConfigEditor |
| Debugging (existing only) | Live test panel (SSE event stream) |
| YAML | Raw editor with edit-source tracking |
Specific-strategy System tabs
| Tab | Content |
|---|---|
| General | System-type selector, monitoring, group; designer content |
| Connection | credential_pointer, base_url / tenant, host / domain |
| Stores | Three-mode inheritance radio |
| Overrides | Instance-specific overrides of system-type defaults |
| Storage | Override-toggle for StorageConfigEditor |
| Debugging (existing only) | Live test panel |
| YAML | Raw editor |
System Types
Template configurations with strategy-specific designers. The Universal System Type designer publishes a long tab set; specific-strategy designers stay narrower.
Universal System Type tabs
- General β strategy selector, monitoring, group; designer content
- Connection β
CircuitBreakerEditor - Settings β
SettingsPanel(connector, schedule, execution, storage, health_check); embeddedStoresEditor; embeddedMonitoringEditorwithlevel=systemType - Variables β
VariablesSchemaEditor(defines what systems must provide) - Connector Calls β
ConnectorCallsTable(named calls with params, produces, next_connector_calls, on_start) - Before Finish β
FinishProducesEditor(purge_unseen, purge_by_relation) - Debugging β live test panel
- Flow β ReactFlow diagram (rendered conditionally when the parsed YAML has
connector_calls) - Used By (existing only) β systems referencing this system type
- YAML β raw editor
Specific-strategy System Type tabs
- General
- Connection
- Stores β
StoresEditorwith EmpowerID / Kafka / File destination toggles - Settings
- Filters (LDAP Delta only) β strategy-specific filter editor inserted between Settings and Storage
- Storage β required
StorageConfigEditor(allowUnset=false) - Debugging (existing only) β page-level tab added by
SystemTypeEditPagefor non-Universal strategies; Universal gets its Debugging tab throughgetUniversalDesignerTabsinstead - Used By (existing only)
- YAML
Strategies & Connectors
| Tab | Content |
|---|---|
| Code | Python source (editable for custom, read-only for builtin) |
| Documentation | Extracted markdown from class docstrings |
| Validation | Loading errors with stack traces |
Custom plugins support 5-second hot-reloadβchanges detected without restarting DC.
Schema Mappings
| Tab | Content |
|---|---|
| Mapping | Target fields with source expressions (Direct, Expression, String Template) |
| Debugging | Test inventories, schema debug drawer for transformed data inspection |
| Used In | Systems that reference this schema |
Credentials
Connector-specific designers:
- LDAP β Bind DN and password fields
- SCIM β OAuth2 client credentials or bearer tokens
- REST β Various auth types (bearer, basic, API key)
JSON tab shows raw structure with metadata:
__connector_nameβ Identifies which connector__descriptionβ Human-readable context
Metadata stripped by DC before passing to connectors. Form and JSON tabs sync bidirectionally.
Create New System Flow
When creating a new system, you first select a system type. The system type determines which strategy runs and therefore which designer appears. Required fields come from the strategy's config schema. Universal strategy systems require variables matching the system type's variables_schema. Specific strategy systems require strategy-specific fields (e.g., base_url, tenant for SAP IAS).
Expression Types in Schema Mappings
The variable in scope inside a schema-mapping field is result β the raw item being transformed for that store. pair is a different variable scoped to the universal-strategy YAML; don't mix them up. Day 28 covers this in detail.
| Type | Syntax | Example |
|---|---|---|
| Direct | Bare field path (no result. prefix) | id, name.givenName, emails.0.value, userName |
| Expression | Python in [[ ]] with result in scope | [[ result.get('email', '').lower() ]] |
| String Template | Jinja {{ }} with result in scope | {{ result['id'] }}-{{ result['tenantId'] }} |
The Debugging tab on a schema page lets you test these expressions against captured connector-call context (see day 28's SchemaDebugDrawer section).
Credential Pointer URI Format
Systems reference credentials via URIs like openbao+kv2://secret/datacollector/system-name. The UI provides a credential picker that lists existing credentials; selecting one fills the URI. Credentials can be tested from the Credentials list page or from system designer Debugging tab.
π Tab-Based Designers Pattern
DC-UI uses a consistent Designer Tab Abstraction where strategy designers publish tabs that appear at the top level alongside General and YAML.
Designer Tab Interface
interface DesignerTab {
key: string;
label: React.ReactNode;
children: React.ReactNode;
}
interface DesignerResult {
content: React.ReactNode; // Content for General tab
additionalTabs: DesignerTab[]; // Extra tabs after General
}
Tab Order
- General β Non-strategy-specific (selector, monitoring, group) + designer content
- ...additionalTabs β Strategy-specific tabs from designer
- YAML β Raw editor (always last)
General Tab Content
The General tab contains minimal shared content: strategy/system-type selector, monitoring overrides, group. Strategy-specific designer content (e.g., connection forms) renders within General.
Specialized Tabs
Strategies provide specialized tabs via additionalTabs. ExampleβUniversal Strategy:
case 'builtin.strategies.universal.UniversalStrategy':
return {
content: <UniversalStrategyDesigner {...props} />,
additionalTabs: getUniversalDesignerTabs({ ...props, yamlContent }),
};
getUniversalDesignerTabs() returns the Universal-strategy-specific tabs that render between General and YAML: Connection, Settings, Variables, Connector Calls, Before Finish, Debugging, and Flow (conditional on parsed YAML having connector_calls). The page (SystemTypeEditPage) wraps these with the always-present General tab, the existing-only Used By tab, and the always-last YAML tab. Designers encapsulate strategy-specific logic (YAML parsing, flow diagrams) in their modules.
Adding Tabs to Custom Designers
To add tabs to any designer:
- Create tab content components (e.g., MyCustomTab.tsx)
- Export
getMyStrategyDesignerTabs(props)returning array of DesignerTab - In edit page switch case:
additionalTabs: getMyStrategyDesignerTabs(designerProps)
export function getMyStrategyDesignerTabs(props: MyDesignerProps): DesignerTab[] {
return [
{ key: 'custom', label: 'Custom Tab', children: <MyCustomTab {...props} /> },
];
}
π‘ Edit Source Tracking
YAML mode preserves formatting during editing. Designer mode immediately serializes changes to YAML. Switching to Designer after YAML edits auto-serializes and may lose comments or unknown properties.
π Universal System Designer
For systems using the universal strategy, the system designer generates form inputs dynamically
from the system type's variables_schema.
Variables Schema
Defines what configuration variables each system must provide:
- Type β string, integer, number, boolean
- Required flag β Systems must provide
- Optional fallback β Default if not specified
- Description β Human-readable help
Common variables: base_url, users_per_page, tenant, connector-specific params.
VariablesValuesEditor
The VariablesValuesEditor component generates form controls based on variable type:
| Type | Form Control |
|---|---|
string |
Text input |
integer |
Number input with precision 0 |
number |
Decimal input |
boolean |
Switch toggle |
Dynamic Form Generation
Renders a table layout with columns: Variable (name, required indicator, description tooltip), Type (colored tag), Value (type-appropriate input), Default (fallback value). DC validates system.config.variables at load time using a Pydantic schema generated from variables_schema.
# variables_schema example
variables_schema:
base_url:
type: string
required: true
description: "API base URL"
users_per_page:
type: integer
fallback: 100
tenant:
type: string
required: true
VariableDefinition Structure
Each variable in variables_schema can have:
typeβ string | integer | number | boolean (required)requiredβ boolean, default falsefallbackβ default value when not specifieddescriptionβ help text shown in UI with InfoCircle icon
VariablesValuesEditor Table Layout
The editor renders a table with columns: Variable (name + required asterisk + description tooltip), Type (colored tag: blue=string, green=integer, orange=number, purple=boolean), Value (type-appropriate input control), Default (fallback value or "-" if none). Empty schema shows "No variables defined in system type" message.
Validation Flow
At config load time, DC's universal strategy builds a Pydantic model from variables_schema using create_model(). System config's variables dict is validated against this model. Missing required variables or wrong types produce validation errors shown in Used In / Validation tabs.
π·οΈ Entity Badges
A unified EntityBadge component system for consistent visual representation of the 6 core entity types across dc-ui.
Entity Type Configuration
| Type | Icon | Color | Label |
|---|---|---|---|
system | CloudServerOutlined | #549fff | System |
systemType | DeploymentUnitOutlined | #b520ff | System Type |
strategy | PlayCircleOutlined | #52c41a | Strategy |
connector | ApiOutlined | #13c2c2 | Connector |
credential | KeyOutlined | #faad14 | Credential |
schema | FunctionOutlined | #eb2f96 | Schema |
Variants
- badge (default) β Light background (25% opacity) + 1px colored border
- tag β Solid colored background + white text (Ant Tag style)
- icon-only β Just the colored icon in a small box
- text β Icon + name, no background/border
Sizes
- small β 11px font, 1px 6px padding
- default β 12px font, 2px 8px padding
- large β 14px font, 4px 10px padding
Convenience Components
<SystemBadge name="prod-sap" />
<SystemTypeBadge name="sapias_specific" />
<StrategyBadge name="SapiasStrategy" />
<ConnectorBadge name="SCIM" />
<CredentialBadge name="sap-cred" />
<SchemaBadge name="account_mapping" />
renderEntityOption Helper
For dropdowns showing mixed entity types: renderEntityOption(type: EntityType, name: string): React.ReactNode renders a styled option with the appropriate badge. Used in Select components when choosing systems, system types, strategies, etc.
Navigation on Click
By default, EntityBadge is clickable and navigates to the edit page for that entity (e.g., /dc-ui/config/systems/prod-sap). Set clickable={false} for read-only display. Custom onClick overrides default navigation.
Short Names for Strategies/Connectors
Fully-qualified names like builtin.strategies.universal.UniversalStrategy are shortened for display (e.g., "UniversalStrategy"). Tooltip shows full name when truncated. EntityBadge handles this automatically.
CSS Overrides
EntityBadge injects CSS to override global card styles that force text color. Uses !important and specific selectors to ensure badge colors display correctly in list pages and dropdowns. Class names (eb-system, eb-systemType, etc.) allow theme customization.
β€οΈ Health Checks
System designers include health check testing that executes checks defined by the strategy. DC resolves credentials, calls the connector with health check params, and displays raw connector responses with timing and any errors.
Automatic Health Checks
- Run on configurable schedule (default 15 minutes)
- Results published to admin events
- Viewable as mini-graphs on Inventories page and Credentials list (24-hour success/failure timeline)
Manual Testing
- Test Health button on system / system-type edit pages β runs every health check the strategy declared for that system
- Test Credential button on credential edit pages β runs only the checks that use this credential pointer
- Test action on the Inventories table per-row menu β same as the system-page Test Health button, but reachable without navigating into the designer
All three open the HealthCheckResultsModal (covered in day 28), with per-result rows and per-row detail. Manual tests use the longer manual_timeout_seconds (vs the scheduler's auto_timeout_seconds) so a thorough validation isn't cut short.
Dual Timeout Configuration
| Config | Purpose |
|---|---|
| auto_timeout_seconds | Capped timeout for scheduled automatic checksβprevents scheduler overrun |
| manual_timeout_seconds | Uncapped timeout for on-demand testing via UIβallows thorough validation |
Mini-Graphs
24-hour timeline per system or credential showing success (green) and failure (red) bars. Displayed on Inventories page and Credentials list.
Health Check Configuration (System Type)
In universal strategy system type designer, Settings tab includes health_check section:
paramsβ Connector-specific parameters (e.g., GET /Users for SCIM, empty search for LDAP)auto_timeout_secondsβ Used by scheduler; keep low (e.g., 10β15) so checks don't blockmanual_timeout_secondsβ Used by UI test button; can be higher (e.g., 30β60) for slow systems
Strategy Health Check Definition
Strategies implement get_health_check_details() returning list of HealthCheckDetails. Each includes connector_name, credential_pointer, params, auto_timeout_seconds, manual_timeout_seconds. A system may have multiple health checks (e.g., one per connector). Testing a credential pointer runs only checks that use that credential.
β οΈ Scheduler Overrun
If auto_timeout_seconds is too high relative to health_check_interval_minutes, checks can overlap. Default interval is 15 minutes; keep auto timeout under ~5 minutes to allow buffer for execution and cleanup.
Health Check Execution Flow
Health checks can be triggered automatically by the scheduler or manually from the UI. The flow differs slightly between automatic and manual modes:
π― Health Check Flow Details
Automatic Mode: Uses auto_timeout_seconds (shorter) to prevent scheduler overrun; results published to admin events for historical tracking
Manual Mode: Uses manual_timeout_seconds (longer) for thorough validation; results displayed immediately in UI
Credential Resolution: Both modes resolve credential_pointer from OpenBao/Vault before calling connector
Mini-Graph Updates: Automatic checks populate the 24-hour health timeline visible on Inventories page
π Used In Tabs
Configuration entities (system types, strategies, schemas, credentials) include Used In tabs showing which systems or other config items reference them.
Where Used In Appears
| Entity | Used In Shows |
|---|---|
| System Types | Which systems reference this type |
| Strategies | Which system types use this strategy |
| Connectors | Which strategies/system types use this connector |
| Schema Mappings | Which systems use this schema |
| Credentials | Which systems reference this credential pointer |
Validation Errors in Systems
System designers show Used In with error_source classification:
- SYSTEM β Errors fixable in this system config
- SYSTEM_TYPE β Errors require fixing referenced system type
- STRATEGY β Errors require fixing referenced strategy
π Debugging Features & Workflows
The Test button in system, system type, and schema mapping designers runs a
DETACHED_READONLY_INVENTORY with unsaved configuration changes, providing comprehensive debugging capabilities.
Complete Debugging Workflow
The following diagram shows the complete developer workflow for testing and debugging configuration changes:
Debug Event Streaming
- Real-time SSE β Events stream as inventory executes; no polling required
- No persistence β DETACHED_READONLY mode doesn't write to production database
- Unsaved changes β Test button uses current form state, not saved config
- use_db_entities toggle β Optionally reference existing entities for relation resolution
9 Debug Tabs
| Tab | Shows | Use For |
|---|---|---|
| Overview | Statistics, timing, success/failure counts | Quick health check of test run |
| Steps | Execution timeline with step names, status, duration | Understanding execution flow and step sequence |
| Connector Calls | API calls with params, responses, status codes, timing | Debugging connector params and API issues |
| Changes | Entity changes (ADD/UPDATE/DELETE) with transformed data | Verifying entity creation and field mappings |
| Logs | Error messages, warnings, debug logs | Finding error details and stack traces |
| Templates | Expression evaluations with input context and output | Debugging Jinja2 expressions and schema mappings |
| Diffs | Publishing results and destination responses | Verifying diff publication (not applicable in DETACHED mode) |
| Input Changes | NII change events captured during the debug session: timestamp, target stream, command, command_id, step name, old / new value with a collapsible diff | Verifying that finish_inventory(next_inventory_input=...) and command writes produce the expected next-run state |
| Diagrams | Mermaid state visualization of execution flow | Visual understanding of step transitions |
Universal Strategy Debug Badges
During streaming, debug badges appear throughout the designer showing evaluation counts at each expression field:
- Green badge β Number of times this expression was evaluated
- Click badge β Opens drawer showing all evaluations with input context and output
- Visual trail β Quickly identify which expressions ran and which didn't
- Zero badge β Expression never evaluated; indicates unreachable code path
Schema Mapping Debugging
Schema edit pages include a Debugging tab with specialized features:
- System selector β Choose any system using this schema mapping
- Run test β Triggers DETACHED_READONLY inventory for that system
- Filtered connector calls β Shows only calls that produced entities for this schema
- Schema debug drawer β Opens when you click a connector call row
- Transformed data grid β Dynamic columns from transformed_data fields
- Cell inspection β Click any cell to see the expression that generated that value
- Expression re-evaluation β Edit expression and re-run with captured context
- Reliability checks β Verifies expression results match between real run and debug re-evaluation
Expression Debug Features
The expression debugging system provides deep inspection capabilities:
- Captured context β Full
ProduceItemContextfrom original evaluation - Serialization safety β Tests if expressions work with JSON-deserialized context (important for API-driven re-evaluation)
- Side-by-side comparison β Original result vs re-evaluated result
- Reliability score β Percentage of expressions that match on re-evaluation
- Iteration over items β For list expressions, shows result for each item in source array
Download Debug Events
After a test run, download all captured events for offline analysis:
| Format | Use Case |
|---|---|
| JSON | Programmatic analysis, reprocessing, sharing with support team |
| YAML | Human-readable inspection, documentation, version control diffs |
π‘ Debugging Best Practices
Start simple: Test with small datasets before full inventory
Use debug badges: Quickly identify which expressions need attention
Check reliability: Verify expressions work with serialized context for API consistency
Download events: Keep records of test runs for comparison across config changes
Schema drawer workflow: Use cell inspection to rapidly iterate on field mappings
π Common User Workflows
This section demonstrates common real-world workflows that combine multiple DC-UI features to accomplish typical administrative and development tasks.
Workflow 1: Triggering Inventory with Different Modes
Production Run (WRITABLE)
- Navigate to Inventories page
- Find target system
- Click Trigger button
- Select mode: New Writable
- Choose inventory_input source:
- From previous run β For delta sync continuation
- Empty β For full sync
- Custom JSON β For specific test scenarios
- Click Start
- Monitor real-time status (updates on the manifest's polling interval β typically every couple of seconds)
- View state diagram for running inventory
- After completion, check entity counts and mini-graph
Resume Interrupted Inventory (EXISTING_READONLY)
- Navigate to Inventories page
- Find system with incomplete inventory
- Click Trigger β Existing Readonly
- Review state to understand where it stopped
- Navigate to Past Inventory Runs for detailed analysis
Test Configuration (DETACHED_READONLY)
- Navigate to system designer
- Make configuration changes (don't save yet)
- Click Test button in Debugging tab
- Toggle use_db_entities if relation resolution needed
- Monitor debug event stream in real-time
- Review 9 debug tabs for issues
- If successful, save changes; if not, iterate
Workflow 2: Testing Configuration Changes Before Production
- Open system designer β Navigate to /dc-ui/config/systems/:name
- Navigate to Settings tab β Modify connector_timeout_ms or schedule
- Switch to Debugging tab β Don't save changes yet
- Click Test button β Runs DETACHED_READONLY with unsaved config
- Monitor Overview tab β Check success/failure statistics
- Review Connector Calls tab β Verify timeout behavior
- Check Changes tab β Confirm entity creation
- Download debug events β Save JSON for comparison
- If successful: Save configuration and trigger production run
- If failed: Review Logs tab, adjust config, test again
Workflow 3: Investigating Failed Inventories
- Identify failure β Inventories page shows status or mini-graph red bars
- Navigate to Past Inventory Runs β /dc-ui/analytics
- Filter by system β Use system filter dropdown
- Click failed run β Opens detailed view with 12 tabs
- Check Overview tab β See failure summary and timing
- Review Logs tab β Find error messages and stack traces
- Examine Steps tab β Identify which step failed
- Inspect Connector Calls tab β Check API responses and status codes
- Diagnose root cause:
- Timeout? Check connector_timeout_ms in Settings
- Auth failure? Check Admin Events β Failed Health Checks, test credential
- API error? Review raw connector response
- Schema mapping issue? Navigate to schema debugging
- Fix and retest β Update config, use Test button before production retry
Workflow 4: Debugging Schema Mapping Issues
- Identify problem β Entities missing fields or wrong values
- Navigate to Schema edit page β /dc-ui/config/schemas/:name
- Open Debugging tab
- Select system using this schema β From dropdown
- Click Run β Starts test inventory
- Wait for connector calls β Grid populates with schema-filtered calls
- Click connector call row β Opens schema debug drawer
- View transformed data grid β Dynamic columns from transformed_data
- Click problematic cell β Loads expression for that field
- Inspect captured context β See input data (raw response, variables, etc.)
- Edit expression β Modify Jinja2 template
- Re-evaluate β Test new expression with captured context
- Check reliability β Verify result matches expected value
- Iterate until correct β Adjust expression as needed
- Apply to schema β Update Mapping tab with corrected expression
- Save and retest β Verify fix with full test run
Workflow 5: Managing Credentials Rotation
- Navigate to Credentials list β /dc-ui/config/credentials
- Find credential to rotate β Search by name or filter
- Check Used In tab β See which systems use this credential
- Note mini-graph β 24-hour health check timeline
- Update credential in OpenBao/Vault β External to DC-UI
- Test credential β Click test button in credential designer
- Review health check result β Verify new credential works
- Check affected systems:
- Navigate to Admin Events β Failed Health Checks preset
- Filter by recent timeframe
- Verify no new failures after rotation
- Trigger test inventories β For critical systems using rotated credential
- Monitor results β Past Inventory Runs for each system
Workflow 6: Monitoring System Health
- Primary view: Inventories page β /dc-ui/systems
- Mini-graphs show 24-hour health timeline per system
- Green bars = successful checks, red bars = failures
- Drill down for failures:
- Navigate to Admin Events β /dc-ui/analytics/admin-events
- Apply preset: Failed Health Checks
- Review error details and timestamps
- Test specific credential:
- Navigate to credential edit page
- Click Test button
- Review raw connector response and timing
- Adjust health check config if needed:
- Navigate to system type designer β Settings tab
- Update health_check section (params, timeouts)
- Test changes before saving
- Monitor trends:
- Past Inventory Runs with date range filters
- Cross-Inventory View for multi-system comparison
Workflow 7: Creating New System from Scratch
- Choose connector and strategy β Review available connectors and strategies
- Create or reuse system type:
- If Universal Strategy: Create system type β Configure connector calls, variables, health check
- If specific strategy: Select existing system type
- Create credential:
- Navigate to Credentials β Add
- Fill credential schema (schema determines required fields)
- Test credential via test button
- Create system:
- Navigate to Systems β Add
- Select system type
- Set credential pointer
- Configure system-specific settings (host, overrides)
- Test in debug mode:
- Open system designer β Debugging tab
- Click Test (DETACHED_READONLY)
- Review all debug tabs for issues
- Iterate on configuration:
- Adjust connector params, schema mappings, variables
- Test again until successful
- Enable and schedule:
- Save configuration
- Enable system on Inventories page
- Set schedule in system type Settings tab
- Trigger first production run (WRITABLE)
- Verify results:
- Check entity counts on Inventories page
- Navigate to Entities Explorer for data inspection
- Review Past Inventory Runs for detailed execution
π‘ Workflow Tips
Always test first: Use DETACHED_READONLY mode before production runs
Download debug events: Keep records for comparison across iterations
Use filters effectively: Narrow results in Past Runs and Admin Events for faster diagnosis
Leverage Used In tabs: Understand config dependencies before making changes
Monitor health mini-graphs: Visual patterns reveal issues faster than logs
Schema debug drawer: Fastest way to iterate on field mappings
π Quick Reference Tables
DC-UI Route Structure
| Route | Purpose |
|---|---|
/dc-ui | Home / Dashboard |
/dc-ui/systems | Inventories page (the breadcrumb label is "Inventories" β the path is /systems for historical reasons) |
/dc-ui/entities-explorer | Entities Explorer (also /dc-ui/entities-explorer/:systemName and /dc-ui/entities-explorer/:systemName/:entityType) |
/dc-ui/analytics | Past Inventory Runs list (Analytics root) |
/dc-ui/analytics/inventory/:inventoryRunId | Past Inventory Run details (12-tab drill-down) |
/dc-ui/analytics/cross-inventory | Cross-Inventory View |
/dc-ui/inventory-diagram/:systemName/:streamName | InventoryDiagramViewer (full-screen Mermaid) |
/dc-ui/onboarding | OnboardingWizard (six-step guided new-system flow) |
/dc-ui/analytics/admin-events | Admin Events |
/dc-ui/config/systems | Systems list |
/dc-ui/config/systems/:name | System edit |
/dc-ui/config/system-types | System Types list |
/dc-ui/config/system-types/:name | System Type edit |
/dc-ui/config/strategies | Strategies list |
/dc-ui/config/connectors | Connectors list |
/dc-ui/config/schemas | Schema Mappings list |
/dc-ui/config/credentials | Credentials list |
Universal Strategy System Type Tabs
| Tab | Key Config |
|---|---|
| General | Strategy selector, monitoring, group |
| Connection | circuit_breaker (threshold, window_seconds, test_timeout) |
| Settings | connector, connector_timeout_ms, schedule, execution, storage, health_check; StoresEditor; MonitoringEditor |
| Variables | variables_schema (name β type, required, fallback, description) |
| Connector Calls | Named calls with params, produces, next_connector_calls, on_start |
| Before Finish | finish.produces (purge_unseen, purge_by_relation) |
| Debugging | Test button, event streaming panel |
| Flow | ReactFlow diagram (rendered when YAML has connector_calls) |
| Used By | Existing only β systems referencing this system type |
| YAML | Raw editor |
Specific Strategy System Type Tabs
| Tab | Purpose |
|---|---|
| General | Strategy selector, monitoring, group |
| Connection | Host, domain, circuit breaker |
| Stores | StoresEditor with EmpowerID / Kafka / File destination toggles |
| Settings | Pagination, timeouts, schema mapping names |
| Filters (LDAP Delta only) | Strategy-specific filter editor inserted between Settings and Storage |
| Storage | disable_changes, enable_entities_transformed_data, enable_changes_transformed_data β required at this level |
| Debugging | Existing only β page-level tab for non-Universal strategies |
| Used By | Existing only |
| YAML | Raw editor |
Universal System Tabs
| Tab | Purpose |
|---|---|
| General | System-type selector, monitoring overrides, group |
| Connection | credential_pointer, circuit-breaker overrides |
| Variables | Form generated from system-type variables_schema |
| Stores | Three-mode inheritance (Inherit / Lightweight Override / Full Replacement) |
| Storage | Override-toggle for storage config |
| Debugging | Existing only β live test panel |
| YAML | Raw editor |
Specific Strategy System Tabs
| Tab | Purpose |
|---|---|
| General | System-type selector, monitoring, group |
| Connection | Host, domain, credentials |
| Stores | Three-mode inheritance radio |
| Overrides | Instance-specific overrides of system type defaults |
| Storage | Override-toggle |
| Debugging | Existing only β test panel |
| YAML | Raw editor |
Admin Event Categories
| Category | Description |
|---|---|
| lifecycle | DC instance start/stop |
| health_check | Automatic or manual health check results |
| config_change | System, system type, schema, credential edits |
| trigger | Inventory trigger (who, when, mode) |
| management | Enable, disable, cleanup, purge |
Past Run Analytics Tab Summary
| Tab | Primary Use |
|---|---|
| Overview | Quick stats, identify failed steps; renders structured_output |
| Steps | Chronological execution, find failure point; per-step structured_output |
| Logs | Error messages, stack traces |
| Changes | Entity modifications, transformed data |
| Diffs | Change decisions, hash comparison |
| Connector Calls | API request/response debugging |
| Diff Publications | Publish success/failure per destination |
| Templates | Expression evaluation context |
| Diagrams | Mermaid state visualization |
| Performance | Gantt chart, bottlenecks |
| Step Dispatch Chain | Logical execution flow |
| Next Inventory Input Changes | Per-stream NII writes with old / new diff and originating step / command |
Trigger Mode Comparison
| Mode | DB persistence | Publishes | NII updated | Scope |
|---|---|---|---|---|
| New Writable | Yes | Yes | Yes | Per stream |
| Existing Readonly | Attach to existing | No | No | Per stream |
| Detached Readonly | No | No | No | Per stream |
| Replay | No | Yes | No | Whole system |
| Readonly Replay | No | No | No | Whole system |
π‘ Canonical references
Full execution-mode semantics, lifecycle, and per-mode behavior live in system-admins/05-execution-modes.md. The DC-UI feature catalog itself lives in system-admins/02-dc-ui.md. Universal-strategy YAML reference is at system-admins/03-universal-strategy-system-type.md.
π Universal Strategy Connector Calls
The Universal strategy defines its collection workflow entirely in YAML. The system-type designer's Connector Calls tab is a UI on top of this YAML. Understanding the schema is essential for configuration. Full reference: system-admins/03-universal-strategy-system-type.md.
connector_calls structure
Named connector call configurations. Each call specifies:
| Field | Required | Description |
|---|---|---|
on_start | No | Marks call to run when inventory starts; optional mode (full/delta/always) and input dict |
params | Yes | Connector-specific parameters; evaluated as template with since, input, system_var |
success_check | No | Boolean expression; if false, step finishes with RETRYABLE_FAILURE |
pre_transform | No | Expression extracting an array from the raw response before schema mapping is applied |
schema_mappings | Yes | Per-store dict mapping each declared store to a schema-mapping name (or null for raw passthrough). Keys must match the system's declared store names. |
produces | No | Array of entity production rules (see below) |
next_connector_calls | No | Follow-up calls for pagination or nested fetching |
β οΈ schema_mappings is a per-store dict, not a single name
The field is plural and is keyed by store name. Each store gets its own mapping (or null for raw passthrough). A connector call producing data for two stores has two entries:
schema_mappings:
eid: scim_user_mapping_for_eid
kafka-feed: scim_user_mapping_for_kafka
produces configuration
Each produces rule specifies its action via a discriminator field whose value is the entity type β not via an action: key. The four discriminator fields:
confirm: <entity_type>β upsert (callsdispatch_entity_confirmed_exact)delete: <entity_type>β soft-delete (callsdispatch_entity_deleted)purge_unseen: <entity_type>β purge entities not confirmed this inventorypurge_by_relation: <entity_type>β unconditional purge scoped to a relation key
(The other four dispatch methods exist on the engine but are not exposed by the universal-strategy YAML β see day 26.)
Plus optional fields:
timingβper_item(default; runs once per transformed item) orper_call(runs once after the call)modeβfull,delta, or omit for "always"key1,relation1_key1,relation2_key1,relation3_key1β entity-key expressionslistβ expression for sub-iteration (one entity per array element, available aschildin expressions)transformed_dataβ override; defaults topair.transformed(the multi-store dict) forper_item
next_connector_calls
callβ call name to dispatch to (the field is literally namedcall;extra="forbid"is set on the Pydantic model so other names will fail validation)timingβper_call(once after current call) orper_item(once per transformed item)whenβ boolean expression; skips dispatch if false (used for pagination "more pages?" check)modeβfull/delta/ omit for alwayslistβ expression for iteration (dispatch one call per array element)inputβ YAML dict of variables passed to the dispatched call
Expression contexts
| Context | Available variables |
|---|---|
params | since, input, system_var |
success_check | since, input, response (a ConnectorCallResult), system_var |
pre_transform | response (raw connector response, not a ConnectorCallResult), since, input, system_var |
produces (per_item) | since, input, pair (a TransformedItem β multi-store), child (current list element if list used), system_var |
produces (per_call) | since, input, response (ConnectorCallResult), system_var |
next_connector_calls | Matches produces based on timing |
Accessing pair.raw vs pair.transformed
pair in per_item contexts is a TransformedItem. Its fields are raw (the original raw item, a flat dict) and transformed (a per-store dict β {store_name: {field_name: value}}). So:
# raw side β flat dict access:
key1: !expr pair.raw['id']
# transformed side β per-store, per-field:
key1: !expr pair.transformed['eid']['SystemIdentifier']
Direct dot-access on pair.transformed.id won't work because transformed is a dict-of-dicts, not a flat object.
Flow Tab
The Flow tab uses ReactFlow to render a diagram of connector-call relationships. Entry step dispatches to on_start calls; arrows show next_connector_calls. Parses YAML from the system-type config; useful for visualizing complex workflows.
Example: SCIM user pagination
connector_calls:
list_users:
on_start: { mode: full }
params:
method: GET
endpoint: "/Users"
query_params:
count: !expr system_var['users_per_page']
startIndex: !expr input.get('startIndex', 0)
schema_mappings:
eid: scim_user_mapping
produces:
- confirm: User
timing: per_item
key1: !expr pair.raw['id']
next_connector_calls:
- call: list_users
timing: per_call
when: !expr response.correlations.raw_connector_response['totalResults'] > input.get('startIndex', 0) + len(response.correlations.raw_connector_response.get('Resources', []))
input:
startIndex: !expr input.get('startIndex', 0) + len(response.correlations.raw_connector_response.get('Resources', []))
success_check: !expr response.status.value == 'success'
This defines pagination: list_users runs on full-sync start; produces User entities; when more pages exist, dispatches to itself with updated startIndex. Note the use of response.correlations.raw_connector_response to access the raw response in per_call contexts.
Example: Delta sync with since
For delta sync, since is available in params (an ISO timestamp). Many SCIM/LDAP APIs support filtering by meta.lastModified. Example: filter: "meta.lastModified gt {{ since.isoformat() }}" in params.
Before Finish (purge_unseen)
The finish.produces block typically includes purge_unseen to remove entities not seen during this sync. Mode filter mode: full skips during delta (delta doesn't list all entities). The internal _purge step checks step statistics first and cancels purge if any prior step ended with EXPECTED_FAILURE or FATAL_FAILURE β never delete entities when collection was incomplete.
π Schema Mapping Expression Reference
Schema mappings transform connector API responses into entity structures. Three expression types available.
Schema mapping expressions evaluate against result β the raw item being transformed. Schema-mapping expressions don't have access to pair; that's a universal-strategy per_item context. The three types are scoped to schema mapping fields.
Direct Field Paths
Bare field paths β dot notation extracts nested fields from the raw item. No result. prefix for Direct (the prefix only applies to Expression and String Template forms):
# Inside a schema mapping field, the Direct form is just the path:
id
displayName
name.givenName
emails.0.value
userName
Expression (Python)
Wrap Python in [[ ]] or use !expr YAML tag. Access result directly:
[[ result.get('email', '').lower() ]]
[[ result['id'] + '-' + result['tenantId'] ]]
[[ len(result.get('groups', [])) ]]
String Template (Jinja)
Use Jinja {{ }} for string concatenation and simple logic:
{{ result.id }}-{{ result.tenantId }}
{{ result.userName | default('unknown') }}
Where each context applies
Inside a schema mapping field expression, the variable is result
β the raw item being transformed for that store. Inside the universal-strategy
per_item contexts (produces, next_connector_calls),
the variable is pair β a TransformedItem with pair.raw
(the same raw item) and pair.transformed['<store_name>'] (the per-store
transformed dict). Don't mix them up: result only works in schema mapping
expressions; pair only works in universal-strategy YAML.
Schema Debug Drawer
When debugging a schema mapping, the debug drawer shows:
- Table of transformed pairs with dynamic columns from transformed_data
- Click a cell to load the field expression in an editor
- Re-evaluate with captured context (reliability check)
- Compare original vs re-evaluated result to verify expression
Connector Call Filtering
Schema debugging runs test inventory and filters connector calls by schema name. Only calls that used this schema appearβreduces noise when multiple schemas are in play.
!yaml Tag
For complex nested structures, use !yaml to embed YAML directly. Enables multi-line values or nested objects without escaping.
Reusable Schemas
Schema mappings are referenced by name. Multiple connector_calls can use the same schema. System types define schema_mapping names; schema files live in config. Used In tab on schema shows all systems/types that reference it.
jinja_guidelines.md
Reference doc for Jinja filters, tests, and built-ins. Covers default, length, join, and common patterns. DC uses Jinja 2.x compatible engine.
π§ Troubleshooting Guide
Inventory Won't Start
- Check system is Enabled (not Disabled)
- Verify no other inventory is running for that stream (writable inventories are one-at-a-time per stream; multi-stream systems can have other streams running independently)
- Check Admin Events for recent config_change or management actions
- Verify credential_pointer resolves (test from Credentials page or system Debugging tab)
Inventory Fails with Connector Error
- Open Past Runs β select failed run β Connector Calls tab
- Expand the failing call to see request params and response
- Check health mini-graphβpattern of failures suggests credential or connectivity issue
- Test system from Debugging tab with same config
- Verify params expressions have correct system_var references
Entities Not Appearing in EmpowerID
- Check Diffs tabβare changes being produced? (add/update decisions)
- Check Diff Publications tabβare publishes succeeding or failing?
- Verify doc_type_ids mapping in diff_destinations.empowerid
- Verify resource_system_id is set at system level
- Check storage configβentity type must not be in disable_changes
Validation Errors with error_source
- SYSTEM β Fix in system config (e.g., missing required variable, invalid credential_pointer)
- SYSTEM_TYPE β Fix in system type (e.g., variables_schema, connector_calls)
- STRATEGY β Fix in strategy or connector Python (rare for config)
Health Check Failures
- Admin Events β Failed Health Checks preset
- Click event for full error message and timing
- Test credential or system manually from UI (uses manual_timeout_seconds)
- Check credential hasn't expired (OAuth tokens) or been rotated in vault
Slow Inventories
- Past Runs β Performance tab (Gantt chart) to find bottleneck steps
- Cross-Inventory β Step Performance for trends
- For universal strategies: consider increasing
execution.max_parallelismin the system-type YAML. For custom strategies: review the throttle-group configuration (see day 26) - Check pagination sizeβtoo small = many API calls; too large = memory/timeout
π― Query Statistics
Analytics tabs show rows read, bytes read, elapsed time. High rows_read with few displayed rows suggests inefficient filteringβconsider adding indexes or narrowing date range.
π‘ Monitoring & Circuit Breaker
Configuration entities include monitoring and circuit_breaker settings. These appear in Connection or General tabs depending on designer.
Monitoring Configuration
Controls which events and fields are excluded from monitoring destinations (Kafka, local files):
- Exclude event types β e.g., template_evaluation to reduce volume
- Exclude fields β Hide sensitive data in events
- Per-destination rules β Different rules for Kafka vs files
- Contextual filters β decision_unchanged for change events, template_use_case_regex for template evaluations
Circuit Breaker
Protects external calls by opening after repeated failures:
- threshold β Number of failures within window to open
- window_seconds β Time window for counting failures
- test_timeout β How long before testing recovery (half-open state)
Only transient errors (429, connectivity, timeouts) trigger. Client errors (400) and server errors (500+) do notβthey indicate request or remote issues.
Override Hierarchy
System type defines defaults; system can override. Monitoring and circuit_breaker follow this pattern. YAML tab shows merged result.
π€ Diff Destinations & Storage
Configurable at system type (defaults) and system (overrides) level. Define where entity changes publish and what gets persisted.
Stores and Destinations
Strategies declare stores (named state slots) via get_destination_config(),
each with lists of routings to one or more destinations. A store can route to zero,
one, or many destinations. The Stores tab in the system designer is the UI for this. Day 26 covers
the underlying model.
| Destination | Routing fields (per StoreConfig) | Notes |
|---|---|---|
| EmpowerID | resource_system_id, doc_type_ids (entity_type β EmpowerID doc type), optional entity_message_formatter |
Always per_entity; last-diff-wins deduplication; batched by doc_type_id; resource_system_id is typically per-system |
| Kafka | output_mode (per_entity or per_attribute), entity_types (subset of store types), topic (or None for DC default), formatters |
Streaming; no deduplication; message keyed by system_name |
| File | output_mode, entity_types, formatters, origin (always OWN in strategy config) |
Local YAML files for debugging; file location is DC-config-level, not per-route |
DC-level overrides
DC's config.yaml can globally modify destination routing β these are operational
toggles, not per-route fields:
disabledβ destination removed from store routingsmirror_to_fileβ destination stays active, File destination added alongsidedivert_to_fileβ destination removed, File destination added insteadmirror_all_stores_to_fileβ File destination added to every store
Output modes
Each Kafka or File route specifies output_mode: per_entity
(one diff per entity with full transformed data) or per_attribute
(one diff per changed attribute, with tombstones for removed attributes). EmpowerID is always
per_entity. Switching output modes is safe at any time β store hashes are unaffected.
The values are lowercase in YAML; the Python OutputMode enum class names are uppercase
but the wire format is what you write.
Stores tab β system-type vs system level
The Stores tab uses the same StoresEditor component at both levels β it's the visible scope, not the editor, that changes:
- System type level β
StoresEditorrenders directly. Each store appears as a card with its entity types and three destination toggles: EmpowerID (configuredoc_type_idsmapping entity_type β EmpowerID doc type, plusresource_system_id), Kafka (configureoutput_mode, optionaltopic, message formatters), and File (configureoutput_mode, formatters). Toggling a destination off removes that routing from the store. - System level β the tab adds a three-mode inheritance radio at the top:
- Inherit β the system uses the system type's stores verbatim. No editor renders.
- Lightweight Override β narrow override applied across all inherited stores: edit only
resource_system_id(for EmpowerID) and Kafkatopic. The full store / destination shape stays inherited; this is the typical per-system override. - Full Replacement β drop into the same
StoresEditoras the system-type tab and replace each store entirely. Use sparingly β it shadows the system type's defaults completely.
Storage tab β Override toggle
The Storage tab follows the same inherit-by-default pattern but with a simpler shape:
- System type level β
StorageConfigEditoris required (allowUnset=false); a system type must declare storage. - System level β an Override toggle appears at the top of the tab; off (default) inherits from the system type, on reveals the same
StorageConfigEditorwithallowUnset=trueso the system can override storage for itself.
The Override-toggle pattern recurs across system-level designer tabs (e.g., monitoring, circuit breaker) β the system type provides defaults, the system overrides individual sections only when needed.
Storage Configuration
- disable_changes β Entity types to skip storing changes for (saves space; no history)
- enable_entities_transformed_data β Entity types to store full data in entities table (needed for Entity Explorer and reference queries)
- enable_changes_transformed_data β Entity types to store full data in changes table (debugging only; significantly increases DB size)
Must list all entity types produced in connector_calls and finish. Missing types cause validation errors.
Storage Best Practices
- Enable entities_transformed_data for entity types you query in Entity Explorer
- Enable changes_transformed_data only temporarily for debuggingβdisable after
- Use disable_changes for high-volume entity types where you only need current state
β DC-UI Best Practices
Configuration
- Use system types for shared defaults; override only instance-specific values in systems
- Define variables_schema in system type before creating systemsβenables validation
- Use Used In tabs before deleting configβensure nothing references it
- Test with Detached Readonly before deploying config changes to production
Operational
- Monitor health mini-graphs regularlyβaddress patterns of failure early
- Use Admin Events preset tiles for common investigations
- Bookmark shareable URLs for frequent Entity Explorer views
- Export Past Run data when escalating to supportβpreserves context
Debugging
- Start with Overview tab, drill to specific tabs based on symptom
- Use schema debug drawer for expression issuesβre-evaluate with real data
- Download debug events for offline analysis or test fixture creation
- Leverage debug badges in universal designer during streaming to trace evaluation
π Glossary
| Term | Definition |
|---|---|
| Connector | Python plugin implementing protocol (SCIM, LDAP, REST). Handles API communication. |
| Strategy | Python plugin defining collection logic. Determines steps, connector calls, entity production. |
| System | Instance configuration. References system type, credentials, instance-specific values. |
| System Type | Template defining shared defaults. Strategy, connector, schema mappings, schedule. |
| Schema Mapping | YAML rules mapping connector response β entity fields. Reusable across strategies. |
| Stream | Named partition within a system. One inventory at a time per stream; multi-stream systems run streams concurrently. Has its own NII, lease, scheduling. |
| Inventory | One execution of data collection for a stream. Resumable, stateful. |
| inventory_input | JSON passed to inventory at start. Snapshotted from the stream's NII when the inventory begins; concurrent NII edits don't affect the running inventory. |
| next_inventory_input (NII) | Per-stream JSON state passed to the stream's next inventory. Set via finish_inventory or commands; used for delta tokens, circuit-breaker state. |
| Replay | Re-publish stored entity data through normal diff pipeline. Per-store profile. Recovers consumer drift. System-wide (acquires all stream leases). |
| Command | User-invocable operation that modifies a stream's NII via CAS without starting an inventory. Declared by strategy. |
| TransformedItem | Multi-store transformed item: raw (raw connector item) + transformed (per-store dict-of-dicts). Available as pair in universal-strategy per_item contexts. |
| TransformedPair | Per-schema (single-store) transform output: raw + transformed (single dict). Used internally by SchemaMapper; the universal strategy's pair is TransformedItem, not this. |
| connector_call | Named config for one API interaction. params, schema_mappings, produces, next_connector_calls. |
| DETACHED_READONLY | Trigger mode. In-memory test, no DB persistence. For debugging config. |
| WRITEABLE_INVENTORY | Trigger mode (note "WRITEABLE" with E). Production. Persists all changes to database. |
| credential_pointer | URI to vault secret (e.g., openbao+kv2://secret/datacollector/name). Auth only. |
| variables_schema | Defines variables systems must provide. Type, required, fallback. For universal strategy. |
| EntityBadge | Unified component for displaying system, systemType, strategy, connector, credential, schema with icons. |
| HealthCheckDetails | Strategy return. Defines health check params, timeouts. One per connector/credential. |
| edit source tracking | UI tracks whether last edit was Designer or YAML. Affects serialization behavior. |
| DesignerTab | Interface for strategy tabs. key, label, children. Spread between General and YAML. |
| ErrorBoundary | React component catching errors, showing fallback. Used throughout dc-ui. |
π Step Outcomes Reference
Steps finish with one of six outcomes. Visible in the Steps tab and Overview statistics. The central rule: only SUCCESS and EXPECTED_FAILURE persist a step's changes and dispatched-steps. Day 26 covers persistence rules and the dispatch_step_on_fatal_failure exception in detail.
| Outcome | Meaning | Changes persist? |
|---|---|---|
| SUCCESS | Step completed without error | Yes |
| EXPECTED_FAILURE | Strategy-anticipated failure (e.g., resource not found when that's a valid state). Not retried. | Yes |
| FATAL_FAILURE | Permanent error requiring intervention. The inventory continues β only this step's changes are discarded. | No (except dispatch_step_on_fatal_failure) |
| RETRYABLE_FAILURE | Transient error. DC retries up to max_retries; final retry promotes to FATAL_FAILURE. | No |
| SUCCESS_REDUCED | Step was merged via unique-key dedup; another step in the group executed. | No |
| DISCARDED | Eagerly-dispatched (immediate=True) step whose parent didn't commit. Monitoring-only β never persisted to the database. | No |
The internal _purge step (in universal strategy) checks for EXPECTED_FAILURE or FATAL_FAILURE in prior steps. If any, purge is cancelled (entities not deleted) and the step finishes with EXPECTED_FAILURE β never delete entities when collection was incomplete.
π DataTable & Common Components
DC-UI uses consistent patterns for tables and lists across pages.
DataTable Features
- Column visibility β Show/hide columns via chooser; persisted in localStorage by table key
- Sorting β Server-side where applicable (Entities, Analytics); client-side for small datasets
- Pagination β Page size options (10, 20, 50, 100); total count when available
- Loading state β Spin indicator during fetch
- Empty state β Custom message when no data
DetailsModal
Reusable modal for viewing full record. Tabs: Overview, Details, Changes (for config diff). Theme-aware. Width 1200px for config diffs.
CredentialPointerInput
Input with credential picker. Lists existing credentials from vault. Selecting one fills URI. Supports create flow.
ErrorBoundary
Wraps routes and sections. Catches React errors, shows fallback with retry. Prevents white screen on component failure.
π€οΈ Common DC-UI Workflows (Quick Reference)
Adding a New System (Universal Strategy)
Two paths get you here. The OnboardingWizard at /dc-ui/onboarding walks first-time users through the full sequence (System Type β Connection β Entity Mapping β Content Packs β First Inventory β First Scan); the manual flow below builds the same artifacts tab-by-tab. Either way produces an identical system.
- Config β System Types β select/create system type with universal strategy, configure variables_schema, connector_calls, finish
- Config β Systems β Create β select the system type
- Connection tab: set credential_pointer (create credential in Config β Credentials first)
- Variables tab: fill values for each variable in variables_schema
- Stores tab: choose Inherit (use the system type's stores) or Lightweight Override (set
resource_system_idfor EmpowerID, or Kafkatopic) or Full Replacement - Storage tab: leave the Override toggle off to inherit storage from the system type, or flip it on to set per-system
disable_changes/enable_entities_transformed_data/enable_changes_transformed_data - Debugging tab: Test to verify config works
- Save. System appears on Inventories page.
Investigating a Failed Run
- Inventories or Past Runs β find failed system/run
- Click run β Overview tab: note which steps failed
- Steps tab: find failure point, note step name and outcome
- Logs tab: filter ERROR, read error message
- Connector Calls tab: expand failing call, inspect request/response
- If credential: Admin Events β Failed Health Checks, test credential
- Fix config, test with Detached Readonly before re-running
Debugging Schema Mapping
- Config β Schemas β select schema
- Debugging tab: select a system that uses this schema
- Run test; events stream in panel
- Connector Calls tab: filter by schema name
- Open schema debug drawer: see transformed data grid
- Click cell with wrong value β loads expression β edit β re-evaluate
- Compare original vs re-evaluated to verify fix
Tracking Config Change
- Admin Events β Config Changes preset (or filter category=config_change)
- Find event for system/type/schema you care about
- Click eye icon β Details modal β Changes tab
- Side-by-side Before/After YAML shows exact diff
- URL params preserved for sharing
Exporting Entity Data
- Entities Explorer β select system and entity type
- Apply filters if needed (date, keys, field values)
- Sort by desired column
- Export button β CSV or JSON
- Copy URL to share filtered view
Rotating Credentials
- Update credential in vault (OpenBao/Vault)
- Config β Credentials β locate credential (or systems using it)
- Test credential from list page or system Debugging tab
- No system config change neededβ
credential_pointerstays the same. DC resolves the pointer on every connector call, so the rotation takes effect on the next connector call, not the next inventory. - Next inventory run uses new credentials
β° Schedule & Execution Configuration
Universal-strategy YAML, not DC-wide
The fields below are universal-strategy system-type YAML fields, not DC-engine-wide settings. Custom Python strategies decide their own scheduling via get_next_trigger_at() and parallelism via throttle groups (get_step_execution_config() + get_throttle_group_config()). Day 26 covers the engine-side scheduling and throttle-group model.
Schedule (universal-strategy schedule block)
| Field | Purpose |
|---|---|
| interval_minutes | Time between automatic triggers. Default often 60. |
| full_sync_hours | Threshold. If time since last full_completed_at exceeds this, the next run is a full sync instead of delta. |
| delta_lookback_seconds | Safety buffer when calculating since timestamp for delta filters. Prevents edge-case misses. |
Execution (universal-strategy execution.max_parallelism)
The universal strategy exposes max_parallelism β concurrent steps allowed across one inventory (default 4). The engine internally translates this into a single throttle group with that limit. Custom strategies don't use this field β they declare per-group max_parallelism via get_throttle_group_config(), which is more flexible (different groups for different external resources). See day 26's Throttle Groups section.
Full vs Delta Sync
Entry step uses schedule to decide: if elapsed time since last full sync > full_sync_hours β full sync. Otherwise delta. Full sync runs all on_start calls with mode: full or no mode. Delta runs mode: delta or no mode. Strategies use the mode filter in produces and next_connector_calls to skip steps during delta.
π§© More UI Patterns & Pages
A collection of cross-cutting UI surfaces and patterns that recur across DC-UI. They're brief on purpose β full mechanics live in system-admins/02-dc-ui.md.
Replay UI workflow
Replay is reached as one of the four mode cards in the Trigger Type modal. Picking it opens a modal with a Profile Select (loaded from getReplayProfiles β labels formatted name (store_name)), a profile description block, a Mode Switch (Readonly = monitoring only, Writable = publishes), and an optional Since ISO datetime that controls how far back to re-publish. OK is disabled until a profile is selected. See system-admins/04-replay.md for profile shape and the engine-side semantics.
Commands UI
Strategies declare commands via get_commands() (returning a list of CommandDefinition). Commands modify a stream's next_inventory_input via CAS without starting an inventory, and can run during active inventories. They surface in two places in DC-UI:
- The Trigger Type modal's Commands card (when the strategy publishes commands applicable to the current scope) β sliding panel of clickable command cards
- The Edit Next Inventory Input modal β applicable commands appear as command cards below the JSON textarea
A command card carries the command's name, description, and the stream(s) it applies to (a CommandDefinition.stream_name match against the active scope). Clicking a card calls executeCommand immediately.
Trigger profiles
Strategies expose preset trigger inputs via get_trigger_profiles(stream_name, β¦). The trigger modal renders these as Quick Trigger Profile tiles when the stream's trigger_profiles is non-empty; clicking a tile pre-populates the Custom JSON textarea, so an operator can launch a known-good run without crafting JSON from scratch.
Output modes per destination
Each Kafka or File store routing carries its own output_mode:
per_entityβ one diff per entity with full transformed dataper_attributeβ one diff per changed attribute, with tombstones for removed attributes
EmpowerID is always per_entity. Output mode drives whether the Diffs and Diff Publications tabs render entity-shaped or attribute-shaped diffs. Switching is safe at any time β store hashes are unaffected. (Values are lowercase in YAML.)
structured_output rendering
Strategies can attach arbitrary JSON to inventory and step finishes via finish_inventory(structured_output={...}) and finish_step(structured_output={...}). The Past Run Details and Debug panels render this data through a JsonViewer on the Overview tab (inventory-level) and within Step Finish events (step-level). Use it to surface strategy-computed metrics, summaries, or links the UI shouldn't have to compute itself.
OnboardingWizard
Reachable at /dc-ui/onboarding; gated by dc-ui:config manage. A six-step guided flow for first-time system creation: System Type β Connection β Entity Mapping β Content Packs β First Inventory β First Scan. The wizard composes the same designers and modals used elsewhere in DC-UI, so a system created here is identical to one built tab-by-tab.
InventoryDiagramViewer
Reachable from any running stream's View Diagram link; URL /dc-ui/inventory-diagram/:systemName/:streamName. A full-screen page (no top nav, no sidebar) that renders a live Mermaid diagram of the running inventory's state, refreshed on the manifest's polling interval. Supports mouse-drag pan and scroll-wheel zoom (clamped to [0.1, 5]); re-renders only when the diagram source string actually changes, so identical updates don't flicker. Error states: "No diagram available for this inventory" (404), "DataCollector is offline" (timeout), "Failed to render diagram - invalid syntax" (Mermaid render failure).
Immediate-editing pattern
DC-UI's drawers and modals (e.g., ConnectorCallDrawer, ProduceEditModal, NextCallEditModal) have no internal Save button. Every change flows to the parent state on each keystroke; the drawer's Close button just dismisses the UI. Saving happens once, at the page level, when the user hits Save in the page header.
The documented exception is ExpressionEditorDrawer: it saves on close because it validates locally and supports a sandbox mode (read-only contexts where the parent state shouldn't be mutated until the user explicitly applies their changes).
Edit-source tracking for YAML / JSON editors
Designer pages track which surface produced the latest edit:
- Designer edits immediately serialize to YAML β the YAML tab updates in real time
- YAML edits are kept verbatim β whitespace and comment changes register in
hasChanges, so save remains enabled even for cosmetic edits - Parse errors in the YAML tab set the Designer tab read-only with an inline warning until the YAML is valid again
Switching Designer β YAML keeps designer state intact. Switching YAML β Designer parses the YAML and may lose comments or unknown properties.
"+ New X" button pattern
Every config listing page (Systems, System Types, Schemas, Credentials, Connectors, Strategies) has a Create button in the breadcrumb. Clicking it navigates to the entity's edit page with ?create=true; the same designer renders, but in create mode (Save becomes Create; Delete is hidden until a record exists).
"Used By" tabs
Visible on system type, schema, credential, connector, and strategy edit pages. Each lists the systems referencing the entity, with badge-styled rows. The tab carries a count badge β secondary color when zero (safe to delete), accent color when non-zero (delete will break callers). Use this before any Delete action.
π Plugin Hot-Reload
Custom strategies and connectors support 5-second hot-reload. DC watches plugin files; changes detected automatically. No restart required. Builtin plugins (builtin.strategies.*, builtin.connectors.*) are read-only. Custom plugins in config/strategies or config/connectors are editable. Validation tab shows loading errors. Used In tab shows references before delete.
ποΈ DC-UI Key Components & Structure
Pages
| Component | Path | Purpose |
|---|---|---|
| HomePage | src/components/Home/ | Dashboard with navigation tiles, stats |
| InventoriesPage | src/components/Inventories/ | Systems list, trigger, status, health mini-graphs |
| EntitiesExplorer | src/components/Entities/ | Entity browsing with filters, export |
| PastRunsAnalytics | src/components/Analytics/ | Past runs list, 12-tab drill-down |
| CrossInventoryView | src/components/Analytics/ | 8-tab cross-run analysis |
| AdminEvents | src/components/Analytics/ | Admin events with preset tiles, filters, URL sync |
| SystemEditPage | src/components/Config/ | System edit with strategy-specific designer |
| SystemTypeEditPage | src/components/Config/ | System type edit with designer tabs |
| SchemaEditPage | src/components/Config/ | Schema mapping with Mapping, Debugging, Used In |
| CredentialEditPage | src/components/Config/ | Credential with connector-specific form, JSON tab |
Designers
- UniversalStrategyDesigner β System type: General content + getUniversalDesignerTabs()
- UniversalSystemDesigner β System: CredentialPointerInput + VariablesValuesEditor
- FieldglassDesigner, IdmReferenceDataVdsDesigner, LdapDeltaDesigner, SapiasSpecificDesigner, SapldapvdsSystemDesigner β the five non-Universal specific-strategy designers
- ConnectorCallsDebugPanel β Shared debug panel for event streaming
Common Components
- EntityBadge β src/components/common/EntityBadge.tsx. ENTITY_CONFIGS, variants, sizes.
- DetailsModal β Tabbed modal (Overview, Details, Changes). Diff view for config.
- DataTable β Pagination, column chooser, sorting. localStorage persistence.
- HealthCheckMiniGraph β 24-hour success/failure bars.
- CredentialPointerInput β URI input with credential picker.
- VariablesValuesEditor β Form from variables_schema. designers/system/universal/.
Routes (routes.ts)
Centralized ROUTES constants: HOME, INVENTORIES, ENTITIES, ANALYTICS_RUNS, ANALYTICS_CROSS, ANALYTICS_ADMIN_EVENTS, CONFIG_SYSTEMS, CONFIG_SYSTEM, CONFIG_SYSTEM_TYPES, CONFIG_SYSTEM_TYPE, CONFIG_STRATEGIES, CONFIG_CONNECTORS, CONFIG_SCHEMAS, CONFIG_CREDENTIALS. buildRoute() for parameterized routes. navigateTo() utility.
β Frequently Asked Questions
Why can't I edit a system type?
Ensure you have an appropriate dc-ui role: app_user (view), app_admin (view + manage non-strategy resources), or platform_admin (full access including strategy management). In PDP mode, your PermissionGrant determines access; in scope mode, your token's datacollector:read / datacollector:write / datacollector:debug scopes do. Day 26 covers the auth model.
Why don't I see entity types in Entities Explorer?
Entity types only appear for systems that have run at least once and produced entities. Check storage configβentity types must be in enable_entities_transformed_data (or not in disable_changes) to be queryable. Run an inventory first.
Detached Readonly vs Existing Readonly?
Detached: in-memory, no DB, optional use_db_entities. For testing config changes. Existing: resumes from DB, read-only. For inspecting interrupted runs.
What is edit source tracking?
UI tracks whether last change came from Designer form or YAML editor. Designer mode serializes immediately. YAML mode preserves formatting. Switching DesignerβYAML keeps designer state. Switching YAMLβDesigner parses YAML and may lose comments.
How do I add a new tab to a custom strategy designer?
Create DesignerTab objects (key, label, children). Export getMyStrategyDesignerTabs(props). In edit page switch, add additionalTabs: getMyStrategyDesignerTabs(props). Tabs render between General and YAML.
Why is health check failing?
Check credential validity (test manually). Verify params in health_check match connector expectations. Increase manual_timeout_seconds if system is slow. Review Admin Events for error message.
When to use Designer vs YAML tab?
Designer: guided forms, validation, most changes. YAML: preserve comments, bulk edits, advanced config, copy-paste from examples. Never mixβchoose one mode per edit session.
How does Used In help before delete?
Used In shows systems/system types that reference the item. Deleting a schema used by 5 systems will break them. Fix or remove references first. Same for credentials, system types, strategies.
β¨ Summary
DC-UI provides a complete, professional interface for DataCollector: real-time inventory monitoring with health mini-graphs, comprehensive entities explorer with server-side filtering and export, 12-tab past run analytics, 8-tab cross-inventory view, admin events with preset tiles and URL sync, strategy-specific designers for systems and system types, connector-specific credential designers, schema mapping with debugging drawer, unified entity badges, dual-timeout health checks, Used In tabs for dependency awareness, and the Designer Tab Abstraction pattern. Use this guide as your technical reference for all DC-UI capabilities.