CI HUBCI HUB SDK
Getting Started

SDK Workbench

The local UI that calls your handlers the same way the CI HUB client does.

The SDK Workbench is the local stand-in for the CI HUB client. npm run dev serves it at http://localhost:8080 (see CLI).

The workbench talks to your integration over the same HTTP surface the client uses. Every control in it runs one of your handlers, with the same inputs the client would send.

What the workbench tests

  • Your handlers, not mocks. Nothing between the workbench and your code is faked. If a flow works here, it works in the client.
  • Your response shape. Every response is validated against the schema for that handler. Failures appear in the diagnostics panel, pointing at the field.
  • What the client does with your response. A valid response that hides a button or fetches an unexpected URL shows up as an insight, not just a pass.

How a click reaches your code

Take the Navigation module. Type a folder id, press Load, and your getFolder handler runs. Everything on screen arrives in that handler's request data: the folder id, the selected filters, the data locale. The second argument carries the session, which is the access token and the adapterData your login handler returned. Both are sent on every call after login.

Two consequences:

  • Auth must succeed before anything else works.
  • A mistake in what login returns often surfaces later, when a handler reads an adapterData field that was never set. See adapterData.

If a control runs a handler you did not export, the server replies that the method is not implemented and the workbench shows that message.

Where to start

Work down the sidebar in order. Each module depends on the ones above it.

Details. Reads your metadata and registers your handler list.

Auth. Everything else needs the session it produces.

Info, if you implement it. Search and Navigation build their filter bars from what it returns.

Search or Navigation, whichever your platform leads with.

Everything else, in any order.


Details

Runs: no handler. The server reads every non-function property of your defineIntegration call and returns it, plus the list of handler names you exported.

Tests: that your metadata is well formed and that the handlers you think you exported are exported.

The Registered Handlers badges are the literal list of functions the server found on your integration object. A handler missing here is missing everywhere, and every feature depending on it is disabled in every other module.

The capability badges are what you declared in capabilities. The handler list and the capabilities together decide what the rest of the workbench lets you do, so read this view before concluding that something else is broken.

Press Refresh Details in the sidebar after changing your integration. Adding a handler or a capability does not change the gating until this runs again.

See Integration Info and Capabilities Reference.


Auth

Runs: login, then checkToken, refreshToken and logout.

Tests: the whole OAuth round trip, as the client performs it.

Login calls your login handler and expects a redirect to your provider in return. The workbench opens that URL in a popup. When your provider redirects back, login runs a second time with the authorization code and is expected to return the token payload. The workbench stores it and immediately calls checkToken with it.

One Login press therefore exercises both halves of your login handler plus the token check. If the popup closes on an error page, your second call returned no access token.

The remaining buttons appear once you are logged in:

ControlEffect
Check TokenCalls checkToken with the current access token
Refresh TokenCalls refreshToken and replaces the stored session with what you return
LogoutCalls logout
View Token JSONShows what the workbench is holding. Use it to confirm adapterData contains what your later handlers read

capabilities.supportsNewLoginUrl changes which login address the workbench uses, but both forms reach the same login handler. See Login Flow and Auth Handlers.


Info

Runs: info.

Tests: the per-user configuration your integration returns after authentication. The handler is optional, but much of the workbench is built from it: pre-search filters, data locales, search configs, the option inputs on the upload and update forms, and the request headers used to fetch thumbnails.

Search and Navigation call info themselves when they need filters, so what is listed here is exactly what those modules offer. If a filter bar is missing from Search, this view tells you whether info returned it.

See Info Handler and Filters.


Runs: search.

Tests: everything the client's search bar does.

  • Typing a query and pressing Search calls search with that text.
  • Selecting a filter re-runs search with the selected filter ids, so you can check that your handler applies them and that the filters you return mark the right options as active.
  • Load more re-runs search with the more cursor you returned, which verifies your pagination.
  • Parent ID appears when you declare capabilities.assetSearch.supportsParentId, and scopes the search to a folder.
  • Similarity Search appears when you declare capabilities.assetSearch.similarSearch. It hands search a base64 image alongside the query, the only case where that handler receives a file.

The two accordions at the bottom call createAsset and updateAsset. Search results are not a folder, so the upload accordion asks for a target parent id. The client offers upload from search results only when you declare capabilities.supportsAddAssetInSearch, the same flag that gates the entry in the grid's background menu.

Results render as a grid. Right-clicking an asset gives the actions the client offers, covered in The grid and its context menus.

See Search and canAddAsset in Search.


Runs: getFolder, plus most of your mutating handlers.

Tests: folder browsing and the permission model around it. This is the widest module in the workbench.

Load calls getFolder with the folder id, starting at root. Double-clicking a folder in the grid calls it again for that folder, which is how you walk your tree.

This module is where capabilities get tested, in two layers. What you return in a folder's capabilities decides what the client offers inside it, and the workbench enforces the same rules: return canAddAsset: false and the upload form is refused, with the reason shown. Mismatches between what you intended and what you returned surface here.

The accordions below the folder input call one handler each, so you can exercise a handler without hunting for the right tile:

AccordionYour handler
Create FoldercreateFolder
Create Asset (Upload)createAsset
Update AssetupdateAsset
Rename FolderrenameFolder
Delete FolderdeleteFolder
Delete AssetdeleteAsset
Rename AssetrenameAsset
Lock / Unlock AssetlockAsset
Downloaddownload

Download resolves the URL through your download handler and shows it without fetching the file, so you can check the URL before trusting it.

See Folder Navigation, Per-Folder Capabilities, Folder Operations, Upload, Download and Asset Operations.


Versions

Runs: getAssetVersions.

Tests: the version history of one asset. Enter an asset id and press Load. The With master checkbox is passed to your handler, so you can exercise both paths through it.

The grid renders each version with the size, modified date and version label you returned, laid out the way the client lays them out. Use it to check that your version ordering and labelling read correctly to a user.

See getAssetVersions.


Brand

Runs: getBrandConfig, then getBrandAssets.

Tests: the Brand Hub surface, which needs capabilities.supportsBrandHub declared plus both handlers exported.

Load Brand Config calls getBrandConfig. Double-clicking a category in the grid calls getBrandAssets with that category's folderId and categoryType, the values you returned in the config. That makes it a real test of the two handlers agreeing with each other. Load more pages through a category using the more cursor you returned.

See Brand Hub.


Tasks

Runs: searchTasks, getTask, getTaskAssets, addTaskComment, addAssetToTask, addTaskAsset, updateTaskState, updateCustomTaskState, deleteTaskAsset.

Tests: task workflows, which need capabilities.tasking declared.

Searching calls searchTasks. Clicking a result calls getTask. Everything in the task detail panel maps to one handler:

ControlYour handler
Get AssetsgetTaskAssets
Add CommentaddTaskComment
Add Asset (id only)addAssetToTask
Add Task Asset (full form)addTaskAsset
A badge under "Transition to state"updateTaskState
Update Custom Task StateupdateCustomTaskState
Remove (Delete Task Asset)deleteTaskAsset

The state badges come from the availableStates you returned on the task, so clicking one tests that your task response and your state handler agree. After a transition or an asset change the workbench re-reads the task, which shows whether the change took effect on your side.

See Tasks.


Reparent

Runs: moveAsset or moveFolder, depending on the type toggle.

Tests: moving something to a new parent, including moving to root. The same form opens from the grid's Move entry with the source already filled in.


The grid and its context menus

Search, Navigation, Versions and Brand render their results as a grid of tiles. Right-clicking a tile gives the actions the client would offer for it, and each one opens the same form the accordions use, pre-filled and locked to that item. The menu runs the same handlers listed above. What it adds is the gating.

Every entry is checked twice: once against your handler list and capabilities, and once against the capability flags on the item you clicked. An entry you cannot use stays visible and explains itself on hover. That message is the useful part, because it tells you why the client would not offer the action to a user.

Folders are the exception worth understanding. A folder listed inside another folder usually arrives with nothing but an id and a name, so the workbench does not know what it permits and will not guess. Load actions in its menu calls your getFolder for that one folder to find out. If the actions stay disabled afterwards, your getFolder did not return capabilities for it.

Preview Details runs no handler. It shows one asset or folder the way the client displays it after transforming your response: dates rewritten, capabilities resolved through their fallback chain, and the classification that decides which host actions appear. Use it to check whether a field you returned survives the client's transforms.

See Asset Object and Asset Types.


When something is disabled

There are three reasons, and the diagnostics panel names which one applies.

The handler is not exported. Diagnostics says Missing handler(s): <name>. Add the function to your defineIntegration call and press Refresh Details.

The capability is not declared. Diagnostics says Capability not met: <expression>, showing the exact flag it tested. Several features need both a handler and a flag: Brand needs supportsBrandHub, Tasks needs tasking, similarity search needs assetSearch.similarSearch, upload from search results needs supportsAddAssetInSearch. Add the flag to capabilities and press Refresh Details. See Capabilities Reference.

The item said no. The handler exists and the capability is declared, but the folder or asset you are acting on returned a flag that forbids it, such as canAddAsset: false or canDeleteAsset: false. Nothing is wrong with your configuration. This is your own response talking, and the fix is in whatever your handler computed for that item.

On any module other than Details and Auth, the panel may simply be telling you to run Details or log in first.


What the workbench cannot tell you

Worth knowing before you treat a green result as final:

  • Direct Access Helper behavior is close, but not identical. Your helper runs in a real browser here, but not the browser environment it gets in production. MD5 is the clearest example: the workbench cannot produce one and passes your helper an empty string, so a helper that depends on it passes here and fails for users. See Limitations and Download Hashes.
  • The CORS check is unauthenticated. A provider that allows the preflight but blocks credentialed requests still passes here and fails in production.
  • Batch operations are not exercised. batchOperations.canDelete and canLock change how the client calls deleteAsset and lockAsset. The workbench acts on one item at a time.
  • Host-specific behavior is out of scope. How your assets place into InDesign, Photoshop or Office is not something a browser can test.

For the hosted end of the process, see Partner Journey.


Handler lookup

Every handler the workbench can call, and where to trigger it. A handler you export that is not listed here is never reached by any control.

HandlerWhere in the workbench
addAssetToTaskTasks, Add Asset
addTaskAssetTasks, Add Task Asset
addTaskCommentTasks, Add Comment
checkTokenAuth, Check Token, and automatically after login
createAssetNavigation and Search accordions, folder and listing context menus
createFolderNavigation accordion, folder and listing context menus
deleteAssetNavigation accordion, asset context menu
deleteFolderNavigation accordion, folder context menu
deleteTaskAssetTasks, Delete Task Asset
downloadNavigation accordion, asset context menu
getAssetVersionsVersions, Load; asset context menu, View Versions
getBrandAssetsBrand, opening a category and Load more
getBrandConfigBrand, Load Brand Config
getFolderNavigation Load and folder drill-down; folder menu, Load actions
getTaskTasks, clicking a result
getTaskAssetsTasks, Get Assets
infoInfo, Load Provider Info; and on demand from Search and Navigation
lockAssetNavigation accordion, asset context menu
loginAuth, Login. Runs twice: the redirect, then the callback
logoutAuth, Logout
moveAssetReparent with type Asset; asset context menu, Move
moveFolderReparent with type Folder; folder context menu, Move
refreshTokenAuth, Refresh Token
renameAssetNavigation accordion, asset context menu
renameFolderNavigation accordion, folder context menu
searchSearch, and every filter change and Load more
searchTasksTasks, Search and Load more
updateAssetNavigation and Search accordions, asset context menu
updateCustomTaskStateTasks, Update Custom Task State
updateTaskStateTasks, clicking a state badge

Next steps

On this page