Skip to main content

Naming schema

Two parallel identifier layers: one for UI elements, one for API operations. They are deliberately different formats so that an identifier is self-describing about which layer it belongs to.

UI layer​

coral.<area>.<surface>.<component>[.<state>]

Lowercase, dot-separated, hyphens inside a segment. The state suffix is optional.

Areas​

AreaCovers
shellApplication chrome, navigation, global controls
toolbarCommand bars
buildThe agent build canvas
panelThe right rail and its sections
dialogModals, flyouts, confirmation surfaces
previewThe preview conversation pane
evaluateTest sets and evaluation runs
monitorAnalytics, formerly Monitor

States​

The state segment is drawn from a closed set, which is what makes parsing unambiguous. A trailing segment that is not a known state is treated as part of the component, so coral.panel.build.knowledge-add.disabled parses with a state and coral.panel.build.knowledge.add.button does not.

Examples​

coral.toolbar.build.save-button
coral.panel.build.knowledge-add.disabled
coral.dialog.knowledge.public-website.url-input
coral.evaluate.testset.import-button

API layer​

{namespace}:{surface}:{group}:{operation}

Colon-separated, four segments, all required.

Namespaces​

NamespaceMeaning
csCopilot Studio platform
asLocal kit
acCards
ltTiles
evidenceAudit-side evidence records
dlAudit-side data-lineage records

Surfaces​

SurfaceBacking service
cs:dvDataverse
cs:bmBot Management and the Island Gateway
cs:envEnvironment
cs:bapBusiness Application Platform
cs:runtimeConversation runtime
cs:graphMicrosoft Graph

Examples​

cs:dv:bots:create
cs:bm:channels:msteams-status
cs:runtime:conversation:send
cs:env:tenant:get

This format was adopted from the authoritative Copilot Studio corpus rather than invented for this audit, so identifiers here line up with the published model instead of forming a parallel vocabulary.

Parsing​

Both layers round-trip through @raybot/object-model.

import { parseCoralId, formatCoralId, parseApiId, formatApiId } from '@raybot/object-model';

formatCoralId(parseCoralId('coral.panel.build.knowledge-add.disabled'));
// 'coral.panel.build.knowledge-add.disabled'

formatApiId(parseApiId('cs:dv:bots:create'));
// 'cs:dv:bots:create'

Both throw SemanticIdError on malformed input. Use tryParseCoralId and tryParseApiId for non-throwing variants.

Test ids are not identifiers​

A data-testid is not a semantic identifier and must not be used as one. 76 of the 177 unique test ids in this audit appear on more than one surface. A test id alone is not a sufficient selector across the application — it must be qualified by surface.

This is why the semantic id includes the surface segment in both layers. It is also why the runbook records the surface alongside every data-testid it cites.

normalizeTestId() in the object model lowercases and trims, because the audit data itself is inconsistent in casing: label-gaps.json keys are lowercase while testids.json preserves the source casing.