# Entities

Published base entity contracts for the Elevasis platform. Each entity ships as a TypeScript interface, a matching Zod schema, and an inferred `Input` type, generic over a `<TMeta>` extension slot.

External projects extend these in `core/types/entities.ts` to attach project-specific metadata while keeping the canonical shape stable.

## Published Exports

The published entry point exposes six entity contracts:

- `BaseProject<TMeta>`, `BaseProjectSchema`, `BaseProjectInput`
- `BaseMilestone<TMeta>`, `BaseMilestoneSchema`, `BaseMilestoneInput`
- `BaseTask<TMeta>`, `BaseTaskSchema`, `BaseTaskInput`
- `BaseDeal<TMeta>`, `BaseDealSchema`, `BaseDealInput`
- `BaseCompany<TMeta>`, `BaseCompanySchema`, `BaseCompanyInput`
- `BaseContact<TMeta>`, `BaseContactSchema`, `BaseContactInput`

Import them from the published subpath:

```ts
import { BaseDealSchema, type BaseDeal } from '@elevasis/core/entities'
```

## Extension Pattern

Each base interface accepts a generic metadata type. Extend the schema with `.extend({ metadata: ... })` and infer the type with `BaseProject<z.infer<typeof MetaSchema>>`.

```ts
import { z } from 'zod'
import { BaseProjectSchema, type BaseProject } from '@elevasis/core/entities'

const ProjectMetaSchema = z.object({
  budget: z.number().int().nonnegative(),
  clientPriority: z.enum(['low', 'medium', 'high'])
})

export const ProjectSchema = BaseProjectSchema.extend({ metadata: ProjectMetaSchema })
export type Project = BaseProject<z.infer<typeof ProjectMetaSchema>>
```

Use the base shape as-is when no extension is needed:

```ts
export const DealSchema = BaseDealSchema
export type Deal = BaseDeal
```

## Recipe

The full pattern is documented in the SDK scaffold bundle: `node_modules/@elevasis/sdk/reference/scaffold/recipes/extend-a-base-entity.md`.

The canonical template demo lives at `external/_template/core/types/entities.ts`.
