Skip to content

Models

Core domain models for the Imbi ecosystem.

Overview

The models module provides Pydantic models for all core domain entities (projects, organizations, teams) and the blueprint system for dynamic schema extension.

Model Categories

Domain Models

  • Organization: Top-level organizational units
  • Team: Groups within organizations
  • Environment: Deployment environments (production, staging, etc.)
  • ProjectType: Project categorization and templates
  • Project: Services and applications

Blueprint Models

  • Blueprint: Dynamic schema definitions
  • BlueprintAssignment: Blueprint-to-entity relationships

Basic Usage

from imbi_common import graph, models

# Create an organization
org = models.Organization(
    name="My Company",
    slug="my-company",
    description="Our organization"
)
await db.create(org)

# Create a team linked to an organization
team = models.Team(
    name="Platform Team",
    slug="platform-team",
    description="Infrastructure and platform",
    organization=org
)
await db.create(team)

API Reference

Base Classes

GraphModel

Bases: BaseModel

Minimal base for any model stored as a graph vertex.

Provides identity (id), timestamps, and extra='ignore' so AGE metadata is silently dropped. Subclass Node when you also need name/slug.

Node

Bases: GraphModel

Graph node with business identity fields.

The icon attribute can either be a URL or a CSS class name.

Domain Models

Organization

Bases: Node

Team

Bases: Node

Environment

Bases: Node

ProjectType

Bases: Node

Project

Bases: Node

Blueprint Models

Blueprint

Bases: Node

generate_and_validate_slug

generate_and_validate_slug() -> typing.Self

Generate slug from name if not provided and validate it.

Source code in src/imbi_common/models.py
@pydantic.model_validator(mode='after')
def generate_and_validate_slug(self) -> typing.Self:
    """Generate slug from name if not provided and validate it."""
    if self.slug is None:
        self.slug = slugify.slugify(self.name)
    else:
        self.slug = self.slug.lower()

    # Validate slug format
    if not self.slug:
        raise ValueError('Slug cannot be empty')
    if not all(c.islower() or c.isdigit() or c == '-' for c in self.slug):
        raise ValueError(
            'Slug must contain only lowercase letters, '
            'numbers, and hyphens'
        )
    return self

validate_kind_fields

validate_kind_fields() -> typing.Self

Validate kind-specific required fields.

Source code in src/imbi_common/models.py
@pydantic.model_validator(mode='after')
def validate_kind_fields(self) -> typing.Self:
    """Validate kind-specific required fields."""
    if self.kind == 'node':
        if not self.type:
            raise ValueError('type is required for node blueprints')
        invalid = [
            f
            for f in ('source', 'target', 'edge')
            if getattr(self, f) is not None
        ]
        if invalid:
            raise ValueError(
                f'{", ".join(invalid)} must be None for node blueprints'
            )
    else:
        if self.type is not None:
            raise ValueError(
                'type must be None for relationship blueprints'
            )
        missing = [
            f for f in ('source', 'target', 'edge') if not getattr(self, f)
        ]
        if missing:
            raise ValueError(
                f'{", ".join(missing)} required for '
                f'relationship blueprints'
            )
    return self

BlueprintAssignment

Bases: BaseModel

BlueprintEdge

Bases: NamedTuple