How Contract Coding Works
Contract Coding turns change requests into contracts that can be validated, compiled, and reviewed before they enter the codebase. This page looks at that flow at two levels: first, when a team defines contracts directly for its own system; second, when Midi Coder turns that approach into a full pipeline from contract to reviewable patch.
What a contract means here
In this context, a contract is a structured specification layer for the system's domain and behavior. It can define business entities, allowed actions, rules, workflows, API mappings, and important end-to-end flows that must remain correct.
A contract is not a free-form prompt. It is also not a temporary snapshot of the current code. In a contract-first model, the contract is treated as the source of truth for behavior, while code is generated, checked, and applied from that specification layer.
The key point is that the contract is strict enough to validate, but still closer to business intent than low-level implementation. That allows the team to review change at the level of intent before looking at the final code diff.
The overall pipeline
From this section onward, the default frame is Midi Coder's implementation of contract coding. At a high level, the Midi Coder flow looks like this:
-
01
Identify the requirement
Identify or update the required change.
-
02
Turn it into a contract
Turn that change into a contract.
-
03
Validate
Validate the contract at both schema level and cross-file level.
-
04
Compile to IR
Compile the valid contract into an IR.
-
05
Build the code plan
Build a code plan from that IR for the target stack.
-
06
Generate the patch
Generate the corresponding patch.
-
07
Apply and review
Apply the patch to the codebase and review the result.
-
08
Feedback loop
If issues are found, record feedback, update the contract, and run the flow again.
In Midi Coder, the front of the flow usually starts from master-brief.md, project context, and a schema summary to generate draft contracts. If a user authors contracts directly, the brief-generation step can be skipped, but validation, compilation, review, and traceability remain core to the process.
The important constraint is that code does not go directly from prompt to file. It goes through contracts, checks, and an intermediate layer before becoming a patch that can be reviewed.
Contract set structure
In the way Midi Coder organizes contracts, a contract is not treated as a single file but as a multi-file contract set. Those files live in a clear directory structure, where each group of files holds a different kind of information.
A typical directory structure, following the example suggested in contracts-spec, looks like this:
You do not need the full set on day one. A team can start with a minimal set such as:
As the domain becomes clearer or the flow becomes more complex, the contract set can expand with events, queries, projections, workflows, policies, and scenarios. If the team is using Midi Coder's tooling, this does not necessarily mean writing every file by hand from scratch. In Midi Coder's flow, the contract set can be generated as a full or near-full draft from the brief, project context, and schema, and then reviewed, refined, and validated. This separation keeps files shorter, makes review easier, and enables stronger validation than putting everything into one long descriptive document.
What each contract layer does
Within Midi Coder's DSL, each contract layer answers a different question.
| Layer | Role |
|---|---|
Entity | Describes the core business entities of the system. This is where the team defines fields, primary keys, indexes, constraints, and tenant scope where relevant. |
Command | Describes the write actions or state-changing operations the system allows. This is where the question "what can the system do" is formalized into input, guards, effects, errors, and outputs. |
Query / Projection | Describe the read side. They separate read logic from write logic and make the read model more explicit. |
Rule / Policy | Describe conditions, constraints, and access control. Instead of embedding every condition directly in a command, rules and policies are separated to make the specification easier to read, easier to change, and easier to review. |
Workflow | Describes the lifecycle of an entity over time. This is where states and transitions are made explicit instead of being scattered through implementation code. |
Effect | Describes system-side consequences such as writing data, emitting events, calling integrations, or sending email. It is the contract-level way to say what the system does after an action occurs. |
API | Is the mapping layer from behavior to HTTP or GraphQL. It does not introduce new business behavior. It connects the external interface to the application layer. |
Scenario | Describes important end-to-end flows so the full chain of behavior can be checked at a higher level. |
Validation | Is the layer that checks the integrity of the contract set as a whole. One part is per-file schema validation. The other is cross-file checking to ensure that ids, refs, commands, routes, events, workflows, and effects line up correctly. |
One point should be explicit: the source materials do not define a separate UI contract layer. If the page needs to talk about the external surface, it should do so in terms of APIs or external interfaces, not by implying a dedicated frontend DSL that the current materials do not support.
Why this flow is more controlled
In Midi Coder's implementation, the main difference is that change is controlled at multiple layers, not only at the final code diff.
First, the contract is the source of truth for behavior. That forces the team to state clearly what the system is supposed to do before code is generated.
Second, schema validation and cross-file checking eliminate many structural errors early. If a command references an entity that does not exist, a route maps to the wrong command, or an effect uses an undefined event, the flow can stop before code generation begins.
Third, the IR and code-plan stages create an intermediate layer between intent and implementation. That makes generation inspectable and repeatable instead of relying on a fresh free-form prompt every time.
Fourth, code is applied as a patch rather than through arbitrary file edits. That gives the team something reviewable at both the contract level and the patch level.
Fifth, contract diffs let the team review change at the level of business intent. The team does not only see which files changed. It also sees which behavior changed.
Finally, because output is tied to a specific contract version, it is possible to trace from code back to the contract that produced it. That is the basis for auditability, traceability, and repeatability when the contract and pipeline stay constant.
An end-to-end example
The example below still follows the way Midi Coder implements the flow. The chosen case is uploading HR documents to Amazon S3 in an employee attendance, payroll, and HR document system.
At the business-requirement level, the problem makes several things explicit: HR can upload employee documents, the system stores files in S3, metadata is stored in the database, and authorized users can later retrieve a file URL or a secure download URL. This is a strong example because it involves not only entities and commands, but also rules, permissions, workflows, events, and API routes.
# Master Brief: Employee Attendance, Payroll & HR Document System
---
# 1. Tổng quan
### Mục tiêu sản phẩm/dịch vụ
Xây dựng hệ thống quản lý nhân sự bao gồm:
* chấm công nhân viên
* gửi bảng lương qua email
* hiển thị thời tiết khi check-in
* **lưu trữ hồ sơ nhân sự trên cloud (Amazon S3)**
Hệ thống giúp:
* HR quản lý hồ sơ nhân sự tập trung
* nhân viên truy cập bảng lương
* lưu trữ tài liệu an toàn và có thể mở rộng.
---
### Đối tượng sử dụng chính
| Actor | Mô tả |
| -------- | ----------------------------- |
| Employee | check-in, nhận bảng lương |
| HR | quản lý nhân sự, upload hồ sơ |
| Admin | quản trị hệ thống |
---
### Phạm vi
**In scope**
* attendance management
* payroll email delivery
* weather integration
* **upload / download HR documents**
* **lưu hồ sơ nhân sự trên S3**
**Out of scope**
* document OCR
* document approval workflow
* DMS phức tạp
---
### Bối cảnh hệ thống liên quan
Hệ thống tích hợp với:
* HRM System
* Payroll System
* Email Service
* Weather API
* **Amazon S3 Storage**
---
### Thuật ngữ chính
| Term | Meaning |
| ----------- | ---------------- |
| Payroll | bảng lương |
| Payslip | file bảng lương |
| HR Document | tài liệu nhân sự |
| S3 Object | file lưu trên S3 |
---
### Metadata version
```yaml
owner: HR Tech Team
version: 1.2
environment: production
contact: hr-tech@company.com
```
---
# 2. Domain & Data
## Entities (map to `domain/entities.yaml`)
### Employee
```yaml
id: UUID
employee_code: string
name: string
email: string
department: string
position: string
status: string
created_at: timestamp
```
### AttendanceRecord
```yaml
id: UUID
employee_id: UUID
date: date
check_in_time: timestamp
check_out_time: timestamp
status: string
total_work_hours: decimal
weather_description: string
temperature: decimal
```
### Payroll
```yaml
id: UUID
employee_id: UUID
period_start: date
period_end: date
net_salary: Money
status: string
created_at: timestamp
```
### Payslip
```yaml
id: UUID
payroll_id: UUID
employee_id: UUID
file_url: string
sent_at: timestamp
email_status: EmailStatus
```
### HRDocument
```yaml
id: UUID
employee_id: UUID
document_type: DocumentType
file_name: string
file_url: string
s3_bucket: string
s3_key: string
uploaded_by: UUID
uploaded_at: timestamp
```
---
## Value Objects (map to `domain/value_objects.yaml`)
### WeatherInfo
```yaml
condition: string
description: string
temperature: decimal
retrieved_at: timestamp
```
### Money
```yaml
amount: decimal
currency: string (default: "VND")
```
### DocumentMetadata
```yaml
file_size: integer
mime_type: string
upload_time: timestamp
```
---
## Enum (map to `domain/entities.yaml` or separate enum definitions)
### DocumentType
```yaml
values:
- cv
- contract
- identity_card
- tax_document
- other
```
### EmailStatus
```yaml
values:
- pending
- sent
- failed
```
### AttendanceStatus
```yaml
values:
- present
- absent
- late
- half_day
```
---
## Errors (map to `domain/errors.yaml`)
```yaml
EmployeeNotFound:
code: "EMPLOYEE_NOT_FOUND"
message: "Employee not found"
http_status: 404
AttendanceNotFound:
code: "ATTENDANCE_NOT_FOUND"
message: "Attendance record not found"
http_status: 404
PayrollNotFound:
code: "PAYROLL_NOT_FOUND"
message: "Payroll not found"
http_status: 404
DocumentNotFound:
code: "DOCUMENT_NOT_FOUND"
message: "HR document not found"
http_status: 404
FileUploadFailed:
code: "FILE_UPLOAD_FAILED"
message: "Failed to upload file"
http_status: 500
S3StorageError:
code: "S3_STORAGE_ERROR"
message: "S3 storage operation failed"
http_status: 500
EmailDeliveryFailed:
code: "EMAIL_DELIVERY_FAILED"
message: "Failed to send email"
http_status: 500
Unauthorized:
code: "UNAUTHORIZED"
message: "Unauthorized access"
http_status: 401
FileSizeExceeded:
code: "FILE_SIZE_EXCEEDED"
message: "File size exceeds 20MB limit"
http_status: 400
```
---
## Persistence Model
### hr_documents
```
id UUID
employee_id UUID
document_type VARCHAR
file_name VARCHAR
file_url TEXT
s3_bucket VARCHAR
s3_key VARCHAR
uploaded_by UUID
uploaded_at TIMESTAMP
```
---
# 3. Luồng nghiệp vụ chính & Scenarios
---
## Luồng A: Check-in
1. employee gửi request check-in
2. system xác thực JWT
3. system gọi Weather API
4. system tạo attendance record
---
## Luồng B: Gửi bảng lương
1. HR approve payroll
2. system tạo payslip
3. system gửi email
4. employee nhận bảng lương
---
## Luồng C: Upload hồ sơ nhân sự
Actor: HR
Steps
1. HR chọn employee
2. HR upload file
3. system upload file lên **Amazon S3**
4. system lưu metadata vào database
5. trả về file_url
---
## Luồng D: Xem hồ sơ nhân sự
Actor: HR / Admin
Steps
1. request document list
2. system truy vấn database
3. trả về **S3 file URL**
---
## Acceptance Scenarios
### Scenario 1
```
Given HR uploads employee document
When upload succeeds
Then file stored in S3
And metadata stored in database
```
---
### Scenario 2
```
Given employee payroll approved
When HR sends payroll
Then employee receives email
```
---
# 4. Commands & Queries
---
## Commands (map to `app/commands.yaml`)
### UploadEmployeeDocumentCommand
**Goal**: Upload HR document to S3 and store metadata
**Input**:
```yaml
employee_id: UUID
document_type: DocumentType
file: binary
uploaded_by: UUID
```
**Output**:
```yaml
document_id: UUID
file_url: string
```
**Side Effects**:
- Upload file to S3 bucket
- Store metadata in hr_documents table
**Errors**:
- EmployeeNotFound
- FileUploadFailed
- S3StorageError
- FileSizeExceeded
- Unauthorized
**Events**:
- EmployeeDocumentUploaded
---
### DeleteEmployeeDocumentCommand
**Goal**: Delete document from S3 and remove metadata
**Input**:
```yaml
document_id: UUID
deleted_by: UUID
```
**Output**:
```yaml
success: boolean
```
**Side Effects**:
- Delete file from S3
- Remove metadata from database
**Errors**:
- DocumentNotFound
- S3StorageError
- Unauthorized
**Events**:
- EmployeeDocumentDeleted
---
### SendPayslipEmailCommand
**Goal**: Send payroll email to employee
**Input**:
```yaml
payroll_id: UUID
employee_id: UUID
```
**Output**:
```yaml
payslip_id: UUID
email_status: EmailStatus
```
**Side Effects**:
- Generate payslip file
- Send email via SMTP/SES
- Update payslip status
**Errors**:
- PayrollNotFound
- EmployeeNotFound
- EmailDeliveryFailed
**Events**:
- PayslipSent
---
### CheckInCommand
**Goal**: Record employee check-in with weather info
**Input**:
```yaml
employee_id: UUID
check_in_time: timestamp
location: string (optional)
```
**Output**:
```yaml
attendance_id: UUID
weather_info: WeatherInfo
```
**Side Effects**:
- Create attendance record
- Fetch weather data from API
**Errors**:
- EmployeeNotFound
- Unauthorized
**Events**:
- EmployeeCheckedIn
---
## Queries (map to `app/queries.yaml`)
### GetEmployeeDocuments
**Goal**: Retrieve all documents for an employee
**Input**:
```yaml
employee_id: UUID
document_type: DocumentType (optional)
```
**Output**:
```yaml
documents:
- id: UUID
document_type: DocumentType
file_name: string
file_url: string
uploaded_at: timestamp
uploaded_by: UUID
```
**Entities Read**: HRDocument, Employee
---
### GetDocumentDownloadURL
**Goal**: Generate pre-signed S3 URL for secure download
**Input**:
```yaml
document_id: UUID
expiration: integer (seconds, default: 3600)
```
**Output**:
```yaml
download_url: string (pre-signed S3 URL)
expires_at: timestamp
```
**Entities Read**: HRDocument
**Errors**:
- DocumentNotFound
- S3StorageError
- Unauthorized
---
### GetEmployeePayslips
**Goal**: Retrieve payslips for an employee
**Input**:
```yaml
employee_id: UUID
period_start: date (optional)
period_end: date (optional)
```
**Output**:
```yaml
payslips:
- id: UUID
payroll_id: UUID
file_url: string
sent_at: timestamp
email_status: EmailStatus
```
**Entities Read**: Payslip, Payroll
---
# 5. Rules & Policy
---
## Business Rules
### Rule: Document Ownership
```
mỗi document phải gắn với một employee
```
---
### Rule: Secure File Access
```
download phải thông qua pre-signed S3 URL
```
---
### Rule: File Size Limit
```
max file size = 20MB
```
---
## RBAC (map to `policy/rbac.yaml`)
### Roles
```yaml
Employee:
description: "Regular employee"
HR:
description: "HR staff member"
Admin:
description: "System administrator"
```
### Permissions (map to `policy/permissions_map.yaml`)
```yaml
Employee:
- view_own_payroll
- view_own_attendance
- check_in
- view_own_documents
HR:
- upload_employee_documents
- delete_employee_documents
- view_all_documents
- send_payslip_email
- manage_payroll
- view_all_attendance
Admin:
- manage_employees
- manage_users
- view_system_logs
- all_hr_permissions
```
### Permission Mapping
```yaml
UploadEmployeeDocumentCommand:
- HR
- Admin
DeleteEmployeeDocumentCommand:
- HR
- Admin
GetEmployeeDocuments:
- HR
- Admin
- Employee (own documents only)
SendPayslipEmailCommand:
- HR
- Admin
CheckInCommand:
- Employee
- HR
- Admin
```
---
# 6. Workflow / State Machine
---
## State Machines (map to `workflows/*.yaml` if complex)
### Payroll States
```yaml
states:
- draft
- approved
- sent
- failed
transitions:
draft -> approved:
trigger: ApprovePayrollCommand
condition: payroll is complete
actor: HR, Admin
approved -> sent:
trigger: SendPayslipEmailCommand
condition: email delivery succeeds
actor: HR, Admin
event: PayslipSent
approved -> failed:
trigger: SendPayslipEmailCommand
condition: email delivery fails
event: PayslipFailed
```
### HRDocument States
```yaml
states:
- uploaded
- active
- deleted
transitions:
uploaded -> active:
trigger: automatic after validation
active -> deleted:
trigger: DeleteEmployeeDocumentCommand
actor: HR, Admin
event: EmployeeDocumentDeleted
```
---
## Domain Events (map to `domain/events.yaml`)
```yaml
EmployeeCheckedIn:
payload:
employee_id: UUID
attendance_id: UUID
check_in_time: timestamp
weather_info: WeatherInfo
PayrollGenerated:
payload:
payroll_id: UUID
employee_id: UUID
period_start: date
period_end: date
PayslipSent:
payload:
payslip_id: UUID
payroll_id: UUID
employee_id: UUID
sent_at: timestamp
EmployeeDocumentUploaded:
payload:
document_id: UUID
employee_id: UUID
document_type: DocumentType
file_url: string
uploaded_by: UUID
EmployeeDocumentDeleted:
payload:
document_id: UUID
employee_id: UUID
deleted_by: UUID
```
---
# 7. API
---
## API Routes (map to `api/http.yaml`)
### Upload Employee Document
```yaml
route: POST /api/v1/employees/{employee_id}/documents
command: UploadEmployeeDocumentCommand
auth: required (JWT)
roles: [HR, Admin]
request:
content_type: multipart/form-data
fields:
file: binary (required)
document_type: string (required)
response:
status: 201
body:
document_id: UUID
file_url: string
uploaded_at: timestamp
errors:
- 400: FileSizeExceeded
- 401: Unauthorized
- 404: EmployeeNotFound
- 500: S3StorageError
```
### List Employee Documents
```yaml
route: GET /api/v1/employees/{employee_id}/documents
query: GetEmployeeDocuments
auth: required (JWT)
roles: [HR, Admin, Employee (own only)]
query_params:
document_type: string (optional)
response:
status: 200
body:
documents: array
errors:
- 401: Unauthorized
- 404: EmployeeNotFound
```
### Download Document
```yaml
route: GET /api/v1/documents/{document_id}/download
query: GetDocumentDownloadURL
auth: required (JWT)
roles: [HR, Admin, Employee (own only)]
response:
status: 200
body:
download_url: string
expires_at: timestamp
errors:
- 401: Unauthorized
- 404: DocumentNotFound
- 500: S3StorageError
```
### Send Payroll Email
```yaml
route: POST /api/v1/payroll/{payroll_id}/send
command: SendPayslipEmailCommand
auth: required (JWT)
roles: [HR, Admin]
response:
status: 200
body:
payslip_id: UUID
email_status: string
errors:
- 401: Unauthorized
- 404: PayrollNotFound
- 500: EmailDeliveryFailed
```
### Check In
```yaml
route: POST /api/v1/attendance/check-in
command: CheckInCommand
auth: required (JWT)
roles: [Employee, HR, Admin]
request:
body:
location: string (optional)
response:
status: 201
body:
attendance_id: UUID
check_in_time: timestamp
weather_info: object
errors:
- 401: Unauthorized
- 404: EmployeeNotFound
```
### API Conventions
```yaml
versioning: URL path (/api/v1/)
auth: JWT Bearer token
error_response_format:
error:
code: string
message: string
details: object (optional)
```
---
# 8. Phi chức năng
Security
```
JWT authentication
RBAC authorization
S3 private bucket
pre-signed URL access
```
---
Performance
```
API latency < 200ms
file upload async
```
---
Observability
Metrics
```
document_upload_rate
email_delivery_rate
attendance_checkin_rate
```
---
Logging
```
log document uploads
log S3 errors
log payroll email delivery
```
---
# 9. Ràng buộc kỹ thuật
Stack
```
Backend: FastAPI
Database: PostgreSQL
Cache: Redis
Storage: Amazon S3
Email: SMTP / SES
```
---
S3 Storage Pattern
```
bucket: hr-documents
key: employee/{employee_id}/{document_id}/{filename}
```
---
Upload Flow
```
Client
│
│ upload
▼
Backend
│
├─ validate file
├─ upload to S3
└─ store metadata
```
---
Transaction
```
upload success → commit DB
upload fail → rollback
```
---
# 10. Phụ lục
Future features
```
document versioning
document approval workflow
HR self-service portal
mobile attendance
AI resume parser
```
If that brief is turned into contracts, the definition spreads across multiple files. Under domain/, there are entities such as Employee and HRDocument, enums such as DocumentType, errors such as DocumentNotFound, FileUploadFailed, and S3StorageError, and events such as EmployeeDocumentUploaded. Under app/, there are commands such as UploadEmployeeDocumentCommand and DeleteEmployeeDocumentCommand, and queries such as GetEmployeeDocuments and GetDocumentDownloadURL. Under rules/ or policy/, there are constraints such as file-size limits, pre-signed S3 URL access, and RBAC for HR and Admin. Under workflows/, there may be the lifecycle of HRDocument, and under api/ there are the upload, list, and download routes.
At the validation stage, Midi Coder checks whether those references line up correctly. Does the upload command use the right entities and defined errors. Does the emitted event exist. Does the HTTP route map to the correct command or query. Do the policy and permission definitions match the intended operations. If any part does not line up, the flow can stop at contract checking before code generation begins.
Once the contracts are valid, the pipeline builds an IR and then a code plan for the target stack. For this brief, the code plan will typically route changes into areas such as the upload and download endpoints, the application service for document handling, the S3 integration layer, metadata persistence, and access-control checks. From there, patches are generated and applied to the repository according to the plan.
The main reason to use this example is that it reflects a brief with multiple layers of information. That makes it easier for readers to understand why Section 9 should not show a single isolated contract file, but a multi-file contract set participating in one business flow.
A real sample contract set
Instead of showing a few isolated snippets, this section opens the full sample contract set so readers can see how domain, app, policy, workflow, and API layers sit together in one workspace. The goal here is to make review feel like opening a real contract set in an IDE, not to repeat the conceptual explanation.
routes:
- method: POST
path: /api/v1/employees/{employee_id}/documents
command: UploadEmployeeDocument
description: Upload HR document to S3 and store metadata
auth: required
request_schema:
- name: file
type: string
required: true
description: Binary file data
- name: document_type
type: string
required: true
description: Type of document (cv, contract, identity_card,
tax_document, other)
response_schema:
- name: document_id
type: uuid
required: true
- name: file_url
type: string
required: true
- name: uploaded_at
type: datetime
required: true
tags:
- documents
- method: GET
path: /api/v1/employees/{employee_id}/documents
query: GetEmployeeDocuments
description: Retrieve all documents for an employee
auth: required
request_schema:
- name: document_type
type: string
required: false
description: Filter by document type
response_schema:
- name: documents
type: list<string>
required: true
description: Array of document objects
tags:
- documents
- method: GET
path: /api/v1/documents/{document_id}/download
query: GetDocumentDownloadURL
description: Generate pre-signed S3 URL for secure download
auth: required
request_schema:
- name: expiration
type: int
required: false
description: URL expiration in seconds (default 3600)
response_schema:
- name: download_url
type: string
required: true
- name: expires_at
type: datetime
required: true
tags:
- documents
- method: DELETE
path: /api/v1/documents/{document_id}
command: DeleteEmployeeDocument
description: Delete document from S3 and remove metadata
auth: required
response_schema:
- name: success
type: bool
required: true
tags:
- documents
- method: POST
path: /api/v1/payroll/{payroll_id}/send
command: SendPayslipEmail
description: Send payroll email to employee
auth: required
response_schema:
- name: payslip_id
type: uuid
required: true
- name: email_status
type: string
required: true
tags:
- payroll
- method: GET
path: /api/v1/employees/{employee_id}/payslips
query: GetEmployeePayslips
description: Retrieve payslips for an employee
auth: required
request_schema:
- name: period_start
type: date
required: false
- name: period_end
type: date
required: false
response_schema:
- name: payslips
type: list<string>
required: true
description: Array of payslip objects
tags:
- payroll
- method: POST
path: /api/v1/attendance/check-in
command: CheckIn
description: Record employee check-in with weather info
auth: required
request_schema:
- name: location
type: string
required: false
response_schema:
- name: attendance_id
type: uuid
required: true
- name: check_in_time
type: datetime
required: true
- name: weather_info
type: json
required: true
tags:
- attendance
commands:
- id: UploadEmployeeDocument
description: Upload HR document to S3 and store metadata
input:
- name: employee_id
type: uuid
required: true
- name: document_type
type: string
required: true
- name: file
type: string
required: true
description: Binary file data
- name: uploaded_by
type: uuid
required: true
guards:
- id: auth.role
params:
roles:
- HR
- Admin
effects:
- id: db.insert
params:
table: hr_documents
entity: HRDocument
- id: call.integration
params:
target: aws_s3_hr_documents
operation_id: get_current_weather
payload:
employee_id: '{{employee_id}}'
document_type: '{{document_type}}'
file: '{{file}}'
- id: emit.event
params:
event: EmployeeDocumentUploaded
returns:
- name: document_id
type: uuid
required: true
- name: file_url
type: string
required: true
errors:
- EmployeeNotFound
- FileUploadFailed
- S3StorageError
- FileSizeExceeded
- Unauthorized
emits:
- EmployeeDocumentUploaded
category: crud.create
transaction: true
- id: DeleteEmployeeDocument
description: Delete document from S3 and remove metadata
input:
- name: document_id
type: uuid
required: true
- name: deleted_by
type: uuid
required: true
guards:
- id: auth.role
params:
roles:
- HR
- Admin
effects:
- id: call.integration
params:
target: aws_s3_hr_documents
operation_id: get_current_weather
payload:
document_id: '{{document_id}}'
- id: db.delete
params:
table: hr_documents
entity: HRDocument
- id: emit.event
params:
event: EmployeeDocumentDeleted
returns:
- name: success
type: bool
required: true
errors:
- DocumentNotFound
- S3StorageError
- Unauthorized
emits:
- EmployeeDocumentDeleted
category: crud.delete
transaction: true
- id: SendPayslipEmail
description: Send payroll email to employee
input:
- name: payroll_id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
guards:
- id: auth.role
params:
roles:
- HR
- Admin
effects:
- id: send.email
params:
template: payslip
- id: db.insert
params:
table: payslips
entity: Payslip
- id: db.update
params:
table: payslips
entity: Payslip
- id: emit.event
params:
event: PayslipSent
returns:
- name: payslip_id
type: uuid
required: true
- name: email_status
type: string
required: true
errors:
- PayrollNotFound
- EmployeeNotFound
- EmailDeliveryFailed
emits:
- PayslipSent
category: notification.send
transaction: true
- id: CheckIn
description: Record employee check-in with weather info
input:
- name: employee_id
type: uuid
required: true
- name: check_in_time
type: datetime
required: true
- name: location
type: string
required: false
guards:
- id: auth.role
params:
roles:
- Employee
- HR
- Admin
effects:
- id: call.integration
params:
service: weather_api
operation: get_weather
- id: db.insert
params:
table: attendance_records
entity: AttendanceRecord
- id: emit.event
params:
event: EmployeeCheckedIn
returns:
- name: attendance_id
type: uuid
required: true
- name: weather_info
type: json
required: true
errors:
- EmployeeNotFound
- Unauthorized
emits:
- EmployeeCheckedIn
category: crud.create
transaction: true
queries:
- id: GetEmployeeDocuments
description: Retrieve all documents for an employee
input:
- name: employee_id
type: uuid
required: true
- name: document_type
type: string
required: false
returns:
- name: documents
type: list<json>
required: true
reads_from:
- hr_documents
required_roles:
- HR
- Admin
- Employee
category: list
- id: GetDocumentDownloadURL
description: Generate pre-signed S3 URL for secure download
input:
- name: document_id
type: uuid
required: true
- name: expiration
type: int
required: false
default: 3600
returns:
- name: download_url
type: string
required: true
- name: expires_at
type: datetime
required: true
reads_from:
- hr_documents
required_roles:
- HR
- Admin
- Employee
category: detail
- id: GetEmployeePayslips
description: Retrieve payslips for an employee
input:
- name: employee_id
type: uuid
required: true
- name: period_start
type: date
required: false
- name: period_end
type: date
required: false
returns:
- name: payslips
type: list<json>
required: true
reads_from:
- payslips
- payrolls
required_roles:
- HR
- Admin
- Employee
category: list
entities:
- id: Employee
description: Employee entity for HR management
fields:
- name: id
type: uuid
required: true
- name: employee_code
type: string
required: true
- name: name
type: string
required: true
- name: email
type: string
required: true
- name: department
type: string
required: true
- name: position
type: string
required: true
- name: status
type: string
required: true
- name: created_at
type: datetime
required: true
primary_key: id
constraints:
- type: unique
fields:
- employee_code
- type: unique
fields:
- email
- id: AttendanceRecord
description: Employee attendance check-in record with weather information
fields:
- name: id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: date
type: date
required: true
- name: check_in_time
type: datetime
required: true
- name: check_out_time
type: datetime
required: false
- name: status
type: string
required: true
- name: total_work_hours
type: decimal
required: false
- name: weather_description
type: string
required: false
- name: temperature
type: decimal
required: false
primary_key: id
constraints:
- type: foreign_key
fields:
- employee_id
ref: Employee.id
- id: Payroll
description: Employee payroll information
fields:
- name: id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: period_start
type: date
required: true
- name: period_end
type: date
required: true
- name: net_salary_amount
type: decimal
required: true
- name: net_salary_currency
type: string
required: true
default: VND
- name: status
type: string
required: true
- name: created_at
type: datetime
required: true
primary_key: id
constraints:
- type: foreign_key
fields:
- employee_id
ref: Employee.id
- id: Payslip
description: Payroll email delivery record
fields:
- name: id
type: uuid
required: true
- name: payroll_id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: file_url
type: string
required: true
- name: sent_at
type: datetime
required: true
- name: email_status
type: string
required: true
primary_key: id
constraints:
- type: foreign_key
fields:
- payroll_id
ref: Payroll.id
- type: foreign_key
fields:
- employee_id
ref: Employee.id
- id: HRDocument
description: HR document stored on Amazon S3
fields:
- name: id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: document_type
type: string
required: true
- name: file_name
type: string
required: true
- name: file_url
type: string
required: true
- name: s3_bucket
type: string
required: true
- name: s3_key
type: string
required: true
- name: uploaded_by
type: uuid
required: true
- name: uploaded_at
type: datetime
required: true
primary_key: id
constraints:
- type: foreign_key
fields:
- employee_id
ref: Employee.id
errors:
- id: EmployeeNotFound
code: EMPLOYEE_NOT_FOUND
description: Employee not found
http_status: 404
category: business
- id: AttendanceNotFound
code: ATTENDANCE_NOT_FOUND
description: Attendance record not found
http_status: 404
category: business
- id: PayrollNotFound
code: PAYROLL_NOT_FOUND
description: Payroll not found
http_status: 404
category: business
- id: DocumentNotFound
code: DOCUMENT_NOT_FOUND
description: HR document not found
http_status: 404
category: business
- id: FileUploadFailed
code: FILE_UPLOAD_FAILED
description: Failed to upload file
http_status: 500
category: system
- id: S3StorageError
code: S3_STORAGE_ERROR
description: S3 storage operation failed
http_status: 500
category: integration
- id: EmailDeliveryFailed
code: EMAIL_DELIVERY_FAILED
description: Failed to send email
http_status: 500
category: integration
- id: Unauthorized
code: UNAUTHORIZED
description: Unauthorized access
http_status: 401
category: security
- id: FileSizeExceeded
code: FILE_SIZE_EXCEEDED
description: File size exceeds 20MB limit
http_status: 400
category: validation
events:
- id: EmployeeCheckedIn
description: Employee checked in with attendance record
kind: domain
payload:
- name: employee_id
type: uuid
required: true
- name: attendance_id
type: uuid
required: true
- name: check_in_time
type: datetime
required: true
- name: weather_condition
type: string
required: false
- name: weather_description
type: string
required: false
- name: temperature
type: decimal
required: false
- name: weather_retrieved_at
type: datetime
required: false
- id: PayrollGenerated
description: Payroll generated for employee
kind: domain
payload:
- name: payroll_id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: period_start
type: date
required: true
- name: period_end
type: date
required: true
- id: PayslipSent
description: Payslip email sent to employee
kind: domain
payload:
- name: payslip_id
type: uuid
required: true
- name: payroll_id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: sent_at
type: datetime
required: true
- id: EmployeeDocumentUploaded
description: HR document uploaded to S3
kind: domain
payload:
- name: document_id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: document_type
type: string
required: true
- name: file_url
type: string
required: true
- name: uploaded_by
type: uuid
required: true
- id: EmployeeDocumentDeleted
description: HR document deleted from S3
kind: domain
payload:
- name: document_id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: deleted_by
type: uuid
required: true
- id: PayslipFailed
description: Payslip email delivery failed
kind: domain
payload:
- name: payslip_id
type: uuid
required: true
- name: payroll_id
type: uuid
required: true
- name: employee_id
type: uuid
required: true
- name: error_message
type: string
required: false
value_objects:
- id: WeatherInfo
description: Weather information retrieved during check-in
fields:
- name: condition
type: string
required: true
description: Weather condition
- name: description
type: string
required: true
description: Weather description
- name: temperature
type: decimal
required: true
description: Temperature value
- name: retrieved_at
type: datetime
required: true
description: Timestamp when weather data was retrieved
category:
tags: []
source: master-brief
- id: Money
description: Monetary value with currency
fields:
- name: amount
type: decimal
required: true
description: Monetary amount
- name: currency
type: string
required: true
default: VND
description: Currency code
category: money
tags: []
source: master-brief
- id: DocumentMetadata
description: Metadata for uploaded documents
fields:
- name: file_size
type: int
required: true
description: File size in bytes
- name: mime_type
type: string
required: true
description: MIME type of the file
- name: upload_time
type: datetime
required: true
description: Timestamp of upload
category:
tags: []
source: master-brief
glossary:
terms:
- id: payroll
term: Payroll
definition: bảng lương
category: business
- id: payslip
term: Payslip
definition: file bảng lương
category: business
- id: hr_document
term: HR Document
definition: tài liệu nhân sự
category: business
- id: s3_object
term: S3 Object
definition: file lưu trên S3
category: technical
- id: employee
term: Employee
definition: nhân viên trong hệ thống
category: domain
- id: hr
term: HR
definition: nhân viên phòng nhân sự
category: domain
- id: admin
term: Admin
definition: quản trị viên hệ thống
category: domain
- id: attendance
term: Attendance
definition: chấm công nhân viên
category: business
- id: check_in
term: Check-in
definition: ghi nhận thời gian vào làm của nhân viên
category: process
integrations:
- id: weather_api
type: rest_api
base_url: https://api.weatherapi.com/v1
auth:
type: api_key
key_name: key
timeouts:
total_ms: 5000
tags:
- weather
- external
- id: aws_s3_hr_documents
type: aws_s3
provider: aws
service: s3
auth:
type: aws_sigv4
tags:
- storage
- hr
- id: email_service
type: smtp
tags:
- email
- payroll
operations:
- id: get_current_weather
integration_id: weather_api
method: GET
path: /current.json
request_schema:
- name: q
type: string
required: true
description: Location query
response_schema:
- name: condition
type: string
required: true
- name: temp_c
type: decimal
required: true
s3_resources:
- integration_id: aws_s3_hr_documents
bucket: hr-documents
region: ap-southeast-1
operations:
- get_current_weather
path_template: employee/{employee_id}/{document_id}/{filename}
encryption: AES256
email_providers:
- id: smtp_payroll
transport: smtp
host: smtp.company.com
port: 587
username_secret:
password_secret:
from_email: payroll@company.com
from_name: HR Payroll System
info:
name: Employee Attendance, Payroll & HR Document System
version: '1.2'
description: System for managing employee attendance, payroll delivery, and HR
document storage on Amazon S3
author: HR Tech Team
stack: fastapi
frameworks:
- fastapi
languages:
- python
keywords:
- attendance
- payroll
- hr-documents
- s3-storage
- weather-integration
tags:
- hr
- payroll
- document-management
- cloud-storage
datasources:
- id: main_db
engine: postgres
connector: asyncpg
database: hr_system
host: localhost
port: 5432
default: true
- id: s3_storage
engine: postgres
connector: asyncpg
database: hr_system
host: localhost
port: 5432
tables:
- id: employees
description: Employee master data
datasource: main_db
columns:
- name: id
type: UUID
required: true
constraints:
primary_key: true
- name: employee_code
type: VARCHAR
required: true
constraints:
unique: true
- name: name
type: VARCHAR
required: true
- name: email
type: VARCHAR
required: true
constraints:
unique: true
- name: department
type: VARCHAR
required: false
- name: position
type: VARCHAR
required: false
- name: status
type: VARCHAR
required: true
- name: created_at
type: TIMESTAMP
required: true
constraints:
default: CURRENT_TIMESTAMP
indexes:
- name: idx_employee_code
columns:
- employee_code
unique: true
- name: idx_email
columns:
- email
unique: true
- id: attendance_records
description: Employee attendance check-in records
datasource: main_db
columns:
- name: id
type: UUID
required: true
constraints:
primary_key: true
- name: employee_id
type: UUID
required: true
constraints:
foreign_key: employees.id
- name: date
type: DATE
required: true
- name: check_in_time
type: TIMESTAMP
required: true
- name: check_out_time
type: TIMESTAMP
required: false
- name: status
type: VARCHAR
required: true
- name: total_work_hours
type: DECIMAL
required: false
- name: weather_description
type: VARCHAR
required: false
- name: temperature
type: DECIMAL
required: false
indexes:
- name: idx_employee_date
columns:
- employee_id
- date
unique: true
- id: payrolls
description: Employee payroll records
datasource: main_db
columns:
- name: id
type: UUID
required: true
constraints:
primary_key: true
- name: employee_id
type: UUID
required: true
constraints:
foreign_key: employees.id
- name: period_start
type: DATE
required: true
- name: period_end
type: DATE
required: true
- name: net_salary_amount
type: DECIMAL
required: true
- name: net_salary_currency
type: VARCHAR
required: true
constraints:
default: VND
- name: status
type: VARCHAR
required: true
- name: created_at
type: TIMESTAMP
required: true
constraints:
default: CURRENT_TIMESTAMP
indexes:
- name: idx_employee_period
columns:
- employee_id
- period_start
- period_end
- id: payslips
description: Payslip email delivery records
datasource: main_db
columns:
- name: id
type: UUID
required: true
constraints:
primary_key: true
- name: payroll_id
type: UUID
required: true
constraints:
foreign_key: payrolls.id
- name: employee_id
type: UUID
required: true
constraints:
foreign_key: employees.id
- name: file_url
type: TEXT
required: true
- name: sent_at
type: TIMESTAMP
required: false
- name: email_status
type: VARCHAR
required: true
indexes:
- name: idx_payroll
columns:
- payroll_id
- id: hr_documents
description: HR document metadata stored in database with S3 references
datasource: main_db
columns:
- name: id
type: UUID
required: true
constraints:
primary_key: true
- name: employee_id
type: UUID
required: true
constraints:
foreign_key: employees.id
- name: document_type
type: VARCHAR
required: true
- name: file_name
type: VARCHAR
required: true
- name: file_url
type: TEXT
required: true
- name: s3_bucket
type: VARCHAR
required: true
- name: s3_key
type: VARCHAR
required: true
- name: uploaded_by
type: UUID
required: true
- name: uploaded_at
type: TIMESTAMP
required: true
constraints:
default: CURRENT_TIMESTAMP
indexes:
- name: idx_employee_documents
columns:
- employee_id
- name: idx_document_type
columns:
- document_type
policies:
- id: document_ownership_policy
description: Each document must be associated with an employee
scope: entity:HRDocument
conditions:
- field: employee_id
op: neq
value:
effects:
- type: deny
params:
message: Document must be associated with an employee
tags:
- document
- ownership
source: master-brief section 5 - Business Rules
- id: file_size_limit_policy
description: Maximum file size is 20MB
scope: entity:HRDocument
conditions:
- field: file_size
op: gt
value: 20971520
effects:
- type: deny
params:
message: File size exceeds 20MB limit
tags:
- document
- validation
source: master-brief section 5 - Business Rules
- id: own_documents_access_policy
description: Employees can only view their own documents
scope: entity:HRDocument
conditions:
- field: employee_id
op: eq
value: '{{actor.employee_id}}'
effects:
- type: allow
tags:
- document
- access
- ownership
source: master-brief section 5 - RBAC permissions
- id: own_payroll_access_policy
description: Employees can only view their own payroll
scope: entity:Payroll
conditions:
- field: employee_id
op: eq
value: '{{actor.employee_id}}'
effects:
- type: allow
tags:
- payroll
- access
- ownership
source: master-brief section 5 - RBAC permissions
- id: own_attendance_access_policy
description: Employees can only view their own attendance records
scope: entity:AttendanceRecord
conditions:
- field: employee_id
op: eq
value: '{{actor.employee_id}}'
effects:
- type: allow
tags:
- attendance
- access
- ownership
source: master-brief section 5 - RBAC permissions
- id: view_own_payroll_ownership_policy
description: Ownership policy for permission view_own_payroll
scope: entity:Payroll
conditions:
- field: actor.id
op: eq
value: actor.id
effects:
- type: allow
params: {}
tags:
- view_own_payroll
- ownership
source: auto-generated by contract repair safety fix
- id: view_own_attendance_ownership_policy
description: Ownership policy for permission view_own_attendance
scope: entity:AttendanceRecord
conditions:
- field: actor.id
op: eq
value: actor.id
effects:
- type: allow
params: {}
tags:
- view_own_attendance
- ownership
source: auto-generated by contract repair safety fix
- id: view_own_documents_ownership_policy
description: Ownership policy for permission view_own_documents
scope: query:GetEmployeeDocuments
conditions:
- field: actor.id
op: eq
value: actor.id
effects:
- type: allow
params: {}
tags:
- view_own_documents
- ownership
source: auto-generated by contract repair safety fix
access:
roles:
- id: Employee
description: Regular employee
- id: HR
description: HR staff member
- id: Admin
description: System administrator
permissions:
- id: view_own_payroll
description: View own payroll information
resource: entity:Payroll
action: read
- id: view_own_attendance
description: View own attendance records
resource: entity:AttendanceRecord
action: read
- id: check_in
description: Record attendance check-in
resource: command:CheckIn
action: write
- id: view_own_documents
description: View own HR documents
resource: query:GetEmployeeDocuments
action: read
- id: upload_employee_documents
description: Upload employee HR documents
resource: command:UploadEmployeeDocument
action: write
- id: delete_employee_documents
description: Delete employee HR documents
resource: command:DeleteEmployeeDocument
action: delete
- id: view_all_documents
description: View all employee documents
resource: query:GetEmployeeDocuments
action: read
- id: send_payslip_email
description: Send payslip email to employees
resource: command:SendPayslipEmail
action: write
- id: manage_payroll
description: Manage employee payroll
resource: entity:Payroll
action: write
- id: view_all_attendance
description: View all attendance records
resource: entity:AttendanceRecord
action: read
- id: manage_employees
description: Manage employee records
resource: entity:Employee
action: admin
- id: manage_users
description: Manage system users
resource: entity:Employee
action: admin
- id: view_system_logs
description: View system logs
resource: document:system_logs
action: read
bindings:
- role: Employee
permissions:
- view_own_payroll
- view_own_attendance
- check_in
- view_own_documents
- role: HR
permissions:
- upload_employee_documents
- delete_employee_documents
- view_all_documents
- send_payslip_email
- manage_payroll
- view_all_attendance
- role: Admin
permissions:
- upload_employee_documents
- delete_employee_documents
- view_all_documents
- send_payslip_email
- manage_payroll
- view_all_attendance
- manage_employees
- manage_users
- view_system_logs
rules:
- id: document_access_authorization
description: "Verify user has permission to access employee documents"
applies_to: "GetEmployeeDocuments"
severity: "error"
tags:
- authorization
- documents
inputs:
- user_role
- target_employee_id
- requesting_user_id
outputs:
- access_granted
rows:
- when:
user_role: "Admin"
then:
access_granted: true
- when:
user_role: "HR"
then:
access_granted: true
- when:
user_role: "Employee"
target_employee_id: "{{ requesting_user_id }}"
then:
access_granted: true
- when:
user_role: "Employee"
then:
access_granted: false
- id: document_deletion_authorization
description: "Verify user has permission to delete employee documents"
applies_to: "DeleteEmployeeDocument"
severity: "error"
tags:
- authorization
- documents
inputs:
- user_role
outputs:
- can_delete
rows:
- when:
user_role: "Admin"
then:
can_delete: true
- when:
user_role: "HR"
then:
can_delete: true
- when:
user_role: "Employee"
then:
can_delete: false
- id: document_upload_size_limit
description: "Enforce file size limits for document uploads"
applies_to: "UploadEmployeeDocument"
severity: "warning"
tags:
- validation
- documents
inputs:
- file_size_bytes
outputs:
- size_valid
- max_size_mb
rows:
- when:
file_size_bytes: "{{ <= 10485760 }}"
then:
size_valid: true
max_size_mb: 10
- when:
file_size_bytes: "{{ > 10485760 }}"
then:
size_valid: false
max_size_mb: 10
- id: payslip_email_authorization
description: "Verify user has permission to send payslip emails"
applies_to: "SendPayslipEmail"
severity: "error"
tags:
- authorization
- payroll
inputs:
- user_role
outputs:
- can_send_email
rows:
- when:
user_role: "Admin"
then:
can_send_email: true
- when:
user_role: "HR"
then:
can_send_email: true
- when:
user_role: "Employee"
then:
can_send_email: false
- id: attendance_check_in_validation
description: "Validate check-in requests for attendance tracking"
applies_to: "CheckIn"
severity: "warning"
tags:
- validation
- attendance
inputs:
- check_in_time
- employee_id
outputs:
- check_in_valid
rows:
- when:
check_in_time: "{{ not null }}"
employee_id: "{{ not null }}"
then:
check_in_valid: true
- when:
check_in_time: "{{ null }}"
then:
check_in_valid: false
- when:
employee_id: "{{ null }}"
then:
check_in_valid: false
scenarios:
- id: upload_employee_document_success
description: HR uploads employee document successfully
actors:
- HR
preconditions:
- HR is authenticated
- Employee exists in system
- File size is under 20MB
steps:
- type: command
ref: UploadEmployeeDocument
input:
employee_id: valid-employee-uuid
document_type: contract
file: binary-file-data
uploaded_by: hr-user-uuid
expect:
document_id: generated-uuid
file_url: s3-url
postconditions:
- File stored in S3
- Metadata stored in database
tags:
- hr_documents
- upload
source: Master Brief Section 3 - Luồng C
- id: upload_document_file_size_exceeded
description: HR uploads document exceeding size limit
actors:
- HR
preconditions:
- HR is authenticated
- File size exceeds 20MB
steps:
- type: command
ref: UploadEmployeeDocument
input:
employee_id: valid-employee-uuid
document_type: contract
file: large-file-data
uploaded_by: hr-user-uuid
expect:
error: FileSizeExceeded
tags:
- hr_documents
- validation
source: 'Master Brief Section 5 - Rule: File Size Limit'
- id: view_employee_documents
description: HR views all documents for an employee
actors:
- HR
preconditions:
- HR is authenticated
- Employee exists with documents
steps:
- type: query
ref: GetEmployeeDocuments
input:
employee_id: valid-employee-uuid
expect:
documents:
- id: document-uuid
document_type: contract
file_name: contract.pdf
file_url: s3-url
uploaded_at: timestamp
uploaded_by: hr-user-uuid
tags:
- hr_documents
- query
source: Master Brief Section 3 - Luồng D
- id: download_document_with_presigned_url
description: HR generates pre-signed URL for document download
actors:
- HR
preconditions:
- HR is authenticated
- Document exists
steps:
- type: query
ref: GetDocumentDownloadURL
input:
document_id: valid-document-uuid
expiration: 3600
expect:
download_url: presigned-s3-url
expires_at: timestamp
postconditions:
- Pre-signed URL generated
- URL expires after specified time
tags:
- hr_documents
- security
source: 'Master Brief Section 5 - Rule: Secure File Access'
- id: delete_employee_document
description: HR deletes employee document
actors:
- HR
preconditions:
- HR is authenticated
- Document exists
steps:
- type: command
ref: DeleteEmployeeDocument
input:
document_id: valid-document-uuid
deleted_by: hr-user-uuid
expect:
success: true
postconditions:
- File deleted from S3
- Metadata removed from database
tags:
- hr_documents
- delete
source: Master Brief Section 4 - DeleteEmployeeDocumentCommand
- id: send_payslip_email_success
description: HR sends payroll email to employee
actors:
- HR
preconditions:
- HR is authenticated
- Payroll is approved
- Employee email is valid
steps:
- type: command
ref: SendPayslipEmail
input:
payroll_id: valid-payroll-uuid
employee_id: valid-employee-uuid
expect:
payslip_id: generated-uuid
email_status: sent
postconditions:
- Payslip file generated
- Email sent to employee
- Payslip status updated
tags:
- payroll
- email
source: Master Brief Section 3 - Luồng B
- id: send_payslip_email_failed
description: Email delivery fails when sending payslip
actors:
- HR
preconditions:
- HR is authenticated
- Payroll is approved
- Email service unavailable
steps:
- type: command
ref: SendPayslipEmail
input:
payroll_id: valid-payroll-uuid
employee_id: valid-employee-uuid
expect:
error: EmailDeliveryFailed
tags:
- payroll
- email
- error
source: Master Brief Section 6 - Payroll State Machine
- id: employee_check_in_with_weather
description: Employee checks in and receives weather info
actors:
- Employee
preconditions:
- Employee is authenticated
- Weather API is available
steps:
- type: command
ref: CheckIn
input:
employee_id: valid-employee-uuid
check_in_time: timestamp
location: office-location
expect:
attendance_id: generated-uuid
weather_info:
condition: sunny
description: clear sky
temperature: 28.5
retrieved_at: timestamp
postconditions:
- Attendance record created
- Weather data fetched and stored
tags:
- attendance
- weather
source: Master Brief Section 3 - Luồng A
- id: employee_view_own_payslips
description: Employee retrieves their payslips
actors:
- Employee
preconditions:
- Employee is authenticated
- Employee has payslips
steps:
- type: query
ref: GetEmployeePayslips
input:
employee_id: valid-employee-uuid
expect:
payslips:
- id: payslip-uuid
payroll_id: payroll-uuid
file_url: s3-url
sent_at: timestamp
email_status: sent
tags:
- payroll
- employee
source: Master Brief Section 4 - GetEmployeePayslips
- id: employee_view_own_documents
description: Employee views their own HR documents
actors:
- Employee
preconditions:
- Employee is authenticated
- Employee has documents
steps:
- type: query
ref: GetEmployeeDocuments
input:
employee_id: own-employee-uuid
expect:
documents:
- id: document-uuid
document_type: contract
file_name: contract.pdf
file_url: s3-url
uploaded_at: timestamp
tags:
- hr_documents
- employee
source: Master Brief Section 5 - RBAC Permissions
- id: unauthorized_document_access
description: Unauthorized user attempts to access documents
actors:
- Anonymous
preconditions:
- User is not authenticated
steps:
- type: query
ref: GetEmployeeDocuments
input:
employee_id: any-employee-uuid
expect:
error: Unauthorized
tags:
- security
- authorization
source: Master Brief Section 2 - Errors
- id: document_not_found
description: User attempts to access non-existent document
actors:
- HR
preconditions:
- HR is authenticated
- Document does not exist
steps:
- type: query
ref: GetDocumentDownloadURL
input:
document_id: invalid-document-uuid
expect:
error: DocumentNotFound
tags:
- hr_documents
- error
source: Master Brief Section 2 - Errors
workflows:
- id: PayrollWorkflow
description: Payroll approval and email delivery workflow
entity: Payroll
initial_state: draft
states:
- id: draft
description: Payroll in draft state
kind: initial
- id: approved
description: Payroll approved by HR
kind: normal
- id: sent
description: Payslip sent to employee
kind: final
- id: failed
description: Email delivery failed
kind: final
transitions:
- from_state: draft
to_state: approved
on_command: SendPayslipEmail
guards:
- id: auth.role
params:
roles:
- HR
- Admin
- from_state: approved
to_state: sent
on_command: SendPayslipEmail
guards:
- id: auth.role
params:
roles:
- HR
- Admin
effects:
- id: emit.event
params:
event: PayslipSent
- from_state: approved
to_state: failed
on_command: SendPayslipEmail
effects:
- id: emit.event
params:
event: PayslipFailed
required_roles:
- HR
- Admin
- id: HRDocumentWorkflow
description: HR document upload and deletion workflow
entity: HRDocument
initial_state: uploaded
states:
- id: uploaded
description: Document uploaded to S3
kind: initial
- id: active
description: Document active and accessible
kind: normal
- id: deleted
description: Document deleted from S3
kind: final
transitions:
- from_state: uploaded
to_state: active
on_event: EmployeeDocumentUploaded
- from_state: active
to_state: deleted
on_command: DeleteEmployeeDocument
guards:
- id: auth.role
params:
roles:
- HR
- Admin
effects:
- id: emit.event
params:
event: EmployeeDocumentDeleted
required_roles:
- HR
- Admin
When this approach fits
Based on the model Midi Coder is implementing, contract coding fits best when the problem domain is clear enough to formalize. Typical signs are clear entities, clear workflows, clear rules or policy, and a real need for stronger reviewability, traceability, or auditability.
A stronger fit when
- the system has multi-tenancy, subscriptions, billing, auth, reporting, or integrations
- behavior repeats across many change cycles and consistency matters over time
- the team wants to review business intent before reviewing code patches
- auditability and traceability are operational requirements, not just nice-to-have ideas
A weaker fit when
- the problem is still highly exploratory and the logic changes constantly
- the team only needs a few local edits and has no reason to maintain a contract layer
- the cost of formalization is higher than the control benefits in the current context
What to read next
If you want to go deeper into the current implementation direction, the next useful step is not another marketing explanation, but pages that help you compare the model against real usage contexts, pilot it on a smaller scope, and connect the contract-first workflow to adjacent technical views.