Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/25361-get-record-limit-form-minimum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@objectstack/service-automation': patch
---

fix: the `get_record` designer form no longer offers a `limit` below 1

Clause-②: no
Metadata-protocol: none

The `get_record` node's `limit` is a positive integer, and every flow save door refuses `0`, a negative or a fraction. The executor's form descriptor still declared `limit` as a bare integer, so the designer form offered values the save always refused. The descriptor's `limit` now declares `minimum: 1`, the same floor as the contract. Nothing a flow can store changes; only the form stops offering what the save refuses.
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,24 @@ describe('CRUD / screen / map form ↔ Zod reconciliation (#4045)', () => {
).toEqual([]);
});

it('get_record.limit: the form\'s minimum is the contract\'s refusal boundary', () => {
// The contract refuses a `limit` below 1 at every save door; a form whose
// floor sits lower offers values the save always refuses. Pin both sides
// at the boundary the descriptor declares, so neither moves alone.
const limit = formSchema('get_record').properties?.limit as
| { type?: string; minimum?: number }
| undefined;
expect(limit?.type).toBe('integer');
expect(limit?.minimum).toBe(1);

const parse = (value: number) =>
(GetRecordConfigSchema as unknown as { safeParse(v: unknown): { success: boolean } })
.safeParse({ objectName: 'account', limit: value }).success;
expect(parse(limit!.minimum!), 'the contract accepts the form\'s minimum').toBe(true);
expect(parse(limit!.minimum! - 1), 'the contract refuses one below the form\'s minimum').toBe(false);
expect(parse(0), 'the contract refuses 0').toBe(false);
});

describe('assignment: pinned as un-reconcilable, with the reason on record', () => {
// `assignment` deliberately has NO entry in builtin-node-config.zod.ts: with
// no `assignments` wrapper, the TOP-LEVEL config keys ARE the author's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,10 @@ export function registerCrudNodes(engine: AutomationEngine, ctx: PluginContext):
type: 'array', items: { type: 'string' }, title: 'Fields',
description: 'Field projection — only these fields are read (default: all).',
},
limit: { type: 'integer', title: 'Limit' },
// `minimum: 1` mirrors the contract: `GetRecordConfigSchema.limit`
// is a positive integer, refused below 1 at every flow save
// door, so the form never offers a value the save refuses.
limit: { type: 'integer', minimum: 1, title: 'Limit' },
outputVariable: { type: 'string', title: 'Output variable' },
},
required: ['objectName'],
Expand Down
Loading