Part of ADR-0053 Phase 2. Design: #1975 · Parent: #1928.
Slice 2 of 6 — independent of timezone; worth doing on its own. Fix the read-time formula evaluation blind spot.
Problem
applyFormulaPlan evaluates read-time formula virtual fields with only { record } — no now, no execution context, no timezone — packages/objectql/src/engine.ts:88-96, called from find/findOne at engine.ts:1841 and :1907. So today()/daysBetween() inside a formula field run against live wall-clock UTC with no determinism and no user/org access.
Scope
- Thread
{ now: nowSnap, timezone, user, org } from opCtx.context (the ExecutionContext already held by find/findOne) into applyFormulaPlan.
- Mirror
applyFieldDefaults, which already does this correctly — packages/objectql/src/engine.ts:691-719.
Acceptance criteria
Depends on
Slice 1 for the timezone value (degrades to 'UTC' without it). The now/user/org threading can land immediately.
Part of ADR-0053 Phase 2. Design: #1975 · Parent: #1928.
Slice 2 of 6 — independent of timezone; worth doing on its own. Fix the read-time formula evaluation blind spot.
Problem
applyFormulaPlanevaluates read-time formula virtual fields with only{ record }— nonow, no execution context, no timezone —packages/objectql/src/engine.ts:88-96, called fromfind/findOneatengine.ts:1841and:1907. Sotoday()/daysBetween()inside a formula field run against live wall-clock UTC with no determinism and no user/org access.Scope
{ now: nowSnap, timezone, user, org }fromopCtx.context(theExecutionContextalready held byfind/findOne) intoapplyFormulaPlan.applyFieldDefaults, which already does this correctly —packages/objectql/src/engine.ts:691-719.Acceptance criteria
now(determinism within one operation) anduser/org.timezone(until then,'UTC').days_to_closein example-crm) unchanged in value.Depends on
Slice 1 for the
timezonevalue (degrades to'UTC'without it). Thenow/user/orgthreading can land immediately.