@chidchanun/bcp 0.1.24 → 0.1.25

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,61 +1,134 @@
1
1
  # BCP Framework Documentation Source
2
2
 
3
- This directory is the documentation source of truth for the BCP Framework documentation website (`bcp-docs`).
3
+ The `docs/` directory is the documentation source of truth for BCP Framework and is intentionally organized so it can be consumed later by the **`bcp-docs-web`** documentation website.
4
4
 
5
- > Documentation target: BCP Framework `0.1.24`
5
+ > **Documentation target:** BCP Framework `0.1.25`
6
+ >
7
+ > The documentation target can be newer than the version currently published to npm. Unreleased behavior must be labeled as a development target until release validation and publication are complete.
6
8
 
7
- When framework behavior changes, update framework source/tests first, then the matching file under `docs/`, then the release note under `docs/releases/`.
9
+ ## Documentation goals
8
10
 
9
- ## Recommended website navigation
11
+ The documentation source should make it possible to build `bcp-docs-web` without duplicating framework knowledge into a second repository.
12
+
13
+ The expected relationship is:
14
+
15
+ ```text
16
+ BCP Framework source/tests
17
+
18
+ docs/
19
+
20
+ bcp-docs-web
21
+ ```
22
+
23
+ Framework source and tests remain authoritative for behavior. Markdown under `docs/` is the authored documentation layer. The future website should primarily render, organize and search this source instead of becoming a separate source of truth.
24
+
25
+ ## Content update rule
26
+
27
+ When framework behavior changes:
28
+
29
+ 1. Update framework source.
30
+ 2. Add or update regression tests.
31
+ 3. Update the matching documentation file under `docs/`.
32
+ 4. Update the release note under `docs/releases/` when the change belongs to a release milestone.
33
+ 5. Only present the feature as published after release validation and npm publication complete.
34
+
35
+ ## Recommended `bcp-docs-web` navigation
36
+
37
+ The website should use these top-level groups:
38
+
39
+ ```text
40
+ Getting Started
41
+ Routing & Data
42
+ Authentication
43
+ Database
44
+ Runtime & Infrastructure
45
+ API Reference
46
+ Releases
47
+ ```
10
48
 
11
49
  ### Getting Started
12
50
 
13
- | Route | Source | Purpose |
51
+ | Website route | Markdown source | Purpose |
14
52
  | --- | --- | --- |
15
53
  | `/docs/getting-started` | `getting-started.md` | Create and run a BCP application |
16
- | `/docs/configuration` | `configuration.md` | Framework configuration |
17
- | `/docs/application-modules` | `application-modules.md` | Client/server boundaries |
18
- | `/docs/deployment` | `deployment.md` | Production deployment |
19
- | `/docs/updating` | `updating.md` | Framework upgrades |
54
+ | `/docs/configuration` | `configuration.md` | Framework configuration and environment behavior |
55
+ | `/docs/application-modules` | `application-modules.md` | Client/server boundaries and module rules |
56
+ | `/docs/deployment` | `deployment.md` | Standalone production deployment |
57
+ | `/docs/updating` | `updating.md` | Framework upgrade workflow |
20
58
 
21
- ### Routing and Data
59
+ ### Routing & Data
22
60
 
23
- | Route | Source | Purpose |
61
+ | Website route | Markdown source | Purpose |
24
62
  | --- | --- | --- |
25
- | `/docs/routing` | `routing.md` | File-based routing |
63
+ | `/docs/routing` | `routing.md` | File-based page/API routing |
26
64
  | `/docs/server-data-loaders` | `server-data-loaders.md` | Server-side page data |
27
65
  | `/docs/route-guards` | `route-guards.md` | Scoped route authorization |
28
- | `/docs/form-actions` | `form-actions.md` | Server mutations/forms |
66
+ | `/docs/form-actions` | `form-actions.md` | Server mutations and forms |
29
67
  | `/docs/server-request-apis` | `server-request-apis.md` | Request/cookie/response APIs |
30
68
  | `/docs/validation` | `validation.md` | Typed validation |
31
69
  | `/docs/error-handling` | `error-handling.md` | Structured HTTP errors |
32
- | `/docs/file-upload` | `file-upload.md` | Multipart parsing, validation and local file storage |
70
+ | `/docs/file-upload` | `file-upload.md` | Multipart parsing and upload validation |
71
+ | `/docs/storage` | `storage.md` | Storage adapters and production file delivery |
33
72
 
34
73
  ### Authentication
35
74
 
36
- | Route | Source | Purpose |
75
+ | Website route | Markdown source | Purpose |
37
76
  | --- | --- | --- |
38
77
  | `/docs/authentication` | `authentication.md` | Authentication Core |
39
- | `/docs/auth-route-guards` | `auth-route-guards.md` | Auth-aware guards |
78
+ | `/docs/auth-route-guards` | `auth-route-guards.md` | Auth-aware route guards |
40
79
  | `/docs/session-auth` | `session-auth.md` | JWT cookie sessions |
41
80
 
42
81
  ### Database
43
82
 
44
- | Route | Source | Purpose |
83
+ | Website route | Markdown source | Purpose |
45
84
  | --- | --- | --- |
46
85
  | `/docs/database` | `database.md` | MySQL database primitives |
47
- | `/docs/database-migrations` | `database-migrations.md` | Migration CLI and files |
86
+ | `/docs/database-migrations` | `database-migrations.md` | Migration CLI and migration files |
48
87
 
49
- ### Runtime and Infrastructure
88
+ ### Runtime & Infrastructure
50
89
 
51
- | Route | Source | Purpose |
90
+ | Website route | Markdown source | Purpose |
52
91
  | --- | --- | --- |
53
92
  | `/docs/middleware` | `middleware.md` | Middleware System v2 |
54
93
  | `/docs/hydration` | `hydration.md` | SSR/client hydration parity |
55
- | `/docs/developer-tools` | `developer-tools.md` | `doctor` / `inspect` diagnostics |
94
+ | `/docs/developer-tools` | `developer-tools.md` | `doctor` and `inspect` diagnostics |
56
95
  | `/docs/development-logging` | `development-logging.md` | Structured logging and observability |
57
- | `/docs/caching` | `caching.md` | Cache/revalidation |
58
- | `/docs/security` | `security.md` | Security defaults and body limits |
96
+ | `/docs/caching` | `caching.md` | Cache and revalidation |
97
+ | `/docs/security` | `security.md` | Security defaults and request body limits |
98
+
99
+ ## API Reference grouping
100
+
101
+ `bcp-docs-web` can derive an API-reference navigation layer from the authored guides.
102
+
103
+ Recommended entrypoint groups:
104
+
105
+ ```text
106
+ bcp
107
+ bcp/server
108
+ bcp/auth
109
+ bcp/database
110
+ bcp/validation
111
+ bcp/error
112
+ bcp/cache
113
+ bcp/config
114
+ bcp/middleware
115
+ ```
116
+
117
+ The first version of the website does not need generated TypeDoc-style reference pages. It can begin by linking APIs to the guide that owns them, then add generated symbol-level reference later if useful.
118
+
119
+ Suggested ownership:
120
+
121
+ | Entrypoint | Primary guide |
122
+ | --- | --- |
123
+ | `bcp` | `routing.md`, `server-data-loaders.md`, `form-actions.md` |
124
+ | `bcp/server` | `server-request-apis.md`, `file-upload.md`, `storage.md`, `development-logging.md` |
125
+ | `bcp/auth` | `authentication.md`, `auth-route-guards.md` |
126
+ | `bcp/database` | `database.md`, `database-migrations.md` |
127
+ | `bcp/validation` | `validation.md` |
128
+ | `bcp/error` | `error-handling.md` |
129
+ | `bcp/cache` | `caching.md` |
130
+ | `bcp/config` | `configuration.md` |
131
+ | `bcp/middleware` | `middleware.md` |
59
132
 
60
133
  ## Current capability groups
61
134
 
@@ -63,29 +136,46 @@ When framework behavior changes, update framework source/tests first, then the m
63
136
 
64
137
  - React SSR and hydration
65
138
  - file-based page/API routing
66
- - dynamic/catch-all routes
139
+ - dynamic routes
140
+ - catch-all and optional catch-all routes
141
+ - route groups
67
142
  - layouts and metadata
68
143
  - SPA navigation
69
- - loaders, guards and form actions
144
+ - server data loaders
145
+ - route guards
146
+ - form actions
70
147
  - client islands / partial hydration
71
- - Fast Refresh and deterministic development hydration
148
+ - Fast Refresh
149
+ - deterministic development hydration
72
150
 
73
151
  ### Server
74
152
 
75
153
  - request-scoped server APIs
154
+ - request IDs
76
155
  - cookies and redirects
77
- - JWT sessions and authentication
156
+ - JWT sessions
157
+ - authentication helpers
78
158
  - Middleware System v2
79
- - typed validation and structured errors
80
- - structured logging with request identity
81
- - multipart file uploads and local filesystem persistence
159
+ - typed validation
160
+ - structured errors
161
+ - structured logging
162
+ - multipart file uploads
163
+ - upload validation
164
+ - storage adapter contract
165
+ - local filesystem storage adapter
166
+ - production file delivery
167
+ - validators and byte ranges
82
168
 
83
169
  ### Database
84
170
 
85
171
  - `bcp/database`
86
- - MySQL pool/query helpers
172
+ - lazy MySQL pool
173
+ - prepared execution
174
+ - query helpers
87
175
  - transactions
88
- - migrations/status/rollback
176
+ - migrations
177
+ - migration status
178
+ - rollback
89
179
 
90
180
  ### Developer Experience
91
181
 
@@ -93,69 +183,110 @@ When framework behavior changes, update framework source/tests first, then the m
93
183
  - `bcp update`
94
184
  - `bcp doctor`
95
185
  - `bcp inspect`
186
+ - route inspection
96
187
  - `bcp-framework` Windows-safe CLI alias
97
188
  - standalone production build
189
+ - unit/integration/E2E/package tests
98
190
  - release/package smoke checks
99
191
 
100
- ## BCP 0.1.24 documentation priorities
192
+ ## BCP 0.1.25 documentation focus
101
193
 
102
- ### File Upload
194
+ ### Storage adapters
103
195
 
104
- BCP 0.1.24 exposes upload helpers through the server-only `bcp/server` entrypoint:
196
+ BCP `0.1.25` introduces the first application-facing storage abstraction through `bcp/server`:
105
197
 
106
198
  ```ts
107
199
  import {
108
- parseMultipartFormData,
109
- getUploadedFile,
110
- requireUploadedFile,
111
- validateUploadedFile,
112
- saveUploadedFile,
113
- sanitizeUploadFileName,
114
- UploadError,
200
+ createLocalStorage,
201
+ createStorageResponse,
202
+ normalizeStorageKey,
203
+ StorageError,
204
+ storeUploadedFile,
115
205
  } from "bcp/server";
116
206
  ```
117
207
 
118
- Documentation must make the following boundaries clear:
208
+ The documentation must make these boundaries clear:
119
209
 
120
- - `server.bodyLimit` / `BCP_BODY_LIMIT` is the outer request-size limit enforced by the security gateway.
121
- - multipart and individual file limits can be stricter than the global body limit.
122
- - MIME type and extension are metadata checks, not file-signature verification.
123
- - default storage names are UUID based.
124
- - existing files are not overwritten unless explicitly requested.
125
- - saved metadata includes SHA-256 checksum.
126
- - local filesystem storage is the initial foundation; distributed/object storage requires a later adapter layer.
210
+ - `StorageAdapter` is the application-facing contract.
211
+ - `createLocalStorage()` is the built-in adapter in this milestone.
212
+ - storage keys are logical relative paths, not operating-system paths.
213
+ - absolute paths and traversal segments are rejected.
214
+ - overwrite is opt-in.
215
+ - local metadata persists content type and SHA-256 identity.
216
+ - `createStorageResponse()` supports `GET` and `HEAD`.
217
+ - validators include ETag and Last-Modified behavior.
218
+ - single byte ranges are supported.
219
+ - multiple ranges are intentionally unsupported in `0.1.25` and return `416`.
220
+ - the default cache policy is private/revalidate.
221
+ - public caching must be explicit.
222
+ - storage keys do not replace authentication or authorization.
127
223
 
128
- See `file-upload.md`.
224
+ See `storage.md`.
129
225
 
130
- ### Dev route/client bundle synchronization
226
+ ### File Upload
131
227
 
132
- 0.1.24 also fixes a development-only graph drift that could produce:
228
+ BCP `0.1.24` introduced:
133
229
 
134
- ```text
135
- Client bundle was not found for route "/docs/[...slug]".
136
- ```
230
+ - multipart parsing,
231
+ - request/file size limits,
232
+ - MIME allowlists,
233
+ - extension allowlists,
234
+ - required/optional file fields,
235
+ - safe local file names,
236
+ - traversal protection,
237
+ - overwrite protection,
238
+ - SHA-256 metadata.
239
+
240
+ Those APIs remain supported in `0.1.25`.
241
+
242
+ `storeUploadedFile()` is the bridge between a validated multipart `File` and a `StorageAdapter`.
243
+
244
+ See:
245
+
246
+ - `file-upload.md`
247
+ - `storage.md`
137
248
 
138
- The dev gateway now compares the actual page route topology and refreshes the internal client bundler when pathname/page/layout structure changes. Users should no longer need to manually delete `.bcp-framework` to recover a missing route bundle.
249
+ ### Production auth guard stabilization
139
250
 
140
- ### Logging & Observability
251
+ The `0.1.24` stabilization cycle unified standalone guard/action authentication imports with the active request-context runtime.
141
252
 
142
- 0.1.23 introduced:
253
+ This prevents production-only failures where APIs such as `cookies()`, `getSession()`, `requireAuth()` or `requireRole()` could see a different request-context instance after bundling.
143
254
 
144
- - `logger` / `createLogger()`
145
- - request-scoped `requestLogger()`
146
- - log levels and JSON format
147
- - `X-Request-Id` helpers
148
- - structured development request/SSR timing
255
+ ### Development route graph synchronization
256
+
257
+ The `0.1.24` stabilization cycle also fixed a development graph drift where the route scanner could see a new route while the incremental client bundle graph still represented the previous topology.
258
+
259
+ The development gateway now compares the actual page route graph and refreshes the internal client bundler when pathname/page/layout topology changes.
260
+
261
+ ### Logging and observability
262
+
263
+ BCP `0.1.23` introduced:
264
+
265
+ - `logger`,
266
+ - `createLogger()`,
267
+ - request-scoped `requestLogger()`,
268
+ - log levels,
269
+ - pretty/JSON formats,
270
+ - request IDs,
271
+ - structured development request logging,
272
+ - SSR/import debug timing.
149
273
 
150
274
  See `development-logging.md`.
151
275
 
152
- ### Developer Tools
276
+ ### Developer tools
153
277
 
154
- 0.1.22 introduced `bcp doctor` and `bcp inspect`, JSON reports, duplicate React diagnostics and duplicate BCP-install protection.
278
+ BCP `0.1.22` introduced:
279
+
280
+ - `bcp doctor`,
281
+ - `bcp inspect`,
282
+ - JSON diagnostic output,
283
+ - duplicate React detection,
284
+ - duplicate BCP installation protection,
285
+ - Windows-safe `bcp-framework` CLI alias.
155
286
 
156
287
  See `developer-tools.md`.
157
288
 
158
- ## Commands
289
+ ## CLI commands
159
290
 
160
291
  ```bash
161
292
  bcp dev
@@ -175,19 +306,29 @@ bcp db status
175
306
  bcp db rollback
176
307
  ```
177
308
 
178
- On Windows systems where SQL Server owns `bcp.exe`, direct shell commands can use:
309
+ On Windows systems where Microsoft SQL Server owns `bcp.exe`, direct project-local commands should prefer:
179
310
 
180
311
  ```powershell
181
- bcp-framework doctor
182
- bcp-framework inspect
183
- bcp-framework dev
312
+ npm exec -- bcp-framework doctor
313
+ npm exec -- bcp-framework inspect
314
+ npm exec -- bcp-framework dev
315
+ npm exec -- bcp-framework build
184
316
  ```
185
317
 
186
- ## Releases
318
+ Inside npm scripts, `bcp` remains safe because npm prepends `node_modules/.bin` to `PATH`.
319
+
320
+ ## Release documentation
187
321
 
188
- Recommended release routes:
322
+ Release notes live under:
189
323
 
190
324
  ```text
325
+ docs/releases/
326
+ ```
327
+
328
+ Recommended website release routes:
329
+
330
+ ```text
331
+ /releases/0.1.25
191
332
  /releases/0.1.24
192
333
  /releases/0.1.23
193
334
  /releases/0.1.22
@@ -195,20 +336,133 @@ Recommended release routes:
195
336
  /releases/0.1.20
196
337
  ```
197
338
 
198
- Do not present unreleased `main` behavior as already available from npm. The website should distinguish the stable npm version from the documentation target when they differ.
339
+ The website should display a clear release state for each version:
340
+
341
+ ```text
342
+ published
343
+ release candidate
344
+ unreleased development target
345
+ ```
346
+
347
+ Do not infer publication state only from the existence of a Markdown release note.
348
+
349
+ ## Suggested `bcp-docs-web` content model
350
+
351
+ A future website can represent each Markdown page with metadata similar to:
352
+
353
+ ```ts
354
+ interface DocPage {
355
+ title: string;
356
+ slug: string;
357
+ section: string;
358
+ sourceFile: string;
359
+ versionTarget?: string;
360
+ releaseState?:
361
+ | "published"
362
+ | "rc"
363
+ | "unreleased";
364
+ }
365
+ ```
366
+
367
+ The metadata does not need to live in frontmatter immediately. The first implementation can use a route manifest in the docs website and consume Markdown files directly.
368
+
369
+ ## Suggested website features
370
+
371
+ The first useful version of `bcp-docs-web` should prioritize:
372
+
373
+ 1. Sidebar navigation generated from the route/source map.
374
+ 2. Markdown rendering with syntax highlighting.
375
+ 3. Previous/next page navigation.
376
+ 4. Version/development-target banner.
377
+ 5. Release note pages.
378
+ 6. Search across Markdown content.
379
+ 7. Copy buttons for code blocks.
380
+ 8. Mobile navigation.
381
+ 9. Direct GitHub source/edit links.
382
+
383
+ Later additions can include:
384
+
385
+ - generated API symbol reference,
386
+ - versioned documentation snapshots,
387
+ - interactive examples,
388
+ - framework playgrounds,
389
+ - release comparison pages.
390
+
391
+ ## Source conventions
392
+
393
+ For documentation intended for the website:
394
+
395
+ - use one H1 per source page,
396
+ - keep heading hierarchy stable,
397
+ - use fenced code blocks with language tags,
398
+ - use relative repository links for other docs,
399
+ - keep API names exactly aligned with public exports,
400
+ - distinguish current behavior from roadmap plans,
401
+ - include security limitations next to the API they affect,
402
+ - prefer runnable examples over pseudo APIs,
403
+ - avoid documenting private/internal modules as public APIs.
404
+
405
+ ## Stable vs development documentation
406
+
407
+ `main` can contain documentation for the next release before npm publication.
408
+
409
+ Therefore the website must distinguish:
410
+
411
+ ```text
412
+ Documentation target != necessarily current npm stable version
413
+ ```
414
+
415
+ For example, while `0.1.25` is under release validation, `docs/storage.md` can describe the `0.1.25` development target, but the website should not label it as published until the release is actually available.
199
416
 
200
- ## Release workflow
417
+ ## Release validation
201
418
 
202
- Before publishing a BCP release:
419
+ Before publishing a framework release:
203
420
 
204
421
  ```bash
205
422
  npm run typecheck
206
423
  npm run test:unit
424
+ npm run test:e2e
425
+ npm run test:package
207
426
  npm run rc:check
208
427
  ```
209
428
 
210
- The framework repository remains authoritative for API behavior. `bcp-docs` is the presentation layer for this source content.
429
+ Release validation should include packed-package smoke verification and representative production application testing.
430
+
431
+ ## Documentation QA checklist
432
+
433
+ Before a docs release or website sync:
211
434
 
212
- ## Next milestone
435
+ - all linked Markdown files exist,
436
+ - examples use public exports,
437
+ - version numbers are current,
438
+ - unreleased features are labeled correctly,
439
+ - Windows CLI instructions use the safe alias where needed,
440
+ - security caveats are present for uploads/storage/authentication,
441
+ - route names match the current router,
442
+ - release notes match the framework version,
443
+ - no generated `.bcp-framework` paths are presented as user-authored source files.
444
+
445
+ ## Roadmap
446
+
447
+ After `0.1.25`, the current planned framework direction is:
448
+
449
+ 1. S3-compatible / cloud storage integration.
450
+ 2. Production upload streaming.
451
+ 3. Broader storage adapter ecosystem.
452
+ 4. Additional production hardening.
453
+
454
+ These are roadmap items, not published API guarantees.
455
+
456
+ ## Repository authority
457
+
458
+ The framework repository remains authoritative for:
459
+
460
+ ```text
461
+ source
462
+ public exports
463
+ tests
464
+ docs
465
+ release notes
466
+ ```
213
467
 
214
- After 0.1.24, the planned follow-up is `0.1.25` for upload/storage adapters and production file-delivery hardening unless roadmap priorities are regrouped.
468
+ `bcp-docs-web` should be treated as the presentation/search/navigation layer for this content rather than a competing documentation source.
@@ -0,0 +1,132 @@
1
+ # BCP Framework 0.1.25
2
+
3
+ BCP 0.1.25 adds the first storage-adapter contract and hardened file-delivery responses on top of the multipart/file upload foundation introduced in 0.1.24.
4
+
5
+ ## Highlights
6
+
7
+ - Added `StorageAdapter` for application-level storage abstraction.
8
+ - Added built-in `createLocalStorage()` filesystem adapter.
9
+ - Added traversal-safe relative storage keys.
10
+ - Added overwrite protection by default.
11
+ - Added persistent local metadata for content type and SHA-256 identity.
12
+ - Added `stat()`, ranged `read()`, `exists()` and `delete()` operations.
13
+ - Added `storeUploadedFile()` to write validated multipart `File` values into any storage adapter.
14
+ - Added `createStorageResponse()` for production GET/HEAD delivery.
15
+ - Added strong ETag validators for objects written through the local adapter.
16
+ - Added `If-None-Match`, `If-Modified-Since` and `If-Range` support.
17
+ - Added single byte-range delivery with `206 Partial Content`.
18
+ - Added `416 Range Not Satisfiable` handling.
19
+ - Added safe `Content-Disposition` generation for downloads.
20
+ - Added conservative private cache defaults.
21
+ - Added storage/file-delivery unit and public-export regression coverage.
22
+
23
+ ## Storage abstraction
24
+
25
+ ```ts
26
+ import {
27
+ createLocalStorage,
28
+ } from "bcp/server";
29
+
30
+ const storage =
31
+ createLocalStorage({
32
+ directory:
33
+ "./uploads",
34
+ });
35
+
36
+ await storage.put(
37
+ "documents/report.txt",
38
+ "Hello",
39
+ {
40
+ contentType:
41
+ "text/plain",
42
+ }
43
+ );
44
+ ```
45
+
46
+ The public adapter contract includes:
47
+
48
+ ```text
49
+ put
50
+ stat
51
+ read
52
+ exists
53
+ delete
54
+ ```
55
+
56
+ Application code can depend on `StorageAdapter` instead of the local filesystem implementation.
57
+
58
+ ## Upload integration
59
+
60
+ ```ts
61
+ const stored =
62
+ await storeUploadedFile(
63
+ file,
64
+ {
65
+ storage,
66
+ key:
67
+ "avatars/user-101.webp",
68
+ }
69
+ );
70
+ ```
71
+
72
+ The upload validation APIs from 0.1.24 remain compatible. `storeUploadedFile()` is additive and reuses the same `UploadConstraints` validation model.
73
+
74
+ ## File delivery
75
+
76
+ ```ts
77
+ return createStorageResponse(
78
+ request,
79
+ storage,
80
+ "documents/report.pdf",
81
+ {
82
+ disposition:
83
+ "attachment",
84
+ downloadName:
85
+ "report.pdf",
86
+ }
87
+ );
88
+ ```
89
+
90
+ The helper supports:
91
+
92
+ ```text
93
+ 200 full response
94
+ 206 single byte range
95
+ 304 validator hit
96
+ 404 missing object
97
+ 405 unsupported request method
98
+ 416 invalid/unsupported range
99
+ ```
100
+
101
+ `HEAD` returns the same entity metadata headers without reading object bytes into the response body.
102
+
103
+ Multiple ranges are intentionally unsupported in 0.1.25 and return `416`.
104
+
105
+ ## Cache policy
106
+
107
+ The default is:
108
+
109
+ ```text
110
+ private, max-age=0, must-revalidate
111
+ ```
112
+
113
+ Applications can explicitly opt public immutable files into stronger caching.
114
+
115
+ ## Security model
116
+
117
+ - Storage keys reject absolute paths and traversal segments.
118
+ - BCP's local metadata directory cannot be addressed as an application storage key.
119
+ - Existing objects are not overwritten unless requested explicitly.
120
+ - Download filenames are stripped of path/control characters before being placed in response headers.
121
+ - Storage keys do not provide authorization; route/API guards must still enforce ownership and access permissions.
122
+ - Content type remains metadata, not content-signature verification.
123
+
124
+ ## Compatibility
125
+
126
+ `saveUploadedFile()` from 0.1.24 remains supported. Applications can migrate incrementally to `StorageAdapter` / `storeUploadedFile()` when they need backend-independent storage behavior.
127
+
128
+ The route-graph synchronization and standalone auth-guard fixes completed during the 0.1.24 stabilization cycle remain part of the 0.1.25 baseline.
129
+
130
+ ## Next milestone
131
+
132
+ The next planned milestone is BCP 0.1.26 — storage adapter ecosystem / S3-compatible integration and production upload streaming, unless roadmap priorities are regrouped.