# Relationship Review (`relationships-01`) - SignalOS page block

> Full-page relationship review block with an ER diagram, field metadata panel, review queue, and add/edit dialogs.

- **Version:** 0.4.8
- **Kind:** block (group: semantics-details) · **Category:** pages
- **Install:** `npx shadcn@latest add @signalos/relationships-01`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/button, @signalos/badge, @signalos/select, @signalos/textarea, @signalos/form-dialog, @signalos/split-panel, @signalos/page-header, @signalos/tooltip, @signalos/dialog
- **npm dependencies:** lucide-react@^1.7.0, @xyflow/react@^12.0.0
- **Files installed:** `src/components/blocks/relationships-01/RelationsShipReview.tsx`, `src/components/blocks/relationships-01/components/RelationshipsHeader.tsx`, `src/components/blocks/relationships-01/components/RelationshipsQueue.tsx`, `src/components/blocks/relationships-01/components/RelationshipsFieldsPanel.tsx`, `src/components/blocks/relationships-01/components/ERDiagram.tsx`, `src/components/blocks/relationships-01/components/EditRelationshipDialog.tsx`, `src/components/blocks/relationships-01/components/RelationshipAddDialog.tsx`, `src/components/blocks/relationships-01/Relationships.types.ts`

## Access

This is a private registry: pulling source requires a `SIGNALOS_REGISTRY_TOKEN`
(GitHub fine-grained PAT with read access to the signal-widgets repo) and an
`@signalos` entry in components.json `"registries"`. Previews and this document are public.

## Usage

```tsx
// after: npx shadcn@latest add @signalos/relationships-01
// mount the pulled page in a route, e.g. src/app/semantics-details/page.tsx
import RelationshipReview from "@/components/blocks/relationships-01/RelationsShipReview"

export default function Page() {
  return <RelationshipReview />
}
```

## Props

### `SensitivityLevel`

```ts
export type SensitivityLevel =
  "none" | "low" | "medium" | "high" | "pii" | "phi"
```

### `RelationshipType`

```ts
export type RelationshipType =
  | "references"
  | "has_many"
  | "belongs_to"
  | "many_to_many"
  | "one_to_one"
  | "measures"
  | "targets"
  | "sponsors"
  | "conducted_at"
  | "co_occurs"
  | "related_to"
```

### `InternalRelationship`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `from_table` | `string` | yes | - |  |
| `from_column` | `string` | yes | - |  |
| `to_table` | `string` | yes | - |  |
| `to_column` | `string` | yes | - |  |
| `relationship_type` | `RelationshipType` | yes | - |  |
| `confidence` | `number` | yes | - |  |
| `detection_method` | `string` | yes | - |  |
| `explanation` | `string \| undefined` | no | - |  |
| `review_origin` | `string \| undefined` | no | - |  |

### `RelationshipReviewItem`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `index` | `number` | yes | - |  |
| `status` | `"accepted" \| "flagged" \| "deleted"` | yes | - |  |
| `feedback` | `string` | yes | - |  |
| `edits` | `Partial<InternalRelationship>` | yes | - |  |

### `RelationshipReviewDecision`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `status` | `"accepted" \| "flagged"` | yes | - |  |
| `feedback` | `string` | yes | - |  |
| `edits` | `Partial<InternalRelationship>` | yes | - |  |

### `FieldOverride`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `is_pii` | `boolean` | yes | - |  |
| `sensitivity` | `SensitivityLevel` | yes | - |  |

### `RelationshipAddValues`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `from_table` | `string` | yes | - |  |
| `from_column` | `string` | yes | - |  |
| `to_table` | `string` | yes | - |  |
| `to_column` | `string` | yes | - |  |
| `relationship_type` | `RelationshipType` | yes | - |  |
| `explanation` | `string \| undefined` | no | - |  |

### `RelationshipItemEdits`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `from_table` | `string` | yes | - |  |
| `from_column` | `string` | yes | - |  |
| `to_table` | `string` | yes | - |  |
| `to_column` | `string` | yes | - |  |
| `relationship_type` | `RelationshipType` | yes | - |  |
| `explanation` | `string \| undefined` | no | - |  |

### `SubmitRelationshipReviewPayload`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `"confirm" \| "retry" \| "add_item"` | yes | - |  |
| `items` | `RelationshipReviewItem[] \| undefined` | no | - |  |
| `field_overrides` | `Record<string, FieldOverride> \| undefined` | no | - |  |
| `connector_id` | `string \| undefined` | no | - |  |
| `item_edits` | `RelationshipAddValues \| undefined` | no | - |  |

### `AddRelationshipPayload`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `"add_item"` | yes | - |  |
| `connector_id` | `string` | yes | - |  |
| `feedback` | `string \| undefined` | no | - |  |
| `item_edits` | `RelationshipItemEdits` | yes | - |  |

### `AddRelationshipResponse`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `status` | `string \| undefined` | no | - |  |
| `index` | `number \| undefined` | no | - |  |
| `item` | `InternalRelationship \| undefined` | no | - |  |
| `soft_warning` | `string \| undefined` | no | - |  |

### `CreateInternalRelationshipPayload`

```ts
export type CreateInternalRelationshipPayload = InternalRelationship
```

### `RelationshipFdeInput`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `items` | `RelationshipReviewItem[]` | yes | - |  |

### `RelationshipGraphNode`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `label` | `string` | yes | - |  |
| `x` | `number` | yes | - |  |
| `y` | `number` | yes | - |  |
| `type` | `"table"` | yes | - |  |

### `RelationshipGraphEdge`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `from` | `string` | yes | - |  |
| `to` | `string` | yes | - |  |
| `label` | `string` | yes | - |  |
| `confidence` | `number` | yes | - |  |

### `SchemaColumn`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `column_name` | `string` | yes | - |  |
| `data_type` | `string` | yes | - |  |
| `is_primary_key` | `boolean \| undefined` | no | - |  |
| `semantic_label` | `string \| undefined` | no | - |  |
| `sensitivity` | `SensitivityLevel \| undefined` | no | - |  |

### `SchemaTable`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `table_name` | `string` | yes | - |  |
| `columns` | `SchemaColumn[]` | yes | - |  |

### `EditRelationshipFormState`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `from_table` | `string` | yes | - |  |
| `from_column` | `string` | yes | - |  |
| `to_table` | `string` | yes | - |  |
| `to_column` | `string` | yes | - |  |
| `relationship_type` | `RelationshipType` | yes | - |  |

### `AddRelationshipFormState`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `from_table` | `string` | yes | - |  |
| `from_column` | `string` | yes | - |  |
| `to_table` | `string` | yes | - |  |
| `to_column` | `string` | yes | - |  |
| `relationship_type` | `RelationshipType` | yes | - |  |
| `explanation` | `string` | yes | - |  |

### `AddRelationshipFormErrors`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `from_table` | `string \| undefined` | no | - |  |
| `from_column` | `string \| undefined` | no | - |  |
| `to_table` | `string \| undefined` | no | - |  |
| `to_column` | `string \| undefined` | no | - |  |

### `ResolvedColumnField`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `column_name` | `string` | yes | - |  |
| `data_type` | `string` | yes | - |  |
| `is_primary_key` | `boolean \| undefined` | no | - |  |
| `semantic_label` | `string \| undefined` | no | - |  |
| `sensitivity` | `SensitivityLevel` | yes | - |  |
| `isPii` | `boolean` | yes | - |  |
| `override` | `FieldOverride \| undefined` | yes | - |  |

## Changelog

## 0.4.8
- Global css update

## 0.4.7

- Replace raw scale token classes with semantic tokens (`text-text-error`, `bg-bg-error`, `border-border-warning`, `border-border-info`, etc.) in `RelationshipsFieldsPanel` and `RelationshipsQueue` to respect client theme overrides.

## 0.4.6

- Replace raw scale token classes with semantic tokens (text-text-error, bg-bg-success, border-border-warning, etc.) to respect client theme overrides.

## 0.4.5

- `RelationshipsHeader`: replace single Dismiss button in error banner with Retry + Dismiss pair; Retry calls `onSubmit`.
- `RelationshipsHeader`: add `data-testid="relationship-retry-button"` to the new Retry button.
- `EditRelationshipDialog`: replace plain `div` footer containers with `DialogFooter`; import `DialogFooter` from `@/components/ui/dialog`.
- `EditRelationshipDialog`: remove `contentClassName="max-h-[85vh] overflow-y-auto"` from `FormDialog`.
- `ERDiagram`: add `data-testid="er-diagram-canvas"` to the root container div.
- `RelationsShipReview`: remove `space-y-5` from the detail panel wrapper div.

## 0.4.4

- Wrap relationship queue item table and column labels in Tooltip so truncated names are fully visible on hover.

## 0.4.3

- Remove stray `DialogFooter` import from EditRelationshipDialog; replace with plain flex div since footer is already passed as ReactNode to FormDialog.
- Remove `@signalos/dialog` from registryDependencies — both dialogs use FormDialog only.

## 0.4.1

- Fix file casing: rename Relationships.types.ts to match PascalCase import paths.

## 0.4.0

- Fix ERDiagram to use controlled nodes/edges props directly on ReactFlow, removing useNodesState/useEdgesState which silently discarded prop updates after first render.

## 0.3.1
## 0.3.0

- Replace `grid grid-cols-1 lg:grid-cols-12` layout with `SplitPanel` widget for the list/detail split.
- Queue (`RelationshipsQueue`) moved to the `SplitPanel` list slot; ER diagram + fields panel moved to the detail slot.
- Add `@signalos/split-panel` to `registryDependencies`.

## 0.2.0

- Refactor: lift all business logic, form state, validation, and graph construction into `RelationshipReview` (parent).
- `EditRelationshipDialog` is now fully presentational — receives controlled form values, column lists, and validation flags via props.
- `RelationshipAddDialog` is now fully presentational — receives controlled form state, column lists, and validation errors via props.
- `ERDiagram` is now fully presentational — receives pre-built `nodes` and `edges` via props; graph construction moved to parent.
- `RelationshipsFieldsPanel` now receives `resolvedColumns` (pre-computed field overrides and PII status) instead of deriving them internally.
- Added `SchemaTable`, `SchemaColumn`, `EditRelationshipFormState`, `AddRelationshipFormState`, `AddRelationshipFormErrors`, and `ResolvedColumnField` to `Relationships.types.ts`.

## 0.1.0

- Initial release: Relationship Review block with ER diagram, field metadata panel, review queue, and add/edit dialogs.
- Dialogs use the `FormDialog` widget.
- All state and handler logic wired up in `RelationsShipReview`.
