@techspokes/typescript-wsdl-client 1.3.0 → 1.4.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.
Files changed (34) hide show
  1. package/README.md +8 -0
  2. package/dist/checkedPipeline.d.ts +73 -2
  3. package/dist/checkedPipeline.js +118 -8
  4. package/dist/checkedPlanning.d.ts +5 -2
  5. package/dist/checkedPlanning.js +30 -5
  6. package/dist/checkedResponseInspection.d.ts +100 -0
  7. package/dist/checkedResponseInspection.js +499 -0
  8. package/dist/cli.js +55 -1
  9. package/dist/client/checkedDirectRuntime.d.ts +8 -0
  10. package/dist/client/checkedDirectRuntime.js +22 -14
  11. package/dist/client/directClientRuntime.d.ts +10 -3
  12. package/dist/client/directClientRuntime.js +14 -8
  13. package/dist/client/directClientVersion.d.ts +2 -0
  14. package/dist/client/directClientVersion.js +2 -0
  15. package/dist/client/generateDirectClient.js +7 -7
  16. package/dist/compiler/componentRecordProjection.d.ts +1 -0
  17. package/dist/compiler/componentRecordProjection.js +15 -4
  18. package/dist/compiler/directCodec.js +3 -11
  19. package/dist/compiler/directSoap.d.ts +50 -5
  20. package/dist/compiler/directSoap.js +204 -98
  21. package/dist/compiler/sourceCorrections.d.ts +118 -0
  22. package/dist/compiler/sourceCorrections.js +794 -0
  23. package/dist/gateway/generateCheckedGateway.js +9 -10
  24. package/dist/index.d.ts +3 -1
  25. package/dist/index.js +2 -1
  26. package/dist/util/readBoundedFile.d.ts +9 -0
  27. package/dist/util/readBoundedFile.js +36 -0
  28. package/dist/util/xmlBytes.d.ts +9 -0
  29. package/dist/util/xmlBytes.js +24 -0
  30. package/docs/api-reference.md +28 -1
  31. package/docs/checked-gateway.md +44 -0
  32. package/docs/cli-reference.md +16 -1
  33. package/docs/migration.md +10 -0
  34. package/package.json +1 -1
@@ -22,7 +22,7 @@ async function generateGatewayFromReconstruction(expected, options) {
22
22
  throw new Error('Checked gateway generation cancelled');
23
23
  inspectReconstructedComponentSource(expected);
24
24
  const capsule = { bytes: componentSourceCapsuleBytes(expected, options.signal) };
25
- const runtime = expected.contract.binding.version === '1.2' ? 'checkedComponentRuntimeV2' : 'checkedComponentRuntimeV1';
25
+ const runtime = expected.contract.binding.version === '1.2' ? 'checkedComponentRuntimeV2' : 'checkedComponentRuntimeV3';
26
26
  if (!options.routePath.startsWith('/') || options.routePath.split('/').slice(1)
27
27
  .some(segment => !segment || !/^(?:[A-Za-z0-9._~-]|%[0-9A-Fa-f]{2})+$/.test(segment))) {
28
28
  throw new TypeError('Checked routePath requires literal nonempty path segments');
@@ -69,12 +69,11 @@ async function generateGatewayFromReconstruction(expected, options) {
69
69
  },
70
70
  },
71
71
  }));
72
- if (soap12)
73
- faultVariants.push({ type: 'object', additionalProperties: false, required: ['fault'], properties: {
74
- fault: { type: 'object', additionalProperties: false, required: ['version', 'code', 'string', 'subcodes', 'reasons'],
75
- properties: protocolFaultProperties },
76
- } });
77
- const fault = faultVariants.length ? { oneOf: faultVariants } : { not: {} };
72
+ faultVariants.push({ type: 'object', additionalProperties: false, required: ['fault'], properties: {
73
+ fault: { type: 'object', additionalProperties: false, required: ['version', 'code', 'string', ...(soap12 ? ['subcodes', 'reasons'] : [])],
74
+ properties: soap12 ? protocolFaultProperties : { version: { const: '1.1' }, code: nameSchema, string: { type: 'string' }, actor: { type: 'string' } } },
75
+ } });
76
+ const fault = { oneOf: faultVariants };
78
77
  const schemas = { request: { $schema: draft07, ...request }, response: { $schema: draft07, ...response }, fault: { $schema: draft07, ...fault } };
79
78
  const grouped = expected.mappings.some(mapping => mapping.kind === 'component-mapping'
80
79
  && inspectComponentValueMapping(mapping, expected.contract).applicationGroups);
@@ -124,7 +123,7 @@ async function generateGatewayFromReconstruction(expected, options) {
124
123
  requestBody: { required: true, content: { 'application/json': { schema: documentation.request } } },
125
124
  responses: { '200': { description: 'Independently validated SOAP response', content: { 'application/json': { schema: documentation.response } } },
126
125
  '400': { description: 'Invalid HTTP request; no SOAP request is dispatched' },
127
- '502': { description: 'Declared SOAP fault or refused upstream response', content: { 'application/json': { schema: { oneOf: [documentation.fault,
126
+ '502': { description: 'SOAP fault or refused upstream response', content: { 'application/json': { schema: { oneOf: [documentation.fault,
128
127
  { type: 'object', additionalProperties: false, required: ['kind', 'rule'], properties: { kind: { type: 'string' }, rule: { type: 'string' } } }] } } } },
129
128
  '500': { description: 'Incompatible artifacts or gateway configuration' } } } } },
130
129
  };
@@ -191,9 +190,9 @@ const plugin: FastifyPluginAsync<CheckedGatewayOptions> = async (fastify, option
191
190
  ...(result.fault.name === undefined ? {} : {name: result.fault.name}),
192
191
  ...(result.fault.node === undefined ? {} : {node: result.fault.node}),
193
192
  ...(result.fault.role === undefined ? {} : {role: result.fault.role})};
194
- const value = result.fault.name === undefined ? {fault} : {fault, value: result.value};` : `const fault = {name: result.fault.name, code: {namespace: result.fault.code.namespace, local: result.fault.code.local},
193
+ const value = result.fault.name === undefined ? {fault} : {fault, value: result.value};` : `const fault = {...(result.fault.name === undefined ? {version: result.fault.version} : {name: result.fault.name}), code: {namespace: result.fault.code.namespace, local: result.fault.code.local},
195
194
  string: result.fault.string, ...(result.fault.actor === undefined ? {} : {actor: result.fault.actor})};
196
- const value = {fault, value: result.value};`}
195
+ const value = 'value' in result ? {fault, value: result.value} : {fault};`}
197
196
  if (!validateFault(value)) return reply.code(502).send({kind: 'value-invalid', rule: 'http-fault-shape'});
198
197
  return reply.code(502).type('application/json').serializer(value => JSON.stringify(value)).send(value);
199
198
  }
package/dist/index.d.ts CHANGED
@@ -12,10 +12,12 @@ export type { ComposedOpenApiDocument, OpenApiCompositionEntry, OpenApiCompositi
12
12
  export type { CheckedComponentOptions, CheckedInventory } from './checkedPipeline.js';
13
13
  export { planCheckedComponents, formatCheckedComponentPlan, writeCheckedPlanningFile, CheckedPlanningError } from './checkedPlanning.js';
14
14
  export type { CheckedComponentPlan, ComponentPlanBlocker } from './checkedPlanning.js';
15
+ export { inspectCheckedResponse } from './checkedResponseInspection.js';
16
+ export type { CheckedResponseInspectionOptions, CheckedResponseInspectionReport } from './checkedResponseInspection.js';
15
17
  export type { ComponentRecordProjectionSpec, ComponentRecordProjectionAssociation } from './compiler/componentRecordProjection.js';
16
18
  export { loadStreamConfigFile, parseStreamConfig, StreamConfigError, type OperationStreamMetadata, type ShapeCatalogRef, type StreamConfig, } from "./util/streamConfig.js";
17
19
  export { applyShapeCatalogs, type ApplyShapeCatalogsOptions } from "./compiler/shapeResolver.js";
18
- export { checkedDirectRuntimeV1, checkedComponentRuntimeV1, checkedComponentRuntimeV2 } from './client/checkedDirectRuntime.js';
20
+ export { checkedDirectRuntimeV1, checkedComponentRuntimeV1, checkedComponentRuntimeV2, checkedComponentRuntimeV3 } from './client/checkedDirectRuntime.js';
19
21
  /**
20
22
  * Compiles a WSDL file to TypeScript client code
21
23
  *
package/dist/index.js CHANGED
@@ -30,9 +30,10 @@ export { runGenerationPipeline } from "./pipeline.js";
30
30
  export { runMultiServicePipeline, loadMultiServiceConfig } from './multiServicePipeline.js';
31
31
  export { composeOpenApiDocuments } from './openapi/composeOpenAPI.js';
32
32
  export { planCheckedComponents, formatCheckedComponentPlan, writeCheckedPlanningFile, CheckedPlanningError } from './checkedPlanning.js';
33
+ export { inspectCheckedResponse } from './checkedResponseInspection.js';
33
34
  export { loadStreamConfigFile, parseStreamConfig, StreamConfigError, } from "./util/streamConfig.js";
34
35
  export { applyShapeCatalogs } from "./compiler/shapeResolver.js";
35
- export { checkedDirectRuntimeV1, checkedComponentRuntimeV1, checkedComponentRuntimeV2 } from './client/checkedDirectRuntime.js';
36
+ export { checkedDirectRuntimeV1, checkedComponentRuntimeV1, checkedComponentRuntimeV2, checkedComponentRuntimeV3 } from './client/checkedDirectRuntime.js';
36
37
  // noinspection JSUnusedGlobalSymbols
37
38
  /**
38
39
  * Compiles a WSDL file to TypeScript client code
@@ -0,0 +1,9 @@
1
+ /** Acquire a regular file through one descriptor under a caller-specified byte limit.
2
+ * @since 1.4.0
3
+ * @param file Local input path.
4
+ * @param maxBytes Maximum accepted file size, leaving room for a one-byte growth probe.
5
+ * @returns The bytes read from the opened file.
6
+ * @throws RangeError For an invalid limit or an input exceeding it.
7
+ * @throws Error For filesystem errors, a nonregular input, or a size change observed during the read.
8
+ */
9
+ export declare function readBoundedFile(file: string, maxBytes: number): Buffer;
@@ -0,0 +1,36 @@
1
+ import fs from 'node:fs';
2
+ import { constants } from 'node:buffer';
3
+ /** Acquire a regular file through one descriptor under a caller-specified byte limit.
4
+ * @since 1.4.0
5
+ * @param file Local input path.
6
+ * @param maxBytes Maximum accepted file size, leaving room for a one-byte growth probe.
7
+ * @returns The bytes read from the opened file.
8
+ * @throws RangeError For an invalid limit or an input exceeding it.
9
+ * @throws Error For filesystem errors, a nonregular input, or a size change observed during the read.
10
+ */
11
+ export function readBoundedFile(file, maxBytes) {
12
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 0 || maxBytes >= constants.MAX_LENGTH)
13
+ throw new RangeError('Invalid file byte limit');
14
+ const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK);
15
+ try {
16
+ const stat = fs.fstatSync(fd);
17
+ if (!stat.isFile())
18
+ throw new TypeError('Expected a regular file');
19
+ if (stat.size > maxBytes)
20
+ throw new RangeError('File byte limit exceeded');
21
+ const buffer = Buffer.alloc(stat.size + 1);
22
+ let offset = 0;
23
+ while (offset < buffer.length) {
24
+ const count = fs.readSync(fd, buffer, offset, buffer.length - offset, null);
25
+ if (count === 0)
26
+ break;
27
+ offset += count;
28
+ }
29
+ if (offset !== stat.size)
30
+ throw new Error('File size changed during the read');
31
+ return buffer.subarray(0, offset);
32
+ }
33
+ finally {
34
+ fs.closeSync(fd);
35
+ }
36
+ }
@@ -0,0 +1,9 @@
1
+ /** Inspect genuine XML bytes without evaluating caller-owned length, backing-store or iterator properties.
2
+ * @throws TypeError For non-byte views, proxies or shared backing stores.
3
+ * @constraints Callers must enforce their capacity before requesting a snapshot.
4
+ */
5
+ export declare function xmlByteLength(value: unknown): number;
6
+ /** Copy XML bytes through native slots so hashing and decoding share one private observation.
7
+ * @constraints Callers must first bound xmlByteLength; no user iterator or property getter is consulted.
8
+ */
9
+ export declare function snapshotXmlBytes(value: Uint8Array): Uint8Array;
@@ -0,0 +1,24 @@
1
+ import { types } from 'node:util';
2
+ const typed = Object.getPrototypeOf(Uint8Array.prototype);
3
+ const lengthGetter = Object.getOwnPropertyDescriptor(typed, 'byteLength').get;
4
+ const bufferGetter = Object.getOwnPropertyDescriptor(typed, 'buffer').get;
5
+ const setBytes = Uint8Array.prototype.set;
6
+ /** Inspect genuine XML bytes without evaluating caller-owned length, backing-store or iterator properties.
7
+ * @throws TypeError For non-byte views, proxies or shared backing stores.
8
+ * @constraints Callers must enforce their capacity before requesting a snapshot.
9
+ */
10
+ export function xmlByteLength(value) {
11
+ if (!types.isUint8Array(value) || types.isProxy(value))
12
+ throw new TypeError('XML requires Uint8Array bytes');
13
+ if (types.isSharedArrayBuffer(bufferGetter.call(value)))
14
+ throw new TypeError('Shared XML bytes are unsupported');
15
+ return lengthGetter.call(value);
16
+ }
17
+ /** Copy XML bytes through native slots so hashing and decoding share one private observation.
18
+ * @constraints Callers must first bound xmlByteLength; no user iterator or property getter is consulted.
19
+ */
20
+ export function snapshotXmlBytes(value) {
21
+ const copy = new Uint8Array(xmlByteLength(value));
22
+ setBytes.call(copy, value);
23
+ return copy;
24
+ }
@@ -4,9 +4,36 @@ This reference covers public generation, composition, stream and security APIs.
4
4
 
5
5
  See the main [README](../README.md) for installation, CLI usage, and project overview.
6
6
 
7
+ ## Captured checked SOAP responses
8
+
9
+ `inspectCheckedResponse(source, options)` returns versioned diagnostic data without generating files or dispatching SOAP. Supply an authorized local WSDL, closed snapshots in `checkedComponents`, a full operation selector, and `responseBytes`. Optional `responseMetadata` supplies the actual HTTP `status`, `contentType` and `contentEncoding`. Omission leaves HTTP duties unassessed. `signal` and `limits` retain cancellation and XML capacity controls.
10
+
11
+ ```typescript
12
+ import {inspectCheckedResponse} from '@techspokes/typescript-wsdl-client';
13
+
14
+ const report = await inspectCheckedResponse('./sources/service.wsdl', {
15
+ checkedComponents: configuration,
16
+ selector: configuration.selectors[0],
17
+ responseBytes: capturedBytes,
18
+ });
19
+ console.log(report.kind);
20
+ ```
21
+
22
+ The report separates wrapper and companion outcomes and excludes raw XML and decoded values. Configuration can select a consumer-owned `sourceCorrectionsFile`; the same effective contract is used for planning, inspection and generation. A correction draft does not authorize execution until its semantic choices are completed. See [source corrections and offline inspection](checked-gateway.md#consumer-owned-source-corrections).
23
+
24
+ Set `includeCorrectionDraft: true` to request an available correction draft. Its exact resource pins can contain local source URIs; default reports retain only diagnostic resource labels.
25
+
26
+ Pass the complete multi-operation checked configuration unchanged. Inspection authenticates the complete correction-source closure before selecting the requested operation and its projection; inactive companions retain their freshness checks.
27
+
28
+ ## Checked runtime bindings
29
+
30
+ New SOAP 1.1 component clients inject package-root `checkedComponentRuntimeV3` with handshake `checked-component-soap11-runtime-v1`. SOAP 1.2 keeps `checkedComponentRuntimeV2`, and existing SOAP 1.1 artifacts keep their V1 binding. These injection contracts are separate from package and capsule versions.
31
+
32
+ A V3 protocol `soap-fault` exposes version `1.1`, expanded `code`, `string`, optional `actor`, response bytes and transport status without a declared application `value` or fault `name`. A uniquely declared fault detail retains native decoding; malformed declared content is refused. See [runtime compatibility](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/decisions/005-checked-protocol-fault-compatibility.md) and [migration](migration.md#from-13x-to-140).
33
+
7
34
  All file-producing APIs automatically apply [TypeScript preambles](generated-code.md#generated-preambles-and-eslint). Adding a preamble does not change an API signature or option; existing scaffold skip/force behavior still applies. Resource and TypeScript file-write failures propagate to callers.
8
35
 
9
- Generated-output compatibility is versioned separately from those preambles. Read the [migration guide for the intended version](migration.md), including [1.2.x-to-1.3.0 SOAP binding adoption](migration.md#from-12x-to-130), before regenerating existing clients or changing their selected profile.
36
+ Generated-output compatibility is versioned separately from those preambles. Read the [migration guide for the intended version](migration.md), including [1.3.x-to-1.4.0 runtime adoption](migration.md#from-13x-to-140), before regenerating existing clients or changing their selected profile.
10
37
 
11
38
  ## compileWsdlToProject
12
39
 
@@ -8,6 +8,8 @@ SOAP 1.2 document/literal operations use the selected binding's envelope namespa
8
8
 
9
9
  Generated SOAP 1.2 clients use the additive `checkedComponentRuntimeV2` package-root binding with protocol `checked-component-soap12-runtime-v1`. Existing SOAP 1.1 clients keep `checkedComponentRuntimeV1` and `checked-component-runtime-v2`, including their TypeScript injection contract. The older binding refuses SOAP 1.2 artifacts before SOAP dispatch.
10
10
 
11
+ Regenerated SOAP 1.1 clients use `checkedComponentRuntimeV3` and `checked-component-soap11-runtime-v1`. Valid SOAP 1.1 faults without declared application detail retain protocol metadata and original response bytes without inventing a typed value. Declared application detail still requires native validation; mixed or ambiguous declared detail refuses. Gateways expose protocol faults as HTTP 502 without a `value` member. Existing V1/V2 injection contracts remain available; see [ADR-005](https://github.com/TechSpokes/typescript-wsdl-client/blob/main/docs/decisions/005-checked-protocol-fault-compatibility.md).
12
+
11
13
  SOAP 1.2 faults retain code, nested subcodes, language-tagged reasons and optional Node/Role metadata. Declared application detail uses the existing native mapping and gateway fault validation. A valid protocol fault without declared application detail carries fault metadata without a typed application value; the client retains original response bytes. Gateways return HTTP 502 for upstream faults, including SOAP Sender faults received on HTTP 400. SOAP 1.2 protocol rules follow [the messaging framework](https://www.w3.org/TR/soap12-part1/#soapfault) and [HTTP binding](https://www.w3.org/TR/soap12-part2/#soapinhttp).
12
14
 
13
15
  SOAP 1.2 header processing uses the default ultimate receiver and next roles. Unknown mandatory blocks targeted at this receiver refuse; other-role and optional blocks may be ignored. The `mustUnderstand` and `relay` attributes accept SOAP 1.2 Boolean lexical forms. This does not enable outgoing application headers, WS-Security, streaming or RPC/encoded SOAP 1.2.
@@ -96,6 +98,48 @@ Previously, ordinary setup authored `sourceResources`, selectors, `endpoint` and
96
98
 
97
99
  This component injection change uses `checked-component-runtime-v2`; regenerate clients, capsules, gateways and server scaffolds together when upgrading. The exported binding name remains `checkedComponentRuntimeV1` for existing imports, and existing explicit endpoint callbacks remain valid after regeneration. Consumer server/config/test files retain skip/force ownership rules; use existing force options deliberately to refresh those scaffolds. The v1.1.5 direct runtime protocol and legacy defaults are unchanged.
98
100
 
101
+ ### Consumer-owned source corrections
102
+
103
+ Set `sourceCorrectionsFile` in checked generation configuration to apply a versioned JSON correction file to the project's outer and companion sources. Paths follow the existing generation convention: resolve them from the invocation working directory. Corrections are generation inputs; do not put them in HTTP request bodies or runtime endpoint configuration.
104
+
105
+ Maintain upstream snapshots unchanged and keep the correction file under version control. The correction file pins the complete original resource set by logical URI and digest. Refreshing upstream metadata requires regenerating and reviewing the correction draft. Scoped targets identify original declarations and particles, not generated TypeScript names. All edits resolve against the original inventory before application.
106
+
107
+ The bounded operations change particle occurrence bounds, narrow element wildcard namespaces, or insert a typed element into an existing sequence. Insertions require an existing named type or global element reference. Corrections do not define new complex types, rewrite imports, or change incoming SOAP XML. Use replacement snapshots for unsupported restructuring or sources that cannot construct a canonical inventory.
108
+
109
+ The correction document has `version: 1`, `resources: [{uri, digest}]`, and `corrections`. Retain every original resource pin supplied by the tool. A target is `{id, uri, digest}` copied from the inventory or draft; do not replace it with a generated DTO name. Complete unresolved draft values before passing the file to generation.
110
+
111
+ | Correction kind | Required settings |
112
+ | --- | --- |
113
+ | `set-occurs` | `target`, `min`, and `max`; bounds are canonical decimal strings, with `"unbounded"` also permitted for `max` |
114
+ | `set-wildcard-namespaces` | `target` and `namespaces`; use explicit namespace strings and `""` for the no-namespace case; the original `processContents` is preserved |
115
+ | `insert-element` | Sequence `target`, `position`, and `element`; position is `"append"` or `{kind: "before" or "after", target: originalChildTarget}` |
116
+
117
+ For a local inserted declaration, `element` contains `{kind: "declaration", name, type: {namespace, local}, min, max}`. The type must be a built-in XSD type or an existing named type. A global element reference instead uses `{kind: "reference", target: globalElementTarget, min, max}`. For example, a reviewed new scalar can use `type: {namespace: "http://www.w3.org/2001/XMLSchema", local: "string"}`; selecting that type is a contract decision, not an inference from one text value. Local declarations follow the containing schema's element-form rules.
118
+
119
+ Inserting a no-namespace type or reference beneath a nonempty default namespace currently refuses rather than changing QName meaning. Use a replacement snapshot for that case. Two insertions at the same original source position also refuse; choose distinct original anchors or supply a replacement snapshot for a larger restructuring.
120
+
121
+ Making metadata optional can make a following unrestricted wildcard ambiguous. Review both declarations: an explicit payload namespace constraint may be necessary to preserve native XSD 1.0 qualification. Narrowing changes the accepted contract, so confirm every intended payload namespace rather than copying the wrapper namespace by assumption.
122
+
123
+ Effective metadata is freshly parsed and checked before generation. Native decoding, SOAP bootstrap, generated types, OpenAPI, and runtime source reconstruction use those same effective bytes. Generated provenance distinguishes upstream and effective digests; successful validation establishes conformance to the consumer's effective contract, not upstream approval. Runtime needs the generated effective snapshots, not the correction file or upstream network access. Regenerate clients, contracts and gateways together after changes, and refresh source-derived presentation targets when necessary.
124
+
125
+ One generated project retains one effective byte sequence per logical URI. Shared declarations change for all their uses in that project. Conflicting URI contents and interpretation-specific edits to shared chameleon declarations refuse; separate replacement snapshots are required for those cases. This feature does not extend checked multi-service composition or legacy generation.
126
+
127
+ ### Offline response inspection
128
+
129
+ Use `inspect-response` with a local WSDL, closed snapshot configuration, one configured operation and a saved SOAP response. It does not acquire missing remote metadata, dispatch SOAP, or read credentials. Create the output directory first; existing report or draft files are not overwritten.
130
+
131
+ ```bash
132
+ npx wsdl-tsc inspect-response --wsdl-source ./sources/service.wsdl --checked-config ./checked.json --operation Fetch --response-file ./captures/fetch.xml --report .generated/inspection.json --corrections-draft .generated/corrections-draft.json
133
+ ```
134
+
135
+ XML-only inspection leaves HTTP status and media checks unassessed. To assess an actual full response, add `--response-metadata ./captures/fetch-metadata.json` containing `status`, `contentType`, and optional `contentEncoding`. Do not invent metadata for a capture that did not retain it.
136
+
137
+ Reports separate wrapper and companion assessment. A valid inner payload cannot rescue an invalid wrapper. Reports omit decoded values and raw XML. Correction drafts provide pinned targets and existing values, but leave type, occurrence and namespace decisions unresolved until a developer reviews and completes them. Drafts may be unavailable when source loading or target inventory construction fails.
138
+
139
+ Drafts retain exact logical source URIs, which can include local filesystem paths, because those identities are needed to apply corrections. The CLI writes them only to the explicitly requested draft file. Programmatic callers must select `includeCorrectionDraft: true` to receive those additional local identities; ordinary diagnostic reports use resource labels.
140
+
141
+ Exit codes are 0 for conformance within the reported scope, 1 for mismatch/refusal, and 2 for invocation/file errors. A conforming SOAP fault remains identified as a fault. The package-root `inspectCheckedResponse` API accepts the same checked choices, a full operation selector, response bytes, optional actual response metadata, cancellation and XML limits; it returns diagnostic data without writing files.
142
+
99
143
  ### Planning and missing-schema recovery
100
144
 
101
145
  `--checked-report` writes versioned `checked-component-plan-v1` JSON on native success or refusal. Human refusals identify the native reason, stage, dimension, affected full operation identities and configuration pointer. Source legality, correspondence, mapping/artifact readiness and runtime remain separate dimensions. Unsupported or inconclusive qualification does not establish invalid vendor schemas. Loading interruptions retain discovered counts plus explicit incomplete inventory; independent operation refusals are collected before generation writes project artifacts.
@@ -10,7 +10,7 @@ Generation paths are explicit. Examples use the git-ignored `.generated/` direct
10
10
 
11
11
  ## Commands Overview
12
12
 
13
- The tool provides six generation commands and the assessment-only `assess` command.
13
+ The tool provides six generation commands and the diagnostic commands `assess` and `inspect-response`.
14
14
 
15
15
  TypeScript outputs automatically receive [generated preambles](generated-code.md#generated-preambles-and-eslint), including app/test scaffolds when actually written. Command syntax is unchanged and there is no preamble flag. `compile` and `openapi` data outputs remain unchanged.
16
16
 
@@ -23,6 +23,21 @@ TypeScript outputs automatically receive [generated preambles](generated-code.md
23
23
  | app | Runnable Fastify app from client + gateway + OpenAPI | Local testing, demos |
24
24
  | compile | Parse WSDL to catalog.json only | Debugging, multi-stage builds |
25
25
  | assess | Source schema diagnostic report | Checked evidence and unresolved duties |
26
+ | inspect-response | Offline captured SOAP response inspection | Scoped mismatches and source correction drafts |
27
+
28
+ ## inspect-response
29
+
30
+ Inspect saved SOAP XML using an authorized local checked source and closed snapshots. This command never dispatches SOAP or reads credentials.
31
+
32
+ Required inputs are `--wsdl-source`, `--checked-config`, `--operation`, `--response-file` and `--report`.
33
+
34
+ ```bash
35
+ npx wsdl-tsc inspect-response --wsdl-source ./sources/service.wsdl --checked-config ./checked.json --operation Fetch --response-file ./captures/fetch.xml --report .generated/inspection.json
36
+ ```
37
+
38
+ The checked configuration must list exactly one matching selector for `--operation`. Narrow `selectors` when different bindings expose the same operation name. Optional `--response-metadata` points to JSON containing actual `status`, `contentType` and optional `contentEncoding`; omission selects XML-only scope with HTTP checks unassessed. Optional `--corrections-draft` writes a draft when the inspector can derive one. Reports and drafts use exclusive creation; create the destination directory and choose unused filenames. Input files have a 1 MiB CLI capacity.
39
+
40
+ Exit 0 establishes conformance only within the report's assessment scope; 1 reports mismatch/refusal and 2 identifies invocation/file errors. SOAP faults remain faults even when their declared shape conforms. See [checked source corrections](checked-gateway.md#consumer-owned-source-corrections) for draft completion and regeneration.
26
41
 
27
42
  ## pipeline
28
43
 
package/docs/migration.md CHANGED
@@ -16,6 +16,16 @@ These steps apply to every version upgrade:
16
16
  4. Regenerate matched generator-owned artifacts using the existing generation script and options.
17
17
  5. Review the generated diff and run the consumer project's TypeScript build and tests.
18
18
 
19
+ ## From 1.3.x to 1.4.0
20
+
21
+ Package updates preserve existing SOAP 1.1 V1 and SOAP 1.2 V2 runtime contracts. Newly generated checked SOAP 1.1 clients use `checkedComponentRuntimeV3` and `checked-component-soap11-runtime-v1`; regenerate matched clients, capsules, OpenAPI and gateways together to adopt that binding. Legacy generation and direct preview remain unchanged.
22
+
23
+ A V3 `soap-fault` can carry protocol metadata without a declared application `value` or fault `name`. Check whether a typed value exists before accessing it. Declared details still undergo native validation, and protocol faults remain gateway HTTP 502 responses.
24
+
25
+ Checked projects can opt into `sourceCorrectionsFile` for digest-pinned consumer corrections. Preserve upstream originals, review source changes, and regenerate effective snapshots and dependent artifacts together. Runtime deployments need effective snapshots and capsules, not the correction recipe; see [contract correction maintenance](checked-gateway.md).
26
+
27
+ Offline inspection accepts the complete multi-operation checked configuration and a full operation selector. Correction pins cover every project companion even when only one operation is inspected. XML-only reports do not establish HTTP status or media conformance without supplied response metadata.
28
+
19
29
  ## From 1.2.x to 1.3.0
20
30
 
21
31
  Version 1.3.0 adds checked SOAP 1.2 document/literal execution. Legacy generation remains the default. Existing SOAP 1.1 component clients keep `checkedComponentRuntimeV1` and `checked-component-runtime-v2`; the shipped direct runtime is unchanged. Updating the package alone does not adopt SOAP 1.2 or require regeneration of existing SOAP 1.1 clients.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techspokes/typescript-wsdl-client",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Turn legacy WSDL/SOAP services into typed TypeScript clients, OpenAPI 3.1 specs, and production-ready Fastify REST gateways. Built for enterprise SOAP modernization.",
5
5
  "keywords": [
6
6
  "wsdl",