You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
8
+
## [1.8.15]
9
+
10
+
### Added
11
+
12
+
-**`FieldType.UUID`** — logical scalar (incl. `LIST``item_type`); TigerGraph / Nebula / Postgres DDL store as `STRING` / `TEXT`.
13
+
-**`Vertex.assigned`** / **`identity_mode == "assigned"`** — intentional UUID primary key, distinct from `blank`. Empty identity is minted with `uuid4()` at assemble time (before edge projection); writer keeps an idempotent safety net. Assigned vertices do **not** participate in blank-edge resolution.
14
+
-**`VertexConfig.assigned_vertices`**; helpers in **`graflo.db.identity_uuid`** (`ensure_assigned_uuid`, `validate_uuid_value`, …).
15
+
- Docs: four identity modes and blank vs assigned in [vertex identity](docs/concepts/schema/vertex_identity.md); UUID moved to supported field types.
Copy file name to clipboardExpand all lines: docs/concepts/architecture/core_components.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -91,15 +91,17 @@ A `Vertex` describes vertices and their logical identity. It supports:
91
91
-**LIST-typed properties cannot be identity / hash-identity sources**
92
92
- Filtering conditions
93
93
-**`blank: true`** — placeholder vertex with no natural key; identity defaults to **`id`** when omitted
94
+
-**`assigned: true`** — intentional UUID primary key; identity defaults to **`id`**; mint at assemble (not blank-edge resolution)
94
95
-**`hash_identity_properties`** — when non-empty, SHA256 hash of these source fields produces a deterministic synthetic **`id`** (see [Vertex identity modes](../schema/vertex_identity.md))
95
-
-**`Vertex.identity_mode`** — derived runtime mode: **`natural`** (upsert on `identity`), **`hash`**, or **`blank`**
96
+
-**`Vertex.identity_mode`** — derived runtime mode: **`natural`**, **`hash`**, **`blank`**, or **`assigned`**
Identity defaults at schema level (`VertexConfig`):
205
206
206
207
- **`identity_from_all_properties: true`** (default) — vertices without explicit **`identity`** use all **`properties`** names as the logical key.
207
-
- **`identity_from_all_properties: false`** — each non-blank vertex must declare **`identity`** explicitly; blank vertices still default to **`id`**.
208
+
- **`identity_from_all_properties: false`** — each non-blank / non-assigned vertex must declare **`identity`** explicitly; blank and assigned vertices still default to **`id`**.
208
209
209
-
**Blank vertices:** set **`blank: true`** on the vertex entry under **`schema.graph.vertex_config.vertices`**. **`VertexConfig.blank_vertices`** is a derived list of names (not a separate YAML field). **`VertexConfig.hash_identity_vertices`** lists vertices with hash-derived identity. At runtime, **`ResourceRuntime`** keeps only vertex types referenced by that resource’s pipeline (and edge-inference selectors); blank types that are declared in the schema but not used by the resource are not injected automatically—include a **`vertex`** (or edge) step when the placeholder must be populated.
210
+
**Blank vertices:** set **`blank: true`** on the vertex entry under **`schema.graph.vertex_config.vertices`**. **`VertexConfig.blank_vertices`** is a derived list of names (not a separate YAML field). **`VertexConfig.hash_identity_vertices`** lists vertices with hash-derived identity; **`VertexConfig.assigned_vertices`** lists intentional UUID-PK vertices. At runtime, **`ResourceRuntime`** keeps only vertex types referenced by that resource’s pipeline (and edge-inference selectors); blank types that are declared in the schema but not used by the resource are not injected automatically—include a **`vertex`** (or edge) step when the placeholder must be populated.
210
211
211
212
Algorithmic identity inference from record samples: **`graflo.db.identity_inference`** (`IdentityInferencer`, `apply_identity_inference_to_vertices`). See [Vertex identity modes](../schema/vertex_identity.md) and [Example 15](../../examples/example-15.md).
Copy file name to clipboardExpand all lines: docs/concepts/schema/vertex_identity.md
+45-10Lines changed: 45 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,23 +2,35 @@
2
2
3
3
GraFlo vertices declare how records are matched during upserts through fields on the logical **`Vertex`** model in `schema.graph.vertex_config`. Identity semantics are **not** configured in `DatabaseProfile` or `IngestionModel`.
4
4
5
-
## Three runtime modes
5
+
## Four runtime modes
6
6
7
-
Each vertex resolves to one of three modes via the derived property **`Vertex.identity_mode`**:
7
+
Each vertex resolves to one of four modes via the derived property **`Vertex.identity_mode`**. Modes describe **how the upsert key is obtained** (not string encoding). They are mutually exclusive.
|**`natural`**|`false`|`[]`|`[f]` or `[f1, f2, ...]`| Upsert on declared fields (same code path for one or many fields) |
12
-
|**`hash`**|`false`|`[f1, f2, ...]`|`["id"]`| SHA256 of hash sources → synthetic `id`, then upsert |
13
-
|**`blank`**|`true`|`[]`|`["id"]`| Random UUID → synthetic `id`, then upsert |
9
+
|`identity_mode`| Authored signal |`identity`| Key behavior |
10
+
|---|---|---|---|
11
+
|**`natural`**| default |`[f]` or `[f1, f2, …]`| Upsert on declared fields. If a field is typed **`UUID`**, validate shape when present — **do not invent**. |
12
+
|**`hash`**| non-empty `hash_identity_properties`|`["id"]`| SHA256 of hash sources → synthetic `id`, then upsert |
13
+
|**`assigned`**|`assigned: true`|`["id"]`| Intentional UUID PK: empty → `uuid4()` at **assemble** (before edge projection); writer is an idempotent safety net. **Not** blank-edge resolution. |
14
+
|**`blank`**|`blank: true`|`["id"]`| Placeholder: random UUID at write time; listed in `blank_vertices`; **does** blank-edge resolution |
14
15
15
16
Unary and composite natural keys are the **same runtime mode**. The upsert path passes `Vertex.identity` to the database as `match_keys`; width does not change the write branch.
16
17
18
+
### Blank vs assigned
19
+
20
+
Both may mint a random UUID when the synthetic `id` is empty, but they are not interchangeable:
21
+
22
+
||`blank`|`assigned`|
23
+
|---|---|---|
24
+
| Meaning | No business identity / placeholder | Intentional UUID primary key |
25
+
| Mint timing | Writer (`_assign_blank_vertex_ids`) | Assemble (before `assemble_edges`); writer net is idempotent |
| Typical use | Mentions, ephemeral join stubs | Events / entities whose PK is a UUID |
28
+
17
29
## Schema fields
18
30
19
31
### `identity`
20
32
21
-
Logical field name(s) used for upsert matching. For `hash`and `blank` modes the normalizer sets `identity` to `["id"]` (GraFlo canonical synthetic key; ArangoDB maps to `_key` at write time).
33
+
Logical field name(s) used for upsert matching. For `hash`, `blank`, and `assigned` modes the normalizer sets `identity` to `["id"]` (GraFlo canonical synthetic key; ArangoDB maps to `_key` at write time).
22
34
23
35
### `hash_identity_properties`
24
36
@@ -35,7 +47,30 @@ Example:
35
47
36
48
### `blank`
37
49
38
-
Placeholder vertices with no stable natural key; each record gets a random UUID at ingest time.
50
+
Placeholder vertices with no stable natural key; each record gets a random UUID at ingest time and may participate in blank-edge expansion.
51
+
52
+
### `assigned`
53
+
54
+
Intentional UUID primary key. Empty identity is filled with `uuid4()` so cast-time edge projections see the key. Present valid UUIDs are preserved; invalid non-empty values raise.
55
+
56
+
```yaml
57
+
- name: event
58
+
properties:
59
+
- { name: id, type: UUID }
60
+
- { name: payload, type: STRING }
61
+
identity: [id]
62
+
assigned: true
63
+
```
64
+
65
+
Natural key that happens to be a UUID (no new mode):
66
+
67
+
```yaml
68
+
- name: user
69
+
properties:
70
+
- { name: external_id, type: UUID }
71
+
- { name: email, type: STRING }
72
+
identity: [external_id]
73
+
```
39
74
40
75
## Inference vs runtime
41
76
@@ -64,4 +99,4 @@ See [Example 15](../../examples/example-15.md) for a CSV → manifest → ingest
64
99
| **`DatabaseProfile`** | Physical indexes and storage names only |
65
100
| **`IngestionModel`** | Pipeline and connectors only; no identity semantics |
66
101
67
-
`VertexConfig.hash_identity_vertices`and `VertexConfig.vertices_by_identity_mode()` are derived lists for runtime introspection and `db_writer` branching.
102
+
`VertexConfig.hash_identity_vertices`, `VertexConfig.blank_vertices`, `VertexConfig.assigned_vertices`, and `VertexConfig.vertices_by_identity_mode()` are derived lists for runtime introspection and `db_writer` / assemble branching.
0 commit comments