schemantic 0.2.1 → 0.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.
- package/CHANGELOG.md +196 -159
- package/LICENSE +21 -21
- package/README.md +88 -830
- package/dist/cli/index.d.ts +4 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +186 -62
- package/dist/cli/index.js.map +1 -1
- package/dist/core/configuration.d.ts +6 -0
- package/dist/core/configuration.d.ts.map +1 -0
- package/dist/core/configuration.js +64 -0
- package/dist/core/configuration.js.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/output-writer.d.ts +7 -0
- package/dist/core/output-writer.d.ts.map +1 -0
- package/dist/core/output-writer.js +255 -0
- package/dist/core/output-writer.js.map +1 -0
- package/dist/core/schemantic.d.ts +8 -6
- package/dist/core/schemantic.d.ts.map +1 -1
- package/dist/core/schemantic.js +194 -127
- package/dist/core/schemantic.js.map +1 -1
- package/dist/generators/api-client-generator.d.ts +9 -20
- package/dist/generators/api-client-generator.d.ts.map +1 -1
- package/dist/generators/api-client-generator.js +364 -424
- package/dist/generators/api-client-generator.js.map +1 -1
- package/dist/generators/base.d.ts.map +1 -1
- package/dist/generators/base.js +7 -25
- package/dist/generators/base.js.map +1 -1
- package/dist/generators/enum-generator.d.ts.map +1 -1
- package/dist/generators/enum-generator.js +30 -3
- package/dist/generators/enum-generator.js.map +1 -1
- package/dist/generators/hook-generator.d.ts +3 -17
- package/dist/generators/hook-generator.d.ts.map +1 -1
- package/dist/generators/hook-generator.js +51 -445
- package/dist/generators/hook-generator.js.map +1 -1
- package/dist/generators/naming.d.ts +10 -0
- package/dist/generators/naming.d.ts.map +1 -0
- package/dist/generators/naming.js +331 -0
- package/dist/generators/naming.js.map +1 -0
- package/dist/generators/object-generator.d.ts +0 -4
- package/dist/generators/object-generator.d.ts.map +1 -1
- package/dist/generators/object-generator.js +13 -101
- package/dist/generators/object-generator.js.map +1 -1
- package/dist/generators/primitive-generator.d.ts +1 -13
- package/dist/generators/primitive-generator.d.ts.map +1 -1
- package/dist/generators/primitive-generator.js +11 -76
- package/dist/generators/primitive-generator.js.map +1 -1
- package/dist/generators/projections.d.ts +10 -0
- package/dist/generators/projections.d.ts.map +1 -0
- package/dist/generators/projections.js +65 -0
- package/dist/generators/projections.js.map +1 -0
- package/dist/generators/schema-type.d.ts +23 -0
- package/dist/generators/schema-type.d.ts.map +1 -0
- package/dist/generators/schema-type.js +233 -0
- package/dist/generators/schema-type.js.map +1 -0
- package/dist/parsers/base.d.ts +2 -0
- package/dist/parsers/base.d.ts.map +1 -1
- package/dist/parsers/base.js +12 -2
- package/dist/parsers/base.js.map +1 -1
- package/dist/parsers/factory.d.ts.map +1 -1
- package/dist/parsers/factory.js +2 -1
- package/dist/parsers/factory.js.map +1 -1
- package/dist/parsers/openapi.d.ts +4 -0
- package/dist/parsers/openapi.d.ts.map +1 -1
- package/dist/parsers/openapi.js +107 -20
- package/dist/parsers/openapi.js.map +1 -1
- package/dist/plugins/branded-types.d.ts.map +1 -1
- package/dist/plugins/branded-types.js +231 -365
- package/dist/plugins/branded-types.js.map +1 -1
- package/dist/plugins/builtin.d.ts.map +1 -1
- package/dist/plugins/builtin.js +6 -141
- package/dist/plugins/builtin.js.map +1 -1
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +17 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/loader.d.ts +5 -1
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +42 -5
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/manager.d.ts.map +1 -1
- package/dist/plugins/manager.js +7 -7
- package/dist/plugins/manager.js.map +1 -1
- package/dist/plugins/performance-monitoring.d.ts +31 -1
- package/dist/plugins/performance-monitoring.d.ts.map +1 -1
- package/dist/plugins/performance-monitoring.js +146 -207
- package/dist/plugins/performance-monitoring.js.map +1 -1
- package/dist/plugins/request-deduplication.d.ts.map +1 -1
- package/dist/plugins/request-deduplication.js +151 -586
- package/dist/plugins/request-deduplication.js.map +1 -1
- package/dist/plugins/zod-validation.d.ts +23 -15
- package/dist/plugins/zod-validation.d.ts.map +1 -1
- package/dist/plugins/zod-validation.js +390 -268
- package/dist/plugins/zod-validation.js.map +1 -1
- package/dist/types/core.d.ts +20 -4
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/core.js +2 -1
- package/dist/types/core.js.map +1 -1
- package/dist/types/openapi.d.ts +14 -1
- package/dist/types/openapi.d.ts.map +1 -1
- package/docs/ADVANCED_PLUGINS_IMPLEMENTATION.md +24 -355
- package/docs/ADVANCED_PLUGIN_DEVELOPMENT.md +33 -309
- package/docs/API.md +80 -600
- package/docs/AUDIT.md +49 -0
- package/docs/CONFIGURATION.md +81 -722
- package/docs/FASTAPI_TUTORIAL.md +109 -1497
- package/docs/NAMING_MIGRATION.md +59 -0
- package/docs/PLUGINS.md +49 -687
- package/docs/PLUGIN_DEVELOPMENT.md +53 -720
- package/docs/REAUDIT.md +399 -0
- package/docs/RELEASING.md +88 -0
- package/docs/REMEDIATION.md +58 -0
- package/docs/superpowers/plans/2026-10-10-audit-remediation.md +113 -0
- package/package.json +114 -95
- package/dist/__tests__/setup.d.ts +0 -6
- package/dist/__tests__/setup.d.ts.map +0 -1
- package/dist/__tests__/setup.js +0 -30
- package/dist/__tests__/setup.js.map +0 -1
- package/dist/__tests__/test-config.d.ts +0 -36
- package/dist/__tests__/test-config.d.ts.map +0 -1
- package/dist/__tests__/test-config.js +0 -563
- package/dist/__tests__/test-config.js.map +0 -1
- package/dist/lib/api/api-client.d.ts +0 -71
- package/dist/lib/api/api-client.d.ts.map +0 -1
- package/dist/lib/api/api-client.js +0 -238
- package/dist/lib/api/api-client.js.map +0 -1
- package/dist/lib/api/barrel.d.ts +0 -4
- package/dist/lib/api/barrel.d.ts.map +0 -1
- package/dist/lib/api/barrel.js +0 -26
- package/dist/lib/api/barrel.js.map +0 -1
- package/dist/lib/api/hooks.d.ts +0 -36
- package/dist/lib/api/hooks.d.ts.map +0 -1
- package/dist/lib/api/hooks.js +0 -120
- package/dist/lib/api/hooks.js.map +0 -1
- package/dist/lib/api/index.d.ts +0 -4
- package/dist/lib/api/index.d.ts.map +0 -1
- package/dist/lib/api/index.js +0 -8
- package/dist/lib/api/index.js.map +0 -1
- package/dist/lib/api/types.d.ts +0 -366
- package/dist/lib/api/types.d.ts.map +0 -1
- package/dist/lib/api/types.js +0 -315
- package/dist/lib/api/types.js.map +0 -1
package/docs/REAUDIT.md
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# Schemantic re-audit
|
|
2
|
+
|
|
3
|
+
Date: 2026-10-10. Audited the current working tree, including the uncommitted corrections from the [previous audit](S:/Code/Node/Packages/schemantic/docs/AUDIT.md). Package version: 0.3.0. Host: Windows, Node 25.3.0, TypeScript 5.9.
|
|
4
|
+
|
|
5
|
+
## Verdict
|
|
6
|
+
|
|
7
|
+
The previous fixes remain effective for their covered regression cases. They do not establish that every affected feature is complete. The wider audit reproduced wrong-data caching, output overwrites, unusable generated types for valid schemas, lost response bodies, misleading validation, and failures under common consumer TypeScript settings.
|
|
8
|
+
|
|
9
|
+
The default types/client workflow works for the repository fixtures. Broad production-readiness and complete advanced-plugin claims are premature. Several public options and documented workflows are ineffective, partial, or explicitly unimplemented. Prioritize correctness and accurate contracts before adding more convenience features.
|
|
10
|
+
|
|
11
|
+
This re-audit adds evidence and a prioritized implementation plan. It does not apply production fixes. The agreed camelCase property migration remains [planned](S:/Code/Node/Packages/schemantic/docs/NAMING_MIGRATION.md); generated properties currently retain their wire names.
|
|
12
|
+
|
|
13
|
+
## Verification and evidence
|
|
14
|
+
|
|
15
|
+
| Check | Result | What it establishes |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `npm test -- --runInBand` | 14 suites, 184 tests passed; pretest clean build passed | Existing regression contracts, including previous fixes |
|
|
18
|
+
| `npm run lint` | Passed without warnings | Source lint rules |
|
|
19
|
+
| Six schemas × plain/Zod/hooks generation | All 18 cases generated and compiled | Fresh fixture output under strict TypeScript, `exactOptionalPropertyTypes`, and `noUncheckedIndexedAccess`; hook imports use React signature declarations |
|
|
20
|
+
| Generated CommonJS client, DOM types | Compiled | Basic browser-compatible type environment |
|
|
21
|
+
| Generated Node server client, no DOM lib | Compiled with installed Node typings | One server-side type environment |
|
|
22
|
+
| Bundler + `verbatimModuleSyntax` | Failed, TS1484 | Type/value import distinction is incorrect |
|
|
23
|
+
| `noUnusedLocals` / `noUnusedParameters` | Failed, TS6133 | Unused generated private helpers block consumers |
|
|
24
|
+
| NodeNext ESM generated output | Failed, TS2835 | Relative generated imports lack required extensions |
|
|
25
|
+
| Package ESM named import | Passed | Importing the package itself works on the audit host; this is separate from generated ESM output |
|
|
26
|
+
| Package dry run | 129 files; 152,671 compressed bytes, 704,899 unpacked bytes | CLI/declarations present; tests, helper fixtures, dependencies and audit probes absent from the archive inspected before this report was added |
|
|
27
|
+
| Additional runtime/consumer probes | Reproduced the findings below | Known bad behavior is recorded, not treated as a successful correctness test |
|
|
28
|
+
|
|
29
|
+
Reproduce against a freshly built `dist`:
|
|
30
|
+
|
|
31
|
+
```powershell
|
|
32
|
+
npm test -- --runInBand
|
|
33
|
+
npm run lint
|
|
34
|
+
node scripts/reaudit.cjs
|
|
35
|
+
node test-output/reaudit-edges/probe.cjs
|
|
36
|
+
node test-output/reaudit-dx/probe.cjs
|
|
37
|
+
node test-output/reaudit-dx/compile-probe.cjs
|
|
38
|
+
node test-output/reaudit-plugins/probe-20261010-feature-claims.cjs
|
|
39
|
+
npm pack --dry-run --ignore-scripts --json --offline --cache ./test-output/reaudit-dx/npm-cache
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The probe commands write only their audit scratch output; they do not modify production source. Their exit status indicates that the probe ran, not that every observed behavior was correct. Evidence:
|
|
43
|
+
|
|
44
|
+
- [Core generator, consumer compatibility and hook lifecycle evidence](S:/Code/Node/Packages/schemantic/test-output/reaudit-core/evidence.json), produced by [reaudit.cjs](S:/Code/Node/Packages/schemantic/scripts/reaudit.cjs).
|
|
45
|
+
- [OpenAPI edge-case evidence](S:/Code/Node/Packages/schemantic/test-output/reaudit-edges/summary.json), with input schemas, generated files and consuming code beside each case.
|
|
46
|
+
- [CLI evidence](S:/Code/Node/Packages/schemantic/test-output/reaudit-dx/results.json), [consumer diagnostics](S:/Code/Node/Packages/schemantic/test-output/reaudit-dx/compile-results.json), and [package inspection](S:/Code/Node/Packages/schemantic/test-output/reaudit-dx/pack.json).
|
|
47
|
+
- [Plugin observations](S:/Code/Node/Packages/schemantic/test-output/reaudit-plugins/results.jsonl), reproducible with the [plugin probe](S:/Code/Node/Packages/schemantic/test-output/reaudit-plugins/probe-20261010-feature-claims.cjs).
|
|
48
|
+
|
|
49
|
+
Limits: no mounted React application, real browser transport, live external FastAPI service, package installation from a published release, or Node 20/22/24 CI execution was performed. The hook harness executes generated state/dependency logic, but cannot establish real React StrictMode/concurrent-render behavior. Cross-project compilation and local HTTP observations are evidence for those exact contracts, not end-to-end certification of every framework. Some incomplete options below are source findings rather than runtime reproductions; those are labeled.
|
|
50
|
+
|
|
51
|
+
## Previous audit: closure check
|
|
52
|
+
|
|
53
|
+
Every previous audit area was revisited. “Covered fixes hold” means the previous regression tests passed again; it does not mean exhaustive closure of that feature.
|
|
54
|
+
|
|
55
|
+
| Previous area | Recheck | Remaining gap found in this pass |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| Type output | Covered fixes hold: literals, basic compositions, arrays, dictionaries, nullability, identifiers, runtime enum exports; fresh fixtures compile | Heterogeneous known properties plus dictionary entries, required-only composition branches, directional read/write properties, binary inputs and global-name collisions remain incorrect (R05–R07, R12) |
|
|
58
|
+
| References and filtering | Covered component/JSON Pointer, inherited parameter, dependency selection and generation-time invalid-ref tests hold | Path Item references silently omit endpoints; 3.1 reference sibling constraints are lost; public validation misses unresolved refs; external refs remain unsupported (R08, R13–R14) |
|
|
59
|
+
| Generation lifecycle | Repeated-call state reset, input preservation, configured plugin/custom-generator dispatch and exact collision tests hold | Case-insensitive/ancestor collisions, stale files, lost custom imports and swallowed plugin failures remain (R02, R14–R15) |
|
|
60
|
+
| Request transport | Covered path escaping, array query parameters, inherited header/cookie parameters, Headers merging and URL-encoded body tests hold | Default object query serialization, binary request typing and authorization key casing remain incorrect (R03, R07, R11) |
|
|
61
|
+
| Responses/retries | Covered JSON/text/Blob/204 and retry policy tests hold | Schema-less media and default-only responses lose bodies; multiple media types and XML produce type/runtime mismatches (R09–R10) |
|
|
62
|
+
| Hooks | Prefix/filename/argument/query-stability and stale-query fixes hold; all fixture hooks compile with React signatures | Concurrent mutation results, loading and reset behavior remain incorrect; mounted React lifecycle is unverified (R04) |
|
|
63
|
+
| Validation | Covered enum/null/union/dictionary/lazy-reference/cache-isolation tests hold | Zod allOf rejects valid objects; oneOf and common constraints are weakened; permissive response validation discards data (R06, R16) |
|
|
64
|
+
| Optional plugin output | Activation, validation alias, auth-state transition, mutation-cache bypass and disabled coalescing tests hold | Multi-interface branded output, guards, cache identity, per-endpoint stale policy and disabled timing output fail; regex/custom-key/statistics gaps are still open (R01, R06, R17–R18) |
|
|
65
|
+
| CLI | Covered ordinary command failure codes, precedence, output selection, local watch and version fixes hold | Interactive failure exits zero, init overwrites configuration, interactive negative defaults invert, config types are unchecked, and plugin loading is disconnected (R19–R22) |
|
|
66
|
+
| Packaging | Clean build, portable clean, test exclusion and package/lockfile engine alignment hold; archive inspection passes | CI size gate checks the wrong quantity; generated module compatibility is incomplete; support matrix has not run locally (R12, R24) |
|
|
67
|
+
| Previously disclosed follow-ups | Still open, not regressions | `generateQueries`, optional syntax flags, advanced parameter encodings, external refs, strict plugin errors, atomic output and several experimental helper options have not been implemented (R14–R18, capability table) |
|
|
68
|
+
| Naming migration | Plan remains available and consistent with the preference | camelCase properties and boundary conversion are not implemented; keep this visible in release planning |
|
|
69
|
+
|
|
70
|
+
## Prioritized reproduced findings
|
|
71
|
+
|
|
72
|
+
P1: wrong data, destructive behavior, misleading runtime validation, or a mainstream supported workflow cannot work. P2: substantial feature/compatibility failure with a narrower trigger. P3: convenience/documentation issue. These are implementation priorities, not CVSS scores.
|
|
73
|
+
|
|
74
|
+
### R01 — P1: request cache identity can return the wrong resource or tenant data
|
|
75
|
+
|
|
76
|
+
The request-deduplication helper hashes the request fingerprint to a small integer and uses that hash as identity. `/Aa` and `/BB` deterministically collide: the second factory is never called and the second request receives the first result. Separately, custom identity-bearing headers are discarded from the fingerprint. Same URL with `X-Api-Key: tenantA` and `X-Api-Key: tenantB` returns tenant A's result to B, with one factory call.
|
|
77
|
+
|
|
78
|
+
Source: [request-deduplication.ts](S:/Code/Node/Packages/schemantic/src/plugins/request-deduplication.ts:268), header filtering at [line 305](S:/Code/Node/Packages/schemantic/src/plugins/request-deduplication.ts:305). Evidence: `fingerprint-collision`, `header-separation` in plugin observations. This affects consumers explicitly using the helper; generated endpoints do not automatically invoke it.
|
|
79
|
+
|
|
80
|
+
Fix: use a canonical full request identity or collision-checked hash buckets; include all response-affecting headers and credential context by default. Avoid storing sensitive header values in diagnostics. Apply `customKeyGenerator` if exposed, and document how cookies/session scope affect caching. Add two-tenant and deterministic collision tests before further cache optimizations.
|
|
81
|
+
|
|
82
|
+
### R02 — P1: output collisions can overwrite types on Windows
|
|
83
|
+
|
|
84
|
+
`outputFileName: 'Types.ts'` passes the case-sensitive collision check. On the audit filesystem it overwrites `types.ts` with the client, drops the User interface, and reports success. `types.ts/client.ts` passes preflight, writes types, then fails while trying to turn that file into a directory, leaving partial output.
|
|
85
|
+
|
|
86
|
+
Source: [schemantic.ts](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:391), writes at [line 493](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:493). Evidence: `lifecycle:file-collision-case` and `lifecycle:file-collision-ancestor`.
|
|
87
|
+
|
|
88
|
+
Fix: validate all normalized destinations, filesystem case aliases and file/ancestor conflicts before any write. Stage complete output and replace only package-owned files after successful generation. Keep arbitrary user files safe.
|
|
89
|
+
|
|
90
|
+
### R03 — P1: authorization setters/clearers mishandle header casing
|
|
91
|
+
|
|
92
|
+
A client initialized with lowercase `authorization: 'Bearer original'` then `setAuthToken('new')` sends `Bearer original, Bearer new`. `clearAuthToken()` leaves the original credential active. Header merging already works for the covered cases; the mutation helpers use case-sensitive object keys.
|
|
93
|
+
|
|
94
|
+
Source: [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:667). Evidence: `auth-headers` local HTTP probe.
|
|
95
|
+
|
|
96
|
+
Fix: normalize defaults through `Headers` or another case-insensitive representation, and use the same representation for set/delete/merge. Assert the exact outgoing Authorization header after replacement and clearing.
|
|
97
|
+
|
|
98
|
+
### R04 — P1: mutation hooks publish stale state and reset does not invalidate pending work
|
|
99
|
+
|
|
100
|
+
Two mutations resolve in reverse order: the older result overwrites the newer result. If the first finishes while the second is pending, `loading` becomes false. Calling `reset()` while a mutation is pending clears state briefly, then the pending result repopulates it. Generated mutation hooks lack the request identity protection already present in query hooks.
|
|
101
|
+
|
|
102
|
+
Source: [hook-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/hook-generator.ts:116). Evidence: `hook:overlapping-mutation`, `hook:pending-mutation-loading`, `hook:reset-pending-mutation`.
|
|
103
|
+
|
|
104
|
+
Fix: specify whether state tracks the latest call or all active calls; implement that policy consistently. Reset/unmount should invalidate pending state updates. Test reverse success/failure ordering, overlapping loading, reset, unmount and client changes in a mounted React application as well as the existing harness. Returning each caller's own promise result is compatible with suppressing stale shared state updates.
|
|
105
|
+
|
|
106
|
+
### R05 — P1: request/response types ignore readOnly/writeOnly direction
|
|
107
|
+
|
|
108
|
+
A valid OpenAPI 3.0.3 User with required read-only `id` and required write-only `password` uses one shared type for requests and responses. A valid create request without server-owned `id` fails TS2345; responses are typed as requiring the request-only password.
|
|
109
|
+
|
|
110
|
+
Source: [schema-type.ts](S:/Code/Node/Packages/schemantic/src/generators/schema-type.ts:53), [object-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/object-generator.ts:191), body/response selection in [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:250). Evidence: `readonly-writeonly`.
|
|
111
|
+
|
|
112
|
+
Fix: derive directional request/response projections, including recursive references, compositions, required fields and validators. Do not infer that all OpenAPI 3.1 annotations have identical semantics without a documented policy. The tested defect is in the explicit 3.0.3 contract. See [OpenAPI 3.0.3 schema rules](https://spec.openapis.org/oas/v3.0.3.html#schema-object).
|
|
113
|
+
|
|
114
|
+
### R06 — P1: branded validation gives false assurance and multi-type output fails compilation
|
|
115
|
+
|
|
116
|
+
With two object schemas and default branded options, generated `types.ts` declares `AuthState` twice (TS2300), while generation reports success. For a User requiring an integer `id >= 1`, the guard accepts `{}` and `[]`, and the assertion accepts `{}`. The object guard checks little beyond a non-null object. Setting guard/assertion flags to false still emits them. Primitive branded schemas are not enhanced by the interface-only path.
|
|
117
|
+
|
|
118
|
+
Source: [branded-types.ts](S:/Code/Node/Packages/schemantic/src/plugins/branded-types.ts:300), shared declarations at [line 533](S:/Code/Node/Packages/schemantic/src/plugins/branded-types.ts:533). Evidence: `branded-multiple-types`, `branded-disable-options`.
|
|
119
|
+
|
|
120
|
+
Fix: emit shared declarations once and register every public export for collision checks. Either implement schema-backed guards/assertions or explicitly expose shallow branding checks under names that do not imply validation. Honor exposed feature switches and cover primitive IDs. Auth-state metadata remains client type-state metadata, not server authorization.
|
|
121
|
+
|
|
122
|
+
### R07 — P1: binary upload types reject actual binary values
|
|
123
|
+
|
|
124
|
+
OpenAPI `type: string, format: binary` maps to `string` in multipart and raw upload bodies. A multipart `{ file: Blob }` fails TS2322; passing a Blob to a raw binary upload fails TS2345. A manually constructed FormData can work around the multipart method's typing, but does not fulfill the claimed typed upload contract.
|
|
125
|
+
|
|
126
|
+
Source: [schema-type.ts](S:/Code/Node/Packages/schemantic/src/generators/schema-type.ts:64), [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:473). Evidence: `multipart-binary`, `raw-binary`.
|
|
127
|
+
|
|
128
|
+
Fix: model binary input according to request media, support binary parts and repeated parts, preserve caller-provided multipart boundaries, and test actual bytes/content types through a server. Keep JSON string encodings distinct from binary upload values. See [OpenAPI 3.0.3 data types](https://spec.openapis.org/oas/v3.0.3.html#data-types).
|
|
129
|
+
|
|
130
|
+
### R08 — P1: valid Path Item references silently produce no endpoints
|
|
131
|
+
|
|
132
|
+
A path whose item is `$ref: '#/components/pathItems/Thing'` generates successfully with zero endpoints, although the referenced item contains a GET operation. Component schema reference support does not extend to Path Item extraction.
|
|
133
|
+
|
|
134
|
+
Source: [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:100). Evidence: `pathitem-ref`.
|
|
135
|
+
|
|
136
|
+
Fix: resolve Path Items before operation extraction, preserve inherited parameters and path context, detect cycles, and explicitly diagnose unresolved/unsupported reference forms. Successful generation must not silently omit recognized operation locations. See [OpenAPI 3.1 Path Item Object](https://spec.openapis.org/oas/v3.1.0.html#path-item-object).
|
|
137
|
+
|
|
138
|
+
### R09 — P1: schema-less successful media responses lose their body
|
|
139
|
+
|
|
140
|
+
A successful `application/octet-stream` response with a media object `{}` is valid without a schema. The generator infers `void`; the client returns `undefined` and discards the bytes. A default-only JSON response that receives HTTP 200 also returns `undefined` (P2 for that narrower schema).
|
|
141
|
+
|
|
142
|
+
Source: [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:301), return selection at [line 328](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:328), void handling at [line 573](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:573). Evidence: `binary-no-schema`, `default-response`.
|
|
143
|
+
|
|
144
|
+
Fix: distinguish “no body” from “body schema unspecified.” Select response metadata by actual status with range/default fallback; infer a media-appropriate result, such as Blob or unknown JSON, where the schema is absent. Keep genuine 204/empty response behavior. See [OpenAPI 3.1 Media Type Object](https://spec.openapis.org/oas/v3.1.0.html#media-type-object) and [Responses Object](https://spec.openapis.org/oas/v3.1.0.html#responses-object).
|
|
145
|
+
|
|
146
|
+
### R10 — P2: multiple response media and XML break type/runtime agreement
|
|
147
|
+
|
|
148
|
+
Static return typing chooses the first documented media schema. Runtime decoding chooses the actual content type. A response declaring text first and JSON second is typed `string` but returns an object when JSON arrives. A declared XML string response returns a Blob.
|
|
149
|
+
|
|
150
|
+
Source: [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:288), decoding at [line 643](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:643). Evidence: `multi-media-response`, `xml-response`.
|
|
151
|
+
|
|
152
|
+
Fix: one shared response-selection model should drive both return types and decoding. Support text-based media consistently, unions or explicit response modes for multiple media, and a clear policy for unknown media. Do not promise an object XML parser unless one is implemented.
|
|
153
|
+
|
|
154
|
+
### R11 — P2: default object query serialization sends `[object Object]`
|
|
155
|
+
|
|
156
|
+
A query object `{ role: 'admin', active: true }` with the normal form/explode defaults becomes `filter=%5Bobject+Object%5D`, instead of separate property parameters. This is a basic object query case, beyond the advanced encodings already deferred in the previous audit.
|
|
157
|
+
|
|
158
|
+
Source: [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:523). Evidence: `object-query` local HTTP probe.
|
|
159
|
+
|
|
160
|
+
Fix: serialize parameters using location/style/explode metadata. Cover default object form encoding first, then explicit form-without-explode, deepObject, matrix/label and per-property form encoding. If an encoding is unsupported, fail or issue a clearly actionable diagnostic rather than stringify objects. See [OpenAPI 3.1 parameter serialization](https://spec.openapis.org/oas/v3.1.0.html#style-values).
|
|
161
|
+
|
|
162
|
+
### R12 — P1/P2: generated files fail normal consumer compiler settings and global-name collisions
|
|
163
|
+
|
|
164
|
+
Bundler output fails TS1484 because interface imports are emitted as value imports. `noUnusedLocals` fails TS6133 because every client includes unused private form helpers. NodeNext ESM fails TS2835 on extensionless relative imports/re-exports. These failures are reproduced in standalone consumers, not just string checks.
|
|
165
|
+
|
|
166
|
+
An enum component named `Blob` also shadows the platform Blob used by always-emitted form helpers, producing TS2359/TS2351 even when the API has no upload endpoint.
|
|
167
|
+
|
|
168
|
+
Source: [api-client-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:678), helper use at [line 608](S:/Code/Node/Packages/schemantic/src/generators/api-client-generator.ts:608), [schemantic.ts](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:524), [hook-generator.ts](S:/Code/Node/Packages/schemantic/src/generators/hook-generator.ts:35). Evidence: consumer matrix and `global-blob-name`.
|
|
169
|
+
|
|
170
|
+
Fix: distinguish type-only imports from required enum/runtime imports; emit helpers only when used; make module emission compatible with a declared bundler/Node ESM target; qualify platform globals or alias colliding imports. Run consumer compilation rather than merely compiling the generator itself. These rules are documented by [TypeScript verbatimModuleSyntax](https://www.typescriptlang.org/tsconfig/verbatimModuleSyntax.html) and [TypeScript module resolution](https://www.typescriptlang.org/docs/handbook/modules/reference.html). The official [Vite React TypeScript template](https://raw.githubusercontent.com/vitejs/vite/main/packages/create-vite/template-react-ts/tsconfig.app.json) uses settings relevant to these failures; no actual Vite app was mounted in this audit.
|
|
171
|
+
|
|
172
|
+
### R13 — P2: OpenAPI support is narrower than the stated contract
|
|
173
|
+
|
|
174
|
+
3.0.4, 3.1.1 and 3.1.2 documents are rejected by a fixed version allowlist. Parser metadata advertises YAML, but parsing YAML text calls JSON.parse and fails. OpenAPI 3.1 boolean schemas are rejected. A 3.1 components-only document is rejected for missing `paths`, even in types-only use.
|
|
175
|
+
|
|
176
|
+
Source: [openapi.ts parser](S:/Code/Node/Packages/schemantic/src/parsers/openapi.ts:33), JSON parsing at [line 51](S:/Code/Node/Packages/schemantic/src/parsers/openapi.ts:51), document structure at [line 178](S:/Code/Node/Packages/schemantic/src/parsers/openapi.ts:178). Evidence: `version-3.0.4`, `version-3.1.1`, `version-3.1.2`, `boolean-schema`, `components-without-paths`, `yaml-advertised`.
|
|
177
|
+
|
|
178
|
+
Fix: select the supported dialect by major/minor with appropriate patch compatibility; implement or remove the YAML capability claim; handle boolean schema semantics; allow components-only type generation when the dialect permits it. Publish a precise supported-keyword/media/reference table instead of “any OpenAPI 3.x.” See [OpenAPI 3.1 version semantics](https://spec.openapis.org/oas/v3.1.0.html#versions), [3.0.4](https://spec.openapis.org/oas/v3.0.4.html) and [3.1.2](https://spec.openapis.org/oas/v3.1.2.html).
|
|
179
|
+
|
|
180
|
+
### R14 — P2: validation and generation disagree; output is not transactional
|
|
181
|
+
|
|
182
|
+
`validate()` returns `isValid: true` for a missing component reference which `generate()` then rejects. A throwing plugin hook logs a warning but generation returns `success: true`, `errors: []`, `warnings: []`. Disabling hooks/client after a first generation reports only new types/index output while leaving old client/hooks files present. Ancestor collision failure also demonstrates partial writes.
|
|
183
|
+
|
|
184
|
+
Source: [schemantic.ts](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:152), separate reference pass at [line 234](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:234), [manager.ts](S:/Code/Node/Packages/schemantic/src/plugins/manager.ts:158). Evidence: `lifecycle:validate-vs-generate`, `plugin-failure-reporting`, `lifecycle:stale-output-files`.
|
|
185
|
+
|
|
186
|
+
Fix: share structural/reference/capability validation; include plugin diagnostics in the result and fail required hooks by default. An explicitly configured best-effort mode may continue, but must report incomplete output. Stage generation, maintain a manifest of owned files, replace atomically as far as the filesystem permits, and delete only stale owned output after success.
|
|
187
|
+
|
|
188
|
+
### R15 — P2: arbitrary custom plugin imports disappear
|
|
189
|
+
|
|
190
|
+
A registered plugin appends `import type { ExternalShape } from './external'` and an exported alias using it; it also declares the dependency. The core strips the import and regenerates imports only for a hardcoded package list. Generation succeeds; the consumer fails TS2304 even when `external.ts` exists.
|
|
191
|
+
|
|
192
|
+
Source: [schemantic.ts](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:453), known import list at [line 666](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:666). Evidence: `plugin:custom-import-preservation`.
|
|
193
|
+
|
|
194
|
+
Fix: give generated modules structured import records with module, symbol, alias and type/value usage; preserve/deduplicate them and rebase paths deliberately. A string dependency name cannot represent arbitrary import semantics. Validate plugin output with a consumer compile before claiming broad extensibility.
|
|
195
|
+
|
|
196
|
+
### R16 — P1/P2: Zod composition and constraints do not match the schema
|
|
197
|
+
|
|
198
|
+
`allOf` with two ordinary object branches `{ a }` and `{ b }` rejects valid `{ a, b }`, because each branch is strict before intersection. `oneOf: [number, integer]` accepts 1 even though it matches both branches. `minItems: 2` accepts `[]`; `uniqueItems` accepts duplicates; exclusive minimum accepts the boundary; an enum combined with minimum string length accepts a forbidden short enum value.
|
|
199
|
+
|
|
200
|
+
With response `strictMode: false`, invalid data returns `undefined`, while the documentation promises the original data. This quietly destroys the response in a purported permissive mode.
|
|
201
|
+
|
|
202
|
+
Source: [zod-validation.ts](S:/Code/Node/Packages/schemantic/src/plugins/zod-validation.ts:401), object strictness at [line 567](S:/Code/Node/Packages/schemantic/src/plugins/zod-validation.ts:567), permissive response path at [line 734](S:/Code/Node/Packages/schemantic/src/plugins/zod-validation.ts:734). Evidence: `zod-schema-constraints`, `permissive-validation`.
|
|
203
|
+
|
|
204
|
+
Fix: use composition semantics that do not falsely reject properties belonging to another branch, enforce exactly one branch for oneOf, compose enum and other constraints, implement array/exclusive bounds, and define whether unknown keys are allowed according to dialect/schema. Strict/permissive modes need explicit documented return/error contracts. Validators must agree with the accepted wire representation and future naming converters.
|
|
205
|
+
|
|
206
|
+
### R17 — P2: stale policy, regex invalidation and cache statistics are incomplete
|
|
207
|
+
|
|
208
|
+
An endpoint with `staleWhileRevalidate: false` still returns expired cached data under global stale defaults and does not refresh it in the reproduced case. Regex invalidation claims an invalidation but leaves the cached entry available. Cache hit rate remains literal zero after a hit. The previous stale path fix restored one path; it did not make endpoint policy complete.
|
|
209
|
+
|
|
210
|
+
Source: [request-deduplication.ts](S:/Code/Node/Packages/schemantic/src/plugins/request-deduplication.ts:427), refresh path at [line 610](S:/Code/Node/Packages/schemantic/src/plugins/request-deduplication.ts:610), invalidation at [line 637](S:/Code/Node/Packages/schemantic/src/plugins/request-deduplication.ts:637). Evidence: `endpoint-no-stale`, `regex-invalidation`.
|
|
211
|
+
|
|
212
|
+
Fix: enforce endpoint policy before returning expired data, retain canonical identity metadata for invalidation, implement real hit/miss/eviction counters, and test TTL boundaries with controlled time. Source-only follow-up: `customKeyGenerator` is declared but unused, and URL-string invalidation does not robustly match identities containing query/header context.
|
|
213
|
+
|
|
214
|
+
### R18 — P2: a documented monitoring switch generates broken exports
|
|
215
|
+
|
|
216
|
+
With `enableTiming: false`, generation succeeds but index exports reference absent `PerformanceMonitor`, `getPerformanceStats` and `clearPerformanceStats` (TS2305). Conditional helpers and advertised exports are out of sync.
|
|
217
|
+
|
|
218
|
+
Source: [performance-monitoring.ts](S:/Code/Node/Packages/schemantic/src/plugins/performance-monitoring.ts:469), exports at [line 501](S:/Code/Node/Packages/schemantic/src/plugins/performance-monitoring.ts:501). Evidence: `monitoring-disabled-timing`.
|
|
219
|
+
|
|
220
|
+
Fix: derive imports, declarations and exports from the same active feature graph. Compile supported option combinations. Further monitoring limitations are source findings in the capability table below.
|
|
221
|
+
|
|
222
|
+
### R19 — P1: init overwrites existing configuration without an overwrite option
|
|
223
|
+
|
|
224
|
+
Running `init --yes` in a directory with an existing configuration replaces it with defaults and reports success. No explicit force/overwrite flag is required. The interactive write uses the same unconditional behavior.
|
|
225
|
+
|
|
226
|
+
Source: [CLI](S:/Code/Node/Packages/schemantic/src/cli/index.ts:829). Evidence: `init overwrites existing`.
|
|
227
|
+
|
|
228
|
+
Fix: use exclusive creation by default, report the existing path, and require an explicit overwrite operation. Consider a separate validated merge/update workflow. Test that a custom existing configuration remains byte-for-byte unchanged when overwrite was not requested.
|
|
229
|
+
|
|
230
|
+
### R20 — P2: interactive command status and defaults are inconsistent
|
|
231
|
+
|
|
232
|
+
Interactive generation of a missing source prints failure but exits 0. Enter at `Generate React hooks? (y/N)` produces `generateHooks: true`; normal defaults correctly use false. A user following defaults therefore receives a React dependency unexpectedly.
|
|
233
|
+
|
|
234
|
+
Source: [CLI result handling](S:/Code/Node/Packages/schemantic/src/cli/index.ts:701), [promptBoolean](S:/Code/Node/Packages/schemantic/src/cli/index.ts:856). Evidence: `interactive missing source exit`, `empty answers init config`.
|
|
235
|
+
|
|
236
|
+
Fix: route interactive and ordinary commands through the same handler/status logic, and make prompt defaults explicit parameters. Ensure Enter agrees with the displayed capitalized option. Invalid/unsupported choices need actionable nonzero failures in automation.
|
|
237
|
+
|
|
238
|
+
### R21 — P2: configuration is weakly validated and defaults are hard to consume
|
|
239
|
+
|
|
240
|
+
JSON containing `generateTypes: "false"`, `generateApiClient: "false"`, `useStrictTypes: "false"`, an unknown property and `generateQueries: true` is accepted; truthy strings generate types/client and the unsupported option has no effect. In TypeScript, `new Schemantic({ schemaFile, outputDir })` fails TS2345 because public config requires the defaulted flags even though runtime merges defaults.
|
|
241
|
+
|
|
242
|
+
A generated conventional config is not automatically discovered by bare `generate`. `validate --config` is rejected, so validation cannot reuse the generation source configuration. These last two are DX improvements rather than an asserted existing auto-discovery feature.
|
|
243
|
+
|
|
244
|
+
Source: [CLI config loader](S:/Code/Node/Packages/schemantic/src/cli/index.ts:494), [SchemanticConfig](S:/Code/Node/Packages/schemantic/src/types/core.ts:19), [constructor](S:/Code/Node/Packages/schemantic/src/core/schemantic.ts:45). Evidence: `invalid config accepted`, `minimal programmatic defaults`, `config autodiscovery`, `validate cannot reuse config`.
|
|
245
|
+
|
|
246
|
+
Fix: one validated config contract shared by CLI/library, an ergonomic input type and fully resolved internal type, consistent discovery/path resolution, and explicit diagnostics for unknown fields and unsupported settings. Keep deterministic precedence: defaults, discovered/explicit config, explicit CLI overrides. Do not change established explicit source precedence accidentally.
|
|
247
|
+
|
|
248
|
+
### R22 — P2: CLI custom plugin loading is disconnected from generation
|
|
249
|
+
|
|
250
|
+
`plugin load ./plugin.cjs` reports success. A later generation with `--plugins dx-plugin` fails “Unknown plugin.” Loading a package name is treated as a filesystem path rather than invoking the package-loading API. The advertised workflow cannot configure a custom plugin for the actual generation process.
|
|
251
|
+
|
|
252
|
+
Source: [CLI plugin load](S:/Code/Node/Packages/schemantic/src/cli/index.ts:309), [built-in resolution](S:/Code/Node/Packages/schemantic/src/cli/index.ts:543), [loader.ts](S:/Code/Node/Packages/schemantic/src/plugins/loader.ts:19). Evidence: `load local custom plugin`, `generate after plugin load`, `plugin package advertised`.
|
|
253
|
+
|
|
254
|
+
Fix: resolve file/package plugin entries from the active config during the same generation invocation, with deterministic relative paths and plugin option validation. Either persist registration explicitly or describe `plugin load` as an inspection command; process-local loading must not imply a lasting installation.
|
|
255
|
+
|
|
256
|
+
### R23 — P2/P3: published tutorials and flags describe APIs that do not exist
|
|
257
|
+
|
|
258
|
+
Compiled tutorial calls to `setDefaultHeader`/`removeDefaultHeader` fail TS2339. Mutation examples use callbacks/isLoading incompatible with the implemented hook signature/`loading`; query examples show unsupported `enabled`. The tutorial describes TanStack behavior although first-party hooks use plain React. It recommends Node 16 while the package requires Node 20+.
|
|
259
|
+
|
|
260
|
+
Configuration docs demonstrate TypeScript config files, but the CLI explicitly supports JSON/CommonJS `.js`/`.cjs` only. Some guides still enable the unavailable built-in `react-hooks` plugin. Plugin-development docs list hook names/CLI extensions not in the current `SchemanticPlugin` interface. `init --template does-not-exist` succeeds while ignoring the template. `--verbose` is declared without behavior (source finding); `--fix` correctly fails explicitly but still appears as a supported repair feature in help/examples. `help bogus` exits 0.
|
|
261
|
+
|
|
262
|
+
Sources: [FASTAPI_TUTORIAL.md](S:/Code/Node/Packages/schemantic/docs/FASTAPI_TUTORIAL.md:840), [CONFIGURATION.md](S:/Code/Node/Packages/schemantic/docs/CONFIGURATION.md:53), [PLUGIN_DEVELOPMENT.md](S:/Code/Node/Packages/schemantic/docs/PLUGIN_DEVELOPMENT.md:20), [plugin interface](S:/Code/Node/Packages/schemantic/src/types/core.ts:222), [CLI template declaration](S:/Code/Node/Packages/schemantic/src/cli/index.ts:167). Evidence: DX CLI/compile probes plus source comparison.
|
|
263
|
+
|
|
264
|
+
Fix: select one public contract and execute its examples in CI. Remove unsupported flags/examples immediately or implement them with real acceptance tests. A correct README disclaimer does not repair conflicting linked guides. Audit the “Production Ready”/“Zero Configuration” language and stale version wording in [README.md](S:/Code/Node/Packages/schemantic/README.md:13).
|
|
265
|
+
|
|
266
|
+
### R24 — P2/P3, source finding: release verification gates are misleading
|
|
267
|
+
|
|
268
|
+
The CI package size guard reads the last stdout line of npm pack (the archive filename) and compares that value as if it were a size; it does not enforce archive bytes. Local dry-run inspection passes, but does not prove that release gate works. CI targets Ubuntu Node 20/22/24; Windows/macOS generated-file behavior is not covered.
|
|
269
|
+
|
|
270
|
+
Source: [ci-cd.yml](S:/Code/Node/Packages/schemantic/.github/workflows/ci-cd.yml:77). Additional source risk: [publish:gh](S:/Code/Node/Packages/schemantic/package.json:35) mutates package name before publishing and restores it only if the publish command succeeds. This command was not executed.
|
|
271
|
+
|
|
272
|
+
Fix: parse npm pack JSON `size`/`unpackedSize` with numeric assertions, verify packed content and installed-package consumers, add platform-sensitive output tests, and make publish preparation/restoration transactional. Do not publish during audit validation.
|
|
273
|
+
|
|
274
|
+
## Feature claim inventory
|
|
275
|
+
|
|
276
|
+
“Implemented, covered” is bounded by the tests described above. “Partial” means real code exists but the advertised feature is incomplete. “Stub/ineffective” means an exposed path does no promised work. Proposed capabilities are not existing features.
|
|
277
|
+
|
|
278
|
+
| Claimed/exposed capability | Status | Finding or boundary |
|
|
279
|
+
| --- | --- | --- |
|
|
280
|
+
| OpenAPI JSON from file/URL/in-memory input | Implemented, covered for repository schemas | URL fixture/live tests are not proof for every server; YAML/dialect limits below |
|
|
281
|
+
| Any OpenAPI 3.x / latest compatible patches | Partial | Version allowlist rejects supported-dialect patch releases; boolean/components-only cases fail (R13) |
|
|
282
|
+
| YAML parser support | Claimed, unimplemented | Metadata says YAML; implementation JSON parses it (R13) |
|
|
283
|
+
| Interfaces, aliases, enums, arrays, nullable types | Implemented with important gaps | Directional types, dictionaries/compositions, binary/global names (R05, R07, R12 and below) |
|
|
284
|
+
| Composition/JSON Schema constraints | Partial | Required-only allOf and reference siblings weakened; Zod constraints incomplete (R16) |
|
|
285
|
+
| Local schema refs/inherited parameters/filter dependency closure | Implemented, covered for tested cases | Path Item refs missing; external file/remote refs unsupported (R08) |
|
|
286
|
+
| Schema validation | Partial | Structural checks exist; unresolved refs and unsupported-feature fidelity inconsistent (R14) |
|
|
287
|
+
| Fetch clients/basic JSON and scalar/array transport | Implemented, covered for tested cases | Object styles, binary media, response selection and auth mutations incomplete |
|
|
288
|
+
| Headers/cookies/authentication | Partial | Basic parameter transport works; casing bug; security-scheme-driven auth conveniences not generated |
|
|
289
|
+
| Upload/download support | Partial | Typed binary requests and schema-less downloads fail (R07, R09) |
|
|
290
|
+
| Retry/timeout/request options | Implemented, covered for existing cases | Browser abort/unmount behavior and every environment not exercised |
|
|
291
|
+
| First-party React hooks | Implemented, partial | Queries covered; mutation lifecycle wrong; not a TanStack adapter (R04, R23) |
|
|
292
|
+
| Legacy `react-hooks` plugin | Placeholder, unavailable as a built-in | Its after-client path contains placeholder behavior; use first-party `generateHooks` and correct stale docs |
|
|
293
|
+
| `generateQueries` | Stub/ineffective | `true` with types/client disabled succeeds with an empty index and zero query generation |
|
|
294
|
+
| `useOptionalChaining` / `useNullishCoalescing` | Inconsistent/ineffective in output | Previous disclosed gap; no uniformly applied emission contract |
|
|
295
|
+
| Naming, prefix/suffix, wire-key preservation | Implemented, covered for existing modes | Application-property camelCase + runtime conversion remains planned |
|
|
296
|
+
| Types-only output | Implemented, covered | Components-only 3.1 parser restriction is unnecessary; future camelCase mode needs converters |
|
|
297
|
+
| Client-only output | Partial as a fresh project workflow | Named schemas require an existing compatible types file; users must manually request both |
|
|
298
|
+
| Watch local schema | Implemented, covered by previous regression | Remote watch intentionally unsupported; init/config DX remains inconsistent |
|
|
299
|
+
| Config activation and programmatic custom generators | Implemented, covered for existing probes | Weak config validation, required default flags, lost arbitrary imports (R15, R21) |
|
|
300
|
+
| CLI custom plugin installation/resolution | Partial/broken workflow | Load success cannot be used by generation; package resolution path unused (R22) |
|
|
301
|
+
| Plugin lifecycle hooks | Partial | Current hooks execute but swallow exceptions; docs advertise absent hooks/extensions |
|
|
302
|
+
| `validation` alias / Zod schemas | Implemented, partial | Zod 4 consumer requirement; composition/constraint correctness gaps (R16) |
|
|
303
|
+
| Automatic endpoint validation/middleware integration | Not implemented as claimed | Helpers are emitted; endpoints do not automatically route through them; consumer must integrate |
|
|
304
|
+
| Permissive validation response pass-through | Incorrect | Invalid response becomes undefined (R16) |
|
|
305
|
+
| Zod `optimizeBundle` | Ineffective, source finding | Declared but no implementation consuming the option |
|
|
306
|
+
| Zod LRU/TTL generation memoization | Partial/misdescribed, source finding | Generation schema/memo maps are unbounded; separate runtime validation cache does not establish that claim |
|
|
307
|
+
| Zod `customErrorMessages` | Partial/misdescribed, source finding | Used as describe metadata rather than configuring validation failure messages |
|
|
308
|
+
| Branded objects/auth type-state helpers | Implemented, partial | Duplicate shared declarations; shallow guards; false feature switches; primitive path missing (R06) |
|
|
309
|
+
| Branded nested/schema constraint validation | Not fully implemented | Metadata does not make runtime guards enforce those constraints |
|
|
310
|
+
| `strict-mode` plugin | Ineffective enhancement | Adds metadata the emitter does not consume and an import stripped by assembly; expected helper output absent in probe |
|
|
311
|
+
| Deduplication/caching for manual integration | Implemented, unsafe for some requests | Identity collisions/header omission; mutation bypass and disabling coalescing work (R01) |
|
|
312
|
+
| Stale revalidation/endpoint cache policy | Partial | Disabled endpoint stale policy still serves expired entries (R17) |
|
|
313
|
+
| Regex invalidation/custom key callback | Stub/ineffective | Regex does no removal; callback exposed but unused |
|
|
314
|
+
| Cache hit/eviction statistics | Stub/partial | Literal zeros instead of tracked counters (R17) |
|
|
315
|
+
| Timing helpers | Implemented, partial | Disabled option leaves invalid exports (R18); no automatic endpoint instrumentation |
|
|
316
|
+
| Metrics TTL/storage limit | Partial/ineffective, source finding | TTL declared but not used for expiry; analyzer storage does not consistently honor max storage |
|
|
317
|
+
| `generateReports` | Ineffective output claim, source finding | Computes/discards a report rather than producing an artifact |
|
|
318
|
+
| Bundle/dependency size analysis | Approximation, misdescribed | Counts generated source bytes and synthetic dependency estimates, not an actual bundled artifact |
|
|
319
|
+
| Memory monitoring/historical regression detection | Partial/misdescribed | Generator-process observation/current duration thresholds do not establish client monitoring or historical regressions |
|
|
320
|
+
| Advanced utility factory exports/examples | Incomplete public API | Helpers not re-exported by root; package exports block documented deep imports; memoized validation example signature disagrees with implementation |
|
|
321
|
+
| `init --template`, `--verbose` | Ignored/ineffective | No template dispatch or verbosity behavior |
|
|
322
|
+
| `validate --fix` | Explicitly unimplemented | Previously corrected failure reporting; schema repair still not a feature |
|
|
323
|
+
| TypeScript config files | Unimplemented | Documentation contradicts JSON/CommonJS-only loader |
|
|
324
|
+
| Published percentage improvements | Unsupported quantitative claims | No evidence for documented 60–80% request savings / 95% error reductions; do not present as measured package results |
|
|
325
|
+
|
|
326
|
+
Additional type fidelity evidence: `dictionary-known-property` rejects a valid `{ name: 'valid', score: 2 }` because output is `{ name: string } & Record<string, number>`, which also constrains `name` to number. `allof-required-only` and `ref-required-sibling` permit `{}` despite a required `id`. Sources: [schema-type.ts](S:/Code/Node/Packages/schemantic/src/generators/schema-type.ts:27), dictionary construction at [line 57](S:/Code/Node/Packages/schemantic/src/generators/schema-type.ts:57). The [JSON Schema additionalProperties rules](https://json-schema.org/understanding-json-schema/reference/object#additional-properties) exclude explicitly declared properties from the additional-property constraint. TypeScript cannot directly express every such index restriction: choose a documented sound approximation plus runtime validation/diagnostics, rather than emitting an impossible intersection.
|
|
327
|
+
|
|
328
|
+
Source-only plugin findings are grounded in [zod-validation.ts](S:/Code/Node/Packages/schemantic/src/plugins/zod-validation.ts:74), [branded-types.ts](S:/Code/Node/Packages/schemantic/src/plugins/branded-types.ts:121), [builtin.ts](S:/Code/Node/Packages/schemantic/src/plugins/builtin.ts:147), [performance-monitoring.ts](S:/Code/Node/Packages/schemantic/src/plugins/performance-monitoring.ts:530), [plugins/index.ts](S:/Code/Node/Packages/schemantic/src/plugins/index.ts:5), and claims in [ADVANCED_PLUGINS_IMPLEMENTATION.md](S:/Code/Node/Packages/schemantic/docs/ADVANCED_PLUGINS_IMPLEMENTATION.md:13). Retiring an ineffective option/plugin is preferable to keeping a feature name with no observable effect.
|
|
329
|
+
|
|
330
|
+
## Cross-project suitability
|
|
331
|
+
|
|
332
|
+
| Consumer/project shape | Current assessment | Needed release gate |
|
|
333
|
+
| --- | --- | --- |
|
|
334
|
+
| Plain strict TS/CommonJS generated client | Fresh simple and repository fixture compilation passes | Retain current regression suite and real request/response probes |
|
|
335
|
+
| Node server without DOM lib | One @types/node environment compiles | Run supported Node majors and actual fetch/upload/error behavior |
|
|
336
|
+
| Vite-style TS bundler with verbatim imports/no-unused checks | Reproduced compilation failures | Compile an official-template consumer with unchanged compiler settings |
|
|
337
|
+
| Node ESM/NodeNext project | Package import works; generated module graph fails | Compile and execute emitted JS in a `type: module` package |
|
|
338
|
+
| React app | Hook files compile against signature stubs; query harness cases pass; mutations fail | Mounted React tests including StrictMode, remount, overlap, reset and cancellation |
|
|
339
|
+
| Vue/Svelte/plain browser app | Framework-neutral core is a reasonable fit; no framework application run | Consumer compile/browser smoke without React dependency; hook default must remain off |
|
|
340
|
+
| FastAPI apps using typical schemas | Six snapshots pass tested modes | Representative live schema/service round trips, read/write projections, file uploads, dictionaries and nullable compositions |
|
|
341
|
+
| Other OpenAPI producers / modular schemas | Partial | Path Item refs, YAML, compatible patches and explicit unsupported-keyword diagnostics; external refs if included in scope |
|
|
342
|
+
| Windows output filesystem | Confirmed case alias overwrite | Case/ancestor/path-reserved-name tests and staged writes |
|
|
343
|
+
| Published package consumer | Pack manifest and host import pass | Temporary installed-pack consumer tests; supported-platform/Node CI; no reliance on repository-only paths |
|
|
344
|
+
|
|
345
|
+
Do not recommend weakening consumer compiler settings as the primary workaround. Generated output should adapt to mainstream settings without forcing projects to change their stack.
|
|
346
|
+
|
|
347
|
+
## UX/DX simplification and default decisions
|
|
348
|
+
|
|
349
|
+
1. **Make one command produce a complete usable graph.** Keep default types + client + index, hooks off. An explicitly selected client should include required types automatically, or require a validated explicit external types module. Avoid a “successful” fresh output that needs undisclosed previous files.
|
|
350
|
+
2. **Resolve configuration once.** Use a small ergonomic public input type, a validated resolved internal config, conventional discovery, and relative paths anchored to the config file. Let generate/validate/watch use the same source/config contract. Show effective source/output/plugin selection in verbose mode once verbosity is real.
|
|
351
|
+
3. **Make interactive defaults identical to noninteractive defaults.** Enter must honor `(y/N)`. Init must protect existing files. Choose meaningful template names only after templates exist; reject unknown names. Automatable commands need reliable exit codes and concise error messages.
|
|
352
|
+
4. **Favor zero surprise dependencies.** Plain clients use fetch without requiring React. Hooks remain explicit. Explain/install-check Zod only when enabled. Expose supported plugin helper APIs through package exports rather than undocumented repository/deep paths.
|
|
353
|
+
5. **Use explicit unsupported-feature diagnostics.** Reject active no-op settings until implemented or remove/deprecate them. Identify schema path and missing capability instead of success with omitted endpoints, incorrect values, or empty query output.
|
|
354
|
+
6. **Keep the agreed naming migration.** PascalCase type/class/interface names; camelCase methods/locals and future application properties by default; `propertyNaming: "preserve"` opt-out. This needs generated schema-aware serializers/deserializers, preserving wire keys, dictionary keys, enum values, nullability and binary objects. Renaming only the TS property is not a complete feature. See the existing migration plan for acceptance details.
|
|
355
|
+
7. **Choose one hook contract.** The current product is a plain React hook layer. Document that accurately and harden it. If users need TanStack features, provide a separate optional adapter with its real options, query keys, invalidation, mutation callbacks and dependency requirements. `generateQueries` should not remain an undocumented empty switch.
|
|
356
|
+
8. **Reduce overlapping plugins/options.** Keep one validation engine with an alias for compatibility; strict output is already a core default. Remove an ineffective strict-mode plugin unless it adds defined behavior. Derive plugin imports/exports from enabled capabilities rather than independently assembled strings.
|
|
357
|
+
9. **Make generated files explain themselves.** A small header should identify generator version, source and chosen compatibility/naming mode. A manifest should track owned files and optional name mappings. Avoid timestamps in normal output if they create needless diffs.
|
|
358
|
+
10. **Make examples executable.** Maintain a small real FastAPI/client example, a strict bundler consumer and a Node ESM consumer. Compile documentation snippets against the same generated output and expose exact implemented APIs, not prospective ones.
|
|
359
|
+
|
|
360
|
+
These are recommendations, not changes made by this audit. Auto-discovery and template support can remain opt-in/absent if their absence is documented, but advertised no-op behavior should be removed immediately.
|
|
361
|
+
|
|
362
|
+
## Missing functionality aligned with the package goal
|
|
363
|
+
|
|
364
|
+
### Essential for a dependable typed FastAPI/OpenAPI client
|
|
365
|
+
|
|
366
|
+
- Shared schema/operation intermediate representation covering direction, resolved references, naming, parameter serialization, media/status selection, validation and plugin imports. This reduces duplicated interpretation across generators and prevents static/runtime drift.
|
|
367
|
+
- Correct request/response projections, binary/media typing, default response handling, required/composition semantics and dictionary modeling. These repair the package's core promise rather than expanding into another product.
|
|
368
|
+
- A declared dialect/support matrix with compatible patch handling, capability diagnostics and a reference-resolution policy. Local external-file refs and YAML materially improve reuse across modular OpenAPI projects; remote refs need a separate explicit policy and tests.
|
|
369
|
+
- Module-aware, type-only import generation and dependency-complete output, verified against real consumer configurations.
|
|
370
|
+
- Safe output ownership/transactional lifecycle, shared validation, and truthful plugin failure reporting.
|
|
371
|
+
- Reliable case-insensitive header operations and schema/security-scheme metadata for supported auth flows. Common bearer/API-key helpers are useful; full OAuth login orchestration is not required to fix the current client contract.
|
|
372
|
+
- Mounted hook lifecycle tests and a defined mutation/reset/cancellation contract.
|
|
373
|
+
|
|
374
|
+
### Valuable after correctness, with explicit product decisions
|
|
375
|
+
|
|
376
|
+
- Schema-aware camelCase converters and preservation mode already requested; share them with Zod/hooks/media handling.
|
|
377
|
+
- Optional wired client middleware for validation, cache and timing, so enabling a plugin can have a documented observable effect. Integration must respect cache identity, cancellation, mutation policy and error semantics. Alternatively, honestly ship explicit helper libraries with complete public APIs.
|
|
378
|
+
- Rich typed response mode exposing status/headers and a structured HTTP error with status, headers and parsed/raw body. Useful for pagination, rate limits and non-JSON errors; validate current error behavior before selecting the new API.
|
|
379
|
+
- Per-call typed serialization/response overrides for media ambiguity and unusual servers; avoid forcing arbitrary unknown casts as the normal path.
|
|
380
|
+
- A real TanStack adapter if query-library integration is a product goal, or retirement of `generateQueries` and contradictory examples.
|
|
381
|
+
- Config discovery, `defineConfig`/typed config assistance, inspect/effective-config output, supported templates and a check mode for generated-output drift.
|
|
382
|
+
- Working cache invalidation/key callbacks/statistics and genuine exported monitoring/report artifacts if those features remain advertised. Use measured benchmark results before publishing performance percentages.
|
|
383
|
+
|
|
384
|
+
Callbacks/webhooks, complete OAuth authorization UI, XML-to-object parsing, and adapters for every framework are possible expansions. Their absence is not automatically a defect in a FastAPI-focused type/client generator. Prioritize evidence of target-user need and make scope explicit.
|
|
385
|
+
|
|
386
|
+
## Implementation order and acceptance gates
|
|
387
|
+
|
|
388
|
+
| Phase | Work | Required evidence before considering it complete |
|
|
389
|
+
| --- | --- | --- |
|
|
390
|
+
| 1. Protect data and trust | R01–R04, R06, R19; plugin exception reporting; remove inaccurate availability claims | Distinct-resource/tenant requests never share results; exact auth replacement/clear; no output/config overwrites; valid branded output and honest guards; overlap/reset/unmount contract tests; failed required plugins return failure |
|
|
391
|
+
| 2. Make generated output portable | R12, R15, R21; complete output graph; config/dependency/export model | Strict bundler with verbatim/no-unused and NodeNext ESM consumers compile and execute; platform name collisions handled; custom imports retained; minimal typed config works; wrong config types/unknown active settings diagnosed |
|
|
392
|
+
| 3. Complete target OpenAPI contracts | R05, R07–R11, R13, R16; dictionary/composition required semantics | Compiled request/response consumers plus local server bytes/status/media/query checks; valid schemas accepted; invalid validator inputs rejected; unsupported cases explicitly reported |
|
|
393
|
+
| 4. Make lifecycle/plugins consistent | R14, R17–R18, R20, R22; helper integration or truthful helper-only APIs | Atomic/staged failure leaves old output intact; only stale owned files removed; shared validation; option combinations compile; TTL/invalidation/statistics assertions; plugin resolution works in the generation process; interactive parity |
|
|
394
|
+
| 5. Ship naming migration | Existing naming plan; generated wire/application projections/converters | Both naming modes compile; request/response round trips preserve wire bytes; dictionaries/enums/binary values preserved; normalized collisions diagnosed; plugins/hooks/validators use the same naming graph |
|
|
395
|
+
| 6. Finish DX, documentation and release gates | R23–R24; examples, config discovery, declared compatibility matrix | Every documented snippet compiles/runs; Node 20/22/24 and platform-sensitive CI pass; packed/installed consumers pass; size gate reads actual bytes; unsupported claims/options removed or implemented |
|
|
396
|
+
|
|
397
|
+
Keep focused regression probes for each reproduced defect, but replace audit observations with assertions as fixes land. Add pairwise plugin/option coverage where features interact; exhaustive independent flag counts are less useful than validating real generated module graphs. Preserve the existing 184-test gate and all 18 fresh fixture compile cases.
|
|
398
|
+
|
|
399
|
+
The exit criterion is a truthful support contract backed by consuming-code and runtime tests. A green generator build or string snapshot alone is insufficient for claims about generated applications, wire compatibility, runtime validation or caching.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Releasing schemantic
|
|
2
|
+
|
|
3
|
+
Everyday releases start with `npm run release:prepare -- <patch|minor|major|exact-version>` and finish by publishing a matching GitHub Release. Preparation is local; publication happens only after the release verification workflow succeeds.
|
|
4
|
+
|
|
5
|
+
## One-time setup
|
|
6
|
+
|
|
7
|
+
Merge these workflows and scripts into the default branch before using the release workflow. In GitHub, create an environment named `npm`. If desired, add a required reviewer as the final publication approval. Environment deployment rules must allow the version tags used by this workflow.
|
|
8
|
+
|
|
9
|
+
In the existing `schemantic` package's npm settings, add a GitHub Actions trusted publisher:
|
|
10
|
+
|
|
11
|
+
| Setting | Value |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Organization or user | `Cstannahill` |
|
|
14
|
+
| Repository | `schemantic` |
|
|
15
|
+
| Workflow filename | `release.yml` |
|
|
16
|
+
| Environment | `npm` |
|
|
17
|
+
| Allowed action | Direct `npm publish` |
|
|
18
|
+
|
|
19
|
+
No `NPM_TOKEN` secret is used. The publisher runs on GitHub-hosted Ubuntu with Node 24, pinned npm 11.12.1, and `id-token: write`; npm requires at least Node 22.14 and npm 11.5.1. Configure trust when ready to release: unused new publisher configurations currently expire after two days. Keep the package repository URL accurate for provenance. See [npm's trusted publishing setup](https://docs.npmjs.com/trusted-publishers/) for account-side settings.
|
|
20
|
+
|
|
21
|
+
Configure branch protection to require the `Required checks` job from `CI / Verify` once GitHub has reported its exact check name. It aggregates lint/tests/coverage, all compatibility jobs, fixture compilation, packed-consumer verification, live integration, and the dependency audit. CodeQL reports separately. Protect `v*` tags against updates/deletion so release identity remains stable between validation and publication. These repository/account settings are not created by local source edits.
|
|
22
|
+
|
|
23
|
+
## Prepare and publish
|
|
24
|
+
|
|
25
|
+
1. Write useful notes under `## [Unreleased]` in `CHANGELOG.md`. Review and commit the implementation first. Preparation requires a clean Git working tree; its dry run also works while changes are pending.
|
|
26
|
+
2. Preview the next version:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm run release:prepare -- minor --dry-run
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. Prepare it:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npm run release:prepare -- minor
|
|
36
|
+
npm run release:check
|
|
37
|
+
npm run release:notes
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This updates only the manifest version, both lockfile version fields, and the changelog. Unreleased notes move into a dated release section. Nothing is committed, tagged, pushed, or published. Exact versions are accepted, must be higher than the current version, and cannot include build metadata.
|
|
41
|
+
|
|
42
|
+
4. Review those three files, commit them, and merge them into the default branch through the normal PR checks. The version stays `0.3.0` until preparation is explicitly run. The current naming default changes warrant a minor release such as `0.4.0` while this package is pre-1.0; do not reuse the already published `0.3.0`.
|
|
43
|
+
5. In GitHub's **Releases → Draft a new release**, use the exact tag `v<package-version>` and select the reviewed commit on the default branch. Paste the output of `npm run release:notes` into the description, then publish the GitHub Release. A draft does not publish to npm. Approve the `npm` environment deployment if you configured a reviewer.
|
|
44
|
+
|
|
45
|
+
The workflow resolves and verifies the tagged commit, runs the full reusable verification workflow without dependency caches, downloads its tested archive, rechecks the tag/release/version, and publishes that archive with provenance. After npm reports matching archive integrity, it attaches the archive and `package-info.json` to the GitHub Release. Existing identical assets are preserved; conflicting assets cause an explicit failure.
|
|
46
|
+
|
|
47
|
+
## Prereleases
|
|
48
|
+
|
|
49
|
+
Use an exact version, for example:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
npm run release:prepare -- 0.4.0-rc.1
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Mark the GitHub Release **prerelease**. The workflow rejects mismatched flags. Prefixes `alpha`, `beta`, `rc`, and `next` select the corresponding npm dist-tag; other prerelease identifiers select `next`. Stable versions select `latest`. Prereleases leave `latest` intact. Preparing `0.4.0` later releases the stable version.
|
|
56
|
+
|
|
57
|
+
## Previewing and recovering a release
|
|
58
|
+
|
|
59
|
+
In **Actions → Release to npm → Run workflow**, supply an existing published GitHub Release tag. Select a workflow ref containing both release workflows; the tagged source must also contain the invoked release and verification scripts. `dry-run` defaults to true: all verification runs, followed by an npm publication preview, without publishing or attaching assets. This preview checks package validity and version availability; it cannot prove successful OIDC authentication. Publishing the GitHub Release normally starts the real release workflow immediately, so use the manual preview for diagnostics rather than as an approval step before that event.
|
|
60
|
+
|
|
61
|
+
For a failed run, fix account configuration or transient infrastructure issues and rerun it. Alternatively dispatch the same tag with `dry-run` unchecked. Publication is serialized and never cancels an in-progress publisher. A version already on npm is accepted only when its SHA512 integrity matches the tested archive; publication is then skipped and missing release assets can be attached. HTTP errors never count as an unpublished version. Stable releases cannot move `latest` backward.
|
|
62
|
+
|
|
63
|
+
If a version exists with different bytes, choose a new version and release; npm versions cannot be replaced. Do not move an existing release tag to fix source code. A verification failure prevents publication. An error after npm publication can leave a valid npm package with incomplete GitHub assets; inspect the job summary and retry the same commit. There is no automatic unpublish or rollback.
|
|
64
|
+
|
|
65
|
+
`npm run publish:npm` remains an explicit local fallback requiring your own npm authentication. It checks release metadata and runs the package lifecycle checks, but the GitHub workflow is the standard path for publishing the exact archive validated by the full release gate. The compatibility shell wrapper `scripts/release.sh` now only invokes local preparation and requires a version argument.
|
|
66
|
+
|
|
67
|
+
## Verification commands and evidence
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
npm ci
|
|
71
|
+
npm run lint
|
|
72
|
+
npm run build
|
|
73
|
+
npm run test:release
|
|
74
|
+
npm run test:coverage -- --runInBand
|
|
75
|
+
npm run verify:fixtures
|
|
76
|
+
npm run package:verify
|
|
77
|
+
python -m pip install fastapi uvicorn python-multipart
|
|
78
|
+
npm run verify:live
|
|
79
|
+
npm audit --audit-level=moderate
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`npm test` builds first; `test:coverage` and the verification scripts expect a fresh build. For live tests, install the Python packages into your development virtual environment; `PYTHON` can select its executable. The live test starts and stops only its own loopback FastAPI process and records backend versions in its report. CI tests FastAPI 0.116.1 and the current version to cover both legacy `format: binary` and modern unencoded `contentMediaType` upload schemas.
|
|
83
|
+
|
|
84
|
+
Fixture checks cover all six schema fixtures in plain, Zod, and hooks modes with both camelCase and preserved properties. Package verification packs once with lifecycle scripts disabled, validates required files and forbidden content, enforces 10 MiB compressed/25 MiB unpacked limits, installs the archive, and checks exports, the CLI, generated runtime conversion, and strict TypeScript consumers. It writes the publishable `.release/package/package-info.json` marker only after successful validation. Diagnostics are retained under `.artifacts/`; workflows upload reports on failure or where configured.
|
|
85
|
+
|
|
86
|
+
Compatibility jobs cover Node 20/22/24 on Linux, Windows, and macOS. External actions use immutable commit pins, checkout credentials are not persisted, and ordinary CI has read-only repository permissions. The always-running aggregate gate fails if any prerequisite fails, is cancelled, or is skipped. Weekly CodeQL and generation measurements run separately; measurements include repeated fixture durations and source sizes, with no unsupported performance regression claims. Retired duplicate workflows and the unconfigured documentation deployment are removed.
|
|
87
|
+
|
|
88
|
+
Local verification does not establish that the hosted matrix, npm trust configuration, or real publication has passed. Confirm those results in GitHub Actions and npm when the reviewed changes are released.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Audit remediation
|
|
2
|
+
|
|
3
|
+
Working-tree implementation completed on 2026-10-12. This closes the reproduced findings R01–R24 in [the re-audit](REAUDIT.md), through corrected implementations or explicit retirement of unsupported contracts. The audit remains a historical snapshot. No package has been published.
|
|
4
|
+
|
|
5
|
+
## Naming and compatibility
|
|
6
|
+
|
|
7
|
+
Application properties default to camelCase. Generated clients serialize declared JSON/form fields to their original wire names and deserialize JSON responses to application names. This includes nested objects, references, arrays, dictionaries and directional unions. Dictionary keys, unknown fields, enum values and binary objects retain their meaning. Types-only output includes conversion helpers.
|
|
8
|
+
|
|
9
|
+
Set `propertyNaming: "preserve"` for the previous payload-shaped contract. Preservation mode omits the conversion module. Classes, interfaces, aliases and enum names use PascalCase; method/parameter naming retains the separate `namingConvention` compatibility setting. Conflicting generic utility/client type names receive a `Model` suffix; public export/property collisions fail explicitly. See [naming migration](NAMING_MIGRATION.md).
|
|
10
|
+
|
|
11
|
+
## Finding closure
|
|
12
|
+
|
|
13
|
+
| Finding | Resolution | Regression evidence |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| R01 cache identity | Full canonical identities include headers/context; unsafe cyclic values bypass caching. No truncated hash or crypto-js dependency. | `plugin-reaudit.test.ts`, request deduplication suite |
|
|
16
|
+
| R02 output collisions | Portable case/ancestor/reserved-name preflight runs before replacing files. | Core and writer re-audit suites |
|
|
17
|
+
| R03 auth casing | Header setters/removers and bearer helpers use case-insensitive Headers behavior. | Client local HTTP assertions |
|
|
18
|
+
| R04 mutation lifecycle | Latest-call state; reset, unmount and client changes invalidate publication while each caller keeps its result. | Hook harness and 11 mounted React tests |
|
|
19
|
+
| R05 direction | Named/inline request and response projections omit readOnly/writeOnly fields, including recursive references and composition. Conversion uses the same directional wire schemas. | Client consumer assignments and union round trips |
|
|
20
|
+
| R06 branding | Shared AuthState emitted once; schema-backed Zod guards/assertions and feature switches; recursive/primitive brands and complete exports. | Branded/plugin runtime and compile tests |
|
|
21
|
+
| R07 binary uploads | Raw/multipart Blob inputs, binary component projections, repeated parts and supplied FormData; nested directional and structural binary unions work. | Actual HTTP bytes/boundaries plus compiler checks |
|
|
22
|
+
| R08 Path Item refs | Resolve operations/parameters before extraction; unresolved and circular references fail. | Path Item regression and reference validation |
|
|
23
|
+
| R09 unspecified bodies | Schema-less/default/range responses retain media-appropriate bodies; genuine empty responses stay empty. Schema-less request bodies also remain callable. | HTTP binary/default/unspecified-body tests |
|
|
24
|
+
| R10 media alternatives | Successful media alternatives form unions; actual text/XML/JSON/binary decoding agrees with supported metadata. Wildcard response media is conservatively unknown. | Negative/positive consumer assignments and HTTP values |
|
|
25
|
+
| R11 parameter serialization | Form/explode objects, repeated arrays, flat deepObject, space/pipe arrays and simple path/header values. Unsupported styles, complex cookies, content encoding and per-property request encoding fail explicitly. | Local HTTP query/header checks and diagnostics |
|
|
26
|
+
| R12 consumer modules | Type-only imports, .js specifiers, conditional helpers and safe global aliases; utility/alias/export collisions handled. Browser and Node type environments compile. | CommonJS, bundler/verbatim, NodeNext, unused and Node-without-DOM matrix |
|
|
27
|
+
| R13 dialect contract | Compatible 3.0.x/3.1.x patches, 3.1 boolean/component-only schemas and typed component-only input; precise JSON/local-reference scope. YAML capability retired with an actionable diagnostic. | Parser/schema/core re-audit suites |
|
|
28
|
+
| R14 output lifecycle | Validate reports missing refs; required plugin failures fail generation. Files/report hooks assemble before staged commit; rollback and manifest-based stale removal; same-process writes queued. | Core plus 19 filesystem regressions |
|
|
29
|
+
| R15 plugin imports | Preserve arbitrary import declarations and dependency ordering, including multiline/type imports. | Custom plugin consumer compilation |
|
|
30
|
+
| R16 validation | allOf openness, oneOf exclusivity, composition/ref siblings, array/exclusive/enum/dictionary constraints and permissive response return semantics corrected. Explicit closed-object rules survive Zod intersections. | Fresh generated runtime and strict compile tests, including Zod 4.6.6 |
|
|
31
|
+
| R17 cache policies | Endpoint stale/TTL policy, regex invalidation, undefined results, counters and runtime key callbacks work. | Controlled-clock/cache regressions |
|
|
32
|
+
| R18 monitoring | Options/exports synchronized; bounded metrics/TTL and generated report artifacts; helper APIs exported. Report artifacts participate in the output transaction. | Plugin runtime, report and compile tests |
|
|
33
|
+
| R19 init overwrite | Protect existing config; explicit --force replacement. | CLI re-audit suite |
|
|
34
|
+
| R20 interactive behavior | Displayed defaults and failed exit statuses agree with execution. | Mocked input plus spawned CLI contracts |
|
|
35
|
+
| R21 configuration | Shared runtime validation, omitted defaults via SchemanticOptions/defineConfig, client-complete output and explicit unsupported-setting errors. | Core/CLI config and consumer tests |
|
|
36
|
+
| R22 plugin loading | Load builtin/file/package plugins in the generation invocation; config-relative resolution and hook validation. | Same-process local/package plugin fixtures |
|
|
37
|
+
| R23 guides/flags | Maintained examples compile; aliases/hooks/signatures/defaults and implemented templates/verbosity reflect actual APIs. Ineffective promises removed or diagnosed. | Compile every maintained TS/TSX guide example |
|
|
38
|
+
| R24 release gates | Numeric pack/content assertions, installed-package consumer checks, Node/OS CI matrix and tag/version check. Removed name-mutating publish scripts; security dependencies refreshed. | Local pack/consumer validation; workflow source checks |
|
|
39
|
+
|
|
40
|
+
## Verification
|
|
41
|
+
|
|
42
|
+
The final gate includes the complete Jest suite with coverage, fresh TypeScript build, ESLint, all six repository schemas in plain/Zod/hooks modes under both naming modes, and strict consumer module configurations. Separate tests use a local HTTP server for serialization/media/binary bytes and real React/test-renderer for lifecycle behavior. Exact totals and archive observations are recorded with the completion result and local evidence in `test-output/reaudit-core/evidence.json` and `test-output/reaudit-package/`.
|
|
43
|
+
|
|
44
|
+
Final results: **316 tests in 22 suites passed**, with 82.25% statement and 83.96% line coverage. Build and lint passed. **36 fixture combinations** and all five consumer compiler configurations passed. The packed archive excludes tests/dependencies and meets the numeric size guards. An isolated installed consumer passed CommonJS/ESM imports, strict NodeNext compilation, camelCase HTTP round trips and CLI generation. The Windows watch test passed after bounded sharing-lock retries; transient/permanent locks and retry-time link substitution have separate regressions. Hosted CI execution and publication remain unverified/not performed.
|
|
45
|
+
|
|
46
|
+
The dependency lockfile was refreshed within compatible major versions. Axios has a safe minimum version. A scoped `@istanbuljs/load-nyc-config` → `js-yaml` 4 override removes its obsolete parser dependency; the loader's actual `load()` API and a YAML coverage configuration were verified, along with coverage execution. Full npm audit reports zero advisories for this lockfile. Re-check the scoped override when updating coverage tooling.
|
|
47
|
+
|
|
48
|
+
Independent review reproduced and corrected additional directional union, nested binary, utility/import alias, referenced-cookie and composition-validator gaps. The final structural multipart union probe reaches fetch with intact Blob contents. CodeQL uses the canonical JavaScript/TypeScript identifier and explicit scan-upload permissions from [GitHub's workflow guidance](https://docs.github.com/en/code-security/reference/code-scanning/troubleshoot-analysis-errors/some-languages-not-analyzed).
|
|
49
|
+
|
|
50
|
+
## Deliberate support limits
|
|
51
|
+
|
|
52
|
+
- YAML and external-file/remote references are explicitly unsupported. Advanced JSON Schema keywords outside the documented generator/validator subset are not a complete JSON Schema implementation.
|
|
53
|
+
- `generateQueries: true` and the retired `strict-mode` plugin fail explicitly. Plain React hooks are implemented; TanStack adapters are future product work.
|
|
54
|
+
- Validation, deduplication and monitoring plugins emit explicit helper integrations. Enabling a plugin does not automatically wrap every HTTP operation. Branded/validation output requires consuming projects to install Zod 4.
|
|
55
|
+
- Matrix/label paths, nested parameter encodings, complex cookies, wildcard request media and custom per-property form encodings require a future adapter. Caller-provided FormData preserves wire keys. Browser fetch cookie/header rules still apply.
|
|
56
|
+
- Active generated filenames are replaced on regeneration. Stale files are deleted only when manifest-owned and unchanged; modified stale files and unrelated files remain. Rollback is attempted for ordinary commit failures, with incomplete restoration reported. Queuing is within one process; cross-process writers, hard power-loss recovery and adversarial check/syscall races are outside the guarantee.
|
|
57
|
+
- Mounted React verification uses the test renderer, not a browser DOM. Local execution was on Windows/Node 25; hosted Node 20/22/24 and Linux/macOS jobs are configured but were not run here.
|
|
58
|
+
- Publishing a naming migration release, a separate name-mapping report, richer response/error envelopes, drift-check commands, automatic middleware adapters, callbacks/webhooks and OAuth login orchestration remain prospective features, not claimed completed functionality.
|