Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/carrot-foundation/methodology-rules --skill rule-schemas명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | rule-schemas |
| description | Rule mapping for schemas |
Apply this rule whenever work touches:
*.tsZod is the runtime validation library for this project. Schemas serve a dual purpose: they validate data at runtime boundaries and provide the canonical type definition via z.infer.
Define schemas close to the types they describe. A common pattern is to export both from the same file:
import { z } from 'zod';
export const VehicleSchema = z.object({
plate: z.string().min(7),
weightKg: z.number().positive(),
type: z.enum(['truck', 'van', 'car']),
});
export type Vehicle = z.infer<typeof VehicleSchema>;
Never create a separate interface Vehicle that duplicates the schema shape.
Choose the right parse method based on the trust level of the data:
// External input (API payload, S3 object, SQS message) - handle errors
const result = VehicleSchema.safeParse(rawPayload);
if (!result.success) {
logger.warn('Invalid vehicle payload', result.error.flatten());
return { error: 'INVALID_INPUT' };
}
const vehicle = result.data;
// Internal data (already validated upstream) - let it throw
const vehicle = VehicleSchema.parse(trustedData);
Reuse schemas through composition rather than copy-pasting fields:
const BaseDocumentSchema = z.object({
id: z.string().uuid(),
createdAt: z.string().datetime(),
});
const CertificateSchema = BaseDocumentSchema.extend({
issuer: z.string(),
validUntil: z.string().datetime(),
});
Use zocker and the shared testing utilities to generate test data from schemas:
import { createStubFromSchema } from '@carrot-fndn/shared/testing';
const stubVehicle = createStubFromSchema(VehicleSchema);
This ensures test data always conforms to the current schema shape and evolves automatically when the schema changes.
Document schemas are organized in five layers with progressive strictness:
| Layer | Naming convention | Zod strategy | Purpose |
|---|---|---|---|
| Envelope | LoadedDocumentEnvelopeSchema | z.object | Wrapper for loaded documents |
| Inbound | Inbound*Schema | z.object (strips unknown fields) | Boundary contract for external data |
| Normalized | *Schema | z.object (strips unknown fields) | Strict internal representation |
| Domain | Bold*Schema, MassID*Schema, RewardsDistribution*Schema | z.object with methodology-specific fields | Methodology-specific extensions |
| Rule | *RuleSubjectSchema | z.object with exact fields needed | Exact contract per rule processor |
Key conventions:
z.object: Every layer strips unknown fields on parse. Do not use z.looseObject in layer schemas — each layer should be more specific, not more permissive.z.looseObject for predicate/getter validators only: Narrow structural checks in predicate or getter helpers (e.g. "does this event have a metadata.attributes array?") may use z.looseObject to avoid rejecting objects that carry extra fields they don't inspect. These are not layer schemas.*RuleSubjectSchema that describes the exact data it needs.validateRuleSubjectOrThrow: Standard entry point for rule subject validation. Use this instead of calling .parse() directly.z.enum() for value sets: Define allowed values as a const object, then derive a z.enum() from its values. Use .extract() to narrow to a subset and .literal() for single-value constraints in deeper layers. Domain-scoped enums use declaration merging (const + type + schema) to provide both dot-notation access and a Zod schema:// Domain enum with declaration merging (schema-first)
export const BoldVehicleType = {
BICYCLE: 'Bicycle',
TRUCK: 'Truck',
} as const;
export const BoldVehicleTypeSchema = z.enum(
Object.values(BoldVehicleType) as [string, ...string[]],
);
// eslint-disable-next-line no-redeclare
export type BoldVehicleType = z.infer<typeof BoldVehicleTypeSchema>;
// Usage: dot-notation in value position, type in type position
const vehicle = BoldVehicleType.TRUCK;
const isValid: BoldVehicleType = 'Bicycle';
// Narrower layer
const TruckOnlySchema = BoldVehicleTypeSchema.extract(['Truck']);
Do not use TypeScript enum — always use the const-object + z.enum() pattern above.