rcf-lite 0.17.0 → 0.19.0
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/CHANGELOG.md +60 -0
- package/blueprints/application-api-rest/README.md +5 -1
- package/blueprints/application-api-rest/blueprint.json +12 -4
- package/blueprints/application-api-rest/contributions/adrs/adr-304-application-api-rest-logging.json +3 -3
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-006.json +4 -4
- package/blueprints/application-api-rest/contributions/tacs/tac-306-application-api-rest-operability.json +9 -8
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2103.json +3 -3
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2108.json +27 -27
- package/blueprints/application-api-rest/docs/topics.md +6 -4
- package/blueprints/application-api-rest/guide/application-api-rest.md +5 -1
- package/blueprints/application-error-handling/README.md +42 -0
- package/blueprints/application-error-handling/assets/schemas/error-record.schema.json +17 -0
- package/blueprints/application-error-handling/blueprint.json +27 -0
- package/blueprints/application-error-handling/contributions/adrs/adr-1701-application-error-handling-record-shape.json +25 -0
- package/blueprints/application-error-handling/contributions/adrs/adr-1702-application-error-handling-classification-vocabulary.json +20 -0
- package/blueprints/application-error-handling/contributions/adrs/adr-1703-application-error-handling-transport-mapping.json +20 -0
- package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-001.json +15 -0
- package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-002.json +15 -0
- package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-003.json +15 -0
- package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-004.json +15 -0
- package/blueprints/application-error-handling/contributions/tacs/tac-1701-application-error-handling-boundary.json +45 -0
- package/blueprints/application-error-handling/contributions/tacs/tac-1702-application-error-handling-record-factory.json +40 -0
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16101.json +25 -0
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16102.json +25 -0
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16103.json +34 -0
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16104.json +25 -0
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16105.json +25 -0
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16106.json +25 -0
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16107.json +25 -0
- package/blueprints/application-error-handling/docs/topics.md +24 -0
- package/blueprints/application-error-handling/guide/application-error-handling.md +35 -0
- package/blueprints/application-spa/blueprint.json +12 -2
- package/blueprints/application-spa/docs/topics.md +4 -2
- package/blueprints/delivery-ci-workflows/docs/topics.md +2 -2
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
- package/blueprints/email-smtp-resend/docs/topics.md +2 -2
- package/blueprints/observability-essentials/README.md +6 -2
- package/blueprints/observability-essentials/blueprint.json +133 -33
- package/blueprints/observability-essentials/contributions/adrs/adr-801-observability-essentials-health-probes.json +4 -4
- package/blueprints/observability-essentials/contributions/adrs/adr-802-observability-essentials-readiness-semantics.json +4 -4
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-001.json +4 -4
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-002.json +4 -4
- package/blueprints/observability-essentials/contributions/tacs/tac-801-observability-essentials-liveness-probe.json +10 -9
- package/blueprints/observability-essentials/contributions/tacs/tac-802-observability-essentials-readiness-probe.json +17 -11
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7101.json +12 -3
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7102.json +12 -3
- package/blueprints/observability-essentials/docs/topics.md +15 -8
- package/blueprints/observability-essentials/guide/observability-essentials.md +9 -3
- package/blueprints/observability-logging/README.md +44 -0
- package/blueprints/observability-logging/assets/samples/log-line.json +13 -0
- package/blueprints/observability-logging/blueprint.json +27 -0
- package/blueprints/observability-logging/contributions/adrs/adr-1601-observability-logging-line-shape.json +25 -0
- package/blueprints/observability-logging/contributions/adrs/adr-1602-observability-logging-correlation-id-header.json +25 -0
- package/blueprints/observability-logging/contributions/adrs/adr-1603-observability-logging-redaction-categories.json +25 -0
- package/blueprints/observability-logging/contributions/adrs/adr-1604-observability-logging-level-vocabulary.json +20 -0
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-001.json +15 -0
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-002.json +15 -0
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-003.json +15 -0
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-004.json +15 -0
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-005.json +15 -0
- package/blueprints/observability-logging/contributions/tacs/tac-1601-observability-logging-logger-factory.json +46 -0
- package/blueprints/observability-logging/contributions/tacs/tac-1602-observability-logging-redaction-boundary.json +27 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15101.json +34 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15102.json +43 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15103.json +34 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15104.json +25 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15105.json +34 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15106.json +25 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15107.json +25 -0
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15108.json +25 -0
- package/blueprints/observability-logging/docs/topics.md +21 -0
- package/blueprints/observability-logging/guide/observability-logging.md +36 -0
- package/blueprints/observability-probe-endpoints/README.md +5 -1
- package/blueprints/observability-probe-endpoints/blueprint.json +116 -24
- package/blueprints/observability-probe-endpoints/contributions/adrs/adr-1503-observability-probe-endpoints-kubernetes-default.json +5 -5
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14102.json +11 -2
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14107.json +11 -2
- package/blueprints/observability-probe-endpoints/docs/topics.md +6 -6
- package/blueprints/observability-probe-endpoints/guide/observability-probe-endpoints.md +10 -0
- package/blueprints/persistence-data-d1/docs/topics.md +2 -2
- package/blueprints/persistence-data-sqlite/docs/topics.md +2 -2
- package/blueprints/security-auth-clerk/docs/topics.md +2 -2
- package/blueprints/security-auth-keycloak/docs/topics.md +2 -2
- package/blueprints/security-auth-magic-link/docs/topics.md +2 -2
- package/blueprints/security-auth-oauth2/docs/topics.md +2 -2
- package/blueprints/security-secrets-management/docs/topics.md +2 -2
- package/fixtures/canary-manifest.json +6 -6
- package/guidance/harness-template.md +8 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +8 -0
- package/package.json +1 -1
- package/rcf/code-nodes/cn-074.json +19 -0
- package/rcf/code-nodes/cn-075.json +15 -0
- package/rcf/code-nodes/cn-076.json +14 -0
- package/rcf/code-nodes/cn-077.json +14 -0
- package/rcf/code-nodes/cn-078.json +15 -0
- package/rcf/code-nodes/cn-079.json +14 -0
- package/rcf/code-nodes/cn-080.json +15 -0
- package/rcf/code-nodes/cn-081.json +15 -0
- package/rcf/code-nodes/cn-082.json +15 -0
- package/rcf/code-nodes/cn-083.json +14 -0
- package/rcf/code-nodes/cn-084.json +15 -0
- package/rcf/code-nodes/cn-085.json +14 -0
- package/rcf/code-nodes/cn-086.json +16 -0
- package/rcf/code-nodes/cn-087.json +14 -0
- package/rcf/code-nodes/cn-088.json +14 -0
- package/rcf/code-nodes/cn-089.json +14 -0
- package/rcf/code-nodes/cn-090.json +14 -0
- package/rcf/code-nodes/cn-091.json +14 -0
- package/rcf/code-nodes/cn-092.json +15 -0
- package/rcf/code-nodes/cn-093.json +15 -0
- package/rcf/code-nodes/cn-094.json +14 -0
- package/rcf/code-nodes/cn-095.json +14 -0
- package/rcf/code-nodes/cn-096.json +14 -0
- package/rcf/code-nodes/cn-097.json +14 -0
- package/rcf/fbs/fbs-024.json +24 -0
- package/rcf/fbs/fbs-025.json +25 -0
- package/rcf/fbs/fbs-026.json +27 -0
- package/rcf/fbs/fbs-027.json +25 -0
- package/rcf/fbs/fbs-028.json +27 -0
- package/rcf/fbs/fbs-029.json +27 -0
- package/rcf/fbs/fbs-030.json +27 -0
- package/rcf/fbs/fbs-031.json +27 -0
- package/rcf/fbs/fbs-032.json +27 -0
- package/rcf/fbs/fbs-033.json +27 -0
- package/rcf/fbs/fbs-034.json +27 -0
- package/rcf/requirements/req-012.json +22 -0
- package/rcf/requirements/req-013.json +22 -0
- package/rcf/requirements/req-014.json +22 -0
- package/rcf/requirements/req-015.json +21 -0
- package/rcf/test-suites/ts-034.json +32 -0
- package/rcf/test-suites/ts-035.json +23 -0
- package/rcf/test-suites/ts-036.json +65 -0
- package/rcf/test-suites/ts-037.json +55 -0
- package/rcf/test-suites/ts-038.json +41 -0
- package/rcf/test-suites/ts-039.json +41 -0
- package/rcf/test-suites/ts-040.json +57 -0
- package/rcf/test-suites/ts-041.json +57 -0
- package/rcf/test-suites/ts-042.json +57 -0
- package/rcf/test-suites/ts-043.json +49 -0
- package/rcf/test-suites/ts-044.json +41 -0
- package/rcf/user-stories/us-1201.json +34 -0
- package/rcf/user-stories/us-1202.json +25 -0
- package/rcf/user-stories/us-1203.json +43 -0
- package/rcf/user-stories/us-1204.json +25 -0
- package/rcf/user-stories/us-1301.json +43 -0
- package/rcf/user-stories/us-1302.json +43 -0
- package/rcf/user-stories/us-1401.json +43 -0
- package/rcf/user-stories/us-1402.json +43 -0
- package/rcf/user-stories/us-1403.json +43 -0
- package/rcf/user-stories/us-1404.json +43 -0
- package/rcf/user-stories/us-1501.json +43 -0
- package/releases/releases.yaml +21 -1
- package/src/blueprint/apply.js +8 -0
- package/src/blueprint/companions.js +485 -0
- package/src/blueprint/index.js +17 -0
- package/src/blueprint/loader.js +243 -1
- package/src/blueprint/remove-resolution.js +104 -0
- package/src/cli/blueprint.js +350 -0
- package/src/cli/doctor.js +76 -1
- package/src/cli/validate.js +7 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-1703-application-error-handling-transport-mapping",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "The transport blueprint's error-envelope ADR writes the wire shape from the internal record; delegation via TAC-1701 writeErrorResponse",
|
|
8
|
+
"context": "The internal record shape (ADR-1701) is transport-agnostic; the wire envelope is a transport-specific decision. For REST, application-api-rest owns 'errorEnvelope' with an RFC 7807-style body plus code/correlationId fields. For gRPC or message-consumer transports, a future transport blueprint claims its own errorEnvelope-family topic. The boundary must delegate the mapping so this blueprint does not have to know every transport.",
|
|
9
|
+
"decision": "TAC-1701 exposes a substitutable transportWriter interface the framework binds. The transport blueprint's errorEnvelope ADR governs the mapping from the internal record to the wire body/headers; the transport writer reads record.code, record.category, record.correlationId and record.context and produces the wire response the transport ADR specifies. This blueprint contributes no writer of its own; it only names the delegation contract.",
|
|
10
|
+
"consequences": "A REST project applies application-api-rest 2.1.0 or later and gets the RFC 7807-shaped response body from the record. A gRPC project supplies its own writer against the same interface. This blueprint remains a companion to whichever transport the project applies; the classification and cause chain travel cleanly across every transport that respects the interface.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "This blueprint ships a REST-shaped default writer",
|
|
14
|
+
"summary": "Provide a default writer that produces a REST envelope; projects override for other transports.",
|
|
15
|
+
"reasonNotChosen": "The blueprint would then have to declare a REST-specific dependency and claim (or conflict on) the errorEnvelope global topic, which application-api-rest already owns. Delegation via a substitutable interface keeps this blueprint transport-agnostic."
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
19
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-error-handling-REQ-001",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The application registers an uncaught-exception boundary at process AND framework level",
|
|
5
|
+
"description": "The application registers TWO boundaries: (1) a process-level handler on uncaughtException / unhandledRejection (Node runtime) or equivalent (browser runtime) that constructs the internal error record via TAC-1702, emits it through the logging companion, and terminates the process cleanly (exit 1); (2) a framework-level handler on the request pipeline (Express-style middleware, Fastify hook, or transport-layer equivalent) that catches exceptions thrown from handler code, constructs the internal error record, and hands it to the transport's response writer (ADR-1703). No exception escapes either boundary silently.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "The most common source of production outages in unchecked applications is an uncaught exception that terminates the process with no diagnostic, or a framework-level exception that produces a mis-shaped response the caller cannot interpret. The two boundaries close both classes at the earliest possible surface.",
|
|
10
|
+
"tags": ["blueprint:application-error-handling", "category:01-boundary"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-error-handling-REQ-002",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The internal error record has a stable shape: code, category, message, correlationId, cause chain, redacted context",
|
|
5
|
+
"description": "Every constructed error record carries the fields governed by ADR-1701: code (string, project-elicited machine-readable identifier), category (one of the ADR-1702 classification vocabulary), message (human-readable string, no PII), correlationId (from the ambient logging context), cause (nested record for the wrapped cause, may be null), context (redacted object per the logging blueprint's redaction categories). Records are constructed only through TAC-1702's factory; a construction that omits code or category is refused at the factory boundary.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "A stable record shape lets one log-side query find every error by category, one transport-side handler write the wire envelope by category, and one alerting rule filter by code. Without a shared shape, every consumer invents its own view, and the record becomes lossy at each hop.",
|
|
10
|
+
"tags": ["blueprint:application-error-handling", "category:02-record-shape"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-error-handling-REQ-003",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Every error class is classified transient, permanent or unknown; the boundary honours the class in its handling",
|
|
5
|
+
"description": "Every constructed record carries a category from the ADR-1702 vocabulary (recommended defaults: transient, permanent, unknown; elicited additions per project). The transport handler (ADR-1703) reads the category and applies the per-class contract: transient errors may include a Retry-After hint if the origin knows one; permanent errors do not; unknown errors are logged at error level and treated as permanent by the wire response. The classification is a property the constructing code declares at record creation, not a property inferred from the exception message.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Retry policies are the difference between a self-healing system and a burning one. Classifying errors at the source (where the code knows whether the failure was a transient network blip or a permanent authorisation refusal) puts the decision where the information is; classifying downstream on the wire message is the source of most retry-storm outages.",
|
|
10
|
+
"tags": ["blueprint:application-error-handling", "category:03-classification"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-error-handling-REQ-004",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Error emission goes through the logging companion factory, never direct stdout or stderr writes",
|
|
5
|
+
"description": "The uncaught-exception boundary and the framework-level handler both emit the constructed record through the logging companion's factory (the logging role provider the project has applied). Direct process.stderr.write or console.error calls for error emission are refused by the boundary contract. When no logging companion is applied the boundary falls back to a one-line JSON emission on stderr with a documented warning; the applying project's guide names the gap.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "The logging companion owns the redaction boundary, the correlation identifier propagation, the environment/service/version stamping and the level filter. Bypassing it for error emission produces lines that ingestion pipelines cannot parse alongside the rest of the logs and PII the redaction pass would have caught. The fallback stderr path exists so a project that has not applied a logging companion still gets a diagnostic.",
|
|
10
|
+
"tags": ["blueprint:application-error-handling", "category:04-emission-through-logging"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-1701-application-error-handling-boundary",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Error-handling boundary",
|
|
8
|
+
"purpose": "Owns the two boundaries a application error-handling contract requires: the process-level uncaught-exception boundary and the framework-level request-pipeline boundary. Both accept a runtime exception, invoke the record factory (TAC-1702), emit the record through the applied logging companion factory, and hand the record to the transport response writer per ADR-1703. Substitutable interface for hermetic tests.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Register the process-level handler on uncaughtException / unhandledRejection (Node) or equivalent (browser) that constructs the record, emits it and exits the process with code 1 (AC-16101-1).",
|
|
11
|
+
"Register a framework-level handler on the request pipeline that catches thrown exceptions, constructs the record, hands it to the transport writer, and never lets a raw stack trace or truncated connection surface (AC-16102-1).",
|
|
12
|
+
"Read the record's classification per ADR-1702 and honour the per-class contract in the transport response (AC-16105-1).",
|
|
13
|
+
"Route error emission through the applied logging companion factory when one is present; fall back to a documented single-line stderr JSON when no companion is applied (AC-16106-1)."
|
|
14
|
+
],
|
|
15
|
+
"internalStructure": "One module exporting boundaryFor({ loggerFactory, transportWriter }) -> { handle(err, context) }, plus a registerProcess({ loggerFactory }) function the boot code calls once. The handler is a stateless async function; the transport writer is a substitutable interface the framework binds (Express: res.status().json(); Fastify: reply.send(); other transports supply their own writer). The boundary owns the classification-to-wire-envelope mapping delegated to ADR-1703.",
|
|
16
|
+
"interfaces": [
|
|
17
|
+
{
|
|
18
|
+
"name": "boundaryFor",
|
|
19
|
+
"kind": "factory",
|
|
20
|
+
"description": "boundaryFor({ loggerFactory, transportWriter }) -> { handle(err, context) }. The factory constructs the framework-level boundary; the framework calls handle on every caught exception. Tests substitute stub loggerFactory and transportWriter."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "registerProcess",
|
|
24
|
+
"kind": "hook",
|
|
25
|
+
"description": "registerProcess({ loggerFactory }): void. Called once at boot; wires the process-level uncaughtException / unhandledRejection handlers to route through the same record factory."
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "transportWriter",
|
|
29
|
+
"kind": "interface",
|
|
30
|
+
"description": "The framework-supplied writer that turns a record + wire envelope into the on-the-wire response. Substitutable per transport blueprint (REST envelope, gRPC status, message-consumer nack)."
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"dependencies": [
|
|
34
|
+
{
|
|
35
|
+
"name": "Record factory",
|
|
36
|
+
"kind": "tac",
|
|
37
|
+
"tacId": "TAC-1702-application-error-handling-record-factory",
|
|
38
|
+
"description": "The boundary constructs every record through the factory; the factory owns the record shape gate and the context redaction pass."
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"tradeoffs": "The boundary owns the runtime interception surface; a project that wants a different framework's hook (a custom router, an application-code-first middleware chain) supplies its own transportWriter and reuses everything else. The v1 boundary does not attempt to recover from an uncaught exception; termination with exit 1 is the intentional contract (recovery is the supervisor's job). The optional logging-companion fallback exists so a project without a logging companion still sees the record on stderr; the guide names the fallback as documented behaviour and points at the observability-logging companion as the recommended fix.",
|
|
42
|
+
"notes": "Known mechanism-reach gap: the blueprint cannot prove every code path routes through the boundary. A project-side grep gate ('no bare console.error, no bare process.exit outside boundary') closes the class.",
|
|
43
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
44
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
45
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-1702-application-error-handling-record-factory",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Error record factory",
|
|
8
|
+
"purpose": "Owns the construction of every internal error record. Threads the operator-elicited redaction categories (from the applied logging companion) into a shared factory that gates the record shape (code + category required per ADR-1701), redacts the context field at construction (AC-16104-1), preserves the cause chain across nested wrappings (AC-16103-2), and returns an immutable record every downstream consumer can trust.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Refuse to construct a record without code or category (AC-16103-1); throw a controlled error naming the missing field.",
|
|
11
|
+
"Redact the context object at construction using the redaction category set the applied logging companion supplied at boot (AC-16104-1); the caller's original context object is not mutated.",
|
|
12
|
+
"Preserve the cause chain by accepting a nested record as cause and threading it verbatim onto the returned record (AC-16103-2).",
|
|
13
|
+
"Stamp the record with the ambient correlationId at construction time so the record carries the identifier even if the emitter loses the ambient context between construction and emission."
|
|
14
|
+
],
|
|
15
|
+
"internalStructure": "One module exporting createErrorRecordFactory({ redactionBoundary, correlationContext }) -> { createErrorRecord({code, category, message, cause, context}) -> Record }. The factory closes over the redaction boundary (from TAC-1602 of the logging companion, when applied) and the correlation-context reader (from the logging companion or a project fallback). The returned record is Object.freeze'd so downstream consumers cannot mutate it.",
|
|
16
|
+
"interfaces": [
|
|
17
|
+
{
|
|
18
|
+
"name": "createErrorRecordFactory",
|
|
19
|
+
"kind": "factory",
|
|
20
|
+
"description": "createErrorRecordFactory({ redactionBoundary, correlationContext }) -> { createErrorRecord({code, category, message, cause, context}) }. Constructed once at boot alongside the logger factory."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Record",
|
|
24
|
+
"kind": "interface",
|
|
25
|
+
"description": "Frozen object with fields code (string), category (string), message (string), correlationId (string or null), cause (Record | null), context (redacted object)."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"dependencies": [
|
|
29
|
+
{
|
|
30
|
+
"name": "Redaction boundary",
|
|
31
|
+
"kind": "tac",
|
|
32
|
+
"tacId": "TAC-1602-observability-logging-redaction-boundary",
|
|
33
|
+
"description": "The factory calls the redaction boundary on the context object at construction; when the logging companion is not applied, the factory uses a pass-through boundary (documented in the guide as the fallback)."
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"tradeoffs": "The factory owns the shape gate; a project that wants an additional record field (severity, retryHint) authors it as part of context rather than at the top level. Freezing the record has a small runtime cost; it is intentional so downstream mutation cannot silently drift the emitted line from the record the caller reasoned about. The v1 factory does not attempt to normalise message strings; the caller supplies the message verbatim.",
|
|
37
|
+
"notes": "",
|
|
38
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
39
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-error-handling-US-16101",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-error-handling-REQ-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "A process-level uncaught exception constructs the record, emits it, and terminates cleanly with exit 1",
|
|
8
|
+
"asA": "operator running the application under a supervising process",
|
|
9
|
+
"iWant": "an uncaught exception to construct the internal record via TAC-1702, emit it through the logging companion at error level, and terminate with exit 1",
|
|
10
|
+
"soThat": "the crash is diagnosable from one log line and the supervisor knows to restart the process",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-16101-1",
|
|
14
|
+
"description": "An uncaughtException on the Node runtime (or an equivalent unhandled error on another runtime) causes the process-level boundary to construct the internal record with category unknown when no code path set one, emit it as one JSON line at error level with the stack trace on cause, and exit the process with code 1.",
|
|
15
|
+
"given": "a running application with the process-level boundary registered",
|
|
16
|
+
"when": "an uncaught exception is thrown from any code path",
|
|
17
|
+
"then": "one log line is emitted at error level with the record shape (code, category unknown, message, correlationId, cause, context), and process.exitCode equals 1",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": ["TAC-1701-application-error-handling-boundary"],
|
|
23
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-error-handling-US-16102",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-error-handling-REQ-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "A framework-level exception thrown from handler code is caught, mapped to the wire, and never leaks a raw stack trace",
|
|
8
|
+
"asA": "consumer of an application endpoint",
|
|
9
|
+
"iWant": "a framework-level exception to produce a mapped wire response, not a raw stack trace or a truncated connection",
|
|
10
|
+
"soThat": "callers can act on the error without inspecting server logs and no internal detail leaks",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-16102-1",
|
|
14
|
+
"description": "A handler that throws produces a wire response written by ADR-1703's transport mapping; the response body carries the fields the transport blueprint's errorEnvelope ADR requires (no raw stack, no PII, code present, message present); the server does not truncate the connection.",
|
|
15
|
+
"given": "an application handler that throws",
|
|
16
|
+
"when": "a request hits the handler",
|
|
17
|
+
"then": "the response arrives cleanly with the mapped wire body, and no raw stack trace or internal path appears in the body",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": ["TAC-1701-application-error-handling-boundary"],
|
|
23
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-error-handling-US-16103",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-error-handling-REQ-002",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "The record factory refuses to construct a record without code and category, and preserves the cause chain across nested wrappings",
|
|
8
|
+
"asA": "developer wrapping a low-level exception into a higher-level record",
|
|
9
|
+
"iWant": "TAC-1702's factory to refuse a construction without code or category and to preserve the wrapped cause chain across every level",
|
|
10
|
+
"soThat": "every record has the minimum debug information and the chain of causes is intact when the record is emitted",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-16103-1",
|
|
14
|
+
"description": "createErrorRecord({code, category, message, cause, context}) refuses (throws a controlled error) when code is missing or blank OR category is missing or blank; the thrown error names the missing field.",
|
|
15
|
+
"given": "a caller invoking the factory without code or without category",
|
|
16
|
+
"when": "the factory is called",
|
|
17
|
+
"then": "the factory throws with a message naming the missing field",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-16103-2",
|
|
23
|
+
"description": "A record whose cause is itself a record has both records' code, category and message reachable through record.cause.cause chain traversal.",
|
|
24
|
+
"given": "a record wrapping a record wrapping a low-level exception",
|
|
25
|
+
"when": "the outermost record is emitted",
|
|
26
|
+
"then": "the emitted JSON carries the full cause chain in the same shape as the top-level record fields, nested under cause",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "runtime"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-1702-application-error-handling-record-factory"],
|
|
32
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
33
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
34
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-error-handling-US-16104",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-error-handling-REQ-002",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "The record's context field is redacted at record construction, not at emission",
|
|
8
|
+
"asA": "operator concerned about PII in error records",
|
|
9
|
+
"iWant": "the context field on the record to be redacted at construction time by the logging companion's redaction categories",
|
|
10
|
+
"soThat": "the record itself never carries un-redacted PII even if the emitter fails to redact",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-16104-1",
|
|
14
|
+
"description": "createErrorRecord({..., context: {email: 'x@y', ip: '1.2.3.4'}}) with pii.email in the redaction category set returns a record whose context.email equals [REDACTED:pii.email]; the caller's original context object is not mutated.",
|
|
15
|
+
"given": "a call to the factory with a context object carrying a pii.email field",
|
|
16
|
+
"when": "the factory returns",
|
|
17
|
+
"then": "the returned record's context.email equals [REDACTED:pii.email] and the caller's context object still holds the original value",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": ["TAC-1702-application-error-handling-record-factory"],
|
|
23
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-error-handling-US-16105",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-error-handling-REQ-003",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "The record's classification drives the transport response's retry hint",
|
|
8
|
+
"asA": "caller of an application endpoint that failed",
|
|
9
|
+
"iWant": "the transport response to reflect whether the failure is retryable",
|
|
10
|
+
"soThat": "my retry policy honours the origin's judgement instead of guessing from the status code alone",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-16105-1",
|
|
14
|
+
"description": "A record with category transient produces a wire response the transport ADR maps to a retryable envelope (HTTP: a 5xx or a 429 with a Retry-After hint when the origin supplied one on the record); a record with category permanent produces a non-retryable envelope with no Retry-After (HTTP: a 4xx); a record with category unknown is treated as permanent by the wire but logged at error level.",
|
|
15
|
+
"given": "three failing handler paths that construct records with category transient, permanent and unknown respectively",
|
|
16
|
+
"when": "each request runs",
|
|
17
|
+
"then": "the transport response bodies and headers reflect the per-class contract above",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": ["TAC-1701-application-error-handling-boundary"],
|
|
23
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-error-handling-US-16106",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-error-handling-REQ-004",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Records emit through the logging companion; the fallback stderr path fires only when no companion is applied",
|
|
8
|
+
"asA": "operator debugging why an error record did not appear in the log ingestion pipeline",
|
|
9
|
+
"iWant": "records to emit exclusively through the applied logging companion's factory (never direct stderr) when a companion is applied",
|
|
10
|
+
"soThat": "records land in the same pipeline as every other log line and inherit the companion's redaction, correlation and stamping discipline",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-16106-1",
|
|
14
|
+
"description": "When a logging companion is applied on the project, the record emission path calls the companion factory's error() method; process.stderr.write and console.error carry no line from the boundary. When no logging companion is applied, the boundary falls back to a single-line JSON emission on stderr with a documented warning line ('no logging companion applied; emitting error record on stderr').",
|
|
15
|
+
"given": "two fixture applications: one with a logging companion applied, one without",
|
|
16
|
+
"when": "an error is emitted from the boundary",
|
|
17
|
+
"then": "the first case emits via the logging companion (nothing on stderr from the boundary itself); the second case emits one JSON line on stderr with the warning",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": ["TAC-1701-application-error-handling-boundary"],
|
|
23
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-error-handling-US-16107",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-error-handling-REQ-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "The boundary is substitutable via the framework interface so tests exercise it without booting the whole stack",
|
|
8
|
+
"asA": "test author verifying that a specific exception produces the expected record",
|
|
9
|
+
"iWant": "the boundary contract to expose a substitutable interface so a test can exercise the error-handling path without booting the full framework",
|
|
10
|
+
"soThat": "boundary tests are hermetic and fast",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-16107-1",
|
|
14
|
+
"description": "TAC-1701 exposes a boundaryFor({ loggerFactory, transportWriter }) -> { handle(err, context) } function the framework registers as its handler; a test constructs the boundary with a stub loggerFactory and a stub transportWriter, invokes handle(err, context), and asserts the observed loggerFactory calls and the observed transportWriter calls.",
|
|
15
|
+
"given": "a stub loggerFactory and a stub transportWriter",
|
|
16
|
+
"when": "the test invokes handle with a synthetic exception",
|
|
17
|
+
"then": "the stub loggerFactory records one error() call with the constructed record and the stub transportWriter records one write with the mapped wire body",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"tacIds": ["TAC-1701-application-error-handling-boundary"],
|
|
23
|
+
"createdAt": "2026-09-04T12:20:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T12:20:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# application-error-handling: coordination vocabulary
|
|
2
|
+
|
|
3
|
+
## Global topics
|
|
4
|
+
|
|
5
|
+
| Topic | Owning ADR | Meaning | Composition note |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| `errorHandling` | `ADR-1701-application-error-handling-record-shape` | Internal error record shape: code, category, message, correlationId, cause chain, redacted context. Minted here at v1.0.0. | Transport-agnostic. Composing blueprints that want a different internal record shape conflict by design; the operator resolves at project level. A library-registered errorHandling provider (wsd-error-handling, acme-error-shape) is preferred over this shelf provider by the companion-suggestion mechanism. |
|
|
8
|
+
|
|
9
|
+
## Distinction from `errorEnvelope`
|
|
10
|
+
|
|
11
|
+
`errorEnvelope` stays with `application-api-rest` and governs the REST wire body (RFC 7807-style, plus code/correlationId fields). `errorHandling` (this blueprint) governs the internal record shape one project decision above every transport-specific envelope. A future transport blueprint (gRPC, message consumer) claims its OWN transport-specific errorEnvelope-family topic and reads records from this blueprint's factory through the substitutable `transportWriter` interface (TAC-1701).
|
|
12
|
+
|
|
13
|
+
## Deliberately unclaimed topics
|
|
14
|
+
|
|
15
|
+
- `retryPolicy` (the runtime schedule and back-off behaviour). Owned by the applying platform; a future blueprint may claim it.
|
|
16
|
+
- `errorTelemetry` (aggregated error rate metrics, alerting rules). Belongs to a future metrics or alerting companion when the shelf ships one.
|
|
17
|
+
|
|
18
|
+
## Shelf id band and suffix block
|
|
19
|
+
|
|
20
|
+
| Blueprint | US band | ADR/TAC suffix block | Status | Global topics |
|
|
21
|
+
|---|---|---|---|---|
|
|
22
|
+
| application-error-handling | 16101-16899 | 17xx | shipped v1.0.0 | `errorHandling` |
|
|
23
|
+
|
|
24
|
+
The shelf-wide band registry lives in `packages/rcf-lite/docs/blueprint-authoring.md` section 5.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Guide: application-error-handling (v1.0.0)
|
|
2
|
+
|
|
3
|
+
## What it is
|
|
4
|
+
|
|
5
|
+
A shipped, org-neutral error-handling contract for a rcf-lite application. Two boundaries (process-level uncaught, framework-level request-pipeline), one shared internal error record shape, one classification vocabulary. Records emit through the applied logging companion so PII redaction, correlation propagation and structured emission all reuse the logging blueprint's discipline. The transport response mapping delegates to the applied transport blueprint's `errorEnvelope` ADR (application-api-rest for REST; a future blueprint for gRPC / message consumer).
|
|
6
|
+
|
|
7
|
+
## What it deliberately is not
|
|
8
|
+
|
|
9
|
+
- Not a transport wire envelope. application-api-rest owns `errorEnvelope` for REST; a future transport blueprint claims its own transport-specific errorEnvelope topic.
|
|
10
|
+
- Not a retry policy. The record carries `category`; the applying platform's retry surface reads it and decides. The blueprint names the per-class contract (transient => retryable; permanent => not retryable; unknown => permanent by wire, logged at error level) but does not itself schedule retries.
|
|
11
|
+
- Not a substitute for the logging companion's redaction. Context redaction at record construction uses the applied logging companion's redaction boundary; when no logging companion is applied, redaction is a pass-through (documented fallback).
|
|
12
|
+
|
|
13
|
+
## When to reach for it
|
|
14
|
+
|
|
15
|
+
- Any application that has not yet applied an error-handling companion. Applying this blueprint gives a working boundary and record shape without registering a library.
|
|
16
|
+
- Any project whose applied service blueprints (application-api-rest, application-spa) declare `suggestedCompanions: ["errorHandling"]` and no more specific library provides the role.
|
|
17
|
+
|
|
18
|
+
## When it does not fit
|
|
19
|
+
|
|
20
|
+
- A project standing on an organisation with a shipped error-handling library (`wsd-error-handling`, `acme-error-shape`) that provides the `errorHandling` role. The companion-suggestion mechanism resolves to the library over this shelf fallback.
|
|
21
|
+
- A project whose transport is not yet served by any transport blueprint the shelf ships. The delegation contract (ADR-1703) still holds; the project supplies its own `transportWriter`.
|
|
22
|
+
|
|
23
|
+
## What a good outcome looks like
|
|
24
|
+
|
|
25
|
+
- The uncaught boundary catches every process-level exception, emits one record and exits cleanly with code 1; the framework-level boundary maps every thrown exception to a mapped wire response with no raw stack trace; every record has code, category and correlationId; the cause chain is intact across every nested wrapping; the transport response reflects the classification (retryable vs not); `rcf define validate` clean.
|
|
26
|
+
|
|
27
|
+
## The operator decisions that remain open
|
|
28
|
+
|
|
29
|
+
- **The classification additions** (ADR-1702). Recommended defaults cover the three shared cases; per-domain additions (rate-limited, quota-exceeded, dependency-degraded) fit the same mechanism.
|
|
30
|
+
- **The applied transport blueprint.** REST projects apply application-api-rest 2.1.0 or later. Non-REST projects supply their own `transportWriter` against the substitutable interface.
|
|
31
|
+
- **The applied logging companion.** Recommended: apply observability-logging 1.0.0 or later (or a registered library-side provider). Without a logging companion, the fallback stderr path fires and the guide names the gap.
|
|
32
|
+
|
|
33
|
+
## Cost-honesty
|
|
34
|
+
|
|
35
|
+
Adds four REQs, seven USs, two TACs, three ADRs to the project's chain. The runtime cost is one boundary registration per boot plus one record construction per error emission (including a context deep-clone for redaction). No runtime dependency added to the project's `package.json`; the boundary is authored against the applying project's own runtime and its applied transport blueprint's writer interface.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "application-spa",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"category": "application",
|
|
5
5
|
"contributions": [
|
|
6
6
|
{
|
|
@@ -405,5 +405,15 @@
|
|
|
405
405
|
"light",
|
|
406
406
|
"dark"
|
|
407
407
|
]
|
|
408
|
-
}
|
|
408
|
+
},
|
|
409
|
+
"suggestedCompanions": [
|
|
410
|
+
{
|
|
411
|
+
"role": "logging",
|
|
412
|
+
"reason": "The client console emits structured lines through the same contract the server side uses; a logging companion supplies the factory and the client tier composes on top through its own boundary."
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
"role": "errorHandling",
|
|
416
|
+
"reason": "The browser-facing error boundary constructs the internal record from a client-side exception and hands it to the applied transport writer; an error-handling companion supplies the boundary and the record factory the SPA composes on."
|
|
417
|
+
}
|
|
418
|
+
]
|
|
409
419
|
}
|
|
@@ -33,14 +33,16 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
33
33
|
| hello-panel (walkthrough exemplar) | 4101-4899 | 4xx | doc-reserved; teaching exemplar in `packages/rcf-lite/docs/blueprint-authoring-walkthrough.md`, not shipped as a blueprint directory | `operatorPanel` |
|
|
34
34
|
| persistence-data-sqlite | 5101-5899 | 6xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
35
35
|
| delivery-ci-workflows | 6101-6899 | 7xx | shipped v2.0.0 (renamed from ci-pipeline) | `ciGates`, `strictCoverageGate`, `releaseArtefacts` |
|
|
36
|
-
| observability-essentials | 7101-7899 | 8xx | shipped
|
|
36
|
+
| observability-essentials | 7101-7899 | 8xx | shipped v2.0.0 | `statusPageContract` |
|
|
37
37
|
| security-secrets-management | 8101-8899 | 9xx | shipped v1.0.0 | `secretsSource` |
|
|
38
38
|
| security-auth-clerk | 9101-9899 | 10xx | shipped v1.0.0 | `authModel` |
|
|
39
39
|
| security-auth-oauth2 | 10101-10899 | 11xx | shipped v1.0.0 | `authModel` |
|
|
40
40
|
| security-auth-keycloak | 11101-11899 | 12xx | shipped v1.0.0 | `authModel` |
|
|
41
41
|
| deploy-cloudflare-workers | 12101-12899 | 13xx | shipped v1.0.0 | `deploymentTarget` |
|
|
42
42
|
| persistence-data-d1 | 13101-13899 | 14xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
43
|
-
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.
|
|
43
|
+
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.1.0 | `healthProbes`, `readinessSemantics` |
|
|
44
|
+
| observability-logging | 15101-15899 | 16xx | shipped v1.0.0 | `logging` |
|
|
45
|
+
| application-error-handling | 16101-16899 | 17xx | shipped v1.0.0 | `errorHandling` |
|
|
44
46
|
|
|
45
47
|
SPA v1.1.0 stays on the LOW end of its band: v1.0.0 occupied US-1101 through US-1128; v1.1.0 adds US-1129 and US-1130, leaving headroom above 1130 for future minor bumps and for project-side stories that mechanically derive to the 11xx numeric range.
|
|
46
48
|
|
|
@@ -41,14 +41,14 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
41
41
|
| hello-panel (walkthrough exemplar) | 4101-4899 | 4xx | doc-reserved; teaching exemplar in `packages/rcf-lite/docs/blueprint-authoring-walkthrough.md`, not shipped as a blueprint directory | `operatorPanel` |
|
|
42
42
|
| persistence-data-sqlite | 5101-5899 | 6xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
43
43
|
| delivery-ci-workflows | 6101-6899 | 7xx | shipped v2.0.0 (renamed from ci-pipeline) | `ciGates`, `strictCoverageGate`, `releaseArtefacts` |
|
|
44
|
-
| observability-essentials | 7101-7899 | 8xx | shipped
|
|
44
|
+
| observability-essentials | 7101-7899 | 8xx | shipped v2.0.0 | `statusPageContract` |
|
|
45
45
|
| security-secrets-management | 8101-8899 | 9xx | shipped v1.0.0 | `secretsSource` |
|
|
46
46
|
| security-auth-clerk | 9101-9899 | 10xx | shipped v1.0.0 | `authModel` |
|
|
47
47
|
| security-auth-oauth2 | 10101-10899 | 11xx | shipped v1.0.0 | `authModel` |
|
|
48
48
|
| security-auth-keycloak | 11101-11899 | 12xx | shipped v1.0.0 | `authModel` |
|
|
49
49
|
| deploy-cloudflare-workers | 12101-12899 | 13xx | shipped v1.0.0 | `deploymentTarget` |
|
|
50
50
|
| persistence-data-d1 | 13101-13899 | 14xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
51
|
-
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.
|
|
51
|
+
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.1.0 | `healthProbes`, `readinessSemantics` |
|
|
52
52
|
|
|
53
53
|
US 6101-6110 sit at the LOW end of the 6101-6899 band on purpose. A project-side story that mechanically derives from `delivery-ci-workflows-REQ-011` into the number `6111` would collide against delivery-ci-workflows-US-6111 in this package; the band leaves headroom at the HIGH end (US 6181-6899) so a project's own stories anchored to delivery-ci-workflows REQs can allocate without conflict. The watchpost run4 lesson applies here too.
|
|
54
54
|
|
|
@@ -27,14 +27,14 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
27
27
|
| hello-panel (walkthrough exemplar) | 4101-4899 | 4xx | doc-reserved; teaching exemplar in `packages/rcf-lite/docs/blueprint-authoring-walkthrough.md`, not shipped as a blueprint directory | `operatorPanel` |
|
|
28
28
|
| persistence-data-sqlite | 5101-5899 | 6xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
29
29
|
| delivery-ci-workflows | 6101-6899 | 7xx | shipped v2.0.0 (renamed from ci-pipeline) | `ciGates`, `strictCoverageGate`, `releaseArtefacts` |
|
|
30
|
-
| observability-essentials | 7101-7899 | 8xx | shipped
|
|
30
|
+
| observability-essentials | 7101-7899 | 8xx | shipped v2.0.0 | `statusPageContract` |
|
|
31
31
|
| security-secrets-management | 8101-8899 | 9xx | shipped v1.0.0 | `secretsSource` |
|
|
32
32
|
| security-auth-clerk | 9101-9899 | 10xx | shipped v1.0.0 | `authModel` |
|
|
33
33
|
| security-auth-oauth2 | 10101-10899 | 11xx | shipped v1.0.0 | `authModel` |
|
|
34
34
|
| security-auth-keycloak | 11101-11899 | 12xx | shipped v1.0.0 | `authModel` |
|
|
35
35
|
| deploy-cloudflare-workers | 12101-12899 | 13xx | shipped v1.0.0 | `deploymentTarget` |
|
|
36
36
|
| persistence-data-d1 | 13101-13899 | 14xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
37
|
-
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.
|
|
37
|
+
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.1.0 | `healthProbes`, `readinessSemantics` |
|
|
38
38
|
|
|
39
39
|
US 12101-12112 sit at the LOW end of the 12101-12899 band on purpose. A project-side story that mechanically derives from a deploy-cloudflare-workers REQ id into the number `12112` would collide against deploy-cloudflare-workers-US-12112 in this package; the band leaves headroom at the HIGH end (US 12181-12899) so a project's own stories anchored to deploy-cloudflare-workers REQs can allocate without conflict. The watchpost run4 lesson applies here too. Band spacing between the last shipped block (security-secrets-management, 8101-8899, 9xx) and this one (12101-12899, 13xx) leaves the 9xxx-11xxx US bands and the 10xx-12xx suffix blocks open for concurrent-lane authoring so a peer authoring another blueprint in the same PR window does not collide with this one.
|
|
40
40
|
|
|
@@ -23,14 +23,14 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
23
23
|
| hello-panel (walkthrough exemplar) | 4101-4899 | 4xx | doc-reserved; teaching exemplar in `packages/rcf-lite/docs/blueprint-authoring-walkthrough.md`, not shipped as a blueprint directory | `operatorPanel` |
|
|
24
24
|
| persistence-data-sqlite | 5101-5899 | 6xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
25
25
|
| delivery-ci-workflows | 6101-6899 | 7xx | shipped v2.0.0 (renamed from ci-pipeline) | `ciGates`, `strictCoverageGate`, `releaseArtefacts` |
|
|
26
|
-
| observability-essentials | 7101-7899 | 8xx | shipped
|
|
26
|
+
| observability-essentials | 7101-7899 | 8xx | shipped v2.0.0 | `statusPageContract` |
|
|
27
27
|
| security-secrets-management | 8101-8899 | 9xx | shipped v1.0.0 | `secretsSource` |
|
|
28
28
|
| security-auth-clerk | 9101-9899 | 10xx | shipped v1.0.0 | `authModel` |
|
|
29
29
|
| security-auth-oauth2 | 10101-10899 | 11xx | shipped v1.0.0 | `authModel` |
|
|
30
30
|
| security-auth-keycloak | 11101-11899 | 12xx | shipped v1.0.0 | `authModel` |
|
|
31
31
|
| deploy-cloudflare-workers | 12101-12899 | 13xx | shipped v1.0.0 | `deploymentTarget` |
|
|
32
32
|
| persistence-data-d1 | 13101-13899 | 14xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
33
|
-
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.
|
|
33
|
+
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.1.0 | `healthProbes`, `readinessSemantics` |
|
|
34
34
|
|
|
35
35
|
US 4101-4106 sit at the LOW end of the 4101-4899 band on purpose. A project-side story that mechanically derives from an email-smtp-resend REQ id into the number `4106` (leading `4` + sequence `106`) would collide against email-smtp-resend-US-4106 in this package; the band leaves headroom at the HIGH end (US 4181-4899) so a project's own stories anchored to email-smtp-resend REQs can allocate without conflict. The watchpost run4 lesson applies here too.
|
|
36
36
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
# Observability blueprint (
|
|
1
|
+
# Observability blueprint (v2.0.0)
|
|
2
2
|
|
|
3
|
-
The fifth content blueprint on the rcf-build-lite blueprint mechanism (design brief v2, ratified; Phase 5 of the blueprint programme). Scope: two HTTP health probes (liveness
|
|
3
|
+
The fifth content blueprint on the rcf-build-lite blueprint mechanism (design brief v2, ratified; Phase 5 of the blueprint programme). Scope: two HTTP health probes (liveness and readiness, path-neutral from v2.0.0: liveness answering strictly on in-process state, readiness aggregating over an explicit boot-time-declared dependency set with strict-any-fail semantics), a public status page rendering a declared component list plus stable-fielded incident notices, and a durable notification-outcome sink recording every attempt's outcome for later query by recipient and window. Targeted at small greenfield rcf-lite projects. Historical uptime charts, metrics export, and distributed tracing are documented future variants; the v2.0.0 blueprint ships the current-state contract only.
|
|
4
|
+
|
|
5
|
+
## Breaking change in v2.0.0 (2026-09-04)
|
|
6
|
+
|
|
7
|
+
This blueprint no longer claims the shelf-wide `healthProbes` or `readinessSemantics` global topics. Path binding moved to `observability-probe-endpoints` (spec `projects/rcf-lite-wsd/specs/rcf-lite-probe-path-alignment-spec-2026-09-04.md`, section 4). Essentials-alone projects now supply `probeInterface.paths.liveness` and `probeInterface.paths.readiness` at boot (a one-line configuration change per environment). Projects that compose `observability-probe-endpoints` v1.1.0 or later inherit its resolved path set automatically and see no functional change beyond the topic ownership. See CHANGELOG.md for the full migration checklist.
|
|
4
8
|
|
|
5
9
|
## Apply
|
|
6
10
|
|