Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
566458b
feat(01-02): add SSE connection limit (PERF-03) and catalog test scaf…
TerrifiedBug Mar 26, 2026
1a9302f
feat(01-01): remove per-heartbeat alert evaluation (PERF-01)
TerrifiedBug Mar 26, 2026
b36ddd7
chore(01-01): add PERF-02 traceability comment to SSE keepalive test
TerrifiedBug Mar 26, 2026
90f01d3
feat(01-02): convert VECTOR_CATALOG to lazy singleton getVectorCatalo…
TerrifiedBug Mar 26, 2026
53c7f85
Merge branch 'worktree-agent-a2e91437'
TerrifiedBug Mar 26, 2026
f5460a2
feat(02-01): Prisma schema -- NodeGroup model + PipelineGroup parentId
TerrifiedBug Mar 26, 2026
0e17072
feat(02-01): NodeGroup tRPC router with CRUD + registration + tests
TerrifiedBug Mar 26, 2026
d9fa94c
feat(02-01): label compliance in fleet.list + enrollment auto-assignm…
TerrifiedBug Mar 26, 2026
aac2744
feat(02-02): extend PipelineGroup router with parentId and 3-level de…
TerrifiedBug Mar 26, 2026
08a759b
feat(02-02): add bulkAddTags and bulkRemoveTags procedures to pipelin…
TerrifiedBug Mar 26, 2026
daa5197
feat(02-01): Prisma schema -- NodeGroup model + PipelineGroup parentId
TerrifiedBug Mar 26, 2026
734e1dc
feat(02-01): NodeGroup tRPC router with CRUD + registration + tests
TerrifiedBug Mar 26, 2026
15dac89
feat(02-01): label compliance in fleet.list + enrollment auto-assignm…
TerrifiedBug Mar 26, 2026
edd5831
feat(02-02): extend PipelineGroup router with parentId and 3-level de…
TerrifiedBug Mar 26, 2026
4d98390
feat(02-02): add bulkAddTags and bulkRemoveTags procedures to pipelin…
TerrifiedBug Mar 26, 2026
747f386
feat(02-03): node group management UI + label compliance badge
TerrifiedBug Mar 26, 2026
0ff6659
docs(02-03): add node groups and label compliance to fleet docs
TerrifiedBug Mar 26, 2026
a325f1a
feat(02-04): pipeline group sidebar tree, breadcrumbs, and nested mov…
TerrifiedBug Mar 26, 2026
f75263d
docs(02-03): complete node group management UI plan
TerrifiedBug Mar 26, 2026
9f23264
feat(02-04): add bulk Add Tags and Remove Tags to BulkActionBar
TerrifiedBug Mar 26, 2026
cc424c4
Merge branch 'worktree-agent-a2d1713f'
TerrifiedBug Mar 26, 2026
41473b2
Merge branch 'worktree-agent-a53aa658'
TerrifiedBug Mar 26, 2026
3624f44
chore: cherry-pick Phase 02 fleet-organization changes as worktree ba…
TerrifiedBug Mar 27, 2026
afe0b60
feat(03-01): groupHealthStats and nodesInGroup tRPC procedures + shar…
TerrifiedBug Mar 27, 2026
2476fd9
docs(03-01): complete groupHealthStats and nodesInGroup plan SUMMARY …
TerrifiedBug Mar 27, 2026
77dbc97
Merge branch 'worktree-agent-a3f6dc87'
TerrifiedBug Mar 27, 2026
218700b
chore: cherry-pick Phase 02 fleet-organization changes as worktree ba…
TerrifiedBug Mar 27, 2026
0b6e3f2
feat(03-01): groupHealthStats and nodesInGroup tRPC procedures + shar…
TerrifiedBug Mar 27, 2026
520d7f1
feat(03-02): fleet health dashboard UI with group cards, drill-down, …
TerrifiedBug Mar 27, 2026
1b931b0
docs(03-02): add fleet health dashboard section to public fleet docs
TerrifiedBug Mar 27, 2026
8d1f24c
docs(03-02): complete fleet health dashboard UI plan SUMMARY + STATE …
TerrifiedBug Mar 27, 2026
0e9ef5a
Merge branch 'worktree-agent-aa0b48c7'
TerrifiedBug Mar 27, 2026
49a7be2
feat(04-01): add WebhookEndpoint and WebhookDelivery Prisma models
TerrifiedBug Mar 27, 2026
7fb30a9
test(04-01): add failing tests for outbound webhook service
TerrifiedBug Mar 27, 2026
09e31b2
feat(04-01): implement outbound webhook service with Standard-Webhook…
TerrifiedBug Mar 27, 2026
891a903
docs(04-01): complete outbound webhook data layer and delivery servic…
TerrifiedBug Mar 27, 2026
b020270
Merge branch 'worktree-agent-a3243b17'
TerrifiedBug Mar 27, 2026
44e3cdf
feat(04-01): cherry-pick Prisma models and outbound webhook service f…
TerrifiedBug Mar 27, 2026
a7e9cb0
test(04-02): add failing tests for webhook endpoint router
TerrifiedBug Mar 27, 2026
f682fad
feat(04-02): add webhookEndpoint tRPC router with CRUD, test delivery…
TerrifiedBug Mar 27, 2026
84ed3f5
feat(04-02): wire outbound webhook dispatch into event alerts and ext…
TerrifiedBug Mar 27, 2026
5aae77e
Merge branch 'worktree-agent-a7b3e7f2'
TerrifiedBug Mar 27, 2026
58ba8e3
fix(04-02): guard processOutboundRetries against undefined webhookDel…
TerrifiedBug Mar 27, 2026
6adc601
feat(04-01): add WebhookEndpoint and WebhookDelivery Prisma models
TerrifiedBug Mar 27, 2026
046feb6
test(04-01): add failing tests for outbound webhook service
TerrifiedBug Mar 27, 2026
6b4c2f9
feat(04-01): implement outbound webhook service with Standard-Webhook…
TerrifiedBug Mar 27, 2026
36cfc46
test(04-02): add failing tests for webhook endpoint router
TerrifiedBug Mar 27, 2026
26b66cd
feat(04-02): add webhookEndpoint tRPC router with CRUD, test delivery…
TerrifiedBug Mar 27, 2026
c115268
feat(04-02): wire outbound webhook dispatch into event alerts and ext…
TerrifiedBug Mar 27, 2026
2be3f81
fix(04-02): guard processOutboundRetries against undefined webhookDel…
TerrifiedBug Mar 27, 2026
c6f98fd
feat(04-03): webhook endpoint management UI with delivery history
TerrifiedBug Mar 27, 2026
726de88
docs(04-03): add outbound webhooks operations guide
TerrifiedBug Mar 27, 2026
2ee31e6
fix(04-03): remove unused Switch import and eventLabels variable
TerrifiedBug Mar 27, 2026
3f39094
Merge branch 'worktree-agent-a6fe74c7'
TerrifiedBug Mar 27, 2026
4146389
merge: bring in outbound webhooks phase (04-01 through 04-03)
TerrifiedBug Mar 27, 2026
796d52f
feat(05-01): implement PromotionRequest model, promotion service, and…
TerrifiedBug Mar 27, 2026
76a8570
test(05-01): add unit tests for promotion router covering all critica…
TerrifiedBug Mar 27, 2026
e7ea7c9
Merge branch 'worktree-agent-a2761ebd'
TerrifiedBug Mar 27, 2026
699b0a5
feat(05-02): replace PromotePipelineDialog with multi-step promotion …
TerrifiedBug Mar 27, 2026
4ad3d09
feat(05-02): add PromotionHistory to pipeline detail page and update …
TerrifiedBug Mar 27, 2026
e27fb58
docs(05-02): complete cross-environment promotion UI plan
TerrifiedBug Mar 27, 2026
88bd16d
feat(06-01): define OpenAPI 3.1 spec with Zod schemas for all 16 REST…
TerrifiedBug Mar 27, 2026
eb1f345
feat(06-01): add OpenAPI spec serving endpoint and build-time generat…
TerrifiedBug Mar 27, 2026
3231d3a
Merge branch 'worktree-agent-a1b81ee7'
TerrifiedBug Mar 27, 2026
15ad196
feat(06-02): add tRPC procedure entries to OpenAPI spec
TerrifiedBug Mar 27, 2026
b36b1c5
feat(06-02): update generation script summary and add OpenAPI docs se…
TerrifiedBug Mar 27, 2026
7540eae
docs(06-02): complete OpenAPI tRPC spec and docs plan
TerrifiedBug Mar 27, 2026
ccd8004
chore(06): install @asteasolutions/zod-to-openapi and resolve merge c…
TerrifiedBug Mar 27, 2026
e4fd5a1
chore(07-01): install @octokit/rest and extend Prisma schema for GitO…
TerrifiedBug Mar 27, 2026
cb6b222
feat(07-01): create gitops-promotion service with createPromotionPR u…
TerrifiedBug Mar 27, 2026
01ed60f
feat(07-01): extend promotion router with GitOps initiation path
TerrifiedBug Mar 27, 2026
a0795ac
feat(07-01): extend git webhook handler for PR merge events
TerrifiedBug Mar 27, 2026
f817f72
feat(07-03): add promotion gitOpsMode to environment router
TerrifiedBug Mar 27, 2026
93c5ebf
feat(07-03): add GitOps promotion mode to GitSyncSection with setup g…
TerrifiedBug Mar 27, 2026
2394b37
docs(07-03): complete GitOps setup wizard UI plan
TerrifiedBug Mar 27, 2026
9ddfd8c
chore: remove .planning files from tracking
TerrifiedBug Mar 27, 2026
1aaec03
fix: resolve security and webhook contract issues from PR review
TerrifiedBug Mar 27, 2026
933bffd
Merge branch 'main' into feat/m016-enterprise-scale
TerrifiedBug Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/public/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* [Service Accounts](operations/service-accounts.md)
* [Backup & Restore](operations/backup-restore.md)
* [GitOps](operations/gitops.md)
* [Outbound Webhooks](operations/outbound-webhooks.md)
* [Security](operations/security.md)
* [Upgrading](operations/upgrading.md)

Expand Down
154 changes: 154 additions & 0 deletions docs/public/operations/outbound-webhooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Outbound Webhooks

VectorFlow can send HMAC-signed HTTP notifications to external systems when key events occur. Use outbound webhooks to integrate with incident management tools, CI/CD pipelines, custom dashboards, or any service that accepts HTTP callbacks.

## Overview

Each **webhook endpoint** is a URL that receives POST requests when one or more subscribed events fire. Requests carry Standard-Webhooks-compliant signature headers so receivers can verify authenticity.

Key properties of each endpoint:

- **Name** — A descriptive label shown in the management UI.
- **URL** — The HTTPS endpoint that receives event payloads.
- **Event types** — One or more event types that trigger delivery.
- **Signing secret** — Optional HMAC key. When set, every request includes a `webhook-signature` header.
- **Enabled / Disabled** — Endpoints can be temporarily disabled without deleting them.

## Supported events

| Event | When it fires |
|-------|---------------|
| `deploy_completed` | A pipeline deployment completed successfully |
| `deploy_rejected` | A deployment request was rejected |
| `deploy_cancelled` | A pending deployment was cancelled |
| `pipeline_crashed` | A running pipeline process exited unexpectedly |
| `node_unreachable` | A fleet node stopped sending heartbeats |
| `node_joined` | A new fleet node enrolled |
| `node_left` | A fleet node was removed |
| `promotion_completed` | A pipeline was promoted to another environment |

## Creating a webhook endpoint

{% stepper %}
{% step %}
### Open Webhook Settings
Navigate to **Settings → Outbound Webhooks**.
{% endstep %}
{% step %}
### Click New Endpoint
Click the **New Endpoint** button in the top-right corner.
{% endstep %}
{% step %}
### Fill in the form
- **Name** — A descriptive label (e.g., "PagerDuty Pipeline Alerts").
- **Endpoint URL** — The HTTPS URL that will receive events.
- **Signing secret** — Optional. If provided, every request is signed and the secret is shown once — copy it before closing the dialog.
- **Event types** — Select one or more events this endpoint should receive.
{% endstep %}
{% step %}
### Create
Click **Create**. If you provided a signing secret, the dialog shows it once — copy it to a secure location.
{% endstep %}
{% endstepper %}

{% hint style="warning" %}
The signing secret is displayed once at creation time and cannot be retrieved afterwards. Store it securely in your receiving application's configuration.
{% endhint %}

## Payload format

All webhook deliveries use the same envelope format:

```json
{
"type": "deploy_completed",
"timestamp": "2026-03-27T12:00:00.000Z",
"data": {
// Event-specific fields
}
}
```

| Field | Description |
|-------|-------------|
| `type` | The `AlertMetric` value that triggered this delivery |
| `timestamp` | ISO-8601 UTC timestamp of the event |
| `data` | Event-specific payload fields |

## Verifying signatures

When a signing secret is configured, every request includes three headers:

| Header | Description |
|--------|-------------|
| `webhook-id` | Unique UUID for this delivery |
| `webhook-timestamp` | Unix timestamp (integer seconds) |
| `webhook-signature` | `v1,{base64(HMAC-SHA256)}` |

To verify a request, compute:

```
signing_string = "{webhook-id}.{webhook-timestamp}.{raw_request_body}"
expected_sig = base64( HMAC-SHA256(signing_string, secret) )
```

The received signature header is `v1,{expected_sig}`. Compare the value after the `v1,` prefix.

{% hint style="info" %}
VectorFlow follows the [Standard Webhooks](https://www.standardwebhooks.com/) specification. Libraries are available for most languages.
{% endhint %}

## Delivery and retry

VectorFlow attempts delivery immediately when an event fires. If the request fails, it retries with exponential backoff:

| Attempt | Delay |
|---------|-------|
| 1 | Immediate |
| 2 | 30 seconds |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5+ | 2 hours |

**Permanent failures** (HTTP 4xx excluding 429, DNS errors, connection refused) are moved to **dead-letter** immediately and are not retried.

**Transient failures** (HTTP 5xx, HTTP 429, timeouts) are retried up to the schedule above.

## Delivery history

Each endpoint row in the settings UI can be expanded to show recent deliveries:

- **Event type** — Which event triggered the delivery.
- **Status** — `success`, `failed`, `dead_letter`, or `pending`.
- **HTTP status** — The HTTP status code returned by the receiver.
- **Attempt** — Which retry attempt this represents.
- **Requested / Completed** — Relative timestamps.

## Test delivery

To send a test delivery to an endpoint without waiting for a real event, click the **Play** button (▶) in the endpoint row. The test payload is:

```json
{
"type": "test",
"timestamp": "2026-03-27T12:00:00.000Z",
"data": {
"message": "Test delivery from VectorFlow",
"endpointId": "..."
}
}
```

The UI shows a success or failure notification. Check delivery history for the HTTP status code and any error details.

## Managing endpoints

| Action | How |
|--------|-----|
| **Enable / Disable** | Click the toggle icon in the endpoint row |
| **Edit** | Click the pencil icon to update name, URL, events, or rotate the secret |
| **Delete** | Click the trash icon — all delivery history is also deleted |

{% hint style="info" %}
Disabling an endpoint stops deliveries immediately without deleting the endpoint or its history. Re-enable it when ready to receive events again.
{% endhint %}
44 changes: 44 additions & 0 deletions docs/public/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,50 @@ Common error codes:

---

## OpenAPI Specification

VectorFlow provides a machine-readable [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0) specification covering all REST v1 endpoints and key tRPC procedures.

### Fetching the spec

```bash
curl -s https://vectorflow.example.com/api/v1/openapi.json | jq .info
```

The spec is served at `/api/v1/openapi.json` with CORS enabled — you can fetch it from any origin without credentials.

### Importing into tools

**Postman:** File > Import > paste URL `https://vectorflow.example.com/api/v1/openapi.json`

**Swagger UI / Stoplight:** Point to the spec URL or paste the JSON content.

### Client generation

Generate a typed API client in any language using [openapi-generator](https://openapi-generator.tech/):

```bash
npx @openapitools/openapi-generator-cli generate \
-i https://vectorflow.example.com/api/v1/openapi.json \
-g python \
-o ./vectorflow-client
```

### What's included

The spec documents two API surfaces:

| Surface | Auth | Endpoints |
|---------|------|-----------|
| REST v1 (`/api/v1/*`) | Service account Bearer token | Pipeline CRUD, deploy, rollback, nodes, secrets, alerts, audit |
| tRPC (`/api/trpc/*`) | Session cookie | Pipeline management, fleet, environments, secrets, deploy, alerts, service accounts |

{% hint style="info" %}
**tRPC encoding note:** tRPC endpoints use [SuperJSON](https://github.com/blitz-js/superjson) encoding. For queries, input is URL-encoded JSON in `?input=` (wrap as `{"json": <input>}`). For mutations, the body is `{"json": <input>}`. Using a tRPC client is recommended for full type safety; the OpenAPI spec is provided for discoverability and non-TypeScript integrations.
{% endhint %}

---

## REST API (v1)

The REST API provides a standard HTTP interface for automation and CI/CD. All endpoints require a [Service Account](../operations/service-accounts.md) API key.
Expand Down
69 changes: 69 additions & 0 deletions docs/public/user-guide/fleet.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,75 @@ The deploy dialog shows a live count of matching nodes (e.g., "3 of 5 nodes matc
Changing a pipeline's node selector on a subsequent deploy updates the targeting. Nodes that no longer match will stop the pipeline on their next poll.
{% endhint %}

## Node groups

Node groups let administrators segment their fleet into logical clusters based on node labels -- for example by datacenter, role, or region. Groups are managed from **Settings > Fleet**.

Each node group has:

| Field | Description |
|-------|-------------|
| **Name** | A unique display name for the group within the environment. |
| **Criteria** | A label selector (key-value pairs) that determines which enrolling nodes match the group. An empty criteria matches all nodes. |
| **Label template** | Key-value labels that are automatically merged into a node's labels when it enrolls and matches the group's criteria. |
| **Required labels** | Label keys that every node should have. Nodes missing any required label are flagged as non-compliant in the fleet list. |

{% hint style="info" %}
Label templates are applied once at enrollment time. Changing a group's template does not retroactively update existing nodes.
{% endhint %}

## Label compliance

When node groups define **required labels**, the fleet list displays a **Non-compliant** badge next to any node that is missing one or more of those labels. This is a warn-only indicator -- non-compliant nodes continue to receive heartbeats and deployments normally.

To resolve a non-compliant node, add the missing labels via the node detail page or ensure the node enrolls with matching labels so that group templates apply automatically.

## Fleet health dashboard

The Health tab on the Fleet page provides an aggregated view of fleet status organized by node group. This is especially useful for large fleets where you want to see health at a glance before drilling into individual nodes.

### Group summary cards

Each node group is represented as a collapsible card showing three metrics:

| Metric | Description |
|--------|-------------|
| **Online** | Count of HEALTHY nodes out of the group total (e.g. `4/5`). Shown in amber when any nodes are offline. |
| **Alerts** | Count of nodes with at least one firing alert rule. Shown in red when greater than zero. |
| **Compliance** | Percentage of nodes that have all required labels defined by the group. Shown in amber when below 100%. |

### Drill-down

Click any group card to expand it and see a per-node detail table with:

- **Name** — the node name, linked to its detail page
- **Status** — current health status badge (Healthy, Degraded, Unreachable, Unknown)
- **CPU Load** — the 1-minute load average from the latest heartbeat, or `--` if no metrics are available
- **Last Seen** — how long ago the node last sent a heartbeat
- **Compliance** — whether the node has all required labels for the group

Nodes are sorted by health status with the least healthy nodes shown first, then alphabetically by name.

### Filtering

The toolbar above the group cards supports three filter types:

- **Group** — show only a specific group card
- **Labels** — filter by label key/value pairs (applied to the per-node detail table inside expanded cards)
- **Compliance** — toggle between All, Compliant (100% compliance rate), or Non-compliant (below 100%)

{% hint style="info" %}
Filter state is stored in the URL as query parameters, so you can copy and share the URL with filters applied.
{% endhint %}

### Ungrouped nodes

Nodes that do not match the criteria of any defined group appear under an **Ungrouped** card. This card behaves the same as any other group card — you can expand it to see the per-node table.

{% hint style="info" %}
The Ungrouped card only appears when at least one node exists outside all group criteria. If all nodes belong to a group, no Ungrouped card is shown.
{% endhint %}

## Maintenance mode

Maintenance mode lets you temporarily stop all pipelines on a node without removing it from the fleet. This is useful for host upgrades, kernel patches, disk maintenance, or any situation where you need the node idle but still connected.
Expand Down
26 changes: 26 additions & 0 deletions docs/public/user-guide/pipeline-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,32 @@ Click the pipeline name in the top-left corner of the editor to rename it inline
On Windows and Linux, use `Ctrl` instead of `Cmd` for all keyboard shortcuts.
{% endhint %}

## Cross-Environment Promotion

Promote a pipeline from one environment to another (e.g., dev to staging, staging to production) with built-in validation and approval workflow.

### Promoting a Pipeline

1. From the pipeline list, click the **...** menu on any pipeline and select **Promote to...**
2. Select the **target environment** and optionally rename the pipeline
3. VectorFlow validates that all secret references in the pipeline exist in the target environment
4. Review the **substitution diff** showing what will change between environments
5. Click **Confirm Promotion** to submit

### Approval Workflow

If the target environment has **Require Deploy Approval** enabled, the promotion creates a request that must be approved by an administrator before the pipeline appears in the target environment.

If approval is not required, the pipeline is promoted immediately.

### Secret Pre-flight Validation

Before promotion proceeds, VectorFlow checks that every `SECRET[name]` reference in the source pipeline has a corresponding secret defined in the target environment. If any secrets are missing, promotion is blocked with a clear list of which secrets need to be created.

### Promotion History

Each pipeline's detail page shows a promotion history log with source environment, target environment, who promoted, and the current status.

## AI-Powered Suggestions

When AI is configured for your team (Settings → AI), two AI features become available:
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
"start": "next start",
"lint": "eslint",
"test": "vitest run",
"postinstall": "prisma generate"
"postinstall": "prisma generate",
"generate:openapi": "tsx scripts/generate-openapi.ts"
},
"dependencies": {
"@auth/prisma-adapter": "^2.11.1",
"@dagrejs/dagre": "^2.0.4",
"@hookform/resolvers": "^5.2.2",
"@monaco-editor/react": "^4.7.0",
"@octokit/rest": "^22.0.1",
"@prisma/adapter-pg": "^7.4.2",
"@prisma/client": "^7.4.2",
"@prisma/client-runtime-utils": "^7.4.2",
Expand Down Expand Up @@ -68,6 +70,7 @@
}
},
"devDependencies": {
"@asteasolutions/zod-to-openapi": "^8.5.0",
"@next/bundle-analyzer": "^16.2.1",
"@tailwindcss/postcss": "^4",
"@types/bcryptjs": "^3.0.0",
Expand Down
Loading
Loading