@chidchanun/bcp 0.1.26 → 0.1.28

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/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # BCP Framework Documentation Source
2
2
 
3
- The `docs/` directory is the documentation source of truth for BCP Framework and is intentionally organized for the future **`bcp-docs-web`** website.
3
+ The `docs/` directory is the documentation source of truth for BCP Framework and is intentionally organized for the **`bcp-docs-web`** website.
4
4
 
5
- > **Documentation target:** BCP Framework `0.1.26`
5
+ > **Documentation target:** BCP Framework `0.1.28`
6
6
  >
7
- > **Release state:** release-candidate source. Do not label `0.1.26` as published until RC validation and npm publication complete.
7
+ > **Release state:** unreleased development target. Do not label `0.1.28` as published until RC validation and npm publication complete.
8
8
 
9
9
  ## Documentation flow
10
10
 
@@ -88,6 +88,7 @@ Releases
88
88
  | `/docs/development-logging` | `development-logging.md` | Logging/observability |
89
89
  | `/docs/caching` | `caching.md` | Cache/revalidation |
90
90
  | `/docs/security` | `security.md` | Security/body limits |
91
+ | `/docs/production-hardening` | `production-hardening.md` | Graceful shutdown, trusted proxy and production timeouts |
91
92
 
92
93
  ### Storage & Uploads
93
94
 
@@ -95,7 +96,8 @@ Releases
95
96
  | --- | --- | --- |
96
97
  | `/docs/file-upload` | `file-upload.md` | Buffered + streaming multipart uploads |
97
98
  | `/docs/storage` | `storage.md` | StorageAdapter, streaming and file delivery |
98
- | `/docs/s3-storage` | `s3-storage.md` | S3-compatible adapter/configuration |
99
+ | `/docs/storage-ecosystem` | `storage-ecosystem.md` | Listing, copy/move, metadata, bulk delete, signed URLs |
100
+ | `/docs/s3-storage` | `s3-storage.md` | S3/R2/MinIO adapter and direct object access |
99
101
 
100
102
  ## API Reference ownership
101
103
 
@@ -116,7 +118,7 @@ bcp/middleware
116
118
  | Entrypoint | Primary guide |
117
119
  | --- | --- |
118
120
  | `bcp` | `routing.md`, `server-data-loaders.md`, `form-actions.md` |
119
- | `bcp/server` | `server-request-apis.md`, `file-upload.md`, `storage.md`, `s3-storage.md`, `development-logging.md` |
121
+ | `bcp/server` | `server-request-apis.md`, `file-upload.md`, `storage.md`, `storage-ecosystem.md`, `s3-storage.md`, `development-logging.md`, `production-hardening.md` |
120
122
  | `bcp/auth` | `authentication.md`, `auth-route-guards.md` |
121
123
  | `bcp/database` | `database.md`, `database-migrations.md` |
122
124
  | `bcp/validation` | `validation.md` |
@@ -138,7 +140,7 @@ bcp/middleware
138
140
  - client islands / partial hydration
139
141
  - Fast Refresh
140
142
 
141
- ### Server
143
+ ### Server and production runtime
142
144
 
143
145
  - request-scoped APIs/cookies/redirects/request IDs
144
146
  - JWT sessions/authentication
@@ -146,18 +148,28 @@ bcp/middleware
146
148
  - validation/structured errors
147
149
  - structured logging
148
150
  - response caching/security gateway
151
+ - production hardening gateway
152
+ - configurable request/header/keep-alive/shutdown timeouts
153
+ - `SIGTERM` / `SIGINT` graceful shutdown
154
+ - application shutdown hooks
155
+ - trusted-proxy forwarding-header controls
149
156
 
150
157
  ### Storage & Uploads
151
158
 
152
159
  - buffered multipart `FormData` upload APIs
153
160
  - production streaming multipart upload (`storeMultipartFile()`)
154
- - `StorageAdapter` contract
155
- - local filesystem adapter
156
- - S3-compatible adapter
157
- - streaming reads/writes
158
- - byte ranges
161
+ - backward-compatible `StorageAdapter` contract
162
+ - local filesystem storage
163
+ - S3/R2/MinIO-compatible storage
164
+ - streaming reads/writes and byte ranges
159
165
  - ETag/Last-Modified file delivery
160
166
  - upload/storage limits and abort cleanup
167
+ - object listing with cursors
168
+ - native/fallback copy and move
169
+ - portable user metadata
170
+ - bulk deletion
171
+ - S3 presigned read/write URLs
172
+ - create-app Local Server / Amazon S3 / Cloudflare R2 presets
161
173
 
162
174
  ### Database
163
175
 
@@ -177,64 +189,56 @@ bcp/middleware
177
189
  - standalone production build
178
190
  - unit/integration/E2E/package/RC checks
179
191
 
180
- ## BCP 0.1.26 documentation focus
192
+ ## BCP 0.1.28 documentation focus
181
193
 
182
- ### Storage streaming
194
+ ### Production hardening
183
195
 
184
- Public additions include:
196
+ Public cleanup API:
185
197
 
186
198
  ```ts
187
199
  import {
188
- getStorageCapabilities,
189
- putStorageStream,
190
- readStorageStream,
200
+ getProductionHardeningConfig,
201
+ registerShutdownHook,
191
202
  } from "bcp/server";
192
203
  ```
193
204
 
194
- Streaming methods remain optional on custom adapters for `0.1.25` compatibility.
205
+ Production environment controls:
195
206
 
196
- ### S3-compatible storage
197
-
198
- ```ts
199
- import {
200
- createS3Storage,
201
- } from "bcp/server";
207
+ ```dotenv
208
+ BCP_REQUEST_TIMEOUT_MS=120000
209
+ BCP_HEADERS_TIMEOUT_MS=66000
210
+ BCP_KEEP_ALIVE_TIMEOUT_MS=65000
211
+ BCP_SHUTDOWN_TIMEOUT_MS=10000
212
+ BCP_TRUST_PROXY=false
202
213
  ```
203
214
 
204
- Document:
215
+ Document these boundaries clearly:
205
216
 
206
- - bucket/region/endpoint setup,
207
- - optional explicit credentials,
208
- - AWS default credential chain behavior,
209
- - `forcePathStyle` for compatible services such as MinIO,
210
- - prefix handling,
211
- - multipart streaming,
212
- - ranges/ETag metadata,
213
- - overwrite limitations for concurrent multipart writers,
214
- - server-only credential/security requirements.
217
+ - trusted proxy mode is off by default,
218
+ - forwarding headers are sanitized when trust is disabled,
219
+ - enable trust only behind a trusted reverse proxy/load balancer,
220
+ - Docker/process-manager `SIGTERM` triggers graceful shutdown,
221
+ - shutdown hooks are process-lifetime resource cleanup, not request cleanup,
222
+ - shutdown force-closes remaining public connections after the configured timeout.
215
223
 
216
- See `s3-storage.md`.
224
+ See `production-hardening.md`.
217
225
 
218
- ### Production multipart streaming
226
+ ### Local Server generator fix
219
227
 
220
- ```ts
221
- import {
222
- storeMultipartFile,
223
- } from "bcp/server";
228
+ `create-bcp-app --storage local` now generates:
229
+
230
+ ```text
231
+ lib/storage.ts
232
+ storage/
233
+ ├─ .gitkeep
234
+ └─ README.md
224
235
  ```
225
236
 
226
- Document:
237
+ Runtime objects remain ignored while the scaffold stays visible/tracked.
227
238
 
228
- - one named streamed file field per operation,
229
- - total request limit,
230
- - per-file limit,
231
- - MIME/extension validation,
232
- - fixed/callback storage keys,
233
- - AbortSignal behavior,
234
- - direct local/S3 streaming,
235
- - difference from `request.formData()` / buffered APIs.
239
+ ### 0.1.27 storage ecosystem remains supported
236
240
 
237
- See `file-upload.md`.
241
+ The storage ecosystem continues to include listing, copy/move, portable metadata, bulk deletion and S3 signed URLs. `0.1.28` hardens deployment/runtime behavior rather than replacing those APIs.
238
242
 
239
243
  ## CLI commands
240
244
 
@@ -278,11 +282,11 @@ docs/releases/
278
282
  Recommended routes:
279
283
 
280
284
  ```text
285
+ /releases/0.1.28
286
+ /releases/0.1.27
281
287
  /releases/0.1.26
282
288
  /releases/0.1.25
283
289
  /releases/0.1.24
284
- /releases/0.1.23
285
- /releases/0.1.22
286
290
  ```
287
291
 
288
292
  Use one of these release states:
@@ -311,8 +315,6 @@ interface DocPage {
311
315
  }
312
316
  ```
313
317
 
314
- The first `bcp-docs-web` implementation can keep this mapping in a route manifest and consume Markdown directly.
315
-
316
318
  ## Suggested website features
317
319
 
318
320
  1. Sidebar navigation from this source map.
@@ -357,15 +359,9 @@ npm run test:package
357
359
  npm run rc:check
358
360
  ```
359
361
 
360
- For `0.1.26`, package validation must also confirm the staged npm artifact contains:
361
-
362
- ```text
363
- @aws-sdk/client-s3
364
- @aws-sdk/lib-storage
365
- busboy
366
- ```
362
+ For `0.1.28`, package validation must confirm the staged artifact includes the production hardening runtime/gateway, shutdown APIs, Local Server generator fix, and the existing S3 runtime dependencies.
367
363
 
368
- and the S3/multipart streaming source files/public exports.
364
+ A representative Docker app should also be built and stopped with `docker stop` to verify graceful `SIGTERM` shutdown.
369
365
 
370
366
  ## Documentation QA checklist
371
367
 
@@ -374,33 +370,24 @@ and the S3/multipart streaming source files/public exports.
374
370
  - version/release states are current,
375
371
  - Windows direct CLI examples use `npm exec -- bcp-framework`,
376
372
  - upload/storage/auth security caveats are present,
377
- - route names match the current router,
378
373
  - release notes match the framework version,
379
374
  - S3 credentials are never shown as public browser variables,
375
+ - signed URLs are documented as temporary credentials,
376
+ - proxy trust is documented as opt-in,
380
377
  - roadmap APIs are not presented as published guarantees.
381
378
 
382
- ## Next direction after 0.1.26
379
+ ## Next direction after 0.1.28
383
380
 
384
- Recommended `0.1.27` direction:
381
+ Planned `0.1.29 — Developer Experience` focus:
385
382
 
386
- - signed URLs where needed,
387
- - object listing/copy/move capabilities,
388
- - broader production hardening,
389
- - graceful shutdown/resource cleanup,
390
- - stronger storage/provider diagnostics.
383
+ - generators for common framework files,
384
+ - richer `doctor` and `inspect`,
385
+ - improved build/runtime diagnostics,
386
+ - create-app preset improvements,
387
+ - production configuration diagnostics.
391
388
 
392
- These are roadmap items, not `0.1.26` guarantees.
389
+ These remain roadmap items until their source/tests land.
393
390
 
394
391
  ## Repository authority
395
392
 
396
- The framework repository remains authoritative for:
397
-
398
- ```text
399
- source
400
- public exports
401
- tests
402
- docs
403
- release notes
404
- ```
405
-
406
- `bcp-docs-web` is the presentation/search/navigation layer for this content.
393
+ The framework repository remains authoritative for source, public exports, tests, docs and release notes. `bcp-docs-web` is the presentation/search/navigation layer for this content.
@@ -0,0 +1,152 @@
1
+ # Production Hardening
2
+
3
+ BCP Framework `0.1.28` adds a production hardening gateway around the standalone runtime.
4
+
5
+ The gateway is the public HTTP listener. Existing security, cache, critical CSS, page/API and SSR runtimes remain bound to internal loopback ports behind it.
6
+
7
+ ## Default production behavior
8
+
9
+ The hardening gateway configures Node HTTP timeouts and graceful shutdown defaults:
10
+
11
+ ```text
12
+ Request timeout: 120000 ms
13
+ Headers timeout: 66000 ms
14
+ Keep-alive timeout: 65000 ms
15
+ Shutdown timeout: 10000 ms
16
+ Trust proxy: false
17
+ ```
18
+
19
+ Override them with server-only environment variables:
20
+
21
+ ```dotenv
22
+ BCP_REQUEST_TIMEOUT_MS=120000
23
+ BCP_HEADERS_TIMEOUT_MS=66000
24
+ BCP_KEEP_ALIVE_TIMEOUT_MS=65000
25
+ BCP_SHUTDOWN_TIMEOUT_MS=10000
26
+ BCP_TRUST_PROXY=false
27
+ ```
28
+
29
+ `BCP_HEADERS_TIMEOUT_MS` must be greater than `BCP_KEEP_ALIVE_TIMEOUT_MS`.
30
+
31
+ ## Graceful shutdown
32
+
33
+ Standalone production now handles `SIGTERM` and `SIGINT`.
34
+
35
+ This is especially important for Docker, Kubernetes and process managers that send `SIGTERM` before stopping a process.
36
+
37
+ Shutdown order:
38
+
39
+ ```text
40
+ stop accepting public traffic
41
+
42
+ drain/close public HTTP connections
43
+
44
+ run application shutdown hooks
45
+
46
+ stop internal BCP runtime layers
47
+
48
+ process exits naturally
49
+ ```
50
+
51
+ If the public server does not close before `BCP_SHUTDOWN_TIMEOUT_MS`, BCP force-closes remaining connections.
52
+
53
+ ## Application shutdown hooks
54
+
55
+ Register cleanup work through `bcp/server`:
56
+
57
+ ```ts
58
+ import {
59
+ registerShutdownHook,
60
+ } from "bcp/server";
61
+
62
+ const unregister =
63
+ registerShutdownHook(
64
+ async () => {
65
+ await closeApplicationResources();
66
+ },
67
+ {
68
+ name: "application-resources",
69
+ }
70
+ );
71
+ ```
72
+
73
+ Hooks run in reverse registration order. Calling the returned function unregisters the hook.
74
+
75
+ For S3-compatible storage, an application can register the adapter client cleanup when it owns the adapter for the lifetime of the process:
76
+
77
+ ```ts
78
+ registerShutdownHook(
79
+ () => {
80
+ storage.destroy();
81
+ },
82
+ {
83
+ name: "s3-storage",
84
+ }
85
+ );
86
+ ```
87
+
88
+ Do not register request-scoped resources as process shutdown hooks.
89
+
90
+ ## Trusted proxy mode
91
+
92
+ The hardening gateway sanitizes forwarding headers by default.
93
+
94
+ ```dotenv
95
+ BCP_TRUST_PROXY=false
96
+ ```
97
+
98
+ This prevents a direct client from spoofing headers such as:
99
+
100
+ ```text
101
+ Forwarded
102
+ X-Forwarded-For
103
+ X-Forwarded-Host
104
+ X-Forwarded-Proto
105
+ X-Real-IP
106
+ ```
107
+
108
+ When BCP is deployed only behind a trusted reverse proxy such as Nginx, Cloudflare Tunnel or a trusted load balancer, enable:
109
+
110
+ ```dotenv
111
+ BCP_TRUST_PROXY=true
112
+ ```
113
+
114
+ BCP then preserves the trusted proxy forwarding chain and appends the immediate peer address where appropriate.
115
+
116
+ Only enable trusted proxy mode when direct untrusted traffic cannot bypass the trusted proxy.
117
+
118
+ ## Docker
119
+
120
+ A production compose service can use:
121
+
122
+ ```yaml
123
+ services:
124
+ app:
125
+ init: true
126
+ restart: unless-stopped
127
+ environment:
128
+ NODE_ENV: production
129
+ BCP_HOSTNAME: 0.0.0.0
130
+ BCP_PORT: 3000
131
+ BCP_SHUTDOWN_TIMEOUT_MS: 10000
132
+ BCP_TRUST_PROXY: "true"
133
+ ```
134
+
135
+ Set `BCP_TRUST_PROXY=true` only when the container receives requests exclusively from a trusted reverse proxy/network path.
136
+
137
+ Docker's stop grace period should be longer than `BCP_SHUTDOWN_TIMEOUT_MS` so BCP gets time to drain connections and cleanup resources.
138
+
139
+ ## Local Server storage scaffold
140
+
141
+ `create-bcp-app --storage local` now creates:
142
+
143
+ ```text
144
+ lib/storage.ts
145
+ storage/
146
+ ├─ .gitkeep
147
+ └─ README.md
148
+ ```
149
+
150
+ Runtime objects inside `storage/` are ignored while the scaffold files remain tracked. The generated README explains that BCP writes objects and `.bcp-storage-meta` metadata there at runtime.
151
+
152
+ The directory therefore no longer appears as an unexplained empty folder before the first upload.