fastify 5.12.1 → 5.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/Reference/Validation-and-Serialization.md +11 -0
- package/docs/Reference/Warnings.md +11 -0
- package/fastify.js +1 -1
- package/lib/four-oh-four.js +10 -22
- package/lib/route.js +7 -4
- package/lib/schemas.js +5 -2
- package/lib/validation.js +196 -23
- package/lib/warnings.js +10 -1
- package/package.json +1 -1
- package/test/404s.test.js +105 -7
- package/test/router-options.test.js +24 -0
- package/test/schema-feature.test.js +158 -0
- package/test/schema-special-usage.test.js +81 -0
- package/test/schema-validation.test.js +378 -0
- package/.pi/self-learning-memory/README.md +0 -8
- package/.pi/self-learning-memory/core/CORE.md +0 -33
- package/.pi/self-learning-memory/core/index.json +0 -735
- package/.pi/self-learning-memory/daily/2026-07-06.md +0 -22
- package/.pi/self-learning-memory/daily/2026-07-29.md +0 -50
- package/.pi/self-learning-memory/daily/2026-08-04.md +0 -41
- package/.pi/self-learning-memory/daily/2026-08-18.md +0 -40
- package/.pi/self-learning-memory/long-term-memory.md +0 -89
- package/AGENTS.md +0 -290
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
## 15:46 UTC — Task
|
|
2
|
-
|
|
3
|
-
### What went wrong
|
|
4
|
-
- Interpolated `${{ inputs.package }}` directly into `actions/github-script` JavaScript, allowing malformed input to break or inject code.
|
|
5
|
-
- Fetched npm metadata with the raw package name instead of URL-encoding it.
|
|
6
|
-
- Assumed `data.repository.url` always existed and was a GitHub `.git` URL.
|
|
7
|
-
- Used a brittle repository URL regex that missed scoped/modern GitHub URL formats and failed without a clear error.
|
|
8
|
-
|
|
9
|
-
### How it was fixed
|
|
10
|
-
- Pass workflow input through `env.NPM_PACKAGE` and read it from `process.env` inside the script.
|
|
11
|
-
- Validate the package name with an npm package-name regex before using it.
|
|
12
|
-
- Use `encodeURIComponent(packageName)` in the npm registry URL.
|
|
13
|
-
- Check `response.ok` and throw explicit errors for failed registry fetches or unsupported repository URLs.
|
|
14
|
-
|
|
15
|
-
## 16:04 UTC — Task
|
|
16
|
-
|
|
17
|
-
### What went wrong
|
|
18
|
-
- PR title did not satisfy the repository's conventional title check before opening/updating the PR.
|
|
19
|
-
|
|
20
|
-
### How it was fixed
|
|
21
|
-
- Renamed PR #6833 to `ci: harden CITGM package workflow input handling` using `gh pr edit`, then watched checks until `pull-request-title-check` passed.
|
|
22
|
-
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
## 19:37 UTC — Task
|
|
2
|
-
|
|
3
|
-
### What went wrong
|
|
4
|
-
- Continued initiating tool work after the tool-budget warning instead of stopping to assess the existing evidence.
|
|
5
|
-
- Started a test command that was aborted, leaving the primitive-coercion fix unverified.
|
|
6
|
-
- Investigated Ajv internals and custom compiler compatibility without first isolating the exact failing repository behavior.
|
|
7
|
-
- Did not establish regression coverage for missing schemaEnv handling and root primitive coercion before changing direction.
|
|
8
|
-
|
|
9
|
-
### How it was fixed
|
|
10
|
-
- Honor soft tool-budget and interruption signals immediately; stop browsing and provide a bounded reflection.
|
|
11
|
-
- Run only the single highest-value targeted test before the budget limit, then report if execution is blocked.
|
|
12
|
-
- Reproduce root primitive coercion with the repository’s actual validatorCompiler path rather than relying on Ajv internals alone.
|
|
13
|
-
- Add focused tests covering custom validator compilation, schemaEnv availability, and root primitive coercion.
|
|
14
|
-
|
|
15
|
-
## 20:03 UTC — Task
|
|
16
|
-
|
|
17
|
-
### What went wrong
|
|
18
|
-
- Root primitive request values were validated without a parent reference, so Ajv coercion changed only its local value and left request.body as a string.
|
|
19
|
-
- Test command output was misread: Borp ran the broader suite despite a specific file argument, making targeted coverage unclear.
|
|
20
|
-
|
|
21
|
-
### How it was fixed
|
|
22
|
-
- Pass request and parameter metadata as Ajv parentData/parentDataProperty so root coercions update the original request value.
|
|
23
|
-
- Add a regression test asserting quoted numeric JSON becomes a number in the handler while out-of-range values remain rejected.
|
|
24
|
-
- Verify targeted test execution separately from the full suite to avoid mistaking aggregate counts for focused coverage.
|
|
25
|
-
|
|
26
|
-
## 20:06 UTC — Task
|
|
27
|
-
|
|
28
|
-
### What went wrong
|
|
29
|
-
- Ajv was called with a primitive root value without parentData context, so coerced values were not written back to request.body.
|
|
30
|
-
- The regression scenario was initially vulnerable because the handler received string "10" after validation accepted it.
|
|
31
|
-
- The CVSS rating assumed PR:L without repository evidence that authentication is required; many affected routes may be unauthenticated.
|
|
32
|
-
- The impact rating was stated as application-dependent without defining the affected endpoint’s actual confidentiality and integrity consequences.
|
|
33
|
-
|
|
34
|
-
### How it was fixed
|
|
35
|
-
- Pass parentData and parentDataProperty to Ajv validators so root primitive coercions update the request object.
|
|
36
|
-
- Retain the direct-call path for validators without schemaEnv to avoid changing non-Ajv validator behavior.
|
|
37
|
-
- Add a regression test asserting quoted numeric JSON reaches the handler as number 10.
|
|
38
|
-
- Determine PR from the deployed route’s authentication requirements; use PR:N for unauthenticated endpoints.
|
|
39
|
-
- Base C/I impact on the specific handler and data affected rather than assigning a universal Fastify score.
|
|
40
|
-
|
|
41
|
-
## 20:09 UTC — Task
|
|
42
|
-
|
|
43
|
-
### What went wrong
|
|
44
|
-
- Validation coerced a root primitive but failed to preserve the coerced value for the caller.
|
|
45
|
-
- The regression scenario was not covered by existing tests.
|
|
46
|
-
|
|
47
|
-
### How it was fixed
|
|
48
|
-
- Updated `lib/validation.js` to retain and return coerced root values.
|
|
49
|
-
- Added `test/fix-root-primitive-coercion.test.js` to prevent recurrence.
|
|
50
|
-
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
## 10:59 UTC — Task
|
|
2
|
-
|
|
3
|
-
### What went wrong
|
|
4
|
-
- Assumed /static/..%2f… 404 meant getPathnameForSend/route miss instead of later send pipeline behavior
|
|
5
|
-
- Did not check that encodeURI() re-encodes residual % as %25 before blaming path guards
|
|
6
|
-
- Conflated reply.callNotFound() JSON ("Route GET:… not found") with an actual find-my-way miss
|
|
7
|
-
- Debugged isolated getPathnameForSend reimplementation before tracing pumpSendToReply → encodeURI(pathnameForSend) → @fastify/send
|
|
8
|
-
- Compared send() on decoded ../ paths (403) to static outcomes without using the exact post-encodeURI string static passes
|
|
9
|
-
|
|
10
|
-
### How it was fixed
|
|
11
|
-
- Always log/compare the exact pathname string passed into send(), including after encodeURI
|
|
12
|
-
- When statuses differ for "same" path, diff charCodes for % vs %25 double-encoding first
|
|
13
|
-
- Instrument static handler vs router to separate callNotFound from unmatched routes
|
|
14
|
-
- Trace full pipeline: raw.url → getPathnameForSend → dotDot guards → encodeURI → @fastify/send
|
|
15
|
-
- Reproduce with send(root, p) using both raw and encodeURI(p) before changing triage conclusions
|
|
16
|
-
|
|
17
|
-
## 11:12 UTC — Task
|
|
18
|
-
|
|
19
|
-
### What went wrong
|
|
20
|
-
- Assumed encodeURI leaves '%' intact on paths like '/..%2ftop-secret.txt', so static 404 vs raw '..' 403 looked inconsistent.
|
|
21
|
-
- Treated encoded traversal and decoded param sinks as the same layer before separating find-my-way dual-decode from @fastify/send root checks.
|
|
22
|
-
- Relied on log/message shape alone (callNotFound 'Route ... not found') to infer static failure mode without probing @fastify/send inputs.
|
|
23
|
-
|
|
24
|
-
### How it was fixed
|
|
25
|
-
- Empirically print encodeURI output/charCodes: '%' → '%25', so static sees '/..%252ftop-secret.txt' (safe 404) not a '..' segment.
|
|
26
|
-
- Reproduce with @fastify/send directly for raw percent, encodeURI(percent), and decoded '../' to map 403 vs 404 to normalize/root logic.
|
|
27
|
-
- Keep reporter response framed as app-level path.join(param) misuse; cite static/sendFile containment and Express parity, not a core CVE.
|
|
28
|
-
|
|
29
|
-
## 12:31 UTC — Task
|
|
30
|
-
|
|
31
|
-
### What went wrong
|
|
32
|
-
- Markdown lint invoked in a way that flooded output with unrelated files (AGENTS.md, .pi memory, response.md) instead of only the two edited docs.
|
|
33
|
-
- Untracked response.md sat in the working tree and could have been staged if git add was too broad.
|
|
34
|
-
- Relied on noisy repo-wide lint signal before confirming MD013 on the actual changed regions.
|
|
35
|
-
|
|
36
|
-
### How it was fixed
|
|
37
|
-
- Re-run markdownlint scoped strictly to docs/Reference/Request.md and docs/Reference/Routes.md.
|
|
38
|
-
- Stage only those two paths (git add docs/Reference/Request.md docs/Reference/Routes.md); never git add .
|
|
39
|
-
- Manually awk length>80 on changed files to confirm new lines stay ≤80 before commit.
|
|
40
|
-
- Leave response.md untracked and verify git status/diff --stat before commit and PR.
|
|
41
|
-
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
## 19:37 UTC — Task
|
|
2
|
-
|
|
3
|
-
### What went wrong
|
|
4
|
-
- Assumed the draft advisory meant `origin/main` and `origin/5.x` must remain untouched without first confirming whether the user expected public pushes.
|
|
5
|
-
- Reported that the private branches were complete without clearly distinguishing advisory-fork refs from public `origin` refs, prompting the user to stop and verify deployment status.
|
|
6
|
-
- Combined PR closing with an unsupported workspace-repository comment under `set -e`, causing the entire command to fail before the close could occur.
|
|
7
|
-
- Called the PR “now-empty” even though GitHub still reported it as mergeable with different head and base OIDs.
|
|
8
|
-
- Deleted local security branches before resolving whether the user wanted the commits pushed to public branches, reducing convenient recovery points.
|
|
9
|
-
|
|
10
|
-
### How it was fixed
|
|
11
|
-
- Before any security-fix push, explicitly ask whether targets are the private advisory fork, public `origin`, or both; treat a draft advisory as a warning, not implicit authorization policy.
|
|
12
|
-
- Always state push destinations and exact resulting refs, e.g. `advisory-ghsa-3m5p/main` changed while `origin/main` remained at `6e95cb9f`.
|
|
13
|
-
- Run workspace-sensitive PR operations separately: attempt the comment, record an expected permission denial, then independently close only if authorized.
|
|
14
|
-
- Describe PR state from verified fields (`CLOSED`, `mergedAt: null`, head/base OIDs) rather than inferring that it is empty.
|
|
15
|
-
- Keep local security branches until the user confirms the intended public/private publication state; delete them only after final authorization and ref verification.
|
|
16
|
-
|
|
17
|
-
## 19:38 UTC — Task
|
|
18
|
-
|
|
19
|
-
### What went wrong
|
|
20
|
-
- Initially pushed the security fix only to the private advisory fork, leaving `origin/main` and `origin/5.x` unchanged without first confirming the intended publication target.
|
|
21
|
-
- After pushing remote refs, local `main` remained one commit behind, creating temporary local/remote inconsistency.
|
|
22
|
-
- A GraphQL `addComment` action was attempted despite workspace-repository restrictions; the denial indicates an intentional permission boundary that should not be bypassed.
|
|
23
|
-
|
|
24
|
-
### How it was fixed
|
|
25
|
-
- Obtained explicit approval before public disclosure, then atomically fast-forwarded `origin/main` to `af079bd4` and `origin/5.x` to `8acfea7e`, verifying both refs with `git ls-remote`.
|
|
26
|
-
- Fast-forwarded local `main` to `origin/main` and confirmed a clean synchronized status.
|
|
27
|
-
- Do not retry forbidden workspace GraphQL actions; use permitted repository operations or ask the user for an authorized alternative before attempting comments or metadata changes.
|
|
28
|
-
|
|
29
|
-
## 19:46 UTC — Task
|
|
30
|
-
|
|
31
|
-
### What went wrong
|
|
32
|
-
- Private PR #1 remained open after its head commit had already been placed on private `main`; its mergeability was `UNKNOWN` and it was no longer the correct landing path.
|
|
33
|
-
- Local `main` and temporary security branches were left out of sync after updating the remote branches.
|
|
34
|
-
- Direct public branch updates bypassed the repository’s pull-request-only rules, so ancestry and target refs required explicit validation to avoid unsafe rewrites.
|
|
35
|
-
|
|
36
|
-
### How it was fixed
|
|
37
|
-
- Closed PR #1 without merging after confirming its head SHA was already the intended private `main` commit.
|
|
38
|
-
- Fetched current `origin/main` and `origin/5.x`, verified each security commit’s parent exactly matched the corresponding remote tip, then used an atomic push.
|
|
39
|
-
- Verified public and private `main`/`5.x` refs matched, fast-forwarded local `main`, deleted temporary security branches, and confirmed a clean synchronized checkout.
|
|
40
|
-
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# Long-term Memory
|
|
2
|
-
|
|
3
|
-
Complete history of durable learnings and recurring mistakes.
|
|
4
|
-
Last updated: 2026-08-18T19:46:43.093Z
|
|
5
|
-
|
|
6
|
-
## All learnings
|
|
7
|
-
- Closed PR #1 without merging after confirming its head SHA was already the intended private `main` commit.
|
|
8
|
-
- Fetched current `origin/main` and `origin/5.x`, verified each security commit’s parent exactly matched the corresponding remote tip, then used an atomic push.
|
|
9
|
-
- Verified public and private `main`/`5.x` refs matched, fast-forwarded local `main`, deleted temporary security branches, and confirmed a clean synchronized checkout.
|
|
10
|
-
- Obtained explicit approval before public disclosure, then atomically fast-forwarded `origin/main` to `af079bd4` and `origin/5.x` to `8acfea7e`, verifying both refs with `git ls-remote`.
|
|
11
|
-
- Fast-forwarded local `main` to `origin/main` and confirmed a clean synchronized status.
|
|
12
|
-
- Do not retry forbidden workspace GraphQL actions; use permitted repository operations or ask the user for an authorized alternative before attempting comments or metadata changes.
|
|
13
|
-
- Before any security-fix push, explicitly ask whether targets are the private advisory fork, public `origin`, or both; treat a draft advisory as a warning, not implicit authorization policy.
|
|
14
|
-
- Always state push destinations and exact resulting refs, e.g. `advisory-ghsa-3m5p/main` changed while `origin/main` remained at `6e95cb9f`.
|
|
15
|
-
- Run workspace-sensitive PR operations separately: attempt the comment, record an expected permission denial, then independently close only if authorized.
|
|
16
|
-
- Describe PR state from verified fields (`CLOSED`, `mergedAt: null`, head/base OIDs) rather than inferring that it is empty.
|
|
17
|
-
- Keep local security branches until the user confirms the intended public/private publication state; delete them only after final authorization and ref verification.
|
|
18
|
-
- Re-run markdownlint scoped strictly to docs/Reference/Request.md and docs/Reference/Routes.md.
|
|
19
|
-
- Stage only those two paths (git add docs/Reference/Request.md docs/Reference/Routes.md); never git add .
|
|
20
|
-
- Manually awk length>80 on changed files to confirm new lines stay ≤80 before commit.
|
|
21
|
-
- Leave response.md untracked and verify git status/diff --stat before commit and PR.
|
|
22
|
-
- Empirically print encodeURI output/charCodes: '%' → '%25', so static sees '/..%252ftop-secret.txt' (safe 404) not a '..' segment.
|
|
23
|
-
- Reproduce with @fastify/send directly for raw percent, encodeURI(percent), and decoded '../' to map 403 vs 404 to normalize/root logic.
|
|
24
|
-
- Keep reporter response framed as app-level path.join(param) misuse; cite static/sendFile containment and Express parity, not a core CVE.
|
|
25
|
-
- Always log/compare the exact pathname string passed into send(), including after encodeURI
|
|
26
|
-
- When statuses differ for "same" path, diff charCodes for % vs %25 double-encoding first
|
|
27
|
-
- Instrument static handler vs router to separate callNotFound from unmatched routes
|
|
28
|
-
- Trace full pipeline: raw.url → getPathnameForSend → dotDot guards → encodeURI → @fastify/send
|
|
29
|
-
- Reproduce with send(root, p) using both raw and encodeURI(p) before changing triage conclusions
|
|
30
|
-
- Updated `lib/validation.js` to retain and return coerced root values.
|
|
31
|
-
- Added `test/fix-root-primitive-coercion.test.js` to prevent recurrence.
|
|
32
|
-
- Pass parentData and parentDataProperty to Ajv validators so root primitive coercions update the request object.
|
|
33
|
-
- Retain the direct-call path for validators without schemaEnv to avoid changing non-Ajv validator behavior.
|
|
34
|
-
- Add a regression test asserting quoted numeric JSON reaches the handler as number 10.
|
|
35
|
-
- Determine PR from the deployed route’s authentication requirements; use PR:N for unauthenticated endpoints.
|
|
36
|
-
- Base C/I impact on the specific handler and data affected rather than assigning a universal Fastify score.
|
|
37
|
-
- Pass request and parameter metadata as Ajv parentData/parentDataProperty so root coercions update the original request value.
|
|
38
|
-
- Add a regression test asserting quoted numeric JSON becomes a number in the handler while out-of-range values remain rejected.
|
|
39
|
-
- Verify targeted test execution separately from the full suite to avoid mistaking aggregate counts for focused coverage.
|
|
40
|
-
- Honor soft tool-budget and interruption signals immediately; stop browsing and provide a bounded reflection.
|
|
41
|
-
- Run only the single highest-value targeted test before the budget limit, then report if execution is blocked.
|
|
42
|
-
- Reproduce root primitive coercion with the repository’s actual validatorCompiler path rather than relying on Ajv internals alone.
|
|
43
|
-
- Add focused tests covering custom validator compilation, schemaEnv availability, and root primitive coercion.
|
|
44
|
-
- Renamed PR #6833 to `ci: harden CITGM package workflow input handling` using `gh pr edit`, then watched checks until `pull-request-title-check` passed.
|
|
45
|
-
- Pass workflow input through `env.NPM_PACKAGE` and read it from `process.env` inside the script.
|
|
46
|
-
- Validate the package name with an npm package-name regex before using it.
|
|
47
|
-
- Use `encodeURIComponent(packageName)` in the npm registry URL.
|
|
48
|
-
- Check `response.ok` and throw explicit errors for failed registry fetches or unsupported repository URLs.
|
|
49
|
-
|
|
50
|
-
## All watch-outs
|
|
51
|
-
- Private PR #1 remained open after its head commit had already been placed on private `main`; its mergeability was `UNKNOWN` and it was no longer the correct landing path.
|
|
52
|
-
- Local `main` and temporary security branches were left out of sync after updating the remote branches.
|
|
53
|
-
- Direct public branch updates bypassed the repository’s pull-request-only rules, so ancestry and target refs required explicit validation to avoid unsafe rewrites.
|
|
54
|
-
- Initially pushed the security fix only to the private advisory fork, leaving `origin/main` and `origin/5.x` unchanged without first confirming the intended publication target.
|
|
55
|
-
- After pushing remote refs, local `main` remained one commit behind, creating temporary local/remote inconsistency.
|
|
56
|
-
- A GraphQL `addComment` action was attempted despite workspace-repository restrictions; the denial indicates an intentional permission boundary that should not be bypassed.
|
|
57
|
-
- Assumed the draft advisory meant `origin/main` and `origin/5.x` must remain untouched without first confirming whether the user expected public pushes.
|
|
58
|
-
- Reported that the private branches were complete without clearly distinguishing advisory-fork refs from public `origin` refs, prompting the user to stop and verify deployment status.
|
|
59
|
-
- Combined PR closing with an unsupported workspace-repository comment under `set -e`, causing the entire command to fail before the close could occur.
|
|
60
|
-
- Called the PR “now-empty” even though GitHub still reported it as mergeable with different head and base OIDs.
|
|
61
|
-
- Deleted local security branches before resolving whether the user wanted the commits pushed to public branches, reducing convenient recovery points.
|
|
62
|
-
- Markdown lint invoked in a way that flooded output with unrelated files (AGENTS.md, .pi memory, response.md) instead of only the two edited docs.
|
|
63
|
-
- Untracked response.md sat in the working tree and could have been staged if git add was too broad.
|
|
64
|
-
- Relied on noisy repo-wide lint signal before confirming MD013 on the actual changed regions.
|
|
65
|
-
- Assumed encodeURI leaves '%' intact on paths like '/..%2ftop-secret.txt', so static 404 vs raw '..' 403 looked inconsistent.
|
|
66
|
-
- Treated encoded traversal and decoded param sinks as the same layer before separating find-my-way dual-decode from @fastify/send root checks.
|
|
67
|
-
- Relied on log/message shape alone (callNotFound 'Route ... not found') to infer static failure mode without probing @fastify/send inputs.
|
|
68
|
-
- Assumed /static/..%2f… 404 meant getPathnameForSend/route miss instead of later send pipeline behavior
|
|
69
|
-
- Did not check that encodeURI() re-encodes residual % as %25 before blaming path guards
|
|
70
|
-
- Conflated reply.callNotFound() JSON ("Route GET:… not found") with an actual find-my-way miss
|
|
71
|
-
- Debugged isolated getPathnameForSend reimplementation before tracing pumpSendToReply → encodeURI(pathnameForSend) → @fastify/send
|
|
72
|
-
- Compared send() on decoded ../ paths (403) to static outcomes without using the exact post-encodeURI string static passes
|
|
73
|
-
- Validation coerced a root primitive but failed to preserve the coerced value for the caller.
|
|
74
|
-
- The regression scenario was not covered by existing tests.
|
|
75
|
-
- Ajv was called with a primitive root value without parentData context, so coerced values were not written back to request.body.
|
|
76
|
-
- The regression scenario was initially vulnerable because the handler received string "10" after validation accepted it.
|
|
77
|
-
- The CVSS rating assumed PR:L without repository evidence that authentication is required; many affected routes may be unauthenticated.
|
|
78
|
-
- The impact rating was stated as application-dependent without defining the affected endpoint’s actual confidentiality and integrity consequences.
|
|
79
|
-
- Root primitive request values were validated without a parent reference, so Ajv coercion changed only its local value and left request.body as a string.
|
|
80
|
-
- Test command output was misread: Borp ran the broader suite despite a specific file argument, making targeted coverage unclear.
|
|
81
|
-
- Continued initiating tool work after the tool-budget warning instead of stopping to assess the existing evidence.
|
|
82
|
-
- Started a test command that was aborted, leaving the primitive-coercion fix unverified.
|
|
83
|
-
- Investigated Ajv internals and custom compiler compatibility without first isolating the exact failing repository behavior.
|
|
84
|
-
- Did not establish regression coverage for missing schemaEnv handling and root primitive coercion before changing direction.
|
|
85
|
-
- PR title did not satisfy the repository's conventional title check before opening/updating the PR.
|
|
86
|
-
- Interpolated `${{ inputs.package }}` directly into `actions/github-script` JavaScript, allowing malformed input to break or inject code.
|
|
87
|
-
- Fetched npm metadata with the raw package name instead of URL-encoding it.
|
|
88
|
-
- Assumed `data.repository.url` always existed and was a GitHub `.git` URL.
|
|
89
|
-
- Used a brittle repository URL regex that missed scoped/modern GitHub URL formats and failed without a clear error.
|
package/AGENTS.md
DELETED
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
# AGENTS.md - Guide for AI Agents Working with Fastify
|
|
2
|
-
|
|
3
|
-
This document provides information and guidelines for AI agents (such as GitHub Copilot, Cursor, pi, or other AI coding assistants) working with the Fastify codebase.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
Fastify is a high-performance web framework for Node.js focused on:
|
|
8
|
-
- **Speed**: One of the fastest Node.js web frameworks
|
|
9
|
-
- **Extensibility**: Powerful plugin architecture with hooks and decorators
|
|
10
|
-
- **Schema-based**: JSON Schema validation and serialization
|
|
11
|
-
- **Developer experience**: Expressive API with minimal overhead
|
|
12
|
-
- **TypeScript support**: Full type definitions included
|
|
13
|
-
|
|
14
|
-
**Current Version**: 5.7.1 (main branch)
|
|
15
|
-
**Repository**: https://github.com/fastify/fastify
|
|
16
|
-
|
|
17
|
-
## Repository Structure
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
fastify/
|
|
21
|
-
├── docs/ # Documentation (Guides and Reference)
|
|
22
|
-
│ ├── Guides/ # Tutorials and how-to guides
|
|
23
|
-
│ └── Reference/ # API documentation
|
|
24
|
-
├── examples/ # Example applications and benchmarks
|
|
25
|
-
├── lib/ # Core library code
|
|
26
|
-
├── test/ # Test files
|
|
27
|
-
├── types/ # TypeScript type definitions
|
|
28
|
-
├── build/ # Build scripts
|
|
29
|
-
├── integration/ # Integration tests
|
|
30
|
-
├── fastify.js # Main entry point
|
|
31
|
-
├── fastify.d.ts # Main TypeScript definitions
|
|
32
|
-
└── package.json # Dependencies and scripts
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Key Files for Agents
|
|
36
|
-
|
|
37
|
-
### Core Files
|
|
38
|
-
- **`fastify.js`** - Main Fastify class and entry point
|
|
39
|
-
- **`fastify.d.ts`** - TypeScript type definitions (keep these in sync)
|
|
40
|
-
- **`lib/`** - All core functionality:
|
|
41
|
-
- `route.js` - Route handling
|
|
42
|
-
- `req-res.js` - Request and Reply objects
|
|
43
|
-
- `hooks.js` - Lifecycle hooks
|
|
44
|
-
- `plugin.js` - Plugin system
|
|
45
|
-
- `validation.js` - Schema validation
|
|
46
|
-
- `content-type-parser.js` - Body parsing
|
|
47
|
-
- `logger.js` - Pino logger integration
|
|
48
|
-
|
|
49
|
-
### Configuration Files
|
|
50
|
-
- **`package.json`** - Scripts, dependencies, and contributors
|
|
51
|
-
- **`eslint.config.js`** - Linting configuration (uses neostandard)
|
|
52
|
-
- **`.markdownlint-cli2.yaml`** - Markdown linting rules
|
|
53
|
-
|
|
54
|
-
### Documentation Files
|
|
55
|
-
- **`README.md`** - Project overview and quick start
|
|
56
|
-
- **`CONTRIBUTING.md`** - Contribution guidelines
|
|
57
|
-
- **`GOVERNANCE.md`** - Links to organization governance
|
|
58
|
-
- **`SECURITY.md`** - Security policy
|
|
59
|
-
- **`docs/Guides/Contributing.md`** - Detailed contributing guide
|
|
60
|
-
- **`docs/Guides/Style-Guide.md`** - Coding style conventions
|
|
61
|
-
|
|
62
|
-
## Testing Conventions
|
|
63
|
-
|
|
64
|
-
### Test Framework
|
|
65
|
-
Fastify uses **Borp** (a custom test runner) for testing.
|
|
66
|
-
|
|
67
|
-
### Test Structure
|
|
68
|
-
- Tests are in the **`test/`** directory
|
|
69
|
-
- Test files follow the pattern: `test/<module>.test.js`
|
|
70
|
-
- Integration tests are in **`integration/`** directory
|
|
71
|
-
|
|
72
|
-
### Running Tests
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
# Run all tests
|
|
76
|
-
npm test
|
|
77
|
-
|
|
78
|
-
# Run unit tests only
|
|
79
|
-
npm run unit
|
|
80
|
-
|
|
81
|
-
# Run tests with coverage
|
|
82
|
-
npm run coverage
|
|
83
|
-
|
|
84
|
-
# Run tests in watch mode
|
|
85
|
-
npm run test:watch
|
|
86
|
-
|
|
87
|
-
# Run TypeScript type tests
|
|
88
|
-
npm run test:typescript
|
|
89
|
-
|
|
90
|
-
# Run CI tests (minimal)
|
|
91
|
-
npm run test:ci
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Test Requirements
|
|
95
|
-
- **100% line coverage** is required for all changes (enforced by CI)
|
|
96
|
-
- Tests must pass on all supported Node.js versions
|
|
97
|
-
- TypeScript types must be tested (using `tsd`)
|
|
98
|
-
|
|
99
|
-
## Code Style and Conventions
|
|
100
|
-
|
|
101
|
-
### Linting
|
|
102
|
-
- Uses **Neostandard** JavaScript style guide
|
|
103
|
-
- ESLint is configured in `eslint.config.js`
|
|
104
|
-
- Run `npm run lint` to check code style
|
|
105
|
-
- Run `npm run lint:fix` to auto-fix issues
|
|
106
|
-
|
|
107
|
-
### Key Style Rules (from Style-Guide.md)
|
|
108
|
-
- Use `const` and `let`, never `var`
|
|
109
|
-
- Use arrow functions for callbacks
|
|
110
|
-
- Use async/await instead of promises
|
|
111
|
-
- Follow semicolon usage (neostandard enforces this)
|
|
112
|
-
- Use template literals for string interpolation
|
|
113
|
-
- Prefer functional methods (`map`, `filter`, `reduce`) over loops
|
|
114
|
-
- Error-first callback pattern for async operations where needed
|
|
115
|
-
|
|
116
|
-
### Naming Conventions
|
|
117
|
-
- **Files**: kebab-case (`content-type-parser.js`)
|
|
118
|
-
- **Variables**: camelCase
|
|
119
|
-
- **Constants**: UPPER_SNAKE_CASE
|
|
120
|
-
- **Classes**: PascalCase
|
|
121
|
-
- **Private methods**: prefixed with `_`
|
|
122
|
-
|
|
123
|
-
## Common Tasks
|
|
124
|
-
|
|
125
|
-
### Adding a New Feature
|
|
126
|
-
1. Implement the feature in `lib/`
|
|
127
|
-
2. Add tests in `test/`
|
|
128
|
-
3. Update TypeScript types in `fastify.d.ts` or `types/`
|
|
129
|
-
4. Update documentation in `docs/`
|
|
130
|
-
5. Run `npm test` to ensure all tests pass
|
|
131
|
-
6. Run `npm run lint` to check code style
|
|
132
|
-
7. Add changelog entry for release
|
|
133
|
-
|
|
134
|
-
### Fixing a Bug
|
|
135
|
-
1. Add a failing test case in `test/`
|
|
136
|
-
2. Fix the bug in `lib/`
|
|
137
|
-
3. Ensure all tests pass
|
|
138
|
-
4. Check if TypeScript types need updating
|
|
139
|
-
5. Update documentation if behavior changes
|
|
140
|
-
|
|
141
|
-
### Working with Plugins
|
|
142
|
-
- See `docs/Guides/Write-Plugin.md` for plugin authoring
|
|
143
|
-
- See `docs/Guides/Plugins-Guide.md` for plugin usage
|
|
144
|
-
- Plugin example: `lib/plugin.js`
|
|
145
|
-
|
|
146
|
-
## Architecture Highlights
|
|
147
|
-
|
|
148
|
-
### Core Components
|
|
149
|
-
|
|
150
|
-
1. **Server (`fastify.js`)**
|
|
151
|
-
- Main Fastify class
|
|
152
|
-
- Server initialization and configuration
|
|
153
|
-
- Plugin system integration (via `avvio`)
|
|
154
|
-
|
|
155
|
-
2. **Routing (`lib/route.js`)**
|
|
156
|
-
- Uses `find-my-way` for fast route matching
|
|
157
|
-
- Route registration and lookup
|
|
158
|
-
- Shorthand methods (get, post, put, delete, etc.)
|
|
159
|
-
|
|
160
|
-
3. **Request/Response (`lib/req-res.js`)**
|
|
161
|
-
- Request object extensions
|
|
162
|
-
- Reply object with fluent API
|
|
163
|
-
- Decorator support
|
|
164
|
-
|
|
165
|
-
4. **Hooks (`lib/hooks.js`)**
|
|
166
|
-
- Lifecycle hooks (onRequest, preHandler, etc.)
|
|
167
|
-
- Hook execution order and timing
|
|
168
|
-
|
|
169
|
-
5. **Validation (`lib/validation.js`)**
|
|
170
|
-
- JSON Schema validation via AJV
|
|
171
|
-
- Response serialization
|
|
172
|
-
- Built-in error serializer
|
|
173
|
-
|
|
174
|
-
6. **Content Type Parser (`lib/content-type-parser.js`)**
|
|
175
|
-
- Request body parsing
|
|
176
|
-
- Custom parser support
|
|
177
|
-
- JSON and other formats
|
|
178
|
-
|
|
179
|
-
### Plugin System
|
|
180
|
-
- Plugins are loaded asynchronously via `avvio`
|
|
181
|
-
- Supports encapsulation (scoped plugins)
|
|
182
|
-
- Hooks and decorators can be scoped
|
|
183
|
-
- See `lib/plugin.js` for implementation
|
|
184
|
-
|
|
185
|
-
## TypeScript Integration
|
|
186
|
-
|
|
187
|
-
- TypeScript definitions are in `fastify.d.ts` and `types/`
|
|
188
|
-
- Types must be tested with `tsd`
|
|
189
|
-
- Run `npm run test:typescript` to verify types
|
|
190
|
-
- Keep types in sync with JavaScript implementation
|
|
191
|
-
|
|
192
|
-
## Performance Considerations
|
|
193
|
-
|
|
194
|
-
Fastify prioritizes performance:
|
|
195
|
-
- **Routes**: Pre-compiled functions for fast matching
|
|
196
|
-
- **Validation**: Compiled JSON Schema validators
|
|
197
|
-
- **Serialization**: Compiled serializers (fast-json-stringify)
|
|
198
|
-
- **Logging**: Low-overhead Pino logger
|
|
199
|
-
- **Caching**: Route context caching with `toad-cache`
|
|
200
|
-
|
|
201
|
-
When making changes:
|
|
202
|
-
- Profile performance impact for hot paths
|
|
203
|
-
- Use benchmarks in `examples/benchmark/`
|
|
204
|
-
- Run `npm run benchmark` to measure
|
|
205
|
-
|
|
206
|
-
## Documentation Updates
|
|
207
|
-
|
|
208
|
-
Documentation is critical for Fastify. When changing behavior:
|
|
209
|
-
|
|
210
|
-
1. Update relevant docs in `docs/Reference/` for API changes
|
|
211
|
-
2. Update `docs/Guides/` for usage pattern changes
|
|
212
|
-
3. Check for broken links (CI validates this)
|
|
213
|
-
4. Update examples in `examples/` if needed
|
|
214
|
-
5. Run `npm run lint:markdown` to check docs
|
|
215
|
-
|
|
216
|
-
## Pre-commit Checks
|
|
217
|
-
|
|
218
|
-
Before submitting changes, ensure:
|
|
219
|
-
|
|
220
|
-
1. ✅ All tests pass: `npm test`
|
|
221
|
-
2. ✅ 100% coverage: `npm run coverage`
|
|
222
|
-
3. ✅ Linting passes: `npm run lint`
|
|
223
|
-
4. ✅ TypeScript types pass: `npm run test:typescript`
|
|
224
|
-
5. ✅ Markdown linting passes: `npm run lint:markdown`
|
|
225
|
-
6. ✅ Documentation is updated
|
|
226
|
-
7. ✅ Examples still work if affected
|
|
227
|
-
|
|
228
|
-
## Working with CI
|
|
229
|
-
|
|
230
|
-
Fastify uses GitHub Actions for CI. Workflows are in `.github/workflows/`:
|
|
231
|
-
- **`ci.yml`** - Main CI pipeline
|
|
232
|
-
- **`package-manager-ci.yml`** - Tests multiple package managers
|
|
233
|
-
- **`website.yml`** - Website deployment
|
|
234
|
-
|
|
235
|
-
## Agent-Specific Tips
|
|
236
|
-
|
|
237
|
-
### When Generating Code
|
|
238
|
-
1. Check existing patterns in `lib/` before creating new patterns
|
|
239
|
-
2. Follow the established error handling patterns
|
|
240
|
-
3. Use async/await consistently
|
|
241
|
-
4. Add appropriate hooks if extending lifecycle
|
|
242
|
-
5. Consider TypeScript types from the start
|
|
243
|
-
|
|
244
|
-
### When Refactoring
|
|
245
|
-
1. Ensure all tests still pass
|
|
246
|
-
2. Don't change public APIs without semver consideration
|
|
247
|
-
3. Update TypeScript definitions if signatures change
|
|
248
|
-
4. Check for deprecation needs
|
|
249
|
-
5. Update documentation for changed behavior
|
|
250
|
-
|
|
251
|
-
### When Analyzing Issues
|
|
252
|
-
1. Check `test/` for usage examples
|
|
253
|
-
2. Review relevant `docs/Reference/` files
|
|
254
|
-
3. Look at similar implementations in `lib/`
|
|
255
|
-
4. Consider the plugin system and encapsulation
|
|
256
|
-
5. Check hook timing and order
|
|
257
|
-
|
|
258
|
-
### Common Gotchas
|
|
259
|
-
- **Encapsulation**: Plugins are isolated - decorators don't leak
|
|
260
|
-
- **Hook order**: Hooks run in specific order (see docs/Reference/Hooks.md)
|
|
261
|
-
- **Async boot**: Server starts asynchronously - use `ready()` or `after()`
|
|
262
|
-
- **Error handling**: Use Fastify error classes from `@fastify/error`
|
|
263
|
-
- **Validation**: Schemas are compiled - changes require recompilation
|
|
264
|
-
|
|
265
|
-
## Key Dependencies
|
|
266
|
-
|
|
267
|
-
- **`avvio`** - Plugin loading and boot
|
|
268
|
-
- **`find-my-way`** - Fast HTTP router
|
|
269
|
-
- **`fast-json-stringify`** - Response serialization
|
|
270
|
-
- **`pino`** - Logging
|
|
271
|
-
- **`@fastify/ajv-compiler`** - JSON Schema validation
|
|
272
|
-
- **`light-my-request`** - HTTP injection for testing
|
|
273
|
-
|
|
274
|
-
## Contact and Resources
|
|
275
|
-
|
|
276
|
-
- **Documentation**: https://fastify.dev/
|
|
277
|
-
- **Discord**: https://discord.gg/fastify
|
|
278
|
-
- **GitHub Issues**: https://github.com/fastify/fastify/issues
|
|
279
|
-
- **GitHub Discussions**: https://github.com/fastify/fastify/discussions
|
|
280
|
-
- **Help**: https://github.com/fastify/help
|
|
281
|
-
|
|
282
|
-
## Version Information
|
|
283
|
-
|
|
284
|
-
- **Main branch**: Fastify v5
|
|
285
|
-
- **v4 branch**: https://github.com/fastify/fastify/tree/4.x
|
|
286
|
-
- **LTS Policy**: See `docs/Reference/LTS.md`
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
This document is maintained by the Fastify team. For questions or suggestions, please open an issue or discussion.
|