<!--
This file was generated by Spark. Do not edit it by hand.
-->
# Diffo.Provider.Extension

Unified DSL extension for all Diffo provider resource kinds.

Provides a single `provider do` section for Instance, Party, and Place kinds.
The sections within `provider do` are self-similar across kinds — each kind uses
the sections relevant to it, and verifiers enforce correct usage.

## Instance

    provider do
      specification do
        id "da9b207a-26c3-451d-8abd-0640c6349979"
        name "DSL Access Service"
        type :serviceSpecification
      end

      characteristics do
        characteristic :circuit, Diffo.Access.Circuit
      end

      features do
        feature :dynamic_line_management do
          characteristics do
            characteristic :constraints, Diffo.Access.Constraints
          end
        end
      end

      pools do
        pool :ports, :port
      end

      parties do
        party :provider, MyApp.Provider
        party_ref :owner, MyApp.InfrastructureCo
        parties :technicians, MyApp.Technician, constraints: [min: 1]
      end

      places do
        place :installation_site, MyApp.GeographicSite
        place_ref :billing_address, MyApp.GeographicAddress
      end

      behaviour do
        actions do
          create :build
        end
      end
    end

## Party

    provider do
      instances do
        role :facilitates, MyApp.AccessService
        instance_ref :manages, MyApp.InternalService
      end
      parties do
        role :employer, MyApp.Person
      end
      places do
        role :headquarters, MyApp.GeographicSite
      end
    end

## Place

    provider do
      instances do
        role :site_for, MyApp.AccessService
      end
      parties do
        role :managed_by, MyApp.Organization
      end
      places do
        role :within, MyApp.GeographicSite
      end
    end

See `Diffo.Provider.Extension.Info` for runtime introspection.
See `Diffo.Provider.BaseInstance`, `Diffo.Provider.BaseParty`, `Diffo.Provider.BasePlace`
for full usage documentation.


## provider
Provider DSL — structure, roles, and behaviour for this resource kind

### Nested DSLs
 * [specification](#provider-specification)
 * [characteristics](#provider-characteristics)
   * characteristic
   * inherited_characteristic
 * [features](#provider-features)
   * feature
     * characteristic
 * [pools](#provider-pools)
   * pool
 * [parties](#provider-parties)
   * party
   * parties
   * party_ref
   * role
   * inherited_party
 * [places](#provider-places)
   * place
   * places
   * place_ref
   * role
   * inherited_place
 * [instances](#provider-instances)
   * role
   * instance_ref
 * [relationships](#provider-relationships)
   * source
   * target
 * [behaviour](#provider-behaviour)
   * actions
     * create
     * update




### provider.specification
Defines the Instance Specification



### Examples
```
specification do
  id "da9b207a-26c3-451d-8abd-0640c6349979"
  name "DSL Access Service"
  type :serviceSpecification
  major_version 1
  description "An access network service"
  category "Network Service"
end

```




### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`id`](#provider-specification-id){: #provider-specification-id .spark-required} | `String.t` |  | The id of the specification, a uuid4 the same in all environments, unique for name and major_version. |
| [`name`](#provider-specification-name){: #provider-specification-name .spark-required} | `String.t` |  | The name of the specification. |
| [`type`](#provider-specification-type){: #provider-specification-type } | `atom` | `:serviceSpecification` | The type of the specification. |
| [`major_version`](#provider-specification-major_version){: #provider-specification-major_version } | `integer` | `1` | The major version of the specification. |
| [`minor_version`](#provider-specification-minor_version){: #provider-specification-minor_version } | `integer` |  | The minor version of the specification. |
| [`patch_version`](#provider-specification-patch_version){: #provider-specification-patch_version } | `integer` |  | The patch version of the specification. |
| [`tmf_version`](#provider-specification-tmf_version){: #provider-specification-tmf_version } | `integer` |  | The TMF API version of the specification, e.g. 4. |
| [`description`](#provider-specification-description){: #provider-specification-description } | `String.t` |  | A generic description of the specified service or resource. |
| [`category`](#provider-specification-category){: #provider-specification-category } | `String.t` |  | The category the specified service or resource belongs to. |




### provider.characteristics
List of Instance Characteristics

### Nested DSLs
 * [characteristic](#provider-characteristics-characteristic)
 * [inherited_characteristic](#provider-characteristics-inherited_characteristic)


### Examples
```
characteristics do
  characteristic :circuit, Diffo.Access.Circuit
  characteristic :line, Diffo.Access.Line
  # Inherit a typed characteristic from the assigner reached by following
  # the :port assignment alias (bare atom = reverse assignment shorthand)
  inherited_characteristic :uni, via: [:port]
  # Surface the typed characteristic of every assignee reached forward via :port
  inherited_characteristic :unis, via: [{:forward, assignment: :port}], read: :uni
end

```




### provider.characteristics.characteristic
```elixir
characteristic name, value_type
```


Adds a Characteristic





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#provider-characteristics-characteristic-name){: #provider-characteristics-characteristic-name .spark-required} | `atom` |  | The name of the characteristic. |
| [`value_type`](#provider-characteristics-characteristic-value_type){: #provider-characteristics-characteristic-value_type } | `any` |  | The type of the characteristic value — a module or `{:array, module}` for an array. |







### provider.characteristics.inherited_characteristic
```elixir
inherited_characteristic name
```


Declares a typed characteristic derived by walking the graph along a `via:` hop chain (assignment and/or relationship edges, in either direction) — generates a calculation; per-reached-instance the typed module is resolved at runtime via AshNeo4j.worlds/1





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#provider-characteristics-inherited_characteristic-name){: #provider-characteristics-inherited_characteristic-name .spark-required} | `atom` |  | The name of the generated calculation (Ash load/field handle), and the default `read` role. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`via`](#provider-characteristics-inherited_characteristic-via){: #provider-characteristics-inherited_characteristic-via } | `list(any)` |  | Ordered hop list. A bare atom is `{:reverse, assignment: alias}` shorthand; tuples are `{:forward \| :reverse, assignment: alias}` or `{:forward \| :reverse, relationship: type \| [type: t, alias: a]}`. Defaults to [name]. |
| [`read`](#provider-characteristics-inherited_characteristic-read){: #provider-characteristics-inherited_characteristic-read } | `atom` |  | The characteristic role to look up on each reached instance. Defaults to the calc name. |
| [`as`](#provider-characteristics-inherited_characteristic-as){: #provider-characteristics-inherited_characteristic-as } | `atom` |  | Renames the surfaced characteristic (loaded value and encoded entry). Defaults to the source characteristic's own name (no rename). |
| [`collapse`](#provider-characteristics-inherited_characteristic-collapse){: #provider-characteristics-inherited_characteristic-collapse } | `:first \| :last` |  | Collapses the result list to one end (`:first`/`:last`). When set, the calc returns a single record or nil rather than a list. |





### Introspection

Target: `Diffo.Provider.Extension.InheritedCharacteristicDeclaration`


### provider.features
Configuration for Instance Features

### Nested DSLs
 * [feature](#provider-features-feature)
   * characteristic


### Examples
```
features do
  feature :dynamic_line_management do
    is_enabled? true
    characteristics do
      characteristic :constraints, Diffo.Access.Constraints
    end
  end
end

```




### provider.features.feature
```elixir
feature name
```


Adds a Feature

### Nested DSLs
 * [characteristic](#provider-features-feature-characteristic)




### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#provider-features-feature-name){: #provider-features-feature-name .spark-required} | `atom` |  | The name of the feature. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`is_enabled?`](#provider-features-feature-is_enabled?){: #provider-features-feature-is_enabled? } | `boolean` |  | Whether the feature is enabled by default, defaults true. |


### provider.features.feature.characteristic
```elixir
characteristic name, value_type
```


Adds a Characteristic





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#provider-features-feature-characteristic-name){: #provider-features-feature-characteristic-name .spark-required} | `atom` |  | The name of the characteristic. |
| [`value_type`](#provider-features-feature-characteristic-value_type){: #provider-features-feature-characteristic-value_type } | `any` |  | The type of the characteristic value — a module or `{:array, module}` for an array. |












### provider.pools
Assignable pools on this Instance — each pool maps to an AssignableCharacteristic

### Nested DSLs
 * [pool](#provider-pools-pool)


### Examples
```
pools do
  pool :ports, :port
end

```




### provider.pools.pool
```elixir
pool name, thing
```


Declares an assignable pool — a named range of values for auto-assignment





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#provider-pools-pool-name){: #provider-pools-pool-name .spark-required} | `atom` |  | The pool name (matches the AssignableCharacteristic name). |
| [`thing`](#provider-pools-pool-thing){: #provider-pools-pool-thing .spark-required} | `atom` |  | The name of the thing being assigned within the pool (e.g. :port). |








### provider.parties
Party roles on this resource — `party`/`parties`/`party_ref`/`inherited_party` for Instance kinds; `role` for Party and Place kinds

### Nested DSLs
 * [party](#provider-parties-party)
 * [parties](#provider-parties-parties)
 * [party_ref](#provider-parties-party_ref)
 * [role](#provider-parties-role)
 * [inherited_party](#provider-parties-inherited_party)


### Examples
```
# Instance
parties do
  party :provider, MyApp.Provider
  party_ref :owner, MyApp.InfrastructureCo
  parties :technicians, MyApp.Technician, constraints: [min: 1]
  inherited_party :customer, source_role: :owner
end

# Party or Place
parties do
  role :employer, MyApp.Person
end

```




### provider.parties.party
```elixir
party role, party_type
```


Declares a singular party role on this Instance





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-parties-party-role){: #provider-parties-party-role .spark-required} | `atom` |  | The role name. |
| [`party_type`](#provider-parties-party-party_type){: #provider-parties-party-party_type } | `any` |  | The module of the Party kind. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`calculate`](#provider-parties-party-calculate){: #provider-parties-party-calculate } | `atom` |  | Ash calculation on this resource that produces the party. |





### Introspection

Target: `Diffo.Provider.Extension.PartyDeclaration`

### provider.parties.parties
```elixir
parties role, party_type
```


Declares a plural party role on this Instance





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-parties-parties-role){: #provider-parties-parties-role .spark-required} | `atom` |  | The role name. |
| [`party_type`](#provider-parties-parties-party_type){: #provider-parties-parties-party_type } | `any` |  | The module of the Party kind. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`calculate`](#provider-parties-parties-calculate){: #provider-parties-parties-calculate } | `atom` |  | Ash calculation on this resource that produces the party. |
| [`constraints`](#provider-parties-parties-constraints){: #provider-parties-parties-constraints } | `keyword` |  | Multiplicity constraints, e.g. [min: 1, max: 3]. |





### Introspection

Target: `Diffo.Provider.Extension.PartyDeclaration`

### provider.parties.party_ref
```elixir
party_ref role, party_type
```


Declares a singular reference party role — no direct PartyRef edge, reachable by graph traversal





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-parties-party_ref-role){: #provider-parties-party_ref-role .spark-required} | `atom` |  | The role name. |
| [`party_type`](#provider-parties-party_ref-party_type){: #provider-parties-party_ref-party_type } | `any` |  | The module of the Party kind. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`calculate`](#provider-parties-party_ref-calculate){: #provider-parties-party_ref-calculate } | `atom` |  | Ash calculation on this resource that produces the party. |





### Introspection

Target: `Diffo.Provider.Extension.PartyDeclaration`

### provider.parties.role
```elixir
role role, party_type
```


Declares a role this Party or Place kind plays with respect to other Parties





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-parties-role-role){: #provider-parties-role-role .spark-required} | `atom` |  | The role name. |
| [`party_type`](#provider-parties-role-party_type){: #provider-parties-role-party_type } | `any` |  | The module of the related Party kind. |






### Introspection

Target: `Diffo.Provider.Extension.PartyRole`

### provider.parties.inherited_party
```elixir
inherited_party role
```


Declares a party derived by walking the instance graph along a via: hop chain then reading a PartyRef at source_role — generates a calculation, no PartyRef node created





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-parties-inherited_party-role){: #provider-parties-inherited_party-role .spark-required} | `atom` |  | The generated calc name and surfaced PartyRef role; default single hop alias. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`source_role`](#provider-parties-inherited_party-source_role){: #provider-parties-inherited_party-source_role .spark-required} | `atom` |  | The PartyRef role to read on the reached instance (terminal deref, not a via: hop). |
| [`via`](#provider-parties-inherited_party-via){: #provider-parties-inherited_party-via } | `list(any)` |  | Hop chain to the instance holding the ref (unified #213 grammar). Bare atom = {:reverse, assignment: alias}; tuples are {:forward\|:reverse, assignment: alias} or {:forward\|:reverse, relationship: type\|[type:, alias:]}. Defaults to [role]. |
| [`collapse`](#provider-parties-inherited_party-collapse){: #provider-parties-inherited_party-collapse } | `:first \| :last` |  | Collapses the result list (refs at source_role across reached instances) to that end; the calc then returns a single party or nil. |





### Introspection

Target: `Diffo.Provider.Extension.InheritedPartyDeclaration`


### provider.places
Place roles on this resource — `place`/`places`/`place_ref`/`inherited_place` for Instance kinds; `role` for Party and Place kinds

### Nested DSLs
 * [place](#provider-places-place)
 * [places](#provider-places-places)
 * [place_ref](#provider-places-place_ref)
 * [role](#provider-places-role)
 * [inherited_place](#provider-places-inherited_place)


### Examples
```
# Instance
places do
  place :installation_site, MyApp.GeographicSite
  place_ref :billing_address, MyApp.GeographicAddress
  inherited_place :a_end, source_role: :location
  inherited_place :poi, via: [:cvc_link, :nni_link], source_role: :poi
end

# Party or Place
places do
  role :headquarters, MyApp.GeographicSite
end

```




### provider.places.place
```elixir
place role, place_type
```


Declares a singular place role on this Instance





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-places-place-role){: #provider-places-place-role .spark-required} | `atom` |  | The role name. |
| [`place_type`](#provider-places-place-place_type){: #provider-places-place-place_type } | `any` |  | The module of the Place kind. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`calculate`](#provider-places-place-calculate){: #provider-places-place-calculate } | `atom` |  | Ash calculation on this resource that produces the place. |





### Introspection

Target: `Diffo.Provider.Extension.PlaceDeclaration`

### provider.places.places
```elixir
places role, place_type
```


Declares a plural place role on this Instance





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-places-places-role){: #provider-places-places-role .spark-required} | `atom` |  | The role name. |
| [`place_type`](#provider-places-places-place_type){: #provider-places-places-place_type } | `any` |  | The module of the Place kind. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`calculate`](#provider-places-places-calculate){: #provider-places-places-calculate } | `atom` |  | Ash calculation on this resource that produces the place. |
| [`constraints`](#provider-places-places-constraints){: #provider-places-places-constraints } | `keyword` |  | Multiplicity constraints, e.g. [min: 1, max: 3]. |





### Introspection

Target: `Diffo.Provider.Extension.PlaceDeclaration`

### provider.places.place_ref
```elixir
place_ref role, place_type
```


Declares a singular reference place role — no direct PlaceRef edge, reachable by graph traversal





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-places-place_ref-role){: #provider-places-place_ref-role .spark-required} | `atom` |  | The role name. |
| [`place_type`](#provider-places-place_ref-place_type){: #provider-places-place_ref-place_type } | `any` |  | The module of the Place kind. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`calculate`](#provider-places-place_ref-calculate){: #provider-places-place_ref-calculate } | `atom` |  | Ash calculation on this resource that produces the place. |





### Introspection

Target: `Diffo.Provider.Extension.PlaceDeclaration`

### provider.places.role
```elixir
role role, place_type
```


Declares a role this Party or Place kind plays with respect to Places





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-places-role-role){: #provider-places-role-role .spark-required} | `atom` |  | The role name. |
| [`place_type`](#provider-places-role-place_type){: #provider-places-role-place_type } | `any` |  | The module of the related Place kind. |






### Introspection

Target: `Diffo.Provider.Extension.PlaceRole`

### provider.places.inherited_place
```elixir
inherited_place role
```


Declares a place derived by walking the instance graph along a via: hop chain then reading a PlaceRef at source_role — generates a calculation, no PlaceRef node created





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-places-inherited_place-role){: #provider-places-inherited_place-role .spark-required} | `atom` |  | The generated calc name and surfaced PlaceRef role; default single hop alias. |
### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`source_role`](#provider-places-inherited_place-source_role){: #provider-places-inherited_place-source_role .spark-required} | `atom` |  | The PlaceRef role to read on the reached instance (terminal deref, not a via: hop). |
| [`via`](#provider-places-inherited_place-via){: #provider-places-inherited_place-via } | `list(any)` |  | Hop chain to the instance holding the ref (unified #213 grammar). Bare atom = {:reverse, assignment: alias}; tuples are {:forward\|:reverse, assignment: alias} or {:forward\|:reverse, relationship: type\|[type:, alias:]}. Defaults to [role]. |
| [`collapse`](#provider-places-inherited_place-collapse){: #provider-places-inherited_place-collapse } | `:first \| :last` |  | Collapses the result list (refs at source_role across reached instances) to that end; the calc then returns a single place or nil. |





### Introspection

Target: `Diffo.Provider.Extension.InheritedPlaceDeclaration`


### provider.instances
Declares the roles this Party or Place kind plays with respect to Instances

### Nested DSLs
 * [role](#provider-instances-role)
 * [instance_ref](#provider-instances-instance_ref)


### Examples
```
instances do
  role :facilitates, MyApp.AccessService
  instance_ref :manages, MyApp.InternalService
end

```




### provider.instances.role
```elixir
role role, instance_type
```


Declares a role this Party or Place kind plays with respect to Instances





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-instances-role-role){: #provider-instances-role-role .spark-required} | `atom` |  | The role name. |
| [`instance_type`](#provider-instances-role-instance_type){: #provider-instances-role-instance_type } | `any` |  | The module of the related Instance kind. |






### Introspection

Target: `Diffo.Provider.Extension.InstanceRole`

### provider.instances.instance_ref
```elixir
instance_ref role, instance_type
```


Declares a reference instance role — no direct edge created, reachable by graph traversal





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`role`](#provider-instances-instance_ref-role){: #provider-instances-instance_ref-role .spark-required} | `atom` |  | The role name. |
| [`instance_type`](#provider-instances-instance_ref-instance_type){: #provider-instances-instance_ref-instance_type } | `any` |  | The module of the related Instance kind. |






### Introspection

Target: `Diffo.Provider.Extension.InstanceRole`


### provider.relationships
Relationship role permissions for this Instance — declares which aliases it may participate in as source or target. Omitting defaults to `:none` per direction.

### Nested DSLs
 * [source](#provider-relationships-source)
 * [target](#provider-relationships-target)


### Examples
```
relationships do
  source [:provides, :requires]
  target :all
end

```




### provider.relationships.source
```elixir
source roles
```


Declares permitted source relationship roles — pipeline step, last declaration wins





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`roles`](#provider-relationships-source-roles){: #provider-relationships-source-roles .spark-required} | `any` |  | `:all`, `:none`, or a list of role name atoms. |







### provider.relationships.target
```elixir
target roles
```


Declares permitted target relationship roles — pipeline step, last declaration wins





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`roles`](#provider-relationships-target-roles){: #provider-relationships-target-roles .spark-required} | `any` |  | `:all`, `:none`, or a list of role name atoms. |








### provider.behaviour
Defines the behavioural wiring for the Instance — actions, and in future triggers

### Nested DSLs
 * [actions](#provider-behaviour-actions)
   * create
   * update


### Examples
```
behaviour do
  actions do
    create :build
  end
end

```



### provider.behaviour.actions
Declares which actions to wire for instance behaviour

### Nested DSLs
 * [create](#provider-behaviour-actions-create)
 * [update](#provider-behaviour-actions-update)


### Examples
```
actions do
  create :build
  update :define
end

```




### provider.behaviour.actions.create
```elixir
create name
```


Marks a create action for instance build wiring





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#provider-behaviour-actions-create-name){: #provider-behaviour-actions-create-name .spark-required} | `atom` |  | The name of the create action to wire. |







### provider.behaviour.actions.update
```elixir
update name
```


Marks an update action for instance behaviour wiring





### Arguments

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`name`](#provider-behaviour-actions-update-name){: #provider-behaviour-actions-update-name .spark-required} | `atom` |  | The name of the update action to wire. |















<style type="text/css">.spark-required::after { content: "*"; color: red !important; }</style>
