Repository navigation
FE-1985: Add Create entity and Update entity flow actions - #10060
kostandinang wants to merge 6 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #10060 +/- ##
==========================================
+ Coverage 68.03% 68.05% +0.02%
==========================================
Files 2006 2010 +4
Lines 206233 206406 +173
Branches 8796 8851 +55
==========================================
+ Hits 140312 140471 +159
- Misses 64253 64255 +2
- Partials 1668 1680 +12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
753313c to
3458b0e
Compare
3458b0e to
62f6c20
Compare
206c304 to
1fa7d8d
Compare
Create entity creates an entity of a type, with values for some of its properties, in the web the flow runs in. Update entity sets or removes some of an entity's properties, only for a user who can edit it. A created entity keeps the same UUID on every attempt of its step, so a Temporal retry can't create a second one. Co-authored-by: Cursor <[email protected]>
f714943 to
3cefbe9
Compare
|
Semgrep found 2
🟡 Medium severity issue identified in your code: MD5 is a a weak hash which is known to have collision. Use a strong hashing function. Semgrep found 2
🟡 Medium severity issue identified in your code: The use of a weak cryptographic algorithm (e.g., SHA-1 or MD5) has been identified. These algorithms are considered insecure due to vulnerabilities that make them susceptible to collision attacks, allowing attackers to compromise data integrity or security. Replace SHA-1 or MD5 with secure hashing algorithms, such as: SHA-256 or higher (e.g., SHA-3). View Dataflow Graphflowchart LR
classDef invis fill:white, stroke: none
classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none
subgraph File0["<b>apps/hash-api/src/mailchimp.ts</b>"]
direction LR
%% Source
subgraph Source
direction LR
v0["<a href=https://github.com/hashintel/hash/blob/3cefbe9fafa7c969515d7d2c2dc342aeceaff0f8/apps/hash-api/src/mailchimp.ts#L41 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 41] "md5"</a>"]
end
%% Intermediate
%% Sink
subgraph Sink
direction LR
v1["<a href=https://github.com/hashintel/hash/blob/3cefbe9fafa7c969515d7d2c2dc342aeceaff0f8/apps/hash-api/src/mailchimp.ts#L41 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 41] "md5"</a>"]
end
end
%% Class Assignment
Source:::invis
Sink:::invis
File0:::invis
%% Connections
Source --> Sink
|
Update entity takes the graph's property patches and applies them as given, and Create entity takes properties with their metadata, so each value names its data type rather than the graph inferring it. The graph validates both, so the separate check against the entity's types is removed. Patches change whole properties, since a patch inside a list isn't safe to retry. Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
| entityTypeId, | ||
| properties, | ||
| draft = false, | ||
| } = getSimplifiedFlowActionInputs({ inputs, actionType: "createEntity" }); |
There was a problem hiding this comment.
One thing this does not support is the creation of links, which additionally must pass linkData.
There was a problem hiding this comment.
Yes, out of scope here. I'll do it as a follow-up.
| { equal: [{ path: ["uuid"] }, { parameter: entityUuid }] }, | ||
| { equal: [{ path: ["webId"] }, { parameter: webId }] }, |
There was a problem hiding this comment.
Just a note that if there is as UUID collision (generally unlikely unless we have duplicate stepIds or runIds for some reason) this would return some other entity.
I appreciate the PR description says we do this in case there's a Temporal retry. I'm not sure that would happen given that the activity is over once the create call succeeds, but probably fine to leave for now.
There was a problem hiding this comment.
Only retries of the same step run share a UUID, since for-each branches get their own step IDs. Temporal can still retry after the create succeeds if the worker dies before reporting back, so I'll leave it.
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
|
Addressed your comments, could you re-approve? The push dismissed your approval. |
🌟 Purpose
Flows can find entities (#10050) but can only write through
persistEntity, which takes a full AI-proposed entity. This adds Create Entity and Update Entity, which write through the graph's own API, so the graph does the validation.entityTypeIds(one or more),properties(which may be empty) and an optionaldraft(default false).propertiesis the graph'sPropertyObjectWithMetadata: values keyed by property type base URL, each with inline metadata (a requireddataTypeId, and optionally provenance and confidence). CallsHashEntity.create. Outputs the newentityId, with a draft ID if it's a draft.entityId(an ID or an item of a stored list) andpropertyPatches, the graph's add/remove/replace patches. Callsentity.patch(). Outputs the sameentityId.persistEntitydoes. Update only changes entities the user can edit, and edits the draft if the ID has one.🔍 Changes
flows/property-values.tsdataTypeId, and each patch targets a whole top-level property. Start here.flows/action-definitions.ts,flows/types.tsPropertyObjectWithMetadataandPropertyPatchkinds.update-entity-action.ts,create-entity-action.tsshared/save-entity.ts,persist-entity-action.tspersistEntityso all three share them. No change topersistEntity's behaviour.generate-uuid.tsgenerateUuidFromName, for Create's UUID.Decisions to review:
propertyMetadatainput.persistEntity'sProposedEntityinput isn't reused because it carries AI provenance, claims and link resolution that a value set on a step doesn't have.dataTypeId: nullis rejected. The graph would accept it and infer a data type, which fails for a property allowing several data types, or only an abstract one.addsets a property, replacing any value.replacefails if the property is missing.removedoes nothing if it's already gone. The graph also takes paths inside a value (e.g. a list index), but adding or removing by index isn't safe if Temporal retries the step.persistEntitydoesn't. A run only starts if the user has a role in its web, so Create can't write outside the user's webs. Should it check the types too?PropertyObjectWithMetadataorPropertyPatchyet, and the run modal doesn't support them, so properties come from constants in the flow definition or flow inputs given programmatically.retrySavealso retries it, as forpersistEntity.persistEntitywith Create Entity.🛡 Tests