Skip to content

Latest commit

 

History

History
88 lines (66 loc) · 6.49 KB

execution-context.mdx

File metadata and controls

88 lines (66 loc) · 6.49 KB
title Execution Context — Kernel Protocol reference
navTitle Execution Context
description Execution Context schemas of the ObjectStack Kernel Protocol: AuthGateCode and 2 more — each property with its type, default and a TypeScript example.

{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}

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

TypeScript Usage

import { AuthGateCodeSchema, AuthGateScopeSchema, ExecutionContextSchema } from '@objectstack/spec/kernel';
import type { AuthGateCode, AuthGateScope, ExecutionContext } from '@objectstack/spec/kernel';

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

AuthGateCode

Allowed Values

  • PASSWORD_EXPIRED
  • PASSWORD_RESET_REQUIRED
  • MFA_REQUIRED

AuthGateScope

Allowed Values

  • account
  • credential

ExecutionContext

Properties

Property Type Required Description
userId string optional
actor string optional
attributedUserId string optional
email string optional
tenantId string optional
timezone string optional
locale string optional
currency string optional
positions string[] optional (default: [])
principalKind Enum<'human' | 'agent' | 'service' | 'guest' | 'system'> optional
audience Enum<'internal' | 'external'> optional
posture Enum<'PLATFORM_ADMIN' | 'TENANT_ADMIN' | 'MEMBER' | 'EXTERNAL'> optional ADR-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 (an external organization member) reaches explicit grants only — shares, sharing rules, and grant RLS — never the OWD baseline.
authGate { code: Enum<'PASSWORD_EXPIRED' | 'PASSWORD_RESET_REQUIRED' | 'MFA_REQUIRED'>; message: string } optional ADR-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, from the closed vocabulary PASSWORD_EXPIRED / PASSWORD_RESET_REQUIRED (an administrator forced a password change) / MFA_REQUIRED, and message is what the blocked user reads; both are required because the transport seam renders them as the 403 body. Each code declares a scope: MFA_REQUIRED holds the account, so an API key whose owner holds it is refused with the same 403; PASSWORD_EXPIRED and PASSWORD_RESET_REQUIRED hold password sign-in alone, and API keys of that owner keep working. 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
performedBy { clientId: string } optional ADR-0090 D10 rule 4 dual attribution: the agent that PERFORMED this operation, when the performer is not the principal the write is authorized as. Set only at the /mcp OAuth door, on the same branch that decides principalKind: agent and onBehalfOf; absent everywhere else, and the absence is the record that the principal acted for itself. ATTRIBUTION ONLY — no security middleware reads it, it never becomes the authorization subject, and userId stays the human so owner-stamping and current_user.* RLS still resolve to them. Server-constructed only, never client-supplied. Surfaced to hooks as HookContext.provenance.performedByClientId and recorded by the audit writer as sys_audit_log.metadata.performed_by beside on_behalf_of; it does not move actor, which ADR-0118 D1/D5 keeps two-valued.
permissions string[] optional (default: [])
systemPermissions string[] optional
tabPermissions Record<string, Enum<'visible' | 'hidden' | 'default_on' | 'default_off'>> optional
org_user_ids string[] optional
accessible_org_ids string[] optional
rlsMembership Record<string, string[]> optional
isSystem boolean optional (default: false)
flowRunId string optional
skipTriggers boolean optional
skipAutomations boolean optional
seedReplay boolean optional
skipStateMachine boolean optional
preserveAudit boolean optional Historical import: preserve the ORIGINAL audit timeline for this write instead of stamping it "now". 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: the create-side static readonly strip runs inside engine.insert itself (after the beforeInsert hooks, before validation — the 2026-09-03 ruling; the DataProtocol ingress copy it replaced is deleted) and reads only 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.
keptOptionValues Record<string, string[]> optional Import with createMissingOptions: per field name, the option values the import kept because they matched none of the field's options. The write-path option check admits exactly these values on this write (and still refuses every other value outside the options); the field's options are not changed, and a later write that sends the field is judged against them again. Server-constructed only (set by the import runner), never client-supplied.
oauthScopes string[] optional
accessToken string optional
transaction any optional
traceId string optional