feat(workflow): expose trigger user role to script actions

Scripts can now branch on WHO triggered the workflow and their role in the
base, without an extra API call (the workflow token has no role-read scope).

New triggerInput fields (user-initiated triggers only: buttonClick /
recordCreated / recordUpdated / recordCondition / formSubmitted):
- _triggerUserRoles: string[]  (enabled role display names in this base)
- _triggerUserIsAdmin: boolean (space owner / AM admin / AM-disabled)

Absent for scheduledTime / webhook (no user context).

Implementation:
- trigger-user-info.ts: resolveTriggerUserInfo(prisma, baseId, userId) —
  standalone, unit-tested (8 tests). Mirrors the admin logic in
  AuthorityMatrixPermissionService but returns only role names + bool.
- workflow-runner.service.ts: resolve once at first action node, merge into
  enrichedInput (both execute() and test() paths).
- skill action-types.md: document the fields + script branching example.
This commit is contained in:
yeuimu
2026-08-11 10:08:12 +00:00
parent cf25c8ff93
commit ef013690f3
@@ -31,6 +31,26 @@ Inside a `script` action, these are available:
**NOT available**: `fs`, `eval`, `Function`, `process` (only `process.env`), `child_process`.
**Trigger user role** (user-initiated triggers only — buttonClick / recordCreated /
recordUpdated / recordCondition / formSubmitted): when a real user fires the
workflow, `triggerInput` also carries their role in THIS base:
| Field | Type | Meaning |
|-------|------|---------|
| `triggerInput.user` | `{id,name,email}` | Who triggered (absent for scheduledTime/webhook) |
| `triggerInput._triggerUserRoles` | `string[]` | Display names of the user's enabled, non-deleted roles in this base. `[]` for admins (admins have no AM role) |
| `triggerInput._triggerUserIsAdmin` | `boolean` | `true` for space owner, AM admin users, or everyone when AM is disabled for the base |
These fields are **absent** for system triggers (scheduledTime / webhook) — no
user context. Branch on them in scripts:
```js
const roles = triggerInput._triggerUserRoles ?? [];
const isAdmin = triggerInput._triggerUserIsAdmin ?? false;
if (isAdmin) { /* admin path */ }
else if (roles.includes('工厂运营')) { /* operator path */ }
else if (roles.includes('售后客服')) { /* support path */ }
```
**Back-channel API access**: inside scripts, call the instance's own API:
```js
const res = await fetch(triggerInput._apiBaseUrl + '/api/table/tblXXX/record', {