Observation, filed from a downstream app (steedos-labs/hotcrm-heimao). Not a runtime defect — the shipped behaviour is right and the prose describing it is not.
The text
packages/spec → dist/contracts/index.d.ts:3033, documenting AutomationContext.flowName:
a runAs:'system' run resolves no user, so resolveRunDataContext labels its data operations svc:flow:FLOWNAME on ExecutionContext.actor … instead of leaving the audit row unattributed
What ships
@objectstack/service-automation's resolveRunDataContext does the opposite, and says so on purpose (#5494):
elevation is not anonymity … carry them through: isSystem alone decides authorization, while the user drives the platform's attribution stamps
Measured on 17.1.0: a write with { ...callerCtx, isSystem: true } leaves updated_by = the caller, byte-identical to the plain user-context write. Corroborated in two more places — sys_stamp_audit_update gates on session?.userId with no isSystem test, and plugin-audit's writeAudit reads sess.userId ?? provenance.attributedUserId with no isSystem gate.
The svc:flow: labelling the prose describes is real, but it is the user-less case — a schedule trigger, where there genuinely is no operator. The sentence generalises it to all runAs:'system' runs.
Why it is worth a card rather than a shrug
The prose reads as "system elevation costs you the operator in the audit trail."
That belief is load-bearing in the wrong direction. In the downstream app it was written into an adjudication as the explicit stop-condition for a security design — "if elevation erases the operator, stop and report a fork, because §九·58 requires 谁修改了什么…都要有日志可查". Had the investigating agent read the contract prose and trusted it, the correct design would have been abandoned on a false premise, and the card would have stopped one measurement short of the truth.
It did not, because it measured instead of reading. But the next reader may not, and a doc that talks someone out of the right answer is worth more than a cosmetic fix.
Context: #14010, the card this surfaced from.
Suggested wording
Say what is true of both cases — elevation decides authorization and leaves attribution alone; the svc:flow: actor label is what a genuinely user-less run (a schedule) falls back to.
Observation, filed from a downstream app (
steedos-labs/hotcrm-heimao). Not a runtime defect — the shipped behaviour is right and the prose describing it is not.The text
packages/spec→dist/contracts/index.d.ts:3033, documentingAutomationContext.flowName:What ships
@objectstack/service-automation'sresolveRunDataContextdoes the opposite, and says so on purpose (#5494):Measured on 17.1.0: a write with
{ ...callerCtx, isSystem: true }leavesupdated_by= the caller, byte-identical to the plain user-context write. Corroborated in two more places —sys_stamp_audit_updategates onsession?.userIdwith noisSystemtest, andplugin-audit'swriteAuditreadssess.userId ?? provenance.attributedUserIdwith noisSystemgate.The
svc:flow:labelling the prose describes is real, but it is the user-less case — a schedule trigger, where there genuinely is no operator. The sentence generalises it to allrunAs:'system'runs.Why it is worth a card rather than a shrug
The prose reads as "system elevation costs you the operator in the audit trail."
That belief is load-bearing in the wrong direction. In the downstream app it was written into an adjudication as the explicit stop-condition for a security design — "if elevation erases the operator, stop and report a fork, because §九·58 requires 谁修改了什么…都要有日志可查". Had the investigating agent read the contract prose and trusted it, the correct design would have been abandoned on a false premise, and the card would have stopped one measurement short of the truth.
It did not, because it measured instead of reading. But the next reader may not, and a doc that talks someone out of the right answer is worth more than a cosmetic fix.
Context: #14010, the card this surfaced from.
Suggested wording
Say what is true of both cases — elevation decides authorization and leaves attribution alone; the
svc:flow:actor label is what a genuinely user-less run (a schedule) falls back to.