@reaatech/prompt-version-control-server 0.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/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +261 -0
- package/dist/api/routes/deployments.d.ts +4 -0
- package/dist/api/routes/deployments.d.ts.map +1 -0
- package/dist/api/routes/deployments.js +48 -0
- package/dist/api/routes/deployments.js.map +1 -0
- package/dist/api/routes/docs.d.ts +4 -0
- package/dist/api/routes/docs.d.ts.map +1 -0
- package/dist/api/routes/docs.js +75 -0
- package/dist/api/routes/docs.js.map +1 -0
- package/dist/api/routes/evaluations.d.ts +4 -0
- package/dist/api/routes/evaluations.d.ts.map +1 -0
- package/dist/api/routes/evaluations.js +63 -0
- package/dist/api/routes/evaluations.js.map +1 -0
- package/dist/api/routes/metrics.d.ts +4 -0
- package/dist/api/routes/metrics.d.ts.map +1 -0
- package/dist/api/routes/metrics.js +38 -0
- package/dist/api/routes/metrics.js.map +1 -0
- package/dist/api/routes/promotions.d.ts +4 -0
- package/dist/api/routes/promotions.d.ts.map +1 -0
- package/dist/api/routes/promotions.js +95 -0
- package/dist/api/routes/promotions.js.map +1 -0
- package/dist/api/routes/prompts.d.ts +4 -0
- package/dist/api/routes/prompts.d.ts.map +1 -0
- package/dist/api/routes/prompts.js +80 -0
- package/dist/api/routes/prompts.js.map +1 -0
- package/dist/api/routes/render.d.ts +4 -0
- package/dist/api/routes/render.d.ts.map +1 -0
- package/dist/api/routes/render.js +44 -0
- package/dist/api/routes/render.js.map +1 -0
- package/dist/api/routes/tags.d.ts +4 -0
- package/dist/api/routes/tags.d.ts.map +1 -0
- package/dist/api/routes/tags.js +41 -0
- package/dist/api/routes/tags.js.map +1 -0
- package/dist/api/routes/webhooks.d.ts +4 -0
- package/dist/api/routes/webhooks.d.ts.map +1 -0
- package/dist/api/routes/webhooks.js +49 -0
- package/dist/api/routes/webhooks.js.map +1 -0
- package/dist/db/client.d.ts +3 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +21 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/redis.d.ts +3 -0
- package/dist/db/redis.d.ts.map +1 -0
- package/dist/db/redis.js +18 -0
- package/dist/db/redis.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +83 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/audit.d.ts +3 -0
- package/dist/middleware/audit.d.ts.map +1 -0
- package/dist/middleware/audit.js +39 -0
- package/dist/middleware/audit.js.map +1 -0
- package/dist/middleware/auth.d.ts +3 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +49 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +3 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +36 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/metrics.d.ts +3 -0
- package/dist/middleware/metrics.d.ts.map +1 -0
- package/dist/middleware/metrics.js +13 -0
- package/dist/middleware/metrics.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +8 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +89 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/middleware/request-id.d.ts +3 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +10 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/services/audit.service.d.ts +6 -0
- package/dist/services/audit.service.d.ts.map +1 -0
- package/dist/services/audit.service.js +26 -0
- package/dist/services/audit.service.js.map +1 -0
- package/dist/services/deployment.service.d.ts +101 -0
- package/dist/services/deployment.service.d.ts.map +1 -0
- package/dist/services/deployment.service.js +127 -0
- package/dist/services/deployment.service.js.map +1 -0
- package/dist/services/diff.engine.d.ts +13 -0
- package/dist/services/diff.engine.d.ts.map +1 -0
- package/dist/services/diff.engine.js +101 -0
- package/dist/services/diff.engine.js.map +1 -0
- package/dist/services/eval.service.d.ts +55 -0
- package/dist/services/eval.service.d.ts.map +1 -0
- package/dist/services/eval.service.js +151 -0
- package/dist/services/eval.service.js.map +1 -0
- package/dist/services/event.bus.d.ts +18 -0
- package/dist/services/event.bus.d.ts.map +1 -0
- package/dist/services/event.bus.js +35 -0
- package/dist/services/event.bus.js.map +1 -0
- package/dist/services/metric.service.d.ts +33 -0
- package/dist/services/metric.service.d.ts.map +1 -0
- package/dist/services/metric.service.js +64 -0
- package/dist/services/metric.service.js.map +1 -0
- package/dist/services/prometheus.service.d.ts +7 -0
- package/dist/services/prometheus.service.d.ts.map +1 -0
- package/dist/services/prometheus.service.js +27 -0
- package/dist/services/prometheus.service.js.map +1 -0
- package/dist/services/prompt.service.d.ts +59 -0
- package/dist/services/prompt.service.d.ts.map +1 -0
- package/dist/services/prompt.service.js +144 -0
- package/dist/services/prompt.service.js.map +1 -0
- package/dist/services/tag.service.d.ts +46 -0
- package/dist/services/tag.service.d.ts.map +1 -0
- package/dist/services/tag.service.js +84 -0
- package/dist/services/tag.service.js.map +1 -0
- package/dist/services/webhook.service.d.ts +50 -0
- package/dist/services/webhook.service.d.ts.map +1 -0
- package/dist/services/webhook.service.js +196 -0
- package/dist/services/webhook.service.js.map +1 -0
- package/dist/types/hono.d.ts +10 -0
- package/dist/types/hono.d.ts.map +1 -0
- package/dist/types/hono.js +2 -0
- package/dist/types/hono.js.map +1 -0
- package/dist/utils/context.d.ts +3 -0
- package/dist/utils/context.d.ts.map +1 -0
- package/dist/utils/context.js +9 -0
- package/dist/utils/context.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +20 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pagination.d.ts +10 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +10 -0
- package/dist/utils/pagination.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { calculateChecksum } from '@reaatech/prompt-version-control-shared';
|
|
2
|
+
import { prisma } from '../db/client.js';
|
|
3
|
+
import { ConflictError, NotFoundError } from '../errors.js';
|
|
4
|
+
import { paginateResult } from '../utils/pagination.js';
|
|
5
|
+
import { promptVersionsCreated } from './prometheus.service.js';
|
|
6
|
+
export class PromptService {
|
|
7
|
+
async createPrompt(projectId, data) {
|
|
8
|
+
const existing = await prisma.prompt.findFirst({
|
|
9
|
+
where: { projectId, name: data.name },
|
|
10
|
+
});
|
|
11
|
+
if (existing) {
|
|
12
|
+
throw new ConflictError('Prompt name already exists in this project');
|
|
13
|
+
}
|
|
14
|
+
const prompt = await prisma.prompt.create({
|
|
15
|
+
data: {
|
|
16
|
+
...data,
|
|
17
|
+
projectId,
|
|
18
|
+
variables: data.variables ?? {},
|
|
19
|
+
metadata: data.metadata,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
return prompt;
|
|
23
|
+
}
|
|
24
|
+
async getPrompt(projectId, id) {
|
|
25
|
+
const prompt = await prisma.prompt.findFirst({
|
|
26
|
+
where: { id, projectId },
|
|
27
|
+
});
|
|
28
|
+
if (!prompt) {
|
|
29
|
+
throw new NotFoundError('Prompt', id);
|
|
30
|
+
}
|
|
31
|
+
return prompt;
|
|
32
|
+
}
|
|
33
|
+
async listPrompts(projectId, opts) {
|
|
34
|
+
const prompts = await prisma.prompt.findMany({
|
|
35
|
+
where: { projectId, archived: false },
|
|
36
|
+
take: opts.limit + 1,
|
|
37
|
+
cursor: opts.cursor ? { id: opts.cursor } : undefined,
|
|
38
|
+
orderBy: { createdAt: 'desc' },
|
|
39
|
+
});
|
|
40
|
+
return paginateResult(prompts, opts.limit);
|
|
41
|
+
}
|
|
42
|
+
async updatePrompt(projectId, id, data) {
|
|
43
|
+
await this.getPrompt(projectId, id);
|
|
44
|
+
return prisma.prompt.update({
|
|
45
|
+
where: { id },
|
|
46
|
+
data: data,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async archivePrompt(projectId, id) {
|
|
50
|
+
await this.getPrompt(projectId, id);
|
|
51
|
+
const prompt = await prisma.prompt.update({
|
|
52
|
+
where: { id },
|
|
53
|
+
data: { archived: true },
|
|
54
|
+
});
|
|
55
|
+
return prompt;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a new version. Wrapped in a transaction with a unique-violation
|
|
59
|
+
* retry loop so concurrent creates against the same prompt don't both win
|
|
60
|
+
* the same version number.
|
|
61
|
+
*/
|
|
62
|
+
async createVersion(projectId, promptId, data) {
|
|
63
|
+
const prompt = await prisma.prompt.findFirst({
|
|
64
|
+
where: { id: promptId, projectId },
|
|
65
|
+
select: { id: true, projectId: true },
|
|
66
|
+
});
|
|
67
|
+
if (!prompt) {
|
|
68
|
+
throw new NotFoundError('Prompt', promptId);
|
|
69
|
+
}
|
|
70
|
+
const checksum = calculateChecksum(data.content);
|
|
71
|
+
const MAX_ATTEMPTS = 5;
|
|
72
|
+
let lastError;
|
|
73
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
74
|
+
const maxVersion = await prisma.version.findFirst({
|
|
75
|
+
where: { promptId },
|
|
76
|
+
orderBy: { number: 'desc' },
|
|
77
|
+
select: { number: true },
|
|
78
|
+
});
|
|
79
|
+
const nextNumber = (maxVersion?.number ?? 0) + 1;
|
|
80
|
+
try {
|
|
81
|
+
const version = await prisma.version.create({
|
|
82
|
+
data: {
|
|
83
|
+
promptId,
|
|
84
|
+
number: nextNumber,
|
|
85
|
+
content: data.content,
|
|
86
|
+
template: data.template,
|
|
87
|
+
variables: data.variables ?? {},
|
|
88
|
+
checksum,
|
|
89
|
+
metadata: data.metadata,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
promptVersionsCreated.inc({ project: prompt.projectId });
|
|
93
|
+
return version;
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
// P2002 = Prisma unique constraint violation. Another concurrent create
|
|
97
|
+
// claimed our number — recompute and retry.
|
|
98
|
+
if (err.code === 'P2002') {
|
|
99
|
+
lastError = err;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
throw lastError ?? new Error('Failed to allocate version number');
|
|
106
|
+
}
|
|
107
|
+
async getVersion(projectId, promptId, versionId) {
|
|
108
|
+
const version = await prisma.version.findFirst({
|
|
109
|
+
where: { id: versionId, promptId, prompt: { projectId } },
|
|
110
|
+
});
|
|
111
|
+
if (!version) {
|
|
112
|
+
throw new NotFoundError('Version', versionId);
|
|
113
|
+
}
|
|
114
|
+
return version;
|
|
115
|
+
}
|
|
116
|
+
async getVersionByNumber(projectId, promptId, number) {
|
|
117
|
+
const version = await prisma.version.findFirst({
|
|
118
|
+
where: { promptId, number, prompt: { projectId } },
|
|
119
|
+
});
|
|
120
|
+
if (!version) {
|
|
121
|
+
throw new NotFoundError('Version', String(number));
|
|
122
|
+
}
|
|
123
|
+
return version;
|
|
124
|
+
}
|
|
125
|
+
async listVersions(projectId, promptId, opts) {
|
|
126
|
+
// Confirm caller owns the prompt before paging through its versions.
|
|
127
|
+
const prompt = await prisma.prompt.findFirst({
|
|
128
|
+
where: { id: promptId, projectId },
|
|
129
|
+
select: { id: true },
|
|
130
|
+
});
|
|
131
|
+
if (!prompt) {
|
|
132
|
+
throw new NotFoundError('Prompt', promptId);
|
|
133
|
+
}
|
|
134
|
+
const versions = await prisma.version.findMany({
|
|
135
|
+
where: { promptId },
|
|
136
|
+
take: opts.limit + 1,
|
|
137
|
+
cursor: opts.cursor ? { id: opts.cursor } : undefined,
|
|
138
|
+
orderBy: { number: 'desc' },
|
|
139
|
+
});
|
|
140
|
+
return paginateResult(versions, opts.limit);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
export const promptService = new PromptService();
|
|
144
|
+
//# sourceMappingURL=prompt.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.service.js","sourceRoot":"","sources":["../../src/services/prompt.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Tag } from '@prisma/client';
|
|
2
|
+
import type { TagName } from '@reaatech/prompt-version-control-shared';
|
|
3
|
+
export declare class TagService {
|
|
4
|
+
listTags(projectId: string, promptId: string): Promise<({
|
|
5
|
+
version: {
|
|
6
|
+
number: number;
|
|
7
|
+
id: string;
|
|
8
|
+
createdAt: Date;
|
|
9
|
+
template: string;
|
|
10
|
+
variables: import("@prisma/client/runtime/library").JsonValue;
|
|
11
|
+
metadata: import("@prisma/client/runtime/library").JsonValue | null;
|
|
12
|
+
promptId: string;
|
|
13
|
+
content: string;
|
|
14
|
+
checksum: string;
|
|
15
|
+
};
|
|
16
|
+
} & {
|
|
17
|
+
id: string;
|
|
18
|
+
projectId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
createdAt: Date;
|
|
21
|
+
updatedAt: Date;
|
|
22
|
+
promptId: string;
|
|
23
|
+
versionId: string;
|
|
24
|
+
})[]>;
|
|
25
|
+
getTag(projectId: string, promptId: string, name: TagName): Promise<Tag & {
|
|
26
|
+
version: {
|
|
27
|
+
number: number;
|
|
28
|
+
id: string;
|
|
29
|
+
};
|
|
30
|
+
}>;
|
|
31
|
+
moveTag(projectId: string, promptId: string, name: TagName, versionId: string): Promise<Tag>;
|
|
32
|
+
removeTag(projectId: string, promptId: string, name: TagName): Promise<void>;
|
|
33
|
+
getProductionVersion(projectId: string, promptId: string): Promise<{
|
|
34
|
+
number: number;
|
|
35
|
+
id: string;
|
|
36
|
+
createdAt: Date;
|
|
37
|
+
template: string;
|
|
38
|
+
variables: import("@prisma/client/runtime/library").JsonValue;
|
|
39
|
+
metadata: import("@prisma/client/runtime/library").JsonValue | null;
|
|
40
|
+
promptId: string;
|
|
41
|
+
content: string;
|
|
42
|
+
checksum: string;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
export declare const tagService: TagService;
|
|
46
|
+
//# sourceMappingURL=tag.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.service.d.ts","sourceRoot":"","sources":["../../src/services/tag.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAYvE,qBAAa,UAAU;IACf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;IAS5C,MAAM,CACV,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,GAAG,GAAG;QAAE,OAAO,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,EAAE,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAavD,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,CAAC;IAkCT,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5E,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;CAY/D;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { prisma } from '../db/client.js';
|
|
2
|
+
import { NotFoundError } from '../errors.js';
|
|
3
|
+
async function assertPromptInProject(projectId, promptId) {
|
|
4
|
+
const prompt = await prisma.prompt.findFirst({
|
|
5
|
+
where: { id: promptId, projectId },
|
|
6
|
+
select: { id: true },
|
|
7
|
+
});
|
|
8
|
+
if (!prompt)
|
|
9
|
+
throw new NotFoundError('Prompt', promptId);
|
|
10
|
+
}
|
|
11
|
+
export class TagService {
|
|
12
|
+
async listTags(projectId, promptId) {
|
|
13
|
+
await assertPromptInProject(projectId, promptId);
|
|
14
|
+
return prisma.tag.findMany({
|
|
15
|
+
where: { promptId, projectId },
|
|
16
|
+
include: { version: true },
|
|
17
|
+
orderBy: { name: 'asc' },
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
async getTag(projectId, promptId, name) {
|
|
21
|
+
const tag = await prisma.tag.findFirst({
|
|
22
|
+
where: { promptId, projectId, name },
|
|
23
|
+
include: { version: { select: { id: true, number: true } } },
|
|
24
|
+
});
|
|
25
|
+
if (!tag) {
|
|
26
|
+
throw new NotFoundError('Tag', `${promptId}/${name}`);
|
|
27
|
+
}
|
|
28
|
+
return tag;
|
|
29
|
+
}
|
|
30
|
+
async moveTag(projectId, promptId, name, versionId) {
|
|
31
|
+
await assertPromptInProject(projectId, promptId);
|
|
32
|
+
// Verify the version exists, belongs to this prompt, and is in this project.
|
|
33
|
+
const version = await prisma.version.findFirst({
|
|
34
|
+
where: { id: versionId, promptId, prompt: { projectId } },
|
|
35
|
+
select: { id: true },
|
|
36
|
+
});
|
|
37
|
+
if (!version) {
|
|
38
|
+
throw new NotFoundError('Version', versionId);
|
|
39
|
+
}
|
|
40
|
+
const tag = await prisma.tag.upsert({
|
|
41
|
+
where: {
|
|
42
|
+
promptId_name: {
|
|
43
|
+
promptId,
|
|
44
|
+
name,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
update: {
|
|
48
|
+
versionId,
|
|
49
|
+
projectId,
|
|
50
|
+
},
|
|
51
|
+
create: {
|
|
52
|
+
projectId,
|
|
53
|
+
promptId,
|
|
54
|
+
versionId,
|
|
55
|
+
name,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
return tag;
|
|
59
|
+
}
|
|
60
|
+
async removeTag(projectId, promptId, name) {
|
|
61
|
+
const tag = await prisma.tag.findFirst({
|
|
62
|
+
where: { promptId, projectId, name },
|
|
63
|
+
select: { id: true },
|
|
64
|
+
});
|
|
65
|
+
if (!tag) {
|
|
66
|
+
throw new NotFoundError('Tag', `${promptId}/${name}`);
|
|
67
|
+
}
|
|
68
|
+
await prisma.tag.delete({
|
|
69
|
+
where: { id: tag.id },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async getProductionVersion(projectId, promptId) {
|
|
73
|
+
const tag = await prisma.tag.findFirst({
|
|
74
|
+
where: { promptId, projectId, name: 'production' },
|
|
75
|
+
include: { version: true },
|
|
76
|
+
});
|
|
77
|
+
if (!tag) {
|
|
78
|
+
throw new NotFoundError('Production version', promptId);
|
|
79
|
+
}
|
|
80
|
+
return tag.version;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export const tagService = new TagService();
|
|
84
|
+
//# sourceMappingURL=tag.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.service.js","sourceRoot":"","sources":["../../src/services/tag.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type EventType } from './event.bus.js';
|
|
2
|
+
/**
|
|
3
|
+
* Reject URLs that point at private/loopback/link-local addresses to prevent
|
|
4
|
+
* SSRF. Set WEBHOOK_ALLOW_PRIVATE=1 to disable (only safe in trusted dev envs).
|
|
5
|
+
*/
|
|
6
|
+
declare function assertPublicUrl(rawUrl: string): Promise<URL>;
|
|
7
|
+
declare function isPrivateAddress(addr: string): boolean;
|
|
8
|
+
export declare class WebhookService {
|
|
9
|
+
private retryDelays;
|
|
10
|
+
constructor();
|
|
11
|
+
createSubscription(projectId: string, data: {
|
|
12
|
+
url: string;
|
|
13
|
+
events: EventType[];
|
|
14
|
+
secret: string;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
projectId: string;
|
|
18
|
+
createdAt: Date;
|
|
19
|
+
updatedAt: Date;
|
|
20
|
+
active: boolean;
|
|
21
|
+
url: string;
|
|
22
|
+
events: string[];
|
|
23
|
+
secret: string;
|
|
24
|
+
}>;
|
|
25
|
+
listSubscriptions(projectId: string): Promise<{
|
|
26
|
+
id: string;
|
|
27
|
+
projectId: string;
|
|
28
|
+
createdAt: Date;
|
|
29
|
+
updatedAt: Date;
|
|
30
|
+
active: boolean;
|
|
31
|
+
url: string;
|
|
32
|
+
events: string[];
|
|
33
|
+
secret: string;
|
|
34
|
+
}[]>;
|
|
35
|
+
deleteSubscription(projectId: string, id: string): Promise<import("@prisma/client").Prisma.BatchPayload>;
|
|
36
|
+
testDelivery(projectId: string, id: string): Promise<{
|
|
37
|
+
success: boolean;
|
|
38
|
+
status?: number;
|
|
39
|
+
error?: string;
|
|
40
|
+
}>;
|
|
41
|
+
private deliver;
|
|
42
|
+
private send;
|
|
43
|
+
}
|
|
44
|
+
export declare const webhookService: WebhookService;
|
|
45
|
+
export declare const __test__: {
|
|
46
|
+
assertPublicUrl: typeof assertPublicUrl;
|
|
47
|
+
isPrivateAddress: typeof isPrivateAddress;
|
|
48
|
+
};
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=webhook.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.service.d.ts","sourceRoot":"","sources":["../../src/services/webhook.service.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,KAAK,SAAS,EAAY,MAAM,gBAAgB,CAAC;AAKzE;;;GAGG;AACH,iBAAe,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAiC3D;AAED,iBAAS,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA6B/C;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAkC;;IAW/C,kBAAkB,CACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,SAAS,EAAE,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;KAChB;;;;;;;;;;IAeG,iBAAiB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;IAMnC,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAMhD,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;YAiBnD,OAAO;YAwBP,IAAI;CAqCnB;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAC;AAEnD,eAAO,MAAM,QAAQ;;;CAAwC,CAAC"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { createHmac } from 'node:crypto';
|
|
2
|
+
import { lookup } from 'node:dns/promises';
|
|
3
|
+
import { isIP } from 'node:net';
|
|
4
|
+
import { sleep } from '@reaatech/prompt-version-control-shared';
|
|
5
|
+
import { prisma } from '../db/client.js';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
import { eventBus } from './event.bus.js';
|
|
8
|
+
const WEBHOOK_TIMEOUT_MS = 10_000;
|
|
9
|
+
const ALLOW_PRIVATE = process.env.WEBHOOK_ALLOW_PRIVATE === '1';
|
|
10
|
+
/**
|
|
11
|
+
* Reject URLs that point at private/loopback/link-local addresses to prevent
|
|
12
|
+
* SSRF. Set WEBHOOK_ALLOW_PRIVATE=1 to disable (only safe in trusted dev envs).
|
|
13
|
+
*/
|
|
14
|
+
async function assertPublicUrl(rawUrl) {
|
|
15
|
+
let url;
|
|
16
|
+
try {
|
|
17
|
+
url = new URL(rawUrl);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new Error(`invalid webhook url: ${rawUrl}`);
|
|
21
|
+
}
|
|
22
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
23
|
+
throw new Error(`webhook url must be http(s): ${url.protocol}`);
|
|
24
|
+
}
|
|
25
|
+
if (ALLOW_PRIVATE)
|
|
26
|
+
return url;
|
|
27
|
+
const host = url.hostname.replace(/^\[|\]$/g, '');
|
|
28
|
+
const candidates = [];
|
|
29
|
+
if (isIP(host)) {
|
|
30
|
+
candidates.push(host);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
try {
|
|
34
|
+
const records = await lookup(host, { all: true });
|
|
35
|
+
for (const r of records)
|
|
36
|
+
candidates.push(r.address);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw new Error(`could not resolve webhook host: ${host}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for (const addr of candidates) {
|
|
43
|
+
if (isPrivateAddress(addr)) {
|
|
44
|
+
throw new Error(`webhook url resolves to disallowed address: ${addr}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return url;
|
|
48
|
+
}
|
|
49
|
+
function isPrivateAddress(addr) {
|
|
50
|
+
if (isIP(addr) === 4) {
|
|
51
|
+
const parts = addr.split('.').map(Number);
|
|
52
|
+
const [a, b] = parts;
|
|
53
|
+
if (a === undefined || b === undefined)
|
|
54
|
+
return true;
|
|
55
|
+
if (a === 10)
|
|
56
|
+
return true;
|
|
57
|
+
if (a === 127)
|
|
58
|
+
return true;
|
|
59
|
+
if (a === 0)
|
|
60
|
+
return true;
|
|
61
|
+
if (a === 169 && b === 254)
|
|
62
|
+
return true; // link-local & metadata
|
|
63
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
64
|
+
return true;
|
|
65
|
+
if (a === 192 && b === 168)
|
|
66
|
+
return true;
|
|
67
|
+
if (a >= 224)
|
|
68
|
+
return true; // multicast/reserved
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (isIP(addr) === 6) {
|
|
72
|
+
const lower = addr.toLowerCase();
|
|
73
|
+
if (lower === '::1')
|
|
74
|
+
return true;
|
|
75
|
+
if (lower === '::')
|
|
76
|
+
return true;
|
|
77
|
+
if (lower.startsWith('fc') || lower.startsWith('fd'))
|
|
78
|
+
return true; // ULA
|
|
79
|
+
if (lower.startsWith('fe80'))
|
|
80
|
+
return true; // link-local
|
|
81
|
+
if (lower.startsWith('ff'))
|
|
82
|
+
return true; // multicast
|
|
83
|
+
if (lower.startsWith('::ffff:')) {
|
|
84
|
+
// IPv4-mapped — recurse on the v4 part
|
|
85
|
+
const v4 = lower.slice('::ffff:'.length);
|
|
86
|
+
return isPrivateAddress(v4);
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
export class WebhookService {
|
|
93
|
+
retryDelays = [1_000, 5_000, 15_000, 60_000]; // ms
|
|
94
|
+
constructor() {
|
|
95
|
+
eventBus.on('version.created', (e) => this.deliver(e));
|
|
96
|
+
eventBus.on('tag.moved', (e) => this.deliver(e));
|
|
97
|
+
eventBus.on('eval.completed', (e) => this.deliver(e));
|
|
98
|
+
eventBus.on('promotion.requested', (e) => this.deliver(e));
|
|
99
|
+
eventBus.on('promotion.approved', (e) => this.deliver(e));
|
|
100
|
+
eventBus.on('promotion.rejected', (e) => this.deliver(e));
|
|
101
|
+
}
|
|
102
|
+
async createSubscription(projectId, data) {
|
|
103
|
+
// Validate destination at creation time so users get immediate feedback.
|
|
104
|
+
await assertPublicUrl(data.url);
|
|
105
|
+
return prisma.webhookSubscription.create({
|
|
106
|
+
data: {
|
|
107
|
+
projectId,
|
|
108
|
+
url: data.url,
|
|
109
|
+
events: data.events,
|
|
110
|
+
secret: data.secret,
|
|
111
|
+
active: true,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async listSubscriptions(projectId) {
|
|
116
|
+
return prisma.webhookSubscription.findMany({
|
|
117
|
+
where: { projectId },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async deleteSubscription(projectId, id) {
|
|
121
|
+
return prisma.webhookSubscription.deleteMany({
|
|
122
|
+
where: { id, projectId },
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async testDelivery(projectId, id) {
|
|
126
|
+
const sub = await prisma.webhookSubscription.findFirst({
|
|
127
|
+
where: { id, projectId },
|
|
128
|
+
});
|
|
129
|
+
if (!sub)
|
|
130
|
+
return { success: false, error: 'Subscription not found' };
|
|
131
|
+
const event = {
|
|
132
|
+
id: `test_${Date.now()}`,
|
|
133
|
+
type: 'version.created',
|
|
134
|
+
projectId,
|
|
135
|
+
payload: { test: true },
|
|
136
|
+
createdAt: new Date(),
|
|
137
|
+
};
|
|
138
|
+
return this.send(sub.url, sub.secret, event);
|
|
139
|
+
}
|
|
140
|
+
async deliver(event) {
|
|
141
|
+
const subs = await prisma.webhookSubscription.findMany({
|
|
142
|
+
where: {
|
|
143
|
+
projectId: event.projectId,
|
|
144
|
+
active: true,
|
|
145
|
+
events: { has: event.type },
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
// Deliver in parallel; per-subscription retries shouldn't block other subs.
|
|
149
|
+
await Promise.all(subs.map(async (sub) => {
|
|
150
|
+
for (let attempt = 0; attempt <= this.retryDelays.length; attempt++) {
|
|
151
|
+
const result = await this.send(sub.url, sub.secret, event);
|
|
152
|
+
if (result.success)
|
|
153
|
+
return;
|
|
154
|
+
if (attempt < this.retryDelays.length) {
|
|
155
|
+
// biome-ignore lint/style/noNonNullAssertion: safe — guarded by length check
|
|
156
|
+
await sleep(this.retryDelays[attempt]);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
async send(url, secret, event) {
|
|
162
|
+
try {
|
|
163
|
+
await assertPublicUrl(url);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
logger.warn({ err: err.message, url }, 'webhook destination rejected');
|
|
167
|
+
return { success: false, error: err.message };
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const payload = JSON.stringify(event);
|
|
171
|
+
const signature = createHmac('sha256', secret).update(payload).digest('hex');
|
|
172
|
+
const res = await fetch(url, {
|
|
173
|
+
method: 'POST',
|
|
174
|
+
headers: {
|
|
175
|
+
'Content-Type': 'application/json',
|
|
176
|
+
'X-Webhook-Signature': `sha256=${signature}`,
|
|
177
|
+
'X-Event-Id': event.id,
|
|
178
|
+
'X-Event-Type': event.type,
|
|
179
|
+
},
|
|
180
|
+
body: payload,
|
|
181
|
+
signal: AbortSignal.timeout(WEBHOOK_TIMEOUT_MS),
|
|
182
|
+
});
|
|
183
|
+
if (res.ok) {
|
|
184
|
+
return { success: true, status: res.status };
|
|
185
|
+
}
|
|
186
|
+
return { success: false, status: res.status };
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
logger.warn({ err, url, eventId: event.id }, 'webhook delivery failed');
|
|
190
|
+
return { success: false, error: err.message };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
export const webhookService = new WebhookService();
|
|
195
|
+
export const __test__ = { assertPublicUrl, isPrivateAddress };
|
|
196
|
+
//# sourceMappingURL=webhook.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.service.js","sourceRoot":"","sources":["../../src/services/webhook.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../../src/types/hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,kBAAkB;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;KAClB;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hono.js","sourceRoot":"","sources":["../../src/types/hono.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAM/C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AppError } from '../errors.js';
|
|
2
|
+
export function getProjectId(c) {
|
|
3
|
+
const projectId = c.get('projectId');
|
|
4
|
+
if (!projectId) {
|
|
5
|
+
throw new AppError('INTERNAL', 500, 'Auth context missing: projectId not set');
|
|
6
|
+
}
|
|
7
|
+
return projectId;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,UAAU,YAAY,CAAC,CAAU;IACrC,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACrC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,yCAAyC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,SAAmB,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,eAAO,MAAM,MAAM,6BAkBjB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
export const logger = pino({
|
|
3
|
+
level: process.env.LOG_LEVEL || 'info',
|
|
4
|
+
formatters: {
|
|
5
|
+
level: (label) => ({ level: label }),
|
|
6
|
+
},
|
|
7
|
+
redact: {
|
|
8
|
+
paths: ['*.apiKey', '*.password', '*.secret', '*.keyHash', '*.token'],
|
|
9
|
+
censor: '[REDACTED]',
|
|
10
|
+
},
|
|
11
|
+
transport: process.env.NODE_ENV === 'development'
|
|
12
|
+
? {
|
|
13
|
+
target: 'pino-pretty',
|
|
14
|
+
options: {
|
|
15
|
+
colorize: true,
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
: undefined,
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;IACtC,UAAU,EAAE;QACV,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;KACrC;IACD,MAAM,EAAE;QACN,KAAK,EAAE,CAAC,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,CAAC;QACrE,MAAM,EAAE,YAAY;KACrB;IACD,SAAS,EACP,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QACpC,CAAC,CAAC;YACE,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,QAAQ,EAAE,IAAI;aACf;SACF;QACH,CAAC,CAAC,SAAS;CAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACrD,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAQ7D"}
|