Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A plugin marketplace for Claude Code, organized by persona. Install only the plugin relevant to you.

Docs: https://developer.rhombus.com/claude-code-plugins · Support: support@rhombus.com

## Quick Start

### 1. Add the marketplace
Expand Down
4 changes: 2 additions & 2 deletions plugins/developer/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "rhombus-developer",
"description": "Build on Rhombus. Auto-configures the official rhombus-node-mcp and docs.rhombus.community MCP servers. Ships six /rhombus-* commands (find-endpoint, schema, curl, sdk, mcp-status, newproject), API-architect and webhook-debugger agents, and five skills covering full API reference (892+ endpoints including Relay/NVR and third-party RTSP), SDK codegen, webhook scaffolding, code review, API doc generation, and edge streaming (RTSP/ONVIF).",
"version": "2.0.0",
"description": "Build on Rhombus. Auto-configures the official rhombus-node-mcp and the Rhombus docs MCP servers. Ships six /rhombus-* commands (find-endpoint, schema, curl, sdk, mcp-status, newproject), API-architect and webhook-debugger agents, and five skills covering full API reference (980+ endpoints including Relay/NVR and third-party RTSP), SDK codegen, webhook scaffolding, code review, API doc generation, and edge streaming (RTSP/ONVIF). Docs: https://developer.rhombus.com",
"version": "2.0.1",
"author": { "name": "Rhombus" },
"hooks": {
"SessionStart": [
Expand Down
11 changes: 8 additions & 3 deletions plugins/developer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Tools for engineers building on the Rhombus platform. Version **2.0.0**.

The plugin wires MCP servers automatically via `.mcp.json`. You only need:

1. **`RHOMBUS_API_KEY`** exported in the shell that launches Claude Code (generate from Rhombus Console → API Key Settings).
1. **`RHOMBUS_API_KEY`** exported in the shell that launches Claude Code. Create it in the Rhombus Console under **Settings → Integrations & Developer Resources → API Tokens → Add API Key** with Auth Type **Api Token** (partner organizations: **Settings → API Management → Add API Key**).
2. **Node 18+** on PATH so `npx` can fetch `rhombus-node-mcp` on first run.

Verify with `/rhombus-mcp-status`.
Expand All @@ -40,10 +40,10 @@ Verify with `/rhombus-mcp-status`.

| Skill | Triggers when user asks about |
|---|---|
| `rhombus-api` | Rhombus API, endpoints, cURL, any "how do I build X on Rhombus" question (covers 892+ endpoints inc. Relay/NVR + third-party RTSP) |
| `rhombus-api` | Rhombus API, endpoints, cURL, any "how do I build X on Rhombus" question (covers 980+ endpoints inc. Relay/NVR + third-party RTSP) |
| `rhombus-sdk-codegen` | Scaffolding typed SDK clients (Python, TS, Java, Go, C#) |
| `rhombus-webhook-receiver` | Building webhook listeners (Express, FastAPI, Lambda) |
| `rhombus-edge-streaming` | RTSP, ONVIF, Secure Raw Streams, custom seekpoints, embedded player |
| `rhombus-edge-streaming` | RTSP, ONVIF, Secure Raw Streams, custom seekpoints, LAN streaming, embedded player |
| `code-review` | Generic code review |
| `api-doc` | Generic API doc generation |

Expand All @@ -54,6 +54,11 @@ Verify with `/rhombus-mcp-status`.
| `rhombus-api-intercept` | PreToolUse (Bash) | Suggests MCP tool → CLI → cURL order when raw Rhombus HTTP calls are detected |
| `rhombus-openapi-freshness.sh` | SessionStart | Warns if bundled OpenAPI spec is >90 days old |

## Docs and support

- Developer docs: https://developer.rhombus.com
- Support: support@rhombus.com

## Typical workflow

```
Expand Down
14 changes: 8 additions & 6 deletions plugins/developer/agents/rhombus-api-architect.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ description: >-
Slack incoming webhook) and recommend architecture trade-offs.</example>
<example>PR review — user submits a PR that polls door events every 30
seconds. The architect should flag that polling is an anti-pattern when
webhooks exist and recommend switching to the Developer Webservice webhook
pattern.</example>
webhooks exist and recommend switching to an organization webhook or a rule
webhook action.</example>
tools: Read, Grep, Glob, Bash
color: "#8E44AD"
---
Expand All @@ -28,7 +28,7 @@ You are a Rhombus API integration architect. You design end-to-end integrations
- CLI (for one-shot scripts, bulk ops, developer workflows)
- Direct API call via typed SDK (for production services)
3. **Chain endpoints with data flow.** Identify UUIDs returned by one call that feed the next. Flag any pagination, rate-limit, or long-running-operation concerns.
4. **Call out anti-patterns.** Common ones on Rhombus: polling when a webhook exists, fetching full camera state when `getMinimal*` suffices, embedding API keys in browser apps instead of using federated session tokens, ignoring the 1,000 req/hr rate limit.
4. **Call out anti-patterns.** Common ones on Rhombus: polling when a webhook exists, fetching full camera state when `getMinimal*` suffices, embedding API keys in browser apps instead of minting federated tokens (`x-auth-scheme: federated-token` + `x-auth-ft`), ignoring the per-organization rate limit (one token bucket shared by every API key and OAuth token in the org, per-second refill with roughly 10x burst; see https://developer.rhombus.com/rate-limits).
5. **Recommend reference repos.** For common integration shapes, point the user at the closest matching example under `RhombusSystems/*` — see `plugins/developer/skills/rhombus-api/references/examples-index.md`.

## Process
Expand All @@ -37,7 +37,7 @@ You are a Rhombus API integration architect. You design end-to-end integrations
2. Use `mcp__rhombus-docs__search-documentation` (if attached) or grep the local OpenAPI spec to enumerate candidate endpoints.
3. Draw the data flow. Use a simple sequence diagram in text:
```
[External event] → webhook → your listener → validates → mcp__rhombus__getClip → your store
[Rhombus event] → webhook → your listener → verifies signature → POST /api/event/getPolicyAlertDetails (alertUuid) → your store
```
4. Flag constraints: auth, rate limits, latency budget, failure modes.
5. Recommend a next action: "Run `/rhombus-newproject <language> <feature>` to scaffold this", or "Open `rhombus-webhook-receiver` skill to generate the listener."
Expand Down Expand Up @@ -66,6 +66,8 @@ Provide a structured recommendation:

## Edge cases

- If the workflow requires browser-side Rhombus calls, always recommend the federated session token pattern and a server-side proxy — never embed API keys client-side.
- If the workflow volume exceeds 1,000 req/hr, recommend event-driven webhooks over polling.
- If the workflow requires browser-side Rhombus calls, always recommend minting a federated token on the server (`POST /api/org/generateFederatedSessionToken`) and sending it as `x-auth-scheme: federated-token` + `x-auth-ft` — never embed API keys client-side.
- If the workflow streams from devices on the customer's LAN, use device-scoped federated tokens (`deviceUUid`); LAN devices never accept API keys.
- Rate limits are per organization, not per key: adding API keys doesn't add throughput. If polling would compete with the organization's other integrations for that budget, recommend event-driven webhooks over polling.
- If the organization is in the EU region, every host changes (API base URL `https://api2.eu.rhombussystems.com`), and API keys only work in their own region.
- If the user is integrating with a system Rhombus already has a direct integration for (PagerDuty, ServiceNow, OAuth providers, Zapier, Make.com), point them at the existing integration first.
50 changes: 32 additions & 18 deletions plugins/developer/agents/rhombus-webhook-debugger.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ description: >-
configuration check, delivery-log inspection, signature verification, and
payload validation.</example>
<example>User reports signature mismatch errors for Rhombus webhook payloads.
The agent runs the signature-verification checklist (raw-body vs parsed-JSON,
HMAC-SHA256 construction, constant-time compare, clock skew).</example>
The agent runs the signature-verification checklist (raw body vs parsed JSON,
which header is present (x-rhombus-signature-sha1 or -sha256), HMAC
algorithm, per-URL secret, lowercase hex, constant-time compare).</example>
tools: Read, Bash
color: "#D35400"
---
Expand All @@ -21,38 +22,51 @@ You are a Rhombus webhook troubleshooter. Your job: take a "my webhook isn't wor

Walk through these in order. Stop at the first failure.

First identify which kind of webhook the user has. They differ in setup, body and signature:

| | Organization webhook | Rule webhook action |
|---|---|---|
| Set up in | Console **Settings → Integrations & Developer Resources → Webhooks** (Activity or Diagnostic) | A rule's webhook action |
| Signature header | `x-rhombus-signature-sha1` (HMAC-SHA1) | `x-rhombus-signature-sha256` (HMAC-SHA256) |
| Secret | **Webhook Secret** column in the Console, or `webhookSecret` from the API | `webhookSecrets` map returned by `createRule` / `updateRule` |

### 1. Is the webhook configured?
Via MCP (`mcp__rhombus__*` Developer Webservice tool) or CLI:
Via the Console (**Settings → Integrations & Developer Resources → Webhooks**), or the CLI:

```bash
rhombus developer get-webhooks
rhombus webhook-integrations get-webhook-integration # organization webhooks
rhombus rules get-rules-for-org # rules and their webhook actions
```

Confirm the target URL, event types, and active status. A common failure is a webhook created for only specific event types that don't match what the user is testing with.
(API equivalents: `POST /api/integrations/webhooks/getWebhookIntegration`, `POST /api/rules/getRulesForOrg`.)

For an organization webhook, confirm the URL is listed under the right trigger type (`activityWebhooksV2` for Activity, `diagnosticWebhooksV2` for Diagnostic), that `webhookDisabled` isn't true, and that the webhook integration itself is enabled. For a rule webhook action, confirm the rule is enabled and its triggers match what the user is testing with.

### 2. Is the listener actually reachable from the internet?
- Probe with `curl -X POST <user's webhook URL> -d '{}'` from somewhere external.
- Probe with `curl -X POST <user's webhook URL> -H 'Content-Type: application/json' -d '{}'` from somewhere external.
- If the listener is behind a tunnel (ngrok, cloudflared), confirm the tunnel is up.
- Check the listener logs for *any* requests at all — if none are arriving, the problem is network-side.

### 3. Is Rhombus attempting delivery?
Check the developer webhook delivery log via the API (Developer Webservice endpoints). Look for:
- Delivery attempts with non-2xx response codes → listener is rejecting.
- No delivery attempts at all → event may not match webhook filters.
Rhombus doesn't retry failed deliveries; it records them as diagnostics in the organization. Look for a "Custom Webhook" notification failure (organization webhooks; try `POST /api/report/getIntegrationDiagnosticEvents` with `timestampMsAfter` / `timestampMsBefore`) or `EXTERNAL_WEBHOOK_FAILURE` (rule webhook actions; try `POST /api/report/getDiagnosticFeed`).
- Failures present → the listener is rejecting or timing out. Rule webhook actions treat only `200` and `202` as success.
- No failures and no requests → the event didn't match the webhook's trigger type or the rule's triggers.

### 4. Is the payload shape what the listener expects?
Rhombus payloads vary by event type. Refer to `plugins/developer/skills/rhombus-webhook-receiver/references/webhook-payloads.md` for known shapes. Common mistake: treating all events as having the same `cameraUuid` field — some events (door, user) use different identifier fields.
Organization webhooks and rule webhook actions send different bodies. Refer to `plugins/developer/skills/rhombus-webhook-receiver/references/webhook-payloads.md`. Common mistakes: expecting a `type` or `eventUuid` field on an organization webhook (it sends `activityTrigger` / `diagnosticTrigger` and `alertUuid`), treating `location` as a name (it's a location UUID), or assuming every event is from a camera (check `deviceType`).

### 5. Is signature verification failing?
- Rhombus signs webhook payloads with a secret configured at webhook creation.
- Compute HMAC-SHA256 of the raw request body (bytes, not parsed JSON) using the secret.
- Compare constant-time to the `X-Rhombus-Signature` (or equivalent) header.
- Common mistake: verifying after the JSON middleware has re-serialized the body. You must use the raw body bytes.
- Read the header that's present: `x-rhombus-signature-sha1` (organization webhooks, HMAC-SHA1) or `x-rhombus-signature-sha256` (rule webhook actions, HMAC-SHA256). Rhombus sends no other signature header and no delivery-ID header.
- Compute the HMAC over the raw request body bytes (not parsed and re-serialized JSON), keyed with the secret string as-is (UTF-8; don't base64-decode it), and hex-encode it in lowercase.
- Use the secret for **that** URL: every webhook URL has its own secret.
- Compare in constant time (`crypto.timingSafeEqual` after a length check, or `hmac.compare_digest`).
- A rule webhook action created before signing was available has no secret and arrives unsigned; updating the rule assigns one.
- Check the implementation with the test vector: secret `AAAAAAAAAAAAAAAAAAAAAA`, body `{"version":"2","summary":"Test webhook"}` → SHA1 `7c67f32d7b1320f76fa6d171a1a54dd6808570b6`, SHA256 `5d3808f7c72ed8b6e52c12cf3ae13e72667d316178c6110081d58282828b2482`.

### 6. Are there duplicates?
Rhombus may retry deliveries. Listeners must be idempotent:
- Dedupe by the event's unique UUID (`eventUuid` or `uuid`).
- Return 2xx quickly (<5s) to avoid timeout-driven retries.
Listeners should still be idempotent:
- Dedupe by `alertUuid` (organization webhooks) or `uuid` (rule webhook actions).
- Return `200` quickly and do heavy work asynchronously.

## Output format

Expand All @@ -72,5 +86,5 @@ After diagnosis, produce:
## Edge cases

- If the user has no webhook yet, redirect to the `rhombus-webhook-receiver` skill to scaffold one.
- If the user's issue is latency (>30s delivery), that is a platform concern — direct them to `api@rhombus.com`.
- If the user's issue is latency (>30s delivery), that is a platform concern — direct them to `support@rhombus.com`.
- Do not ask the user for their API key or webhook secret; instruct them to check locally.
4 changes: 2 additions & 2 deletions plugins/developer/commands/rhombus-curl.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ argument-hint: "[operationId]"
Emit a runnable cURL command for the Rhombus API endpoint with operationId `$ARGUMENTS`.

1. Resolve the endpoint path and request schema using `/rhombus-schema $ARGUMENTS` (or the docs MCP if attached).
2. Produce the cURL in this exact shape:
2. Produce the cURL in this exact shape (for an EU organization, use the host `https://api2.eu.rhombussystems.com`):

```bash
curl -X POST "https://api2.rhombussystems.com/api/<path>" \
Expand All @@ -25,4 +25,4 @@ curl -X POST "https://api2.rhombussystems.com/api/<path>" \
- Required fields populated with realistic example values (base64 url-safe UUIDs like `AAAAAAAAAAAAAAAAAAAAAA`, millisecond epoch timestamps like `1234567890000`)
- Optional fields included in a trailing comment for discoverability

4. If the user probably wanted to *run* the call rather than copy a shell example, remind them: *"If you want to execute this, `mcp__rhombus__<operationId>` handles auth and typing for you."*
4. If the user probably wanted to *run* the call rather than copy a shell example, remind them that the `rhombus` MCP tools (`mcp__rhombus__*`, see `skills/rhombus-api/references/mcp-tool-reference.md`) or the `rhombus` CLI handle auth for them.
2 changes: 2 additions & 0 deletions plugins/developer/commands/rhombus-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ openapi-generator-cli generate \
-o <output-dir>
```

For EU organizations, set the generated client's base URL to `https://api2.eu.rhombussystems.com` (the spec's `servers` entry is the US host).

Prerequisites check:
- `openapi-generator-cli` available on PATH (`which openapi-generator-cli`)
- Network access to `api2.rhombussystems.com`
Expand Down
4 changes: 2 additions & 2 deletions plugins/developer/hooks/rhombus-api-intercept.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ type: prompt

Inspect the bash command about to be executed. If it contains a `curl`, `wget`, or `fetch` call targeting any of these Rhombus API domains:

- `api2.rhombussystems.com`
- `api2.rhombussystems.com` (EU: `api2.eu.rhombussystems.com`)
- `api.rhombussystems.com`
- `media.rhombussystems.com`
- `media.rhombussystems.com` (EU: `media.eu.rhombussystems.com`)
- `auth.rhombussystems.com`

Then surface a suggestion in this priority order (do NOT block — only suggest):
Expand Down
2 changes: 1 addition & 1 deletion plugins/developer/skills/api-doc/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Generate clear, complete API documentation from source code.

For each endpoint, document:

- **Method & Path**: `GET /api/v1/users/:id`
- **Method & Path**: `GET /v1/users/:id`
- **Description**: What this endpoint does (infer from handler logic and naming)
- **Authentication**: Required auth (check for auth middleware/decorators)
- **Parameters**: Path params, query params, headers
Expand Down
Loading
Loading