create-bcp-app 0.2.17 → 0.2.19

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.
Files changed (3) hide show
  1. package/README.md +101 -187
  2. package/package.json +1 -1
  3. package/template/README.md +84 -288
package/README.md CHANGED
@@ -10,9 +10,7 @@ npm run dev
10
10
 
11
11
  ## Project-local BCP CLI
12
12
 
13
- `create-bcp-app` installs BCP Framework as a project-local dependency. It does not install the framework CLI globally.
14
-
15
- Generated npm scripts use `bcp` because npm places `node_modules/.bin` on the script `PATH`:
13
+ `create-bcp-app` installs BCP Framework as a project-local dependency. Generated npm scripts use the local CLI:
16
14
 
17
15
  ```json
18
16
  {
@@ -28,7 +26,7 @@ Generated npm scripts use `bcp` because npm places `node_modules/.bin` on the sc
28
26
  }
29
27
  ```
30
28
 
31
- For direct PowerShell usage, prefer the collision-free local alias:
29
+ For direct PowerShell usage, prefer the collision-free alias:
32
30
 
33
31
  ```powershell
34
32
  npm exec -- bcp-framework --version
@@ -66,17 +64,17 @@ Select storage provider:
66
64
 
67
65
  New projects include `bcp.project.json`.
68
66
 
69
- Example for the `0.2.17` target:
67
+ Example for the `0.2.19` target:
70
68
 
71
69
  ```json
72
70
  {
73
71
  "schemaVersion": 1,
74
72
  "framework": "bcp",
75
73
  "projectName": "my-app",
76
- "frameworkPackage": "npm:@chidchanun/bcp@0.2.17",
74
+ "frameworkPackage": "npm:@chidchanun/bcp@0.2.19",
77
75
  "createdWith": {
78
76
  "package": "create-bcp-app",
79
- "version": "0.2.17"
77
+ "version": "0.2.19"
80
78
  },
81
79
  "packageManager": "npm",
82
80
  "presets": {
@@ -88,7 +86,7 @@ Example for the `0.2.17` target:
88
86
  }
89
87
  ```
90
88
 
91
- This manifest records scaffold identity only. It must not contain secrets and should normally be committed to source control.
89
+ This manifest records scaffold identity only. Do not place secrets in it.
92
90
 
93
91
  ## Database presets
94
92
 
@@ -104,71 +102,23 @@ For MySQL, PostgreSQL and SQLite, generated `lib/database.ts` exposes BCP databa
104
102
 
105
103
  ## Authentication and security
106
104
 
107
- The JWT Cookie preset creates `lib/auth.ts` and starter auth routes. BCP `0.2.5+` supports optional revocable server-side auth state, while `0.2.6+` adds permission/policy authorization plus same-origin/CSRF helpers.
105
+ The JWT Cookie preset creates starter authentication code. BCP supports revocable session stores, permission/policy authorization, route guards and same-origin/CSRF helpers.
108
106
 
109
- ## Background jobs and scheduling
107
+ ## Background jobs, workflows and events
110
108
 
111
109
  ```ts
112
110
  import {
113
111
  createJobQueue,
114
112
  createJobScheduler,
115
113
  } from "bcp/jobs";
116
-
117
- export const jobs =
118
- createJobQueue();
119
-
120
- export const scheduler =
121
- createJobScheduler({
122
- queue: jobs,
123
- });
124
- ```
125
-
126
- `0.2.10+` adds visibility leases, heartbeat renewal, stale-running recovery, DLQ/requeue, retention cleanup and Redis-compatible durable adapters.
127
-
128
- ## Workflow orchestration — 0.2.11+
129
-
130
- ```ts
131
114
  import {
132
115
  createWorkflow,
133
116
  } from "bcp/workflow";
134
-
135
- export const onboarding =
136
- createWorkflow(
137
- "user.onboarding",
138
- workflow => {
139
- workflow.step(
140
- "profile",
141
- createProfile
142
- );
143
- workflow.delay(
144
- "cooldown",
145
- 1_000
146
- );
147
- }
148
- );
149
117
  ```
150
118
 
151
- ## Transactional Outbox & Events 0.2.12+
152
-
153
- ```ts
154
- await db.transaction(
155
- async tx => {
156
- await tx.execute(
157
- "INSERT INTO orders ..."
158
- );
159
-
160
- await outbox.publish(
161
- tx,
162
- "order.created",
163
- {
164
- orderId: 42,
165
- }
166
- );
167
- }
168
- );
169
- ```
119
+ Durable Redis-compatible queues/schedules, workflow orchestration and transactional outbox/event delivery are available without forcing a Redis client dependency.
170
120
 
171
- ## Realtime Platform — 0.2.13+
121
+ ## Realtime
172
122
 
173
123
  ```ts
174
124
  import {
@@ -179,187 +129,151 @@ export const realtime =
179
129
  createRealtime();
180
130
  ```
181
131
 
182
- BCP does not install a WebSocket library. Adapt your selected provider to `RealtimeSocket`. SSE is available directly through `realtime.sse()`.
132
+ BCP does not install a WebSocket server library. Applications adapt their provider to `RealtimeSocket`; SSE is built in.
183
133
 
184
- ## Testing Platform — 0.2.14+
134
+ ## Testing
185
135
 
186
- ```ts
187
- import {
188
- createRouteTestHandler,
189
- createTestApp,
190
- expectResponse,
191
- } from "bcp/testing";
192
-
193
- const app =
194
- createTestApp({
195
- handler:
196
- createRouteTestHandler({
197
- GET() {
198
- return {
199
- ok: true,
200
- };
201
- },
202
- }),
203
- });
136
+ `bcp/testing` provides request/route/page/auth/database/middleware/jobs/workflow/outbox/realtime test harnesses and does not require Jest or Vitest.
204
137
 
205
- await expectResponse(
206
- await app.get("/api/health")
207
- )
208
- .status(200)
209
- .json({
210
- ok: true,
211
- });
212
- ```
138
+ ## Plugins
213
139
 
214
- BCP testing helpers are runner-neutral and can be used with Node `node:test`, Vitest, Jest or another runner.
140
+ `bcp/plugins` provides dependency ordering, module composition, lifecycle hooks, config parsing, shared services and async hooks.
215
141
 
216
- ## Plugin & Module Platform — 0.2.15+
217
-
218
- ```ts
219
- import {
220
- createPluginHost,
221
- definePlugin,
222
- } from "bcp/plugins";
223
-
224
- const databasePlugin =
225
- definePlugin({
226
- name: "database",
227
- setup(context) {
228
- context.services.provide(
229
- "database",
230
- db
231
- );
232
- },
233
- });
234
-
235
- const jobsPlugin =
236
- definePlugin({
237
- name: "jobs",
238
- requires: [
239
- "database",
240
- ],
241
- });
242
-
243
- export const plugins =
244
- createPluginHost({
245
- plugins: [
246
- jobsPlugin,
247
- databasePlugin,
248
- ],
249
- });
250
- ```
251
-
252
- ## Cache Platform v2 — 0.2.16+
142
+ ## Cache Platform v2
253
143
 
254
144
  ```ts
255
145
  import {
256
146
  createCacheStore,
257
- createRedisCacheAdapter,
258
- createRedisCacheLockAdapter,
259
147
  } from "bcp/cache";
260
148
 
261
149
  export const cache =
262
- createCacheStore({
263
- adapter:
264
- createRedisCacheAdapter({
265
- client: redisClient,
266
- }),
267
- lock:
268
- createRedisCacheLockAdapter({
269
- client: redisClient,
270
- }),
271
- });
150
+ createCacheStore();
272
151
  ```
273
152
 
274
- BCP does not install or own the Redis client. Applications remain responsible for credentials, TLS, Cluster/Sentinel configuration, reconnect behavior and connection shutdown.
275
-
276
- ## Observability Platform v3 — 0.2.17+
153
+ Multi-instance applications can use Redis-compatible cache and lock adapters for distributed cache-fill coordination.
277
154
 
278
- Metrics and health remain available through the same entrypoint:
155
+ ## Observability Platform v3
279
156
 
280
157
  ```ts
281
158
  import {
282
- createHealthRegistry,
283
- createMetricsRegistry,
284
159
  createTracer,
285
160
  } from "bcp/observability";
286
- ```
287
-
288
- Create a tracer:
289
161
 
290
- ```ts
291
162
  export const tracer =
292
163
  createTracer({
293
164
  serviceName: "my-app",
294
165
  });
295
166
  ```
296
167
 
297
- Trace incoming HTTP requests with Middleware System v2:
168
+ Tracing supports W3C `traceparent`, correlation IDs, request middleware, explicit carriers for jobs/workflows/events/realtime and provider-neutral exporters.
169
+
170
+ ## Deployment Platform v2 — 0.2.18+
171
+
172
+ Use `bcp/deployment` to coordinate application resources in production:
298
173
 
299
174
  ```ts
300
175
  import {
301
- createRequestTracingMiddleware,
302
- } from "bcp/observability";
176
+ createDeploymentRuntime,
177
+ } from "bcp/deployment";
303
178
 
304
- export const middleware =
305
- createRequestTracingMiddleware(
306
- tracer
307
- );
179
+ export const deployment =
180
+ createDeploymentRuntime({
181
+ serviceName: "my-app",
182
+ });
308
183
  ```
309
184
 
310
- The middleware understands W3C `traceparent`, preserves `x-correlation-id`, creates a server span and returns the current trace headers on the response.
185
+ Register shared dependencies before components that use them:
186
+
187
+ ```ts
188
+ deployment.addResource({
189
+ name: "database",
190
+
191
+ async start() {
192
+ await db.connect();
193
+ },
194
+
195
+ ready() {
196
+ return db.status === "ready";
197
+ },
198
+
199
+ async stop() {
200
+ await db.close();
201
+ },
202
+ });
203
+
204
+ deployment.addResource({
205
+ name: "workers",
206
+
207
+ start() {
208
+ worker = jobs.startWorker();
209
+ },
311
210
 
312
- For jobs/workflows/events/realtime payloads use explicit trace carriers:
211
+ async stop() {
212
+ await worker.stop();
213
+ },
214
+ });
215
+
216
+ await deployment.start();
217
+ ```
218
+
219
+ Startup follows registration order and shutdown reverses it. This naturally stops workers before database/cache/Redis connections.
220
+
221
+ Readiness endpoint:
313
222
 
314
223
  ```ts
315
224
  import {
316
- createTraceCarrier,
317
- runWithTraceCarrier,
318
- } from "bcp/observability";
225
+ createDeploymentReadinessResponse,
226
+ } from "bcp/deployment";
319
227
 
320
- const trace =
321
- createTraceCarrier();
228
+ export function GET() {
229
+ return createDeploymentReadinessResponse(
230
+ deployment
231
+ );
232
+ }
233
+ ```
322
234
 
323
- await jobs.enqueue(
324
- "order.process",
325
- {
326
- orderId,
327
- trace,
328
- }
329
- );
235
+ Runtime identity can use:
236
+
237
+ ```text
238
+ BCP_DEPLOYMENT_ID
239
+ BCP_INSTANCE_ID
240
+ BCP_RELEASE
241
+ NODE_ENV
242
+ BCP_SHUTDOWN_TIMEOUT_MS
330
243
  ```
331
244
 
332
- Consumer:
245
+ Install graceful signal handling with:
333
246
 
334
247
  ```ts
335
- await runWithTraceCarrier(
336
- payload.trace,
337
- () =>
338
- tracer.withSpan(
339
- "job order.process",
340
- handler,
341
- {
342
- kind: "consumer",
343
- }
344
- )
345
- );
248
+ const removeSignals =
249
+ deployment.installSignalHandlers();
346
250
  ```
347
251
 
348
- Use `getTraceLogFields()` to add `traceId`, `spanId` and `correlationId` to structured logs.
252
+ Default signals are `SIGTERM` and `SIGINT`.
349
253
 
350
- BCP does not install OpenTelemetry or a vendor APM package. Implement `TraceSpanExporter` when production spans need to be sent to an external collector.
254
+ ## Stability & API Freeze 0.2.19
351
255
 
352
- ## Storage providers
256
+ `0.2.19` keeps the `0.2.x` public package surface stable before the next platform baseline.
353
257
 
354
- Supported presets are Local Server, Amazon S3 and Cloudflare R2. Storage credentials are server-only and must not use `BCP_PUBLIC_*` variables.
258
+ Framework maintainers can validate the frozen contract with:
259
+
260
+ ```bash
261
+ npm run api:check
262
+ npm run release:readiness
263
+ ```
264
+
265
+ Generated applications do not need to run these framework-repository release commands. Application code should continue importing documented `bcp/*` entrypoints rather than private framework source paths.
355
266
 
356
267
  ## Application packaging
357
268
 
358
269
  ```bash
270
+ npm run build
359
271
  npm run package
360
272
  ```
361
273
 
362
- The deployment package excludes application `devDependencies` and project `.env` values. Supply real secrets through the deployment environment.
274
+ The deployment package excludes application `devDependencies` and project `.env` values. Supply secrets through the deployment environment.
275
+
276
+ BCP `0.2.19` prepared framework packages preserve the compiled ESM runtime map introduced by Deployment Platform v2 for the main server entrypoints including config, auth, observability, deployment, server and middleware.
363
277
 
364
278
  ## Project generators
365
279
 
@@ -387,5 +301,5 @@ npm run generate -- migration create_users
387
301
  For prerelease/local package verification:
388
302
 
389
303
  ```bash
390
- npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.17.tgz
304
+ npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.19.tgz
391
305
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bcp-app",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "Create a new BCP Framework application.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,113 +27,33 @@ npm run update
27
27
 
28
28
  Generated projects include `bcp.project.json` with non-secret scaffold metadata. Commit it with the project, but never put passwords, tokens or access keys in it.
29
29
 
30
- ## Authentication BCP 0.2.5+
30
+ ## Authentication and authorization
31
31
 
32
- JWT Cookie projects can opt into revocable server-side session state with `createAuth()` and `AuthSessionStore`.
32
+ JWT Cookie projects can use `createAuth()` and optional `AuthSessionStore` revocation. Permission guards/resource policies live in `bcp/auth`; same-origin/CSRF helpers live in `bcp/server`.
33
33
 
34
- ## Authorization & request security — BCP 0.2.6+
34
+ ## Database
35
35
 
36
- Use permission guards/resource policies from `bcp/auth`, and same-origin/CSRF protection from `bcp/server`. Authorization must remain server-side.
36
+ MySQL, PostgreSQL and SQLite projects expose the BCP database platform through `bcp/database`.
37
37
 
38
- ## Observability BCP 0.2.7+
39
-
40
- ```ts
41
- import {
42
- createHealthRegistry,
43
- createMetricsRegistry,
44
- } from "bcp/observability";
45
- ```
46
-
47
- ## Background jobs — BCP 0.2.8+
38
+ ## Jobs, scheduling and workflows
48
39
 
49
40
  ```ts
50
41
  import {
51
42
  createJobQueue,
52
- } from "bcp/jobs";
53
-
54
- export const jobs =
55
- createJobQueue();
56
- ```
57
-
58
- ## Job scheduling — BCP 0.2.9+
59
-
60
- ```ts
61
- import {
62
43
  createJobScheduler,
63
44
  } from "bcp/jobs";
64
-
65
- export const scheduler =
66
- createJobScheduler({
67
- queue: jobs,
68
- });
69
- ```
70
-
71
- ## Durable jobs — BCP 0.2.10+
72
-
73
- Workers can use visibility leases, heartbeat renewal, stale recovery and DLQ/requeue. Redis-compatible adapters are available without forcing a Redis client dependency.
74
-
75
- ```ts
76
- const worker =
77
- jobs.startWorker({
78
- workerId: "worker-a",
79
- concurrency: 4,
80
- visibilityTimeoutMs: 30_000,
81
- heartbeatIntervalMs: 10_000,
82
- });
83
- ```
84
-
85
- ## Workflow orchestration — BCP 0.2.11+
86
-
87
- ```ts
88
45
  import {
89
46
  createWorkflow,
90
47
  } from "bcp/workflow";
91
-
92
- export const onboarding =
93
- createWorkflow(
94
- "user.onboarding",
95
- workflow => {
96
- workflow.step(
97
- "profile",
98
- createProfile
99
- );
100
- workflow.delay(
101
- "cooldown",
102
- 1_000
103
- );
104
- }
105
- );
106
48
  ```
107
49
 
108
- Workflows support sequential/parallel steps, retries, persisted delays, compensation, run leases and optional durable queue execution.
50
+ Durable jobs support leases, heartbeat, stale recovery and DLQ. Workflows support sequential/parallel steps, retries, persisted delays and compensation.
109
51
 
110
- ## Transactional Outbox & Events — BCP 0.2.12+
52
+ ## Transactional events
111
53
 
112
- Use `bcp/events` when application data and an integration event must commit atomically in the same SQL transaction.
54
+ Use `bcp/events` when business data and an integration event must commit in the same SQL transaction. The outbox dispatcher can deliver through durable jobs or an application publisher after commit.
113
55
 
114
- ```ts
115
- await db.transaction(
116
- async tx => {
117
- await tx.execute(
118
- "INSERT INTO orders ..."
119
- );
120
-
121
- await outbox.publish(
122
- tx,
123
- "order.created",
124
- {
125
- orderId: 42,
126
- }
127
- );
128
- }
129
- );
130
- ```
131
-
132
- After commit, `createOutboxDispatcher()` can deliver through durable jobs or a custom publisher.
133
-
134
- ## Realtime Platform — BCP 0.2.13+
135
-
136
- Create a server-side realtime hub:
56
+ ## Realtime
137
57
 
138
58
  ```ts
139
59
  import {
@@ -144,252 +64,143 @@ export const realtime =
144
64
  createRealtime();
145
65
  ```
146
66
 
147
- Channels/rooms:
67
+ BCP does not install a WebSocket server library. Adapt the selected provider through `RealtimeSocket`; SSE is built in.
148
68
 
149
- ```ts
150
- const connection =
151
- await realtime.connect();
152
-
153
- await connection.join(
154
- "orders:42"
155
- );
156
-
157
- await realtime.broadcast(
158
- "orders:42",
159
- "order.updated",
160
- {
161
- status: "paid",
162
- }
163
- );
164
- ```
69
+ ## Testing
165
70
 
166
- BCP does not install a WebSocket server dependency. Adapt the selected provider to `RealtimeSocket`. SSE is built in through `realtime.sse()`.
71
+ `bcp/testing` provides request/route/page/auth/database/middleware/jobs/workflow/outbox/realtime/SSE test helpers without requiring Jest or Vitest.
167
72
 
168
- For multi-instance deployment, replace the memory broker/presence store with shared `RealtimeBroker` and `RealtimePresenceStore` implementations.
73
+ ## Plugins
169
74
 
170
- ## Testing Platform BCP 0.2.14+
75
+ `bcp/plugins` provides reusable server-side plugins/modules, dependency ordering, lifecycle hooks, config parsing, shared services and awaited hooks.
171
76
 
172
- Use server-only `bcp/testing` to exercise framework contracts without adding a BCP-specific test runner.
77
+ ## Cache Platform v2
173
78
 
174
79
  ```ts
175
80
  import {
176
- createRouteTestHandler,
177
- createTestApp,
178
- expectResponse,
179
- } from "bcp/testing";
180
-
181
- const app =
182
- createTestApp({
183
- handler:
184
- createRouteTestHandler({
185
- GET() {
186
- return {
187
- ok: true,
188
- };
189
- },
190
- }),
191
- });
81
+ createCacheStore,
82
+ } from "bcp/cache";
192
83
 
193
- await expectResponse(
194
- await app.get("/api/health")
195
- )
196
- .status(200)
197
- .json({
198
- ok: true,
199
- });
84
+ export const cache =
85
+ createCacheStore();
200
86
  ```
201
87
 
202
- BCP does not require Jest or Vitest; these helpers work with Node `node:test` or another runner.
88
+ Use Redis-compatible cache/lock adapters for multi-instance cache-fill coordination when needed.
203
89
 
204
- ## Plugin & Module Platform — BCP 0.2.15+
205
-
206
- Use `bcp/plugins` to compose reusable server-only application services with explicit dependencies.
90
+ ## Observability Platform v3
207
91
 
208
92
  ```ts
209
93
  import {
210
- createPluginHost,
211
- definePlugin,
212
- } from "bcp/plugins";
213
-
214
- const databasePlugin =
215
- definePlugin({
216
- name: "database",
217
- setup(context) {
218
- context.services.provide(
219
- "database",
220
- db
221
- );
222
- },
223
- });
224
-
225
- const jobsPlugin =
226
- definePlugin({
227
- name: "jobs",
228
- requires: [
229
- "database",
230
- ],
231
- });
94
+ createTracer,
95
+ } from "bcp/observability";
232
96
 
233
- export const plugins =
234
- createPluginHost({
235
- plugins: [
236
- jobsPlugin,
237
- databasePlugin,
238
- ],
97
+ export const tracer =
98
+ createTracer({
99
+ serviceName: "bcp-app",
239
100
  });
240
101
  ```
241
102
 
242
- Plugin startup follows dependency order and shutdown reverses it. Plugins can use `setup/start/stop/dispose`, config parsers, shared services and async hooks.
103
+ Tracing supports AsyncLocalStorage context, W3C `traceparent`, correlation IDs, request tracing, trace carriers and provider-neutral exporters.
243
104
 
244
- ## Cache Platform v2 — BCP 0.2.16+
105
+ ## Deployment Platform v2 — BCP 0.2.18+
245
106
 
246
- Use `createCacheStore()` for async cache-aside loading, shared adapters and distributed cache-fill coordination.
107
+ Use `bcp/deployment` to manage production resource lifecycle:
247
108
 
248
109
  ```ts
249
110
  import {
250
- createCacheStore,
251
- } from "bcp/cache";
252
-
253
- export const cache =
254
- createCacheStore();
255
- ```
111
+ createDeploymentRuntime,
112
+ } from "bcp/deployment";
256
113
 
257
- ```ts
258
- const user =
259
- await cache.getOrSet(
260
- "user:42",
261
- () => loadUser(42),
262
- {
263
- ttlMs: 60_000,
264
- tags: ["users"],
265
- paths: ["/users/42"],
266
- }
267
- );
114
+ export const deployment =
115
+ createDeploymentRuntime({
116
+ serviceName: "bcp-app",
117
+ });
268
118
  ```
269
119
 
270
- For multiple instances, connect a shared cache and lock provider:
120
+ Register dependencies first:
271
121
 
272
122
  ```ts
273
- import {
274
- createRedisCacheAdapter,
275
- createRedisCacheLockAdapter,
276
- } from "bcp/cache";
123
+ deployment.addResource({
124
+ name: "database",
277
125
 
278
- const redisCache =
279
- createRedisCacheAdapter({
280
- client: redisClient,
281
- });
126
+ async start() {
127
+ await db.connect();
128
+ },
282
129
 
283
- const redisLock =
284
- createRedisCacheLockAdapter({
285
- client: redisClient,
286
- });
130
+ ready() {
131
+ return db.status === "ready";
132
+ },
287
133
 
288
- export const cache =
289
- createCacheStore({
290
- adapter: redisCache,
291
- lock: redisLock,
292
- });
134
+ async stop() {
135
+ await db.close();
136
+ },
137
+ });
293
138
  ```
294
139
 
295
- BCP does not install or own a Redis client. The default adapter namespace is `bcp:{cache}`. The original `cache()` and `dedupe()` APIs remain available for backward-compatible process-local caching.
296
-
297
- ## Observability Platform v3 — BCP 0.2.17+
140
+ Register workers/realtime services afterward so reverse-order shutdown stops them before their shared database/cache/Redis dependencies.
298
141
 
299
- Use the existing `bcp/observability` entrypoint for tracing as well as metrics and health.
142
+ Start runtime:
300
143
 
301
144
  ```ts
302
- import {
303
- createTracer,
304
- } from "bcp/observability";
305
-
306
- export const tracer =
307
- createTracer({
308
- serviceName: "my-app",
309
- });
145
+ await deployment.start();
310
146
  ```
311
147
 
312
- Trace incoming Middleware System v2 requests:
148
+ Readiness endpoint:
313
149
 
314
150
  ```ts
315
151
  import {
316
- createRequestTracingMiddleware,
317
- } from "bcp/observability";
152
+ createDeploymentReadinessResponse,
153
+ } from "bcp/deployment";
318
154
 
319
- export const middleware =
320
- createRequestTracingMiddleware(
321
- tracer
155
+ export function GET() {
156
+ return createDeploymentReadinessResponse(
157
+ deployment
322
158
  );
159
+ }
323
160
  ```
324
161
 
325
- The middleware continues valid W3C `traceparent` headers, preserves `x-correlation-id`, creates a server span and includes active trace headers in the response.
326
-
327
- Create child spans for application work:
162
+ Install graceful signal handling when the app owns process signals:
328
163
 
329
164
  ```ts
330
- await tracer.withSpan(
331
- "order.checkout",
332
- async () => {
333
- await tracer.withSpan(
334
- "database.order.insert",
335
- createOrder,
336
- {
337
- kind: "client",
338
- }
339
- );
340
- }
341
- );
165
+ const removeSignals =
166
+ deployment.installSignalHandlers();
342
167
  ```
343
168
 
344
- For jobs, workflows, events and realtime payloads, propagate context explicitly:
169
+ Default signals are `SIGTERM` and `SIGINT`.
345
170
 
346
- ```ts
347
- import {
348
- createTraceCarrier,
349
- runWithTraceCarrier,
350
- } from "bcp/observability";
351
-
352
- const trace =
353
- createTraceCarrier();
171
+ Deployment identity can be supplied through:
354
172
 
355
- await jobs.enqueue(
356
- "order.process",
357
- {
358
- orderId,
359
- trace,
360
- }
361
- );
173
+ ```text
174
+ BCP_DEPLOYMENT_ID
175
+ BCP_INSTANCE_ID
176
+ BCP_RELEASE
177
+ NODE_ENV
178
+ BCP_SHUTDOWN_TIMEOUT_MS
362
179
  ```
363
180
 
364
- Consumer:
181
+ ## Stability baseline — BCP 0.2.19
365
182
 
366
- ```ts
367
- await runWithTraceCarrier(
368
- payload.trace,
369
- () =>
370
- tracer.withSpan(
371
- "job order.process",
372
- handler,
373
- {
374
- kind: "consumer",
375
- }
376
- )
377
- );
378
- ```
183
+ BCP `0.2.19` freezes the documented `0.2.x` public `bcp/*` entrypoints and prepared package-resolution contract before the next `0.3.0` baseline.
379
184
 
380
- Use `getTraceLogFields()` to attach `traceId`, `spanId` and `correlationId` to structured logs.
185
+ Application code should import documented public entrypoints and avoid private framework `packages/*` paths. This keeps applications compatible with the frozen `0.2.19` surface.
381
186
 
382
- BCP does not install OpenTelemetry or a vendor APM SDK. Production collector integration is application-owned through `TraceSpanExporter`.
187
+ ## Production build
383
188
 
384
- ## Generate framework files
189
+ ```bash
190
+ npm run build
191
+ npm start
192
+ ```
193
+
194
+ ## Deployment package
385
195
 
386
196
  ```bash
387
- npm run generate -- page dashboard/users
388
- npm run generate -- api users
389
- npm run generate -- middleware
390
- npm run generate -- migration create_users
197
+ npm run package
391
198
  ```
392
199
 
200
+ BCP excludes project `.env` files and application `devDependencies` from the deployment package. Supply secrets through the deployment environment.
201
+
202
+ BCP 0.2.19 preserves compiled `.mjs` runtimes for the main server entrypoints, including config, auth, observability, deployment, server and middleware.
203
+
393
204
  ## Direct CLI usage
394
205
 
395
206
  For PowerShell:
@@ -403,18 +214,3 @@ npm exec -- bcp-framework dev
403
214
  npm exec -- bcp-framework build
404
215
  npm exec -- bcp-framework package
405
216
  ```
406
-
407
- ## Production build
408
-
409
- ```bash
410
- npm run build
411
- npm start
412
- ```
413
-
414
- ## Deployment package
415
-
416
- ```bash
417
- npm run package
418
- ```
419
-
420
- BCP excludes project `.env` files and application `devDependencies` from the deployment package. Supply secrets through the deployment environment.