Enforce mandatory usage of @template/contracts across all packages. Prevents inline DTOs, schema drift, and inconsistent request/response handling. Trigger: When reviewing code for contract compliance or detecting inline schema definitions.
shared-contracts - Contract definitionscontract-versioning - SemVer and changelogcontract-testing - Fixture-based testingzod-4 - Schema validationtypescript - Type safety patternsEnsure every package strictly uses the @template/contracts package for shared data types. No inline DTOs allowed anywhere data crosses package boundaries.
@template/contractsActionResult<T> in Server Actionsui/, packages/core/, or other consumers// ❌ FORBIDDEN — schema defined inline instead of from contracts
"use server";
const LoginSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
export async function login(input: unknown) {
const parsed = LoginSchema.safeParse(input);
// ...
}
// ❌ FORBIDDEN — interface defined inline instead of from contracts
interface ChatMessage {
id: string;
role: "user" | "assistant";
content: string;
}
export function MessageBubble({ message }: { message: ChatMessage }) {
// ...
}
// ❌ FORBIDDEN — type defined locally in core
type UserProfile = {
id: string;
email: string;
name: string;
};
export function getUserProfile(): Promise<UserProfile> {
// ...
}
// ✅ REQUIRED — schema from @template/contracts
"use server";
import { LoginRequestSchema, type LoginResponse } from "@template/contracts";
type ActionResult<T> =
| { success: true; data: T }
| { success: false; error: string };
export async function login(
input: unknown
): Promise<ActionResult<LoginResponse>> {
const parsed = LoginRequestSchema.safeParse(input);
if (!parsed.success) {
return { success: false, error: "Invalid credentials" };
}
// ...
}
// ✅ REQUIRED — type from @template/contracts
import { type ChatMessage } from "@template/contracts";
export function MessageBubble({ message }: { message: ChatMessage }) {
// ...
}
// ✅ REQUIRED — type from @template/contracts
import { type UserProfile } from "@template/contracts";
export function getUserProfile(): Promise<UserProfile> {
// ...
}
Look for these patterns that indicate contract violations:
| Sign | Where | Problem |
|---|---|---|
z.object({...}) | In ui/ files | Inline schema — should be in contracts |
interface ...Request | In action files | Inline DTO — should be in contracts |
interface ...Response | In core files | Inline DTO — should be in contracts |
type ... = { | In component files (for API data) | Inline type — should be in contracts |
Missing @template/contracts import | Any file handling API data | Not using shared contracts |
Exception: Local component props (type ButtonProps) and UI-only state types are NOT violations — they don't cross package boundaries.
| Action | Invoke? |
|---|---|
| New Server Action created | ✅ Yes |
| New component consuming API data | ✅ Yes |
| Code review for contracts | ✅ Yes |
| Inline DTO detected | ✅ Yes |
| Local UI-only types | ❌ No |
@template/contractsshared-contracts skill