@growth-labs/conformance 0.4.0 → 0.5.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 +44 -0
- package/README.md +45 -1
- package/dist/endpoint.d.ts +21 -0
- package/dist/endpoint.d.ts.map +1 -0
- package/dist/endpoint.js +225 -0
- package/dist/endpoint.js.map +1 -0
- package/dist/schema.d.ts +142 -142
- package/dist/schema.js +3 -3
- package/dist/schema.js.map +1 -1
- package/package.json +5 -1
- package/src/endpoint.ts +279 -0
- package/src/schema.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @growth-labs/conformance Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0 — 2026-07-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Ship the stable `./endpoint` export with `initConformanceEndpoint` as the
|
|
8
|
+
deployment path: parses, validates, schema-strips, bounds, and serializes
|
|
9
|
+
the v2 artifact **once** at module initialization; per-request handling
|
|
10
|
+
validates only method and `versionMetadata.tag` — no I/O, no re-serialization.
|
|
11
|
+
Also exports `createDeploymentConformanceResponse` as a non-recommended
|
|
12
|
+
compatibility helper for direct per-request use (not the deployment path).
|
|
13
|
+
- The immutable factory captures body bytes at initialization time; post-init
|
|
14
|
+
source mutation and schema-external enumerable getters cannot change served
|
|
15
|
+
bytes or trigger I/O. The combined stripping parse validates endpoint
|
|
16
|
+
`buildEvidence` and the served v2 bundle together without reading schema-external
|
|
17
|
+
fields — no `.passthrough()`.
|
|
18
|
+
- Require `buildEvidence.generatedAt` (timezone-qualified ISO-8601 datetime) at
|
|
19
|
+
the deployment endpoint boundary alongside the existing `buildEvidence.commitSha`.
|
|
20
|
+
A missing or non-datetime `generatedAt` produces a permanently-failing handler.
|
|
21
|
+
- Support `GET` and `HEAD`; `HEAD` returns the same headers without a body,
|
|
22
|
+
while unsupported methods return generic `405` JSON with `Allow: GET, HEAD`.
|
|
23
|
+
- Require a non-empty string request method at runtime; missing, non-string, or
|
|
24
|
+
empty values fail closed with generic no-store JSON rather than defaulting to
|
|
25
|
+
`GET` or throwing from the helper.
|
|
26
|
+
- Require the expected production site and an exact lowercase 40-character
|
|
27
|
+
deployment tag from Cloudflare version metadata `tag`; expose that tag as
|
|
28
|
+
`X-Growth-Labs-Commit-SHA` without serializing Cloudflare version IDs or
|
|
29
|
+
timestamps.
|
|
30
|
+
- Require endpoint input bundles to carry an exact lowercase 40-character
|
|
31
|
+
`buildEvidence.commitSha` matching the deployment tag before returning any
|
|
32
|
+
success body or commit header. `buildEvidence.commitSha` is set from build
|
|
33
|
+
provenance independently of `versionMetadata.tag`; they are compared per
|
|
34
|
+
request and must match or the endpoint fails closed.
|
|
35
|
+
- Bound successful endpoint JSON responses to 1 MiB and return
|
|
36
|
+
`Content-Type: application/json; charset=utf-8`, `Cache-Control: private,
|
|
37
|
+
no-store`, and `X-Content-Type-Options: nosniff`.
|
|
38
|
+
- Fail closed with generic JSON for malformed bundles, wrong site or
|
|
39
|
+
environment, missing or malformed deployment tags, oversized evidence, and
|
|
40
|
+
internal exceptions.
|
|
41
|
+
- Serialize only the parsed v2 `SiteEvidenceBundle` schema so unknown schema
|
|
42
|
+
fields are stripped before the body is emitted.
|
|
43
|
+
- Document the consumer-owned sanitization boundary: the adapter does not
|
|
44
|
+
perform heuristic secret detection, and documented free-form finding or
|
|
45
|
+
receipt strings remain the consumer's responsibility.
|
|
46
|
+
|
|
3
47
|
## 0.4.0 — 2026-07-18
|
|
4
48
|
|
|
5
49
|
### Added
|
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ const fixture = {
|
|
|
87
87
|
},
|
|
88
88
|
buildEvidence: {
|
|
89
89
|
commitSha: 'bd39d718f6a5b0df9a249e11638a8b430050941e',
|
|
90
|
-
packageVersions: { '@growth-labs/conformance': '0.
|
|
90
|
+
packageVersions: { '@growth-labs/conformance': '0.5.0', '@growth-labs/seo': '0.9.0' },
|
|
91
91
|
staticHeaderPolicy: true,
|
|
92
92
|
ssrHeaderPolicy: true,
|
|
93
93
|
},
|
|
@@ -97,6 +97,50 @@ const siteBundle = runSiteConformance(fixture)
|
|
|
97
97
|
const fleetBundle = runFleetConformance([fixture])
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
## Deployment Endpoint Adapter
|
|
101
|
+
|
|
102
|
+
Consumers own the route, the conformance artifact, and the Cloudflare
|
|
103
|
+
`[version_metadata]` binding. The CI/build probe step runs
|
|
104
|
+
`runSiteConformance()`, serializes the result to a JSON artifact file, and
|
|
105
|
+
bundles that file with the Worker. The adapter reads the pre-built artifact at
|
|
106
|
+
module load (not per request) and serves it:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import artifact from './conformance-artifact.json' with { type: 'json' }
|
|
110
|
+
import { initConformanceEndpoint } from '@growth-labs/conformance/endpoint'
|
|
111
|
+
|
|
112
|
+
// Artifact produced by the CI probe step before deployment.
|
|
113
|
+
// Static import: a missing conformance-artifact.json is a build-time error —
|
|
114
|
+
// the Worker never starts if the artifact is absent.
|
|
115
|
+
// Artifact is parsed, schema-stripped, bounded, and serialized ONCE here.
|
|
116
|
+
const handler = initConformanceEndpoint(artifact, 'fronts')
|
|
117
|
+
|
|
118
|
+
// src/pages/.well-known/growth-labs-conformance.json.ts
|
|
119
|
+
export function GET({ locals, request }) {
|
|
120
|
+
return handler.handle({
|
|
121
|
+
method: request.method,
|
|
122
|
+
versionMetadata: locals.runtime.env.CF_VERSION_METADATA,
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const HEAD = GET
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`initConformanceEndpoint` parses the artifact, validates it against the v2
|
|
130
|
+
schema, checks `environment: 'production'` and the expected site, requires
|
|
131
|
+
`buildEvidence.commitSha` (lowercase 40-character hex) and
|
|
132
|
+
`buildEvidence.generatedAt` (timezone-qualified ISO-8601 datetime), and
|
|
133
|
+
serializes the schema-stripped body bytes once. Per-request handling only
|
|
134
|
+
validates the method and compares `versionMetadata.tag` against the baked commit
|
|
135
|
+
SHA — no I/O, no probe execution, no re-serialization. Missing/malformed
|
|
136
|
+
artifacts and wrong site/environment produce a handler that always returns 503.
|
|
137
|
+
The adapter never reads or serializes environment bindings, request headers,
|
|
138
|
+
Cloudflare version IDs, Cloudflare version timestamps, internal exceptions, or
|
|
139
|
+
fields outside the parsed v2 schema. It does not perform heuristic secret
|
|
140
|
+
detection: documented free-form strings such as finding messages, finding
|
|
141
|
+
evidence, remediation text, and receipt evidence remain unchanged and are the
|
|
142
|
+
consumer's sanitization responsibility.
|
|
143
|
+
|
|
100
144
|
## Shared Header Policy
|
|
101
145
|
|
|
102
146
|
Use `buildSharedPublicationHeaders()` when a site wants the package-owned
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const CONFORMANCE_ENDPOINT_MAX_BYTES: number;
|
|
2
|
+
export interface CloudflareVersionMetadataLike {
|
|
3
|
+
id?: unknown;
|
|
4
|
+
tag?: unknown;
|
|
5
|
+
timestamp?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export interface DeploymentConformanceResponseOptions {
|
|
8
|
+
method: string;
|
|
9
|
+
bundle: unknown;
|
|
10
|
+
expectedSite: string;
|
|
11
|
+
versionMetadata?: CloudflareVersionMetadataLike | null;
|
|
12
|
+
}
|
|
13
|
+
export interface ConformanceEndpointHandler {
|
|
14
|
+
handle(options: {
|
|
15
|
+
method: unknown;
|
|
16
|
+
versionMetadata?: CloudflareVersionMetadataLike | null;
|
|
17
|
+
}): Response;
|
|
18
|
+
}
|
|
19
|
+
export declare function initConformanceEndpoint(artifact: unknown, expectedSite: string): ConformanceEndpointHandler;
|
|
20
|
+
export declare function createDeploymentConformanceResponse(options: DeploymentConformanceResponseOptions): Response;
|
|
21
|
+
//# sourceMappingURL=endpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,8BAA8B,QAAc,CAAA;AAiBzD,MAAM,WAAW,6BAA6B;IAC7C,EAAE,CAAC,EAAE,OAAO,CAAA;IACZ,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,SAAS,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,oCAAoC;IACpD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,6BAA6B,GAAG,IAAI,CAAA;CACtD;AAED,MAAM,WAAW,0BAA0B;IAC1C,MAAM,CAAC,OAAO,EAAE;QACf,MAAM,EAAE,OAAO,CAAA;QACf,eAAe,CAAC,EAAE,6BAA6B,GAAG,IAAI,CAAA;KACtD,GAAG,QAAQ,CAAA;CACZ;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,OAAO,EACjB,YAAY,EAAE,MAAM,GAClB,0BAA0B,CA+C5B;AAUD,wBAAgB,mCAAmC,CAClD,OAAO,EAAE,oCAAoC,GAC3C,QAAQ,CA8BV"}
|
package/dist/endpoint.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { buildEvidenceSchema, siteEvidenceBundleSchema } from './schema.js';
|
|
3
|
+
export const CONFORMANCE_ENDPOINT_MAX_BYTES = 1024 * 1024;
|
|
4
|
+
const COMMIT_SHA_PATTERN = /^[0-9a-f]{40}$/;
|
|
5
|
+
const CONTENT_TYPE = 'application/json; charset=utf-8';
|
|
6
|
+
const GENERIC_FAILURE_BODY = '{"status":"unavailable"}';
|
|
7
|
+
const INIT_FAILURE_DIAGNOSTIC = '[conformance] initConformanceEndpoint: artifact validation failed at init';
|
|
8
|
+
// Single stripping schema: validates endpoint buildEvidence and the v2 bundle together
|
|
9
|
+
// without touching schema-external fields. No .passthrough() — unknown fields are stripped.
|
|
10
|
+
const deploymentArtifactSchema = siteEvidenceBundleSchema.extend({
|
|
11
|
+
buildEvidence: buildEvidenceSchema.extend({
|
|
12
|
+
commitSha: z.string().regex(COMMIT_SHA_PATTERN),
|
|
13
|
+
generatedAt: z.string().datetime({ offset: true }),
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
16
|
+
export function initConformanceEndpoint(artifact, expectedSite) {
|
|
17
|
+
let capturedBody = null;
|
|
18
|
+
let capturedBuildCommitSha = null;
|
|
19
|
+
try {
|
|
20
|
+
const site = readExpectedSite(expectedSite);
|
|
21
|
+
const { buildEvidence, ...bundle } = deploymentArtifactSchema.parse(artifact);
|
|
22
|
+
if (bundle.site !== site || bundle.environment !== 'production') {
|
|
23
|
+
throw new Error('Conformance endpoint evidence does not match the expected production site.');
|
|
24
|
+
}
|
|
25
|
+
capturedBody = stringifyJsonBounded(bundle, CONFORMANCE_ENDPOINT_MAX_BYTES);
|
|
26
|
+
capturedBuildCommitSha = buildEvidence.commitSha;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
reportInitFailure();
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
handle(options) {
|
|
33
|
+
let isHead = false;
|
|
34
|
+
try {
|
|
35
|
+
const methodStr = readRequestMethod(options.method);
|
|
36
|
+
isHead = methodStr === 'HEAD';
|
|
37
|
+
if (methodStr !== 'GET' && methodStr !== 'HEAD') {
|
|
38
|
+
return genericFailureResponse(405, false, { Allow: 'GET, HEAD' });
|
|
39
|
+
}
|
|
40
|
+
if (capturedBody === null || capturedBuildCommitSha === null) {
|
|
41
|
+
throw new Error('Conformance endpoint artifact initialization failed.');
|
|
42
|
+
}
|
|
43
|
+
const commitSha = readDeploymentCommitSha(options.versionMetadata);
|
|
44
|
+
if (!commitShaEquals(capturedBuildCommitSha, commitSha)) {
|
|
45
|
+
throw new Error('Conformance endpoint build evidence does not match the deployment tag.');
|
|
46
|
+
}
|
|
47
|
+
return new Response(isHead ? null : capturedBody, {
|
|
48
|
+
status: 200,
|
|
49
|
+
headers: responseHeaders(commitSha),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return genericFailureResponse(503, isHead);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function reportInitFailure() {
|
|
59
|
+
try {
|
|
60
|
+
console.error(INIT_FAILURE_DIAGNOSTIC);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Logging must never turn a fail-closed handler into an import-time crash.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function createDeploymentConformanceResponse(options) {
|
|
67
|
+
let isHead = false;
|
|
68
|
+
try {
|
|
69
|
+
const method = readRequestMethod(options.method);
|
|
70
|
+
isHead = method === 'HEAD';
|
|
71
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
72
|
+
return genericFailureResponse(405, false, { Allow: 'GET, HEAD' });
|
|
73
|
+
}
|
|
74
|
+
const commitSha = readDeploymentCommitSha(options.versionMetadata);
|
|
75
|
+
const expectedSite = readExpectedSite(options.expectedSite);
|
|
76
|
+
const { buildEvidence, ...bundle } = deploymentArtifactSchema.parse(options.bundle);
|
|
77
|
+
if (bundle.site !== expectedSite || bundle.environment !== 'production') {
|
|
78
|
+
throw new Error('Conformance endpoint evidence does not match the expected production site.');
|
|
79
|
+
}
|
|
80
|
+
if (!commitShaEquals(buildEvidence.commitSha, commitSha)) {
|
|
81
|
+
throw new Error('Conformance endpoint build evidence does not match the deployment tag.');
|
|
82
|
+
}
|
|
83
|
+
const body = stringifyJsonBounded(bundle, CONFORMANCE_ENDPOINT_MAX_BYTES);
|
|
84
|
+
return new Response(isHead ? null : body, {
|
|
85
|
+
status: 200,
|
|
86
|
+
headers: responseHeaders(commitSha),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return genericFailureResponse(503, isHead);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function readRequestMethod(method) {
|
|
94
|
+
if (typeof method !== 'string') {
|
|
95
|
+
throw new Error('Request method is required.');
|
|
96
|
+
}
|
|
97
|
+
const normalizedMethod = method.trim().toUpperCase();
|
|
98
|
+
if (normalizedMethod.length === 0) {
|
|
99
|
+
throw new Error('Request method is required.');
|
|
100
|
+
}
|
|
101
|
+
return normalizedMethod;
|
|
102
|
+
}
|
|
103
|
+
function readExpectedSite(expectedSite) {
|
|
104
|
+
if (typeof expectedSite !== 'string' || expectedSite.trim().length === 0) {
|
|
105
|
+
throw new Error('Expected site identity is required.');
|
|
106
|
+
}
|
|
107
|
+
return expectedSite;
|
|
108
|
+
}
|
|
109
|
+
function readDeploymentCommitSha(versionMetadata) {
|
|
110
|
+
if (!versionMetadata || typeof versionMetadata !== 'object') {
|
|
111
|
+
throw new Error('Cloudflare version metadata is required.');
|
|
112
|
+
}
|
|
113
|
+
const { tag } = versionMetadata;
|
|
114
|
+
if (typeof tag !== 'string' || !COMMIT_SHA_PATTERN.test(tag)) {
|
|
115
|
+
throw new Error('Cloudflare version metadata tag must be a lowercase 40-character commit SHA.');
|
|
116
|
+
}
|
|
117
|
+
return tag;
|
|
118
|
+
}
|
|
119
|
+
function commitShaEquals(left, right) {
|
|
120
|
+
if (left.length !== right.length)
|
|
121
|
+
return false;
|
|
122
|
+
let difference = 0;
|
|
123
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
124
|
+
difference |= left.charCodeAt(index) ^ right.charCodeAt(index);
|
|
125
|
+
}
|
|
126
|
+
return difference === 0;
|
|
127
|
+
}
|
|
128
|
+
function responseHeaders(commitSha) {
|
|
129
|
+
const headers = new Headers({
|
|
130
|
+
'Content-Type': CONTENT_TYPE,
|
|
131
|
+
'Cache-Control': 'private, no-store',
|
|
132
|
+
'X-Content-Type-Options': 'nosniff',
|
|
133
|
+
});
|
|
134
|
+
if (commitSha)
|
|
135
|
+
headers.set('X-Growth-Labs-Commit-SHA', commitSha);
|
|
136
|
+
return headers;
|
|
137
|
+
}
|
|
138
|
+
function genericFailureResponse(status, head, extraHeaders = {}) {
|
|
139
|
+
const headers = responseHeaders();
|
|
140
|
+
for (const [name, value] of Object.entries(extraHeaders))
|
|
141
|
+
headers.set(name, value);
|
|
142
|
+
return new Response(head ? null : GENERIC_FAILURE_BODY, { status, headers });
|
|
143
|
+
}
|
|
144
|
+
function stringifyJsonBounded(value, maxBytes) {
|
|
145
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1) {
|
|
146
|
+
throw new RangeError('maxBytes must be a positive safe integer.');
|
|
147
|
+
}
|
|
148
|
+
const encoder = new TextEncoder();
|
|
149
|
+
const parts = [];
|
|
150
|
+
const seen = new Set();
|
|
151
|
+
let bytes = 0;
|
|
152
|
+
function append(part) {
|
|
153
|
+
const nextBytes = bytes + encoder.encode(part).byteLength;
|
|
154
|
+
if (nextBytes > maxBytes)
|
|
155
|
+
throw new RangeError('Conformance endpoint response is too large.');
|
|
156
|
+
bytes = nextBytes;
|
|
157
|
+
parts.push(part);
|
|
158
|
+
}
|
|
159
|
+
function writeJsonString(text) {
|
|
160
|
+
append(JSON.stringify(text));
|
|
161
|
+
}
|
|
162
|
+
function write(next) {
|
|
163
|
+
if (next === null) {
|
|
164
|
+
append('null');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
switch (typeof next) {
|
|
168
|
+
case 'string':
|
|
169
|
+
writeJsonString(next);
|
|
170
|
+
return;
|
|
171
|
+
case 'number':
|
|
172
|
+
append(Number.isFinite(next) ? String(next) : 'null');
|
|
173
|
+
return;
|
|
174
|
+
case 'boolean':
|
|
175
|
+
append(next ? 'true' : 'false');
|
|
176
|
+
return;
|
|
177
|
+
case 'object':
|
|
178
|
+
writeObject(next);
|
|
179
|
+
return;
|
|
180
|
+
default:
|
|
181
|
+
throw new TypeError('Unsupported JSON value.');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function writeObject(next) {
|
|
185
|
+
if (seen.has(next))
|
|
186
|
+
throw new TypeError('Cannot serialize circular evidence.');
|
|
187
|
+
seen.add(next);
|
|
188
|
+
try {
|
|
189
|
+
if (Array.isArray(next)) {
|
|
190
|
+
append('[');
|
|
191
|
+
next.forEach((item, index) => {
|
|
192
|
+
if (index > 0)
|
|
193
|
+
append(',');
|
|
194
|
+
if (item === undefined || typeof item === 'function' || typeof item === 'symbol') {
|
|
195
|
+
append('null');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
write(item);
|
|
199
|
+
});
|
|
200
|
+
append(']');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
append('{');
|
|
204
|
+
let first = true;
|
|
205
|
+
for (const key of Object.keys(next)) {
|
|
206
|
+
const item = next[key];
|
|
207
|
+
if (item === undefined || typeof item === 'function' || typeof item === 'symbol')
|
|
208
|
+
continue;
|
|
209
|
+
if (!first)
|
|
210
|
+
append(',');
|
|
211
|
+
first = false;
|
|
212
|
+
append(JSON.stringify(key));
|
|
213
|
+
append(':');
|
|
214
|
+
write(item);
|
|
215
|
+
}
|
|
216
|
+
append('}');
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
seen.delete(next);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
write(value);
|
|
223
|
+
return parts.join('');
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
|