Integration Contracts
Every new Mistflow app ships with a contracts/ directory: a Zod-backed validation layer derived from your Drizzle schema. It exists so that when the schema changes, every touchpoint that depends on the schema changes with it, in one place, not five.
This page explains what drift looks like, what the contract layer does, and how to add it to a project that doesn’t have one yet.
What drift looks like without contracts
Section titled “What drift looks like without contracts”Say you have a habit tracker with a habits table. Somewhere in your app:
- A server action inserts new habits (
name,targetDaysPerWeek,color) - A form on the client collects those fields
- A list view displays habits by joining onto a
streakstable
One day the AI adds a reminderTime column to habits. Without a contract layer, it has to find every one of those places by hand and update each one to match. The form schema doesn’t know about the new field. The server action still rejects it. The list view is fine until someone filters by reminder time, at which point it returns the wrong shape.
This is the drift problem: one source of truth in db/schema.ts, three or four places that have to be manually synced to it.
What the contracts/ directory does
Section titled “What the contracts/ directory does”Mistflow scaffolds every new app with a contracts/ directory that re-exports Zod schemas derived from your Drizzle tables using drizzle-zod. A habit tracker’s layout looks roughly like this:
db/ schema.ts # Drizzle tables, the source of truthcontracts/ habit.ts # Zod schemas derived from db/schema.ts index.ts # Re-exports everythingInside contracts/habit.ts:
import { createInsertSchema, createSelectSchema } from 'drizzle-zod';import { z } from 'zod';import { habits } from '@/db/schema';
export const HabitRow = createSelectSchema(habits);export const HabitInsert = createInsertSchema(habits, { name: z.string().min(1).max(80), targetDaysPerWeek: z.number().int().min(1).max(7),});export const HabitUpdate = HabitInsert.partial();
export type Habit = z.infer<typeof HabitRow>;export type NewHabit = z.infer<typeof HabitInsert>;Every consumer of the habits shape imports from contracts/ instead of redefining the shape inline:
- Forms use
HabitInsertviazodResolver(HabitInsert)inreact-hook-form - Server actions call
HabitInsert.parse(input)before touching the database - API routes validate request bodies with
HabitInsert - List views type their data as
Habit[]
Now when the AI adds reminderTime, it edits db/schema.ts once. drizzle-zod picks up the new column, Zod’s type inference updates, TypeScript catches every place that was assuming the old shape, and the form/server-action/API-route all converge to the new shape in one pass.
What the AI is instructed to do with it
Section titled “What the AI is instructed to do with it”methodologies/mistflow-stack.md is the context document every Mistflow build loads into the editor. It has a section on contracts that tells the AI:
- Never write inline Zod schemas for persisted entities. Use
contracts/. - When adding a column, edit
db/schema.tsfirst. The contract and every consumer follow from that. - Before writing a server action, import the insert schema from
contracts/. Don’t hand-roll validation. - If the schema change adds a required field, update the form’s default values. TypeScript will usually catch this but not always.
mist_implement also surfaces the existing contracts as part of its context.crud payload, so the editor sees what’s already defined before it generates new code.
Retrofitting an existing project
Section titled “Retrofitting an existing project”Projects created before MCP 0.5.0 don’t have a contracts/ directory. Retrofit with:
mist contracts initThis scans db/schema.ts, writes a contract file per table, and adds the appropriate imports. Run it from the project root.
To check that the contracts still match the schema (for example, after a manual schema edit):
Contract drift is surfaced by mist_project with action: "get" — the response flags schema/contract mismatches so your editor can regenerate or add entities before continuing.
Where to go next
Section titled “Where to go next”- The CLI guide, full
mist contractsreference - The feature manifest, the other half of the keep-the-plan-honest story