@growth-labs/cms 0.8.20 → 0.8.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/dist/cli/foundry-emit.d.ts +14 -0
  2. package/dist/cli/foundry-emit.d.ts.map +1 -0
  3. package/dist/cli/foundry-emit.js +69 -0
  4. package/dist/cli/foundry-emit.js.map +1 -0
  5. package/dist/engine/foundry-dispatch.d.ts +1 -0
  6. package/dist/engine/foundry-dispatch.d.ts.map +1 -1
  7. package/dist/engine/foundry-dispatch.js +1 -1
  8. package/dist/engine/foundry-dispatch.js.map +1 -1
  9. package/dist/engine/fronts-publish-intent.d.ts +1 -1
  10. package/dist/engine/fronts-publish-intent.d.ts.map +1 -1
  11. package/dist/engine/fronts-publish-intent.js +12 -1
  12. package/dist/engine/fronts-publish-intent.js.map +1 -1
  13. package/dist/engine/index.d.ts +1 -0
  14. package/dist/engine/index.d.ts.map +1 -1
  15. package/dist/engine/index.js +2 -0
  16. package/dist/engine/index.js.map +1 -1
  17. package/dist/engine/publication-receipt/receipt.d.ts +20 -20
  18. package/dist/engine/publisher.d.ts +16 -1
  19. package/dist/engine/publisher.d.ts.map +1 -1
  20. package/dist/engine/publisher.js +55 -4
  21. package/dist/engine/publisher.js.map +1 -1
  22. package/dist/engine/tags.d.ts.map +1 -1
  23. package/dist/engine/tags.js +18 -1
  24. package/dist/engine/tags.js.map +1 -1
  25. package/dist/engine/topics.d.ts.map +1 -1
  26. package/dist/engine/topics.js +4 -1
  27. package/dist/engine/topics.js.map +1 -1
  28. package/dist/engine/video-source.d.ts +21 -0
  29. package/dist/engine/video-source.d.ts.map +1 -1
  30. package/dist/engine/video-source.js +40 -0
  31. package/dist/engine/video-source.js.map +1 -1
  32. package/dist/foundry-emit.d.ts +146 -0
  33. package/dist/foundry-emit.d.ts.map +1 -0
  34. package/dist/foundry-emit.js +189 -0
  35. package/dist/foundry-emit.js.map +1 -0
  36. package/dist/integration/index.d.ts.map +1 -1
  37. package/dist/integration/index.js +9 -0
  38. package/dist/integration/index.js.map +1 -1
  39. package/dist/integration/options.d.ts +24 -0
  40. package/dist/integration/options.d.ts.map +1 -1
  41. package/dist/integration/options.js +22 -0
  42. package/dist/integration/options.js.map +1 -1
  43. package/dist/providers/null.d.ts.map +1 -1
  44. package/dist/providers/null.js +6 -0
  45. package/dist/providers/null.js.map +1 -1
  46. package/dist/providers/types.d.ts +56 -0
  47. package/dist/providers/types.d.ts.map +1 -1
  48. package/dist/providers/types.js.map +1 -1
  49. package/dist/routes/ai.d.ts.map +1 -1
  50. package/dist/routes/ai.js +21 -13
  51. package/dist/routes/ai.js.map +1 -1
  52. package/dist/routes/analytics.d.ts +1 -0
  53. package/dist/routes/analytics.d.ts.map +1 -1
  54. package/dist/routes/analytics.js +20 -0
  55. package/dist/routes/analytics.js.map +1 -1
  56. package/dist/routes/content.d.ts +27 -0
  57. package/dist/routes/content.d.ts.map +1 -1
  58. package/dist/routes/content.js +58 -12
  59. package/dist/routes/content.js.map +1 -1
  60. package/dist/routes/foundry-publish.d.ts +50 -0
  61. package/dist/routes/foundry-publish.d.ts.map +1 -1
  62. package/dist/routes/foundry-publish.js +540 -27
  63. package/dist/routes/foundry-publish.js.map +1 -1
  64. package/dist/routes/machine-context.d.ts +6 -0
  65. package/dist/routes/machine-context.d.ts.map +1 -0
  66. package/dist/routes/machine-context.js +20 -0
  67. package/dist/routes/machine-context.js.map +1 -0
  68. package/dist/routes/surveys.d.ts +14 -1
  69. package/dist/routes/surveys.d.ts.map +1 -1
  70. package/dist/routes/surveys.js +515 -10
  71. package/dist/routes/surveys.js.map +1 -1
  72. package/dist/schema/insights-ingest.d.ts +8 -8
  73. package/dist/schema/migrations.d.ts.map +1 -1
  74. package/dist/schema/migrations.js +15 -0
  75. package/dist/schema/migrations.js.map +1 -1
  76. package/dist/schema/tables.d.ts +1 -1
  77. package/dist/schema/tables.d.ts.map +1 -1
  78. package/dist/schema/tables.js +2 -0
  79. package/dist/schema/tables.js.map +1 -1
  80. package/dist/surveys/access.d.ts +1 -0
  81. package/dist/surveys/access.d.ts.map +1 -1
  82. package/dist/surveys/access.js +13 -4
  83. package/dist/surveys/access.js.map +1 -1
  84. package/dist/surveys/auto-label.d.ts +100 -0
  85. package/dist/surveys/auto-label.d.ts.map +1 -0
  86. package/dist/surveys/auto-label.js +325 -0
  87. package/dist/surveys/auto-label.js.map +1 -0
  88. package/dist/surveys/schema.d.ts +38 -12
  89. package/dist/surveys/schema.d.ts.map +1 -1
  90. package/dist/surveys/schema.js +18 -1
  91. package/dist/surveys/schema.js.map +1 -1
  92. package/dist/ui/api/_content-config.d.ts.map +1 -1
  93. package/dist/ui/api/_content-config.js +4 -0
  94. package/dist/ui/api/_content-config.js.map +1 -1
  95. package/dist/ui/api/analytics.d.ts.map +1 -1
  96. package/dist/ui/api/analytics.js +5 -2
  97. package/dist/ui/api/analytics.js.map +1 -1
  98. package/dist/ui/api/foundry/articles/[external_id]/publish.d.ts +3 -0
  99. package/dist/ui/api/foundry/articles/[external_id]/publish.d.ts.map +1 -0
  100. package/dist/ui/api/foundry/articles/[external_id]/publish.js +14 -0
  101. package/dist/ui/api/foundry/articles/[external_id]/publish.js.map +1 -0
  102. package/dist/ui/api/surveys/[surveyId]/answers/label.d.ts +3 -0
  103. package/dist/ui/api/surveys/[surveyId]/answers/label.d.ts.map +1 -0
  104. package/dist/ui/api/surveys/[surveyId]/answers/label.js +17 -0
  105. package/dist/ui/api/surveys/[surveyId]/answers/label.js.map +1 -0
  106. package/dist/ui/api/surveys/[surveyId].d.ts.map +1 -1
  107. package/dist/ui/api/surveys/[surveyId].js +28 -1
  108. package/dist/ui/api/surveys/[surveyId].js.map +1 -1
  109. package/dist/ui/commands.d.ts.map +1 -1
  110. package/dist/ui/commands.js +2 -0
  111. package/dist/ui/commands.js.map +1 -1
  112. package/dist/ui/hash-router.d.ts +1 -1
  113. package/dist/ui/hash-router.d.ts.map +1 -1
  114. package/dist/ui/hash-router.js +1 -0
  115. package/dist/ui/hash-router.js.map +1 -1
  116. package/dist/ui/nav.d.ts.map +1 -1
  117. package/dist/ui/nav.js +1 -0
  118. package/dist/ui/nav.js.map +1 -1
  119. package/dist/ui/screens/AnalyticsScreen.d.ts +6 -1
  120. package/dist/ui/screens/AnalyticsScreen.d.ts.map +1 -1
  121. package/dist/ui/screens/AnalyticsScreen.js +13 -8
  122. package/dist/ui/screens/AnalyticsScreen.js.map +1 -1
  123. package/dist/ui/screens/PodcastListeningScreen.d.ts +6 -0
  124. package/dist/ui/screens/PodcastListeningScreen.d.ts.map +1 -0
  125. package/dist/ui/screens/PodcastListeningScreen.js +244 -0
  126. package/dist/ui/screens/PodcastListeningScreen.js.map +1 -0
  127. package/dist/ui/screens/SurveyResponsesScreen.d.ts +4 -2
  128. package/dist/ui/screens/SurveyResponsesScreen.d.ts.map +1 -1
  129. package/dist/ui/screens/SurveyResponsesScreen.js +71 -12
  130. package/dist/ui/screens/SurveyResponsesScreen.js.map +1 -1
  131. package/dist/ui/screens/analytics-data.d.ts +14 -0
  132. package/dist/ui/screens/analytics-data.d.ts.map +1 -1
  133. package/dist/ui/screens/analytics-data.js +16 -0
  134. package/dist/ui/screens/analytics-data.js.map +1 -1
  135. package/dist/ui/screens/podcast-listening-data.d.ts +19 -0
  136. package/dist/ui/screens/podcast-listening-data.d.ts.map +1 -0
  137. package/dist/ui/screens/podcast-listening-data.js +98 -0
  138. package/dist/ui/screens/podcast-listening-data.js.map +1 -0
  139. package/dist/ui/screens/registry.d.ts.map +1 -1
  140. package/dist/ui/screens/registry.js +2 -0
  141. package/dist/ui/screens/registry.js.map +1 -1
  142. package/docs/foundry-publish.md +208 -0
  143. package/migrations/0033_survey_answer_labels.sql +15 -0
  144. package/package.json +9 -3
  145. package/src/cli/foundry-emit.ts +85 -0
  146. package/src/engine/foundry-dispatch.ts +1 -1
  147. package/src/engine/fronts-publish-intent.ts +23 -1
  148. package/src/engine/index.ts +5 -0
  149. package/src/engine/publisher.ts +80 -4
  150. package/src/engine/tags.ts +21 -1
  151. package/src/engine/topics.ts +4 -1
  152. package/src/engine/video-source.ts +44 -0
  153. package/src/foundry-emit.ts +255 -0
  154. package/src/integration/index.ts +9 -0
  155. package/src/integration/options.ts +23 -0
  156. package/src/providers/null.ts +6 -0
  157. package/src/providers/types.ts +52 -0
  158. package/src/routes/ai.ts +29 -17
  159. package/src/routes/analytics.ts +21 -0
  160. package/src/routes/content.ts +81 -15
  161. package/src/routes/foundry-publish.ts +746 -29
  162. package/src/routes/machine-context.ts +24 -0
  163. package/src/routes/surveys.ts +587 -12
  164. package/src/schema/migrations.ts +15 -0
  165. package/src/schema/tables.ts +2 -0
  166. package/src/surveys/access.ts +14 -4
  167. package/src/surveys/auto-label.ts +420 -0
  168. package/src/surveys/schema.ts +25 -1
  169. package/src/ui/api/_content-config.ts +6 -0
  170. package/src/ui/api/analytics.ts +5 -2
  171. package/src/ui/api/foundry/articles/[external_id]/publish.ts +18 -0
  172. package/src/ui/api/surveys/[surveyId]/answers/label.ts +23 -0
  173. package/src/ui/api/surveys/[surveyId].ts +37 -3
  174. package/src/ui/commands.ts +2 -0
  175. package/src/ui/hash-router.ts +1 -0
  176. package/src/ui/nav.ts +1 -0
  177. package/src/ui/screens/AnalyticsScreen.tsx +34 -6
  178. package/src/ui/screens/PodcastListeningScreen.tsx +529 -0
  179. package/src/ui/screens/SurveyResponsesScreen.tsx +179 -13
  180. package/src/ui/screens/analytics-data.ts +18 -0
  181. package/src/ui/screens/podcast-listening-data.ts +114 -0
  182. package/src/ui/screens/registry.tsx +2 -0
@@ -1,7 +1,17 @@
1
+ import { z } from 'zod';
1
2
  import { nullProviders } from '../providers/null.js';
2
3
  import { ProviderHttpError } from '../providers/types.js';
4
+ import { canLabelSurveyAnswers } from '../surveys/access.js';
5
+ import { containsPersonalDetails, SURVEY_AUTO_LABEL_BATCH_LIMIT, scheduleSurveyAutoLabel, } from '../surveys/auto-label.js';
3
6
  import { SURVEY_ERROR_CODE_HEADER, SURVEY_ERROR_DEFINITIONS, surveyErrorBody, } from '../surveys/errors.js';
4
- import { SurveyCsvResultSchema, SurveyIdSchema, SurveyResultsSchema } from '../surveys/schema.js';
7
+ import { BoundedRecordIdSchema, SurveyCsvResultSchema, SurveyIdSchema, SurveyQuestionIdSchema, SurveyResultsSchema, } from '../surveys/schema.js';
8
+ const SurveyAnswerLabelRequestSchema = z
9
+ .object({
10
+ responseId: BoundedRecordIdSchema,
11
+ questionId: SurveyQuestionIdSchema,
12
+ label: z.enum(['technical', 'general']),
13
+ })
14
+ .strict();
5
15
  export function createSurveyRoutes(config) {
6
16
  const providers = { ...nullProviders, ...(config.providers ?? {}) };
7
17
  return {
@@ -20,7 +30,23 @@ export function createSurveyRoutes(config) {
20
30
  if (!parsed.success || parsed.data.survey.id !== surveyId) {
21
31
  return surveyErrorResponse('survey_provider_malformed');
22
32
  }
23
- return responseJson(parsed.data);
33
+ const caller = await resolveSurveyCaller(config.authz, ctx);
34
+ // Both roles share one path: any written answer on the page needs
35
+ // the label index — the owner view decorates with it, the non-owner
36
+ // view withholds by it, and auto-labeling (when enabled) schedules
37
+ // against it after the response is built. The unlabeled set is
38
+ // computed once: the scheduler dispatches (a bounded slice of) it,
39
+ // and the owner payload counts it.
40
+ if (!hasWrittenAnswers(parsed.data))
41
+ return responseJson(parsed.data);
42
+ const labels = await loadAnswerLabelsOrFail(ctx.db, surveyId);
43
+ if (labels instanceof Response)
44
+ return labels;
45
+ const unlabeled = unlabeledWrittenAnswers(parsed.data, labels);
46
+ scheduleAutoLabelIfEnabled(ctx, config, surveyId, unlabeled);
47
+ return responseJson(canLabelSurveyAnswers(caller?.role)
48
+ ? withOwnerLabelCounts(withOwnerLabels(parsed.data, labels), unlabeled)
49
+ : withholdNonGeneralAnswers(parsed.data, labels));
24
50
  }
25
51
  catch (error) {
26
52
  return providerFailure(error);
@@ -37,18 +63,57 @@ export function createSurveyRoutes(config) {
37
63
  const parsed = SurveyCsvResultSchema.safeParse(await providers.surveys?.getCsv({ surveyId }));
38
64
  if (!parsed.success)
39
65
  return surveyErrorResponse('survey_provider_malformed');
40
- return new Response(parsed.data.content, {
41
- headers: {
42
- 'Cache-Control': 'no-store',
43
- 'Content-Disposition': `attachment; filename="${safeCsvFilename(parsed.data.filename)}"`,
44
- 'Content-Type': 'text/csv; charset=utf-8',
45
- },
46
- });
66
+ const caller = await resolveSurveyCaller(config.authz, ctx);
67
+ // The owner exports byte-identical provider bytes; every other role
68
+ // gets text cells redacted before the bytes leave the Worker.
69
+ if (!canLabelSurveyAnswers(caller?.role)) {
70
+ const redacted = await redactCsvForNonOwner(providers, ctx, surveyId, parsed.data.content);
71
+ if (redacted instanceof Response)
72
+ return redacted;
73
+ return csvResponse({ filename: parsed.data.filename, content: redacted });
74
+ }
75
+ return csvResponse(parsed.data);
47
76
  }
48
77
  catch (error) {
49
78
  return providerFailure(error);
50
79
  }
51
80
  },
81
+ async label(ctx) {
82
+ const denied = await requireSurveyAccess(config.authz, ctx);
83
+ if (denied)
84
+ return withNoStoreAuthFailure(denied);
85
+ const caller = await resolveSurveyCaller(config.authz, ctx);
86
+ if (!canLabelSurveyAnswers(caller?.role))
87
+ return surveyErrorResponse('survey_forbidden');
88
+ const surveyId = parseSurveyId(ctx);
89
+ if (!surveyId)
90
+ return surveyErrorResponse('survey_invalid_request');
91
+ let body;
92
+ try {
93
+ body = await ctx.request.json();
94
+ }
95
+ catch {
96
+ return surveyErrorResponse('survey_invalid_request');
97
+ }
98
+ const parsed = SurveyAnswerLabelRequestSchema.safeParse(body);
99
+ if (!parsed.success)
100
+ return surveyErrorResponse('survey_invalid_request');
101
+ try {
102
+ await ctx.db
103
+ .prepare(`INSERT INTO survey_answer_labels
104
+ (survey_id, response_id, question_id, label, source, labeled_by, labeled_at)
105
+ VALUES (?, ?, ?, ?, 'owner', ?, ?)
106
+ ON CONFLICT(survey_id, response_id, question_id) DO UPDATE SET
107
+ label = excluded.label, source = 'owner',
108
+ labeled_by = excluded.labeled_by, labeled_at = excluded.labeled_at`)
109
+ .bind(surveyId, parsed.data.responseId, parsed.data.questionId, parsed.data.label, caller?.subject ?? null, Date.now())
110
+ .run();
111
+ }
112
+ catch {
113
+ return surveyErrorResponse('survey_internal_failure');
114
+ }
115
+ return responseJson({ surveyId, ...parsed.data });
116
+ },
52
117
  };
53
118
  }
54
119
  async function requireSurveyAccess(authz, ctx) {
@@ -56,6 +121,446 @@ async function requireSurveyAccess(authz, ctx) {
56
121
  return surveyErrorResponse('survey_internal_failure');
57
122
  return authz.requireRole('view_survey_responses', ctx);
58
123
  }
124
+ /**
125
+ * The caller's CMS role, resolved server-side from the injected authz seam.
126
+ * A host that has not wired `getUser` gets null — which every label decision
127
+ * reads as "not the owner", so an unwired seam withholds rather than leaks.
128
+ */
129
+ async function resolveSurveyCaller(authz, ctx) {
130
+ if (!authz.getUser)
131
+ return null;
132
+ try {
133
+ return await authz.getUser(ctx);
134
+ }
135
+ catch {
136
+ return null;
137
+ }
138
+ }
139
+ function answerLabelKey(responseId, questionId) {
140
+ return `${responseId}\u0000${questionId}`;
141
+ }
142
+ async function loadAnswerLabels(db, surveyId) {
143
+ const result = await db
144
+ .prepare('SELECT response_id, question_id, label, source FROM survey_answer_labels WHERE survey_id = ?')
145
+ .bind(surveyId)
146
+ .all();
147
+ const labels = new Map();
148
+ for (const row of result.results ?? []) {
149
+ if (row.label === 'technical' || row.label === 'general') {
150
+ labels.set(answerLabelKey(row.response_id, row.question_id), {
151
+ label: row.label,
152
+ source: row.source,
153
+ });
154
+ }
155
+ }
156
+ return labels;
157
+ }
158
+ /**
159
+ * Label-store reads fail loudly (500), never by degrading to an unfiltered
160
+ * payload: a silent empty read would hand technical comments to non-owners.
161
+ */
162
+ async function loadAnswerLabelsOrFail(db, surveyId) {
163
+ try {
164
+ return await loadAnswerLabels(db, surveyId);
165
+ }
166
+ catch {
167
+ return surveyErrorResponse('survey_internal_failure');
168
+ }
169
+ }
170
+ function questionIndex(data) {
171
+ const choiceOptions = new Map();
172
+ for (const question of data.questions) {
173
+ if (question.kind === 'single_choice' || question.kind === 'multi_choice') {
174
+ choiceOptions.set(question.id, new Set(question.options));
175
+ }
176
+ }
177
+ return {
178
+ textQuestionIds: new Set(data.questions.filter((question) => question.kind === 'text').map((question) => question.id)),
179
+ allQuestionIds: new Set(data.questions.map((question) => question.id)),
180
+ choiceOptions,
181
+ };
182
+ }
183
+ function emptyQuestionIndex() {
184
+ return { textQuestionIds: new Set(), allQuestionIds: new Set(), choiceOptions: new Map() };
185
+ }
186
+ function hasWrittenAnswers(data) {
187
+ if (data.freeText.length > 0)
188
+ return true;
189
+ const questions = questionIndex(data);
190
+ return data.responses.some((response) => (response.answers ?? []).some((answer) => isWrittenAnswer(answer, questions)));
191
+ }
192
+ /**
193
+ * A written (potentially technical) answer: one attached to a text question,
194
+ * a choice value the question never declared ("Other: …" free text,
195
+ * sec-review publishing #22), or a string or array answer to a question the
196
+ * payload no longer knows — a retired text question stays withheld rather
197
+ * than leaking. Declared choice selections and scale numbers are never
198
+ * written answers.
199
+ */
200
+ function isWrittenAnswer(answer, questions) {
201
+ if (questions.textQuestionIds.has(answer.questionId))
202
+ return true;
203
+ const options = questions.choiceOptions.get(answer.questionId);
204
+ if (!options)
205
+ return typeof answer.value !== 'number';
206
+ if (typeof answer.value === 'string')
207
+ return !options.has(answer.value);
208
+ if (Array.isArray(answer.value))
209
+ return answer.value.some((value) => !options.has(value));
210
+ return false;
211
+ }
212
+ /**
213
+ * The non-owner view is an allow-list, not a block-list (operator ruling
214
+ * 2026-10-02, restated in the packet addendum): only answers labeled 'general'
215
+ * pass. Technical AND unlabeled answers are withheld — a new comment is
216
+ * owner-only until it is explicitly labeled general. Declared choice
217
+ * selections and scale values are not written answers, so they are unaffected;
218
+ * a free-typed choice value is written text and is withheld.
219
+ */
220
+ function withholdNonGeneralAnswers(data, labels) {
221
+ const questions = questionIndex(data);
222
+ return {
223
+ ...data,
224
+ freeText: data.freeText.filter((entry) => labels.get(answerLabelKey(entry.responseId, entry.questionId))?.label === 'general'),
225
+ responses: data.responses.map((response) => ({
226
+ ...response,
227
+ answers: (response.answers ?? []).flatMap((answer) => {
228
+ const kept = nonOwnerAnswer(answer, response.id, questions, labels);
229
+ return kept === null ? [] : [kept];
230
+ }),
231
+ })),
232
+ };
233
+ }
234
+ /**
235
+ * One answer as a non-owner may see it, or null to withhold it: 'general'
236
+ * passes untouched; a wholly written answer is withheld; a multi-choice that
237
+ * mixes declared selections with free-typed values keeps only the declared
238
+ * ones, so a declared selection never carries its sibling "Other: …" out.
239
+ */
240
+ function nonOwnerAnswer(answer, responseId, questions, labels) {
241
+ if (labels.get(answerLabelKey(responseId, answer.questionId))?.label === 'general')
242
+ return answer;
243
+ if (questions.textQuestionIds.has(answer.questionId))
244
+ return null;
245
+ const options = questions.choiceOptions.get(answer.questionId);
246
+ if (!options) {
247
+ // A question the payload no longer knows: strings and arrays stay
248
+ // withheld (fail closed); numbers pass as scale-like.
249
+ return typeof answer.value === 'number' ? answer : null;
250
+ }
251
+ if (typeof answer.value === 'string')
252
+ return options.has(answer.value) ? answer : null;
253
+ if (Array.isArray(answer.value)) {
254
+ const declared = answer.value.filter((value) => options.has(value));
255
+ if (declared.length === answer.value.length)
256
+ return answer;
257
+ return declared.length > 0 ? { ...answer, value: declared } : null;
258
+ }
259
+ return answer;
260
+ }
261
+ /**
262
+ * The owner sees everything, with each written answer's current label and its
263
+ * provenance (`labelSource`: who labeled it, so the screen can badge the
264
+ * automatic ones). Non-owner payloads are never decorated — they pass through
265
+ * withholdNonGeneralAnswers untouched.
266
+ */
267
+ function withOwnerLabels(data, labels) {
268
+ return {
269
+ ...data,
270
+ freeText: data.freeText.map((entry) => {
271
+ const row = labels.get(answerLabelKey(entry.responseId, entry.questionId));
272
+ if (row === undefined)
273
+ return entry;
274
+ const labelSource = isAnswerLabelSource(row.source) ? row.source : undefined;
275
+ return labelSource === undefined
276
+ ? { ...entry, label: row.label }
277
+ : { ...entry, label: row.label, labelSource };
278
+ }),
279
+ };
280
+ }
281
+ function isAnswerLabelSource(value) {
282
+ return value === 'owner' || value === 'auto' || value === 'import';
283
+ }
284
+ /**
285
+ * The owner payload also says how many written answers on this page are still
286
+ * unlabeled — the whole team-hidden set, plus the subset the personal-details
287
+ * pre-filter will never dispatch (owner labels those by hand). Attached only
288
+ * when non-zero; non-owner payloads are never decorated.
289
+ */
290
+ function withOwnerLabelCounts(data, unlabeled) {
291
+ const personalDetails = unlabeled.filter((candidate) => containsPersonalDetails(candidate.answerText)).length;
292
+ return {
293
+ ...data,
294
+ ...(unlabeled.length > 0 ? { unlabeledCount: unlabeled.length } : {}),
295
+ ...(personalDetails > 0 ? { personalDetailsCount: personalDetails } : {}),
296
+ };
297
+ }
298
+ /**
299
+ * Hand the current page's unlabeled written answers to the background
300
+ * labeler (surveys.autoLabel). A no-op unless the option is on, the host
301
+ * wired LlmDispatch and the attempt store, and the request carries a
302
+ * waitUntil seam; scheduling is synchronous, so the results response is
303
+ * already on its way.
304
+ */
305
+ function scheduleAutoLabelIfEnabled(ctx, config, surveyId, unlabeled) {
306
+ if (!config.autoLabel?.llm || !ctx.waitUntil)
307
+ return;
308
+ const batch = unlabeled.slice(0, SURVEY_AUTO_LABEL_BATCH_LIMIT);
309
+ if (batch.length === 0)
310
+ return;
311
+ scheduleSurveyAutoLabel({
312
+ surveyId,
313
+ db: ctx.db,
314
+ llm: config.autoLabel.llm,
315
+ attempts: config.autoLabel.attempts,
316
+ waitUntil: ctx.waitUntil,
317
+ }, batch);
318
+ }
319
+ /**
320
+ * Every unlabeled written answer on the current page, in payload order
321
+ * (freeText first, then free-typed choice values inside responses).
322
+ * Already-labeled answers — owner or import — are never returned; the auto
323
+ * INSERT's ON CONFLICT DO NOTHING is the second guard when the in-memory
324
+ * index is stale. The scheduler caps its dispatch slice at
325
+ * SURVEY_AUTO_LABEL_BATCH_LIMIT; the owner's unlabeledCount uses the full set.
326
+ */
327
+ function unlabeledWrittenAnswers(data, labels) {
328
+ if (data.freeText.length === 0 && data.responses.length === 0)
329
+ return [];
330
+ const questions = questionIndex(data);
331
+ const promptById = new Map(data.questions.map((question) => [question.id, question.prompt]));
332
+ const candidates = [];
333
+ const seen = new Set();
334
+ const consider = (responseId, questionId, answerText) => {
335
+ const key = answerLabelKey(responseId, questionId);
336
+ if (seen.has(key) || labels.has(key))
337
+ return;
338
+ seen.add(key);
339
+ candidates.push({
340
+ responseId,
341
+ questionId,
342
+ questionPrompt: promptById.get(questionId) ?? '',
343
+ answerText,
344
+ });
345
+ };
346
+ for (const entry of data.freeText) {
347
+ consider(entry.responseId, entry.questionId, entry.value);
348
+ }
349
+ for (const response of data.responses) {
350
+ for (const answer of response.answers ?? []) {
351
+ if (!isWrittenAnswer(answer, questions))
352
+ continue;
353
+ if (typeof answer.value === 'string') {
354
+ consider(response.id, answer.questionId, answer.value);
355
+ }
356
+ else if (Array.isArray(answer.value)) {
357
+ // A multi-choice mixing declared selections with free-typed values:
358
+ // only the free-typed part is written text.
359
+ const options = questions.choiceOptions.get(answer.questionId);
360
+ const written = answer.value.filter((value) => !options?.has(value));
361
+ if (written.length > 0) {
362
+ consider(response.id, answer.questionId, written.join(' '));
363
+ }
364
+ }
365
+ }
366
+ }
367
+ return candidates;
368
+ }
369
+ /**
370
+ * Redacts the CSV for a non-owner: every cell that holds written text (a text
371
+ * answer, an unknown question's answer, or a choice value the question never
372
+ * declared) is blanked or reduced to its declared selections unless labeled
373
+ * 'general', and every cell beyond the header width is dropped — an overlong
374
+ * row is an unknown shape whose extras never pass through (sec-review
375
+ * publishing #22). Returns the redacted CSV text, or a Response when the shape
376
+ * is unrecognised (loud 500 — passing provider bytes through unrecognised
377
+ * would leak them) or a dependency failed. Byte-identical passthrough when
378
+ * nothing needs changing.
379
+ */
380
+ async function redactCsvForNonOwner(providers, ctx, surveyId, content) {
381
+ const rows = parseCsvRows(content);
382
+ if (!rows || rows.length === 0)
383
+ return surveyErrorResponse('survey_internal_failure');
384
+ const header = rows[0];
385
+ const answerColumns = header.reduce((columns, column, index) => {
386
+ if (column.startsWith('answer:'))
387
+ columns.push(index);
388
+ return columns;
389
+ }, []);
390
+ const overlong = rows.some((row) => row.length > header.length);
391
+ if (answerColumns.length === 0 && !overlong)
392
+ return content;
393
+ // Which cells can hold written text: the question kinds come from the
394
+ // provider's own results payload. A column whose question is unknown is
395
+ // treated as text — an answer that cannot be proven non-text is withheld
396
+ // when it cannot be proven 'general'.
397
+ let questions = emptyQuestionIndex();
398
+ if (answerColumns.length > 0) {
399
+ try {
400
+ const results = SurveyResultsSchema.safeParse(await providers.surveys?.getResults({ surveyId, offset: 0 }));
401
+ if (!results.success || results.data.survey.id !== surveyId) {
402
+ return surveyErrorResponse('survey_provider_malformed');
403
+ }
404
+ questions = questionIndex(results.data);
405
+ }
406
+ catch (error) {
407
+ return providerFailure(error);
408
+ }
409
+ }
410
+ let labels = new Map();
411
+ if (answerColumns.length > 0) {
412
+ const loaded = await loadAnswerLabelsOrFail(ctx.db, surveyId);
413
+ if (loaded instanceof Response)
414
+ return loaded;
415
+ labels = loaded;
416
+ }
417
+ const responseIdIndex = header.indexOf('response_id');
418
+ let blanked = 0;
419
+ for (const row of rows.slice(1)) {
420
+ if (row.length > header.length)
421
+ row.length = header.length;
422
+ const responseId = responseIdIndex >= 0 ? row[responseIdIndex] : null;
423
+ for (const column of answerColumns) {
424
+ const questionId = header[column].slice('answer:'.length);
425
+ if (responseId !== null &&
426
+ responseId !== '' &&
427
+ labels.get(answerLabelKey(responseId, questionId))?.label === 'general') {
428
+ continue;
429
+ }
430
+ const cell = row[column] ?? '';
431
+ if (cell === '' || !cellIsWritten(cell, questionId, questions))
432
+ continue;
433
+ row[column] = declaredSelections(cell, questions.choiceOptions.get(questionId));
434
+ blanked += 1;
435
+ }
436
+ }
437
+ if (blanked === 0 && !overlong)
438
+ return content;
439
+ const terminator = content.includes('\r\n') ? '\r\n' : '\n';
440
+ return `${rows.map((row) => row.map(csvField).join(',')).join(terminator)}${terminator}`;
441
+ }
442
+ /** A CSV answer cell holds written text unless it is a declared choice selection. */
443
+ function cellIsWritten(cell, questionId, questions) {
444
+ if (questions.textQuestionIds.has(questionId) || !questions.allQuestionIds.has(questionId)) {
445
+ return true;
446
+ }
447
+ const options = questions.choiceOptions.get(questionId);
448
+ // A scale cell is an integer or empty; anything else is written text (the
449
+ // JSON path withholds a non-integer scale value the same way).
450
+ if (!options)
451
+ return cell.trim() !== '' && !/^-?\d+$/.test(cell.trim());
452
+ if (options.has(cell))
453
+ return false;
454
+ // A multi-choice cell serializes its selections comma-separated; the cell
455
+ // is written text unless every selection is a declared option.
456
+ return !cell.split(',').every((token) => options.has(token.trim()));
457
+ }
458
+ /** Only the declared selections of a choice cell (or '' when none or not a choice). */
459
+ function declaredSelections(cell, options) {
460
+ if (!options)
461
+ return '';
462
+ return cell
463
+ .split(',')
464
+ .filter((token) => options.has(token.trim()))
465
+ .map((token) => token.trim())
466
+ .join(', ');
467
+ }
468
+ /**
469
+ * Full RFC4180 row parse (quoted fields, escaped quotes, newlines inside
470
+ * quotes, CRLF or LF terminators). Null when the shape is unrecognised —
471
+ * an unclosed quote or junk after a closing quote. Blank lines are skipped.
472
+ */
473
+ function parseCsvRows(content) {
474
+ const source = content.startsWith('\uFEFF') ? content.slice(1) : content;
475
+ const rows = [];
476
+ let row = [];
477
+ let field = '';
478
+ let inQuotes = false;
479
+ let closedQuote = false;
480
+ let atFieldStart = true;
481
+ const endField = () => {
482
+ row.push(field);
483
+ field = '';
484
+ closedQuote = false;
485
+ atFieldStart = true;
486
+ };
487
+ const endRow = () => {
488
+ if (row.length > 0 || field !== '')
489
+ rows.push([...row, field]);
490
+ row = [];
491
+ field = '';
492
+ closedQuote = false;
493
+ atFieldStart = true;
494
+ };
495
+ for (let index = 0; index < source.length; index += 1) {
496
+ const char = source[index];
497
+ if (inQuotes) {
498
+ if (char !== '"') {
499
+ field += char;
500
+ continue;
501
+ }
502
+ if (source[index + 1] === '"') {
503
+ field += '"';
504
+ index += 1;
505
+ continue;
506
+ }
507
+ inQuotes = false;
508
+ closedQuote = true;
509
+ continue;
510
+ }
511
+ if (closedQuote) {
512
+ if (char === ',') {
513
+ endField();
514
+ continue;
515
+ }
516
+ if (char === '\n' || char === '\r') {
517
+ endRow();
518
+ if (char === '\r' && source[index + 1] === '\n')
519
+ index += 1;
520
+ continue;
521
+ }
522
+ return null;
523
+ }
524
+ if (atFieldStart && char === '"') {
525
+ inQuotes = true;
526
+ atFieldStart = false;
527
+ continue;
528
+ }
529
+ if (char === '"')
530
+ return null;
531
+ if (char === ',') {
532
+ endField();
533
+ continue;
534
+ }
535
+ if (char === '\n' || char === '\r') {
536
+ if (field === '' && row.length === 0)
537
+ continue; // blank line
538
+ endRow();
539
+ if (char === '\r' && source[index + 1] === '\n')
540
+ index += 1;
541
+ continue;
542
+ }
543
+ field += char;
544
+ atFieldStart = false;
545
+ }
546
+ if (inQuotes)
547
+ return null;
548
+ if (field !== '' || row.length > 0)
549
+ rows.push([...row, field]);
550
+ return rows;
551
+ }
552
+ function csvField(value) {
553
+ return /[",\r\n]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value;
554
+ }
555
+ function csvResponse(data) {
556
+ return new Response(data.content, {
557
+ headers: {
558
+ 'Cache-Control': 'no-store',
559
+ 'Content-Disposition': `attachment; filename="${safeCsvFilename(data.filename)}"`,
560
+ 'Content-Type': 'text/csv; charset=utf-8',
561
+ },
562
+ });
563
+ }
59
564
  function parseOffset(ctx) {
60
565
  const raw = new URL(ctx.request.url).searchParams.get('offset');
61
566
  if (raw === null)
@@ -76,7 +581,7 @@ function safeCsvFilename(value) {
76
581
  const safe = basename
77
582
  .replace(/[^A-Za-z0-9._-]+/g, '-')
78
583
  .replace(/^\.+/, '')
79
- .replace(/-+/g, '-')
584
+ .replace('-+', '-')
80
585
  .slice(0, 180);
81
586
  return safe.endsWith('.csv') ? safe : `${safe || 'survey-responses'}.csv`;
82
587
  }
@@ -1 +1 @@
1
- {"version":3,"file":"surveys.js","sourceRoot":"","sources":["../../src/routes/surveys.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"surveys.js","sourceRoot":"","sources":["../../src/routes/surveys.ts"],"names":[],"mappings":"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"}