create-safest-tools 0.4.1 → 0.4.2
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/package.json +1 -1
- package/template/console/reports/ReportDrawer.tsx +9 -0
- package/template/console/reports/types.ts +3 -0
- package/template/package.json +2 -2
- package/template/public/console/auth-shell.js +270 -263
- package/template/src/index.ts +8 -2
- package/template/src/report-workflow.ts +36 -2
- package/template/worker-configuration.d.ts +3 -3
package/template/src/index.ts
CHANGED
|
@@ -2595,7 +2595,10 @@ async function handleAdminAiQualitySample(
|
|
|
2595
2595
|
const sample = await loadAiQualitySample(env.DB, sampleId);
|
|
2596
2596
|
if (!sample) throw new ApiError(404, "quality_sample_not_found", "The quality sample does not exist.");
|
|
2597
2597
|
await assertOperatorReportAccess(env.DB, session, String(sample.reportId));
|
|
2598
|
-
const report = await loadReportDetail(env.DB, String(sample.reportId)
|
|
2598
|
+
const report = await loadReportDetail(env.DB, String(sample.reportId), {
|
|
2599
|
+
contactEncryptionKey: env.CREDENTIAL_ENCRYPTION_KEY,
|
|
2600
|
+
includeReporterEmail: session.permissions.messageReporters,
|
|
2601
|
+
});
|
|
2599
2602
|
if (!report) throw new ApiError(404, "report_not_found", "The sampled report does not exist.");
|
|
2600
2603
|
return json({ schema_version: "1", sample: projectOperatorFields(session, "quality_sample", sample), report: projectOperatorFields(session, "report", report) });
|
|
2601
2604
|
}
|
|
@@ -2843,7 +2846,10 @@ async function handleAdminReportDetail(request: Request, env: Env, reportId: str
|
|
|
2843
2846
|
if (request.method !== "GET") return methodNotAllowed(["GET"]);
|
|
2844
2847
|
const session = await requireOperator(request, env, "readReports");
|
|
2845
2848
|
await assertOperatorReportAccess(env.DB, session, reportId);
|
|
2846
|
-
const report = await loadReportDetail(env.DB, reportId
|
|
2849
|
+
const report = await loadReportDetail(env.DB, reportId, {
|
|
2850
|
+
contactEncryptionKey: env.CREDENTIAL_ENCRYPTION_KEY,
|
|
2851
|
+
includeReporterEmail: session.permissions.messageReporters,
|
|
2852
|
+
});
|
|
2847
2853
|
if (!report) throw new ApiError(404, "report_not_found", "The report does not exist.");
|
|
2848
2854
|
return json({ schema_version: "1", report: projectOperatorFields(session, "report", report) });
|
|
2849
2855
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AUDIT_GENESIS_HASH, canonicalJson, hashAuditEntry } from "./audit";
|
|
2
|
+
import { decryptReportContact } from "./report-crypto";
|
|
2
3
|
import { selectParticipantDelivery, type ParticipantDelivery } from "./report-email";
|
|
3
4
|
import { ApiError } from "./report-http";
|
|
4
5
|
import { analystAvatarColor } from "./report-presence";
|
|
@@ -160,7 +161,11 @@ export async function releaseReportClaim(db: D1Database, reportId: string, sessi
|
|
|
160
161
|
]);
|
|
161
162
|
}
|
|
162
163
|
|
|
163
|
-
export async function loadReportDetail(
|
|
164
|
+
export async function loadReportDetail(
|
|
165
|
+
db: D1Database,
|
|
166
|
+
reportId: string,
|
|
167
|
+
options: { contactEncryptionKey?: string; includeReporterEmail?: boolean } = {},
|
|
168
|
+
): Promise<Record<string, unknown> | null> {
|
|
164
169
|
const report = await db.prepare(`
|
|
165
170
|
SELECT r.id, r.public_reference AS reference, r.source, r.state, r.priority, r.reason_code AS reasonCode,
|
|
166
171
|
r.locale, r.queue_id AS queueId, r.submitted_at AS submittedAt, r.received_at AS receivedAt,
|
|
@@ -172,7 +177,9 @@ export async function loadReportDetail(db: D1Database, reportId: string): Promis
|
|
|
172
177
|
qv.management_mode AS queueManagementMode, qv.reviewer_instructions AS reviewerInstructions,
|
|
173
178
|
t.target_type AS targetType, t.target_reference AS targetReference,
|
|
174
179
|
t.owner_reference AS ownerReference, t.customer_url AS customerUrl,
|
|
175
|
-
p.reference AS reporterReference
|
|
180
|
+
p.reference AS reporterReference, p.contact_mode AS reporterContactMode,
|
|
181
|
+
p.contact_ciphertext AS reporterContactCiphertext,
|
|
182
|
+
p.reference_redacted_at AS reporterReferenceRedactedAt
|
|
176
183
|
FROM reports r
|
|
177
184
|
JOIN report_targets t ON t.report_id = r.id
|
|
178
185
|
JOIN report_participants p ON p.report_id = r.id AND p.audience = 'reporter'
|
|
@@ -266,8 +273,35 @@ export async function loadReportDetail(db: D1Database, reportId: string): Promis
|
|
|
266
273
|
value: parsedJson(row.valueJson, null),
|
|
267
274
|
});
|
|
268
275
|
}
|
|
276
|
+
let reporterEmail: string | null = null;
|
|
277
|
+
let reporterContactStatus: "available" | "not_provided" | "redacted" | "restricted" | "unavailable";
|
|
278
|
+
if (report.reporterReferenceRedactedAt) {
|
|
279
|
+
reporterContactStatus = "redacted";
|
|
280
|
+
} else if (!report.reporterContactCiphertext) {
|
|
281
|
+
reporterContactStatus = "not_provided";
|
|
282
|
+
} else if (!options.includeReporterEmail) {
|
|
283
|
+
reporterContactStatus = "restricted";
|
|
284
|
+
} else if (!options.contactEncryptionKey) {
|
|
285
|
+
reporterContactStatus = "unavailable";
|
|
286
|
+
} else {
|
|
287
|
+
try {
|
|
288
|
+
reporterEmail = (await decryptReportContact(
|
|
289
|
+
options.contactEncryptionKey,
|
|
290
|
+
String(report.reporterContactCiphertext),
|
|
291
|
+
reportId,
|
|
292
|
+
"reporter",
|
|
293
|
+
)).trim().toLowerCase();
|
|
294
|
+
reporterContactStatus = reporterEmail ? "available" : "unavailable";
|
|
295
|
+
} catch {
|
|
296
|
+
reporterContactStatus = "unavailable";
|
|
297
|
+
}
|
|
298
|
+
}
|
|
269
299
|
return {
|
|
270
300
|
...report,
|
|
301
|
+
reporterEmail,
|
|
302
|
+
reporterContactStatus,
|
|
303
|
+
reporterContactCiphertext: undefined,
|
|
304
|
+
reporterReferenceRedactedAt: undefined,
|
|
271
305
|
policyRules: (() => {
|
|
272
306
|
try {
|
|
273
307
|
const value: unknown = JSON.parse(String(report.policyRulesJson ?? "[]"));
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
// Generated by Wrangler by running `wrangler types --env-file=config/dev.vars.example --include-runtime=false --strict-vars=false` (hash:
|
|
2
|
+
// Generated by Wrangler by running `wrangler types --env-file=config/dev.vars.example --include-runtime=false --strict-vars=false` (hash: 2d2c98e01480f3c1492835530279c5f1)
|
|
3
3
|
interface __BaseEnv_Env {
|
|
4
4
|
PROFILE_MEDIA: R2Bucket;
|
|
5
5
|
WORKFLOW_ARTIFACTS: R2Bucket;
|
|
6
6
|
EVIDENCE_OBJECTS: R2Bucket;
|
|
7
7
|
EXPORTS: R2Bucket;
|
|
8
8
|
DB: D1Database;
|
|
9
|
+
AUTH_EMAIL: SendEmail;
|
|
10
|
+
REPORTER_EMAIL: SendEmail;
|
|
9
11
|
CONTROL_JOBS: Queue;
|
|
10
12
|
REPORT_JOBS: Queue;
|
|
11
13
|
DELIVERY_JOBS: Queue;
|
|
12
14
|
LOADER: WorkerLoader;
|
|
13
15
|
AI: Ai;
|
|
14
16
|
ASSETS: Fetcher;
|
|
15
|
-
AUTH_EMAIL: SendEmail;
|
|
16
|
-
REPORTER_EMAIL: SendEmail;
|
|
17
17
|
PUBLIC_BASE_URL: string;
|
|
18
18
|
ALLOWED_ORIGINS: string;
|
|
19
19
|
CONTEXT_TOKEN_TTL_SECONDS: string;
|