@datasynx/agentic-ai-cartography 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1558,6 +1558,8 @@ interface QueryBackend {
1558
1558
  nodes(ctx: TenantContext, q: NodeQuery, sessionId?: string): NodesResult;
1559
1559
  /** One node by id (or `undefined` if absent). Throws {@link NotFoundError} if no session resolves. */
1560
1560
  node(ctx: TenantContext, id: string, sessionId?: string): NodeRow | undefined;
1561
+ /** All edges of the resolved session (for full-topology consumers, e.g. the Backstage catalog). Throws {@link NotFoundError} if no session resolves. */
1562
+ edges(ctx: TenantContext, sessionId?: string): EdgeRow[];
1561
1563
  /** Dependency traversal from a node. Throws {@link NotFoundError} if no session resolves. */
1562
1564
  dependencies(ctx: TenantContext, id: string, q: DependencyQuery, sessionId?: string): TraversalResult;
1563
1565
  /** Compare two sessions (both must belong to the tenant). Throws {@link NotFoundError} on an unknown/foreign id. */
@@ -1585,6 +1587,7 @@ declare class SqliteQueryBackend implements QueryBackend {
1585
1587
  summary(ctx: TenantContext, sessionId?: string): GraphSummary;
1586
1588
  nodes(ctx: TenantContext, q: NodeQuery, sessionId?: string): NodesResult;
1587
1589
  node(ctx: TenantContext, id: string, sessionId?: string): NodeRow | undefined;
1590
+ edges(ctx: TenantContext, sessionId?: string): EdgeRow[];
1588
1591
  dependencies(ctx: TenantContext, id: string, q: DependencyQuery, sessionId?: string): TraversalResult;
1589
1592
  diff(ctx: TenantContext, base: string, current: string): TopologyDiff;
1590
1593
  sessions(ctx: TenantContext): SessionRow[];
@@ -3970,6 +3973,42 @@ declare function sanitizeUntrusted(text: string): string;
3970
3973
  /** Recursively apply `sanitizeUntrusted` to every string in an arbitrary value. */
3971
3974
  declare function sanitizeValue(value: unknown): unknown;
3972
3975
 
3976
+ /**
3977
+ * Backstage catalog entity mapping (4.6).
3978
+ *
3979
+ * A dependency-free, transport-agnostic mapper: `toBackstageEntities` turns the
3980
+ * discovered topology into plain typed Backstage entity objects, and `entitiesToYaml`
3981
+ * serializes them to the multi-doc `catalog-info.yaml` format. It NEVER imports
3982
+ * `@backstage/*` — Backstage stays an optional adapter, never a core dependency
3983
+ * (ROADMAP locked constraints). The legacy `exportBackstageYAML` is re-expressed over
3984
+ * this mapper and stays byte-identical (snapshot-guarded). The same typed entities are
3985
+ * served live over the API (`GET /v1/backstage/catalog`) so a Backstage instance can
3986
+ * consume the topology as a continuously-refreshed data source.
3987
+ */
3988
+
3989
+ interface BackstageEntity {
3990
+ apiVersion: 'backstage.io/v1alpha1';
3991
+ kind: 'Component' | 'API' | 'Resource';
3992
+ metadata: {
3993
+ name: string;
3994
+ annotations: Record<string, string>;
3995
+ };
3996
+ spec: {
3997
+ type: string;
3998
+ lifecycle: string;
3999
+ owner: string;
4000
+ dependsOn?: string[];
4001
+ };
4002
+ }
4003
+ interface BackstageMapOptions {
4004
+ /** Default owner when a node carries none (the org/tenant). */
4005
+ org?: string;
4006
+ }
4007
+ /** Map discovered nodes/edges to typed Backstage catalog entities. Pure, deterministic. */
4008
+ declare function toBackstageEntities(nodes: NodeRow[], edges: EdgeRow[], opts?: BackstageMapOptions): BackstageEntity[];
4009
+ /** Serialize entities to the multi-doc `catalog-info.yaml` string (byte-identical to the legacy exporter). */
4010
+ declare function entitiesToYaml(entities: BackstageEntity[]): string;
4011
+
3973
4012
  /**
3974
4013
  * Hex Grid Engine — flat-top axial coordinate system.
3975
4014
  * Reference: https://www.redblobgames.com/grids/hexagons/
@@ -4089,4 +4128,4 @@ declare function logInfo(message: string, context?: Record<string, unknown>): vo
4089
4128
  declare function logWarn(message: string, context?: Record<string, unknown>): void;
4090
4129
  declare function logError(message: string, context?: Record<string, unknown>): void;
4091
4130
 
4092
- export { ACTIONS, ANOMALY_KINDS, ANOMALY_SEVERITIES, type Action, ActionSchema, type AgentProvider, type AgentRunContext, type AgentTool, type Anomaly, type AnomalyConfig, type AnomalyKind, type AnomalySeverity, type AnomalyThresholds, type AnonViolation, type AnonymizationLevel, type ApiServerOptions, type AskUserFn, type AuthConfig, AuthConfigSchema, AuthorizationError, type BindGuardOptions, CLIENTS, CONFIDENCE, COST_PERIODS, type CartographyConfig, CartographyDB, type CartographyMapData, type CentralDbConfig, CentralDbConfigSchema, type ClassifiedItem, type ClassifyInput, type ClassifyResult, type ClientSpec, type Cluster, ClusterSchema, type ComplianceInput, type ComplianceReport, ComplianceReportSchema, type ComplianceRule, ComplianceRuleSchema, type Condition, ConditionSchema, ConfigError, type ConfigFile, ConfigFileSchema, type ConfigFormat, type Connection, ConnectionSchema, type Contributor, type ControlResult, ControlResultSchema, type CostEntry, CostEntrySchema, type CostPeriod, type CostRecord, type CostSource, type CreateMcpServerOptions, type CredentialConfig, CredentialConfigSchema, type CredentialDb, type CredentialRecord, type CredentialStore, type CronFields, CsvCostSource, type CsvCostSourceOptions, DEFAULT_ANOMALY_THRESHOLDS, DEFAULT_FAST_MODEL, DEFAULT_LEAD_MODEL, DEFAULT_SERVER_NAME, DEFAULT_TENANT, DOMAIN_COLORS, DOMAIN_PALETTE, DRIFT_FIELDS, type DataAsset, DataAssetSchema, type DependencyQuery, type DiscoveryEdge, type DiscoveryEvent, type DiscoveryFn, type DiscoveryNode, type DriftAlert, type DriftAlertItem, type DriftConfig, DriftConfigSchema, type DriftField, type DriftItemKind, type DriftRunRow, type DriftSink, type DriftSinkConfig, EDGE_RELATIONSHIPS, type EdgeRelationship, type EdgeRow, EdgeSchema, type EmbeddingProvider, type EnrichResult, type EntryOptions, type EstablishedConn, type EvidenceKind, type FetchLike, type FragmentKind, type GraphSummary, type HealthResult, type HttpOptions, INGEST_SCHEMA_VERSION, type IngestEnvelope, IngestEnvelopeSchema, type IngestHandler, type IngestOptions, type IngestResponse, type IngestResult, type InstallPlan, InvalidTenantError, type JiraIssue, type JiraOptions, JiraSink, type JiraSinkOptions, LOOPBACK_HOSTS, type LocalDiscoveryOptions, type LocalDiscoveryResult, type LogEntry, type LogLevel, MCP_BIN, type MatchStrategy, NODE_TYPES, NODE_TYPE_GROUPS, type NlIntent, type NlQueryOptions, type NlQueryResult, type NlRelation, type NodeAttribution, type NodeChange, type NodeIdentity, type NodeQuery, type NodeRow, NodeSchema, type NodeType, type NodesResult, NotFoundError, OUTPUT_FORMATS, type OrgKeyOptions, type OrgSummary, type OsKind, type OutputFormat, PACKAGE_NAME, PAGERDUTY_ENQUEUE_URL, PENDING_STATUSES, PERSONAL, PORT_MAP, PRIVATE_IP, PUSH_SCHEMA_VERSION, type PagerDutyEvent, PagerDutySink, type PagerDutySinkOptions, type ParsedApiArgs, type PendingShareRow, type PendingStatus, type PlanOptions, type PolicyResult, type PostJsonOptions, type Principal, PrincipalSchema, type ProviderFactory, type ProviderName, ProviderRegistry, type PushItem, type PushOptions, type PushResult, type QueryBackend, RELATION_TO_DIRECTION, ROLES, type ResolveContext, type ResolveOptions, type Role, RoleSchema, type RuleCheck, RuleCheckSchema, type RuleScope, type Ruleset, RulesetSchema, type RunDriftOptions, SCAN_ARG_PATTERNS, SDL, SECURITY_METADATA_KEYS, SEVERITIES, SEVERITY_WEIGHT, SHARING_LEVELS, type ScanArgKind, type ScanContext, type ScanHintParams, type ScanResult, type Scanner, type ScannerPlugin, type ScannerPluginApi, ScannerRegistry, ScannerShape, type ScheduleConfig, ScheduleConfigSchema, type ScheduledRunResult, type Scope, type SearchFn, type SemanticSearchOptions, type ServerEntry, type SessionRow, type Severity, type SharePreview, type SharePreviewEntry, type SharingLevel, SharingLevelSchema, type SharingPolicy, type ShellKind, type SlackMessage, SlackSink, SqliteCredentialStore, SqliteQueryBackend, SqliteStoreBackend, type StartApiOptions, StdoutSink, type StoreBackend, type SyncClassifyOptions, type SyncClassifyResult, TENANT_HEADER, type TenantContext, TenantMismatchError, type TenantOptions, type ToolResult, type TopologyDelta, type TopologyDiff, type TopologyInput, type TraversalResult, VectorStore, WebhookSink, type WebhookSinkOptions, applyInstall, applySharingLevel, assertReadOnly, assertSafeBind, assertSafeScanArg, assertSameTenant, assignColors, authorize, bearerToken, bookmarksScanner, buildCartographyToolHandlers, buildMapData, buildOpenApiDocument, buildReport, buildSinks, can, centralDbFromEnv, checkBearer, checkPrerequisites, checkReadOnly, clampText, classify, classifyDrift, cleanupTempFiles, cloudAwsScanner, cloudAzureScanner, cloudGcpScanner, codeAddMcpCommand, computeCentroid, computeClusterBounds, computeIdentity, connectionsScanner, contentHash, createBashTool, createCartographyTools, createClaudeProvider, createDefaultRegistry, createHashEmbedder, createIngestHandler, createLocalEmbedder, createMcpServer, createOllamaProvider, createOpenAIProvider, createScanRunner, createSemanticSearch, createSqliteQueryBackend, currentOs, cursorDeeplink, databasesScanner, deepMerge, defaultAllowedHosts, defaultConfig, defaultContext, defaultProviderRegistry, defaultRegistry, defaultServerEntry, definePlugin, deriveSessionName, detectAnomalies, detectOrphans, detectShadowIt, diffTopology, edgesToConnections, enrichCosts, evaluateCheck, evaluateRule, evidenceLine, executeGraphql, executeNlQuery, exportAll, exportBackstageYAML, exportComplianceReport, exportCostCSV, exportCostSummary, exportDiscoveryApp, exportJGF, exportJSON, extractListeningPorts, filterBySeverity, findAnonViolations, formatComplianceText, formatJira, formatPagerDuty, formatSlack, generateDependencyMermaid, generateDiffMermaid, generateTopologyMermaid, getClient, getRuleset, globalId, groupByDomain, handleGraphqlGet, hashToken, hexCorners, hexDistance, hexNeighbors, hexRing, hexSpiral, hexToPixel, hmacKey, hostname, ingestEnvelope, installedAppsScanner, isLoopbackHost, isPersonalHost, isReadOnlyCommand, isRemembered, isSecureWebhookUrl, k8sScanner, keyMetaOf, layoutClusters, listClients, listRulesets, loadConfig, loadOrgKey, loadPlugins, loadRuleset, localDiscoveryFn, log, logDebug, logError, logInfo, logWarn, machineId, maxSeverity, mcpServerObject, newAnomalies, nextRun, nodesToAssets, normalizeId, normalizeTenant, orgKeyPath, osUser, parseApiArgs, parseComposeDeps, parseConfig, parseConnectionString, parseCostCsv, parseCron, parseEstablished, parseNginxUpstreams, parseNlQuery, parseScanHint, pixelToHex, planInstall, portsScanner, postJson, previewShare, pseudonymize, pseudonymizeFragment, pseudonymizeString, pushDeltas, readConfigFile, redactConnectionString, redactSecrets, redactValue, renderDiff, resolveEffectiveLevel, resolveNlQuery, resolvePrincipal, resolveSharingLevel, resolveTenant, revalidateAnonymized, reversalKey, reversePseudonym, rotateOrgKey, runApi, runDiscovery, runDrift, runHttp, runLocalDiscovery, runOnce, runStdio, runSyncClassify, safeEnv, safeJson, safetyHook, sanitizeUntrusted, sanitizeValue, scopeReads, scoreTopology, securityRelevantChange, serializeConfig, serviceConfigScanner, setVerbose, shadeVariant, shapeToJsonSchema, shareHash, splitSegments, stableStringify, startApi, stripSensitive, timingSafeEqual, validateScanner, vscodeDeeplink, zodToJsonSchema };
4131
+ export { ACTIONS, ANOMALY_KINDS, ANOMALY_SEVERITIES, type Action, ActionSchema, type AgentProvider, type AgentRunContext, type AgentTool, type Anomaly, type AnomalyConfig, type AnomalyKind, type AnomalySeverity, type AnomalyThresholds, type AnonViolation, type AnonymizationLevel, type ApiServerOptions, type AskUserFn, type AuthConfig, AuthConfigSchema, AuthorizationError, type BackstageEntity, type BackstageMapOptions, type BindGuardOptions, CLIENTS, CONFIDENCE, COST_PERIODS, type CartographyConfig, CartographyDB, type CartographyMapData, type CentralDbConfig, CentralDbConfigSchema, type ClassifiedItem, type ClassifyInput, type ClassifyResult, type ClientSpec, type Cluster, ClusterSchema, type ComplianceInput, type ComplianceReport, ComplianceReportSchema, type ComplianceRule, ComplianceRuleSchema, type Condition, ConditionSchema, ConfigError, type ConfigFile, ConfigFileSchema, type ConfigFormat, type Connection, ConnectionSchema, type Contributor, type ControlResult, ControlResultSchema, type CostEntry, CostEntrySchema, type CostPeriod, type CostRecord, type CostSource, type CreateMcpServerOptions, type CredentialConfig, CredentialConfigSchema, type CredentialDb, type CredentialRecord, type CredentialStore, type CronFields, CsvCostSource, type CsvCostSourceOptions, DEFAULT_ANOMALY_THRESHOLDS, DEFAULT_FAST_MODEL, DEFAULT_LEAD_MODEL, DEFAULT_SERVER_NAME, DEFAULT_TENANT, DOMAIN_COLORS, DOMAIN_PALETTE, DRIFT_FIELDS, type DataAsset, DataAssetSchema, type DependencyQuery, type DiscoveryEdge, type DiscoveryEvent, type DiscoveryFn, type DiscoveryNode, type DriftAlert, type DriftAlertItem, type DriftConfig, DriftConfigSchema, type DriftField, type DriftItemKind, type DriftRunRow, type DriftSink, type DriftSinkConfig, EDGE_RELATIONSHIPS, type EdgeRelationship, type EdgeRow, EdgeSchema, type EmbeddingProvider, type EnrichResult, type EntryOptions, type EstablishedConn, type EvidenceKind, type FetchLike, type FragmentKind, type GraphSummary, type HealthResult, type HttpOptions, INGEST_SCHEMA_VERSION, type IngestEnvelope, IngestEnvelopeSchema, type IngestHandler, type IngestOptions, type IngestResponse, type IngestResult, type InstallPlan, InvalidTenantError, type JiraIssue, type JiraOptions, JiraSink, type JiraSinkOptions, LOOPBACK_HOSTS, type LocalDiscoveryOptions, type LocalDiscoveryResult, type LogEntry, type LogLevel, MCP_BIN, type MatchStrategy, NODE_TYPES, NODE_TYPE_GROUPS, type NlIntent, type NlQueryOptions, type NlQueryResult, type NlRelation, type NodeAttribution, type NodeChange, type NodeIdentity, type NodeQuery, type NodeRow, NodeSchema, type NodeType, type NodesResult, NotFoundError, OUTPUT_FORMATS, type OrgKeyOptions, type OrgSummary, type OsKind, type OutputFormat, PACKAGE_NAME, PAGERDUTY_ENQUEUE_URL, PENDING_STATUSES, PERSONAL, PORT_MAP, PRIVATE_IP, PUSH_SCHEMA_VERSION, type PagerDutyEvent, PagerDutySink, type PagerDutySinkOptions, type ParsedApiArgs, type PendingShareRow, type PendingStatus, type PlanOptions, type PolicyResult, type PostJsonOptions, type Principal, PrincipalSchema, type ProviderFactory, type ProviderName, ProviderRegistry, type PushItem, type PushOptions, type PushResult, type QueryBackend, RELATION_TO_DIRECTION, ROLES, type ResolveContext, type ResolveOptions, type Role, RoleSchema, type RuleCheck, RuleCheckSchema, type RuleScope, type Ruleset, RulesetSchema, type RunDriftOptions, SCAN_ARG_PATTERNS, SDL, SECURITY_METADATA_KEYS, SEVERITIES, SEVERITY_WEIGHT, SHARING_LEVELS, type ScanArgKind, type ScanContext, type ScanHintParams, type ScanResult, type Scanner, type ScannerPlugin, type ScannerPluginApi, ScannerRegistry, ScannerShape, type ScheduleConfig, ScheduleConfigSchema, type ScheduledRunResult, type Scope, type SearchFn, type SemanticSearchOptions, type ServerEntry, type SessionRow, type Severity, type SharePreview, type SharePreviewEntry, type SharingLevel, SharingLevelSchema, type SharingPolicy, type ShellKind, type SlackMessage, SlackSink, SqliteCredentialStore, SqliteQueryBackend, SqliteStoreBackend, type StartApiOptions, StdoutSink, type StoreBackend, type SyncClassifyOptions, type SyncClassifyResult, TENANT_HEADER, type TenantContext, TenantMismatchError, type TenantOptions, type ToolResult, type TopologyDelta, type TopologyDiff, type TopologyInput, type TraversalResult, VectorStore, WebhookSink, type WebhookSinkOptions, applyInstall, applySharingLevel, assertReadOnly, assertSafeBind, assertSafeScanArg, assertSameTenant, assignColors, authorize, bearerToken, bookmarksScanner, buildCartographyToolHandlers, buildMapData, buildOpenApiDocument, buildReport, buildSinks, can, centralDbFromEnv, checkBearer, checkPrerequisites, checkReadOnly, clampText, classify, classifyDrift, cleanupTempFiles, cloudAwsScanner, cloudAzureScanner, cloudGcpScanner, codeAddMcpCommand, computeCentroid, computeClusterBounds, computeIdentity, connectionsScanner, contentHash, createBashTool, createCartographyTools, createClaudeProvider, createDefaultRegistry, createHashEmbedder, createIngestHandler, createLocalEmbedder, createMcpServer, createOllamaProvider, createOpenAIProvider, createScanRunner, createSemanticSearch, createSqliteQueryBackend, currentOs, cursorDeeplink, databasesScanner, deepMerge, defaultAllowedHosts, defaultConfig, defaultContext, defaultProviderRegistry, defaultRegistry, defaultServerEntry, definePlugin, deriveSessionName, detectAnomalies, detectOrphans, detectShadowIt, diffTopology, edgesToConnections, enrichCosts, entitiesToYaml, evaluateCheck, evaluateRule, evidenceLine, executeGraphql, executeNlQuery, exportAll, exportBackstageYAML, exportComplianceReport, exportCostCSV, exportCostSummary, exportDiscoveryApp, exportJGF, exportJSON, extractListeningPorts, filterBySeverity, findAnonViolations, formatComplianceText, formatJira, formatPagerDuty, formatSlack, generateDependencyMermaid, generateDiffMermaid, generateTopologyMermaid, getClient, getRuleset, globalId, groupByDomain, handleGraphqlGet, hashToken, hexCorners, hexDistance, hexNeighbors, hexRing, hexSpiral, hexToPixel, hmacKey, hostname, ingestEnvelope, installedAppsScanner, isLoopbackHost, isPersonalHost, isReadOnlyCommand, isRemembered, isSecureWebhookUrl, k8sScanner, keyMetaOf, layoutClusters, listClients, listRulesets, loadConfig, loadOrgKey, loadPlugins, loadRuleset, localDiscoveryFn, log, logDebug, logError, logInfo, logWarn, machineId, maxSeverity, mcpServerObject, newAnomalies, nextRun, nodesToAssets, normalizeId, normalizeTenant, orgKeyPath, osUser, parseApiArgs, parseComposeDeps, parseConfig, parseConnectionString, parseCostCsv, parseCron, parseEstablished, parseNginxUpstreams, parseNlQuery, parseScanHint, pixelToHex, planInstall, portsScanner, postJson, previewShare, pseudonymize, pseudonymizeFragment, pseudonymizeString, pushDeltas, readConfigFile, redactConnectionString, redactSecrets, redactValue, renderDiff, resolveEffectiveLevel, resolveNlQuery, resolvePrincipal, resolveSharingLevel, resolveTenant, revalidateAnonymized, reversalKey, reversePseudonym, rotateOrgKey, runApi, runDiscovery, runDrift, runHttp, runLocalDiscovery, runOnce, runStdio, runSyncClassify, safeEnv, safeJson, safetyHook, sanitizeUntrusted, sanitizeValue, scopeReads, scoreTopology, securityRelevantChange, serializeConfig, serviceConfigScanner, setVerbose, shadeVariant, shapeToJsonSchema, shareHash, splitSegments, stableStringify, startApi, stripSensitive, timingSafeEqual, toBackstageEntities, validateScanner, vscodeDeeplink, zodToJsonSchema };
package/dist/index.d.ts CHANGED
@@ -1558,6 +1558,8 @@ interface QueryBackend {
1558
1558
  nodes(ctx: TenantContext, q: NodeQuery, sessionId?: string): NodesResult;
1559
1559
  /** One node by id (or `undefined` if absent). Throws {@link NotFoundError} if no session resolves. */
1560
1560
  node(ctx: TenantContext, id: string, sessionId?: string): NodeRow | undefined;
1561
+ /** All edges of the resolved session (for full-topology consumers, e.g. the Backstage catalog). Throws {@link NotFoundError} if no session resolves. */
1562
+ edges(ctx: TenantContext, sessionId?: string): EdgeRow[];
1561
1563
  /** Dependency traversal from a node. Throws {@link NotFoundError} if no session resolves. */
1562
1564
  dependencies(ctx: TenantContext, id: string, q: DependencyQuery, sessionId?: string): TraversalResult;
1563
1565
  /** Compare two sessions (both must belong to the tenant). Throws {@link NotFoundError} on an unknown/foreign id. */
@@ -1585,6 +1587,7 @@ declare class SqliteQueryBackend implements QueryBackend {
1585
1587
  summary(ctx: TenantContext, sessionId?: string): GraphSummary;
1586
1588
  nodes(ctx: TenantContext, q: NodeQuery, sessionId?: string): NodesResult;
1587
1589
  node(ctx: TenantContext, id: string, sessionId?: string): NodeRow | undefined;
1590
+ edges(ctx: TenantContext, sessionId?: string): EdgeRow[];
1588
1591
  dependencies(ctx: TenantContext, id: string, q: DependencyQuery, sessionId?: string): TraversalResult;
1589
1592
  diff(ctx: TenantContext, base: string, current: string): TopologyDiff;
1590
1593
  sessions(ctx: TenantContext): SessionRow[];
@@ -3970,6 +3973,42 @@ declare function sanitizeUntrusted(text: string): string;
3970
3973
  /** Recursively apply `sanitizeUntrusted` to every string in an arbitrary value. */
3971
3974
  declare function sanitizeValue(value: unknown): unknown;
3972
3975
 
3976
+ /**
3977
+ * Backstage catalog entity mapping (4.6).
3978
+ *
3979
+ * A dependency-free, transport-agnostic mapper: `toBackstageEntities` turns the
3980
+ * discovered topology into plain typed Backstage entity objects, and `entitiesToYaml`
3981
+ * serializes them to the multi-doc `catalog-info.yaml` format. It NEVER imports
3982
+ * `@backstage/*` — Backstage stays an optional adapter, never a core dependency
3983
+ * (ROADMAP locked constraints). The legacy `exportBackstageYAML` is re-expressed over
3984
+ * this mapper and stays byte-identical (snapshot-guarded). The same typed entities are
3985
+ * served live over the API (`GET /v1/backstage/catalog`) so a Backstage instance can
3986
+ * consume the topology as a continuously-refreshed data source.
3987
+ */
3988
+
3989
+ interface BackstageEntity {
3990
+ apiVersion: 'backstage.io/v1alpha1';
3991
+ kind: 'Component' | 'API' | 'Resource';
3992
+ metadata: {
3993
+ name: string;
3994
+ annotations: Record<string, string>;
3995
+ };
3996
+ spec: {
3997
+ type: string;
3998
+ lifecycle: string;
3999
+ owner: string;
4000
+ dependsOn?: string[];
4001
+ };
4002
+ }
4003
+ interface BackstageMapOptions {
4004
+ /** Default owner when a node carries none (the org/tenant). */
4005
+ org?: string;
4006
+ }
4007
+ /** Map discovered nodes/edges to typed Backstage catalog entities. Pure, deterministic. */
4008
+ declare function toBackstageEntities(nodes: NodeRow[], edges: EdgeRow[], opts?: BackstageMapOptions): BackstageEntity[];
4009
+ /** Serialize entities to the multi-doc `catalog-info.yaml` string (byte-identical to the legacy exporter). */
4010
+ declare function entitiesToYaml(entities: BackstageEntity[]): string;
4011
+
3973
4012
  /**
3974
4013
  * Hex Grid Engine — flat-top axial coordinate system.
3975
4014
  * Reference: https://www.redblobgames.com/grids/hexagons/
@@ -4089,4 +4128,4 @@ declare function logInfo(message: string, context?: Record<string, unknown>): vo
4089
4128
  declare function logWarn(message: string, context?: Record<string, unknown>): void;
4090
4129
  declare function logError(message: string, context?: Record<string, unknown>): void;
4091
4130
 
4092
- export { ACTIONS, ANOMALY_KINDS, ANOMALY_SEVERITIES, type Action, ActionSchema, type AgentProvider, type AgentRunContext, type AgentTool, type Anomaly, type AnomalyConfig, type AnomalyKind, type AnomalySeverity, type AnomalyThresholds, type AnonViolation, type AnonymizationLevel, type ApiServerOptions, type AskUserFn, type AuthConfig, AuthConfigSchema, AuthorizationError, type BindGuardOptions, CLIENTS, CONFIDENCE, COST_PERIODS, type CartographyConfig, CartographyDB, type CartographyMapData, type CentralDbConfig, CentralDbConfigSchema, type ClassifiedItem, type ClassifyInput, type ClassifyResult, type ClientSpec, type Cluster, ClusterSchema, type ComplianceInput, type ComplianceReport, ComplianceReportSchema, type ComplianceRule, ComplianceRuleSchema, type Condition, ConditionSchema, ConfigError, type ConfigFile, ConfigFileSchema, type ConfigFormat, type Connection, ConnectionSchema, type Contributor, type ControlResult, ControlResultSchema, type CostEntry, CostEntrySchema, type CostPeriod, type CostRecord, type CostSource, type CreateMcpServerOptions, type CredentialConfig, CredentialConfigSchema, type CredentialDb, type CredentialRecord, type CredentialStore, type CronFields, CsvCostSource, type CsvCostSourceOptions, DEFAULT_ANOMALY_THRESHOLDS, DEFAULT_FAST_MODEL, DEFAULT_LEAD_MODEL, DEFAULT_SERVER_NAME, DEFAULT_TENANT, DOMAIN_COLORS, DOMAIN_PALETTE, DRIFT_FIELDS, type DataAsset, DataAssetSchema, type DependencyQuery, type DiscoveryEdge, type DiscoveryEvent, type DiscoveryFn, type DiscoveryNode, type DriftAlert, type DriftAlertItem, type DriftConfig, DriftConfigSchema, type DriftField, type DriftItemKind, type DriftRunRow, type DriftSink, type DriftSinkConfig, EDGE_RELATIONSHIPS, type EdgeRelationship, type EdgeRow, EdgeSchema, type EmbeddingProvider, type EnrichResult, type EntryOptions, type EstablishedConn, type EvidenceKind, type FetchLike, type FragmentKind, type GraphSummary, type HealthResult, type HttpOptions, INGEST_SCHEMA_VERSION, type IngestEnvelope, IngestEnvelopeSchema, type IngestHandler, type IngestOptions, type IngestResponse, type IngestResult, type InstallPlan, InvalidTenantError, type JiraIssue, type JiraOptions, JiraSink, type JiraSinkOptions, LOOPBACK_HOSTS, type LocalDiscoveryOptions, type LocalDiscoveryResult, type LogEntry, type LogLevel, MCP_BIN, type MatchStrategy, NODE_TYPES, NODE_TYPE_GROUPS, type NlIntent, type NlQueryOptions, type NlQueryResult, type NlRelation, type NodeAttribution, type NodeChange, type NodeIdentity, type NodeQuery, type NodeRow, NodeSchema, type NodeType, type NodesResult, NotFoundError, OUTPUT_FORMATS, type OrgKeyOptions, type OrgSummary, type OsKind, type OutputFormat, PACKAGE_NAME, PAGERDUTY_ENQUEUE_URL, PENDING_STATUSES, PERSONAL, PORT_MAP, PRIVATE_IP, PUSH_SCHEMA_VERSION, type PagerDutyEvent, PagerDutySink, type PagerDutySinkOptions, type ParsedApiArgs, type PendingShareRow, type PendingStatus, type PlanOptions, type PolicyResult, type PostJsonOptions, type Principal, PrincipalSchema, type ProviderFactory, type ProviderName, ProviderRegistry, type PushItem, type PushOptions, type PushResult, type QueryBackend, RELATION_TO_DIRECTION, ROLES, type ResolveContext, type ResolveOptions, type Role, RoleSchema, type RuleCheck, RuleCheckSchema, type RuleScope, type Ruleset, RulesetSchema, type RunDriftOptions, SCAN_ARG_PATTERNS, SDL, SECURITY_METADATA_KEYS, SEVERITIES, SEVERITY_WEIGHT, SHARING_LEVELS, type ScanArgKind, type ScanContext, type ScanHintParams, type ScanResult, type Scanner, type ScannerPlugin, type ScannerPluginApi, ScannerRegistry, ScannerShape, type ScheduleConfig, ScheduleConfigSchema, type ScheduledRunResult, type Scope, type SearchFn, type SemanticSearchOptions, type ServerEntry, type SessionRow, type Severity, type SharePreview, type SharePreviewEntry, type SharingLevel, SharingLevelSchema, type SharingPolicy, type ShellKind, type SlackMessage, SlackSink, SqliteCredentialStore, SqliteQueryBackend, SqliteStoreBackend, type StartApiOptions, StdoutSink, type StoreBackend, type SyncClassifyOptions, type SyncClassifyResult, TENANT_HEADER, type TenantContext, TenantMismatchError, type TenantOptions, type ToolResult, type TopologyDelta, type TopologyDiff, type TopologyInput, type TraversalResult, VectorStore, WebhookSink, type WebhookSinkOptions, applyInstall, applySharingLevel, assertReadOnly, assertSafeBind, assertSafeScanArg, assertSameTenant, assignColors, authorize, bearerToken, bookmarksScanner, buildCartographyToolHandlers, buildMapData, buildOpenApiDocument, buildReport, buildSinks, can, centralDbFromEnv, checkBearer, checkPrerequisites, checkReadOnly, clampText, classify, classifyDrift, cleanupTempFiles, cloudAwsScanner, cloudAzureScanner, cloudGcpScanner, codeAddMcpCommand, computeCentroid, computeClusterBounds, computeIdentity, connectionsScanner, contentHash, createBashTool, createCartographyTools, createClaudeProvider, createDefaultRegistry, createHashEmbedder, createIngestHandler, createLocalEmbedder, createMcpServer, createOllamaProvider, createOpenAIProvider, createScanRunner, createSemanticSearch, createSqliteQueryBackend, currentOs, cursorDeeplink, databasesScanner, deepMerge, defaultAllowedHosts, defaultConfig, defaultContext, defaultProviderRegistry, defaultRegistry, defaultServerEntry, definePlugin, deriveSessionName, detectAnomalies, detectOrphans, detectShadowIt, diffTopology, edgesToConnections, enrichCosts, evaluateCheck, evaluateRule, evidenceLine, executeGraphql, executeNlQuery, exportAll, exportBackstageYAML, exportComplianceReport, exportCostCSV, exportCostSummary, exportDiscoveryApp, exportJGF, exportJSON, extractListeningPorts, filterBySeverity, findAnonViolations, formatComplianceText, formatJira, formatPagerDuty, formatSlack, generateDependencyMermaid, generateDiffMermaid, generateTopologyMermaid, getClient, getRuleset, globalId, groupByDomain, handleGraphqlGet, hashToken, hexCorners, hexDistance, hexNeighbors, hexRing, hexSpiral, hexToPixel, hmacKey, hostname, ingestEnvelope, installedAppsScanner, isLoopbackHost, isPersonalHost, isReadOnlyCommand, isRemembered, isSecureWebhookUrl, k8sScanner, keyMetaOf, layoutClusters, listClients, listRulesets, loadConfig, loadOrgKey, loadPlugins, loadRuleset, localDiscoveryFn, log, logDebug, logError, logInfo, logWarn, machineId, maxSeverity, mcpServerObject, newAnomalies, nextRun, nodesToAssets, normalizeId, normalizeTenant, orgKeyPath, osUser, parseApiArgs, parseComposeDeps, parseConfig, parseConnectionString, parseCostCsv, parseCron, parseEstablished, parseNginxUpstreams, parseNlQuery, parseScanHint, pixelToHex, planInstall, portsScanner, postJson, previewShare, pseudonymize, pseudonymizeFragment, pseudonymizeString, pushDeltas, readConfigFile, redactConnectionString, redactSecrets, redactValue, renderDiff, resolveEffectiveLevel, resolveNlQuery, resolvePrincipal, resolveSharingLevel, resolveTenant, revalidateAnonymized, reversalKey, reversePseudonym, rotateOrgKey, runApi, runDiscovery, runDrift, runHttp, runLocalDiscovery, runOnce, runStdio, runSyncClassify, safeEnv, safeJson, safetyHook, sanitizeUntrusted, sanitizeValue, scopeReads, scoreTopology, securityRelevantChange, serializeConfig, serviceConfigScanner, setVerbose, shadeVariant, shapeToJsonSchema, shareHash, splitSegments, stableStringify, startApi, stripSensitive, timingSafeEqual, validateScanner, vscodeDeeplink, zodToJsonSchema };
4131
+ export { ACTIONS, ANOMALY_KINDS, ANOMALY_SEVERITIES, type Action, ActionSchema, type AgentProvider, type AgentRunContext, type AgentTool, type Anomaly, type AnomalyConfig, type AnomalyKind, type AnomalySeverity, type AnomalyThresholds, type AnonViolation, type AnonymizationLevel, type ApiServerOptions, type AskUserFn, type AuthConfig, AuthConfigSchema, AuthorizationError, type BackstageEntity, type BackstageMapOptions, type BindGuardOptions, CLIENTS, CONFIDENCE, COST_PERIODS, type CartographyConfig, CartographyDB, type CartographyMapData, type CentralDbConfig, CentralDbConfigSchema, type ClassifiedItem, type ClassifyInput, type ClassifyResult, type ClientSpec, type Cluster, ClusterSchema, type ComplianceInput, type ComplianceReport, ComplianceReportSchema, type ComplianceRule, ComplianceRuleSchema, type Condition, ConditionSchema, ConfigError, type ConfigFile, ConfigFileSchema, type ConfigFormat, type Connection, ConnectionSchema, type Contributor, type ControlResult, ControlResultSchema, type CostEntry, CostEntrySchema, type CostPeriod, type CostRecord, type CostSource, type CreateMcpServerOptions, type CredentialConfig, CredentialConfigSchema, type CredentialDb, type CredentialRecord, type CredentialStore, type CronFields, CsvCostSource, type CsvCostSourceOptions, DEFAULT_ANOMALY_THRESHOLDS, DEFAULT_FAST_MODEL, DEFAULT_LEAD_MODEL, DEFAULT_SERVER_NAME, DEFAULT_TENANT, DOMAIN_COLORS, DOMAIN_PALETTE, DRIFT_FIELDS, type DataAsset, DataAssetSchema, type DependencyQuery, type DiscoveryEdge, type DiscoveryEvent, type DiscoveryFn, type DiscoveryNode, type DriftAlert, type DriftAlertItem, type DriftConfig, DriftConfigSchema, type DriftField, type DriftItemKind, type DriftRunRow, type DriftSink, type DriftSinkConfig, EDGE_RELATIONSHIPS, type EdgeRelationship, type EdgeRow, EdgeSchema, type EmbeddingProvider, type EnrichResult, type EntryOptions, type EstablishedConn, type EvidenceKind, type FetchLike, type FragmentKind, type GraphSummary, type HealthResult, type HttpOptions, INGEST_SCHEMA_VERSION, type IngestEnvelope, IngestEnvelopeSchema, type IngestHandler, type IngestOptions, type IngestResponse, type IngestResult, type InstallPlan, InvalidTenantError, type JiraIssue, type JiraOptions, JiraSink, type JiraSinkOptions, LOOPBACK_HOSTS, type LocalDiscoveryOptions, type LocalDiscoveryResult, type LogEntry, type LogLevel, MCP_BIN, type MatchStrategy, NODE_TYPES, NODE_TYPE_GROUPS, type NlIntent, type NlQueryOptions, type NlQueryResult, type NlRelation, type NodeAttribution, type NodeChange, type NodeIdentity, type NodeQuery, type NodeRow, NodeSchema, type NodeType, type NodesResult, NotFoundError, OUTPUT_FORMATS, type OrgKeyOptions, type OrgSummary, type OsKind, type OutputFormat, PACKAGE_NAME, PAGERDUTY_ENQUEUE_URL, PENDING_STATUSES, PERSONAL, PORT_MAP, PRIVATE_IP, PUSH_SCHEMA_VERSION, type PagerDutyEvent, PagerDutySink, type PagerDutySinkOptions, type ParsedApiArgs, type PendingShareRow, type PendingStatus, type PlanOptions, type PolicyResult, type PostJsonOptions, type Principal, PrincipalSchema, type ProviderFactory, type ProviderName, ProviderRegistry, type PushItem, type PushOptions, type PushResult, type QueryBackend, RELATION_TO_DIRECTION, ROLES, type ResolveContext, type ResolveOptions, type Role, RoleSchema, type RuleCheck, RuleCheckSchema, type RuleScope, type Ruleset, RulesetSchema, type RunDriftOptions, SCAN_ARG_PATTERNS, SDL, SECURITY_METADATA_KEYS, SEVERITIES, SEVERITY_WEIGHT, SHARING_LEVELS, type ScanArgKind, type ScanContext, type ScanHintParams, type ScanResult, type Scanner, type ScannerPlugin, type ScannerPluginApi, ScannerRegistry, ScannerShape, type ScheduleConfig, ScheduleConfigSchema, type ScheduledRunResult, type Scope, type SearchFn, type SemanticSearchOptions, type ServerEntry, type SessionRow, type Severity, type SharePreview, type SharePreviewEntry, type SharingLevel, SharingLevelSchema, type SharingPolicy, type ShellKind, type SlackMessage, SlackSink, SqliteCredentialStore, SqliteQueryBackend, SqliteStoreBackend, type StartApiOptions, StdoutSink, type StoreBackend, type SyncClassifyOptions, type SyncClassifyResult, TENANT_HEADER, type TenantContext, TenantMismatchError, type TenantOptions, type ToolResult, type TopologyDelta, type TopologyDiff, type TopologyInput, type TraversalResult, VectorStore, WebhookSink, type WebhookSinkOptions, applyInstall, applySharingLevel, assertReadOnly, assertSafeBind, assertSafeScanArg, assertSameTenant, assignColors, authorize, bearerToken, bookmarksScanner, buildCartographyToolHandlers, buildMapData, buildOpenApiDocument, buildReport, buildSinks, can, centralDbFromEnv, checkBearer, checkPrerequisites, checkReadOnly, clampText, classify, classifyDrift, cleanupTempFiles, cloudAwsScanner, cloudAzureScanner, cloudGcpScanner, codeAddMcpCommand, computeCentroid, computeClusterBounds, computeIdentity, connectionsScanner, contentHash, createBashTool, createCartographyTools, createClaudeProvider, createDefaultRegistry, createHashEmbedder, createIngestHandler, createLocalEmbedder, createMcpServer, createOllamaProvider, createOpenAIProvider, createScanRunner, createSemanticSearch, createSqliteQueryBackend, currentOs, cursorDeeplink, databasesScanner, deepMerge, defaultAllowedHosts, defaultConfig, defaultContext, defaultProviderRegistry, defaultRegistry, defaultServerEntry, definePlugin, deriveSessionName, detectAnomalies, detectOrphans, detectShadowIt, diffTopology, edgesToConnections, enrichCosts, entitiesToYaml, evaluateCheck, evaluateRule, evidenceLine, executeGraphql, executeNlQuery, exportAll, exportBackstageYAML, exportComplianceReport, exportCostCSV, exportCostSummary, exportDiscoveryApp, exportJGF, exportJSON, extractListeningPorts, filterBySeverity, findAnonViolations, formatComplianceText, formatJira, formatPagerDuty, formatSlack, generateDependencyMermaid, generateDiffMermaid, generateTopologyMermaid, getClient, getRuleset, globalId, groupByDomain, handleGraphqlGet, hashToken, hexCorners, hexDistance, hexNeighbors, hexRing, hexSpiral, hexToPixel, hmacKey, hostname, ingestEnvelope, installedAppsScanner, isLoopbackHost, isPersonalHost, isReadOnlyCommand, isRemembered, isSecureWebhookUrl, k8sScanner, keyMetaOf, layoutClusters, listClients, listRulesets, loadConfig, loadOrgKey, loadPlugins, loadRuleset, localDiscoveryFn, log, logDebug, logError, logInfo, logWarn, machineId, maxSeverity, mcpServerObject, newAnomalies, nextRun, nodesToAssets, normalizeId, normalizeTenant, orgKeyPath, osUser, parseApiArgs, parseComposeDeps, parseConfig, parseConnectionString, parseCostCsv, parseCron, parseEstablished, parseNginxUpstreams, parseNlQuery, parseScanHint, pixelToHex, planInstall, portsScanner, postJson, previewShare, pseudonymize, pseudonymizeFragment, pseudonymizeString, pushDeltas, readConfigFile, redactConnectionString, redactSecrets, redactValue, renderDiff, resolveEffectiveLevel, resolveNlQuery, resolvePrincipal, resolveSharingLevel, resolveTenant, revalidateAnonymized, reversalKey, reversePseudonym, rotateOrgKey, runApi, runDiscovery, runDrift, runHttp, runLocalDiscovery, runOnce, runStdio, runSyncClassify, safeEnv, safeJson, safetyHook, sanitizeUntrusted, sanitizeValue, scopeReads, scoreTopology, securityRelevantChange, serializeConfig, serviceConfigScanner, setVerbose, shadeVariant, shapeToJsonSchema, shareHash, splitSegments, stableStringify, startApi, stripSensitive, timingSafeEqual, toBackstageEntities, validateScanner, vscodeDeeplink, zodToJsonSchema };
package/dist/index.js CHANGED
@@ -4404,6 +4404,9 @@ var SqliteQueryBackend = class {
4404
4404
  node(ctx, id, sessionId) {
4405
4405
  return this.db.getNode(this.resolveSession(ctx, sessionId), id);
4406
4406
  }
4407
+ edges(ctx, sessionId) {
4408
+ return this.db.getEdges(this.resolveSession(ctx, sessionId));
4409
+ }
4407
4410
  dependencies(ctx, id, q, sessionId) {
4408
4411
  const sid = this.resolveSession(ctx, sessionId);
4409
4412
  return this.db.getDependencies(sid, id, {
@@ -5646,7 +5649,7 @@ async function resolveNlQuery(db, sessionId, search, raw, opts) {
5646
5649
 
5647
5650
  // src/mcp/server.ts
5648
5651
  var SERVER_NAME = "cartography";
5649
- var SERVER_VERSION = "2.5.0";
5652
+ var SERVER_VERSION = "2.6.0";
5650
5653
  var SERVICE_TYPES = NODE_TYPE_GROUPS.web;
5651
5654
  var DATA_TYPES = NODE_TYPE_GROUPS.data;
5652
5655
  var lexicalSearch = async (db, sessionId, query, opts) => db.searchNodes(sessionId, query, { types: opts.types, limit: opts.limit }).map((node) => ({ node }));
@@ -7179,6 +7182,54 @@ function headerValue(req, name) {
7179
7182
  return v;
7180
7183
  }
7181
7184
 
7185
+ // src/backstage.ts
7186
+ var COMPONENT_TYPES = ["web_service", "container", "pod"];
7187
+ function sanitize(id) {
7188
+ return id.replace(/[^a-zA-Z0-9_]/g, "_");
7189
+ }
7190
+ function toBackstageEntities(nodes, edges, opts = {}) {
7191
+ const owner = opts.org ?? "unknown";
7192
+ return nodes.map((node) => {
7193
+ const kind = COMPONENT_TYPES.includes(node.type) ? "Component" : node.type === "api_endpoint" ? "API" : "Resource";
7194
+ const dependsOn = edges.filter((e) => e.sourceId === node.id).map((e) => `resource:default/${sanitize(e.targetId)}`);
7195
+ return {
7196
+ apiVersion: "backstage.io/v1alpha1",
7197
+ kind,
7198
+ metadata: {
7199
+ name: sanitize(node.id),
7200
+ annotations: {
7201
+ "cartography/discovered-at": node.discoveredAt,
7202
+ "cartography/confidence": String(node.confidence)
7203
+ }
7204
+ },
7205
+ spec: {
7206
+ type: node.type,
7207
+ lifecycle: "production",
7208
+ owner: node.owner ?? owner,
7209
+ ...dependsOn.length > 0 ? { dependsOn } : {}
7210
+ }
7211
+ };
7212
+ });
7213
+ }
7214
+ function entitiesToYaml(entities) {
7215
+ return entities.map((e) => {
7216
+ const lines = [
7217
+ `apiVersion: ${e.apiVersion}`,
7218
+ `kind: ${e.kind}`,
7219
+ `metadata:`,
7220
+ ` name: ${e.metadata.name}`,
7221
+ ` annotations:`,
7222
+ ...Object.entries(e.metadata.annotations).map(([k, v]) => ` ${k}: "${v}"`),
7223
+ `spec:`,
7224
+ ` type: ${e.spec.type}`,
7225
+ ` lifecycle: ${e.spec.lifecycle}`,
7226
+ ` owner: ${e.spec.owner}`,
7227
+ ...e.spec.dependsOn && e.spec.dependsOn.length > 0 ? [" dependsOn:", ...e.spec.dependsOn.map((d) => ` - ${d}`)] : []
7228
+ ];
7229
+ return lines.join("\n");
7230
+ }).join("\n---\n");
7231
+ }
7232
+
7182
7233
  // src/api/schemas.ts
7183
7234
  import { z as z8 } from "zod";
7184
7235
  var DIRECTIONS = ["downstream", "upstream", "both"];
@@ -7314,6 +7365,21 @@ var ErrorResponse = z8.object({
7314
7365
  error: z8.string(),
7315
7366
  code: z8.string().optional()
7316
7367
  });
7368
+ var BackstageEntitySchema = z8.object({
7369
+ apiVersion: z8.literal("backstage.io/v1alpha1"),
7370
+ kind: z8.enum(["Component", "API", "Resource"]),
7371
+ metadata: z8.object({
7372
+ name: z8.string(),
7373
+ annotations: z8.record(z8.string(), z8.string())
7374
+ }),
7375
+ spec: z8.object({
7376
+ type: z8.string(),
7377
+ lifecycle: z8.string(),
7378
+ owner: z8.string(),
7379
+ dependsOn: z8.array(z8.string()).optional()
7380
+ })
7381
+ });
7382
+ var BackstageCatalogResponse = z8.object({ entities: z8.array(BackstageEntitySchema) });
7317
7383
  var API_SCHEMAS = {
7318
7384
  Node: NodeSchema2,
7319
7385
  Edge: EdgeSchema2,
@@ -7325,10 +7391,13 @@ var API_SCHEMAS = {
7325
7391
  Session: SessionSchema,
7326
7392
  Sessions: SessionsResponse,
7327
7393
  Health: HealthResponse,
7328
- Error: ErrorResponse
7394
+ Error: ErrorResponse,
7395
+ BackstageEntity: BackstageEntitySchema,
7396
+ BackstageCatalog: BackstageCatalogResponse
7329
7397
  };
7330
7398
 
7331
7399
  // src/api/rest.ts
7400
+ var BACKSTAGE_NODE_CAP = 1e3;
7332
7401
  function toApiNode(n) {
7333
7402
  const out = { id: n.id, type: n.type, name: n.name, confidence: n.confidence, tags: n.tags };
7334
7403
  if (n.domain !== void 0) out["domain"] = n.domain;
@@ -7463,6 +7532,14 @@ function handleHealth(ctx, d) {
7463
7532
  const h = d.backend.health(ctx);
7464
7533
  return ok(validateOut(HealthResponse, { status: "ok", version: d.version, store: h.store, sessions: h.sessions }));
7465
7534
  }
7535
+ function handleBackstageCatalog(ctx, d) {
7536
+ return guard(() => {
7537
+ const page = d.backend.nodes(ctx, { limit: BACKSTAGE_NODE_CAP });
7538
+ const edges = d.backend.edges(ctx);
7539
+ const entities = toBackstageEntities(page.nodes, edges, { org: ctx.tenant });
7540
+ return ok(validateOut(BackstageCatalogResponse, { entities }));
7541
+ });
7542
+ }
7466
7543
 
7467
7544
  // src/api/openapi.ts
7468
7545
  function defOf(schema) {
@@ -7619,6 +7696,13 @@ function buildOpenApiDocument(opts) {
7619
7696
  parameters: [TENANT_PARAM],
7620
7697
  responses: { "200": ok2("Sessions", "Sessions"), ...errorResponses() }
7621
7698
  }
7699
+ },
7700
+ "/v1/backstage/catalog": {
7701
+ get: {
7702
+ summary: "The tenant topology as Backstage catalog entities (live data source, 4.6)",
7703
+ parameters: [SESSION_PARAM, TENANT_PARAM],
7704
+ responses: { "200": ok2("BackstageCatalog", "Backstage catalog entities"), ...errorResponses() }
7705
+ }
7622
7706
  }
7623
7707
  }
7624
7708
  };
@@ -8133,6 +8217,8 @@ function dispatchRest(ctx, path, url, deps) {
8133
8217
  return handleDiff(ctx, url, deps);
8134
8218
  case "/v1/sessions":
8135
8219
  return handleSessions(ctx, deps);
8220
+ case "/v1/backstage/catalog":
8221
+ return handleBackstageCatalog(ctx, deps);
8136
8222
  default: {
8137
8223
  const m = DEPENDENCIES_RE.exec(path);
8138
8224
  if (m) return handleDependencies(ctx, decodeURIComponent(m[1]), url, deps);
@@ -9638,7 +9724,7 @@ var MERMAID_CLASSES = {
9638
9724
  saas_tool: "fill:#2a1a2a,stroke:#9a3a9a,color:#daf",
9639
9725
  unknown: "fill:#2a2a2a,stroke:#5a5a5a,color:#aaa"
9640
9726
  };
9641
- function sanitize(id) {
9727
+ function sanitize2(id) {
9642
9728
  return id.replace(/[^a-zA-Z0-9_]/g, "_");
9643
9729
  }
9644
9730
  function nodeLabel(node) {
@@ -9680,14 +9766,14 @@ function generateTopologyMermaid(nodes, edges) {
9680
9766
  const label = LAYER_LABELS[layerKey] ?? layerKey;
9681
9767
  lines.push(` subgraph ${layerKey}["${label}"]`);
9682
9768
  for (const node of layerNodes) {
9683
- lines.push(` ${sanitize(node.id)}${nodeLabel(node)}:::${node.type.replace(/_/g, "")}`);
9769
+ lines.push(` ${sanitize2(node.id)}${nodeLabel(node)}:::${node.type.replace(/_/g, "")}`);
9684
9770
  }
9685
9771
  lines.push(" end");
9686
9772
  lines.push("");
9687
9773
  }
9688
9774
  for (const edge of edges) {
9689
- const src = sanitize(edge.sourceId);
9690
- const tgt = sanitize(edge.targetId);
9775
+ const src = sanitize2(edge.sourceId);
9776
+ const tgt = sanitize2(edge.targetId);
9691
9777
  const label = EDGE_LABELS[edge.relationship] ?? edge.relationship;
9692
9778
  const arrow = edge.confidence < 0.6 ? `-. "${label}" .->` : `-->|"${label}"|`;
9693
9779
  lines.push(` ${src} ${arrow} ${tgt}`);
@@ -9713,12 +9799,12 @@ function generateDependencyMermaid(nodes, edges) {
9713
9799
  }
9714
9800
  lines.push("");
9715
9801
  for (const node of usedNodes) {
9716
- lines.push(` ${sanitize(node.id)}${nodeLabel(node)}:::${node.type.replace(/_/g, "")}`);
9802
+ lines.push(` ${sanitize2(node.id)}${nodeLabel(node)}:::${node.type.replace(/_/g, "")}`);
9717
9803
  }
9718
9804
  lines.push("");
9719
9805
  for (const edge of depEdges) {
9720
9806
  const label = EDGE_LABELS[edge.relationship] ?? edge.relationship;
9721
- lines.push(` ${sanitize(edge.sourceId)} -->|"${label}"| ${sanitize(edge.targetId)}`);
9807
+ lines.push(` ${sanitize2(edge.sourceId)} -->|"${label}"| ${sanitize2(edge.targetId)}`);
9722
9808
  }
9723
9809
  return lines.join("\n");
9724
9810
  }
@@ -9769,44 +9855,21 @@ function generateDiffMermaid(diff) {
9769
9855
  ensureEndpoint(e.targetId);
9770
9856
  }
9771
9857
  for (const { node, cls, suffix } of entries.values()) {
9772
- lines.push(` ${sanitize(node.id)}${diffNodeLabel(node, suffix)}:::${cls}`);
9858
+ lines.push(` ${sanitize2(node.id)}${diffNodeLabel(node, suffix)}:::${cls}`);
9773
9859
  }
9774
9860
  lines.push("");
9775
9861
  for (const e of diff.edges.added) {
9776
9862
  const label = EDGE_LABELS[e.relationship] ?? e.relationship;
9777
- lines.push(` ${sanitize(e.sourceId)} ==>|"+ ${label}"| ${sanitize(e.targetId)}`);
9863
+ lines.push(` ${sanitize2(e.sourceId)} ==>|"+ ${label}"| ${sanitize2(e.targetId)}`);
9778
9864
  }
9779
9865
  for (const e of diff.edges.removed) {
9780
9866
  const label = EDGE_LABELS[e.relationship] ?? e.relationship;
9781
- lines.push(` ${sanitize(e.sourceId)} -.->|"- ${label}"| ${sanitize(e.targetId)}`);
9867
+ lines.push(` ${sanitize2(e.sourceId)} -.->|"- ${label}"| ${sanitize2(e.targetId)}`);
9782
9868
  }
9783
9869
  return lines.join("\n");
9784
9870
  }
9785
9871
  function exportBackstageYAML(nodes, edges, org) {
9786
- const owner = org ?? "unknown";
9787
- const docs = [];
9788
- for (const node of nodes) {
9789
- const isComponent = ["web_service", "container", "pod"].includes(node.type);
9790
- const isAPI = node.type === "api_endpoint";
9791
- const kind = isComponent ? "Component" : isAPI ? "API" : "Resource";
9792
- const deps = edges.filter((e) => e.sourceId === node.id).map((e) => ` - resource:default/${sanitize(e.targetId)}`);
9793
- const doc = [
9794
- `apiVersion: backstage.io/v1alpha1`,
9795
- `kind: ${kind}`,
9796
- `metadata:`,
9797
- ` name: ${sanitize(node.id)}`,
9798
- ` annotations:`,
9799
- ` cartography/discovered-at: "${node.discoveredAt}"`,
9800
- ` cartography/confidence: "${node.confidence}"`,
9801
- `spec:`,
9802
- ` type: ${node.type}`,
9803
- ` lifecycle: production`,
9804
- ` owner: ${node.owner ?? owner}`,
9805
- ...deps.length > 0 ? [" dependsOn:", ...deps] : []
9806
- ].join("\n");
9807
- docs.push(doc);
9808
- }
9809
- return docs.join("\n---\n");
9872
+ return entitiesToYaml(toBackstageEntities(nodes, edges, org !== void 0 ? { org } : {}));
9810
9873
  }
9811
9874
  function exportJSON(db, sessionId) {
9812
9875
  const nodes = db.getNodes(sessionId);
@@ -11610,6 +11673,7 @@ export {
11610
11673
  diffTopology,
11611
11674
  edgesToConnections,
11612
11675
  enrichCosts,
11676
+ entitiesToYaml,
11613
11677
  evaluateCheck,
11614
11678
  evaluateRule,
11615
11679
  evidenceLine,
@@ -11739,6 +11803,7 @@ export {
11739
11803
  startApi,
11740
11804
  stripSensitive,
11741
11805
  timingSafeEqual,
11806
+ toBackstageEntities,
11742
11807
  validateScanner,
11743
11808
  vscodeDeeplink,
11744
11809
  zodToJsonSchema