@heavybit/shared-lib 0.0.0-stage → 1.1.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/dist/cjs/access/index.js +118 -0
- package/dist/cjs/access/index.js.map +1 -0
- package/dist/cjs/alerting/index.js +56 -0
- package/dist/cjs/alerting/index.js.map +1 -0
- package/dist/cjs/cache/index.js +167 -0
- package/dist/cjs/cache/index.js.map +1 -0
- package/dist/cjs/common/async.js +40 -0
- package/dist/cjs/common/async.js.map +1 -0
- package/dist/cjs/common/audit.js +21 -0
- package/dist/cjs/common/audit.js.map +1 -0
- package/dist/cjs/common/crypto.js +75 -0
- package/dist/cjs/common/crypto.js.map +1 -0
- package/dist/cjs/common/errors.js +90 -0
- package/dist/cjs/common/errors.js.map +1 -0
- package/dist/cjs/common/id.js +40 -0
- package/dist/cjs/common/id.js.map +1 -0
- package/dist/cjs/common/index.js +28 -0
- package/dist/cjs/common/index.js.map +1 -0
- package/dist/cjs/common/jwt.js +59 -0
- package/dist/cjs/common/jwt.js.map +1 -0
- package/dist/cjs/common/password.js +38 -0
- package/dist/cjs/common/password.js.map +1 -0
- package/dist/cjs/common/phone.js +42 -0
- package/dist/cjs/common/phone.js.map +1 -0
- package/dist/cjs/common/response.js +32 -0
- package/dist/cjs/common/response.js.map +1 -0
- package/dist/cjs/common/text.js +46 -0
- package/dist/cjs/common/text.js.map +1 -0
- package/dist/cjs/common/time.js +109 -0
- package/dist/cjs/common/time.js.map +1 -0
- package/dist/cjs/config/index.js +96 -0
- package/dist/cjs/config/index.js.map +1 -0
- package/dist/cjs/contracts/editorial-draft.js +111 -0
- package/dist/cjs/contracts/editorial-draft.js.map +1 -0
- package/dist/cjs/contracts/index.js +20 -0
- package/dist/cjs/contracts/index.js.map +1 -0
- package/dist/cjs/contracts/notification-dispatch.js +92 -0
- package/dist/cjs/contracts/notification-dispatch.js.map +1 -0
- package/dist/cjs/contracts/upload-import.js +54 -0
- package/dist/cjs/contracts/upload-import.js.map +1 -0
- package/dist/cjs/database/index.js +57 -0
- package/dist/cjs/database/index.js.map +1 -0
- package/dist/cjs/express/auth.js +72 -0
- package/dist/cjs/express/auth.js.map +1 -0
- package/dist/cjs/express/health.js +31 -0
- package/dist/cjs/express/health.js.map +1 -0
- package/dist/cjs/express/index.js +20 -0
- package/dist/cjs/express/index.js.map +1 -0
- package/dist/cjs/express/middleware.js +95 -0
- package/dist/cjs/express/middleware.js.map +1 -0
- package/dist/cjs/http/index.js +90 -0
- package/dist/cjs/http/index.js.map +1 -0
- package/dist/cjs/http/safe-fetch.js +199 -0
- package/dist/cjs/http/safe-fetch.js.map +1 -0
- package/dist/cjs/identity/index.js +117 -0
- package/dist/cjs/identity/index.js.map +1 -0
- package/dist/cjs/index.js +29 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/knex/index.js +76 -0
- package/dist/cjs/knex/index.js.map +1 -0
- package/dist/cjs/logging/index.js +75 -0
- package/dist/cjs/logging/index.js.map +1 -0
- package/dist/cjs/messaging/connection.js +115 -0
- package/dist/cjs/messaging/connection.js.map +1 -0
- package/dist/cjs/messaging/consumer.js +134 -0
- package/dist/cjs/messaging/consumer.js.map +1 -0
- package/dist/cjs/messaging/envelope.js +23 -0
- package/dist/cjs/messaging/envelope.js.map +1 -0
- package/dist/cjs/messaging/idempotency.js +57 -0
- package/dist/cjs/messaging/idempotency.js.map +1 -0
- package/dist/cjs/messaging/index.js +62 -0
- package/dist/cjs/messaging/index.js.map +1 -0
- package/dist/cjs/messaging/monitor.js +48 -0
- package/dist/cjs/messaging/monitor.js.map +1 -0
- package/dist/cjs/messaging/outbox.js +135 -0
- package/dist/cjs/messaging/outbox.js.map +1 -0
- package/dist/cjs/messaging/publisher.js +149 -0
- package/dist/cjs/messaging/publisher.js.map +1 -0
- package/dist/cjs/messaging/rpc.js +125 -0
- package/dist/cjs/messaging/rpc.js.map +1 -0
- package/dist/cjs/messaging/staff-notifier.js +78 -0
- package/dist/cjs/messaging/staff-notifier.js.map +1 -0
- package/dist/cjs/messaging/topology.js +22 -0
- package/dist/cjs/messaging/topology.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/rate-limit/index.js +61 -0
- package/dist/cjs/rate-limit/index.js.map +1 -0
- package/dist/cjs/scheduling/index.js +88 -0
- package/dist/cjs/scheduling/index.js.map +1 -0
- package/dist/cjs/security/index.js +39 -0
- package/dist/cjs/security/index.js.map +1 -0
- package/dist/cjs/socket/index.js +53 -0
- package/dist/cjs/socket/index.js.map +1 -0
- package/dist/cjs/testing/index.js +73 -0
- package/dist/cjs/testing/index.js.map +1 -0
- package/dist/cjs/types/index.js +3 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/validation/index.js +41 -0
- package/dist/cjs/validation/index.js.map +1 -0
- package/dist/esm/access/index.js +104 -0
- package/dist/esm/access/index.js.map +1 -0
- package/dist/esm/alerting/index.js +52 -0
- package/dist/esm/alerting/index.js.map +1 -0
- package/dist/esm/cache/index.js +163 -0
- package/dist/esm/cache/index.js.map +1 -0
- package/dist/esm/common/async.js +33 -0
- package/dist/esm/common/async.js.map +1 -0
- package/dist/esm/common/audit.js +18 -0
- package/dist/esm/common/audit.js.map +1 -0
- package/dist/esm/common/crypto.js +64 -0
- package/dist/esm/common/crypto.js.map +1 -0
- package/dist/esm/common/errors.js +75 -0
- package/dist/esm/common/errors.js.map +1 -0
- package/dist/esm/common/id.js +33 -0
- package/dist/esm/common/id.js.map +1 -0
- package/dist/esm/common/index.js +12 -0
- package/dist/esm/common/index.js.map +1 -0
- package/dist/esm/common/jwt.js +49 -0
- package/dist/esm/common/jwt.js.map +1 -0
- package/dist/esm/common/password.js +30 -0
- package/dist/esm/common/password.js.map +1 -0
- package/dist/esm/common/phone.js +33 -0
- package/dist/esm/common/phone.js.map +1 -0
- package/dist/esm/common/response.js +24 -0
- package/dist/esm/common/response.js.map +1 -0
- package/dist/esm/common/text.js +39 -0
- package/dist/esm/common/text.js.map +1 -0
- package/dist/esm/common/time.js +96 -0
- package/dist/esm/common/time.js.map +1 -0
- package/dist/esm/config/index.js +88 -0
- package/dist/esm/config/index.js.map +1 -0
- package/dist/esm/contracts/editorial-draft.js +108 -0
- package/dist/esm/contracts/editorial-draft.js.map +1 -0
- package/dist/esm/contracts/index.js +4 -0
- package/dist/esm/contracts/index.js.map +1 -0
- package/dist/esm/contracts/notification-dispatch.js +89 -0
- package/dist/esm/contracts/notification-dispatch.js.map +1 -0
- package/dist/esm/contracts/upload-import.js +51 -0
- package/dist/esm/contracts/upload-import.js.map +1 -0
- package/dist/esm/database/index.js +48 -0
- package/dist/esm/database/index.js.map +1 -0
- package/dist/esm/express/auth.js +63 -0
- package/dist/esm/express/auth.js.map +1 -0
- package/dist/esm/express/health.js +27 -0
- package/dist/esm/express/health.js.map +1 -0
- package/dist/esm/express/index.js +4 -0
- package/dist/esm/express/index.js.map +1 -0
- package/dist/esm/express/middleware.js +84 -0
- package/dist/esm/express/middleware.js.map +1 -0
- package/dist/esm/http/index.js +73 -0
- package/dist/esm/http/index.js.map +1 -0
- package/dist/esm/http/safe-fetch.js +193 -0
- package/dist/esm/http/safe-fetch.js.map +1 -0
- package/dist/esm/identity/index.js +111 -0
- package/dist/esm/identity/index.js.map +1 -0
- package/dist/esm/index.js +13 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/knex/index.js +66 -0
- package/dist/esm/knex/index.js.map +1 -0
- package/dist/esm/logging/index.js +67 -0
- package/dist/esm/logging/index.js.map +1 -0
- package/dist/esm/messaging/connection.js +108 -0
- package/dist/esm/messaging/connection.js.map +1 -0
- package/dist/esm/messaging/consumer.js +130 -0
- package/dist/esm/messaging/consumer.js.map +1 -0
- package/dist/esm/messaging/envelope.js +19 -0
- package/dist/esm/messaging/envelope.js.map +1 -0
- package/dist/esm/messaging/idempotency.js +52 -0
- package/dist/esm/messaging/idempotency.js.map +1 -0
- package/dist/esm/messaging/index.js +45 -0
- package/dist/esm/messaging/index.js.map +1 -0
- package/dist/esm/messaging/monitor.js +44 -0
- package/dist/esm/messaging/monitor.js.map +1 -0
- package/dist/esm/messaging/outbox.js +129 -0
- package/dist/esm/messaging/outbox.js.map +1 -0
- package/dist/esm/messaging/publisher.js +142 -0
- package/dist/esm/messaging/publisher.js.map +1 -0
- package/dist/esm/messaging/rpc.js +120 -0
- package/dist/esm/messaging/rpc.js.map +1 -0
- package/dist/esm/messaging/staff-notifier.js +73 -0
- package/dist/esm/messaging/staff-notifier.js.map +1 -0
- package/dist/esm/messaging/topology.js +16 -0
- package/dist/esm/messaging/topology.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/rate-limit/index.js +56 -0
- package/dist/esm/rate-limit/index.js.map +1 -0
- package/dist/esm/scheduling/index.js +83 -0
- package/dist/esm/scheduling/index.js.map +1 -0
- package/dist/esm/security/index.js +36 -0
- package/dist/esm/security/index.js.map +1 -0
- package/dist/esm/socket/index.js +47 -0
- package/dist/esm/socket/index.js.map +1 -0
- package/dist/esm/testing/index.js +66 -0
- package/dist/esm/testing/index.js.map +1 -0
- package/dist/esm/types/index.js +2 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/validation/index.js +36 -0
- package/dist/esm/validation/index.js.map +1 -0
- package/dist/types/access/index.d.ts +50 -0
- package/dist/types/access/index.d.ts.map +1 -0
- package/dist/types/alerting/index.d.ts +43 -0
- package/dist/types/alerting/index.d.ts.map +1 -0
- package/dist/types/cache/index.d.ts +45 -0
- package/dist/types/cache/index.d.ts.map +1 -0
- package/dist/types/common/async.d.ts +14 -0
- package/dist/types/common/async.d.ts.map +1 -0
- package/dist/types/common/audit.d.ts +17 -0
- package/dist/types/common/audit.d.ts.map +1 -0
- package/dist/types/common/crypto.d.ts +18 -0
- package/dist/types/common/crypto.d.ts.map +1 -0
- package/dist/types/common/errors.d.ts +71 -0
- package/dist/types/common/errors.d.ts.map +1 -0
- package/dist/types/common/id.d.ts +14 -0
- package/dist/types/common/id.d.ts.map +1 -0
- package/dist/types/common/index.d.ts +12 -0
- package/dist/types/common/index.d.ts.map +1 -0
- package/dist/types/common/jwt.d.ts +28 -0
- package/dist/types/common/jwt.d.ts.map +1 -0
- package/dist/types/common/password.d.ts +4 -0
- package/dist/types/common/password.d.ts.map +1 -0
- package/dist/types/common/phone.d.ts +10 -0
- package/dist/types/common/phone.d.ts.map +1 -0
- package/dist/types/common/response.d.ts +12 -0
- package/dist/types/common/response.d.ts.map +1 -0
- package/dist/types/common/text.d.ts +10 -0
- package/dist/types/common/text.d.ts.map +1 -0
- package/dist/types/common/time.d.ts +40 -0
- package/dist/types/common/time.d.ts.map +1 -0
- package/dist/types/config/index.d.ts +115 -0
- package/dist/types/config/index.d.ts.map +1 -0
- package/dist/types/contracts/editorial-draft.d.ts +577 -0
- package/dist/types/contracts/editorial-draft.d.ts.map +1 -0
- package/dist/types/contracts/index.d.ts +4 -0
- package/dist/types/contracts/index.d.ts.map +1 -0
- package/dist/types/contracts/notification-dispatch.d.ts +175 -0
- package/dist/types/contracts/notification-dispatch.d.ts.map +1 -0
- package/dist/types/contracts/upload-import.d.ts +96 -0
- package/dist/types/contracts/upload-import.d.ts.map +1 -0
- package/dist/types/database/index.d.ts +25 -0
- package/dist/types/database/index.d.ts.map +1 -0
- package/dist/types/express/auth.d.ts +27 -0
- package/dist/types/express/auth.d.ts.map +1 -0
- package/dist/types/express/health.d.ts +14 -0
- package/dist/types/express/health.d.ts.map +1 -0
- package/dist/types/express/index.d.ts +4 -0
- package/dist/types/express/index.d.ts.map +1 -0
- package/dist/types/express/middleware.d.ts +20 -0
- package/dist/types/express/middleware.d.ts.map +1 -0
- package/dist/types/http/index.d.ts +34 -0
- package/dist/types/http/index.d.ts.map +1 -0
- package/dist/types/http/safe-fetch.d.ts +58 -0
- package/dist/types/http/safe-fetch.d.ts.map +1 -0
- package/dist/types/identity/index.d.ts +51 -0
- package/dist/types/identity/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/knex/index.d.ts +25 -0
- package/dist/types/knex/index.d.ts.map +1 -0
- package/dist/types/logging/index.d.ts +22 -0
- package/dist/types/logging/index.d.ts.map +1 -0
- package/dist/types/messaging/connection.d.ts +48 -0
- package/dist/types/messaging/connection.d.ts.map +1 -0
- package/dist/types/messaging/consumer.d.ts +56 -0
- package/dist/types/messaging/consumer.d.ts.map +1 -0
- package/dist/types/messaging/envelope.d.ts +16 -0
- package/dist/types/messaging/envelope.d.ts.map +1 -0
- package/dist/types/messaging/idempotency.d.ts +29 -0
- package/dist/types/messaging/idempotency.d.ts.map +1 -0
- package/dist/types/messaging/index.d.ts +39 -0
- package/dist/types/messaging/index.d.ts.map +1 -0
- package/dist/types/messaging/monitor.d.ts +23 -0
- package/dist/types/messaging/monitor.d.ts.map +1 -0
- package/dist/types/messaging/outbox.d.ts +51 -0
- package/dist/types/messaging/outbox.d.ts.map +1 -0
- package/dist/types/messaging/publisher.d.ts +84 -0
- package/dist/types/messaging/publisher.d.ts.map +1 -0
- package/dist/types/messaging/rpc.d.ts +46 -0
- package/dist/types/messaging/rpc.d.ts.map +1 -0
- package/dist/types/messaging/staff-notifier.d.ts +56 -0
- package/dist/types/messaging/staff-notifier.d.ts.map +1 -0
- package/dist/types/messaging/topology.d.ts +23 -0
- package/dist/types/messaging/topology.d.ts.map +1 -0
- package/dist/types/rate-limit/index.d.ts +28 -0
- package/dist/types/rate-limit/index.d.ts.map +1 -0
- package/dist/types/scheduling/index.d.ts +33 -0
- package/dist/types/scheduling/index.d.ts.map +1 -0
- package/dist/types/security/index.d.ts +20 -0
- package/dist/types/security/index.d.ts.map +1 -0
- package/dist/types/socket/index.d.ts +30 -0
- package/dist/types/socket/index.d.ts.map +1 -0
- package/dist/types/testing/index.d.ts +41 -0
- package/dist/types/testing/index.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +65 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/validation/index.d.ts +34 -0
- package/dist/types/validation/index.d.ts.map +1 -0
- package/package.json +189 -4
- package/README.md +0 -3
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.editorialDraftSubmitSchema = exports.FACT_KINDS = exports.QUALITY_GATE_NAMES = exports.GATE_VERDICTS = exports.DRAFT_RISKS = exports.DRAFT_SOURCE_ROLES = exports.EDITORIAL_DRAFT_LIMITS = exports.EDITORIAL_DRAFT_SUBMIT = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const index_js_1 = require("../validation/index.js");
|
|
6
|
+
/**
|
|
7
|
+
* The newswire → editorial draft hand-off (design Appendix A.4 plus `paragraphFactIds` and
|
|
8
|
+
* `image.uploadId`, decision R14). newswire-service stages it through its outbox; editorial-service
|
|
9
|
+
* validates it with the same schema before creating the story. One contract for both sides.
|
|
10
|
+
*/
|
|
11
|
+
exports.EDITORIAL_DRAFT_SUBMIT = 'editorial:draft.submit';
|
|
12
|
+
/** Field limits of the contract (editorial's story columns). */
|
|
13
|
+
exports.EDITORIAL_DRAFT_LIMITS = {
|
|
14
|
+
headline: 200,
|
|
15
|
+
excerpt: 400,
|
|
16
|
+
tags: 6,
|
|
17
|
+
seoTitle: 70,
|
|
18
|
+
seoDescription: 170,
|
|
19
|
+
};
|
|
20
|
+
exports.DRAFT_SOURCE_ROLES = ['primary', 'corroborating'];
|
|
21
|
+
exports.DRAFT_RISKS = ['low', 'medium', 'high'];
|
|
22
|
+
exports.GATE_VERDICTS = ['pass', 'review', 'block'];
|
|
23
|
+
/**
|
|
24
|
+
* Every quality gate newswire runs on a draft, in design order. A submitted draft carries one result per
|
|
25
|
+
* gate; editorial treats a missing one as not passed (auto-publish never runs on an unchecked draft).
|
|
26
|
+
*/
|
|
27
|
+
exports.QUALITY_GATE_NAMES = [
|
|
28
|
+
'originality', 'grounding', 'quote_limits', 'corroboration', 'conflicts',
|
|
29
|
+
'sensitivity', 'category', 'freshness', 'duplicate_of_published', 'length_format',
|
|
30
|
+
];
|
|
31
|
+
exports.FACT_KINDS = ['event', 'person', 'date', 'place', 'number', 'quote', 'context'];
|
|
32
|
+
const text = zod_1.z.string().trim().min(1);
|
|
33
|
+
const httpsUrl = zod_1.z
|
|
34
|
+
.string()
|
|
35
|
+
.url()
|
|
36
|
+
.refine((u) => u.startsWith('https://'), 'Source URL must use https');
|
|
37
|
+
const draftSourceSchema = zod_1.z.object({
|
|
38
|
+
name: text.max(160),
|
|
39
|
+
url: httpsUrl,
|
|
40
|
+
publishedAt: zod_1.z.string().datetime({ offset: true }).optional(),
|
|
41
|
+
role: zod_1.z.enum(exports.DRAFT_SOURCE_ROLES),
|
|
42
|
+
});
|
|
43
|
+
const gateResultSchema = zod_1.z.object({
|
|
44
|
+
gate: text,
|
|
45
|
+
verdict: zod_1.z.enum(exports.GATE_VERDICTS),
|
|
46
|
+
reasons: zod_1.z.array(zod_1.z.string()),
|
|
47
|
+
metrics: zod_1.z.record(zod_1.z.string(), zod_1.z.number()).optional(),
|
|
48
|
+
});
|
|
49
|
+
const factSupportSchema = zod_1.z.object({ itemId: index_js_1.idSchema, paragraph: zod_1.z.number().int().min(1) });
|
|
50
|
+
const factSchema = zod_1.z.object({
|
|
51
|
+
id: text,
|
|
52
|
+
statement: text,
|
|
53
|
+
kind: zod_1.z.enum(exports.FACT_KINDS),
|
|
54
|
+
entities: zod_1.z.array(zod_1.z.string()),
|
|
55
|
+
supportedBy: zod_1.z.array(factSupportSchema).min(1),
|
|
56
|
+
conflictsWith: zod_1.z.array(zod_1.z.string()),
|
|
57
|
+
independentSources: zod_1.z.number().int().min(0),
|
|
58
|
+
});
|
|
59
|
+
const quoteSchema = factSupportSchema.extend({ text, speaker: text });
|
|
60
|
+
const conflictSchema = zod_1.z.object({ description: text, factIds: zod_1.z.array(zod_1.z.string()) });
|
|
61
|
+
exports.editorialDraftSubmitSchema = zod_1.z
|
|
62
|
+
.object({
|
|
63
|
+
draftId: index_js_1.idSchema,
|
|
64
|
+
clusterId: index_js_1.idSchema,
|
|
65
|
+
headline: text.max(exports.EDITORIAL_DRAFT_LIMITS.headline),
|
|
66
|
+
excerpt: text.max(exports.EDITORIAL_DRAFT_LIMITS.excerpt),
|
|
67
|
+
paragraphs: zod_1.z.array(text).min(1),
|
|
68
|
+
/** The fact-sheet fact ids each paragraph asserts (same length as `paragraphs`). */
|
|
69
|
+
paragraphFactIds: zod_1.z.array(zod_1.z.array(zod_1.z.string())),
|
|
70
|
+
category: text.max(60),
|
|
71
|
+
tags: zod_1.z.array(text.max(40)).max(exports.EDITORIAL_DRAFT_LIMITS.tags),
|
|
72
|
+
seo: zod_1.z.object({
|
|
73
|
+
title: text.max(exports.EDITORIAL_DRAFT_LIMITS.seoTitle),
|
|
74
|
+
description: text.max(exports.EDITORIAL_DRAFT_LIMITS.seoDescription),
|
|
75
|
+
}),
|
|
76
|
+
social: zod_1.z.object({ facebook: text, x: text, whatsapp: text, instagram: text }),
|
|
77
|
+
sources: zod_1.z.array(draftSourceSchema).min(1),
|
|
78
|
+
/** An imported or profile cover (upload-service id), or null when the draft has none. */
|
|
79
|
+
image: zod_1.z.object({ uploadId: index_js_1.idSchema, credit: text.max(160), alt: text.max(255) }).nullable(),
|
|
80
|
+
relatedProfileIds: zod_1.z.array(index_js_1.idSchema),
|
|
81
|
+
suggestedProfileIds: zod_1.z.array(index_js_1.idSchema),
|
|
82
|
+
review: zod_1.z.object({
|
|
83
|
+
confidence: zod_1.z.number().min(0).max(1),
|
|
84
|
+
risk: zod_1.z.enum(exports.DRAFT_RISKS),
|
|
85
|
+
riskReasons: zod_1.z.array(zod_1.z.string()),
|
|
86
|
+
gates: zod_1.z.array(gateResultSchema),
|
|
87
|
+
factSheet: zod_1.z.object({
|
|
88
|
+
facts: zod_1.z.array(factSchema),
|
|
89
|
+
quotes: zod_1.z.array(quoteSchema),
|
|
90
|
+
conflicts: zod_1.z.array(conflictSchema),
|
|
91
|
+
}),
|
|
92
|
+
/** Prompt slug → version used to produce the draft. */
|
|
93
|
+
promptVersions: zod_1.z.record(zod_1.z.string(), zod_1.z.number().int().positive()),
|
|
94
|
+
}),
|
|
95
|
+
})
|
|
96
|
+
.superRefine((draft, ctx) => {
|
|
97
|
+
if (draft.paragraphFactIds.length !== draft.paragraphs.length) {
|
|
98
|
+
ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['paragraphFactIds'], message: 'Must have one entry per paragraph' });
|
|
99
|
+
}
|
|
100
|
+
const factIds = new Set(draft.review.factSheet.facts.map((f) => f.id));
|
|
101
|
+
draft.paragraphFactIds.forEach((ids, i) => {
|
|
102
|
+
for (const id of ids) {
|
|
103
|
+
if (!factIds.has(id))
|
|
104
|
+
ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['paragraphFactIds', i], message: `Unknown fact id ${id}` });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
if (draft.sources.filter((s) => s.role === 'primary').length !== 1) {
|
|
108
|
+
ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['sources'], message: 'Exactly one source must be primary' });
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=editorial-draft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorial-draft.js","sourceRoot":"","sources":["../../../src/contracts/editorial-draft.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,qDAAkD;AAElD;;;;GAIG;AACU,QAAA,sBAAsB,GAAG,wBAAwB,CAAC;AAE/D,gEAAgE;AACnD,QAAA,sBAAsB,GAAG;IACpC,QAAQ,EAAE,GAAG;IACb,OAAO,EAAE,GAAG;IACZ,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,EAAE;IACZ,cAAc,EAAE,GAAG;CACX,CAAC;AAEE,QAAA,kBAAkB,GAAG,CAAC,SAAS,EAAE,eAAe,CAAU,CAAC;AAC3D,QAAA,WAAW,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC;AACjD,QAAA,aAAa,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAClE;;;GAGG;AACU,QAAA,kBAAkB,GAAG;IAChC,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW;IACxE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,wBAAwB,EAAE,eAAe;CACzE,CAAC;AAEE,QAAA,UAAU,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAEtG,MAAM,IAAI,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,QAAQ,GAAG,OAAC;KACf,MAAM,EAAE;KACR,GAAG,EAAE;KACL,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,2BAA2B,CAAC,CAAC;AAExE,MAAM,iBAAiB,GAAG,OAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACnB,GAAG,EAAE,QAAQ;IACb,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC7D,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,0BAAkB,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,OAAC,CAAC,IAAI,CAAC,qBAAa,CAAC;IAC9B,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrD,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,OAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,mBAAQ,EAAE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAE7F,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1B,EAAE,EAAE,IAAI;IACR,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,kBAAU,CAAC;IACxB,QAAQ,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,OAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,aAAa,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;IAClC,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAEtE,MAAM,cAAc,GAAG,OAAC,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AAExE,QAAA,0BAA0B,GAAG,OAAC;KACxC,MAAM,CAAC;IACN,OAAO,EAAE,mBAAQ;IACjB,SAAS,EAAE,mBAAQ;IACnB,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,8BAAsB,CAAC,QAAQ,CAAC;IACnD,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,8BAAsB,CAAC,OAAO,CAAC;IACjD,UAAU,EAAE,OAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,oFAAoF;IACpF,gBAAgB,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACtB,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,8BAAsB,CAAC,IAAI,CAAC;IAC5D,GAAG,EAAE,OAAC,CAAC,MAAM,CAAC;QACZ,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,8BAAsB,CAAC,QAAQ,CAAC;QAChD,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,8BAAsB,CAAC,cAAc,CAAC;KAC7D,CAAC;IACF,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC9E,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,yFAAyF;IACzF,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,mBAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC7F,iBAAiB,EAAE,OAAC,CAAC,KAAK,CAAC,mBAAQ,CAAC;IACpC,mBAAmB,EAAE,OAAC,CAAC,KAAK,CAAC,mBAAQ,CAAC;IACtC,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;QACf,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,mBAAW,CAAC;QACzB,WAAW,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;QAChC,KAAK,EAAE,OAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC;QAChC,SAAS,EAAE,OAAC,CAAC,MAAM,CAAC;YAClB,KAAK,EAAE,OAAC,CAAC,KAAK,CAAC,UAAU,CAAC;YAC1B,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,WAAW,CAAC;YAC5B,SAAS,EAAE,OAAC,CAAC,KAAK,CAAC,cAAc,CAAC;SACnC,CAAC;QACF,uDAAuD;QACvD,cAAc,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;KAClE,CAAC;CACH,CAAC;KACD,WAAW,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC1B,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,KAAK,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QAC9D,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAC;IAC1H,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACxC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,EAAE,EAAE,CAAC,CAAC;QACvI,CAAC;IACH,CAAC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC;IAClH,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./editorial-draft.js"), exports);
|
|
18
|
+
__exportStar(require("./notification-dispatch.js"), exports);
|
|
19
|
+
__exportStar(require("./upload-import.js"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/contracts/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,6DAA2C;AAC3C,qDAAmC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DISPATCH_TEMPLATE_VARIABLES = exports.notificationDispatchSchema = exports.dispatchRecipientSchema = exports.dispatchValueSchema = exports.DISPATCH_LIMITS = exports.NOTIFICATION_CATEGORIES = exports.DISPATCH_CHANNELS = exports.NOTIFICATION_DISPATCH = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/**
|
|
6
|
+
* `notification:dispatch` — the one command every Showbiz service stages (through its outbox) to have
|
|
7
|
+
* notification-service render a seeded template and deliver it by email and/or the in-app feed. No
|
|
8
|
+
* other service sends email itself. One contract for both sides: producers type their payload with it
|
|
9
|
+
* and notification-service validates against it, so the two cannot drift.
|
|
10
|
+
*/
|
|
11
|
+
exports.NOTIFICATION_DISPATCH = 'notification:dispatch';
|
|
12
|
+
/** Channels a dispatch may ask for. `in_app` needs a recipient `userId` (the bell feed is per user). */
|
|
13
|
+
exports.DISPATCH_CHANNELS = ['email', 'in_app'];
|
|
14
|
+
/**
|
|
15
|
+
* What a dispatch is about. Account mail (`security`, `account`, `team`, `marketing`) goes to a user;
|
|
16
|
+
* `staff` is an operational alert to a configured staff address.
|
|
17
|
+
*/
|
|
18
|
+
exports.NOTIFICATION_CATEGORIES = ['security', 'account', 'team', 'marketing', 'staff'];
|
|
19
|
+
exports.DISPATCH_LIMITS = {
|
|
20
|
+
template: 100,
|
|
21
|
+
email: 254,
|
|
22
|
+
name: 200,
|
|
23
|
+
dataKeys: 40,
|
|
24
|
+
dataKey: 64,
|
|
25
|
+
dataValue: 2000,
|
|
26
|
+
secretKeys: 10,
|
|
27
|
+
permission: 100,
|
|
28
|
+
};
|
|
29
|
+
/** Template variables are flat scalars: they are printed into the copy, never serialised objects. */
|
|
30
|
+
exports.dispatchValueSchema = zod_1.z.union([zod_1.z.string().max(exports.DISPATCH_LIMITS.dataValue), zod_1.z.number().finite(), zod_1.z.boolean(), zod_1.z.null()]);
|
|
31
|
+
exports.dispatchRecipientSchema = zod_1.z.object({
|
|
32
|
+
email: zod_1.z.string().trim().email().max(exports.DISPATCH_LIMITS.email),
|
|
33
|
+
name: zod_1.z.string().trim().max(exports.DISPATCH_LIMITS.name).optional(),
|
|
34
|
+
userId: zod_1.z.string().max(36).nullish(),
|
|
35
|
+
locale: zod_1.z.string().max(20).nullish(),
|
|
36
|
+
/** IANA zone; time variables are rendered in it. */
|
|
37
|
+
timezone: zod_1.z.string().max(64).nullish(),
|
|
38
|
+
});
|
|
39
|
+
const dataKey = zod_1.z.string().regex(/^[A-Za-z][A-Za-z0-9_]*$/, 'Use a template variable name').max(exports.DISPATCH_LIMITS.dataKey);
|
|
40
|
+
exports.notificationDispatchSchema = zod_1.z
|
|
41
|
+
.object({
|
|
42
|
+
/** Seeded `notification_templates.slug`. */
|
|
43
|
+
template: zod_1.z.string().trim().min(1).max(exports.DISPATCH_LIMITS.template),
|
|
44
|
+
category: zod_1.z.enum(exports.NOTIFICATION_CATEGORIES),
|
|
45
|
+
recipient: exports.dispatchRecipientSchema,
|
|
46
|
+
channels: zod_1.z.array(zod_1.z.enum(exports.DISPATCH_CHANNELS)).min(1).max(exports.DISPATCH_CHANNELS.length),
|
|
47
|
+
data: zod_1.z
|
|
48
|
+
.record(dataKey, exports.dispatchValueSchema)
|
|
49
|
+
.default({})
|
|
50
|
+
.refine((data) => Object.keys(data).length <= exports.DISPATCH_LIMITS.dataKeys, `At most ${exports.DISPATCH_LIMITS.dataKeys} variables`),
|
|
51
|
+
/**
|
|
52
|
+
* Keys of `data` holding a one-time secret (a sign-in code, a reset or confirm link). They are used to
|
|
53
|
+
* render the email and nothing else: notification-service never stores them and never puts them in the
|
|
54
|
+
* in-app feed, and email-service masks them in what it keeps.
|
|
55
|
+
*/
|
|
56
|
+
secretKeys: zod_1.z.array(dataKey).max(exports.DISPATCH_LIMITS.secretKeys).default([]),
|
|
57
|
+
/** Security and staff alerts are always delivered, whatever the recipient's preferences. */
|
|
58
|
+
bypassPreferences: zod_1.z.boolean().optional(),
|
|
59
|
+
/** The permission staff recipients hold; informational until recipients are resolved by permission. */
|
|
60
|
+
targetPermission: zod_1.z.string().max(exports.DISPATCH_LIMITS.permission).optional(),
|
|
61
|
+
})
|
|
62
|
+
.superRefine((dispatch, ctx) => {
|
|
63
|
+
for (const key of dispatch.secretKeys) {
|
|
64
|
+
if (!(key in dispatch.data)) {
|
|
65
|
+
ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ['secretKeys'], message: `Secret key "${key}" is not in data` });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* The seeded templates Showbiz services dispatch, with the variables (`data` keys) each dispatch carries.
|
|
71
|
+
* Producers send exactly these keys; a seeded template may use any subset (notification-service dead-letters
|
|
72
|
+
* a dispatch missing a variable its template uses). Both sides test against this table.
|
|
73
|
+
*/
|
|
74
|
+
exports.DISPATCH_TEMPLATE_VARIABLES = {
|
|
75
|
+
// auth-admin-service: account and security mail
|
|
76
|
+
'account-activation': ['name', 'code', 'expiresInHours'],
|
|
77
|
+
'login-otp': ['name', 'code', 'expiresInMinutes', 'device'],
|
|
78
|
+
'password-reset': ['name', 'resetUrl', 'expiresInMinutes'],
|
|
79
|
+
'staff-invitation': ['name', 'resetUrl', 'expiresInMinutes'],
|
|
80
|
+
'password-changed': ['name', 'changedAt'],
|
|
81
|
+
'new-device-login': ['name', 'device', 'ip', 'country', 'occurredAt', 'confirmUrl', 'disputeUrl'],
|
|
82
|
+
'team-member-added': ['name', 'profileName', 'role', 'invitedBy'],
|
|
83
|
+
'account-suspended': ['name', 'reason'],
|
|
84
|
+
'welcome-listener': ['name'],
|
|
85
|
+
'welcome-creator': ['name'],
|
|
86
|
+
// ai / newswire / editorial: staff alerts
|
|
87
|
+
'ai_budget_threshold': ['requester', 'period', 'threshold_pct', 'spent_usd', 'limit_usd'],
|
|
88
|
+
'newswire_source_unhealthy': ['source_name', 'source_slug', 'consecutive_failures', 'last_error', 'last_success_at'],
|
|
89
|
+
'newswire_block_rate_high': ['blocked', 'total', 'block_rate_pct', 'window_hours'],
|
|
90
|
+
'autopublish_audit_alert': ['problem_rate_pct', 'problem_count', 'sample_count', 'window_days', 'action_taken'],
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=notification-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-dispatch.js","sourceRoot":"","sources":["../../../src/contracts/notification-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadImportFailedSchema = exports.uploadImportCompletedSchema = exports.uploadImportCommandSchema = exports.UPLOAD_IMPORT_LIMITS = exports.UPLOAD_IMPORT_POLICIES = exports.UPLOAD_IMPORT_EVENTS = exports.UPLOAD_IMPORT = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const index_js_1 = require("../validation/index.js");
|
|
6
|
+
/**
|
|
7
|
+
* Licensed image import by URL (Newswire R5, decision R39). newswire-service (and later
|
|
8
|
+
* editorial-service) sends `upload:import`; upload-service fetches the file and answers with an
|
|
9
|
+
* `upload.import.completed` or `upload.import.failed` event. One contract for both sides.
|
|
10
|
+
*/
|
|
11
|
+
exports.UPLOAD_IMPORT = 'upload:import';
|
|
12
|
+
exports.UPLOAD_IMPORT_EVENTS = {
|
|
13
|
+
COMPLETED: 'upload.import.completed',
|
|
14
|
+
FAILED: 'upload.import.failed',
|
|
15
|
+
};
|
|
16
|
+
/** Upload policies an import may use. */
|
|
17
|
+
exports.UPLOAD_IMPORT_POLICIES = ['news_image'];
|
|
18
|
+
/** Field limits of the contract (upload-service's `uploads` columns). */
|
|
19
|
+
exports.UPLOAD_IMPORT_LIMITS = {
|
|
20
|
+
url: 2048,
|
|
21
|
+
ownerType: 50,
|
|
22
|
+
licenceHolder: 160,
|
|
23
|
+
licenceBasis: 255,
|
|
24
|
+
reason: 255,
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* `upload:import` data. The URL is only length-checked here: upload-service rejects a non-https or
|
|
28
|
+
* unsafe URL itself, so the sender hears about it through a `failed` event instead of a dead letter.
|
|
29
|
+
*/
|
|
30
|
+
exports.uploadImportCommandSchema = zod_1.z.object({
|
|
31
|
+
/** ULID the outcome event echoes back; upload-service is idempotent on it. */
|
|
32
|
+
importId: index_js_1.idSchema,
|
|
33
|
+
url: zod_1.z.string().min(1).max(exports.UPLOAD_IMPORT_LIMITS.url),
|
|
34
|
+
policy: zod_1.z.enum(exports.UPLOAD_IMPORT_POLICIES),
|
|
35
|
+
/** Echoed in the outcome only; the imported upload is a system row with no owner. */
|
|
36
|
+
ownerType: zod_1.z.string().min(1).max(exports.UPLOAD_IMPORT_LIMITS.ownerType),
|
|
37
|
+
ownerId: index_js_1.idSchema,
|
|
38
|
+
licence: zod_1.z.object({
|
|
39
|
+
holder: zod_1.z.string().trim().min(1).max(exports.UPLOAD_IMPORT_LIMITS.licenceHolder),
|
|
40
|
+
basis: zod_1.z.string().trim().min(1).max(exports.UPLOAD_IMPORT_LIMITS.licenceBasis),
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
exports.uploadImportCompletedSchema = zod_1.z.object({
|
|
44
|
+
importId: index_js_1.idSchema,
|
|
45
|
+
uploadId: index_js_1.idSchema,
|
|
46
|
+
ownerType: zod_1.z.string().min(1).max(exports.UPLOAD_IMPORT_LIMITS.ownerType),
|
|
47
|
+
ownerId: index_js_1.idSchema,
|
|
48
|
+
});
|
|
49
|
+
/** `reason` is a machine code (`too_large`, `http_404`, …; see upload-service `ImportFailureReason`). */
|
|
50
|
+
exports.uploadImportFailedSchema = zod_1.z.object({
|
|
51
|
+
importId: index_js_1.idSchema,
|
|
52
|
+
reason: zod_1.z.string().min(1).max(exports.UPLOAD_IMPORT_LIMITS.reason),
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=upload-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-import.js","sourceRoot":"","sources":["../../../src/contracts/upload-import.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,qDAAkD;AAElD;;;;GAIG;AACU,QAAA,aAAa,GAAG,eAAe,CAAC;AAEhC,QAAA,oBAAoB,GAAG;IAClC,SAAS,EAAE,yBAAyB;IACpC,MAAM,EAAE,sBAAsB;CACtB,CAAC;AAEX,yCAAyC;AAC5B,QAAA,sBAAsB,GAAG,CAAC,YAAY,CAAU,CAAC;AAG9D,yEAAyE;AAC5D,QAAA,oBAAoB,GAAG;IAClC,GAAG,EAAE,IAAI;IACT,SAAS,EAAE,EAAE;IACb,aAAa,EAAE,GAAG;IAClB,YAAY,EAAE,GAAG;IACjB,MAAM,EAAE,GAAG;CACH,CAAC;AAEX;;;GAGG;AACU,QAAA,yBAAyB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChD,8EAA8E;IAC9E,QAAQ,EAAE,mBAAQ;IAClB,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,4BAAoB,CAAC,GAAG,CAAC;IACpD,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,8BAAsB,CAAC;IACtC,qFAAqF;IACrF,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,4BAAoB,CAAC,SAAS,CAAC;IAChE,OAAO,EAAE,mBAAQ;IACjB,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC;QAChB,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,4BAAoB,CAAC,aAAa,CAAC;QACxE,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,4BAAoB,CAAC,YAAY,CAAC;KACvE,CAAC;CACH,CAAC,CAAC;AAEU,QAAA,2BAA2B,GAAG,OAAC,CAAC,MAAM,CAAC;IAClD,QAAQ,EAAE,mBAAQ;IAClB,QAAQ,EAAE,mBAAQ;IAClB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,4BAAoB,CAAC,SAAS,CAAC;IAChE,OAAO,EAAE,mBAAQ;CAClB,CAAC,CAAC;AAEH,yGAAyG;AAC5F,QAAA,wBAAwB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC/C,QAAQ,EAAE,mBAAQ;IAClB,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,4BAAoB,CAAC,MAAM,CAAC;CAC3D,CAAC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createMysqlPool = createMysqlPool;
|
|
7
|
+
exports.createKnexConfig = createKnexConfig;
|
|
8
|
+
exports.pingMysql = pingMysql;
|
|
9
|
+
exports.escapeLike = escapeLike;
|
|
10
|
+
const promise_1 = __importDefault(require("mysql2/promise"));
|
|
11
|
+
/**
|
|
12
|
+
* mysql2 pool for Drizzle. Sessions run in UTC and utf8mb4 so timestamps and emoji round-trip
|
|
13
|
+
* unchanged regardless of server defaults.
|
|
14
|
+
*/
|
|
15
|
+
function createMysqlPool(options) {
|
|
16
|
+
return promise_1.default.createPool({
|
|
17
|
+
host: options.host,
|
|
18
|
+
port: options.port,
|
|
19
|
+
user: options.user,
|
|
20
|
+
password: options.password,
|
|
21
|
+
database: options.database,
|
|
22
|
+
connectionLimit: options.poolMax ?? 10,
|
|
23
|
+
waitForConnections: true,
|
|
24
|
+
enableKeepAlive: true,
|
|
25
|
+
timezone: 'Z',
|
|
26
|
+
charset: 'utf8mb4_unicode_ci',
|
|
27
|
+
dateStrings: false,
|
|
28
|
+
supportBigNumbers: true,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Knex config for migrations/seeds and query-builder use (same session settings as the pool). */
|
|
32
|
+
function createKnexConfig(options) {
|
|
33
|
+
return {
|
|
34
|
+
client: 'mysql2',
|
|
35
|
+
connection: {
|
|
36
|
+
host: options.host,
|
|
37
|
+
port: options.port,
|
|
38
|
+
user: options.user,
|
|
39
|
+
password: options.password,
|
|
40
|
+
database: options.database,
|
|
41
|
+
timezone: 'Z',
|
|
42
|
+
charset: 'utf8mb4',
|
|
43
|
+
},
|
|
44
|
+
pool: { min: 0, max: options.poolMax ?? 10 },
|
|
45
|
+
migrations: { directory: options.migrationsDir ?? './migrations', tableName: 'knex_migrations', loadExtensions: ['.cjs', '.js'] },
|
|
46
|
+
seeds: { directory: options.seedsDir ?? './seeds', loadExtensions: ['.cjs', '.js'] },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Readiness probe helper. */
|
|
50
|
+
async function pingMysql(pool) {
|
|
51
|
+
await pool.query('SELECT 1');
|
|
52
|
+
}
|
|
53
|
+
/** Escapes `%`, `_` and `\` for use inside a LIKE pattern. */
|
|
54
|
+
function escapeLike(value) {
|
|
55
|
+
return value.replace(/[\\%_]/g, (ch) => `\\${ch}`);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/database/index.ts"],"names":[],"mappings":";;;;;AAgBA,0CAeC;AAGD,4CAgBC;AAGD,8BAEC;AAGD,gCAEC;AA3DD,6DAAmC;AAWnC;;;GAGG;AACH,SAAgB,eAAe,CAAC,OAA+B;IAC7D,OAAO,iBAAK,CAAC,UAAU,CAAC;QACtB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,eAAe,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QACtC,kBAAkB,EAAE,IAAI;QACxB,eAAe,EAAE,IAAI;QACrB,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE,oBAAoB;QAC7B,WAAW,EAAE,KAAK;QAClB,iBAAiB,EAAE,IAAI;KACxB,CAAC,CAAC;AACL,CAAC;AAED,kGAAkG;AAClG,SAAgB,gBAAgB,CAAC,OAA+E;IAC9G,OAAO;QACL,MAAM,EAAE,QAAQ;QAChB,UAAU,EAAE;YACV,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,QAAQ,EAAE,GAAG;YACb,OAAO,EAAE,SAAS;SACnB;QACD,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE;QAC5C,UAAU,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,aAAa,IAAI,cAAc,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;QACjI,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;KACrF,CAAC;AACJ,CAAC;AAED,8BAA8B;AACvB,KAAK,UAAU,SAAS,CAAC,IAAgB;IAC9C,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAC/B,CAAC;AAED,8DAA8D;AAC9D,SAAgB,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireRole = exports.requireAllPermissions = exports.requirePermission = void 0;
|
|
4
|
+
exports.authenticateFromGateway = authenticateFromGateway;
|
|
5
|
+
exports.optionalAuthFromGateway = optionalAuthFromGateway;
|
|
6
|
+
exports.requireInternalServiceSecret = requireInternalServiceSecret;
|
|
7
|
+
const index_js_1 = require("../access/index.js");
|
|
8
|
+
const crypto_js_1 = require("../common/crypto.js");
|
|
9
|
+
const response_js_1 = require("../common/response.js");
|
|
10
|
+
const index_js_2 = require("../identity/index.js");
|
|
11
|
+
function resolveIdentity(req, options) {
|
|
12
|
+
const result = (0, index_js_2.verifyIdentityHeaders)(req.headers, options.secret, { maxSkewMs: options.maxSkewMs });
|
|
13
|
+
if (result.status === 'authenticated') {
|
|
14
|
+
req.user = result.user;
|
|
15
|
+
return 'ok';
|
|
16
|
+
}
|
|
17
|
+
if (result.status === 'invalid') {
|
|
18
|
+
options.logger?.warn('Rejected forged or stale gateway identity', { reason: result.reason, path: req.path });
|
|
19
|
+
return 'invalid';
|
|
20
|
+
}
|
|
21
|
+
return 'anonymous';
|
|
22
|
+
}
|
|
23
|
+
/** Requires a valid gateway-signed identity; 401 otherwise. */
|
|
24
|
+
function authenticateFromGateway(options) {
|
|
25
|
+
return (req, res, next) => {
|
|
26
|
+
if (resolveIdentity(req, options) === 'ok')
|
|
27
|
+
return next();
|
|
28
|
+
res.status(401).json((0, response_js_1.errorResponse)('Authentication required', undefined, 'UNAUTHENTICATED'));
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Attaches `req.user` when a valid identity is present; continues anonymously otherwise. */
|
|
32
|
+
function optionalAuthFromGateway(options) {
|
|
33
|
+
return (req, res, next) => {
|
|
34
|
+
if (resolveIdentity(req, options) === 'invalid') {
|
|
35
|
+
res.status(401).json((0, response_js_1.errorResponse)('Invalid identity', undefined, 'UNAUTHENTICATED'));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
next();
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function guard(check, message = 'You do not have permission to perform this action') {
|
|
42
|
+
return (req, res, next) => {
|
|
43
|
+
if (!req.user) {
|
|
44
|
+
res.status(401).json((0, response_js_1.errorResponse)('Authentication required', undefined, 'UNAUTHENTICATED'));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!check(req.user)) {
|
|
48
|
+
res.status(403).json((0, response_js_1.errorResponse)(message, undefined, 'FORBIDDEN'));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
next();
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Allows callers holding any of `permissions`. */
|
|
55
|
+
const requirePermission = (...permissions) => guard((u) => (0, index_js_1.hasPermission)(u, ...permissions));
|
|
56
|
+
exports.requirePermission = requirePermission;
|
|
57
|
+
/** Allows callers holding every one of `permissions`. */
|
|
58
|
+
const requireAllPermissions = (...permissions) => guard((u) => (0, index_js_1.hasAllPermissions)(u, ...permissions));
|
|
59
|
+
exports.requireAllPermissions = requireAllPermissions;
|
|
60
|
+
/** Allows callers with any of `roles`. Prefer permissions; roles are for coarse gates only. */
|
|
61
|
+
const requireRole = (...roles) => guard((u) => (0, index_js_1.hasRole)(u, ...roles), 'Insufficient role');
|
|
62
|
+
exports.requireRole = requireRole;
|
|
63
|
+
/** Guards `/internal/*` routes: requires the shared service secret header. */
|
|
64
|
+
function requireInternalServiceSecret(secret) {
|
|
65
|
+
return (req, res, next) => {
|
|
66
|
+
const provided = req.headers[index_js_2.CONTEXT_HEADERS.INTERNAL_SECRET];
|
|
67
|
+
if (typeof provided === 'string' && secret && (0, crypto_js_1.safeEqual)(provided, secret))
|
|
68
|
+
return next();
|
|
69
|
+
res.status(401).json((0, response_js_1.errorResponse)('Invalid internal service credentials', undefined, 'UNAUTHENTICATED'));
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/express/auth.ts"],"names":[],"mappings":";;;AAoCA,0DAKC;AAGD,0DAQC;AA0BD,oEAMC;AAnFD,iDAA+E;AAC/E,mDAAgD;AAChD,uDAAsD;AACtD,mDAA8E;AAkB9E,SAAS,eAAe,CAAC,GAAY,EAAE,OAA2B;IAChE,MAAM,MAAM,GAAG,IAAA,gCAAqB,EAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACpG,IAAI,MAAM,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;QACtC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,2CAA2C,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7G,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,+DAA+D;AAC/D,SAAgB,uBAAuB,CAAC,OAA2B;IACjE,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,IAAI,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,IAAI;YAAE,OAAO,IAAI,EAAE,CAAC;QAC1D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,2BAAa,EAAC,yBAAyB,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC/F,CAAC,CAAC;AACJ,CAAC;AAED,6FAA6F;AAC7F,SAAgB,uBAAuB,CAAC,OAA2B;IACjE,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,IAAI,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;YAChD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,2BAAa,EAAC,kBAAkB,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;YACtF,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,KAAkC,EAAE,OAAO,GAAG,mDAAmD;IAC9G,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,2BAAa,EAAC,yBAAyB,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;YAC7F,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,2BAAa,EAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC;AAED,mDAAmD;AAC5C,MAAM,iBAAiB,GAAG,CAAC,GAAG,WAAqB,EAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,wBAAa,EAAC,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;AAAjH,QAAA,iBAAiB,qBAAgG;AAE9H,yDAAyD;AAClD,MAAM,qBAAqB,GAAG,CAAC,GAAG,WAAqB,EAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,4BAAiB,EAAC,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;AAAzH,QAAA,qBAAqB,yBAAoG;AAEtI,+FAA+F;AACxF,MAAM,WAAW,GAAG,CAAC,GAAG,KAAe,EAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,kBAAO,EAAC,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAA9G,QAAA,WAAW,eAAmG;AAE3H,8EAA8E;AAC9E,SAAgB,4BAA4B,CAAC,MAAc;IACzD,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,0BAAe,CAAC,eAAe,CAAC,CAAC;QAC9D,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,MAAM,IAAI,IAAA,qBAAS,EAAC,QAAQ,EAAE,MAAM,CAAC;YAAE,OAAO,IAAI,EAAE,CAAC;QACzF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAA,2BAAa,EAAC,sCAAsC,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC5G,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.livenessHandler = livenessHandler;
|
|
4
|
+
exports.readinessHandler = readinessHandler;
|
|
5
|
+
const async_js_1 = require("../common/async.js");
|
|
6
|
+
/** `GET /health` — liveness: the process is up. Never touches dependencies. */
|
|
7
|
+
function livenessHandler(options) {
|
|
8
|
+
const startedAt = Date.now();
|
|
9
|
+
return (_req, res) => {
|
|
10
|
+
res.json({ status: 'ok', service: options.service, version: options.version, uptimeSec: Math.round((Date.now() - startedAt) / 1000) });
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** `GET /health/ready` — readiness: every dependency responds. 503 when any fails. */
|
|
14
|
+
function readinessHandler(options) {
|
|
15
|
+
return async (_req, res) => {
|
|
16
|
+
const entries = Object.entries(options.checks ?? {});
|
|
17
|
+
const results = await Promise.all(entries.map(async ([name, check]) => {
|
|
18
|
+
const started = Date.now();
|
|
19
|
+
try {
|
|
20
|
+
const detail = await (0, async_js_1.withTimeout)(Promise.resolve(check()), options.timeoutMs ?? 3000, () => new Error('timeout'));
|
|
21
|
+
return [name, { status: 'up', latencyMs: Date.now() - started, ...(detail && typeof detail === 'object' ? { detail } : {}) }];
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
return [name, { status: 'down', latencyMs: Date.now() - started, error: error.message }];
|
|
25
|
+
}
|
|
26
|
+
}));
|
|
27
|
+
const healthy = results.every(([, r]) => r.status === 'up');
|
|
28
|
+
res.status(healthy ? 200 : 503).json({ status: healthy ? 'ok' : 'degraded', service: options.service, checks: Object.fromEntries(results) });
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/express/health.ts"],"names":[],"mappings":";;AAcA,0CAKC;AAGD,4CAeC;AApCD,iDAAiD;AAYjD,+EAA+E;AAC/E,SAAgB,eAAe,CAAC,OAAsB;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,OAAO,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACtC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IACzI,CAAC,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,SAAgB,gBAAgB,CAAC,OAAsB;IACrD,OAAO,KAAK,EAAE,IAAa,EAAE,GAAa,EAAE,EAAE;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;YACpE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAA,sBAAW,EAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;gBAClH,OAAO,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAU,CAAC;YACzI,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,CAAU,CAAC;YAC/G,CAAC;QACH,CAAC,CAAC,CAAC,CAAC;QACJ,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;QAC5D,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/I,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./auth.js"), exports);
|
|
18
|
+
__exportStar(require("./middleware.js"), exports);
|
|
19
|
+
__exportStar(require("./health.js"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/express/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,kDAAgC;AAChC,8CAA4B"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.correlationMiddleware = correlationMiddleware;
|
|
4
|
+
exports.correlationId = correlationId;
|
|
5
|
+
exports.clientIp = clientIp;
|
|
6
|
+
exports.clientTimezone = clientTimezone;
|
|
7
|
+
exports.anonId = anonId;
|
|
8
|
+
exports.validate = validate;
|
|
9
|
+
exports.asyncHandler = asyncHandler;
|
|
10
|
+
exports.errorHandler = errorHandler;
|
|
11
|
+
exports.notFoundHandler = notFoundHandler;
|
|
12
|
+
const errors_js_1 = require("../common/errors.js");
|
|
13
|
+
const id_js_1 = require("../common/id.js");
|
|
14
|
+
const response_js_1 = require("../common/response.js");
|
|
15
|
+
const index_js_1 = require("../identity/index.js");
|
|
16
|
+
const index_js_2 = require("../validation/index.js");
|
|
17
|
+
/** Ensures every request carries `x-correlation-id` (reused from the gateway when present). */
|
|
18
|
+
function correlationMiddleware() {
|
|
19
|
+
return (req, res, next) => {
|
|
20
|
+
const incoming = req.headers[index_js_1.CONTEXT_HEADERS.CORRELATION_ID];
|
|
21
|
+
const id = typeof incoming === 'string' && incoming.length <= 128 ? incoming : (0, id_js_1.newId)();
|
|
22
|
+
req.headers[index_js_1.CONTEXT_HEADERS.CORRELATION_ID] = id;
|
|
23
|
+
res.setHeader(index_js_1.CONTEXT_HEADERS.CORRELATION_ID, id);
|
|
24
|
+
next();
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function correlationId(req) {
|
|
28
|
+
const value = req.headers[index_js_1.CONTEXT_HEADERS.CORRELATION_ID];
|
|
29
|
+
return typeof value === 'string' ? value : undefined;
|
|
30
|
+
}
|
|
31
|
+
/** Real client IP: gateway-forwarded header first, then Express's `req.ip`. */
|
|
32
|
+
function clientIp(req) {
|
|
33
|
+
const forwarded = req.headers[index_js_1.CONTEXT_HEADERS.CLIENT_IP];
|
|
34
|
+
if (typeof forwarded === 'string' && forwarded)
|
|
35
|
+
return forwarded;
|
|
36
|
+
return req.ip ?? null;
|
|
37
|
+
}
|
|
38
|
+
function clientTimezone(req) {
|
|
39
|
+
const tz = req.headers[index_js_1.CONTEXT_HEADERS.TIMEZONE];
|
|
40
|
+
return typeof tz === 'string' && tz ? tz : null;
|
|
41
|
+
}
|
|
42
|
+
function anonId(req) {
|
|
43
|
+
const id = req.headers[index_js_1.CONTEXT_HEADERS.ANON_ID];
|
|
44
|
+
return typeof id === 'string' && id ? id : null;
|
|
45
|
+
}
|
|
46
|
+
/** Validates and replaces `req[part]` with the parsed value; 422 with field errors on failure. */
|
|
47
|
+
function validate(schema, part = 'body') {
|
|
48
|
+
return (req, res, next) => {
|
|
49
|
+
const result = schema.safeParse(req[part]);
|
|
50
|
+
if (!result.success) {
|
|
51
|
+
res.status(422).json((0, response_js_1.errorResponse)('Validation failed', (0, index_js_2.zodIssuesToErrors)(result.error), 'VALIDATION_FAILED'));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Express 5 exposes req.query as a getter; redefine to store the parsed value.
|
|
55
|
+
Object.defineProperty(req, part, { value: result.data, writable: true, configurable: true, enumerable: true });
|
|
56
|
+
next();
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Wraps an async handler so rejections reach the error middleware (needed on Express 4). */
|
|
60
|
+
function asyncHandler(fn) {
|
|
61
|
+
return (req, res, next) => {
|
|
62
|
+
fn(req, res, next).catch(next);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** Maps AppErrors to their status; everything else becomes a logged 500 with a generic message. */
|
|
66
|
+
function errorHandler(logger) {
|
|
67
|
+
return (err, req, res, _next) => {
|
|
68
|
+
if (res.headersSent)
|
|
69
|
+
return;
|
|
70
|
+
const bodyError = err;
|
|
71
|
+
if (bodyError?.type === 'entity.parse.failed') {
|
|
72
|
+
res.status(400).json((0, response_js_1.errorResponse)('Malformed JSON body', undefined, 'BAD_REQUEST'));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (bodyError?.type === 'entity.too.large') {
|
|
76
|
+
res.status(413).json((0, response_js_1.errorResponse)('Request body too large', undefined, 'PAYLOAD_TOO_LARGE'));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if ((0, errors_js_1.isAppError)(err)) {
|
|
80
|
+
if (err.statusCode >= 500)
|
|
81
|
+
logger?.error(err.message, { path: req.path, code: err.code, correlationId: correlationId(req) });
|
|
82
|
+
res.status(err.statusCode).json((0, response_js_1.errorResponse)((0, errors_js_1.publicMessage)(err), err.errors, err.code));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
86
|
+
logger?.error('Unhandled error', { error: error.message, stack: error.stack, path: req.path, correlationId: correlationId(req) });
|
|
87
|
+
res.status(500).json((0, response_js_1.errorResponse)('Internal server error', undefined, 'INTERNAL_ERROR'));
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function notFoundHandler() {
|
|
91
|
+
return (_req, res) => {
|
|
92
|
+
res.status(404).json((0, response_js_1.errorResponse)('Resource not found', undefined, 'NOT_FOUND'));
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/express/middleware.ts"],"names":[],"mappings":"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"}
|