Skip to content

Commit c2f1605

Browse files
os-zhuangclaude
andauthored
fix(examples): declare runAs:'system' on showcase webhook + approval-outcome flows (#1888) (#2316)
Audit follow-up to #1888 (flow `runAs` enforcement). Two showcase flows relied on implicit elevation and would teach the wrong pattern as AI-authoring reference templates now that `runAs` is enforced: - `showcase_inbound_task_webhook` — an HMAC webhook (no authenticated user) that creates records. It only worked via the "no identity → security-skipped" fall-through. Now declares `runAs:'system'` — the correct, explicit pattern for external ingest (and robust once the target object carries RLS). - `showcase_invoice_signoff` — the revert-on-reject write is an approval-process outcome, not an act of the submitter. `runAs:'system'` so it lands regardless of whether the submitter still has edit rights on a "sent" invoice. No behavioral regression in the showcase itself (broad member perms — the full dogfood gate was already green); this hardens the templates so they stay correct under stricter RLS and as patterns AI copies. The rest of the example flows were audited and are correct as-is: `system` where they cross owners (lead qualification, renewal/stale sweeps, todo escalation/recurrence) and `user` where they act on the trigger user's own accessible record (lead convert, task reassign, resilient-sync self-update). Verified: `pnpm --filter @objectstack/example-showcase typecheck` + full dogfood gate (173 tests) green. Refs #1888 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4a242ad commit c2f1605

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

examples/app-showcase/src/flows/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,10 @@ export const InvoiceDualSignoffFlow = defineFlow({
883883
label: 'Invoice Dual Sign-off (parallel approval)',
884884
description: 'On send, requires finance AND legal to both approve via one aggregating approval node — demonstrates parallel approvals without a token tree (ADR-0039 Track A).',
885885
type: 'autolaunched',
886+
// The revert-on-reject write is an approval-process outcome, not an act of the
887+
// submitter — run it as the system principal so it lands regardless of whether
888+
// the submitter still has edit rights on a "sent" invoice (#1888 runAs enforced).
889+
runAs: 'system',
886890
nodes: [
887891
{
888892
id: 'start',
@@ -1160,6 +1164,11 @@ export const InboundTaskWebhookFlow = defineFlow({
11601164
label: 'Inbound Task Webhook',
11611165
description: 'Creates a task from an external system via the HMAC-verified inbound hook.',
11621166
type: 'api',
1167+
// An inbound webhook has no authenticated user, so the create must run as the
1168+
// system principal (#1888 runAs is now enforced). Without this it relies on the
1169+
// "no identity → security-skipped" fall-through, which breaks the moment the
1170+
// target object carries row-level security.
1171+
runAs: 'system',
11631172
nodes: [
11641173
{
11651174
id: 'start',

0 commit comments

Comments
 (0)