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

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 25, 2026 6:12am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation size/m labels Jun 25, 2026
…, 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 main Jun 25, 2026
15 checks passed
@os-zhuang
os-zhuang deleted the adr/automation-execution-identity branch June 25, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant