00-caso-de-uso.md,逐块说明
一份真实的分文件:bank-app 中的 UC-001-create-customer,为节选。把鼠标移到某一块上或点击它,可以看到 skill 在这里固定了什么。文件的各个章节也是标签:点击即可跳转。
UC-001 · Create customer
Parent spec. Fixes the boundary and the names; doesn't detail any layer. Per-layer detail lives in this folder's partials, each with its own owner.
| Field | Value |
|---|---|
| Identifier | UC-001-create-customer |
| Date | 2026-10-07 |
| Trigger | customer creation, over HTTP — inbound REST adapter. The exact path and verb belong to rest-api-architect, in 30-rest.md |
| Access | public — anyone may call it, no caller identity required (business fact, user's answer). Mechanism, the permitAll reason and status belong to security-architect, in 32-seguranca.md |
| Side effects | 1 — INSERT into customers |
| External calls | none — no side effect reaches a system this service does not own |
| Publication | none — no other system needs to learn that a customer was created; no domain event is published by this case |
| Transaction | opens at the use case CreateCustomerUseCase, closes before the response |
| Repetition | repeating the request with the same security number must not create a second customer (business fact): one customer per security number, the repeat is a conflict. The mechanism — Idempotency-Key or none — is delegated to rest-api-architect |
| Concurrency | the uniqueness of the security number is arbitrated by a unique constraint on the stored value; no application-level lock. Two concurrent requests with the same number: one is created, the other is a conflict |
| Personal data | securityNumber (national identification number, 11 digits) and birthDate are personal data. They never appear in clear in logs — @.claude/rules/personal-data.md, @.claude/rules/logging.md. The response carries only a reference, so neither leaves the service in a response body |
| Active blueprint | clean-architecture-single-module |
## Trigger, payload, and response
In
| Field | Type | Required | Rule |
|---|---|---|---|
name | string | ✅ | leading and trailing whitespace trimmed; after trimming, not blank and 2 to 120 characters |
securityNumber | string | ✅ | exactly 11 numeric digits (0–9); no check-digit validation; unique in the system |
birthDate | date | ✅ | the customer's 18th birthday is strictly before today (a customer whose 18th birthday is today is rejected); the customer is not over 130 years old today; a date in the future is rejected |
How "today" and the anniversaries are computed:
- "Today" is the current calendar date taken from the application's clock, never from the
- The N-th birthday is
birthDateplus N calendar years. For abirthDateof 29 February, - Accepted when
birthDate + 18 years < todayandbirthDate + 131 years > today—
Out
Situations, not statuses. The HTTP code for each is rest-api-architect's decision.
… 此处截断,其余见文件
## Flow
- The inbound adapter receives the request and validates the payload's shape.
- Translates it into the command
CreateCustomerCommand. - The use case
CreateCustomerUseCaseexecutes: checks through the outbound port - The outbound port
CustomerRepositorypersists it. A unique-constraint violation from a - The adapter translates the returned aggregate into the response — a reference only.
Nothing in this flow names annotations, columns, or framework types — that belongs to the partials.
## Components
State: NEW to be created · CHANGE already exists and changes · REUSE already exists and serves.
Paths relative to src/main/java/dev/nerviz/bankapp/ unless they start with src/.
… 此处截断,其余见文件
## Invariants
| Rule | Guaranteed by | Who violates it |
|---|---|---|
securityNumber is exactly 11 numeric digits | the security number's creation | caller with letters, punctuation, or a different length |
securityNumber is unique in the system | check at the outbound port + unique constraint | second registration, or a race between two requests |
name, trimmed, is 2 to 120 characters and not blank | Customer's creation | blank or overly long payload |
| 18th birthday strictly before today | Customer's creation, against the clock's date | a minor, or a customer whose 18th birthday is today |
| completed age at most 130 | Customer's creation, against the clock's date | a typo such as 1825 instead of 1985 |
birthDate is not in the future | Customer's creation, against the clock's date | a typo, or a wrong date format interpreted |
Invariants live in the aggregate, never in the caller — @.claude/rules/architecture-ddd.md.
## Errors
| Situation | Kind |
|---|---|
| security number already registered | conflict with existing state |
| customer not strictly over 18 | business rule |
| security number not exactly 11 digits | validation |
| name blank or outside 2 to 120 characters | validation |
| birth date in the future, or age over 130 | validation |
| required field missing, or a date that does not parse | shape — rejected in the adapter, never reaches the domain |
Situations and kinds, never exception names or statuses. The exception class and errorCode belong to 10-dominio.md (@.claude/rules/error-handling.md); the HTTP mapping belongs to 30-rest.md.
## Expected tests
| Level | Target | Detailed by |
|---|---|---|
| unit | Customer: name trim and length, 11-digit security number, age boundaries (18th birthday yesterday / today / tomorrow, 29 February, age 130 / 131, future date) with a fixed clock | test-architect |
| unit | use case: security number already registered is a conflict, nothing persisted | test-architect |
| slice | controller: created with reference only, malformed payload, each validation error, under-age, conflict | test-architect |
| integration | CustomerRepositoryJpaAdapter against a real database, including the unique constraint | test-architect |
## Out of scope for this use case
Written down so nobody merges it back in by accident:
- Reading, updating and deleting a customer → their own use cases, their own triggers; not
- Check-digit validation of the security number (Brazilian CPF algorithm) → decided against:
- Publishing a
CustomerCreatedevent → no consumer exists; a future case that needs it adds - Authentication of the caller → the endpoint is public by decision.
## Impact on approved use cases
none — UC-001 is the first case.
## Implementation order
Derived from the Components table, in compile order.
- [ ] 1. domain typed fields (
SecurityNumber, and name / birth date if typed) - [ ] 2.
domain/model/Customer.java - [ ] 3. domain exceptions — named in
10-dominio.md - [ ] 4.
application/usecase/customer/CreateCustomerCommand.java - [ ] 5.
application/port/CustomerRepository.java - [ ] 6.
application/usecase/customer/CreateCustomerUseCase.java - [ ] 7.
src/main/resources/db/migration/V1__create_customers.sql - [ ] 8.
infrastructure/persistence/customer/(entity, Spring Data, adapter) - [ ] 9.
infrastructure/rest/(DTOs, mapper, controller, exception handler) - [ ] 10. tests for the levels above
- [ ] 11.
./mvnw clean verifygreen
它读什么、写什么、拒绝什么
skill 自己的契约,取自 SKILL.md,保留原文。
Class
design — the territory is skill_classes.design in @.claude/schemas/extensions.json and ArchHook.java guard enforces it. Writes inside the use case folder and the backlog, nothing else; a write anywhere outside is refused with exit 2, not reported.
Reads
@.claude/rules/architecture-ddd.md (Application section — where the transaction opens, what doesn't go in the signatures), @.claude/rules/naming.md, @.claude/rules/error-handling.md (the four kinds only — names belong to domain-modeling), @.claude/rules/api-graphql.md (§ Choosing the inbound protocol only, for an HTTP trigger), @.claude/rules/spec-diagrams.md (the sequence diagram and the flowchart) with references/mermaid-use-case-diagrams.md, @.claude/rules/spec-external-facts.md (every fact about another system carries a source), the active blueprint's packages.map and naming convention, and this skill's references/scope-boundary.md before counting effects.
Writes
docs/use-cases/UC-NNN-<slug>/00-use-case.md and appends to docs/use-cases/BACKLOG.md. Only those. The 10- through 40- partials belong to the layer skills; the consolidated UC-NNN-spec.md belongs to the /new-feature orchestrator.
Owns
the use case number and slug. No other piece assigns them.
Shares one sequence, with one other named writer
BL-NN is assigned here when a split appends a backlog row, and by /new-feature's consolidation when a partial defers something to the backlog. Those two, never a third: a design skill that appended its own row would compute "highest plus one" against the same file in the same run and issue a duplicate.
Does not
edit an approved spec (status: approved, implemented or implemented-blocked) — reads it as a contract, and records the needed change in its own impact section.
Does not
write code, tests, migrations, or OpenAPI, and never writes under src/. Doesn't touch the inbound REST adapter — the package the blueprint's packages.map gives that role (rest-api-architect) —, the domain or application (gof-design-patterns, domain-modeling), nor .claude/rules/**. Doesn't weigh a storage technology: records the storage family and the search engine the request states or the user answers.
Does not
reproduce rules. Cites by path; what the rule already says isn't repeated in the spec.
Also carries
examples/ — twelve complete 00-use-case.md fixtures for testing /new-feature and java-spring-boot-developer, indexed in examples/README.md. Meta-repo documentation, not this skill's runtime output: the export manifest keeps only SKILL.md, templates/ and references/, so this directory does not travel.
来源:SKILL.md § Contract(nerviz e4cae27)。
guard 如何处理它
design 是这个 skill 的类。ArchHook 在 skill 被调用时开启一个阶段,并按该类的领地检查每次写入。右侧文字是 hook 自己的输出。
design 类的 write_allow
- ✓
docs/use-cases/UC-*/** - ✓
docs/use-cases/BACKLOG.md src/**:迁移和类归执行器docker-compose.yml:另一个类的文件已批准的用例:其 spec 已冻结
拒绝以退出码 2 结束,消息回到模型。
PreToolUse Skill(use-case-design) audit call exit 0 guard call exit 0 # a skill of another class replaces the phase # write_allow: docs/use-cases/UC-*/**, docs/use-cases/BACKLOG.md
PreToolUse Write(docs/use-cases/UC-005-record-kyc-verdict/00-caso-de-uso.md) guard write exit 0 PostToolUse audit file exit 0
PreToolUse Write(docker-compose.yml) guard write exit 2 ❌ `use-case-design` is class `design` — docker-compose.yml is outside its territory. write_allow: docs/use-cases/UC-*/**, docs/use-cases/BACKLOG.md Put the content in the spec as a code block, or finish the run and invoke the skill that owns this path. If the path is legitimately this skill's, widen skill_classes.design in .claude/schemas/extensions.json — retrying will not help.
# UC-005-record-kyc-verdict-spec.md: status: approved PreToolUse Edit(docs/use-cases/UC-005-record-kyc-verdict/00-caso-de-uso.md) guard write exit 2 ❌ UC-005-record-kyc-verdict is approved — its specs are immutable. Record the change in the new use case's "Impact on approved use cases" section, and the one-line entry in UC-005-record-kyc-verdict/CHANGELOG.md, which stays writable.
它在轨道上的位置
每张卡片是 /new-feature 的一步;箭头带着一步交给下一步的分文件。虚线的步骤仅在用例需要时运行。
/new-feature orchestrator · opus/new-feature-implement 之后谁读这份分文件批准之后,/new-feature-implement 让执行器构建代码。spec 按引用整合,与分文件不一致时以 spec 为准;分文件按章节读取,用于细节。