Skip to content

Conversation

@TimDiekmann
Copy link
Member

@TimDiekmann TimDiekmann commented Jan 28, 2026

🌟 What is the purpose of this PR?

This PR adds protection against enumeration attacks by preventing filtering on sensitive properties like email for User entities. It implements a filter transformation system that automatically excludes User entities when filtering by email, while preserving legitimate query paths.

🔍 What does this change?

  • Adds a FilterProtectionConfig system to specify which properties should be protected for which entity types
  • Implements a filter transformation algorithm that prevents User enumeration via email filters
  • Adds a new skip_filter_protection flag to disable protection in development/testing
  • Updates the AI worker to exclude email from entity embeddings for User entities

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

🛡 What tests cover this?

  • Comprehensive integration tests for all filter protection cases
  • Truth table verification for various filter combinations
  • Tests for multi-property and multi-type protection scenarios
  • Tests for actor identity-based exclusions

❓ How to test this?

  1. Checkout the branch
  2. Try filtering entities by email
  3. Confirm that User entities are not returned when filtering by email
  4. Verify that non-User entities (like Invitations) can still be filtered by email
  5. Verify that a User can query their own entity by email, but not other Users

Introduces a filter transformation system that prevents attackers from
discovering users by filtering on protected properties like email. Even
when the API strips email from responses, returning results reveals user
existence.

The protection works by transforming filters at query time:
- Email conditions get `AND NOT(type=User)` added at leaf level
- NOT depth tracking ensures De Morgan-correct transformations
- OR branches are preserved (legitimate matches via other conditions)
- Machine actors bypass protection for system operations

Configurable via FilterProtectionConfig with property→entity type mapping.
CLI flag `--skip-filter-protection` available for dev/testing.
Refactors filter protection to correctly handle entities with multiple types.

- Introduces FilterExpressionList enum to allow Filter::In to accept either
  a ParameterList or a Path, enabling IN checks against array columns
- Changes type exclusion from Equal(EntityTypeEdge) to In(TypeBaseUrls)
  which properly checks if a type is present in an entity's type array
- Updates all Filter::In usages to wrap ParameterList in FilterExpressionList
- Use let chains to collapse nested if-let statements
- Change &Option<T> to Option<&T> for better API ergonomics
- Add #[must_use] to transform_filter
- Replace wildcard enum match with explicit variants
- Use #[expect] instead of #[allow] with reasons
- Fix doc comment punctuation
- Use is_none_or instead of map_or(true, ...)
- Add const to pure functions
- Use self instead of &self for Copy types
Prevents email enumeration attacks via CosineDistance queries on embeddings.
When generating embeddings for User entities, the email property is now
excluded from both individual property embeddings and the combined embedding.
Add early check for empty FilterProtectionConfig to avoid unnecessary
filter transformation when no properties are protected.
Extend test coverage for FilterProtectionConfig:

Multi-property tests (2 properties / 1 type):
- email AND phone both protected for User
- Tests: individual filters, AND, OR combinations

Multi-type tests (2 types / 1 property each):
- email protected for User, secret_code protected for SecretEntity
- Tests: verify cross-type protection independence

Also adds DatabaseTestWrapper::new_with_settings() to allow custom
FilterProtectionConfig in tests.
Document the expected behavior with ASCII truth tables showing:
- MP-1 to MP-4: Multi-property cases (email + phone → User)
- MT-1 to MT-4: Multi-type cases (email → User, secret → SecretEntity)

Tables clarify the cross-protection behavior in OR expressions where
each type can still match via the branch that isn't protected for them.
- Remove unused #[expect(clippy::struct_excessive_bools)] on MultiTypeRow
- Auto-format eprintln! statements
…ction

Allow users to query their own User entity by email while still
protecting other users' emails from enumeration.

- Add CellFilterExpression::ActorId variant for dynamic actor comparison
- Add CellFilter::NotEqual for uuid != ActorId conditions
- Add lifetime parameters to CellFilter types for borrowed data
- Update hash_default() to use All([type=User, uuid!=ActorId])
- Add integration tests for ActorId validation (positive/negative cases)
- Update unit tests for new exclusion filter structure
@vercel
Copy link

vercel bot commented Jan 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Review Updated (UTC)
hashdotdesign Ignored Ignored Preview Jan 28, 2026 1:35pm
hashdotdesign-tokens Ignored Ignored Preview Jan 28, 2026 1:35pm

@github-actions github-actions bot added area/apps > hash* Affects HASH (a `hash-*` app) area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team area/tests New or updated tests area/apps area/apps > hash-graph labels Jan 28, 2026
Copy link
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codecov
Copy link

codecov bot commented Jan 28, 2026

Codecov Report

❌ Patch coverage is 86.30807% with 56 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.30%. Comparing base (2105a2d) to head (6fb86a1).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
...postgres-store/src/store/postgres/query/compile.rs 58.69% 18 Missing and 1 partial ⚠️
...store/src/store/postgres/query/property_masking.rs 89.38% 18 Missing and 1 partial ⚠️
...s-store/src/store/postgres/knowledge/entity/mod.rs 0.00% 12 Missing ⚠️
...cal/graph/postgres-store/src/store/postgres/mod.rs 0.00% 3 Missing ⚠️
...h-ai-worker-ts/src/activities/shared/embeddings.ts 0.00% 2 Missing ⚠️
...al/graph/postgres-store/src/store/postgres/pool.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8332      +/-   ##
==========================================
+ Coverage   60.19%   60.30%   +0.11%     
==========================================
  Files        1232     1233       +1     
  Lines      118007   118398     +391     
  Branches     5135     5146      +11     
==========================================
+ Hits        71029    71402     +373     
- Misses      46152    46168      +16     
- Partials      826      828       +2     
Flag Coverage Δ
apps.hash-ai-worker-ts 1.41% <0.00%> (-0.01%) ⬇️
apps.hash-api 0.00% <ø> (ø)
local.hash-graph-sdk 10.88% <ø> (ø)
local.hash-isomorphic-utils 0.00% <ø> (ø)
rust.error-stack 90.88% <ø> (ø)
rust.harpc-tower 66.80% <ø> (ø)
rust.harpc-types 0.00% <ø> (ø)
rust.harpc-wire-protocol 92.23% <ø> (ø)
rust.hash-graph-api 2.88% <ø> (ø)
rust.hash-graph-authorization 62.47% <ø> (ø)
rust.hash-graph-postgres-store 27.26% <86.73%> (+1.65%) ⬆️
rust.hash-graph-temporal-versioning 47.95% <ø> (ø)
rust.hash-graph-validation 83.45% <ø> (ø)
rust.hashql-compiletest 46.65% <ø> (ø)
rust.hashql-eval 68.54% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq
Copy link

codspeed-hq bot commented Jan 28, 2026

CodSpeed Performance Report

Merging this PR will not alter performance

Comparing t/be-310-dont-allow-filtering-users-by-email (6fb86a1) with main (8e4d972)1

Summary

✅ 18 untouched benchmarks
🗄️ 12 archived benchmarks run2

Footnotes

  1. No successful run was found on main (1205c42) during the generation of this report, so 8e4d972 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 12 benchmarks were run, but are now archived. If they were deleted in another branch, consider rebasing to remove them from the report. Instead if they were added back, click here to restore them.

Implement JSONB key deletion to remove protected properties from entity
responses at the database level. Properties like email are now masked
directly in SQL SELECT statements, ensuring they never leave the database
unless the actor is the entity owner.

- Add CaseWhen, JsonDeleteKeys, ArrayConcat, ArrayLiteral expressions
- Implement property_masking module for building masking expressions
- Integrate masking into SelectCompiler for Properties and PropertyMetadata
- Add integration tests for response masking and sorting protection
- Add unit tests for masked expression generation
@github-actions
Copy link
Contributor

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$26.2 \mathrm{ms} \pm 163 \mathrm{μs}\left({\color{lightgreen}-5.565 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.21 \mathrm{ms} \pm 12.9 \mathrm{μs}\left({\color{gray}-1.377 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1001 $$11.8 \mathrm{ms} \pm 66.6 \mathrm{μs}\left({\color{gray}-3.013 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$42.0 \mathrm{ms} \pm 305 \mathrm{μs}\left({\color{gray}0.122 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$13.9 \mathrm{ms} \pm 92.3 \mathrm{μs}\left({\color{gray}1.84 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1526 $$23.1 \mathrm{ms} \pm 129 \mathrm{μs}\left({\color{gray}0.054 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$26.3 \mathrm{ms} \pm 192 \mathrm{μs}\left({\color{lightgreen}-38.665 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.59 \mathrm{ms} \pm 17.8 \mathrm{μs}\left({\color{lightgreen}-81.761 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$11.0 \mathrm{ms} \pm 79.6 \mathrm{μs}\left({\color{lightgreen}-63.119 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.65 \mathrm{ms} \pm 14.8 \mathrm{μs}\left({\color{gray}-0.288 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.86 \mathrm{ms} \pm 11.1 \mathrm{μs}\left({\color{gray}0.557 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 51 $$3.21 \mathrm{ms} \pm 13.0 \mathrm{μs}\left({\color{gray}0.627 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.01 \mathrm{ms} \pm 21.4 \mathrm{μs}\left({\color{gray}-0.165 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.41 \mathrm{ms} \pm 13.2 \mathrm{μs}\left({\color{gray}-0.280 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 107 $$4.01 \mathrm{ms} \pm 26.0 \mathrm{μs}\left({\color{gray}0.816 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.29 \mathrm{ms} \pm 23.2 \mathrm{μs}\left({\color{gray}3.83 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.30 \mathrm{ms} \pm 15.8 \mathrm{μs}\left({\color{gray}0.368 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$3.92 \mathrm{ms} \pm 30.0 \mathrm{μs}\left({\color{gray}0.391 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.58 \mathrm{ms} \pm 11.4 \mathrm{μs}\left({\color{red}8.09 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.51 \mathrm{ms} \pm 10.8 \mathrm{μs}\left({\color{red}7.45 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1 $$2.61 \mathrm{ms} \pm 11.9 \mathrm{μs}\left({\color{red}8.15 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$2.79 \mathrm{ms} \pm 10.2 \mathrm{μs}\left({\color{gray}3.84 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.70 \mathrm{ms} \pm 10.4 \mathrm{μs}\left({\color{red}7.39 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$2.88 \mathrm{ms} \pm 12.0 \mathrm{μs}\left({\color{red}6.39 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$2.97 \mathrm{ms} \pm 15.6 \mathrm{μs}\left({\color{red}7.33 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.65 \mathrm{ms} \pm 9.97 \mathrm{μs}\left({\color{red}9.04 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 25 $$2.81 \mathrm{ms} \pm 12.0 \mathrm{μs}\left({\color{red}6.90 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.31 \mathrm{ms} \pm 14.1 \mathrm{μs}\left({\color{red}5.28 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$2.89 \mathrm{ms} \pm 12.9 \mathrm{μs}\left({\color{red}8.47 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 26 $$3.09 \mathrm{ms} \pm 10.9 \mathrm{μs}\left({\color{red}6.49 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.19 \mathrm{ms} \pm 11.6 \mathrm{μs}\left({\color{gray}4.48 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.85 \mathrm{ms} \pm 11.2 \mathrm{μs}\left({\color{red}6.57 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.07 \mathrm{ms} \pm 11.6 \mathrm{μs}\left({\color{red}5.98 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$42.7 \mathrm{ms} \pm 138 \mathrm{μs}\left({\color{red}9.84 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$78.9 \mathrm{ms} \pm 327 \mathrm{μs}\left({\color{gray}3.92 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$47.4 \mathrm{ms} \pm 202 \mathrm{μs}\left({\color{red}8.48 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$50.8 \mathrm{ms} \pm 350 \mathrm{μs}\left({\color{red}11.0 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$59.8 \mathrm{ms} \pm 373 \mathrm{μs}\left({\color{red}12.4 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$44.8 \mathrm{ms} \pm 178 \mathrm{μs}\left({\color{red}10.0 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$414 \mathrm{ms} \pm 879 \mathrm{μs}\left({\color{gray}-1.164 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$98.4 \mathrm{ms} \pm 479 \mathrm{μs}\left({\color{gray}1.98 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$88.4 \mathrm{ms} \pm 305 \mathrm{μs}\left({\color{gray}4.30 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$288 \mathrm{ms} \pm 780 \mathrm{μs}\left({\color{lightgreen}-8.526 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$18.0 \mathrm{ms} \pm 76.1 \mathrm{μs}\left({\color{red}21.5 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$18.2 \mathrm{ms} \pm 89.2 \mathrm{μs}\left({\color{red}18.3 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$18.7 \mathrm{ms} \pm 80.8 \mathrm{μs}\left({\color{red}20.3 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$19.1 \mathrm{ms} \pm 102 \mathrm{μs}\left({\color{red}26.1 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$24.0 \mathrm{ms} \pm 115 \mathrm{μs}\left({\color{red}34.1 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$18.8 \mathrm{ms} \pm 85.9 \mathrm{μs}\left({\color{red}26.5 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$19.3 \mathrm{ms} \pm 103 \mathrm{μs}\left({\color{red}32.4 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$18.8 \mathrm{ms} \pm 88.2 \mathrm{μs}\left({\color{red}28.5 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$19.1 \mathrm{ms} \pm 101 \mathrm{μs}\left({\color{red}25.6 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$31.9 \mathrm{ms} \pm 276 \mathrm{μs}\left({\color{red}40.5 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$44.3 \mathrm{ms} \pm 518 \mathrm{μs}\left({\color{red}52.1 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$42.9 \mathrm{ms} \pm 537 \mathrm{μs}\left({\color{red}46.5 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$44.3 \mathrm{ms} \pm 400 \mathrm{μs}\left({\color{red}52.5 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$45.1 \mathrm{ms} \pm 480 \mathrm{μs}\left({\color{red}54.1 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$45.7 \mathrm{ms} \pm 434 \mathrm{μs}\left({\color{red}51.2 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$45.3 \mathrm{ms} \pm 497 \mathrm{μs}\left({\color{red}52.8 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$42.9 \mathrm{ms} \pm 443 \mathrm{μs}\left({\color{red}46.1 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$44.1 \mathrm{ms} \pm 459 \mathrm{μs}\left({\color{red}47.8 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$44.5 \mathrm{ms} \pm 448 \mathrm{μs}\left({\color{red}43.9 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$8.18 \mathrm{ms} \pm 32.4 \mathrm{μs}\left({\color{gray}0.937 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$90.8 \mathrm{ms} \pm 613 \mathrm{μs}\left({\color{red}102 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$138 \mathrm{ms} \pm 517 \mathrm{μs}\left({\color{red}46.4 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$98.7 \mathrm{ms} \pm 464 \mathrm{μs}\left({\color{red}92.8 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$106 \mathrm{ms} \pm 457 \mathrm{μs}\left({\color{red}76.6 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$114 \mathrm{ms} \pm 468 \mathrm{μs}\left({\color{red}67.9 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$122 \mathrm{ms} \pm 475 \mathrm{μs}\left({\color{red}63.1 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$85.0 \mathrm{ms} \pm 392 \mathrm{μs}\left({\color{red}74.6 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$112 \mathrm{ms} \pm 558 \mathrm{μs}\left({\color{red}47.8 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$91.8 \mathrm{ms} \pm 432 \mathrm{μs}\left({\color{red}65.4 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$99.8 \mathrm{ms} \pm 416 \mathrm{μs}\left({\color{red}56.7 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$102 \mathrm{ms} \pm 538 \mathrm{μs}\left({\color{red}56.0 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$102 \mathrm{ms} \pm 443 \mathrm{μs}\left({\color{red}55.2 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$138 \mathrm{ms} \pm 539 \mathrm{μs}\left({\color{red}5.86 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$133 \mathrm{ms} \pm 572 \mathrm{μs}\left({\color{gray}1.39 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$42.1 \mathrm{ms} \pm 187 \mathrm{μs}\left({\color{lightgreen}-59.358 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$583 \mathrm{ms} \pm 1.02 \mathrm{ms}\left({\color{gray}-3.022 \mathrm{\%}}\right) $$ Flame Graph

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

Labels

area/apps > hash* Affects HASH (a `hash-*` app) area/apps > hash-graph area/apps area/libs Relates to first-party libraries/crates/packages (area) area/tests New or updated tests type/eng > backend Owned by the @backend team

Development

Successfully merging this pull request may close these issues.

2 participants