[Traits](https://oods-foundry.com/traits) / Addressable

# Addressable

Canonical multi-role address trait with validation metadata, geocoding, and international formatting hooks.

Generated from @oods/foundry 0.10.1

- Group

  core

- Maturity

  experimental

- Contexts

  detail, form, list

Provides a single, reusable capability for billing, shipping, warehouse, and office addresses.

## Fields it adds

| Field | Type | Required | Description |
| - | - | - | - |
| `address_roles` | `string[]` | yes | Ordered list of roles that currently have address entries. |
| `default_address_role` | `string` | no | Role surfaced in UI contexts when one address must be highlighted. |
| `addresses` | `AddressableEntry[]` | no | Collection of { role, address, metadata } entries keyed by role. |

## What it shows in each context

- [list](https://oods-foundry.com/contexts/list)

  `AddressSummaryBadge`

- [detail](https://oods-foundry.com/contexts/detail)

  `AddressCollectionPanel`

- [form](https://oods-foundry.com/contexts/form)

  `AddressEditor`

## Parameters

- `roles` `string[]`, required

  Ordered list of supported address roles (billing, shipping, warehouse, etc.).

- `defaultRole` `string`

  Preferred role returned when consumers omit a role argument.

- `allowDynamicRoles` `boolean`

  Allow runtime creation of roles that are not pre-declared in roles.

## Objects that use it

- [Organization](https://oods-foundry.com/objects/organization)
- [User](https://oods-foundry.com/objects/user)

## The trait file

`traits/core/Addressable.trait.yaml`

```
trait:
  name: Addressable
  version: 1.0.0
  description: |
    Canonical multi-role address trait with validation metadata, geocoding, and international formatting hooks.
    Provides a single, reusable capability for billing, shipping, warehouse, and office addresses.
  category: core
  tags:
    - address
    - location
    - validation
    - delivery

parameters:
  - name: roles
    type: string[]
    required: true
    description: Ordered list of supported address roles (billing, shipping, warehouse, etc.).
    default:
      - billing
      - shipping
    validation:
      minItems: 1
      maxItems: 16
      uniqueItems: true
      items:
        pattern: "^[a-z0-9._-]+$"
        minLength: 2
        maxLength: 32
  - name: defaultRole
    type: string
    required: false
    description: Preferred role returned when consumers omit a role argument.
    validation:
      enumFromParameter: roles
  - name: allowDynamicRoles
    type: boolean
    required: false
    description: Allow runtime creation of roles that are not pre-declared in roles.
    default: false

schema:
  address_roles:
    type: string[]
    required: true
    description: Ordered list of roles that currently have address entries.
    default: []
  default_address_role:
    type: string
    required: false
    description: Role surfaced in UI contexts when one address must be highlighted.
    validation:
      enumFromParameter: roles
  addresses:
    type: AddressableEntry[]
    required: false
    description: Collection of { role, address, metadata } entries keyed by role.
    default: []

semantics:
  addresses:
    semantic_type: location.address.collection
    token_mapping: tokenMap(location.address.collection)
    ui_hints:
      component: AddressCollection
      roleParameter: roles
      defaultRoleField: default_address_role
  default_address_role:
    semantic_type: location.address.default_role
    token_mapping: tokenMap(location.address.default_role)
    ui_hints:
      component: AddressRoleBadge
      parameterSource: defaultRole
  address_roles:
    semantic_type: location.address.roles
    token_mapping: tokenMap(location.address.roles)
    ui_hints:
      component: AddressRolePills

view_extensions:
  list:
    - component: AddressSummaryBadge
      position: after
      props:
        field: default_address_role
  detail:
    - component: AddressCollectionPanel
      position: main
      priority: 60
      props:
        field: addresses
        roleField: address_roles
        defaultRoleField: default_address_role
        roleParameter: roles
  form:
    - component: AddressEditor
      position: top
      props:
        field: addresses
        roleParameter: roles
        allowDynamicParameter: allowDynamicRoles
        defaultRoleField: default_address_role

tokens:
  location.address.card.bg: "var(--sys-surface-raised)"
  location.address.card.border: "var(--sys-border-subtle)"
  location.address.role.text: "var(--sys-text-muted)"

dependencies: []

metadata:
  created: "2025-11-17"
  owners:
    - core@oods.systems
    - platform@oods.systems
  maturity: experimental
  accessibility:
    keyboard: "AddressEditor respects standard focus order and announces role changes."
    screenreader: "AddressCollection surfaces headings per role and announces validation status."
  regionsUsed:
    - list
    - detail
    - form
  examples:
    - User
    - Organization
  references:
    - "R21.1 Canonical Model for Address/Location Systems"
```
