All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.
v0.4.1 (2026-05-22)
- Assigner lifecycle (#168) — broadened the lifecycle states permitted to make assignments. Services may now assign from
:feasibilityChecked,:reserved,:inactive,:active, or:suspended(was:active/:inactiveonly). Resources may now assign from:installingor:operating(was:operatingonly).Assigner.assignable_state?/1exposes the policy directly.
-
Diffo.Provider.Changes.Define/Relate/Assign(#170) — change modules that wrap the standard after-action patterns every Instance consumer writes. Replace the hand-writtenafter_actionbody threadingCharacteristic.update_all/Pool.update_pools/Relationship.relate_instance/Assigner.assigntogether with a one-liner:update :define do argument :characteristic_value_updates, {:array, :term} change Diffo.Provider.Changes.Define end update :relate do argument :relationships, {:array, :struct} change Diffo.Provider.Changes.Relate end update :assign_port do argument :assignment, :struct, constraints: [instance_of: Assignment] change {Diffo.Provider.Changes.Assign, pool: :ports} end
Reload happens via the resource's primary
:readaction, so no consumer-specific reader is needed. -
BaseCharacteristic auto-generated
:create/:updateactions (#171) —BaseCharacteristic-derived resources now get default:createand:updateactions synthesised from their public attributes.:createaccepts[:name | <public_attrs>]with:instance_id/:feature_idarguments andmanage_relationshipchanges;:updateaccepts<public_attrs>. Consumers may still declare their own actions to override the defaults. -
Typed characteristics and pools in Instance JSON (#169) —
BaseInstancenow loads two new calculations (:typed_characteristics,:pool_characteristics) by default and the jason customize merges their values into theserviceCharacteristic/resourceCharacteristicarray. TypedBaseCharacteristicrecords andAssignableCharacteristicpool records that were already present in the graph are now visible at the TMF JSON surface.
Diffo.Provider.Calculations.TypedCharacteristicsandDiffo.Provider.Calculations.PoolCharacteristics— new calc modules backing the JSON surfacing for #169.- Regression test added for #62 (characteristic update validation) — typed
BaseCharacteristicupdates now reject unknown fields and invalid types through Ash's standard changeset machinery.
v0.4.0 (2026-05-20)
Diffo.Provider.AssignedToRelationshipreplaced byDiffo.Provider.AssignmentRelationship— stores pool assignments with top-levelpool,thing,value, andaliasscalar attributes, enabling graph-level filtering in AshNeo4j queries. Any existing graph data onAssignedToRelationshipnodes must be migrated.create_assigned_to_relationshipcode interface removed — usecreate_assignment_relationshipinstead.instance.assignmentsnow returnsAssignmentRelationshiprecords (struct name change only).
DefinedSimpleRelationship— new resource for relationships carrying an optional single embeddedNameValuePrimitivecharacteristic, frozen at creation. Used by the Assigner and available as a general-purpose committed-relationship primitive. Accessible viainstance.assignments.AssignmentRelationshipaliases — thealiasattribute onAssignmentRelationship(identity[:target_id, :alias]) gives a consuming instance a stable name for an assignment slot. Mirrors the[:source_id, :alias]identity onDefinedSimpleRelationship. Alias semantics are the foundation of the first-order expectation system (#74).relationships doDSL — source and target validation pipeline for Instance resources.ValidateRelationshipPermittedis injected automatically into relate actions. Supports:all,:none, and explicit role-name lists.- Resource lifecycle states —
resource_stateattribute on Instance resources with standard TMF states (:installed,:operating,:retired, etc.). The Assigner enforces:operatingbefore allowing assignment. inherited_place/inherited_partyDSL — declare insideplaces do/parties doon an Instance resource to generate an Ash calculation that traverses the assignment graph by alias and inherits a place or party from the source instance. NoPlaceRef/PartyRefedge is created — the calculation is the reference. Supports single-hop (default: role name as alias) and multi-hop (via:list).FieldFromAssignment(Diffo.Provider.Calculations.FieldFromAssignment) — reads a field directly from anAssignmentRelationshiprecord (:value,:pool,:thing,:alias). Filtered by optionalalias:. Returns a list.FieldViaAssignedRelationship(Diffo.Provider.Calculations.FieldViaAssignedRelationship) — traversesAssignmentRelationshipin reverse (target → source) and reads a named field from each source instance. Supports multi-hopvia:traversal. Returns a list.FieldViaRelationship(Diffo.Provider.Calculations.FieldViaRelationship) — traversesDefinedSimpleRelationshipforward (source → target) filtered by optionalalias:and/ortype:, and reads a named field from each target instance. Returns a list.
- Assigner rearchitected —
AssignmentRelationshipcarriespool,thing,value,aliasas top-level attributes for AshNeo4j-level filtering;assigned_valuesandfree_valuesuse query-level filtering rather than in-memory computation where possible. TransformBehaviourmoved from persister pipeline to transformer pipeline for correct Spark ordering relative to Ash's own transformers.- Characteristic type verifier improved — rejects
characteristicDSL declarations whose type module is not derived fromBaseCharacteristic.
usage-rules.md— new sections covering alias semantics,inherited_place/inherited_partyDSL, and all three field calculation modules including a decision table.AGENTS.md— updated project structure, DSL inline examples for inherited refs, and new common mistakes section entries.- Provider Extension livebook — new section "Aliases, Inherited DSL, and Field Calculations" with Compute-domain examples.
- defined_simple_relationship by @matt-beanland in #142
- refactored assigner using defined_simple_relationship by @matt-beanland in #143
- relationships DSL by @matt-beanland in #146
- relationships target side validation by @matt-beanlanda in #148
- clean code by @matt-beanland in #150
- improved assigner using aggregates by @matt-beanland in #151
- refactor transformers and persisters by @matt-beanland in #152
- resource lifecycle state by @matt-beanland in #154
- inherited party and place via instance DSL by @matt-beanland in #155
- agent guidance by @matt-beanland in #161
- FieldViaAssignedRelationship calculation by @matt-beanland in #162
- FieldViaRelationship calculation by @matt-beanland in #165
- FieldFromAssignment calculation by @matt-beanland in #164
- docs pass — inherited DSL, aliases, and field calculations by @matt-beanland in #166
v0.3.0 (2026-05-17)
Diffo.Provider.Relationshipno longer stores assignment records. Assignment relationships are now onDiffo.Provider.AssignedToRelationship. Any existing graph data withtype: :assignedToonRelationshipnodes will need to be migrated.instance.forward_relationshipsno longer contains assignment records — useinstance.assignmentsinstead.Diffo.Provider.create_assignment_relationshipremoved — useDiffo.Provider.create_assigned_to_relationship.
Diffo.Provider.BaseRelationship— new Ash Resource Fragment providing common attributes and behaviour for all relationship typesDiffo.Provider.AssignedToRelationship— new dedicated resource for pool assignment relationships, split out fromDiffo.Provider.RelationshipDiffo.Provider.Relationship— now TMF-only;pool,thing,assignedattributes and:create_assignmentaction removedinstance.assignments— newhas_manyonBaseInstancefor pool assignment relationships; included in JSON encoding and default loadsDiffo.Provider.BaseCharacteristic— new Ash Resource Fragment for typed characteristic resources;ShelfCharacteristic,CardCharacteristicetc. now extend this rather than using plainAsh.TypedStructpools doDSL — new section on Instance resources replacing the oldcharacteristic :name, AssignableValuepattern; generatespools/0andpool/1introspection functions- Module naming convention — Instance resources must be suffixed
…Instance, Characteristic resources…Characteristicto avoid Neo4j label collisions (documented inusage-rules.mdandAGENTS.md) Diffo.Provider.Extension— unified Spark DSL extension consolidating the prior per-kind extensions
- provider extension consolidation by @matt-beanland in #130
- base characteristic by @matt-beanland in #133
- assigner refactor — BaseRelationship, AssignedToRelationship, pools DSL, resource naming by @matt-beanland in #135
v0.2.2 (2026-05-08)
- Updated to ash_neo4j 0.5.0 with async test support
- Igniter installer —
mix igniter.install diffonow sets up Neo4j config, custom expressions, and Spark DSL formatter - Spark DSL formatter configured for all provider extensions;
mix formatenforced across the codebase usage-rules.mdadded for AI coding assistant guidance when working with Diffo
- async tests by @matt-beanland in #114
- igniter by @matt-beanlanda in #116
- spark formatter by @matt-beanlanda in #117
- usage_rules by @matt-beanlanda in #118
v0.2.1 (2026-05-06)
- Updated to ash_neo4j 0.4.1 and bolty 0.0.12, now supporting transactions and test sandbox
- Improvements to provider DSL and documentation
- base party and related DSL and livebook by @matt-beanland in #82
- Instance DSL parties — multiplicity, validation, and enforcement by @matt-beanland in #89
- 86 transformers persisters verifiers by @matt-beanland in #92
- 91 place dsl by @matt-beanland in #93
- 79 provider instance specification doesnt set description by @matt-beanland in #95
- 94 provider instance specification dsl additional fields by @matt-beanland in #97
- document instance versioning lifecycle by @matt-beanland in #98
- accept raw dynamic by @matt-beanland in #100
- removed duplicate tests by @matt-beanland in #108
- 105 latest ash neo4j by @matt-beanland in #109
v0.2.0 (2026-04-24)
- Updated to ash_neo4j 0.3.1 and bolty 0.0.10 — no database compatibility with prior versions due to significant changes in the data layer and Bolt protocol handling
Diffo.Type.Value— union ofDiffo.Type.PrimitiveandDiffo.Type.Dynamic, enabling mixed primitive and typed-struct values on characteristics and other resourcesDiffo.Type.Primitive— typed union of string, integer, float, boolean, date, time, datetime, durationDiffo.Type.Dynamic— runtime-typed struct for Ash.Type.NewType valuesDiffo.Type.Dynamic.is_valid?/1— predicate to check whether a module is a valid Dynamic type (Ash.Type.NewType with storage_type :map) before constructing a valueCharacteristic.values— homogeneous array ofDiffo.Type.Valueon a characteristic, withis_arrayboolean flag; supports morphing between scalar and array representationsDiffo.UnwraponList— unwraps each element, enablingDiffo.Unwrap.unwrap/1to reduce nested wrapped lists to plain Elixir values in one call- Provider instance extension DSL — characteristic and feature characteristic value types now accept
{:array, Module}in addition to plain module references
Diffo.Type.Valuenil update — overridehandle_change/3to prevent Ash union type from wrapping nil in the previous member type, which caused malformed JSON to be written to Neo4jDiffo.Type.Valuenil array update — added nil guards tohandle_change_array/3andprepare_change_array/3to prevent enumeration errors when setting an array characteristic to nilDiffo.Type.Dynamicnil safety — added nil clauses tocast_stored/2anddump_to_native/2
- bolty 0.0.10 — native DateTime handling for both BOLT 4.x and BOLT 5.x
Diffo.Unwrapprotocol documentation — recursive unwrap behaviour, custom implementation guide, and array examples added to livebook and module docs
v0.1.6 (2026-03-19)
- incorrect domain label
- improved error handling
v0.1.5 (2026-03-19)
- fixed relationship enrichment inconsistent across neo4j versions
v0.1.4 (2026-03-12)
- assigner unassign operation
- updated ash_neo4j, uses bolty rather than boltx
v0.1.3 (2025-12-01)
- place_ref source party or place
- party_ref source place or party
- instance events
- remove access domain
v0.1.2 (2025-10-20)
- REUSE compliant
v0.1.1 (2025-09-09)
- update for AshNeo4j DSL changes
- refactor specification relationships
- characteristic value schemas
- customise instance via specification
- improve relationships to avoid circular loads
v0.1.0 (2025-08-11)
- initial version on AshNeo4j DataLayer