Skip to content

Object-level workflows: [...] (and any unknown ObjectSchema key) is silently stripped at build — no error/warning (ADR-0032 'no silent failure', metadata layer) #1535

Closed

Description

@xuyushun441-sys

Summary

Object-level workflows: [...] authored on an ObjectSchema is silently dropped at build — no error, no warning, and tsc --noEmit passes. The result: declarative on-update automation that authors believe they shipped never runs, and nothing anywhere tells them.

This surfaced in objectstack-ai/templates: 15 object-level workflows across 8 objects / 6 packages (timestamp stamping, contract auto-activate/expire, order auto-receive, etc.) were authored, built green, and were completely absent from every built artifact — dead from day one. We have since migrated them to lifecycle hooks (templates-side fix), but the silent-drop behavior is the platform problem.

This is the metadata-key analogue of ADR-0032's "no silent failure" principle: today a misauthored expression is caught at build, but a misauthored schema key is silently discarded.

Root cause

ObjectSchemaBase is a plain z.object({...}) (Zod default = .strip()), and ObjectSchema.create() parses through it:

  • packages/spec/src/data/object.zod.ts:334 — const ObjectSchemaBase = z.object({ ... })
  • :524 — validations: z.array(ValidationRuleSchema).optional() ✅ (supported)
  • No workflows key anywhere in ObjectSchemaBase (grep for workflow in packages/spec/src/data/ returns only unrelated hits).
  • :740 — create: <const T extends z.input<typeof ObjectSchemaBase>>(config) => ObjectSchemaBase.parse(withDefaults) → unknown keys are stripped on parse.

So any unknown top-level key (workflows, or a typo'd validation/indexs/etc.) is silently removed. The generic create() signature also did not trigger a TypeScript excess-property error for the extra workflows key (the templates typechecked clean with it present).

Reproduction

import { ObjectSchema } from '@objectstack/spec/data';

const Obj = ObjectSchema.create({
  name: 'demo',
  fields: { status: { type: 'text' } },
  workflows: [{                       // ← not a real ObjectSchema field
    name: 'stamp', objectName: 'demo', triggerType: 'on_update',
    criteria: 'record.status == "done"', active: true,
    actions: [{ name: 'x', type: 'field_update', field: 'done_at', value: 'now()' }],
  }],
});

console.log('workflows' in Obj);   // → false  (silently stripped; no error, no warning)

objectstack build on a package full of these prints ✓ Build complete with no diagnostic; the composed artifact contains 0 object-workflows.

Why this is bad

  1. Silent no-op automation. Exactly the failure mode ADR-0032 set out to eliminate ("a malformed thing must come back to the author as a precise, fixable error, never a runtime no-op") — but for schema shape rather than expressions. An AI author (the ADR's design center) gets zero signal and ships dead metadata with full confidence.
  2. The platform's own guidance teaches the dropped shape. The objectstack-data skill's "CRM Schema Blueprint" table lists:

    Lifecycle workflow | src/objects/*.object.ts | Use workflows[] for field updates triggered by record changes
    So authors (and agents) are actively told to write workflows[] on objects — a field the spec doesn't accept.

Asks

  1. Don't strip silently. Reject unknown top-level keys on ObjectSchema.create() / at objectstack build (or at minimum emit a located build warning). Mirrors ADR-0032 §1c "no silent fallback", applied to metadata shape. A typo'd validation/hoooks/workflows should be a fixable build error, not a vanished field.
  2. Decide the object-workflow story. Either (a) make object-level declarative on-update automation a first-class ObjectSchema field, or (b) if lifecycle hooks and top-level record_change flows are the only supported paths, say so — and have the build flag workflows explicitly pointing authors at the supported mechanism.
  3. Fix the docs/skill. Remove/repair the objectstack-data CRM-blueprint row that teaches workflows[].

Refs

Activity

  1. xuyushun441-sys commented on Jun 3, 2026

    @xuyushun441-sys
    CollaboratorAuthor

    Confirmed fixed in 7.7.0 ✅ — objectstack build now rejects unknown ObjectSchema keys with a located, actionable error:

    ✗ ObjectSchema.create('todo_task'): unknown key(s) — stateMachines.
      Remove the unknown key(s), fix the typo, or move the logic to a supported mechanism.
    

    Verified while taking objectstack-ai/templates to 7.7.0: the new validator caught both silently-stripped keys — workflows (the one this issue reported) and stateMachines (14 objects whose lifecycle machines had never been enforced). Both have since been migrated to supported mechanisms (hooks / state_machine validation rules). Thanks for the quick turnaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions