@veltrixsecops/app-sdk 2.4.0 → 2.5.1

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.
@@ -330,6 +330,44 @@ interface Credential {
330
330
  toolId: string;
331
331
  customerId: string;
332
332
  }
333
+ /**
334
+ * A redacted view of a {@link Credential}, as returned by the SDK's
335
+ * `listCredentials` helper. Secret material (password / apiToken / certificate)
336
+ * is deliberately dropped so it never enters app code or logs — only whether a
337
+ * secret is present is surfaced, via {@link CredentialSummary.hasSecret}. Used
338
+ * to pair a credential with its server (a "connection") for display.
339
+ */
340
+ interface CredentialSummary {
341
+ id: string;
342
+ /** Human-readable label. For connections this mirrors the server hostname. */
343
+ name: string;
344
+ /** Account / client id the credential authenticates as. */
345
+ username: string;
346
+ /** Auth kind (e.g. "password", "token"), or null when unspecified. */
347
+ type: string | null;
348
+ /** The tool this credential belongs to. */
349
+ toolId: string;
350
+ /** True when a write-only secret (apiToken or password) is stored. */
351
+ hasSecret: boolean;
352
+ }
353
+ /**
354
+ * Input accepted by `createCredential` / `updateCredential`. Mirrors the
355
+ * platform credentials API body. `name`, `username`, and `password` are
356
+ * required by the platform on create (`password` may be an empty string for
357
+ * token-only auth); the write-only secret travels in `apiToken`. `toolId` is
358
+ * required on create — pass the id your app registers connections under.
359
+ */
360
+ interface CredentialInput {
361
+ name: string;
362
+ username: string;
363
+ password: string;
364
+ apiToken?: string;
365
+ type?: string;
366
+ /** The tool this credential belongs to. Required by the platform on create. */
367
+ toolId?: string;
368
+ /** IDs of existing platform tags to attach to the credential. */
369
+ tagIds?: string[];
370
+ }
333
371
  interface Connectivity {
334
372
  id: string;
335
373
  componentId: string;
@@ -426,4 +464,4 @@ declare const AppContext: Context<AppContextValue | null>;
426
464
  */
427
465
  declare function useAppContext(): AppContextValue;
428
466
 
429
- export { type AppBrandingDeclaration as A, type Customer as B, type Component as C, type InventoryItemInput as D, type InventoryItem as I, type PlatformDatabaseClient as P, type Tag as T, type User as U, AppContext as a, type AppContextValue as b, APP_PAGE_LAYOUTS as c, APP_PAGE_NAV as d, type AccessServer as e, type AccessServerInput as f, type AppConfigurationTypeManifest as g, type AppDetail as h, type AppHookContext as i, type AppInstallationDetail as j, type AppInstallationStatus as k, type AppListItem as l, type AppManifest as m, type AppPageDeclaration as n, type AppPageLayout as o, type AppPageNav as p, type AppPagePermission as q, type AppPermissionDeclaration as r, type AppRouteContext as s, type AppSettingDeclaration as t, useAppContext as u, type AppSource as v, type AppStatusType as w, type Connectivity as x, type ConnectivityProviderRef as y, type Credential as z };
467
+ export { type AppBrandingDeclaration as A, type CredentialInput as B, type Component as C, type CredentialSummary as D, type Customer as E, type InventoryItemInput as F, type InventoryItem as I, type PlatformDatabaseClient as P, type Tag as T, type User as U, AppContext as a, type AppContextValue as b, APP_PAGE_LAYOUTS as c, APP_PAGE_NAV as d, type AccessServer as e, type AccessServerInput as f, type AppConfigurationTypeManifest as g, type AppDetail as h, type AppHookContext as i, type AppInstallationDetail as j, type AppInstallationStatus as k, type AppListItem as l, type AppManifest as m, type AppPageDeclaration as n, type AppPageLayout as o, type AppPageNav as p, type AppPagePermission as q, type AppPermissionDeclaration as r, type AppRouteContext as s, type AppSettingDeclaration as t, useAppContext as u, type AppSource as v, type AppStatusType as w, type Connectivity as x, type ConnectivityProviderRef as y, type Credential as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltrixsecops/app-sdk",
3
- "version": "2.4.0",
3
+ "version": "2.5.1",
4
4
  "description": "Official SDK for building Veltrix Security-as-Code apps — typed pipeline handler contracts, lifecycle hook types, manifest types, and React hooks.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/client/inventory.ts","../src/client/access-servers.ts","../src/client/index.ts"],"sourcesContent":["// ========================================================================\n// Inventory — the deployment targets an app can deploy configuration to.\n//\n// \"Inventory\" is the app-facing name for the platform's *components*: the\n// servers (hostname/port), domains, and IP/CIDR ranges a customer has\n// registered as deploy targets. These helpers are a typed, convenient\n// surface over the platform's components API (/api/components), enriched\n// with `domains` and `ipRanges`.\n//\n// Framework-free (no React) — safe to import from any client code. Every\n// call goes through the same `authFetch` the '/client' subpath exports, so\n// requests carry the platform's Authorization header. Non-2xx responses are\n// surfaced as thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type { InventoryItem, InventoryItemInput } from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's components (inventory) API. */\nconst INVENTORY_API = '/api/components'\n\n/**\n * Loosely-typed shape of a raw component as returned by the platform, before\n * it is normalized down to the {@link InventoryItem} surface.\n */\ninterface RawInventoryItem {\n id: string\n hostname?: string\n port?: string\n type?: string[]\n domains?: string[]\n ipRanges?: string[]\n tags?: Array<{ id: string; name: string }>\n connectivityProviderId?: string | null\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function inventoryError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform component into the typed InventoryItem surface. */\nfunction toInventoryItem(raw: RawInventoryItem): InventoryItem {\n return {\n id: String(raw.id),\n hostname: raw.hostname ?? '',\n port: raw.port ?? undefined,\n type: Array.isArray(raw.type) ? raw.type : undefined,\n domains: Array.isArray(raw.domains) ? raw.domains : [],\n ipRanges: Array.isArray(raw.ipRanges) ? raw.ipRanges : [],\n tags: Array.isArray(raw.tags)\n ? raw.tags.map((tag) => ({ id: String(tag.id), name: String(tag.name) }))\n : [],\n connectivityProviderId: raw.connectivityProviderId ?? null,\n }\n}\n\n/**\n * A platform Tool. Each installed app is upserted as a Tool keyed by its\n * manifest `name`, and inventory items (components) belong to a tool.\n */\nexport interface Tool {\n id: string\n name: string\n vendor?: string\n}\n\n/**\n * Resolve the platform Tool for an app by its manifest name (the platform\n * upserts `Tool.name === app name`). The tool id is required by the platform\n * when creating an inventory item, so call this once and pass the id as\n * `toolId` to {@link addInventoryItem}. Returns null when no tool matches.\n *\n * GET /api/tools (the endpoint is paginated — `{ data, pagination }` — or a\n * bare array; both are handled).\n */\nexport async function resolveTool(name: string): Promise<Tool | null> {\n const res = await authFetch('/api/tools')\n if (!res.ok) throw await inventoryError(res)\n const body = (await res.json()) as unknown\n const tools: Tool[] = Array.isArray(body)\n ? (body as Tool[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: Tool[] }).data)\n : []\n return tools.find((tool) => tool.name === name) ?? null\n}\n\n/** List the customer's inventory (deployment targets). GET /api/components */\nexport async function listInventory(): Promise<InventoryItem[]> {\n const res = await authFetch(INVENTORY_API)\n if (!res.ok) throw await inventoryError(res)\n const data = (await res.json()) as RawInventoryItem[]\n return Array.isArray(data) ? data.map(toInventoryItem) : []\n}\n\n/** Add a new inventory item (deployment target). POST /api/components */\nexport async function addInventoryItem(input: InventoryItemInput): Promise<InventoryItem> {\n const res = await authFetch(INVENTORY_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Update an existing inventory item. PUT /api/components/:id */\nexport async function updateInventoryItem(\n id: string,\n input: InventoryItemInput,\n): Promise<InventoryItem> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Remove an inventory item. DELETE /api/components/:id */\nexport async function removeInventoryItem(id: string): Promise<void> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await inventoryError(res)\n}\n","// ========================================================================\n// Access Servers — the Zero-Trust Access (ZTNA) gateways an app manages.\n//\n// Each Access Server is a ZTNA gateway (name + endpoint) a customer has\n// registered, optionally linked to one of their connectivity providers. These\n// helpers are a typed, convenient surface over the platform's access-servers\n// API (/api/access-servers), plus a thin reader over the connectivity\n// providers API (/api/connectivity-providers) used to populate the ZTNA link\n// picker.\n//\n// Framework-free (no React) — safe to import from any client code. Every call\n// goes through the same `authFetch` the '/client' subpath exports, so requests\n// carry the platform's Authorization header. Non-2xx responses are surfaced as\n// thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type {\n AccessServer,\n AccessServerInput,\n ConnectivityProviderRef,\n} from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's access-servers API. */\nconst ACCESS_SERVERS_API = '/api/access-servers'\n/** Base route for the platform's connectivity-providers API (ZTNA picker). */\nconst CONNECTIVITY_PROVIDERS_API = '/api/connectivity-providers'\n\n/**\n * Loosely-typed shape of a raw access server as returned by the platform,\n * before it is normalized down to the {@link AccessServer} surface.\n */\ninterface RawAccessServer {\n id: string\n name?: string\n endpoint?: string\n type?: string\n region?: string | null\n status?: string\n description?: string | null\n connectivityProviderId?: string | null\n connectivityProvider?: { id: string; name: string } | null\n}\n\n/**\n * Loosely-typed shape of a raw connectivity provider as returned by the\n * platform, before it is normalized to the {@link ConnectivityProviderRef}\n * picker surface.\n */\ninterface RawConnectivityProvider {\n id: string\n name?: string\n providerType?: string\n status?: string\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function accessServerError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform access server into the typed AccessServer surface. */\nfunction toAccessServer(raw: RawAccessServer): AccessServer {\n return {\n id: String(raw.id),\n name: raw.name ?? '',\n endpoint: raw.endpoint ?? '',\n type: raw.type ?? undefined,\n region: raw.region ?? null,\n status: raw.status ?? undefined,\n description: raw.description ?? null,\n connectivityProviderId: raw.connectivityProviderId ?? null,\n connectivityProvider: raw.connectivityProvider\n ? { id: String(raw.connectivityProvider.id), name: String(raw.connectivityProvider.name) }\n : null,\n }\n}\n\n/** List the customer's access servers (ZTNA gateways). GET /api/access-servers */\nexport async function listAccessServers(): Promise<AccessServer[]> {\n const res = await authFetch(ACCESS_SERVERS_API)\n if (!res.ok) throw await accessServerError(res)\n const data = (await res.json()) as RawAccessServer[]\n return Array.isArray(data) ? data.map(toAccessServer) : []\n}\n\n/** Add a new access server (ZTNA gateway). POST /api/access-servers */\nexport async function addAccessServer(input: AccessServerInput): Promise<AccessServer> {\n const res = await authFetch(ACCESS_SERVERS_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await accessServerError(res)\n return toAccessServer((await res.json()) as RawAccessServer)\n}\n\n/** Update an existing access server. PUT /api/access-servers/:id */\nexport async function updateAccessServer(\n id: string,\n input: AccessServerInput,\n): Promise<AccessServer> {\n const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await accessServerError(res)\n return toAccessServer((await res.json()) as RawAccessServer)\n}\n\n/** Remove an access server. DELETE /api/access-servers/:id */\nexport async function removeAccessServer(id: string): Promise<void> {\n const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await accessServerError(res)\n}\n\n/**\n * List the customer's ZTNA connectivity providers, used to populate the Access\n * Server link picker. GET /api/connectivity-providers (the endpoint may return\n * a bare array or a paginated `{ data, ... }` shape — both are handled).\n */\nexport async function listConnectivityProviders(): Promise<ConnectivityProviderRef[]> {\n const res = await authFetch(CONNECTIVITY_PROVIDERS_API)\n if (!res.ok) throw await accessServerError(res)\n const body = (await res.json()) as unknown\n const providers: RawConnectivityProvider[] = Array.isArray(body)\n ? (body as RawConnectivityProvider[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: RawConnectivityProvider[] }).data)\n : []\n return providers.map((provider) => ({\n id: String(provider.id),\n name: provider.name ?? '',\n providerType: provider.providerType ?? undefined,\n status: provider.status ?? undefined,\n }))\n}\n","// ========================================================================\n// Client runtime contract — how app client bundles talk to the host.\n//\n// App client code is packaged as a hermetic ESM bundle in which `react`,\n// `react-dom`, `react/jsx-runtime`, and every `@veltrixsecops/app-sdk`\n// subpath are compile-time shims that read the host-provided runtime from\n// `globalThis.__VELTRIX_APP_RUNTIME__`. The platform installs that global\n// (with ITS React instance, the shared AppContext, and an authenticated\n// fetch) before dynamically importing any app bundle, so app components\n// render inside the host React tree with working hooks and context.\n//\n// App authors: import from '@veltrixsecops/app-sdk/client' (and /hooks) —\n// never bundle your own copy of react. Use `authFetch` for calls to your\n// app's server routes (/api/apps/<app-id>/...): plain fetch() lacks the\n// platform's Authorization header and will receive 401s.\n// ========================================================================\n\nimport type { ComponentType, Context, LazyExoticComponent } from 'react'\nimport type { AppContextValue } from '../hooks/use-app-context'\n\nexport type { AppBrandingDeclaration } from '../types/manifest'\n\n// Inventory — typed helpers over the platform's components API (deployment\n// targets: servers, domains, IP/CIDR ranges). Framework-free; they use the\n// `authFetch` exported below internally.\nexport {\n listInventory,\n addInventoryItem,\n updateInventoryItem,\n removeInventoryItem,\n resolveTool,\n} from './inventory'\nexport type { Tool } from './inventory'\nexport type { InventoryItem, InventoryItemInput } from '../types/platform'\n\n// Access Servers — typed helpers over the platform's access-servers API (ZTNA\n// gateways) plus a reader over connectivity providers for the link picker.\n// Framework-free; they use the `authFetch` exported below internally.\nexport {\n listAccessServers,\n addAccessServer,\n updateAccessServer,\n removeAccessServer,\n listConnectivityProviders,\n} from './access-servers'\nexport type { AccessServer, AccessServerInput, ConnectivityProviderRef } from '../types/platform'\n\n/** Name of the global the platform installs before loading app bundles. */\nexport const HOST_RUNTIME_GLOBAL = '__VELTRIX_APP_RUNTIME__'\n\n/**\n * The runtime surface the platform exposes to app client bundles.\n * The react/reactDom/jsxRuntime members are the host's own module objects —\n * app bundles are compiled with shims that re-export them, guaranteeing a\n * single React instance per page.\n */\nexport interface VeltrixHostRuntime {\n /** The host's `react` module object. */\n react: unknown\n /** The host's `react-dom` module object. */\n reactDom: unknown\n /** The host's `react-dom/client` module object. */\n reactDomClient?: unknown\n /** The host's `react/jsx-runtime` module object. */\n jsxRuntime: unknown\n /** Shared app context — the host wraps app pages in its Provider. */\n AppContext: Context<AppContextValue | null>\n /** fetch() with the platform's Authorization header attached. */\n authFetch: (input: string, init?: RequestInit) => Promise<Response>\n /**\n * The SDK surface app bundles receive for `@veltrixsecops/app-sdk`,\n * `.../hooks`, and `.../client` imports (useAppContext, AppContext,\n * usePipelineStatus, authFetch, getHostRuntime, ...).\n */\n sdk: Record<string, unknown>\n /**\n * The platform's design-system components and hooks, host-owned so they\n * share the single host React instance. Keyed by the exact component/hook\n * names re-exported from `@veltrixsecops/app-sdk/ui` (Button, Input, Card,\n * DataTable, useToast, ...). Present only inside the platform.\n */\n ui?: Record<string, unknown>\n}\n\n/** Read the host runtime, or null outside the platform (tests, storybook). */\nexport function getHostRuntime(): VeltrixHostRuntime | null {\n const runtime = (globalThis as Record<string, unknown>)[HOST_RUNTIME_GLOBAL]\n return (runtime as VeltrixHostRuntime) ?? null\n}\n\n/** Read the host runtime, throwing a diagnosable error when absent. */\nexport function requireHostRuntime(): VeltrixHostRuntime {\n const runtime = getHostRuntime()\n if (!runtime) {\n throw new Error(\n 'Veltrix host runtime not found — app client bundles only run inside the ' +\n `Veltrix platform (missing globalThis.${HOST_RUNTIME_GLOBAL})`,\n )\n }\n return runtime\n}\n\n/**\n * fetch() that carries the platform's Authorization header. Required for an\n * app page to call its own server routes (/api/apps/<app-id>/...), which are\n * bearer-token protected. Falls back to plain fetch outside the platform.\n */\nexport function authFetch(input: string, init?: RequestInit): Promise<Response> {\n const runtime = getHostRuntime()\n if (runtime) return runtime.authFetch(input, init)\n return fetch(input, init)\n}\n\n/** A sidebar entry contributed by the app's client entry module. */\nexport interface AppSidebarItem {\n path: string\n label: string\n icon?: string\n}\n\n/**\n * Shape of the default export of an app's `client/index.tsx`.\n * `pages` keys must match `manifest.client.pages[].component`.\n */\nexport interface AppClientModule {\n id: string\n pages: Record<string, ComponentType | LazyExoticComponent<ComponentType>>\n sidebarItems?: AppSidebarItem[]\n}\n"],"mappings":"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","names":[]}