mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
improvement(access-controls): docs, terminology, fix delete bug (#5141)
* improvement(access-controls): dedup independent block names * improvement(access-controls): fix delete button, naming in perm group modal
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Webhook
|
||||
description: The Webhook block sends an HTTP POST to an external endpoint, with automatic headers and optional signing.
|
||||
title: Outgoing Webhook
|
||||
description: The Outgoing Webhook block sends an HTTP POST to an external endpoint, with automatic headers and optional signing.
|
||||
pageType: reference
|
||||
---
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { BlockPreview, WorkflowPreview, WEBHOOK_NOTIFY_WORKFLOW, WEBHOOK_TRIGGER_WORKFLOW } from '@/components/workflow-preview'
|
||||
import { FAQ } from '@/components/ui/faq'
|
||||
|
||||
The Webhook block sends HTTP POST requests to external webhook endpoints with automatic webhook headers and optional HMAC signing.
|
||||
The Outgoing Webhook block sends HTTP POST requests to external webhook endpoints with automatic webhook headers and optional HMAC signing.
|
||||
|
||||
<BlockPreview type="webhook" />
|
||||
|
||||
@@ -77,16 +77,16 @@ Format the result, then POST it to a Slack, Discord, or custom endpoint.
|
||||
|
||||
<WorkflowPreview workflow={WEBHOOK_TRIGGER_WORKFLOW} />
|
||||
|
||||
When the Condition passes, the Webhook starts a process in another system.
|
||||
When the Condition passes, the Outgoing Webhook starts a process in another system.
|
||||
|
||||
<Callout>
|
||||
The Webhook block always uses POST. For other HTTP methods or more control, use the [API block](/workflows/blocks/api).
|
||||
The Outgoing Webhook block always uses POST. For other HTTP methods or more control, use the [API block](/workflows/blocks/api).
|
||||
</Callout>
|
||||
|
||||
<FAQ items={[
|
||||
{ question: "Can I use HTTP methods other than POST?", answer: "No. The Webhook block always sends POST requests. If you need GET, PUT, DELETE, or PATCH, use the API block instead, which supports all standard HTTP methods." },
|
||||
{ question: "Can I use HTTP methods other than POST?", answer: "No. The Outgoing Webhook block always sends POST requests. If you need GET, PUT, DELETE, or PATCH, use the API block instead, which supports all standard HTTP methods." },
|
||||
{ question: "How does HMAC payload signing work?", answer: "When you provide a signing secret, the block generates an HMAC-SHA256 signature of the payload and includes it in the X-Webhook-Signature header in the format t=timestamp,v1=signature. The receiver can verify by computing HMAC-SHA256(secret, \"timestamp.body\") and comparing with the v1 value." },
|
||||
{ question: "What headers are added automatically?", answer: "Every webhook request automatically includes Content-Type (application/json), X-Webhook-Timestamp (Unix timestamp in milliseconds), X-Delivery-ID (unique UUID), and Idempotency-Key (same as X-Delivery-ID for deduplication)." },
|
||||
{ question: "Can custom headers override the automatic ones?", answer: "Yes. Any custom headers you define in the Additional Headers section will override automatic headers that share the same name." },
|
||||
{ question: "How is the Webhook block different from the API block?", answer: "The Webhook block is purpose-built for webhook delivery: it is POST-only, automatically adds webhook-specific headers (timestamp, delivery ID, idempotency key), and supports optional HMAC signing. The API block is more general-purpose with support for all HTTP methods, query parameters, and configurable retries." },
|
||||
{ question: "How is the Outgoing Webhook block different from the API block?", answer: "The Outgoing Webhook block is purpose-built for webhook delivery: it is POST-only, automatically adds webhook-specific headers (timestamp, delivery ID, idempotency key), and supports optional HMAC signing. The API block is more general-purpose with support for all HTTP methods, query parameters, and configurable retries." },
|
||||
]} />
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
title: Sim
|
||||
title: Sim Workspace Events
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout'
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
|
||||
import { FAQ } from '@/components/ui/faq'
|
||||
|
||||
The Sim trigger runs a workflow when events happen in your workspace: another workflow's run fails or succeeds, a workflow is deployed, or an alert condition like a latency spike or cost threshold is met. Use it to build side-effect workflows — alerting, escalation, auto-remediation — composed from any blocks (Slack, email, webhooks, custom logic).
|
||||
The Sim Workspace Events trigger runs a workflow when events happen in your workspace: another workflow's run fails or succeeds, a workflow is deployed, or an alert condition like a latency spike or cost threshold is met. Use it to build side-effect workflows — alerting, escalation, auto-remediation — composed from any blocks (Slack, email, webhooks, custom logic).
|
||||
|
||||
## Events
|
||||
|
||||
Pick one event per Sim trigger block:
|
||||
Pick one event per Sim Workspace Events trigger block:
|
||||
|
||||
**Plain events** — fire on every occurrence:
|
||||
|
||||
@@ -68,8 +68,8 @@ All events include `event`, `timestamp`, `workflowId`, and `workflowName` (the s
|
||||
## Behavior
|
||||
|
||||
<ul className="list-disc space-y-1 pl-6">
|
||||
<li>The workflow containing the Sim trigger must be <strong>deployed</strong> for events to fire.</li>
|
||||
<li>Runs started by a Sim trigger never emit workspace events, so side-effect workflows cannot chain or loop.</li>
|
||||
<li>The workflow containing the Sim Workspace Events trigger must be <strong>deployed</strong> for events to fire.</li>
|
||||
<li>Runs started by a Sim Workspace Events trigger never emit workspace events, so side-effect workflows cannot chain or loop.</li>
|
||||
<li>Alert conditions fire at most once per cooldown window (one hour, or the inactivity window for No Activity).</li>
|
||||
<li>Event delivery is fire-and-forget: side-effect runs are billed like any other run and are subject to workspace rate limits.</li>
|
||||
</ul>
|
||||
@@ -80,8 +80,8 @@ All events include `event`, `timestamp`, `workflowId`, and `workflowName` (the s
|
||||
</Callout>
|
||||
|
||||
<FAQ items={[
|
||||
{ question: "Why isn't my Sim trigger firing?", answer: "The workflow containing the trigger must be deployed — events only fire for deployed workflows. Also note the trigger never fires for the workflow it lives in, and runs started by another Sim trigger don't emit events." },
|
||||
{ question: "Can a Sim-triggered workflow trigger other Sim triggers?", answer: "No. Runs started by a Sim trigger never emit workspace events. This prevents chains and infinite loops — an alert workflow that fails can't re-trigger itself." },
|
||||
{ question: "Why isn't my Sim Workspace Events trigger firing?", answer: "The workflow containing the trigger must be deployed — events only fire for deployed workflows. Also note the trigger never fires for the workflow it lives in, and runs started by another Sim Workspace Events trigger don't emit events." },
|
||||
{ question: "Can a workflow started by a Sim Workspace Events trigger fire other Sim Workspace Events triggers?", answer: "No. Runs started by a Sim Workspace Events trigger never emit workspace events. This prevents chains and infinite loops — an alert workflow that fails can't re-trigger itself." },
|
||||
{ question: "How often do alert conditions fire?", answer: "At most once per cooldown window per trigger block. Most conditions use a one-hour cooldown; No Activity uses the configured inactivity window, evaluated per watched workflow." },
|
||||
{ question: "What unit is cost in?", answer: "Credits, both for the Cost Threshold configuration and the cost field in event payloads." },
|
||||
]} />
|
||||
|
||||
@@ -8,7 +8,7 @@ export const SimWorkspaceEventBlock: BlockConfig = {
|
||||
// can scrape the type for icon-map keys; a test asserts it stays equal to
|
||||
// the constant.
|
||||
type: 'sim_workspace_event',
|
||||
name: 'Sim',
|
||||
name: 'Sim Workspace Events',
|
||||
description:
|
||||
'Run this workflow when workspace events occur: run errors or successes, deployments, and alert conditions like latency or cost spikes.',
|
||||
category: 'triggers',
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { RequestResponse } from '@/tools/http/types'
|
||||
|
||||
export const WebhookRequestBlock: BlockConfig<RequestResponse> = {
|
||||
type: 'webhook_request',
|
||||
name: 'Webhook',
|
||||
name: 'Outgoing Webhook',
|
||||
description: 'Send a webhook request',
|
||||
longDescription:
|
||||
'Send an HTTP POST request to a webhook URL with automatic webhook headers. Optionally sign the payload with HMAC-SHA256 for secure webhook delivery.',
|
||||
|
||||
@@ -1170,6 +1170,28 @@ export function AccessControl() {
|
||||
)
|
||||
}
|
||||
|
||||
const deleteConfirmModal = (
|
||||
<ChipConfirmModal
|
||||
open={!!deletingGroup}
|
||||
onOpenChange={() => setDeletingGroup(null)}
|
||||
srTitle='Delete Permission Group'
|
||||
title='Delete Permission Group'
|
||||
text={[
|
||||
'Are you sure you want to delete ',
|
||||
{ text: deletingGroup?.name ?? 'this group', bold: true },
|
||||
'? ',
|
||||
{ text: 'All members will be removed from this group.', error: true },
|
||||
' This action cannot be undone.',
|
||||
]}
|
||||
confirm={{
|
||||
label: 'Delete',
|
||||
onClick: confirmDelete,
|
||||
pending: deletePermissionGroup.isPending,
|
||||
pendingLabel: 'Deleting...',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
if (viewingGroup) {
|
||||
return (
|
||||
<>
|
||||
@@ -1479,7 +1501,7 @@ export function AccessControl() {
|
||||
{filteredToolBlocks.length > 0 && (
|
||||
<div className='flex flex-col gap-1.5 border-[var(--border)] border-t pt-4'>
|
||||
<span className='font-medium text-[var(--text-tertiary)] text-xs uppercase tracking-wide'>
|
||||
Tools
|
||||
Integrations and Triggers
|
||||
</span>
|
||||
<div className='grid grid-cols-3 gap-x-2 gap-y-0.5'>
|
||||
{filteredToolBlocks.map((block) => {
|
||||
@@ -1638,6 +1660,8 @@ export function AccessControl() {
|
||||
isAdding={bulkAddMembers.isPending}
|
||||
errorMessage={addMembersError}
|
||||
/>
|
||||
|
||||
{deleteConfirmModal}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1784,25 +1808,7 @@ export function AccessControl() {
|
||||
/>
|
||||
</ChipModal>
|
||||
|
||||
<ChipConfirmModal
|
||||
open={!!deletingGroup}
|
||||
onOpenChange={() => setDeletingGroup(null)}
|
||||
srTitle='Delete Permission Group'
|
||||
title='Delete Permission Group'
|
||||
text={[
|
||||
'Are you sure you want to delete ',
|
||||
{ text: deletingGroup?.name ?? 'this group', bold: true },
|
||||
'? ',
|
||||
{ text: 'All members will be removed from this group.', error: true },
|
||||
' This action cannot be undone.',
|
||||
]}
|
||||
confirm={{
|
||||
label: 'Delete',
|
||||
onClick: confirmDelete,
|
||||
pending: deletePermissionGroup.isPending,
|
||||
pendingLabel: 'Deleting...',
|
||||
}}
|
||||
/>
|
||||
{deleteConfirmModal}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ describe('sim workspace event trigger registration', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('is named Sim', () => {
|
||||
expect(SimWorkspaceEventBlock.name).toBe('Sim')
|
||||
expect(simWorkspaceEventTrigger.name).toBe('Sim')
|
||||
it('is named Sim Workspace Events', () => {
|
||||
expect(SimWorkspaceEventBlock.name).toBe('Sim Workspace Events')
|
||||
expect(simWorkspaceEventTrigger.name).toBe('Sim Workspace Events')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import type { TriggerConfig } from '@/triggers/types'
|
||||
|
||||
export const simWorkspaceEventTrigger: TriggerConfig = {
|
||||
id: SIM_WORKSPACE_EVENT_TRIGGER_ID,
|
||||
name: 'Sim',
|
||||
name: 'Sim Workspace Events',
|
||||
provider: SIM_TRIGGER_PROVIDER,
|
||||
description:
|
||||
'Triggers when workspace events occur: run errors or successes, deployments, and alert conditions like latency or cost spikes',
|
||||
|
||||
Reference in New Issue
Block a user