Problem
Hook handlers run in a single-suspended-async QuickJS (asyncify) sandbox. A hook that issues a nested engine write (e.g. ctx.api.object('parent').update(...) from a child's hook) re-enters the sandbox while the first call is suspended and crashes the process with memory access out of bounds.
Impact (platform-wide)
This single limitation forces a reaction-free, denormalized workaround across five shipped templates. Each CHARTER explicitly documents it as the reason header/rollup fields are hand-maintained:
expense_report.total_amount, procurement_order.received_amount, pm_project.progress_percent/actual_cost, content_publication.total_*, compliance rollups.
Authors cannot write the most natural automation ("when a child changes, update the parent").
Repro
Add an afterInsert/afterUpdate hook on a child object that calls ctx.api.object(parent).update(...); trigger it → process crash (memory access out of bounds). ctx.services.data is also undefined inside the sandbox (silent no-op), so the "obvious" alternative also fails.
Expected
Nested engine writes from a hook should be safe — e.g. queued and flushed after the current op commits, or hooks executed in a model that allows more than one suspended async call.
Affected
@objectstack/runtime (hook execution sandbox).
Found while runtime-testing objectstack-ai/templates (all 9 templates via objectstack dev all) on @objectstack 9.5.1. Build + typecheck pass; these only surface at runtime.
Problem
Hook handlers run in a single-suspended-async QuickJS (asyncify) sandbox. A hook that issues a nested engine write (e.g.
ctx.api.object('parent').update(...)from a child's hook) re-enters the sandbox while the first call is suspended and crashes the process withmemory access out of bounds.Impact (platform-wide)
This single limitation forces a reaction-free, denormalized workaround across five shipped templates. Each CHARTER explicitly documents it as the reason header/rollup fields are hand-maintained:
expense_report.total_amount,procurement_order.received_amount,pm_project.progress_percent/actual_cost,content_publication.total_*,compliancerollups.Authors cannot write the most natural automation ("when a child changes, update the parent").
Repro
Add an
afterInsert/afterUpdatehook on a child object that callsctx.api.object(parent).update(...); trigger it → process crash (memory access out of bounds).ctx.services.datais also undefined inside the sandbox (silent no-op), so the "obvious" alternative also fails.Expected
Nested engine writes from a hook should be safe — e.g. queued and flushed after the current op commits, or hooks executed in a model that allows more than one suspended async call.
Affected
@objectstack/runtime(hook execution sandbox).Found while runtime-testing
objectstack-ai/templates(all 9 templates viaobjectstack dev all) on@objectstack9.5.1. Build + typecheck pass; these only surface at runtime.