Skip to content

docs(adr): ADR-0073 — automation execution identity (non-human principal for user-less runs) - #2318

Merged
os-zhuang merged 3 commits into
mainfrom
adr/automation-execution-identity
Jun 25, 2026
Merged

docs(adr): ADR-0073 — automation execution identity (non-human principal for user-less runs)#2318
os-zhuang merged 3 commits into
mainfrom
adr/automation-execution-identity

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Status: Proposed — opened for discussion (not for immediate merge).

Follow-up to #1888 / #2308. #2308 made the schedule/user-less runAs:'user' fail-open audible but deliberately left the runtime identity unchanged, because the real fix is a platform-identity decision. This ADR records it.

The decision in one breath

ObjectStack conflates two axes into "is userId present?": authorization (what may the run do) and attribution (who did it). That's why a user-less scheduled run both skips into god-mode and writes created_by = NULL. ADR-0073 separates them, in the ADR-0068 idiom:

  1. Automation is a first-class non-human identity, expressed as built-in rolesautomation (org-scoped) and platform_automation (unscoped, platform-only). No anonymous run.
  2. runAs becomes an authorization posture: user / automation (RLS-enforced — the Salesforce "with sharing" middle, new default for user-less triggers) / system (god-mode, unchanged for back-compat).
  3. Attribution always concrete (audit actor), decoupled from ownership so automation never silently owns the rows it writes (owner-RLS would hide them from humans — Salesforce models this the same way).
  4. User-less runAs:'user' is a config error.

Why this shape

Grounded in how Salesforce (Automated Process user + system-with/without-sharing), ServiceNow (Run-as service account), AWS IAM (execution roles, least-privilege), Kubernetes (ServiceAccount), iPaaS (connection owner), and GitHub Actions (least-privilege token) all converge on four invariants: automation runs as a concrete non-human principal; authorization ≠ attribution; safe explicit defaults; elevation is explicit + audited.

It's a platform primitive, not a flow feature — plugin-reports (already hand-rolling SYSTEM_CTX), audit, ADR-0057 lifecycle jobs, webhooks, and AI agents are all consumers.

Staging (per ADR-0049)

  • v1 (non-breaking, foundational): the contract + seeded roles + lint completeness (extend the fix(security): surface schedule/user-less flow runAs fail-open (#1888 follow-up) #2308 lint to all user-less triggers; user-less runAs:'user' → validation error). Runtime behavior unchanged.
  • M2 (roadmapped enforcement): attribution wiring (non-breaking) → then automation-default RLS-enforced authorization + scopable grants (default-broad → tighten).
  • runAs:'system' unchanged throughout.

Open questions called out in the ADR's "Alternatives" + costs. Builds on ADR-0049 / 0057 / 0066 / 0068.

🤖 Generated with Claude Code

…pal for user-less runs)
Completes the identity model (ADR-0068 unified the human surface) by adding the
non-human / automation identity that user-less runs need:
- Automation is a first-class identity expressed as built-in roles (`automation`
org-scoped, `platform_automation` unscoped) — the ADR-0068 idiom; no anonymous run.
- `runAs` becomes an authorization POSTURE (user / automation-with-RLS / system),
decoupling authorization from attribution; `automation` (RLS-enforced) is the new
safe default for user-less triggers, `system` (god-mode) unchanged for back-compat.
- Attribution always concrete (audit actor), decoupled from record ownership so
automation never silently owns the rows it writes (owner-RLS would hide them).
- User-less `runAs:'user'` is a configuration error.
Staged per ADR-0049: contract + seeded roles + lint completeness now (non-breaking,
mirrors ADR-0068 v1); runtime wiring (attribution then RLS-enforced authorization +
scopable grants) deferred to M2. Grounds the decision in how Salesforce / ServiceNow
/ AWS IAM / K8s / iPaaS / GitHub Actions handle automation identity.
Status: Proposed — for discussion. Refs #1888, #2308; builds on ADR-0049/0057/0066/0068.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 25, 2026 6:12am

Request Review

…, defer runtime to M2 (gated on first consumer)
…se (ADR-0002); automation principal is per-env Data-Plane, cross-env is Control-Plane
@os-zhuang
os-zhuang merged commit 60d48a0 into mainJun 25, 2026
15 checks passed
@os-zhuang
os-zhuang deleted the adr/automation-execution-identity branch June 25, 2026 06:15
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang