--- 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/.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/.md` but the current branch is ``, ask the user to confirm the rename, then `git mv docs/api-changes/.md docs/api-changes/.md`. - After renaming, continue extending the renamed file. Do not create a new empty doc for `` 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 ## 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: ``` Rules: - The link in the PR description must point to the externally-shared location, not to `docs/api-changes/.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/.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).