@growth-labs/cms 0.5.27 → 0.5.30
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/README.md +20 -0
- package/dist/engine/index.d.ts +5 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +5 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/publication-continuity.d.ts +77 -0
- package/dist/engine/publication-continuity.d.ts.map +1 -0
- package/dist/engine/publication-continuity.js +94 -0
- package/dist/engine/publication-continuity.js.map +1 -0
- package/dist/engine/publication-receipt/canonical-json.d.ts +34 -0
- package/dist/engine/publication-receipt/canonical-json.d.ts.map +1 -0
- package/dist/engine/publication-receipt/canonical-json.js +100 -0
- package/dist/engine/publication-receipt/canonical-json.js.map +1 -0
- package/dist/engine/publication-receipt/receipt.d.ts +316 -0
- package/dist/engine/publication-receipt/receipt.d.ts.map +1 -0
- package/dist/engine/publication-receipt/receipt.js +131 -0
- package/dist/engine/publication-receipt/receipt.js.map +1 -0
- package/dist/engine/publication-receipt/signature.d.ts +36 -0
- package/dist/engine/publication-receipt/signature.d.ts.map +1 -0
- package/dist/engine/publication-receipt/signature.js +79 -0
- package/dist/engine/publication-receipt/signature.js.map +1 -0
- package/dist/engine/publication.d.ts.map +1 -1
- package/dist/engine/publication.js +2 -0
- package/dist/engine/publication.js.map +1 -1
- package/dist/engine/publisher.d.ts.map +1 -1
- package/dist/engine/publisher.js +2 -0
- package/dist/engine/publisher.js.map +1 -1
- package/dist/engine/slug.d.ts.map +1 -1
- package/dist/engine/slug.js +11 -1
- package/dist/engine/slug.js.map +1 -1
- package/dist/engine/source-sections.d.ts +20 -0
- package/dist/engine/source-sections.d.ts.map +1 -0
- package/dist/engine/source-sections.js +130 -0
- package/dist/engine/source-sections.js.map +1 -0
- package/dist/engine/validator/checks/source-section-diagnostics.d.ts +7 -0
- package/dist/engine/validator/checks/source-section-diagnostics.d.ts.map +1 -0
- package/dist/engine/validator/checks/source-section-diagnostics.js +120 -0
- package/dist/engine/validator/checks/source-section-diagnostics.js.map +1 -0
- package/dist/engine/validator/index.d.ts +10 -0
- package/dist/engine/validator/index.d.ts.map +1 -1
- package/dist/engine/validator/index.js +4 -0
- package/dist/engine/validator/index.js.map +1 -1
- package/dist/engine/validator/types.d.ts +1 -1
- package/dist/engine/validator/types.d.ts.map +1 -1
- package/dist/engine/validator/types.js +10 -0
- package/dist/engine/validator/types.js.map +1 -1
- package/dist/integration/options.d.ts +196 -0
- package/dist/integration/options.d.ts.map +1 -1
- package/dist/integration/options.js +62 -0
- package/dist/integration/options.js.map +1 -1
- package/dist/providers/types.d.ts +1 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/routes/content.d.ts.map +1 -1
- package/dist/routes/content.js +52 -2
- package/dist/routes/content.js.map +1 -1
- package/dist/routes/surveys.d.ts.map +1 -1
- package/dist/routes/surveys.js +13 -1
- package/dist/routes/surveys.js.map +1 -1
- package/dist/schema/insights-ingest.d.ts +28 -28
- package/dist/surveys/access.d.ts +2 -0
- package/dist/surveys/access.d.ts.map +1 -1
- package/dist/surveys/access.js +7 -0
- package/dist/surveys/access.js.map +1 -1
- package/dist/surveys/errors.d.ts +8 -0
- package/dist/surveys/errors.d.ts.map +1 -1
- package/dist/surveys/errors.js +12 -0
- package/dist/surveys/errors.js.map +1 -1
- package/dist/surveys/schema.d.ts +75 -0
- package/dist/surveys/schema.d.ts.map +1 -1
- package/dist/surveys/schema.js +45 -0
- package/dist/surveys/schema.js.map +1 -1
- package/dist/ui/client/mount.d.ts.map +1 -1
- package/dist/ui/client/mount.js +1 -0
- package/dist/ui/client/mount.js.map +1 -1
- package/dist/ui/editor/ContentForm.d.ts +3 -1
- package/dist/ui/editor/ContentForm.d.ts.map +1 -1
- package/dist/ui/editor/ContentForm.js +87 -9
- package/dist/ui/editor/ContentForm.js.map +1 -1
- package/dist/ui/editor/body-warnings.d.ts +27 -0
- package/dist/ui/editor/body-warnings.d.ts.map +1 -0
- package/dist/ui/editor/body-warnings.js +58 -0
- package/dist/ui/editor/body-warnings.js.map +1 -0
- package/dist/ui/editor/content-payload.d.ts +12 -0
- package/dist/ui/editor/content-payload.d.ts.map +1 -1
- package/dist/ui/editor/content-payload.js +24 -0
- package/dist/ui/editor/content-payload.js.map +1 -1
- package/dist/ui/screens/ContentRoute.d.ts +3 -1
- package/dist/ui/screens/ContentRoute.d.ts.map +1 -1
- package/dist/ui/screens/ContentRoute.js +2 -2
- package/dist/ui/screens/ContentRoute.js.map +1 -1
- package/dist/ui/screens/EditorScreen.d.ts +3 -1
- package/dist/ui/screens/EditorScreen.d.ts.map +1 -1
- package/dist/ui/screens/EditorScreen.js +2 -2
- package/dist/ui/screens/EditorScreen.js.map +1 -1
- package/dist/ui/screens/SurveyResponsesScreen.d.ts +7 -1
- package/dist/ui/screens/SurveyResponsesScreen.d.ts.map +1 -1
- package/dist/ui/screens/SurveyResponsesScreen.js +141 -32
- package/dist/ui/screens/SurveyResponsesScreen.js.map +1 -1
- package/dist/ui/screens/registry.d.ts +3 -1
- package/dist/ui/screens/registry.d.ts.map +1 -1
- package/dist/ui/screens/registry.js +2 -2
- package/dist/ui/screens/registry.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/index.ts +33 -0
- package/src/engine/publication-continuity.ts +140 -0
- package/src/engine/publication-receipt/canonical-json.ts +123 -0
- package/src/engine/publication-receipt/receipt.ts +160 -0
- package/src/engine/publication-receipt/signature.ts +112 -0
- package/src/engine/publication.ts +2 -0
- package/src/engine/publisher.ts +2 -0
- package/src/engine/slug.ts +12 -1
- package/src/engine/source-sections.ts +153 -0
- package/src/engine/validator/checks/source-section-diagnostics.ts +187 -0
- package/src/engine/validator/index.ts +12 -0
- package/src/engine/validator/types.ts +19 -0
- package/src/integration/options.ts +69 -0
- package/src/providers/types.ts +1 -1
- package/src/routes/content.ts +60 -2
- package/src/routes/surveys.ts +12 -1
- package/src/surveys/access.ts +9 -0
- package/src/surveys/errors.ts +12 -0
- package/src/surveys/schema.ts +47 -0
- package/src/ui/client/mount.tsx +1 -0
- package/src/ui/editor/ContentForm.tsx +167 -5
- package/src/ui/editor/body-warnings.ts +78 -0
- package/src/ui/editor/content-payload.ts +39 -0
- package/src/ui/screens/ContentRoute.tsx +4 -0
- package/src/ui/screens/EditorScreen.tsx +4 -0
- package/src/ui/screens/SurveyResponsesScreen.tsx +369 -121
- package/src/ui/screens/registry.tsx +4 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const SITE_PUBLICATION_RECEIPT_SCHEMA: "site.publication.receipt.v1";
|
|
3
|
+
export declare const SITE_PUBLICATION_RECEIPT_AUDIENCE: "foundry:site-publication-receipt";
|
|
4
|
+
export declare const publicationProbeSchema: z.ZodObject<{
|
|
5
|
+
/** What was probed, e.g. `html` or `markdown`. */
|
|
6
|
+
kind: z.ZodEnum<["html", "markdown"]>;
|
|
7
|
+
url: z.ZodString;
|
|
8
|
+
status: z.ZodNumber;
|
|
9
|
+
/** SHA-256 of the exact bytes observed, so Foundry can compare. */
|
|
10
|
+
digest: z.ZodString;
|
|
11
|
+
}, "strict", z.ZodTypeAny, {
|
|
12
|
+
status: number;
|
|
13
|
+
kind: "html" | "markdown";
|
|
14
|
+
url: string;
|
|
15
|
+
digest: string;
|
|
16
|
+
}, {
|
|
17
|
+
status: number;
|
|
18
|
+
kind: "html" | "markdown";
|
|
19
|
+
url: string;
|
|
20
|
+
digest: string;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const publicationProjectionCountsSchema: z.ZodObject<{
|
|
23
|
+
seo: z.ZodNumber;
|
|
24
|
+
search: z.ZodNumber;
|
|
25
|
+
sitemap: z.ZodNumber;
|
|
26
|
+
feed: z.ZodNumber;
|
|
27
|
+
}, "strict", z.ZodTypeAny, {
|
|
28
|
+
search: number;
|
|
29
|
+
seo: number;
|
|
30
|
+
sitemap: number;
|
|
31
|
+
feed: number;
|
|
32
|
+
}, {
|
|
33
|
+
search: number;
|
|
34
|
+
seo: number;
|
|
35
|
+
sitemap: number;
|
|
36
|
+
feed: number;
|
|
37
|
+
}>;
|
|
38
|
+
export declare const sitePublicationReceiptBodySchema: z.ZodEffects<z.ZodObject<{
|
|
39
|
+
schema: z.ZodLiteral<"site.publication.receipt.v1">;
|
|
40
|
+
audience: z.ZodLiteral<"foundry:site-publication-receipt">;
|
|
41
|
+
/** Success and failure are both signed; a silent failure is unverifiable. */
|
|
42
|
+
outcome: z.ZodEnum<["success", "failure"]>;
|
|
43
|
+
/** Identity of the publishing property (the site). */
|
|
44
|
+
property: z.ZodObject<{
|
|
45
|
+
id: z.ZodString;
|
|
46
|
+
origin: z.ZodString;
|
|
47
|
+
}, "strict", z.ZodTypeAny, {
|
|
48
|
+
id: string;
|
|
49
|
+
origin: string;
|
|
50
|
+
}, {
|
|
51
|
+
id: string;
|
|
52
|
+
origin: string;
|
|
53
|
+
}>;
|
|
54
|
+
/** Identity of the thing published, stable across revisions. */
|
|
55
|
+
content: z.ZodObject<{
|
|
56
|
+
stableId: z.ZodString;
|
|
57
|
+
slug: z.ZodString;
|
|
58
|
+
revisionId: z.ZodString;
|
|
59
|
+
}, "strict", z.ZodTypeAny, {
|
|
60
|
+
slug: string;
|
|
61
|
+
revisionId: string;
|
|
62
|
+
stableId: string;
|
|
63
|
+
}, {
|
|
64
|
+
slug: string;
|
|
65
|
+
revisionId: string;
|
|
66
|
+
stableId: string;
|
|
67
|
+
}>;
|
|
68
|
+
/** What produced it. */
|
|
69
|
+
source: z.ZodObject<{
|
|
70
|
+
commit: z.ZodString;
|
|
71
|
+
foundryHandoffId: z.ZodString;
|
|
72
|
+
foundryRunId: z.ZodString;
|
|
73
|
+
}, "strict", z.ZodTypeAny, {
|
|
74
|
+
commit: string;
|
|
75
|
+
foundryHandoffId: string;
|
|
76
|
+
foundryRunId: string;
|
|
77
|
+
}, {
|
|
78
|
+
commit: string;
|
|
79
|
+
foundryHandoffId: string;
|
|
80
|
+
foundryRunId: string;
|
|
81
|
+
}>;
|
|
82
|
+
/** Logical database identity — never a connection string or credential. */
|
|
83
|
+
database: z.ZodObject<{
|
|
84
|
+
logicalId: z.ZodString;
|
|
85
|
+
}, "strict", z.ZodTypeAny, {
|
|
86
|
+
logicalId: string;
|
|
87
|
+
}, {
|
|
88
|
+
logicalId: string;
|
|
89
|
+
}>;
|
|
90
|
+
/** Hash of the public media manifest, not the media itself. */
|
|
91
|
+
publicMediaManifestHash: z.ZodString;
|
|
92
|
+
projections: z.ZodObject<{
|
|
93
|
+
seo: z.ZodNumber;
|
|
94
|
+
search: z.ZodNumber;
|
|
95
|
+
sitemap: z.ZodNumber;
|
|
96
|
+
feed: z.ZodNumber;
|
|
97
|
+
}, "strict", z.ZodTypeAny, {
|
|
98
|
+
search: number;
|
|
99
|
+
seo: number;
|
|
100
|
+
sitemap: number;
|
|
101
|
+
feed: number;
|
|
102
|
+
}, {
|
|
103
|
+
search: number;
|
|
104
|
+
seo: number;
|
|
105
|
+
sitemap: number;
|
|
106
|
+
feed: number;
|
|
107
|
+
}>;
|
|
108
|
+
probes: z.ZodArray<z.ZodObject<{
|
|
109
|
+
/** What was probed, e.g. `html` or `markdown`. */
|
|
110
|
+
kind: z.ZodEnum<["html", "markdown"]>;
|
|
111
|
+
url: z.ZodString;
|
|
112
|
+
status: z.ZodNumber;
|
|
113
|
+
/** SHA-256 of the exact bytes observed, so Foundry can compare. */
|
|
114
|
+
digest: z.ZodString;
|
|
115
|
+
}, "strict", z.ZodTypeAny, {
|
|
116
|
+
status: number;
|
|
117
|
+
kind: "html" | "markdown";
|
|
118
|
+
url: string;
|
|
119
|
+
digest: string;
|
|
120
|
+
}, {
|
|
121
|
+
status: number;
|
|
122
|
+
kind: "html" | "markdown";
|
|
123
|
+
url: string;
|
|
124
|
+
digest: string;
|
|
125
|
+
}>, "many">;
|
|
126
|
+
/** How to undo this publication. */
|
|
127
|
+
rollback: z.ZodObject<{
|
|
128
|
+
pointer: z.ZodString;
|
|
129
|
+
}, "strict", z.ZodTypeAny, {
|
|
130
|
+
pointer: string;
|
|
131
|
+
}, {
|
|
132
|
+
pointer: string;
|
|
133
|
+
}>;
|
|
134
|
+
/** Replay identity. Supplied by the caller and persisted, never generated here. */
|
|
135
|
+
nonce: z.ZodString;
|
|
136
|
+
issuedAt: z.ZodString;
|
|
137
|
+
/** Present only when `outcome` is `failure`, and bounded. */
|
|
138
|
+
failureReason: z.ZodOptional<z.ZodString>;
|
|
139
|
+
}, "strict", z.ZodTypeAny, {
|
|
140
|
+
rollback: {
|
|
141
|
+
pointer: string;
|
|
142
|
+
};
|
|
143
|
+
source: {
|
|
144
|
+
commit: string;
|
|
145
|
+
foundryHandoffId: string;
|
|
146
|
+
foundryRunId: string;
|
|
147
|
+
};
|
|
148
|
+
content: {
|
|
149
|
+
slug: string;
|
|
150
|
+
revisionId: string;
|
|
151
|
+
stableId: string;
|
|
152
|
+
};
|
|
153
|
+
audience: "foundry:site-publication-receipt";
|
|
154
|
+
schema: "site.publication.receipt.v1";
|
|
155
|
+
outcome: "success" | "failure";
|
|
156
|
+
property: {
|
|
157
|
+
id: string;
|
|
158
|
+
origin: string;
|
|
159
|
+
};
|
|
160
|
+
database: {
|
|
161
|
+
logicalId: string;
|
|
162
|
+
};
|
|
163
|
+
publicMediaManifestHash: string;
|
|
164
|
+
projections: {
|
|
165
|
+
search: number;
|
|
166
|
+
seo: number;
|
|
167
|
+
sitemap: number;
|
|
168
|
+
feed: number;
|
|
169
|
+
};
|
|
170
|
+
probes: {
|
|
171
|
+
status: number;
|
|
172
|
+
kind: "html" | "markdown";
|
|
173
|
+
url: string;
|
|
174
|
+
digest: string;
|
|
175
|
+
}[];
|
|
176
|
+
nonce: string;
|
|
177
|
+
issuedAt: string;
|
|
178
|
+
failureReason?: string | undefined;
|
|
179
|
+
}, {
|
|
180
|
+
rollback: {
|
|
181
|
+
pointer: string;
|
|
182
|
+
};
|
|
183
|
+
source: {
|
|
184
|
+
commit: string;
|
|
185
|
+
foundryHandoffId: string;
|
|
186
|
+
foundryRunId: string;
|
|
187
|
+
};
|
|
188
|
+
content: {
|
|
189
|
+
slug: string;
|
|
190
|
+
revisionId: string;
|
|
191
|
+
stableId: string;
|
|
192
|
+
};
|
|
193
|
+
audience: "foundry:site-publication-receipt";
|
|
194
|
+
schema: "site.publication.receipt.v1";
|
|
195
|
+
outcome: "success" | "failure";
|
|
196
|
+
property: {
|
|
197
|
+
id: string;
|
|
198
|
+
origin: string;
|
|
199
|
+
};
|
|
200
|
+
database: {
|
|
201
|
+
logicalId: string;
|
|
202
|
+
};
|
|
203
|
+
publicMediaManifestHash: string;
|
|
204
|
+
projections: {
|
|
205
|
+
search: number;
|
|
206
|
+
seo: number;
|
|
207
|
+
sitemap: number;
|
|
208
|
+
feed: number;
|
|
209
|
+
};
|
|
210
|
+
probes: {
|
|
211
|
+
status: number;
|
|
212
|
+
kind: "html" | "markdown";
|
|
213
|
+
url: string;
|
|
214
|
+
digest: string;
|
|
215
|
+
}[];
|
|
216
|
+
nonce: string;
|
|
217
|
+
issuedAt: string;
|
|
218
|
+
failureReason?: string | undefined;
|
|
219
|
+
}>, {
|
|
220
|
+
rollback: {
|
|
221
|
+
pointer: string;
|
|
222
|
+
};
|
|
223
|
+
source: {
|
|
224
|
+
commit: string;
|
|
225
|
+
foundryHandoffId: string;
|
|
226
|
+
foundryRunId: string;
|
|
227
|
+
};
|
|
228
|
+
content: {
|
|
229
|
+
slug: string;
|
|
230
|
+
revisionId: string;
|
|
231
|
+
stableId: string;
|
|
232
|
+
};
|
|
233
|
+
audience: "foundry:site-publication-receipt";
|
|
234
|
+
schema: "site.publication.receipt.v1";
|
|
235
|
+
outcome: "success" | "failure";
|
|
236
|
+
property: {
|
|
237
|
+
id: string;
|
|
238
|
+
origin: string;
|
|
239
|
+
};
|
|
240
|
+
database: {
|
|
241
|
+
logicalId: string;
|
|
242
|
+
};
|
|
243
|
+
publicMediaManifestHash: string;
|
|
244
|
+
projections: {
|
|
245
|
+
search: number;
|
|
246
|
+
seo: number;
|
|
247
|
+
sitemap: number;
|
|
248
|
+
feed: number;
|
|
249
|
+
};
|
|
250
|
+
probes: {
|
|
251
|
+
status: number;
|
|
252
|
+
kind: "html" | "markdown";
|
|
253
|
+
url: string;
|
|
254
|
+
digest: string;
|
|
255
|
+
}[];
|
|
256
|
+
nonce: string;
|
|
257
|
+
issuedAt: string;
|
|
258
|
+
failureReason?: string | undefined;
|
|
259
|
+
}, {
|
|
260
|
+
rollback: {
|
|
261
|
+
pointer: string;
|
|
262
|
+
};
|
|
263
|
+
source: {
|
|
264
|
+
commit: string;
|
|
265
|
+
foundryHandoffId: string;
|
|
266
|
+
foundryRunId: string;
|
|
267
|
+
};
|
|
268
|
+
content: {
|
|
269
|
+
slug: string;
|
|
270
|
+
revisionId: string;
|
|
271
|
+
stableId: string;
|
|
272
|
+
};
|
|
273
|
+
audience: "foundry:site-publication-receipt";
|
|
274
|
+
schema: "site.publication.receipt.v1";
|
|
275
|
+
outcome: "success" | "failure";
|
|
276
|
+
property: {
|
|
277
|
+
id: string;
|
|
278
|
+
origin: string;
|
|
279
|
+
};
|
|
280
|
+
database: {
|
|
281
|
+
logicalId: string;
|
|
282
|
+
};
|
|
283
|
+
publicMediaManifestHash: string;
|
|
284
|
+
projections: {
|
|
285
|
+
search: number;
|
|
286
|
+
seo: number;
|
|
287
|
+
sitemap: number;
|
|
288
|
+
feed: number;
|
|
289
|
+
};
|
|
290
|
+
probes: {
|
|
291
|
+
status: number;
|
|
292
|
+
kind: "html" | "markdown";
|
|
293
|
+
url: string;
|
|
294
|
+
digest: string;
|
|
295
|
+
}[];
|
|
296
|
+
nonce: string;
|
|
297
|
+
issuedAt: string;
|
|
298
|
+
failureReason?: string | undefined;
|
|
299
|
+
}>;
|
|
300
|
+
export type SitePublicationReceiptBody = z.infer<typeof sitePublicationReceiptBodySchema>;
|
|
301
|
+
export declare class PublicationReceiptError extends Error {
|
|
302
|
+
readonly code: 'invalid_body' | 'invalid_key';
|
|
303
|
+
constructor(code: PublicationReceiptError['code'], message: string);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Validate a receipt body and return its canonical RFC 8785 form.
|
|
307
|
+
*
|
|
308
|
+
* Validation happens before canonicalization on purpose: signing an unvalidated
|
|
309
|
+
* body would produce a verifiable signature over a malformed claim, which is
|
|
310
|
+
* strictly worse than refusing, because downstream would trust it.
|
|
311
|
+
*/
|
|
312
|
+
export declare function canonicalizeReceiptBody(body: unknown): {
|
|
313
|
+
body: SitePublicationReceiptBody;
|
|
314
|
+
canonical: string;
|
|
315
|
+
};
|
|
316
|
+
//# sourceMappingURL=receipt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../../../src/engine/publication-receipt/receipt.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,+BAA+B,EAAG,6BAAsC,CAAA;AACrF,eAAO,MAAM,iCAAiC,EAAG,kCAA2C,CAAA;AAoB5F,eAAO,MAAM,sBAAsB;IAEjC,kDAAkD;;;;IAIlD,mEAAmE;;;;;;;;;;;;EAG3D,CAAA;AAEV,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;EAOpC,CAAA;AAEV,eAAO,MAAM,gCAAgC;;;IAK3C,6EAA6E;;IAG7E,sDAAsD;;;;;;;;;;;IAGtD,gEAAgE;;;;;;;;;;;;;;IAShE,wBAAwB;;;;;;;;;;;;;;IASxB,2EAA2E;;;;;;;;IAG3E,+DAA+D;;;;;;;;;;;;;;;;;;;QAlD/D,kDAAkD;;;;QAIlD,mEAAmE;;;;;;;;;;;;;IAoDnE,oCAAoC;;;;;;;;IAGpC,mFAAmF;;;IAInF,6DAA6D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmB5D,CAAA;AAEH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AAEzF,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CAAA;gBAEjC,IAAI,EAAE,uBAAuB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAKlE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG;IACvD,IAAI,EAAE,0BAA0B,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;CACjB,CAcA"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// `site.publication.receipt.v1` — the signed handoff receipt (#342).
|
|
2
|
+
//
|
|
3
|
+
// A receipt is the site's terminal, non-repudiable statement about one
|
|
4
|
+
// publication attempt. Foundry must be able to verify it without trusting the
|
|
5
|
+
// transport and without re-querying the site, so everything it needs to judge
|
|
6
|
+
// the claim is inside the signed body.
|
|
7
|
+
//
|
|
8
|
+
// The site persists the canonical bytes and signature exactly once BEFORE
|
|
9
|
+
// network delivery; a retry resends those stored bytes verbatim. That is why
|
|
10
|
+
// nothing in the body is derived at sign time — the nonce and timestamps are
|
|
11
|
+
// inputs, not defaults. A schema that generated its own nonce would produce a
|
|
12
|
+
// different receipt on every retry and break replay-safety by construction.
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { canonicalJson } from './canonical-json.js';
|
|
15
|
+
export const SITE_PUBLICATION_RECEIPT_SCHEMA = 'site.publication.receipt.v1';
|
|
16
|
+
export const SITE_PUBLICATION_RECEIPT_AUDIENCE = 'foundry:site-publication-receipt';
|
|
17
|
+
/** Lowercase hex SHA-256. */
|
|
18
|
+
const sha256Hex = z.string().regex(/^[0-9a-f]{64}$/, 'expected lowercase hex sha-256');
|
|
19
|
+
/** A bounded identifier: printable ASCII, no whitespace, capped. */
|
|
20
|
+
const identifier = z
|
|
21
|
+
.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.max(256)
|
|
24
|
+
.regex(/^[\x21-\x7e]+$/, 'expected a bounded printable identifier');
|
|
25
|
+
/** RFC 3339 UTC instant, seconds precision, `Z` only — no local offsets. */
|
|
26
|
+
const instant = z
|
|
27
|
+
.string()
|
|
28
|
+
.regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, 'expected an RFC 3339 UTC instant');
|
|
29
|
+
/** A count that must stay bounded so a receipt cannot carry unbounded claims. */
|
|
30
|
+
const boundedCount = z.number().int().min(0).max(1_000_000);
|
|
31
|
+
export const publicationProbeSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
/** What was probed, e.g. `html` or `markdown`. */
|
|
34
|
+
kind: z.enum(['html', 'markdown']),
|
|
35
|
+
url: z.string().url().max(2048),
|
|
36
|
+
status: z.number().int().min(100).max(599),
|
|
37
|
+
/** SHA-256 of the exact bytes observed, so Foundry can compare. */
|
|
38
|
+
digest: sha256Hex,
|
|
39
|
+
})
|
|
40
|
+
.strict();
|
|
41
|
+
export const publicationProjectionCountsSchema = z
|
|
42
|
+
.object({
|
|
43
|
+
seo: boundedCount,
|
|
44
|
+
search: boundedCount,
|
|
45
|
+
sitemap: boundedCount,
|
|
46
|
+
feed: boundedCount,
|
|
47
|
+
})
|
|
48
|
+
.strict();
|
|
49
|
+
export const sitePublicationReceiptBodySchema = z
|
|
50
|
+
.object({
|
|
51
|
+
schema: z.literal(SITE_PUBLICATION_RECEIPT_SCHEMA),
|
|
52
|
+
audience: z.literal(SITE_PUBLICATION_RECEIPT_AUDIENCE),
|
|
53
|
+
/** Success and failure are both signed; a silent failure is unverifiable. */
|
|
54
|
+
outcome: z.enum(['success', 'failure']),
|
|
55
|
+
/** Identity of the publishing property (the site). */
|
|
56
|
+
property: z.object({ id: identifier, origin: z.string().url().max(2048) }).strict(),
|
|
57
|
+
/** Identity of the thing published, stable across revisions. */
|
|
58
|
+
content: z
|
|
59
|
+
.object({
|
|
60
|
+
stableId: identifier,
|
|
61
|
+
slug: identifier,
|
|
62
|
+
revisionId: identifier,
|
|
63
|
+
})
|
|
64
|
+
.strict(),
|
|
65
|
+
/** What produced it. */
|
|
66
|
+
source: z
|
|
67
|
+
.object({
|
|
68
|
+
commit: z.string().regex(/^[0-9a-f]{40}$/, 'expected a full git sha'),
|
|
69
|
+
foundryHandoffId: identifier,
|
|
70
|
+
foundryRunId: identifier,
|
|
71
|
+
})
|
|
72
|
+
.strict(),
|
|
73
|
+
/** Logical database identity — never a connection string or credential. */
|
|
74
|
+
database: z.object({ logicalId: identifier }).strict(),
|
|
75
|
+
/** Hash of the public media manifest, not the media itself. */
|
|
76
|
+
publicMediaManifestHash: sha256Hex,
|
|
77
|
+
projections: publicationProjectionCountsSchema,
|
|
78
|
+
probes: z.array(publicationProbeSchema).max(16),
|
|
79
|
+
/** How to undo this publication. */
|
|
80
|
+
rollback: z.object({ pointer: identifier }).strict(),
|
|
81
|
+
/** Replay identity. Supplied by the caller and persisted, never generated here. */
|
|
82
|
+
nonce: identifier,
|
|
83
|
+
issuedAt: instant,
|
|
84
|
+
/** Present only when `outcome` is `failure`, and bounded. */
|
|
85
|
+
failureReason: z.string().min(1).max(512).optional(),
|
|
86
|
+
})
|
|
87
|
+
.strict()
|
|
88
|
+
.superRefine((body, ctx) => {
|
|
89
|
+
if (body.outcome === 'failure' && body.failureReason === undefined) {
|
|
90
|
+
ctx.addIssue({
|
|
91
|
+
code: z.ZodIssueCode.custom,
|
|
92
|
+
path: ['failureReason'],
|
|
93
|
+
message: 'a failure receipt must state its reason',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (body.outcome === 'success' && body.failureReason !== undefined) {
|
|
97
|
+
ctx.addIssue({
|
|
98
|
+
code: z.ZodIssueCode.custom,
|
|
99
|
+
path: ['failureReason'],
|
|
100
|
+
message: 'a success receipt must not carry a failure reason',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
export class PublicationReceiptError extends Error {
|
|
105
|
+
code;
|
|
106
|
+
constructor(code, message) {
|
|
107
|
+
super(message);
|
|
108
|
+
this.name = 'PublicationReceiptError';
|
|
109
|
+
this.code = code;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Validate a receipt body and return its canonical RFC 8785 form.
|
|
114
|
+
*
|
|
115
|
+
* Validation happens before canonicalization on purpose: signing an unvalidated
|
|
116
|
+
* body would produce a verifiable signature over a malformed claim, which is
|
|
117
|
+
* strictly worse than refusing, because downstream would trust it.
|
|
118
|
+
*/
|
|
119
|
+
export function canonicalizeReceiptBody(body) {
|
|
120
|
+
const parsed = sitePublicationReceiptBodySchema.safeParse(body);
|
|
121
|
+
if (!parsed.success) {
|
|
122
|
+
throw new PublicationReceiptError('invalid_body', `Receipt body failed validation: ${parsed.error.issues
|
|
123
|
+
.map((issue) => `${issue.path.join('.')}: ${issue.message}`)
|
|
124
|
+
.join('; ')}`);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
body: parsed.data,
|
|
128
|
+
canonical: canonicalJson(parsed.data),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=receipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.js","sourceRoot":"","sources":["../../../src/engine/publication-receipt/receipt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SITE_PUBLICATION_RECEIPT_AUDIENCE, type SitePublicationReceiptBody } from './receipt.js';
|
|
2
|
+
export interface SignedPublicationReceipt {
|
|
3
|
+
body: SitePublicationReceiptBody;
|
|
4
|
+
/** The exact bytes that were signed. Persist these, not a re-serialization. */
|
|
5
|
+
canonical: string;
|
|
6
|
+
/** Lowercase hex SHA-256 of `canonical`. */
|
|
7
|
+
bodyHash: string;
|
|
8
|
+
/** Base64url, unpadded. */
|
|
9
|
+
signature: string;
|
|
10
|
+
/** Key id the verifier should select. */
|
|
11
|
+
kid: string;
|
|
12
|
+
audience: typeof SITE_PUBLICATION_RECEIPT_AUDIENCE;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validate, canonicalize and sign a receipt body.
|
|
16
|
+
*
|
|
17
|
+
* Deterministic: the same body and key always produce the same bytes and the
|
|
18
|
+
* same signature, which is what makes "retries resend byte-identical bytes"
|
|
19
|
+
* achievable. Nothing is generated here — the nonce and `issuedAt` come from
|
|
20
|
+
* the caller, who is responsible for persisting them once.
|
|
21
|
+
*/
|
|
22
|
+
export declare function signPublicationReceipt(body: unknown, key: CryptoKey, kid: string): Promise<SignedPublicationReceipt>;
|
|
23
|
+
/**
|
|
24
|
+
* Verify a receipt as Foundry would: re-canonicalize the body from scratch and
|
|
25
|
+
* check the signature over THOSE bytes.
|
|
26
|
+
*
|
|
27
|
+
* Deliberately ignores any `canonical` string supplied alongside the receipt. A
|
|
28
|
+
* verifier that trusts the sender's canonical form would accept a signature
|
|
29
|
+
* over bytes that do not match the body it then acts on — which is the whole
|
|
30
|
+
* attack canonicalization exists to prevent.
|
|
31
|
+
*/
|
|
32
|
+
export declare function verifyPublicationReceipt(receipt: {
|
|
33
|
+
body: unknown;
|
|
34
|
+
signature: string;
|
|
35
|
+
}, key: CryptoKey): Promise<boolean>;
|
|
36
|
+
//# sourceMappingURL=signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../../src/engine/publication-receipt/signature.ts"],"names":[],"mappings":"AASA,OAAO,EAGN,iCAAiC,EACjC,KAAK,0BAA0B,EAE/B,MAAM,cAAc,CAAA;AAErB,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,0BAA0B,CAAA;IAChC,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,OAAO,iCAAiC,CAAA;CAClD;AAwBD;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC3C,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,SAAS,EACd,GAAG,EAAE,MAAM,GACT,OAAO,CAAC,wBAAwB,CAAC,CAcnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAC7C,GAAG,EAAE,SAAS,GACZ,OAAO,CAAC,OAAO,CAAC,CAmBlB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Ed25519 signature envelope for `site.publication.receipt.v1` (#342).
|
|
2
|
+
//
|
|
3
|
+
// Signs the RFC 8785 canonical bytes of the receipt body, so the signature is
|
|
4
|
+
// over exactly what Foundry will re-canonicalize and compare — not over a
|
|
5
|
+
// re-serialization that might differ in key order.
|
|
6
|
+
//
|
|
7
|
+
// crypto.subtle only; never node:crypto. The package runs in Workers.
|
|
8
|
+
import { canonicalJsonSha256 } from './canonical-json.js';
|
|
9
|
+
import { canonicalizeReceiptBody, PublicationReceiptError, SITE_PUBLICATION_RECEIPT_AUDIENCE, sitePublicationReceiptBodySchema, } from './receipt.js';
|
|
10
|
+
function toBase64Url(bytes) {
|
|
11
|
+
let binary = '';
|
|
12
|
+
for (const byte of bytes)
|
|
13
|
+
binary += String.fromCharCode(byte);
|
|
14
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
15
|
+
}
|
|
16
|
+
function fromBase64Url(value) {
|
|
17
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value)) {
|
|
18
|
+
throw new PublicationReceiptError('invalid_body', 'Signature is not unpadded base64url');
|
|
19
|
+
}
|
|
20
|
+
const padded = value.replace(/-/g, '+').replace(/_/g, '/');
|
|
21
|
+
const binary = atob(padded + '='.repeat((4 - (padded.length % 4)) % 4));
|
|
22
|
+
const bytes = new Uint8Array(binary.length);
|
|
23
|
+
for (let index = 0; index < binary.length; index += 1)
|
|
24
|
+
bytes[index] = binary.charCodeAt(index);
|
|
25
|
+
return bytes;
|
|
26
|
+
}
|
|
27
|
+
/** ArrayBuffer-backed copy — TextEncoder output is not a `BufferSource`. */
|
|
28
|
+
function encode(value) {
|
|
29
|
+
return Uint8Array.from(new TextEncoder().encode(value));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validate, canonicalize and sign a receipt body.
|
|
33
|
+
*
|
|
34
|
+
* Deterministic: the same body and key always produce the same bytes and the
|
|
35
|
+
* same signature, which is what makes "retries resend byte-identical bytes"
|
|
36
|
+
* achievable. Nothing is generated here — the nonce and `issuedAt` come from
|
|
37
|
+
* the caller, who is responsible for persisting them once.
|
|
38
|
+
*/
|
|
39
|
+
export async function signPublicationReceipt(body, key, kid) {
|
|
40
|
+
if (key.type !== 'private') {
|
|
41
|
+
throw new PublicationReceiptError('invalid_key', 'Signing requires an Ed25519 private key');
|
|
42
|
+
}
|
|
43
|
+
const { body: validated, canonical } = canonicalizeReceiptBody(body);
|
|
44
|
+
const signature = await globalThis.crypto.subtle.sign({ name: 'Ed25519' }, key, encode(canonical));
|
|
45
|
+
return {
|
|
46
|
+
body: validated,
|
|
47
|
+
canonical,
|
|
48
|
+
bodyHash: await canonicalJsonSha256(validated),
|
|
49
|
+
signature: toBase64Url(new Uint8Array(signature)),
|
|
50
|
+
kid,
|
|
51
|
+
audience: SITE_PUBLICATION_RECEIPT_AUDIENCE,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Verify a receipt as Foundry would: re-canonicalize the body from scratch and
|
|
56
|
+
* check the signature over THOSE bytes.
|
|
57
|
+
*
|
|
58
|
+
* Deliberately ignores any `canonical` string supplied alongside the receipt. A
|
|
59
|
+
* verifier that trusts the sender's canonical form would accept a signature
|
|
60
|
+
* over bytes that do not match the body it then acts on — which is the whole
|
|
61
|
+
* attack canonicalization exists to prevent.
|
|
62
|
+
*/
|
|
63
|
+
export async function verifyPublicationReceipt(receipt, key) {
|
|
64
|
+
const parsed = sitePublicationReceiptBodySchema.safeParse(receipt.body);
|
|
65
|
+
if (!parsed.success)
|
|
66
|
+
return false;
|
|
67
|
+
if (parsed.data.audience !== SITE_PUBLICATION_RECEIPT_AUDIENCE)
|
|
68
|
+
return false;
|
|
69
|
+
let signatureBytes;
|
|
70
|
+
try {
|
|
71
|
+
signatureBytes = fromBase64Url(receipt.signature);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const { canonical } = canonicalizeReceiptBody(parsed.data);
|
|
77
|
+
return await globalThis.crypto.subtle.verify({ name: 'Ed25519' }, key, Uint8Array.from(signatureBytes), encode(canonical));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.js","sourceRoot":"","sources":["../../../src/engine/publication-receipt/signature.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publication.d.ts","sourceRoot":"","sources":["../../src/engine/publication.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"publication.d.ts","sourceRoot":"","sources":["../../src/engine/publication.ts"],"names":[],"mappings":"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"}
|
|
@@ -410,6 +410,8 @@ function assertPublicationSnapshotBodyValid(snapshot, contentId) {
|
|
|
410
410
|
body_html: typeof bodyHtml === 'string' ? bodyHtml : null,
|
|
411
411
|
}, {
|
|
412
412
|
source: 'publish-one',
|
|
413
|
+
// #329: source-section defects block at publish, warn on save.
|
|
414
|
+
blockSourceSectionDefects: true,
|
|
413
415
|
contentId,
|
|
414
416
|
requireBody: true,
|
|
415
417
|
});
|