Rensei docs

Template Subscriptions

Per-project subscriptions and auto-subscribe.

Template subscriptions control which official SDLC templates are active for each project. The subscription model decouples the canonical template bundle (owned by the operator) from per-project enablement - one template can be subscribed across hundreds of projects without creating a workflow clone per project.

How subscriptions work

Every official template published by the operator has a row in the templates table with isOfficial = true. For each (project, template) pair, the platform maintains a project_template_subscriptions row with a status of published or unpublished.

The event router checks this table on every inbound webhook: if the matching subscription is published, the template fires; if it is unpublished, the template is dormant for that project.

inbound webhook

  event router

  project_template_subscriptions

  status = published?  ──yes──→  trigger.subscriptions → workflow fires
      ↓ no
  drop (no template execution)

There is a known desync between the UI "Published" badge and the event router: the UI reads project_template_subscriptions.status while the router reads trigger_subscriptions. If you archive a workflow directly from the workflow editor rather than toggling the subscription, the UI badge may show "Published" while the template is actually dormant. Always use the subscription toggle (not direct archive) to pause a template on a project. This is a known issue being tracked.

Auto-subscribe on project creation

When a new project is created, the platform calls ensureProjectSubscriptionsToOfficialTemplates for that project with status = 'published'. This means:

  • Every current official template is immediately active for the new project.
  • No operator action is required for new projects to receive the default SDLC.

Backfill on new official template publish

When a template is first marked as official (or first published as official), the platform runs fanoutSubscriptionToAllProjects with status = 'unpublished'. This means:

  • Every existing project gets a subscription row for the new template.
  • The status defaults to unpublished - existing projects must opt in explicitly.
  • New projects created after the template is official get it as published automatically.

This asymmetry is intentional: you never want a new SDLC template to silently start firing on every existing project without operator review.

Subscription status semantics

StatusMeaning
publishedTemplate fires for this project on matching events
unpublishedTemplate is dormant for this project. The workflow exists but no triggers route to it

Sticky unpublish: once a subscription is unpublished, subsequent backfills (from new official templates or template republishes) never reset it back to published. The operator must explicitly re-enable it. This is the primary mechanism for per-project opt-out.

Managing subscriptions

There is no rensei CLI surface for template subscriptions today - manage them from the UI panel or the API below.

Via the UI

Open the project's Workflows page. The System Templates panel at the top lists every official-template subscription for the project - template name, slug, a link to the read-only template preview, and a Published / Unpublished toggle. Loading the panel also lazily backfills a subscription row (at published) for any official template the project is missing, so projects created before a template became official still surface it.

Via the API

# List the project's template subscriptions
curl https://rensei.ai/api/projects/{projectId}/workflow-subscriptions \
  -H "Authorization: Bearer rsk_live_..."

# Toggle a subscription using the `id` from the list response
curl -X PATCH https://rensei.ai/api/projects/{projectId}/workflow-subscriptions \
  -H "Authorization: Bearer rsk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "subscriptionId": "pts_...",
    "status": "unpublished"
  }'

When you toggle a subscription, the platform calls syncSubscriptionTriggers immediately - trigger routing updates take effect within seconds, not at the next cron cycle.

Subscription lifecycle sync

The platform keeps project_template_subscriptions in sync with the underlying workflow status automatically:

Workflow status changeSubscription effect
Workflow archivedSubscription flipped to unpublished
Workflow publishedSubscription flipped to published
Workflow set to draftNo-op (intermediate state)

This sync runs via syncProjectSubscriptionsToWorkflow whenever a workflow's status changes. It uses the template slug stored in metadata.templateInstall.templateSlug (stamped at install time) to find the matching subscription row.

Only workflows installed via the template install path carry a templateInstall.templateSlug metadata stamp. Workflows created manually on the canvas (even if they implement the same logic) are not linked to a subscription row and are not affected by this sync.

Required workflow policies

For enterprise operators who need to guarantee that certain templates are always active on specific project sets, Rensei provides required workflow policies. Policies operate independently of the subscription model and can override the unpublished state.

Policy modeBehavior
seed-and-enforceInstall the template if missing; reset to published if unpublished
seed-onlyInstall the template if missing; do not reset existing unpublished subscriptions

Policies are authored in the admin panel (Admin → Required Workflow Policies) and reconciled every minute by the /api/cron/required-workflows cron. Operators can trigger an immediate run on demand:

# Same endpoint Vercel Cron calls (CRON_SECRET bearer auth)
curl -X POST https://rensei.ai/api/cron/required-workflows \
  -H "Authorization: Bearer $CRON_SECRET"

# Or from a platform checkout
pnpm tsx scripts/reconcile-required-workflows.ts --apply

See Required Workflow Policies for the full policy authoring reference.

Subscription table shape

For teams building on the API or writing their own tooling, the key fields on a subscription row:

FieldTypeDescription
idpts_<hex>Opaque subscription ID
workspaceIdUUIDThe org that owns the subscription
projectIdUUIDThe project the subscription applies to
templateIdUUIDReferences templates.id
statuspublished | unpublishedCurrent enablement state
createdAttimestampWhen the subscription was created
updatedAttimestampLast status toggle time

The (projectId, templateId) pair is unique - there is exactly one subscription row per (project, template) combination. Idempotent upserts use ON CONFLICT DO NOTHING on this pair.

Troubleshooting

Template fires on wrong projects

Check that the subscription is published only for the intended projects - open each project's Workflows → System Templates panel, or list per project via the API:

curl https://rensei.ai/api/projects/{projectId}/workflow-subscriptions \
  -H "Authorization: Bearer rsk_live_..."

If the subscription was created by the backfill fan-out (when you first published the template as official), it defaults to unpublished for existing projects. Confirm that the rows you expect to fire have status = published.

Template stopped firing after archiving and republishing

If you archived and then republished a workflow directly from the editor, the subscription may still be unpublished (the archive toggled it; the republish synced it back). Check the status in the System Templates panel (or the GET above). If it is unpublished, re-enable it with the panel toggle or:

curl -X PATCH https://rensei.ai/api/projects/{projectId}/workflow-subscriptions \
  -H "Authorization: Bearer rsk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "subscriptionId": "pts_...", "status": "published" }'

New projects not getting the template

Confirm the template is marked as official in the admin panel (Admin → Templates → [template] → Official). Only isOfficial = true templates are auto-subscribed on project creation.

UI badge shows "Published" but template is not firing

This is the known project_template_subscriptions vs trigger_subscriptions desync. Use the subscription toggle (not direct archive) to disable the template, wait a few seconds, then re-enable it. The syncSubscriptionTriggers call on toggle rebuilds the trigger_subscriptions rows.

On this page