@vercel/factory 0.0.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/chunk-BSDWPFKE.js +197 -0
- package/dist/chunk-BSDWPFKE.js.map +1 -0
- package/dist/chunk-CEF6VJZC.js +28 -0
- package/dist/chunk-CEF6VJZC.js.map +1 -0
- package/dist/common-CaHaEOAS.d.ts +18 -0
- package/dist/connectors/github.d.ts +37 -0
- package/dist/connectors/github.js +50 -0
- package/dist/connectors/github.js.map +1 -0
- package/dist/driver-tRNggCCJ.d.ts +32 -0
- package/dist/engine-BXVTLiXU.d.ts +350 -0
- package/dist/eve/index.d.ts +507 -0
- package/dist/eve/index.js +128 -0
- package/dist/eve/index.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +743 -0
- package/dist/index.js.map +1 -0
- package/dist/postgres/index.d.ts +137 -0
- package/dist/postgres/index.js +118 -0
- package/dist/postgres/index.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// src/schema/common.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var SCHEMA_VERSION = 1;
|
|
4
|
+
var schemaVersionSchema = z.literal(SCHEMA_VERSION).describe("Version of the entity schema this row was written with.");
|
|
5
|
+
var isoDateTimeSchema = z.iso.datetime().describe("UTC timestamp in ISO 8601 format, e.g. 2026-08-26T12:00:00Z.");
|
|
6
|
+
var usdSchema = z.number().finite().nonnegative().describe("Amount in US dollars.");
|
|
7
|
+
var vocabularySchema = z.string().regex(/^[a-z][a-z0-9_]{0,63}$/, "must be lowercase snake_case starting with a letter").describe("Lowercase snake_case name, e.g. github_issue or sentry_alert.");
|
|
8
|
+
var replyToSchema = z.strictObject({
|
|
9
|
+
channel: z.string().min(1).describe("Connector that should carry replies, e.g. github or slack."),
|
|
10
|
+
address: z.string().min(1).describe("Connector-specific reply address, e.g. acme/web#41 or a Slack thread id.")
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// src/schema/id.ts
|
|
14
|
+
import { z as z2 } from "zod";
|
|
15
|
+
function idSchema(prefix) {
|
|
16
|
+
return z2.string().regex(new RegExp(`^${prefix}_[a-z0-9]{6,64}$`));
|
|
17
|
+
}
|
|
18
|
+
var factoryIdSchema = idSchema("fac");
|
|
19
|
+
var repositoryIdSchema = idSchema("repo");
|
|
20
|
+
var signalIdSchema = idSchema("sig");
|
|
21
|
+
var taskIdSchema = idSchema("task");
|
|
22
|
+
var changeIdSchema = idSchema("chg");
|
|
23
|
+
var receiptIdSchema = idSchema("rcpt");
|
|
24
|
+
var repositoryIdsSchema = z2.array(repositoryIdSchema).min(1);
|
|
25
|
+
|
|
26
|
+
// src/schema/change.ts
|
|
27
|
+
import { z as z3 } from "zod";
|
|
28
|
+
var levelSchema = z3.enum(["low", "medium", "high"]);
|
|
29
|
+
var changeStateSchema = z3.enum([
|
|
30
|
+
"verifying",
|
|
31
|
+
"ready",
|
|
32
|
+
"merged",
|
|
33
|
+
"deployed",
|
|
34
|
+
"rolled_out",
|
|
35
|
+
"rolled_back",
|
|
36
|
+
"closed"
|
|
37
|
+
]);
|
|
38
|
+
var postMergeStates = ["merged", "deployed", "rolled_out", "rolled_back"];
|
|
39
|
+
var changeEvidenceSchema = z3.strictObject({
|
|
40
|
+
reproVerified: z3.boolean(),
|
|
41
|
+
testsAdded: z3.number().int().min(0),
|
|
42
|
+
checksGreen: z3.boolean(),
|
|
43
|
+
attackPassed: z3.boolean(),
|
|
44
|
+
scopeMatches: z3.boolean(),
|
|
45
|
+
previewUrl: z3.url().optional()
|
|
46
|
+
});
|
|
47
|
+
var changeSchema = z3.strictObject({
|
|
48
|
+
schemaVersion: schemaVersionSchema,
|
|
49
|
+
id: changeIdSchema,
|
|
50
|
+
repositoryId: repositoryIdSchema,
|
|
51
|
+
taskId: taskIdSchema.optional(),
|
|
52
|
+
groupId: taskIdSchema.optional(),
|
|
53
|
+
prNumber: z3.number().int().min(1),
|
|
54
|
+
prUrl: z3.url(),
|
|
55
|
+
author: z3.string().min(1),
|
|
56
|
+
risk: levelSchema,
|
|
57
|
+
confidence: levelSchema,
|
|
58
|
+
evidence: changeEvidenceSchema,
|
|
59
|
+
state: changeStateSchema,
|
|
60
|
+
decidedBy: z3.string().min(1).optional(),
|
|
61
|
+
createdAt: isoDateTimeSchema,
|
|
62
|
+
updatedAt: isoDateTimeSchema
|
|
63
|
+
}).superRefine((change, ctx) => {
|
|
64
|
+
if (postMergeStates.includes(change.state) && change.decidedBy === void 0) {
|
|
65
|
+
ctx.addIssue({
|
|
66
|
+
code: "custom",
|
|
67
|
+
path: ["decidedBy"],
|
|
68
|
+
message: `${change.state} changes require decidedBy`
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// src/schema/task.ts
|
|
74
|
+
import { z as z4 } from "zod";
|
|
75
|
+
var standardTaskKinds = [
|
|
76
|
+
"code_change",
|
|
77
|
+
"verification",
|
|
78
|
+
"investigation",
|
|
79
|
+
"question"
|
|
80
|
+
];
|
|
81
|
+
var taskKindSchema = vocabularySchema.describe(
|
|
82
|
+
"What kind of work this is, e.g. code_change, question, or a registered custom kind."
|
|
83
|
+
);
|
|
84
|
+
var taskStateSchema = z4.enum(["queued", "running", "verifying", "succeeded", "failed", "needs_human", "cancelled"]).describe("Lifecycle state. Transitions are fixed; see taskTransitions.");
|
|
85
|
+
var harnessSchema = z4.string().min(1).describe("Coding harness used in the devbox, e.g. claude-code or codex.");
|
|
86
|
+
var taskOriginSchema = z4.strictObject({
|
|
87
|
+
signalId: signalIdSchema.optional().describe("Signal that led to this task."),
|
|
88
|
+
parentTaskId: taskIdSchema.optional().describe("Parent task that planned this child."),
|
|
89
|
+
operator: z4.string().min(1).optional().describe("Human operator who requested it.")
|
|
90
|
+
}).refine(
|
|
91
|
+
(origin) => origin.signalId !== void 0 || origin.parentTaskId !== void 0 || origin.operator !== void 0,
|
|
92
|
+
{ message: "origin requires a signalId, parentTaskId, or operator" }
|
|
93
|
+
);
|
|
94
|
+
var taskDevboxSchema = z4.strictObject({
|
|
95
|
+
devboxId: z4.string().min(1).describe("Devbox running or having run this task."),
|
|
96
|
+
remoteId: z4.string().min(1).describe("Provider-side id of the execution."),
|
|
97
|
+
harness: harnessSchema
|
|
98
|
+
});
|
|
99
|
+
var taskQuestionSchema = z4.strictObject({
|
|
100
|
+
text: z4.string().min(1).describe("The question a human must answer."),
|
|
101
|
+
options: z4.array(z4.string().min(1)).describe("Suggested answers; free-text is also allowed."),
|
|
102
|
+
answer: z4.string().min(1).optional(),
|
|
103
|
+
answeredBy: z4.string().min(1).optional().describe("Authenticated operator who answered.")
|
|
104
|
+
});
|
|
105
|
+
var taskSchema = z4.strictObject({
|
|
106
|
+
schemaVersion: schemaVersionSchema,
|
|
107
|
+
id: taskIdSchema,
|
|
108
|
+
repositoryIds: repositoryIdsSchema.optional().describe("Repositories the task works on; absent only on a multi-repo parent."),
|
|
109
|
+
kind: taskKindSchema,
|
|
110
|
+
area: z4.string().min(1).optional().describe("Investigation area, e.g. onboarding or security. Investigation tasks only."),
|
|
111
|
+
state: taskStateSchema,
|
|
112
|
+
origin: taskOriginSchema,
|
|
113
|
+
dependsOn: z4.array(taskIdSchema).min(1).optional().describe("Sibling tasks that must produce a change before this one may run."),
|
|
114
|
+
replyTo: replyToSchema,
|
|
115
|
+
devbox: taskDevboxSchema.optional(),
|
|
116
|
+
attempt: z4.number().int().min(1).describe("Execution attempt, starting at 1; bumps on retry."),
|
|
117
|
+
reservedUsd: usdSchema.optional().describe("Budget reserved before dispatch."),
|
|
118
|
+
settledUsd: usdSchema.optional().describe("Measured cost settled after execution."),
|
|
119
|
+
question: taskQuestionSchema.optional(),
|
|
120
|
+
changeId: changeIdSchema.optional().describe("Change this code_change task produced."),
|
|
121
|
+
reportRef: z4.string().min(1).optional().describe("Reference to the report artifact an investigation produced."),
|
|
122
|
+
createdAt: isoDateTimeSchema,
|
|
123
|
+
updatedAt: isoDateTimeSchema
|
|
124
|
+
}).superRefine((task, ctx) => {
|
|
125
|
+
if (task.area !== void 0 && task.kind !== "investigation") {
|
|
126
|
+
ctx.addIssue({
|
|
127
|
+
code: "custom",
|
|
128
|
+
path: ["area"],
|
|
129
|
+
message: "area is only valid on investigation tasks"
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (task.kind === "question") {
|
|
133
|
+
if (task.question === void 0) {
|
|
134
|
+
ctx.addIssue({
|
|
135
|
+
code: "custom",
|
|
136
|
+
path: ["question"],
|
|
137
|
+
message: "question tasks require a question"
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (task.devbox !== void 0) {
|
|
141
|
+
ctx.addIssue({
|
|
142
|
+
code: "custom",
|
|
143
|
+
path: ["devbox"],
|
|
144
|
+
message: "question tasks never run in a devbox"
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
} else if (task.question !== void 0) {
|
|
148
|
+
ctx.addIssue({
|
|
149
|
+
code: "custom",
|
|
150
|
+
path: ["question"],
|
|
151
|
+
message: "question is only valid on question tasks"
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (task.changeId !== void 0 && task.kind !== "code_change") {
|
|
155
|
+
ctx.addIssue({
|
|
156
|
+
code: "custom",
|
|
157
|
+
path: ["changeId"],
|
|
158
|
+
message: "changeId is only valid on code_change tasks"
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (task.reportRef !== void 0 && task.kind !== "investigation") {
|
|
162
|
+
ctx.addIssue({
|
|
163
|
+
code: "custom",
|
|
164
|
+
path: ["reportRef"],
|
|
165
|
+
message: "reportRef is only valid on investigation tasks"
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
export {
|
|
171
|
+
SCHEMA_VERSION,
|
|
172
|
+
schemaVersionSchema,
|
|
173
|
+
isoDateTimeSchema,
|
|
174
|
+
usdSchema,
|
|
175
|
+
vocabularySchema,
|
|
176
|
+
replyToSchema,
|
|
177
|
+
factoryIdSchema,
|
|
178
|
+
repositoryIdSchema,
|
|
179
|
+
signalIdSchema,
|
|
180
|
+
taskIdSchema,
|
|
181
|
+
changeIdSchema,
|
|
182
|
+
receiptIdSchema,
|
|
183
|
+
repositoryIdsSchema,
|
|
184
|
+
levelSchema,
|
|
185
|
+
changeStateSchema,
|
|
186
|
+
changeEvidenceSchema,
|
|
187
|
+
changeSchema,
|
|
188
|
+
standardTaskKinds,
|
|
189
|
+
taskKindSchema,
|
|
190
|
+
taskStateSchema,
|
|
191
|
+
harnessSchema,
|
|
192
|
+
taskOriginSchema,
|
|
193
|
+
taskDevboxSchema,
|
|
194
|
+
taskQuestionSchema,
|
|
195
|
+
taskSchema
|
|
196
|
+
};
|
|
197
|
+
//# sourceMappingURL=chunk-BSDWPFKE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema/common.ts","../src/schema/id.ts","../src/schema/change.ts","../src/schema/task.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const SCHEMA_VERSION = 1;\n\nexport const schemaVersionSchema = z\n .literal(SCHEMA_VERSION)\n .describe(\"Version of the entity schema this row was written with.\");\n\nexport const isoDateTimeSchema = z.iso\n .datetime()\n .describe(\"UTC timestamp in ISO 8601 format, e.g. 2026-08-26T12:00:00Z.\");\n\nexport const usdSchema = z.number().finite().nonnegative().describe(\"Amount in US dollars.\");\n\n/**\n * Open vocabulary value. Standard values ship as exported constants; custom\n * values matching the pattern are equally valid.\n */\nexport const vocabularySchema = z\n .string()\n .regex(/^[a-z][a-z0-9_]{0,63}$/, \"must be lowercase snake_case starting with a letter\")\n .describe(\"Lowercase snake_case name, e.g. github_issue or sentry_alert.\");\n\nexport const replyToSchema = z.strictObject({\n channel: z\n .string()\n .min(1)\n .describe(\"Connector that should carry replies, e.g. github or slack.\"),\n address: z\n .string()\n .min(1)\n .describe(\"Connector-specific reply address, e.g. acme/web#41 or a Slack thread id.\"),\n});\n\nexport type ReplyTo = z.infer<typeof replyToSchema>;\n","import { z } from \"zod\";\n\nfunction idSchema(prefix: string) {\n return z.string().regex(new RegExp(`^${prefix}_[a-z0-9]{6,64}$`));\n}\n\nexport const factoryIdSchema = idSchema(\"fac\");\nexport const repositoryIdSchema = idSchema(\"repo\");\nexport const signalIdSchema = idSchema(\"sig\");\nexport const taskIdSchema = idSchema(\"task\");\nexport const changeIdSchema = idSchema(\"chg\");\nexport const receiptIdSchema = idSchema(\"rcpt\");\n\nexport const repositoryIdsSchema = z.array(repositoryIdSchema).min(1);\n\nexport type FactoryId = z.infer<typeof factoryIdSchema>;\nexport type RepositoryId = z.infer<typeof repositoryIdSchema>;\nexport type SignalId = z.infer<typeof signalIdSchema>;\nexport type TaskId = z.infer<typeof taskIdSchema>;\nexport type ChangeId = z.infer<typeof changeIdSchema>;\nexport type ReceiptId = z.infer<typeof receiptIdSchema>;\n","import { z } from \"zod\";\nimport { isoDateTimeSchema, schemaVersionSchema } from \"./common\";\nimport { changeIdSchema, repositoryIdSchema, taskIdSchema } from \"./id\";\n\nexport const levelSchema = z.enum([\"low\", \"medium\", \"high\"]);\n\nexport const changeStateSchema = z.enum([\n \"verifying\",\n \"ready\",\n \"merged\",\n \"deployed\",\n \"rolled_out\",\n \"rolled_back\",\n \"closed\",\n]);\n\nconst postMergeStates: readonly string[] = [\"merged\", \"deployed\", \"rolled_out\", \"rolled_back\"];\n\nexport const changeEvidenceSchema = z.strictObject({\n reproVerified: z.boolean(),\n testsAdded: z.number().int().min(0),\n checksGreen: z.boolean(),\n attackPassed: z.boolean(),\n scopeMatches: z.boolean(),\n previewUrl: z.url().optional(),\n});\n\nexport const changeSchema = z\n .strictObject({\n schemaVersion: schemaVersionSchema,\n id: changeIdSchema,\n repositoryId: repositoryIdSchema,\n taskId: taskIdSchema.optional(),\n groupId: taskIdSchema.optional(),\n prNumber: z.number().int().min(1),\n prUrl: z.url(),\n author: z.string().min(1),\n risk: levelSchema,\n confidence: levelSchema,\n evidence: changeEvidenceSchema,\n state: changeStateSchema,\n decidedBy: z.string().min(1).optional(),\n createdAt: isoDateTimeSchema,\n updatedAt: isoDateTimeSchema,\n })\n .superRefine((change, ctx) => {\n if (postMergeStates.includes(change.state) && change.decidedBy === undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"decidedBy\"],\n message: `${change.state} changes require decidedBy`,\n });\n }\n });\n\nexport type Level = z.infer<typeof levelSchema>;\nexport type ChangeState = z.infer<typeof changeStateSchema>;\nexport type ChangeEvidence = z.infer<typeof changeEvidenceSchema>;\nexport type Change = z.infer<typeof changeSchema>;\n","import { z } from \"zod\";\nimport {\n isoDateTimeSchema,\n replyToSchema,\n schemaVersionSchema,\n usdSchema,\n vocabularySchema,\n} from \"./common\";\nimport { changeIdSchema, repositoryIdsSchema, signalIdSchema, taskIdSchema } from \"./id\";\n\n/**\n * Kinds the standard loop understands. Any vocabulary value is valid; the\n * kind-scoped rules below apply only to these standard kinds.\n */\nexport const standardTaskKinds = [\n \"code_change\",\n \"verification\",\n \"investigation\",\n \"question\",\n] as const;\n\nexport const taskKindSchema = vocabularySchema.describe(\n \"What kind of work this is, e.g. code_change, question, or a registered custom kind.\",\n);\n\nexport const taskStateSchema = z\n .enum([\"queued\", \"running\", \"verifying\", \"succeeded\", \"failed\", \"needs_human\", \"cancelled\"])\n .describe(\"Lifecycle state. Transitions are fixed; see taskTransitions.\");\n\nexport const harnessSchema = z\n .string()\n .min(1)\n .describe(\"Coding harness used in the devbox, e.g. claude-code or codex.\");\n\nexport const taskOriginSchema = z\n .strictObject({\n signalId: signalIdSchema.optional().describe(\"Signal that led to this task.\"),\n parentTaskId: taskIdSchema.optional().describe(\"Parent task that planned this child.\"),\n operator: z.string().min(1).optional().describe(\"Human operator who requested it.\"),\n })\n .refine(\n (origin) =>\n origin.signalId !== undefined ||\n origin.parentTaskId !== undefined ||\n origin.operator !== undefined,\n { message: \"origin requires a signalId, parentTaskId, or operator\" },\n );\n\nexport const taskDevboxSchema = z.strictObject({\n devboxId: z.string().min(1).describe(\"Devbox running or having run this task.\"),\n remoteId: z.string().min(1).describe(\"Provider-side id of the execution.\"),\n harness: harnessSchema,\n});\n\nexport const taskQuestionSchema = z.strictObject({\n text: z.string().min(1).describe(\"The question a human must answer.\"),\n options: z.array(z.string().min(1)).describe(\"Suggested answers; free-text is also allowed.\"),\n answer: z.string().min(1).optional(),\n answeredBy: z.string().min(1).optional().describe(\"Authenticated operator who answered.\"),\n});\n\nexport const taskSchema = z\n .strictObject({\n schemaVersion: schemaVersionSchema,\n id: taskIdSchema,\n repositoryIds: repositoryIdsSchema\n .optional()\n .describe(\"Repositories the task works on; absent only on a multi-repo parent.\"),\n kind: taskKindSchema,\n area: z\n .string()\n .min(1)\n .optional()\n .describe(\"Investigation area, e.g. onboarding or security. Investigation tasks only.\"),\n state: taskStateSchema,\n origin: taskOriginSchema,\n dependsOn: z\n .array(taskIdSchema)\n .min(1)\n .optional()\n .describe(\"Sibling tasks that must produce a change before this one may run.\"),\n replyTo: replyToSchema,\n devbox: taskDevboxSchema.optional(),\n attempt: z\n .number()\n .int()\n .min(1)\n .describe(\"Execution attempt, starting at 1; bumps on retry.\"),\n reservedUsd: usdSchema.optional().describe(\"Budget reserved before dispatch.\"),\n settledUsd: usdSchema.optional().describe(\"Measured cost settled after execution.\"),\n question: taskQuestionSchema.optional(),\n changeId: changeIdSchema.optional().describe(\"Change this code_change task produced.\"),\n reportRef: z\n .string()\n .min(1)\n .optional()\n .describe(\"Reference to the report artifact an investigation produced.\"),\n createdAt: isoDateTimeSchema,\n updatedAt: isoDateTimeSchema,\n })\n .superRefine((task, ctx) => {\n if (task.area !== undefined && task.kind !== \"investigation\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"area\"],\n message: \"area is only valid on investigation tasks\",\n });\n }\n if (task.kind === \"question\") {\n if (task.question === undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"question\"],\n message: \"question tasks require a question\",\n });\n }\n if (task.devbox !== undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"devbox\"],\n message: \"question tasks never run in a devbox\",\n });\n }\n } else if (task.question !== undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"question\"],\n message: \"question is only valid on question tasks\",\n });\n }\n if (task.changeId !== undefined && task.kind !== \"code_change\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"changeId\"],\n message: \"changeId is only valid on code_change tasks\",\n });\n }\n if (task.reportRef !== undefined && task.kind !== \"investigation\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"reportRef\"],\n message: \"reportRef is only valid on investigation tasks\",\n });\n }\n });\n\nexport type TaskKind = z.infer<typeof taskKindSchema>;\nexport type TaskState = z.infer<typeof taskStateSchema>;\nexport type Task = z.infer<typeof taskSchema>;\n"],"mappings":"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","names":["z","z","z","z","z"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/store/driver.ts
|
|
2
|
+
var RecordExistsError = class extends Error {
|
|
3
|
+
constructor(collection, id) {
|
|
4
|
+
super(`record "${id}" already exists in "${collection}"`);
|
|
5
|
+
this.name = "RecordExistsError";
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var RecordNotFoundError = class extends Error {
|
|
9
|
+
constructor(collection, id) {
|
|
10
|
+
super(`record "${id}" not found in "${collection}"`);
|
|
11
|
+
this.name = "RecordNotFoundError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var VersionConflictError = class extends Error {
|
|
15
|
+
constructor(collection, id, expectedVersion) {
|
|
16
|
+
super(
|
|
17
|
+
`record "${id}" in "${collection}" changed since version ${expectedVersion} was read`
|
|
18
|
+
);
|
|
19
|
+
this.name = "VersionConflictError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
RecordExistsError,
|
|
25
|
+
RecordNotFoundError,
|
|
26
|
+
VersionConflictError
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=chunk-CEF6VJZC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/store/driver.ts"],"sourcesContent":["export type CollectionName = \"repositories\" | \"signals\" | \"tasks\" | \"changes\" | \"receipts\";\n\nexport interface StoredRecord {\n readonly value: unknown;\n readonly version: number;\n}\n\nexport interface StoredEntry {\n readonly id: string;\n readonly record: StoredRecord;\n}\n\nexport class RecordExistsError extends Error {\n constructor(collection: CollectionName, id: string) {\n super(`record \"${id}\" already exists in \"${collection}\"`);\n this.name = \"RecordExistsError\";\n }\n}\n\nexport class RecordNotFoundError extends Error {\n constructor(collection: CollectionName, id: string) {\n super(`record \"${id}\" not found in \"${collection}\"`);\n this.name = \"RecordNotFoundError\";\n }\n}\n\nexport class VersionConflictError extends Error {\n constructor(collection: CollectionName, id: string, expectedVersion: number) {\n super(\n `record \"${id}\" in \"${collection}\" changed since version ${expectedVersion} was read`,\n );\n this.name = \"VersionConflictError\";\n }\n}\n\n/**\n * Raw persistence contract. Drivers store opaque values and enforce nothing\n * about their content; every invariant lives in the engine above. `update`\n * must be an atomic compare-and-swap on `expectedVersion`.\n */\nexport interface StoreDriver {\n readonly name: string;\n get(collection: CollectionName, id: string): Promise<StoredRecord | null>;\n insert(collection: CollectionName, id: string, value: unknown): Promise<void>;\n update(\n collection: CollectionName,\n id: string,\n value: unknown,\n expectedVersion: number,\n ): Promise<void>;\n list(collection: CollectionName): Promise<readonly StoredEntry[]>;\n}\n"],"mappings":";AAYO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YAAY,YAA4B,IAAY;AAClD,UAAM,WAAW,EAAE,wBAAwB,UAAU,GAAG;AACxD,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YAAY,YAA4B,IAAY;AAClD,UAAM,WAAW,EAAE,mBAAmB,UAAU,GAAG;AACnD,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,YAA4B,IAAY,iBAAyB;AAC3E;AAAA,MACE,WAAW,EAAE,SAAS,UAAU,2BAA2B,eAAe;AAAA,IAC5E;AACA,SAAK,OAAO;AAAA,EACd;AACF;","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const SCHEMA_VERSION = 1;
|
|
4
|
+
declare const schemaVersionSchema: z.ZodLiteral<1>;
|
|
5
|
+
declare const isoDateTimeSchema: z.ZodISODateTime;
|
|
6
|
+
declare const usdSchema: z.ZodNumber;
|
|
7
|
+
/**
|
|
8
|
+
* Open vocabulary value. Standard values ship as exported constants; custom
|
|
9
|
+
* values matching the pattern are equally valid.
|
|
10
|
+
*/
|
|
11
|
+
declare const vocabularySchema: z.ZodString;
|
|
12
|
+
declare const replyToSchema: z.ZodObject<{
|
|
13
|
+
channel: z.ZodString;
|
|
14
|
+
address: z.ZodString;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
type ReplyTo = z.infer<typeof replyToSchema>;
|
|
17
|
+
|
|
18
|
+
export { type ReplyTo as R, SCHEMA_VERSION as S, isoDateTimeSchema as i, replyToSchema as r, schemaVersionSchema as s, usdSchema as u, vocabularySchema as v };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { R as ReplyTo } from '../common-CaHaEOAS.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Verify a GitHub webhook HMAC signature (the x-hub-signature-256 header)
|
|
6
|
+
* against the raw request body. Returns false for missing or malformed
|
|
7
|
+
* signatures instead of throwing.
|
|
8
|
+
*/
|
|
9
|
+
declare function verifyGitHubSignature(options: {
|
|
10
|
+
secret: string;
|
|
11
|
+
payload: string;
|
|
12
|
+
signature: string | null;
|
|
13
|
+
}): boolean;
|
|
14
|
+
interface GitHubIssueSignal {
|
|
15
|
+
source: "github_issue";
|
|
16
|
+
deliveryId: string;
|
|
17
|
+
repositorySlug: string;
|
|
18
|
+
replyTo: ReplyTo;
|
|
19
|
+
issue: {
|
|
20
|
+
number: number;
|
|
21
|
+
title: string;
|
|
22
|
+
body: string | null;
|
|
23
|
+
};
|
|
24
|
+
payload: unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Normalize a GitHub issues webhook into the factory's signal shape. Returns
|
|
28
|
+
* null for payloads that are not an opened issue. The caller supplies the
|
|
29
|
+
* repository id; the payload stays untrusted data.
|
|
30
|
+
*/
|
|
31
|
+
declare function normalizeGitHubIssueOpened(options: {
|
|
32
|
+
deliveryId: string;
|
|
33
|
+
event: string;
|
|
34
|
+
payload: unknown;
|
|
35
|
+
}): GitHubIssueSignal | null;
|
|
36
|
+
|
|
37
|
+
export { type GitHubIssueSignal, normalizeGitHubIssueOpened, verifyGitHubSignature };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/connectors/github.ts
|
|
2
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
function verifyGitHubSignature(options) {
|
|
5
|
+
const { secret, payload, signature } = options;
|
|
6
|
+
if (signature === null || !signature.startsWith("sha256=")) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const expected = createHmac("sha256", secret).update(payload).digest("hex");
|
|
10
|
+
const provided = signature.slice("sha256=".length);
|
|
11
|
+
if (provided.length !== expected.length) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return timingSafeEqual(Buffer.from(provided, "hex"), Buffer.from(expected, "hex"));
|
|
15
|
+
}
|
|
16
|
+
var issueEventSchema = z.looseObject({
|
|
17
|
+
action: z.string(),
|
|
18
|
+
issue: z.looseObject({
|
|
19
|
+
number: z.number().int().min(1),
|
|
20
|
+
title: z.string(),
|
|
21
|
+
body: z.string().nullable()
|
|
22
|
+
}),
|
|
23
|
+
repository: z.looseObject({
|
|
24
|
+
full_name: z.string().min(1)
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
function normalizeGitHubIssueOpened(options) {
|
|
28
|
+
if (options.event !== "issues") {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const parsed = issueEventSchema.safeParse(options.payload);
|
|
32
|
+
if (!parsed.success || parsed.data.action !== "opened") {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const slug = parsed.data.repository.full_name.toLowerCase();
|
|
36
|
+
const { number, title, body } = parsed.data.issue;
|
|
37
|
+
return {
|
|
38
|
+
source: "github_issue",
|
|
39
|
+
deliveryId: options.deliveryId,
|
|
40
|
+
repositorySlug: slug,
|
|
41
|
+
replyTo: { channel: "github", address: `${slug}#${number}` },
|
|
42
|
+
issue: { number, title, body },
|
|
43
|
+
payload: options.payload
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
normalizeGitHubIssueOpened,
|
|
48
|
+
verifyGitHubSignature
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/connectors/github.ts"],"sourcesContent":["import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { z } from \"zod\";\nimport type { ReplyTo } from \"../schema/common\";\n\n/**\n * Verify a GitHub webhook HMAC signature (the x-hub-signature-256 header)\n * against the raw request body. Returns false for missing or malformed\n * signatures instead of throwing.\n */\nexport function verifyGitHubSignature(options: {\n secret: string;\n payload: string;\n signature: string | null;\n}): boolean {\n const { secret, payload, signature } = options;\n if (signature === null || !signature.startsWith(\"sha256=\")) {\n return false;\n }\n const expected = createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n const provided = signature.slice(\"sha256=\".length);\n if (provided.length !== expected.length) {\n return false;\n }\n return timingSafeEqual(Buffer.from(provided, \"hex\"), Buffer.from(expected, \"hex\"));\n}\n\nconst issueEventSchema = z.looseObject({\n action: z.string(),\n issue: z.looseObject({\n number: z.number().int().min(1),\n title: z.string(),\n body: z.string().nullable(),\n }),\n repository: z.looseObject({\n full_name: z.string().min(1),\n }),\n});\n\nexport interface GitHubIssueSignal {\n source: \"github_issue\";\n deliveryId: string;\n repositorySlug: string;\n replyTo: ReplyTo;\n issue: { number: number; title: string; body: string | null };\n payload: unknown;\n}\n\n/**\n * Normalize a GitHub issues webhook into the factory's signal shape. Returns\n * null for payloads that are not an opened issue. The caller supplies the\n * repository id; the payload stays untrusted data.\n */\nexport function normalizeGitHubIssueOpened(options: {\n deliveryId: string;\n event: string;\n payload: unknown;\n}): GitHubIssueSignal | null {\n if (options.event !== \"issues\") {\n return null;\n }\n const parsed = issueEventSchema.safeParse(options.payload);\n if (!parsed.success || parsed.data.action !== \"opened\") {\n return null;\n }\n const slug = parsed.data.repository.full_name.toLowerCase();\n const { number, title, body } = parsed.data.issue;\n return {\n source: \"github_issue\",\n deliveryId: options.deliveryId,\n repositorySlug: slug,\n replyTo: { channel: \"github\", address: `${slug}#${number}` },\n issue: { number, title, body },\n payload: options.payload,\n };\n}\n"],"mappings":";AAAA,SAAS,YAAY,uBAAuB;AAC5C,SAAS,SAAS;AAQX,SAAS,sBAAsB,SAI1B;AACV,QAAM,EAAE,QAAQ,SAAS,UAAU,IAAI;AACvC,MAAI,cAAc,QAAQ,CAAC,UAAU,WAAW,SAAS,GAAG;AAC1D,WAAO;AAAA,EACT;AACA,QAAM,WAAW,WAAW,UAAU,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAC1E,QAAM,WAAW,UAAU,MAAM,UAAU,MAAM;AACjD,MAAI,SAAS,WAAW,SAAS,QAAQ;AACvC,WAAO;AAAA,EACT;AACA,SAAO,gBAAgB,OAAO,KAAK,UAAU,KAAK,GAAG,OAAO,KAAK,UAAU,KAAK,CAAC;AACnF;AAEA,IAAM,mBAAmB,EAAE,YAAY;AAAA,EACrC,QAAQ,EAAE,OAAO;AAAA,EACjB,OAAO,EAAE,YAAY;AAAA,IACnB,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC9B,OAAO,EAAE,OAAO;AAAA,IAChB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,CAAC;AAAA,EACD,YAAY,EAAE,YAAY;AAAA,IACxB,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,CAAC;AACH,CAAC;AAgBM,SAAS,2BAA2B,SAId;AAC3B,MAAI,QAAQ,UAAU,UAAU;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,SAAS,iBAAiB,UAAU,QAAQ,OAAO;AACzD,MAAI,CAAC,OAAO,WAAW,OAAO,KAAK,WAAW,UAAU;AACtD,WAAO;AAAA,EACT;AACA,QAAM,OAAO,OAAO,KAAK,WAAW,UAAU,YAAY;AAC1D,QAAM,EAAE,QAAQ,OAAO,KAAK,IAAI,OAAO,KAAK;AAC5C,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,YAAY,QAAQ;AAAA,IACpB,gBAAgB;AAAA,IAChB,SAAS,EAAE,SAAS,UAAU,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG;AAAA,IAC3D,OAAO,EAAE,QAAQ,OAAO,KAAK;AAAA,IAC7B,SAAS,QAAQ;AAAA,EACnB;AACF;","names":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type CollectionName = "repositories" | "signals" | "tasks" | "changes" | "receipts";
|
|
2
|
+
interface StoredRecord {
|
|
3
|
+
readonly value: unknown;
|
|
4
|
+
readonly version: number;
|
|
5
|
+
}
|
|
6
|
+
interface StoredEntry {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly record: StoredRecord;
|
|
9
|
+
}
|
|
10
|
+
declare class RecordExistsError extends Error {
|
|
11
|
+
constructor(collection: CollectionName, id: string);
|
|
12
|
+
}
|
|
13
|
+
declare class RecordNotFoundError extends Error {
|
|
14
|
+
constructor(collection: CollectionName, id: string);
|
|
15
|
+
}
|
|
16
|
+
declare class VersionConflictError extends Error {
|
|
17
|
+
constructor(collection: CollectionName, id: string, expectedVersion: number);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Raw persistence contract. Drivers store opaque values and enforce nothing
|
|
21
|
+
* about their content; every invariant lives in the engine above. `update`
|
|
22
|
+
* must be an atomic compare-and-swap on `expectedVersion`.
|
|
23
|
+
*/
|
|
24
|
+
interface StoreDriver {
|
|
25
|
+
readonly name: string;
|
|
26
|
+
get(collection: CollectionName, id: string): Promise<StoredRecord | null>;
|
|
27
|
+
insert(collection: CollectionName, id: string, value: unknown): Promise<void>;
|
|
28
|
+
update(collection: CollectionName, id: string, value: unknown, expectedVersion: number): Promise<void>;
|
|
29
|
+
list(collection: CollectionName): Promise<readonly StoredEntry[]>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { type CollectionName as C, RecordExistsError as R, type StoreDriver as S, VersionConflictError as V, RecordNotFoundError as a, type StoredEntry as b, type StoredRecord as c };
|