identity tier

identity-party-places

Link between parties (orgs, persons) and places (physical locations) with roles

Link between parties (orgs, persons) and places (physical locations) with roles

Tieridentity
Roleunclassified (baselined)
Pathcrates/identity/party-places
Edition2021
Targetsidentity_party_places
Public items51 across 1 module
Tests26

What it is for

# identity-party-places

Link between parties (organizations, persons, groups) and places (physical locations).

Design Philosophy

A PartyPlace answers: "What role does this place play for this party?"

This enables:

Key Relationships

Organization (Party)
│
├── PartyPlace (role=headquarters, is_primary=true)
│      └── Place (Phoenix HQ)
│            ├── Contact (local phone)
│            └── Identifier (google_place_id)
│
├── PartyPlace (role=branch)
│      └── Place (Surprise Branch)
│            ├── Contact (branch phone)
│            └── Identifier (google_place_id)
│
└── PartyPlace (role=branch)
└── Place (Sun City Branch)
├── Contact (branch phone)
└── Identifier (google_place_id)

Example

use identity_party_places::{PartyPlace, PartyType, PlaceRole};
use uuid::Uuid;

// Link an organization to its headquarters
let hq_link = PartyPlace::new(
Uuid::new_v4(),  // tenant_id
PartyType::Organization,
Uuid::new_v4(),  // org_id
Uuid::new_v4(),  // place_id (Phoenix HQ)
)
.with_role(PlaceRole::Headquarters)
.as_primary();

// Link same org to a branch
let branch_link = PartyPlace::new(
hq_link.tenant_id,
PartyType::Organization,
hq_link.party_id,
Uuid::new_v4(),  // place_id (Surprise Branch)
)
.with_role(PlaceRole::Branch)
.with_label("Surprise Location");

Capabilities

PartyPlace:PartyPlace

# identity-party-places

Item
pub struct PartyPlace

PartyPlace:as

# identity-party-places

Item
PartyPlace :: fn as_primary(mut self) -> Self

PartyPlace:branch

# identity-party-places

Item
PartyPlace :: fn branch(tenant_id : Uuid, party_type : PartyType, party_id : Uuid, place_id : Uuid) -> Self

PartyPlace:builder

# identity-party-places

Item
PartyPlace :: fn builder() -> PartyPlaceBuilder

PartyPlace:created

# identity-party-places

Item
PartyPlace :: fn created_at(& self) -> DateTime <Utc>

PartyPlace:deactivate

# identity-party-places

Item
PartyPlace :: fn deactivate(mut self) -> Self

PartyPlace:deleted

# identity-party-places

Item
PartyPlace :: fn deleted_at(& self) -> Option <DateTime <Utc>>

PartyPlace:display

# identity-party-places

Item
PartyPlace :: fn display_name(& self) -> String

PartyPlace:headquarters

# identity-party-places

Item
PartyPlace :: fn headquarters(tenant_id : Uuid, party_type : PartyType, party_id : Uuid, place_id : Uuid,) -> Self

PartyPlace:home

# identity-party-places

Item
PartyPlace :: fn home(tenant_id : Uuid, party_id : Uuid, place_id : Uuid) -> Self

PartyPlace:id

# identity-party-places

Item
PartyPlace :: fn id(& self) -> Uuid

PartyPlace:is

# identity-party-places

Item
PartyPlace :: fn is_headquarters(& self) -> bool
PartyPlace :: fn is_branch(& self) -> bool
PartyPlace :: fn is_effective(& self) -> bool

PartyPlace:new

# identity-party-places

Item
PartyPlace :: fn new(tenant_id : Uuid, party_type : PartyType, party_id : Uuid, place_id : Uuid) -> Self

PartyPlace:updated

# identity-party-places

Item
PartyPlace :: fn updated_at(& self) -> DateTime <Utc>

PartyPlace:with

# identity-party-places

Item
PartyPlace :: fn with_role(mut self, role : PlaceRole) -> Self
PartyPlace :: fn with_label(mut self, label : impl Into <String>) -> Self
PartyPlace :: fn with_notes(mut self, notes : impl Into <String>) -> Self
PartyPlace :: fn with_effective_dates(mut self, from : Option <DateTime <Utc>>, to : Option <DateTime <Utc>>,) -> Self

PartyPlace:work

# identity-party-places

Item
PartyPlace :: fn work(tenant_id : Uuid, party_id : Uuid, place_id : Uuid) -> Self

PartyPlaceBuilder:PartyPlaceBuilder

# identity-party-places

Item
pub struct PartyPlaceBuilder

PartyPlaceBuilder:build

# identity-party-places

Item
PartyPlaceBuilder :: fn build(self) -> Result <PartyPlace, PartyPlaceError>

PartyPlaceBuilder:effective

# identity-party-places

Item
PartyPlaceBuilder :: fn effective_from(mut self, from : DateTime <Utc>) -> Self
PartyPlaceBuilder :: fn effective_to(mut self, to : DateTime <Utc>) -> Self

PartyPlaceBuilder:is

# identity-party-places

Item
PartyPlaceBuilder :: fn is_primary(mut self, is_primary : bool) -> Self
PartyPlaceBuilder :: fn is_active(mut self, is_active : bool) -> Self

PartyPlaceBuilder:label

# identity-party-places

Item
PartyPlaceBuilder :: fn label(mut self, label : impl Into <String>) -> Self

PartyPlaceBuilder:new

# identity-party-places

Item
PartyPlaceBuilder :: fn new() -> Self

PartyPlaceBuilder:notes

# identity-party-places

Item
PartyPlaceBuilder :: fn notes(mut self, notes : impl Into <String>) -> Self

PartyPlaceBuilder:party

# identity-party-places

Item
PartyPlaceBuilder :: fn party_type(mut self, party_type : PartyType) -> Self
PartyPlaceBuilder :: fn party_id(mut self, party_id : Uuid) -> Self

PartyPlaceBuilder:place

# identity-party-places

Item
PartyPlaceBuilder :: fn place_id(mut self, place_id : Uuid) -> Self

PartyPlaceBuilder:role

# identity-party-places

Item
PartyPlaceBuilder :: fn role(mut self, role : PlaceRole) -> Self

PartyPlaceBuilder:tenant

# identity-party-places

Item
PartyPlaceBuilder :: fn tenant_id(mut self, tenant_id : Uuid) -> Self

PartyPlaceError

# identity-party-places

Item
pub enum PartyPlaceError

PartyType

# identity-party-places

Item
pub enum PartyType
PartyType :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result
PartyType :: fn from_str(s : & str) -> Result <Self, Self::Err>

PlaceRole

# identity-party-places

Item
pub enum PlaceRole
PlaceRole :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result
PlaceRole :: fn from_str(s : & str) -> Result <Self, Self::Err>

repo (other)

Tenant-scoped repository for the composed "party address" surface —

Item
async fn create_party_address_for_tenant(pool : & PgPool, tenant_id : Uuid, party_type : PartyType, party_id : Uuid, role : PlaceRole, label : Option <& str>, is_primary : bool, street1 : & str, street2 : Option <& str>, city : & str, state : Option <& str>, postal_code : Option <& str>, country : & str,) -> Result <PartyAddress, PartyAddressRepoError>
async fn find_party_address_by_id_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid,) -> Result <Option <PartyAddress>, PartyAddressRepoError>
async fn list_party_addresses_for_party_for_tenant(pool : & PgPool, tenant_id : Uuid, party_id : Uuid, role : Option <PlaceRole>,) -> Result <Vec <PartyAddress>, PartyAddressRepoError>
async fn update_party_address_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid, role : PlaceRole, label : Option <& str>, is_active : bool, street1 : & str, street2 : Option <& str>, city : & str, state : Option <& str>, postal_code : Option <& str>, country : & str,) -> Result <Option <PartyAddress>, PartyAddressRepoError>
async fn set_primary_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid,) -> Result <Option <PartyAddress>, PartyAddressRepoError>

PartyAddress

Tenant-scoped repository for the composed "party address" surface —

Item
pub struct PartyAddress

PartyAddressRepoError

Tenant-scoped repository for the composed "party address" surface —

Item
pub enum PartyAddressRepoError
PartyAddressRepoError :: fn from(e : GeoRepoError) -> Self
async fn soft_delete_party_address_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid,) -> Result <(), PartyAddressRepoError>

How to use it

From this crate's own rustdoc:


## Example

Module structure

identity_party_places

Public surface

`crate root`

ItemWhat it is
pub enum PartyPlaceErrorParty-place link errors.
pub enum PartyTypeType of party in the link.
PartyType :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result
PartyType :: fn from_str(s : & str) -> Result <Self, Self::Err>
pub enum PlaceRoleRole/purpose of the place for the party.
PlaceRole :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result
PlaceRole :: fn from_str(s : & str) -> Result <Self, Self::Err>
pub struct PartyPlaceA link between a party and a place with role semantics
PartyPlace :: fn new(tenant_id : Uuid, party_type : PartyType, party_id : Uuid, place_id : Uuid) -> SelfCreate a new party-place link.
PartyPlace :: fn builder() -> PartyPlaceBuilderCreate a new builder.
PartyPlace :: fn with_role(mut self, role : PlaceRole) -> SelfSet the role.
PartyPlace :: fn with_label(mut self, label : impl Into <String>) -> SelfSet the label.
PartyPlace :: fn as_primary(mut self) -> SelfMark as primary.
PartyPlace :: fn with_notes(mut self, notes : impl Into <String>) -> SelfSet notes.
PartyPlace :: fn with_effective_dates(mut self, from : Option <DateTime <Utc>>, to : Option <DateTime <Utc>>,) -> SelfSet effective dates.
PartyPlace :: fn deactivate(mut self) -> SelfDeactivate this link.
PartyPlace :: fn is_headquarters(& self) -> boolCheck if this is the headquarters.
PartyPlace :: fn is_branch(& self) -> boolCheck if this is a branch location.
PartyPlace :: fn is_effective(& self) -> boolCheck if this link is currently effective.
PartyPlace :: fn display_name(& self) -> StringGet a display-friendly name.
PartyPlace :: fn id(& self) -> Uuid
PartyPlace :: fn created_at(& self) -> DateTime <Utc>
PartyPlace :: fn updated_at(& self) -> DateTime <Utc>
PartyPlace :: fn deleted_at(& self) -> Option <DateTime <Utc>>
pub struct PartyPlaceBuilderBuilder for PartyPlace.
PartyPlaceBuilder :: fn new() -> SelfCreate a new builder.
PartyPlaceBuilder :: fn tenant_id(mut self, tenant_id : Uuid) -> SelfSet the tenant ID.
PartyPlaceBuilder :: fn party_type(mut self, party_type : PartyType) -> SelfSet the party type.
PartyPlaceBuilder :: fn party_id(mut self, party_id : Uuid) -> SelfSet the party ID.
PartyPlaceBuilder :: fn place_id(mut self, place_id : Uuid) -> SelfSet the place ID.
PartyPlaceBuilder :: fn role(mut self, role : PlaceRole) -> SelfSet the role.
PartyPlaceBuilder :: fn label(mut self, label : impl Into <String>) -> SelfSet the label.
PartyPlaceBuilder :: fn is_primary(mut self, is_primary : bool) -> SelfSet as primary.
PartyPlaceBuilder :: fn is_active(mut self, is_active : bool) -> SelfSet as active.
PartyPlaceBuilder :: fn effective_from(mut self, from : DateTime <Utc>) -> SelfSet effective from date.
PartyPlaceBuilder :: fn effective_to(mut self, to : DateTime <Utc>) -> SelfSet effective to date.
PartyPlaceBuilder :: fn notes(mut self, notes : impl Into <String>) -> SelfSet notes.
PartyPlaceBuilder :: fn build(self) -> Result <PartyPlace, PartyPlaceError>Build the party-place link
PartyPlace :: fn headquarters(tenant_id : Uuid, party_type : PartyType, party_id : Uuid, place_id : Uuid,) -> SelfCreate a headquarters link.
PartyPlace :: fn branch(tenant_id : Uuid, party_type : PartyType, party_id : Uuid, place_id : Uuid) -> SelfCreate a branch link.
PartyPlace :: fn home(tenant_id : Uuid, party_id : Uuid, place_id : Uuid) -> SelfCreate a home address link (for persons).
PartyPlace :: fn work(tenant_id : Uuid, party_id : Uuid, place_id : Uuid) -> SelfCreate a work address link (for persons).

`repo`

ItemWhat it is
pub enum PartyAddressRepoErrorErrors from the repository layer
PartyAddressRepoError :: fn from(e : GeoRepoError) -> Self
pub struct PartyAddressThe flattened read/write shape the API exposes — one row that answers "what does this party call this address, and where is it" without the caller ever walking party_places -> geo_places -> geo_addresses (ADR 0037)
async fn create_party_address_for_tenant(pool : & PgPool, tenant_id : Uuid, party_type : PartyType, party_id : Uuid, role : PlaceRole, label : Option <& str>, is_primary : bool, street1 : & str, street2 : Option <& str>, city : & str, state : Option <& str>, postal_code : Option <& str>, country : & str,) -> Result <PartyAddress, PartyAddressRepoError>Create a party address: one geo_addresses row, one geo_places row (its own, never shared — ADR 0037 decision 2) and one party_places row, all in ONE transaction (AC1)
async fn find_party_address_by_id_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid,) -> Result <Option <PartyAddress>, PartyAddressRepoError>One party address by id, scoped to tenant_id
async fn list_party_addresses_for_party_for_tenant(pool : & PgPool, tenant_id : Uuid, party_id : Uuid, role : Option <PlaceRole>,) -> Result <Vec <PartyAddress>, PartyAddressRepoError>Every non-deleted address for one party, scoped to tenant_id, optionally filtered to one role
async fn update_party_address_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid, role : PlaceRole, label : Option <& str>, is_active : bool, street1 : & str, street2 : Option <& str>, city : & str, state : Option <& str>, postal_code : Option <& str>, country : & str,) -> Result <Option <PartyAddress>, PartyAddressRepoError>Update a party address: the linked geo_addresses row AND the party_places row's role/label/is_active, in ONE transaction
async fn soft_delete_party_address_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid,) -> Result <(), PartyAddressRepoError>Soft-delete (AC5)
async fn set_primary_for_tenant(pool : & PgPool, tenant_id : Uuid, id : Uuid,) -> Result <Option <PartyAddress>, PartyAddressRepoError>Demote every other primary address in the same (party_id, role) scope, then promote id, atomically (AC3)

No pub use re-exports: every item above is declared in this crate.

Boundary

Reaches into domain, foundation.

Shares tier identity with 7 other crates: identity-auth, identity-identifiers, identity-impersonation, identity-parties, identity-rbac, identity-tenant, identity-user-prefs.

_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._

Where it sits

Tier (ontology)identity
Architectural role (taxonomy)unclassified (baselined)
Locationcrates/identity/party-places
Vocabulary in force (lexicon)current

Tier flow. Which tiers this crate's own edges cross.

flowchart LR
  n_identity["identity"] --> n_domain["domain"]
  n_identity["identity"] --> n_foundation["foundation"]

Dependencies

Runtime, in this workspace.

CrateTierOptionalOnly on
`domain-geo`domainnoalways
`foundation-basemodels`foundationnoalways

Runtime, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
chrono^0.4serdenoalways
serde^1derivenoalways
serde_json^1noalways
sqlx^0.8runtime-tokio, postgres, chrono, uuid, jsonnoalways
thiserror^2noalways
tokio^1fullnoalways
uuid^1v4, v7, serde, jsnoalways

Development, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
tokio-test^0.4noalways

Build. None.

Depended on by. 1 workspace crate.

Signal flow — what reaches this crate, and what it reaches.

flowchart LR
  n_application_parties["application-parties"] -->|uses| SELF
  SELF["identity-party-places"]
  SELF -->|runtime| n_domain_geo["domain-geo"]
  SELF -->|runtime| n_foundation_basemodels["foundation-basemodels"]
  classDef self fill:#1f883d,stroke:#1f883d,color:#fff;
  class SELF self;

Feature flags

No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.

Targets

KindNameSource
libidentity_party_places`src/lib.rs`

Error model

Error typeNamed by
PartyAddressRepoErrorcreate_party_address_for_tenant, find_party_address_by_id_for_tenant, list_party_addresses_for_party_for_tenant, set_primary_for_tenant, soft_delete_party_address_for_tenant, update_party_address_for_tenant
PartyPlaceErrordeclared, no public signature returns it

Operational characteristics

PropertyEvidence
async public surfaceyes
async runtimeyes
database accessyes
network I/Onone detected
unsafe codenone detected
environment variablesnone detected

No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.

Configuration

No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.

1 workspace crate depends on this one: application-parties.

Verification

KindCount
Unit tests26
Integration tests0
Examples0
Doctests1

Evidence by module. How often each public module is named by something executable.

ModuleTestsExamplesConsumers
crate root504
repo808

What the tests establish, by name:

Documentation coverage

MeasureDocumentedTotal
Public items with rustdoc4251
Public modules with a //! block11
pie showData
    title Public items with rustdoc
    "Documented" : 42
    "No rustdoc detected" : 9

Metrics

MetricValue
Rust source files2
Source lines1502
Code lines980
Public API items51
Public modules1
Tests26
Examples0
Cargo features0
Direct runtime dependencies9
Workspace reverse dependencies1
pie showData
    title Public API by kind
    "enum" : 4
    "function" : 6
    "method" : 38
    "struct" : 3
pie showData
    title Rust source composition
    "Code" : 980
    "Blank or comment" : 522

Generation

Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.

All identity · Manual