---
name: document-node-be-changes-for-fe
description: Use when implementing or reviewing backend changes in the Humand Node/TypeScript backend (humand-main-api) that affect any FE-facing contract — request shape, response shape, validation, error codes, behavior, defaults, async effects, deprecations, new endpoints. Frontend developers consume the doc to update their typed clients.
disable-model-invocation: true
---

# Document Node Backend Changes for Frontend

Produce a markdown doc that gives FE developers everything they need to update their typed clients and behavior after a backend change in this repo. **One doc per branch.**

## When to use

Any time a BE change is being made that the FE needs to know about. Examples:

- New field on a request or response (added, renamed, removed, type narrowed/widened).
- New default value applied server-side when a field is omitted.
- New error code, or expanded conditions under which an existing error is returned.
- Authorization rule change that affects which users get 403 on a path.
- New side-effect triggered (background process, queue message) that the FE needs to know for polling/refresh.
- Endpoint added or deprecated.
- Validation rule changed (enum values, cross-field dependency, range constraint).
- New rate limit or change to an existing one.

**Do NOT use for:**

- Public API or gRPC endpoints — they are not FE-consumed.
- Purely internal refactors (DAOs, mappers, services, business models) that don't change anything observable at the boundary.

## File location — tied to the current branch

Resolve the branch before any write or edit:

```bash
git rev-parse --abbrev-ref HEAD
```

Path: `docs/api-changes/<branch>.md`, replacing `/` in the branch name with `-` (e.g., `feat/foo/bar` → `feat-foo-bar.md`). Other characters stay as-is.

**Rules:**

- If the file does not exist, create it from the template below.
- If the file exists, **extend it** — never overwrite. Add new entries to the Affected endpoints table, the Errors table, the FE checklist, etc.
- If the branch changes mid-session (user runs `git checkout`), re-resolve the branch and write to the new file. **Do not move content** between branch docs.
- The doc tracks the changes shipping in this branch's PR. Multiple commits in the same branch share one doc.

### Branch renames

If the branch is **renamed** (same work, new name — e.g., `git branch -m old new`), the doc file must be renamed in sync. Detect this by comparing `git rev-parse --abbrev-ref HEAD` against existing files in `docs/api-changes/`:

- If a doc exists at `docs/api-changes/<old-branch>.md` but the current branch is `<new-branch>`, ask the user to confirm the rename, then `git mv docs/api-changes/<old-branch>.md docs/api-changes/<new-branch>.md`.
- After renaming, continue extending the renamed file. Do not create a new empty doc for `<new-branch>` while orphaning the old one.

## Scope rules

- Document only FE-consumed scopes: **APP** and **BO**.
- Exclude **Public API** and **gRPC** unless the user explicitly confirms FE consumption in this specific case.
- Doc language is **English**.

## Authoring rules

### Endpoints

- One doc covers one PR/branch even when many endpoints are affected.
- List every touched endpoint in the **Affected endpoints** table at the top.
- Use `Endpoints affected: See "Affected endpoints" below` in the metadata table when more than one endpoint is touched.

### Grouping contracts by shape

When several endpoints are affected:

- If they share the **same** request or response shape, document it **once** under a single heading (e.g., `## GoalCycle resource — contract`) and list the endpoints that share it.
- If shapes **differ**, split with a heading per endpoint (e.g., `#### Response — GET /goal-cycles/{id}`).
- If shape is shared but **behavior** differs per endpoint within the same group (e.g., `Cache-Control` applies to GET but not PUT), qualify behavior bullets with the endpoint prefix (e.g., *"`GET` responses include `Cache-Control: private, max-age=30`. `PUT` responses are not cacheable."*). Do not split the shared shape into one section per endpoint just because behavior differs.

### Contract sections

For each shape group:

- `Previous contract` — include only when modifying an existing contract. Omit for brand-new endpoints.
- `New contract` — always present.
- `Changes` (Type changes + Behavior changes) — include only when modifying an existing contract.

Inside `Previous contract`, document only `Request` and `Response`. Do **not** put a `Behavior` sub-section under `Previous` — behavior deltas go in `Changes → Behavior changes`.

**Placement of `Changes` with multiple shape groups:**

- Single shape group → `## Changes` lives at the top level after `## New contract`.
- Multiple shape groups (e.g., shared response + endpoint-specific request) → nest `### Changes` inside each group's section, scoped to that group. Do not use a single global `## Changes` that mixes deltas from different shapes.

### Request sub-sections (use when relevant)

Inside any `Request` block, use these sub-sections only when they apply or changed:

- `Path params` — small table of `name / type / constraints`. Include only when path params changed or have non-obvious constraints.
- `Query params` — TS type or table. Include only when query params changed or are non-obvious to understanding the change.
- `Body` — TS type. Most common.

For a change that doesn't touch path/query, omit those sub-sections and just write the `Body` block directly.

### Behavior sub-sections (use only what applies)

Inside `New contract → Behavior` or `Changes → Behavior changes`, keep only the sub-sections that apply:

- `Defaults and derived fields`
- `Async effects / background processes`
- `Chaining with other endpoints`
- `Cache / consistency`
- `Rate limiting`
- `Backwards compatibility / deprecations`

`Rate limiting` is only needed when there's non-trivial behavior for the FE to handle: backoff strategy, `Retry-After` header, per-instance vs per-user scope, burst allowance. For a simple "N req/min returns 429", the Metadata `Rate limit` row + the 429 row in the Errors table are enough — omit the sub-section.

### Errors table

Always include a `Change` column with one of:

- `New` — new code introduced by this change.
- `Expanded conditions` — existing code, but more paths trigger it.
- `Message changed` — string changed (FE should not depend on it).
- `Unchanged` — listed for context only.

Always add a reminder below the table: *"FE should not depend on error message strings; only on status + code."*

**For brand-new endpoints**, the `Change` column tracks whether the **error code itself** is new in the system, not whether the endpoint is new:

- `New` — error code did not exist anywhere before this PR.
- `Unchanged` — error code already existed elsewhere; this endpoint now also returns it (FE likely has handling already).

Apply this convention regardless of whether the endpoint is new or existing.

### Error response shape

Every error in this repo returns the same body shape:

```ts
type ApiErrorResponse = {
    code: string;    // stable identifier — FE may match on this
    message: string; // human-readable — FE must not match on this
};
```

JSON examples for error responses must include both `code` and `message`, even though the FE should only match on `code`. The presence of `message` in examples reminds the FE of the full response type.

### Recommended FE gating (optional)

Include this section when the backend introduces a rule whose inputs are not exposed in any response the FE consumes (e.g., the rule depends on `bossId` and no response returns it). Describe:

- The decision matrix the FE should mirror, OR
- The fallback (try the call + handle the error response).

### Types and examples

- All TS types must be **copy-pasteable** (real types, no `// ...` placeholders for required fields).
- Inline simple constraints as TS comments (`// integer >= 0`). Put cross-field rules and constraints that don't fit TS in the `Validations and constraints` section.
- Examples use raw JSON (no JSON comments). Use a `Notes:` prose line after each example for caveats.
- Document **all relevant status codes** in examples (success + at least one error per new/changed condition).
- Prefix request examples with the HTTP method + path line (and `Content-Type` when applicable) **at least in the first example** when path params or query params are in play. This disambiguates how the params look in a real request.
- When response **headers** carry signal (`Cache-Control`, `Deprecation-Warning`, `Retry-After`, `Location`, `ETag`, custom headers), render them as a separate fenced code block immediately before the JSON body. Omit when no header is part of the contract change.

### TL;DR

1–3 bullets, plain language: what changed and what the FE has to do. Read this first.

### FE checklist

Concrete, verifiable items. Reference the exact type/field/endpoint. Avoid vague ones.

- Good: "Add `progressControlConfig?: GoalCycleProgressControlConfig` to `CreateGoalCycleRequest`."
- Bad: "Update types."

## Document template

Drop this into the file when it does not yet exist, then fill it in. Omit sections per the rules above.

````markdown
# [Resource or feature] — [One-line summary]

> **PR**: #... · **Module**: ... · **Date**: YYYY-MM-DD · **Author**: ...
> **Status**: Draft / Ready for FE / Implemented

## Metadata

| | |
|---|---|
| Endpoints affected | See "Affected endpoints" below |
| Scopes affected | APP / BO |
| Permissions required | ... |
| Breaking change | No / Yes — [short reason] |
| Deprecation window | N/A or [dates / versions] |
| Rate limit | N/A or `N requests / window` |
| Related endpoints | None or ... |

## TL;DR

- ...

## Affected endpoints

| Method | Path | Scope | Change |
|---|---|---|---|
| ... | ... | ... | ... |

## [Resource or endpoint group] — contract

### Previous contract

#### Request

```ts
type RequestBody = {
};
```

#### Response

```ts
type SuccessResponse = {
};
```

### New contract

#### Request

```ts
type RequestBody = {
};
```

#### Response

```ts
type SuccessResponse = {
};
```

#### Behavior

##### Defaults and derived fields
- ...

##### Async effects / background processes
- ...

##### Chaining with other endpoints
- ...

##### Cache / consistency
- ...

##### Rate limiting
- ...

##### Backwards compatibility / deprecations
- ...

## Changes

### Type changes

- `fieldA` — **added**. ...
- `fieldB` — **renamed** from `oldFieldB`. ...
- `fieldC` — **removed**. ...
- `fieldD` — **deprecated**. Stays in contract until [date]; FE should stop using it. Include the migration path (which field replaces it) when applicable.
- `fieldE` — **type narrowed** from `string` to `'X' | 'Y'`. ...

### Behavior changes

- ...

## Errors

| Status | Code | Change | When | Suggested FE action |
|---|---|---|---|---|
| 403 | `ACCESS_DENIED` | Expanded conditions | ... | ... |

> FE should not depend on error message strings; only on status + code.

## Validations and constraints

- `fieldA`: enum, optional. Valid values: ... Default: ...
- `fieldB`: integer, `>= 0`. **Required when** `fieldC === true`.

## Recommended FE gating

<!-- Include only when the backend rule depends on inputs not exposed in any response the FE consumes. -->

## FE checklist

- [ ] ...

## Examples

### [Scenario name]

Request:

```
POST /path/{id}?param=value
Content-Type: application/json
```

```json
{
}
```

Notes: ...

Response (201):

```json
{
}
```

Notes: ...

Error response (4xx):

```json
{
    "code": "...",
    "message": "..."
}
```

Notes: ...

## Links

- Backend PR: ...
- Design doc / spec: ...
- Ticket: ...
````

## Common mistakes

| Mistake | Fix |
|---|---|
| Documenting Public API or gRPC endpoints. | Remove them. Only APP and BO are FE-consumed in this repo. |
| One endpoint per doc when a single PR touches many. | One doc per branch. Use the "Affected endpoints" table and group contracts by shared shape. |
| Repeating the same response shape under each endpoint heading. | Document the shape once and list the endpoints that share it. |
| Including all 5 Behavior sub-sections even when most don't apply. | Omit sub-sections that don't apply. |
| Putting `Behavior` under `Previous contract`. | Behavior deltas live in `Changes → Behavior changes`. `Previous contract` only has Request and Response. |
| Errors table without `Change` column. | Always include `Change` (`New`, `Expanded conditions`, `Message changed`, `Unchanged`). |
| Documenting a rule whose inputs the FE can't access, with no guidance. | Add a `Recommended FE gating` section explaining how to mirror the rule or fall back to handle the error. |
| Filename using date prefix. | Use the branch name, replacing `/` with `-`. Date goes in the header line. |
| Switching branches and continuing to write in the original branch's doc. | Re-resolve branch on every authoring step. Each branch gets its own doc. |
| Spanish prose, mixed languages. | Doc language is **English**. |
| Vague FE checklist items ("Update types"). | Concrete, verifiable actions referencing the exact type, field, and endpoint. |
| Including path/query params sub-sections when nothing changed there. | Omit them. The doc is about what changed; static info belongs in the OpenAPI schema. |

## PR hand-off to FE

The doc lives only in the author's local checkout — `docs/api-changes/` is gitignored. To deliver it to the FE team, the author must share the file externally (Slack thread, Linear/Jira ticket, Notion page, Google Doc — whichever channel the team uses) and link to that shared location from the PR description.

Suggested line near the top of the PR description:

```
FE-facing changes: <shared external link>
```

Rules:

- The link in the PR description must point to the externally-shared location, not to `docs/api-changes/<branch>.md`. The repo path does not resolve for reviewers.
- If the PR description is being edited and the shared link is missing, ask the author for it and add it. Do not substitute the local repo path.

## Evolving this skill

The skill must stay in sync with how docs are actually written, but only **after explicit confirmation** that a change is definitive. Mid-iteration proposals do not auto-update the skill.

When the user requests a **structural change** to a doc:

1. Apply the change to the current doc only.
2. In your reply, flag that the change diverges from the current skill convention and ask the user one explicit question: *"Should this become the convention for future docs? If yes, I'll update the skill."*
3. **Only when the user explicitly confirms** — words like "yes, update the skill", "make it the convention", "definitivo", "aplicalo al skill" — edit this skill's `SKILL.md` (template + rules + `Common mistakes` table when relevant). The skill is distributed via the `humand-backend` plugin, so the source of truth lives in `hu-ai-agent-plugin/plugins/humand-backend/skills/document-node-be-changes-for-fe/SKILL.md` — open a PR there.
4. If the user does not confirm, or replies non-committally, leave the skill untouched. The current doc keeps the one-off divergence.

**Structural changes** (the kind that triggers this flow): changes to the template structure, required/optional sections, filename conventions, scope rules (which scopes are in/out), columns of any table the skill prescribes, grouping/splitting rules.

**Non-structural changes** (do NOT trigger this flow): filling in content for the current change — writing a specific Behavior bullet, listing a specific endpoint, adding a specific error row, choosing a specific TS type for a field.

**Why post-acceptance:** mid-iteration proposals are exploratory. Updating the skill on every proposal generates churn and a skill that contradicts itself across versions. Wait for the user to commit.

## Real-world example

The sibling file `example.md` (alongside this `SKILL.md`) — multi-endpoint resource change covering shape addition (`progressControlConfig` on the `GoalCycle` resource) plus a behavior change in a downstream endpoint (`POST /goals/{id}/progress`).

Use it as:

- **Anchor on first use** — if you have never authored a doc with this skill in your current context, read `example.md` once **before** writing to calibrate on tone, depth, and layout decisions the template leaves open. Skip on subsequent sessions or when extending an already-existing doc.
- **Fallback for ambiguity** — when a layout decision is not pinned down by the template or the authoring rules (e.g., how to phrase the `Recommended FE gating` matrix, how to organize multiple Behavior bullets that overlap, how to qualify shared-shape behavior per endpoint), consult the example for precedent rather than inventing a new shape.

Do NOT read the example for every doc — it is a calibration reference, not a step-by-step. The example is a tracked snapshot kept alongside the skill so new contributors can read a complete reference even though `docs/api-changes/` is gitignored. It may drift from the original branch's doc over time; treat it as illustrative, not canonical.

## Final checklist

- [ ] Resolved the current branch via `git rev-parse --abbrev-ref HEAD`.
- [ ] Wrote or extended the doc at `docs/api-changes/<branch>.md`.
- [ ] If the branch was renamed, the doc file was renamed in sync.
- [ ] Scope is APP and/or BO only.
- [ ] All affected endpoints listed in the Affected endpoints table.
- [ ] Contracts grouped by shared shape, separated when different.
- [ ] All TS types are copy-pasteable; no placeholders for required fields.
- [ ] Errors table includes the `Change` column and the message-strings reminder.
- [ ] `Recommended FE gating` included when the rule depends on FE-inaccessible inputs.
- [ ] FE checklist items are concrete and verifiable.
- [ ] Doc language is English.
- [ ] Links section filled (PR, spec, ticket — `TBD` if not known yet).
- [ ] PR description includes the link to this doc (or a reminder to add it on PR open).
