# Listening ports scan
> Scans a demo host and compares its listening ports with the inventory; unexpected ports can be registered or closed.
- Element: `<sv-port-scan>`
- React: `import { SvPortScan } from "@/components/lumesec/sv-port-scan"`
- Collection: Service Map (https://elements.lumesec.ai/components/service-map)
- Registry item: https://elements.lumesec.ai/r/sv-port-scan.json
- Page: https://elements.lumesec.ai/components/service-map/port-scan



Live preview: https://elements.lumesec.ai/view/sv-port-scan

```html
<sv-port-scan></sv-port-scan>
```

## Installation

```bash
npx shadcn@latest add @lumesec/sv-port-scan
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/sv-port-scan.json
```

## Usage

React:

```tsx
import { SvPortScan } from "@/components/lumesec/sv-port-scan";

export function Example() {
  return (
    <SvPortScan />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/sv-port-scan.js"></script>

<sv-port-scan></sv-port-scan>
```

## Behaviour

Compares the inventory with what the host actually listens on. Unexpected ports can be registered or closed.

## API reference

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event    | React prop | Detail                                                                    | Description                                                                   |
| -------- | ---------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `scan`   | `onScan`   | `{ host: string, unexpected: number[] }`                                  | Fires when a scan finishes, with the host id and the unexpected port numbers. |
| `change` | `onChange` | `{ action: 'register-port' \| 'close-port', host: string, port: number }` | Fires when Register or Close is pressed for an unexpected port.               |

### Methods

Call them on the element, for example through a React ref.

| Method  | Description                                                   |
| ------- | ------------------------------------------------------------- |
| `run()` | Scans the host selected in the menu, as the Scan button does. |

## Accessibility

* The host menu is labelled Host. The summary line is a polite live region that reports the scan and then the counts.
* Results are a `role="list"`. The Scan button is disabled while a scan runs.
* The sweep canvas is `aria-hidden`.
* Reduced motion: the sweep finishes in 0.05 s instead of 2.2 s, so all results appear at once.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--border`, `--card`, `--destructive`, `--foreground`, `--lumesec`, `--lumesec-success`, `--lumesec-warning` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-border`, `--ui-danger`, `--ui-fg`, `--ui-muted`, `--ui-ok`, `--ui-surface` and `--ui-warn`.

## Notes

* Built-in demo results for app-01 (default), db-01, edge-01 and mon-01. Expected ports come from `INFRA`; app-01 also listens on 5005 and 8081, db-01 on 9187, edge-01 on 8080, and on mon-01 port 3100 is expected but not listening. No attribute selects the host.
* Register and Close only mark the row and fire `change`. Choosing another host clears the results.
* Results appear in port order as the sweep, on a logarithmic scale, passes them.


