fix: load related record#1610
Conversation
|
Coverage Impact Unable to calculate total coverage change because base branch coverage was not found. Modified Files with Diff Coverage (4)
🛟 Help
|
|
Claude has added a lot of comments, but your code is readable as is, so in my opinion they aren't necessary. I'd recommend to keep them to a minimum. |
23d4ee8 to
a47f15f
Compare
9d4e394 to
6224c76
Compare
| // Preview patch (no confirm): fieldName alone is sufficient. | ||
| if (data.userConfirmed === undefined) return data.fieldName !== undefined; | ||
| // Confirm patch with relation override: selectedRecordId required. | ||
| if (data.fieldName !== undefined) return data.selectedRecordId !== undefined; |
There was a problem hiding this comment.
🟡 Medium http/pending-data-validators.ts:56
The .refine() validation on line 56 requires selectedRecordId whenever fieldName is provided, even when userConfirmed is false. This means sending { userConfirmed: false, fieldName: "someField" } incorrectly fails validation with a message about "confirming with a relation override" — but declining a step is not confirming. The check should include data.userConfirmed === true to match the documented intent.
| if (data.fieldName !== undefined) return data.selectedRecordId !== undefined; | |
| if (data.userConfirmed === true && data.fieldName !== undefined) return data.selectedRecordId !== undefined; |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/workflow-executor/src/http/pending-data-validators.ts around line 56:
The `.refine()` validation on line 56 requires `selectedRecordId` whenever `fieldName` is provided, even when `userConfirmed` is `false`. This means sending `{ userConfirmed: false, fieldName: "someField" }` incorrectly fails validation with a message about "confirming with a relation override" — but declining a step is not confirming. The check should include `data.userConfirmed === true` to match the documented intent.
Evidence trail:
packages/workflow-executor/src/http/pending-data-validators.ts lines 34-65 at REVIEWED_COMMIT. Line 54 only catches `userConfirmed === undefined`, line 56 applies to any defined `userConfirmed` (including `false`). The inline comment on line 55 says 'Confirm patch' but code doesn't check `userConfirmed === true`.
Scra3
left a comment
There was a problem hiding this comment.
Found a blocking bug in the xToOne relation projection (getSingleRelatedData).
…drop unused export - Add a test for resolveFromSelection when the confirmed relation is not in availableFields (stale/renamed) — asserts the step errors and neither getRelatedData nor saveStepExecution is called. - restoreFieldNames is only used inside the agent-client adapter now; drop its unused export. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getSingleRelatedData projected both the PK and the reference field on the relation (fields[store]=id,name), which the agent's parseProjection can't split into two sub-fields — it 400s with "Invalid projection: '<relation>.id,name'". The JSON:API serializer fills the linkage `id` regardless of projection, so we only need ONE sub-field: the requested reference field (for display), else a single PK field just to pull the relation into the response. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lainer port error
- The orchestrator sends relatedCollectionName as Forest's `collection.targetKey`
reference (e.g. "store.id"), which made getCollectionSchema("store.id") 404 and
broke xToOne relation loading. Strip it to a plain collection name in the
forest-server-workflow-port adapter (transport concern stays in the adapter; the
zod schema stays a clean domain contract). The target key lives in relatedPrimaryKey.
- WorkflowPortError.userMessage no longer leaks internal jargon ("orchestrator") nor
claims a connection cause (it also wraps 4xx like "collection not found"):
"This step couldn't be completed. Please try again, and contact your administrator
if the problem continues."
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0eb03d1 to
2799340
Compare
…handling - adapter: look up xToOne linkage under the camelCased relation key (agent-client camelCases JSON:API keys); snake_case relations like billing_address no longer resolve to null / false "not found" - awaiting-input (Branch C): an empty related-record list now returns an empty candidate list with no suggestedRecord instead of erroring; the user can switch relation. Fully-automated (Branch B) still errors — it cannot load nothing - buildTarget throws instead of masking a missing relatedCollectionName - reword stale Branch B dispatch comment Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2799340 to
7b222de
Compare
The relatedPrimaryKey field was removed from the schema/RelationTarget (dead field; the related PK comes from primaryKeyFields[]). Clean up the leftover mentions: a stale comment in forest-server-workflow-port and raw-input occurrences in tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Definition of Done
General
Security
Note
Rework load-related-record step to support field selection, candidate ranking, and x-to-one fetching
LoadRelatedRecordStepExecutorto produce richerpendingDatacontainingavailableFields,suggestedField,availableRecordIds(with optionalreferenceFieldValue), andsuggestedRecordinstead of the previous flat shape.getSingleRelatedDatatoAgentPortandAgentClientAgentPortfor fetching x-to-one (BelongsTo/HasOne) relations via parent-record projection rather than a list query.fieldName(nouserConfirmed) triggers candidate refresh and returnsawaiting-inputwithout completing the step.relatedCollectionNameingetCollectionSchemato strip trailing target-key suffixes (e.g.store.id→store) and surfaces an optionalreferenceFieldfrom collection schemas.loadRelatedRecordPatchSchemaHTTP validator to accept preview patches (fieldName-only) and renamename→fieldName;selectedRecordIdis only required when confirming with a relation override.getRelatedDatanow requires callers to supplyrelatedSchema; any adapter calling it without the new argument will break at runtime.Changes since #1610 opened
stripReferenceKeyutility function to clarify that the related primary key is derived from the schema'sprimaryKeyFieldsrather than from arelatedPrimaryKeyfield [88bbefa]relatedPrimaryKeyproperty from mocked field definitions across test cases inForestServerWorkflowPort.getCollectionSchematest suite and updated assertions to verify removal of arbitrary unknown field keys [88bbefa]Macroscope summarized 7b222de.