Skip to content

Plane connector

Built-in plane connector. Floh stays the ticket of record. A Plane work item is created only when a catalog (or other) workflow includes an explicit connector step: type plane, command createWorkItem. There is no automatic create on every Floh ticket, and there is no inbound sync from Plane in this story.

Connection fields

Field Required Notes
baseUrl no Default https://api.plane.so. Self-hosted: https://{host} or https://{host}/api/v1. No embedded credentials. Private/RFC1918 hosts require allowPrivateNetworkEndpoint.
apiKey yes Plane personal access token. Encrypted at rest. Sent only as X-API-Key. Never logged or returned in API errors.
workspaceSlug yes Plane workspace slug.
projectId yes Plane project UUID that receives work items.
stateMap no Optional JSON map of Floh ticket status → Plane state UUID. Unused on create; reserved if product later asks for outbound status.
allowPrivateNetworkEndpoint no Allow baseUrl to target localhost / RFC1918 / Docker-internal hosts.

Do not put a webhook secret on this connector. Inbound HMAC webhooks are parked (LSA-9895) — Phase 3 v1 is one-way and opt-in.

Commands

Command Purpose
test Probe the configured workspace and project with the PAT.
createWorkItem Create (or adopt on 409) a work item keyed by Floh ticket id. This is the catalog path.
listStates List project states (for operators preparing a future stateMap).

Catalog setup

  1. Create a built-in connector instance of type plane and fill PAT / workspace / project. Use Test to confirm.
  2. On the catalog workflow, keep create_ticket so a Floh ticket is created.
  3. Add a Connector step after create_ticket (or rely on the reserved {{ticket.*}} snapshot injected at catalog submit):
  4. Connector: the plane instance
  5. Command: createWorkItem
  6. name: e.g. {{title}} (or the form field that holds the request title)
  7. description: optional
  8. priority: optional (critical maps to Plane urgent)
  9. externalId: {{ticket.id}}
  10. ticketNumber: {{ticket.ticketNumber}}

The engine overwrites interpolated externalId / ticketNumber from the reserved {{ticket.*}} snapshot before calling Plane. A caller-controlled binding cannot attach the link to another Floh ticket. Missing or non-UUID ticket.id fails the step with no outbound POST.

If a plane row already exists for that Floh ticket, the step completes with the stored Plane id / key and does not call Plane again.

On success the step writes ticket_external_link including a snapshot browser URL from the connector config at create time. Later edits to the connector's workspace or project do not rewrite historical links. Admin ticket detail shows External ticket (external_key + that URL). Email inbound and POST /api/tickets do not create Plane work items.

{{ticket.id}} and {{ticket.ticketNumber}} are a reserved runtime snapshot. Authors cannot declare a workflow variable named ticket.

What this story does not do

  • Automatic Plane create for every Floh ticket
  • Inbound Plane webhooks / CSRF-exempt routes (parked: LSA-9895)
  • Outbound status or priority PATCH (parked: LSA-9895)
  • Bidirectional comments (parked: LSA-9896)
  • Creating Floh tickets from Plane (source=itsm)
  • Portal My Tickets Plane URL
  • Per-queue Plane project binding
  • Assignee, attachments, or OAuth Plane-app auth

Rollback

  • Migration down() drops ticket_external_link.
  • Remove the Plane connector step from the catalog workflow, or disable the connector instance, to stop new Plane creates. A disabled instance fails the workflow step before any Plane HTTP. Existing Floh tickets and stored snapshot URLs are unchanged.

Security

  • Outbound HTTP uses connectorHttpRequest only (X-API-Key, no raw fetch()).
  • baseUrl is validated like Vault/S3 (validateConnectorEndpoint): http/https only, no userinfo, private nets require the flag.
  • Structured logs carry connector id, ticket id, and Plane work-item id / external_key — never title, description, or the PAT.