ObjectStackObjectStack

Execution Context

Execution Context protocol schemas

Execution Context Schema

Defines the runtime context that flows from HTTP request → data operations. This is the "identity + environment" envelope that every data operation can carry.

Design:

  • All fields are optional for backward compatibility
  • isSystem bypasses permission checks (for internal/migration operations)
  • transaction carries the database transaction handle for atomicity
  • traceId enables distributed tracing across microservices

Usage: engine.find('account', { context: { userId: '...', tenantId: '...' } })

Source: packages/spec/src/kernel/execution-context.zod.ts

TypeScript Usage

import { ExecutionContextSchema } from '@objectstack/spec/kernel';
import type { ExecutionContext } from '@objectstack/spec/kernel';

// Validate data
const result = ExecutionContextSchema.parse(data);

ExecutionContext

Properties

PropertyTypeRequiredDescription
userIdstringoptional
actorstringoptional
attributedUserIdstringoptional
emailstringoptional
tenantIdstringoptional
timezonestringoptional
localestringoptional
currencystringoptional
positionsstring[]
principalKindEnum<'human' | 'agent' | 'service' | 'guest' | 'system'>optional
audienceEnum<'internal' | 'external'>optional
postureEnum<'PLATFORM_ADMIN' | 'TENANT_ADMIN' | 'MEMBER' | 'EXTERNAL'>optionalADR-0095 D2 posture rung — PLATFORM_ADMIN crosses the tenant wall where object posture permits; TENANT_ADMIN sees all rows in the org; MEMBER gets business RLS; EXTERNAL sees only explicitly shared rows.
authGate{ code: string; message: string }optionalADR-0069 authentication-policy gate: present only while the principal is blocked from protected resources until they remediate (expired password, enforced MFA), absent for every healthy session. code is the stable machine code the client branches on (PASSWORD_EXPIRED / MFA_REQUIRED) and message is what the blocked user reads; both are required because the transport seam renders them as the 403 body. AUTHENTICATION, not authorization — it suspends access entirely rather than narrowing it, and nothing in the permission/RLS path reads it, while the allow-listed remediation endpoints stay reachable. Server-constructed only, never client-supplied; a guest/anonymous principal never carries one.
onBehalfOf{ userId: string; principalKind?: Enum<'human' | 'agent' | 'service' | 'guest' | 'system'> }optional
permissionsstring[]
systemPermissionsstring[]optional
tabPermissionsRecord<string, Enum<'visible' | 'hidden' | 'default_on' | 'default_off'>>optional
org_user_idsstring[]optional
accessible_org_idsstring[]optional
rlsMembershipRecord<string, string[]>optional
isSystemboolean
flowRunIdstringoptional
skipTriggersbooleanoptional
skipAutomationsbooleanoptional
seedReplaybooleanoptional
skipStateMachinebooleanoptional
preserveAuditbooleanoptionalHistorical import: preserve the ORIGINAL audit timeline for this write instead of stamping it "now" (#3493). Opt-in and server-constructed only, never client-supplied. On the UPDATE path it admits a whitelist — the audit/timestamp family (created_at / created_by / updated_at / updated_by) plus author-declared business readonly fields — while platform-managed system columns (tenancy, generated) stay stripped. On INSERT the exemption does NOT apply (#6640): a create is stripped earlier, at the DataProtocol ingress, whose only exemption is context.isSystem, so a non-system create carrying preserveAudit still has those fields stripped and is warned (WARN) that the exemption is UPDATE-only — replaying archival readonly facts on create requires a system context. Permissions / RLS / field-level security are unaffected.
oauthScopesstring[]optional
accessTokenstringoptional
transactionanyoptional
traceIdstringoptional

On this page