@x12i/memorix-service 0.0.0-bootstrap.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/README.md +37 -0
- package/dist/app.d.ts +21 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +67 -0
- package/dist/app.js.map +1 -0
- package/dist/catalog-bridge.d.ts +7 -0
- package/dist/catalog-bridge.d.ts.map +1 -0
- package/dist/catalog-bridge.js +155 -0
- package/dist/catalog-bridge.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +36 -0
- package/dist/cli.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +79 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/isolation.d.ts +63 -0
- package/dist/isolation.d.ts.map +1 -0
- package/dist/isolation.js +175 -0
- package/dist/isolation.js.map +1 -0
- package/dist/known-packs.d.ts +5 -0
- package/dist/known-packs.d.ts.map +1 -0
- package/dist/known-packs.js +26 -0
- package/dist/known-packs.js.map +1 -0
- package/dist/mongo-metadata-store.d.ts +17 -0
- package/dist/mongo-metadata-store.d.ts.map +1 -0
- package/dist/mongo-metadata-store.js +81 -0
- package/dist/mongo-metadata-store.js.map +1 -0
- package/dist/openapi/openapi.json +6431 -0
- package/dist/platform.d.ts +52 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +246 -0
- package/dist/platform.js.map +1 -0
- package/dist/relationships/operator-links.d.ts +23 -0
- package/dist/relationships/operator-links.d.ts.map +1 -0
- package/dist/relationships/operator-links.js +41 -0
- package/dist/relationships/operator-links.js.map +1 -0
- package/dist/request-scope.d.ts +7 -0
- package/dist/request-scope.d.ts.map +1 -0
- package/dist/request-scope.js +24 -0
- package/dist/request-scope.js.map +1 -0
- package/dist/routes/data.d.ts +4 -0
- package/dist/routes/data.d.ts.map +1 -0
- package/dist/routes/data.js +237 -0
- package/dist/routes/data.js.map +1 -0
- package/dist/routes/intelligence.d.ts +5 -0
- package/dist/routes/intelligence.d.ts.map +1 -0
- package/dist/routes/intelligence.js +94 -0
- package/dist/routes/intelligence.js.map +1 -0
- package/dist/routes/memory.d.ts +4 -0
- package/dist/routes/memory.d.ts.map +1 -0
- package/dist/routes/memory.js +80 -0
- package/dist/routes/memory.js.map +1 -0
- package/dist/routes/metadata.d.ts +4 -0
- package/dist/routes/metadata.d.ts.map +1 -0
- package/dist/routes/metadata.js +104 -0
- package/dist/routes/metadata.js.map +1 -0
- package/dist/routes/operations.d.ts +4 -0
- package/dist/routes/operations.d.ts.map +1 -0
- package/dist/routes/operations.js +66 -0
- package/dist/routes/operations.js.map +1 -0
- package/dist/routes/pipelines.d.ts +4 -0
- package/dist/routes/pipelines.d.ts.map +1 -0
- package/dist/routes/pipelines.js +128 -0
- package/dist/routes/pipelines.js.map +1 -0
- package/dist/routes/relationships.d.ts +4 -0
- package/dist/routes/relationships.d.ts.map +1 -0
- package/dist/routes/relationships.js +138 -0
- package/dist/routes/relationships.js.map +1 -0
- package/dist/routes/workflow.d.ts +4 -0
- package/dist/routes/workflow.d.ts.map +1 -0
- package/dist/routes/workflow.js +104 -0
- package/dist/routes/workflow.js.map +1 -0
- package/dist/scope.d.ts +19 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +53 -0
- package/dist/scope.js.map +1 -0
- package/openapi/openapi.json +6431 -0
- package/package.json +65 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { resolveScope } from "../request-scope.js";
|
|
2
|
+
export async function registerOperationsRoutes(app, platform) {
|
|
3
|
+
app.get("/api/operations/runs", async (req) => {
|
|
4
|
+
const scope = resolveScope(req);
|
|
5
|
+
const ports = platform.client ? platform.portsFor(scope) : null;
|
|
6
|
+
const pipelineRuns = ports
|
|
7
|
+
? await ports.pipeline.listRuns?.() ?? []
|
|
8
|
+
: [];
|
|
9
|
+
return {
|
|
10
|
+
scope,
|
|
11
|
+
pipelineRuns,
|
|
12
|
+
memoryRuns: [],
|
|
13
|
+
relationshipRuns: [],
|
|
14
|
+
intelligenceArtifacts: platform.client
|
|
15
|
+
? await platform.intelligenceArtifactsFor(scope.orgId).listProposalIds()
|
|
16
|
+
: [],
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
app.get("/api/operations/schedules", async (req) => {
|
|
20
|
+
const scope = resolveScope(req);
|
|
21
|
+
const effective = platform.metadata.resolveEffective(scope.agentIds);
|
|
22
|
+
const schedules = (effective.effective ?? [])
|
|
23
|
+
.filter((e) => e.kind === "schedules")
|
|
24
|
+
.map((e) => e.definition);
|
|
25
|
+
return { scope, schedules };
|
|
26
|
+
});
|
|
27
|
+
app.get("/api/operations/artifacts", async (req) => {
|
|
28
|
+
const scope = resolveScope(req);
|
|
29
|
+
const ports = platform.client ? platform.portsFor(scope) : null;
|
|
30
|
+
const runs = ports ? ((await ports.pipeline.listRuns?.()) ?? []) : [];
|
|
31
|
+
const artifacts = [];
|
|
32
|
+
for (const run of runs) {
|
|
33
|
+
const runId = String(run.runId ?? "");
|
|
34
|
+
const refs = [
|
|
35
|
+
run.capturedContextRef,
|
|
36
|
+
...(Array.isArray(run.artifacts) ? run.artifacts : []),
|
|
37
|
+
].filter(Boolean);
|
|
38
|
+
for (const ref of refs) {
|
|
39
|
+
if (ref && typeof ref === "object") {
|
|
40
|
+
artifacts.push({
|
|
41
|
+
...ref,
|
|
42
|
+
runId,
|
|
43
|
+
pipelineId: run.pipelineId ?? null,
|
|
44
|
+
runStatus: run.status ?? null,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Also surface run identity as operational context when DataRef missing but run exists
|
|
49
|
+
if (refs.length === 0 && runId) {
|
|
50
|
+
artifacts.push({
|
|
51
|
+
kind: "pipeline-run",
|
|
52
|
+
runId,
|
|
53
|
+
pipelineId: run.pipelineId ?? null,
|
|
54
|
+
status: run.status ?? null,
|
|
55
|
+
note: "run ledger entry (no capturedContextRef on this run)",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
scope,
|
|
61
|
+
artifacts,
|
|
62
|
+
note: "DataRef / G8 artifact references from pipeline runs; no inline secrets",
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/routes/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipelines.d.ts","sourceRoot":"","sources":["../../src/routes/pipelines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CA0Jf"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { validatePipelineDefinition } from "@x12i/memorix-pipeline/v2";
|
|
2
|
+
import { resolveScope } from "../request-scope.js";
|
|
3
|
+
import { ServiceError } from "../errors.js";
|
|
4
|
+
export async function registerPipelineRoutes(app, platform) {
|
|
5
|
+
app.get("/api/pipelines/definitions", async (req) => {
|
|
6
|
+
const scope = resolveScope(req);
|
|
7
|
+
const effective = platform.metadata.resolveEffective(scope.agentIds);
|
|
8
|
+
const definitions = (effective.effective ?? [])
|
|
9
|
+
.filter((e) => e.kind === "pipelines")
|
|
10
|
+
.map((e) => e.definition);
|
|
11
|
+
return { scope, definitions };
|
|
12
|
+
});
|
|
13
|
+
app.post("/api/pipelines/validate", async (req) => {
|
|
14
|
+
const scope = resolveScope(req);
|
|
15
|
+
const body = req.body;
|
|
16
|
+
let definition = body.definition;
|
|
17
|
+
if (!definition && body.pipelineId) {
|
|
18
|
+
const def = platform.metadata.getDefinition(scope.agentIds, "pipelines", body.pipelineId);
|
|
19
|
+
definition = def?.definition;
|
|
20
|
+
}
|
|
21
|
+
if (!definition) {
|
|
22
|
+
throw new ServiceError("VALIDATION", "definition or pipelineId required", 400);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
validatePipelineDefinition(definition);
|
|
26
|
+
return { scope, valid: true, compiled: true, issues: [] };
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
return {
|
|
30
|
+
scope,
|
|
31
|
+
valid: false,
|
|
32
|
+
compiled: false,
|
|
33
|
+
issues: [err instanceof Error ? err.message : String(err)],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
app.post("/api/pipelines/start", async (req) => {
|
|
38
|
+
const scope = resolveScope(req);
|
|
39
|
+
const body = req.body;
|
|
40
|
+
if (!body?.pipelineId && !body?.definition) {
|
|
41
|
+
throw new ServiceError("VALIDATION", "pipelineId or definition required", 400);
|
|
42
|
+
}
|
|
43
|
+
const ports = platform.portsFor(scope);
|
|
44
|
+
let definition;
|
|
45
|
+
if (body.definition) {
|
|
46
|
+
definition = structuredClone(body.definition);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const def = platform.metadata.getDefinition(scope.agentIds, "pipelines", body.pipelineId);
|
|
50
|
+
if (!def?.definition) {
|
|
51
|
+
throw new ServiceError("NOT_FOUND", `pipeline ${body.pipelineId} not found`, 404);
|
|
52
|
+
}
|
|
53
|
+
definition = structuredClone(def.definition);
|
|
54
|
+
}
|
|
55
|
+
if (body.forceFailStepId) {
|
|
56
|
+
const steps = definition.steps ?? [];
|
|
57
|
+
const step = steps.find((s) => s.id === body.forceFailStepId || s.stepId === body.forceFailStepId);
|
|
58
|
+
if (!step) {
|
|
59
|
+
throw new ServiceError("VALIDATION", `forceFailStepId ${body.forceFailStepId} not found on pipeline`, 400);
|
|
60
|
+
}
|
|
61
|
+
step.portConfig = { ...(step.portConfig ?? {}), forceFail: true };
|
|
62
|
+
}
|
|
63
|
+
const run = await ports.pipeline.start(definition, body.input, {
|
|
64
|
+
trigger: body.trigger ?? "on-demand",
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
scope,
|
|
68
|
+
runId: run.runId,
|
|
69
|
+
pipelineId: body.pipelineId ?? definition.pipelineId ?? null,
|
|
70
|
+
trigger: body.trigger ?? "on-demand",
|
|
71
|
+
status: run.status,
|
|
72
|
+
forceFailStepId: body.forceFailStepId ?? null,
|
|
73
|
+
run,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
app.get("/api/pipelines/runs/:runId", async (req) => {
|
|
77
|
+
const scope = resolveScope(req);
|
|
78
|
+
const { runId } = req.params;
|
|
79
|
+
const ports = platform.portsFor(scope);
|
|
80
|
+
const run = await ports.pipeline.getRun(runId);
|
|
81
|
+
const steps = run
|
|
82
|
+
? await ports.pipeline.getStepAttempts(runId)
|
|
83
|
+
: [];
|
|
84
|
+
const captured = run?.capturedContextRef ?? null;
|
|
85
|
+
return {
|
|
86
|
+
scope,
|
|
87
|
+
runId,
|
|
88
|
+
status: run?.status ?? "unknown",
|
|
89
|
+
pipelineId: run?.pipelineId ?? null,
|
|
90
|
+
steps,
|
|
91
|
+
artifacts: captured ? [captured] : [],
|
|
92
|
+
capturedContextRef: captured,
|
|
93
|
+
run,
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
app.post("/api/pipelines/runs/:runId/retry-step", async (req) => {
|
|
97
|
+
const scope = resolveScope(req);
|
|
98
|
+
const { runId } = req.params;
|
|
99
|
+
const body = req.body;
|
|
100
|
+
if (!body?.confirm) {
|
|
101
|
+
throw new ServiceError("CONFIRMATION_REQUIRED", "confirm:true required", 400);
|
|
102
|
+
}
|
|
103
|
+
if (!body.stepId)
|
|
104
|
+
throw new ServiceError("VALIDATION", "stepId required", 400);
|
|
105
|
+
const ports = platform.portsFor(scope);
|
|
106
|
+
const result = await ports.pipeline.retryFailedStep(runId, body.stepId);
|
|
107
|
+
const run = await ports.pipeline.getRun(runId);
|
|
108
|
+
const steps = await ports.pipeline.getStepAttempts(runId);
|
|
109
|
+
return {
|
|
110
|
+
scope,
|
|
111
|
+
runId,
|
|
112
|
+
stepId: body.stepId,
|
|
113
|
+
status: run?.status ?? "unknown",
|
|
114
|
+
stepAttempt: result,
|
|
115
|
+
steps,
|
|
116
|
+
run,
|
|
117
|
+
note: "retry envelope; status is the refreshed pipeline run status",
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
app.post("/api/pipelines/runs/:runId/resume", async (req) => {
|
|
121
|
+
const scope = resolveScope(req);
|
|
122
|
+
const { runId } = req.params;
|
|
123
|
+
const ports = platform.portsFor(scope);
|
|
124
|
+
const result = await ports.pipeline.resume(runId);
|
|
125
|
+
return { scope, runId, status: "resume-accepted", result };
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=pipelines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipelines.js","sourceRoot":"","sources":["../../src/routes/pipelines.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../../src/routes/relationships.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CA6Kf"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { resolveScope } from "../request-scope.js";
|
|
2
|
+
import { ServiceError } from "../errors.js";
|
|
3
|
+
import { normalizeOperatorRelationshipLink } from "../relationships/operator-links.js";
|
|
4
|
+
export async function registerRelationshipRoutes(app, platform) {
|
|
5
|
+
app.get("/api/relationships/definitions", async (req) => {
|
|
6
|
+
const scope = resolveScope(req);
|
|
7
|
+
const ports = platform.portsFor(scope);
|
|
8
|
+
const definitions = platform.metadata
|
|
9
|
+
.resolveEffective(scope.agentIds)
|
|
10
|
+
.effective?.filter((e) => e.kind === "relationship-definitions")
|
|
11
|
+
.map((e) => e.definition) ?? [];
|
|
12
|
+
const compiledPlans = [];
|
|
13
|
+
for (const d of definitions) {
|
|
14
|
+
const id = String(d.id ?? "");
|
|
15
|
+
if (!id)
|
|
16
|
+
continue;
|
|
17
|
+
try {
|
|
18
|
+
compiledPlans.push(ports.relationships.compile(id, scope.agentIds));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
/* skip */
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { scope, definitions, compiledPlans };
|
|
25
|
+
});
|
|
26
|
+
app.get("/api/relationships/query", async (req) => {
|
|
27
|
+
const scope = resolveScope(req);
|
|
28
|
+
const q = req.query;
|
|
29
|
+
if (!q.recordId) {
|
|
30
|
+
throw new ServiceError("VALIDATION", "recordId required", 400);
|
|
31
|
+
}
|
|
32
|
+
const ports = platform.portsFor(scope);
|
|
33
|
+
const traversal = q.direction === "inverse" ? "inverse" : "forward";
|
|
34
|
+
const section = await ports.reader.getRelationships(scope, q.recordId, {
|
|
35
|
+
include: true,
|
|
36
|
+
definitionIds: q.definitionId ? [q.definitionId] : undefined,
|
|
37
|
+
traversal,
|
|
38
|
+
// Prefer snapshots for expansion proof; fall back to raw when snapshots absent.
|
|
39
|
+
expandContentTypes: q.expand === "true" ? ["snapshots", "raw"] : undefined,
|
|
40
|
+
});
|
|
41
|
+
const links = section.items.map((item) => normalizeOperatorRelationshipLink(q.recordId, item, traversal));
|
|
42
|
+
const unresolvedTargets = links.filter((i) => i.targetStatus === "unresolved");
|
|
43
|
+
return {
|
|
44
|
+
scope,
|
|
45
|
+
direction: q.direction ?? "forward",
|
|
46
|
+
definitionId: q.definitionId ?? null,
|
|
47
|
+
links,
|
|
48
|
+
unresolvedTargets,
|
|
49
|
+
pageInfo: section.pageInfo,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
app.post("/api/relationships/discover", async (req) => {
|
|
53
|
+
const scope = resolveScope(req);
|
|
54
|
+
const body = req.body;
|
|
55
|
+
if (!body?.definitionId) {
|
|
56
|
+
throw new ServiceError("VALIDATION", "definitionId required", 400);
|
|
57
|
+
}
|
|
58
|
+
const ports = platform.portsFor(scope);
|
|
59
|
+
const result = await ports.relationships.discoverAndMaterialize(scope, body.definitionId);
|
|
60
|
+
return {
|
|
61
|
+
scope,
|
|
62
|
+
runId: `rel-discover-${Date.now()}`,
|
|
63
|
+
definitionId: body.definitionId,
|
|
64
|
+
status: "completed",
|
|
65
|
+
result,
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
app.post("/api/relationships/verify", async (req) => {
|
|
69
|
+
const scope = resolveScope(req);
|
|
70
|
+
const body = req.body;
|
|
71
|
+
if (!body?.definitionId) {
|
|
72
|
+
throw new ServiceError("VALIDATION", "definitionId required", 400);
|
|
73
|
+
}
|
|
74
|
+
const ports = platform.portsFor(scope);
|
|
75
|
+
const verify = await ports.relationships.verifyDefinition(scope, body.definitionId);
|
|
76
|
+
return { scope, definitionId: body.definitionId, verify };
|
|
77
|
+
});
|
|
78
|
+
app.post("/api/relationships/rebuild", async (req) => {
|
|
79
|
+
const scope = resolveScope(req);
|
|
80
|
+
const body = req.body;
|
|
81
|
+
if (!body?.confirm) {
|
|
82
|
+
throw new ServiceError("CONFIRMATION_REQUIRED", "confirm:true required", 400);
|
|
83
|
+
}
|
|
84
|
+
if (!body.definitionId) {
|
|
85
|
+
throw new ServiceError("VALIDATION", "definitionId required", 400);
|
|
86
|
+
}
|
|
87
|
+
const ports = platform.portsFor(scope);
|
|
88
|
+
const rebuild = await ports.relationships.rebuildDefinition(scope, body.definitionId);
|
|
89
|
+
return { scope, definitionId: body.definitionId, rebuild };
|
|
90
|
+
});
|
|
91
|
+
app.post("/api/relationships/cleanup", async (req) => {
|
|
92
|
+
const scope = resolveScope(req);
|
|
93
|
+
const body = req.body;
|
|
94
|
+
if (!body?.confirm) {
|
|
95
|
+
throw new ServiceError("CONFIRMATION_REQUIRED", "confirm:true required", 400);
|
|
96
|
+
}
|
|
97
|
+
if (!body.definitionId) {
|
|
98
|
+
throw new ServiceError("VALIDATION", "definitionId required", 400);
|
|
99
|
+
}
|
|
100
|
+
const ports = platform.portsFor(scope);
|
|
101
|
+
const engine = ports.relationships;
|
|
102
|
+
const cleanup = engine.removeDefinitionLinks
|
|
103
|
+
? await engine.removeDefinitionLinks(scope, body.definitionId)
|
|
104
|
+
: { status: "noop" };
|
|
105
|
+
return { scope, definitionId: body.definitionId, cleanup };
|
|
106
|
+
});
|
|
107
|
+
app.get("/api/relationships/related-property", async (req) => {
|
|
108
|
+
const scope = resolveScope(req);
|
|
109
|
+
const q = req.query;
|
|
110
|
+
if (!q.definitionId || !q.subjectRecordId || !q.relatedObjectType) {
|
|
111
|
+
throw new ServiceError("VALIDATION", "definitionId, subjectRecordId, relatedObjectType required", 400);
|
|
112
|
+
}
|
|
113
|
+
const ports = platform.portsFor(scope);
|
|
114
|
+
const results = await ports.reader.queryRelationshipsByRelatedProperties(scope, {
|
|
115
|
+
definitionId: q.definitionId,
|
|
116
|
+
subjectRecordId: q.subjectRecordId,
|
|
117
|
+
traversal: "forward",
|
|
118
|
+
relatedObjectType: q.relatedObjectType,
|
|
119
|
+
relatedContentType: q.relatedContentType ?? "snapshots",
|
|
120
|
+
relatedFilters: q.property
|
|
121
|
+
? [{ field: q.property, op: "exists", value: true }]
|
|
122
|
+
: undefined,
|
|
123
|
+
relatedScanLimit: Math.min(Number(q.limit ?? 50), 200),
|
|
124
|
+
limit: Math.min(Number(q.limit ?? 50), 200),
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
scope,
|
|
128
|
+
definitionId: q.definitionId,
|
|
129
|
+
property: q.property ?? null,
|
|
130
|
+
limit: Math.min(Number(q.limit ?? 50), 200),
|
|
131
|
+
results,
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
app.all("/api/relationships/links", async () => {
|
|
135
|
+
throw new ServiceError("FORBIDDEN_ROUTE", "ad-hoc/manual link mutation is not exposed", 405);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=relationships.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relationships.js","sourceRoot":"","sources":["../../src/routes/relationships.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/routes/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAqHf"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { resolveScope } from "../request-scope.js";
|
|
2
|
+
import { ServiceError } from "../errors.js";
|
|
3
|
+
export async function registerWorkflowRoutes(app, platform) {
|
|
4
|
+
app.get("/api/workflow", async (req) => {
|
|
5
|
+
const scope = resolveScope(req);
|
|
6
|
+
const q = req.query;
|
|
7
|
+
if (!q.id) {
|
|
8
|
+
return {
|
|
9
|
+
scope,
|
|
10
|
+
id: null,
|
|
11
|
+
contentType: "workflow",
|
|
12
|
+
record: null,
|
|
13
|
+
currentRevision: null,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const ports = platform.portsFor(scope);
|
|
17
|
+
const objectType = q.objectType ?? "work-items";
|
|
18
|
+
const record = await ports.reader.getContent(scope, {
|
|
19
|
+
objectType,
|
|
20
|
+
contentType: "workflow",
|
|
21
|
+
recordId: q.id,
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
scope,
|
|
25
|
+
id: q.id,
|
|
26
|
+
objectType,
|
|
27
|
+
contentType: "workflow",
|
|
28
|
+
record,
|
|
29
|
+
currentRevision: record.revision,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
app.put("/api/workflow", async (req) => {
|
|
33
|
+
const scope = resolveScope(req);
|
|
34
|
+
const body = req.body;
|
|
35
|
+
if (!body?.id || !body.record) {
|
|
36
|
+
throw new ServiceError("VALIDATION", "id and record required", 400);
|
|
37
|
+
}
|
|
38
|
+
if (body.expectedRevision === undefined) {
|
|
39
|
+
throw new ServiceError("VALIDATION", "exact revision precondition required (expectedRevision)", 400);
|
|
40
|
+
}
|
|
41
|
+
if (body.currentRevision !== undefined &&
|
|
42
|
+
body.currentRevision !== body.expectedRevision) {
|
|
43
|
+
throw new ServiceError("REVISION_CONFLICT", "stale expectedRevision — reload and retry", 409, {
|
|
44
|
+
id: body.id,
|
|
45
|
+
expectedRevision: body.expectedRevision,
|
|
46
|
+
currentRevision: body.currentRevision,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const ports = platform.portsFor(scope);
|
|
50
|
+
const objectType = body.objectType ?? "work-items";
|
|
51
|
+
try {
|
|
52
|
+
const record = {
|
|
53
|
+
...body.record,
|
|
54
|
+
recordId: body.id,
|
|
55
|
+
objectType,
|
|
56
|
+
contentType: "workflow",
|
|
57
|
+
dataCategory: "entity",
|
|
58
|
+
};
|
|
59
|
+
let existing = null;
|
|
60
|
+
try {
|
|
61
|
+
existing = await ports.reader.getContent(scope, {
|
|
62
|
+
objectType,
|
|
63
|
+
contentType: "workflow",
|
|
64
|
+
recordId: body.id,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
existing = null;
|
|
69
|
+
}
|
|
70
|
+
let result;
|
|
71
|
+
if (!existing && Number(body.expectedRevision) === 0) {
|
|
72
|
+
result = await ports.writer.add({
|
|
73
|
+
scope,
|
|
74
|
+
precondition: { kind: "absent" },
|
|
75
|
+
record,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
result = await ports.writer.upsert({
|
|
80
|
+
scope,
|
|
81
|
+
precondition: { kind: "revision", revision: Number(body.expectedRevision) },
|
|
82
|
+
record,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
scope,
|
|
87
|
+
id: body.id,
|
|
88
|
+
expectedRevision: body.expectedRevision,
|
|
89
|
+
currentRevision: result.record.revision,
|
|
90
|
+
status: "accepted",
|
|
91
|
+
conflict: false,
|
|
92
|
+
result,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
97
|
+
if (/stale|revision|WRITE_STALE/i.test(msg)) {
|
|
98
|
+
throw new ServiceError("REVISION_CONFLICT", msg, 409);
|
|
99
|
+
}
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/routes/workflow.ts"],"names":[],"mappings":"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"}
|
package/dist/scope.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical request scope: exactly one orgId + one or more unique agentIds.
|
|
3
|
+
* orgId = data universe; agentIds = effective metadata only.
|
|
4
|
+
*/
|
|
5
|
+
export type MemorixScope = {
|
|
6
|
+
orgId: string;
|
|
7
|
+
agentIds: string[];
|
|
8
|
+
};
|
|
9
|
+
export declare class ScopeValidationError extends Error {
|
|
10
|
+
readonly code = "SCOPE_INVALID";
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare function canonicalizeScope(input: {
|
|
14
|
+
orgId?: unknown;
|
|
15
|
+
agentIds?: unknown;
|
|
16
|
+
agentId?: unknown;
|
|
17
|
+
}): MemorixScope;
|
|
18
|
+
export declare function scopeFromHeaders(headers: Record<string, string | string[] | undefined>): MemorixScope;
|
|
19
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,mBAAmB;gBACpB,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,YAAY,CAkCf;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,YAAY,CAarG"}
|
package/dist/scope.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export class ScopeValidationError extends Error {
|
|
2
|
+
code = "SCOPE_INVALID";
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "ScopeValidationError";
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export function canonicalizeScope(input) {
|
|
9
|
+
const orgId = typeof input.orgId === "string" ? input.orgId.trim() : "";
|
|
10
|
+
if (!orgId) {
|
|
11
|
+
throw new ScopeValidationError("orgId is required and must be a non-empty string");
|
|
12
|
+
}
|
|
13
|
+
// Reject singular agentId-only scope on new routes
|
|
14
|
+
if (input.agentId !== undefined && input.agentIds === undefined) {
|
|
15
|
+
throw new ScopeValidationError("singular agentId is rejected; provide agentIds[] (one or more)");
|
|
16
|
+
}
|
|
17
|
+
let raw = [];
|
|
18
|
+
if (Array.isArray(input.agentIds)) {
|
|
19
|
+
raw = input.agentIds;
|
|
20
|
+
}
|
|
21
|
+
else if (typeof input.agentIds === "string") {
|
|
22
|
+
raw = input.agentIds.split(",").map((s) => s.trim());
|
|
23
|
+
}
|
|
24
|
+
const agentIds = [
|
|
25
|
+
...new Set(raw
|
|
26
|
+
.filter((a) => typeof a === "string")
|
|
27
|
+
.map((a) => a.trim())
|
|
28
|
+
.filter(Boolean)),
|
|
29
|
+
].sort((a, b) => a.localeCompare(b));
|
|
30
|
+
if (agentIds.length === 0) {
|
|
31
|
+
throw new ScopeValidationError("agentIds[] must contain at least one non-empty agent id");
|
|
32
|
+
}
|
|
33
|
+
return { orgId, agentIds };
|
|
34
|
+
}
|
|
35
|
+
export function scopeFromHeaders(headers) {
|
|
36
|
+
const org = header(headers, "x-memorix-org-id") ??
|
|
37
|
+
header(headers, "x-org-id");
|
|
38
|
+
const agents = header(headers, "x-memorix-agent-ids") ??
|
|
39
|
+
header(headers, "x-agent-ids");
|
|
40
|
+
const singular = header(headers, "x-memorix-agent-id") ?? header(headers, "x-agent-id");
|
|
41
|
+
return canonicalizeScope({
|
|
42
|
+
orgId: org,
|
|
43
|
+
agentIds: agents,
|
|
44
|
+
agentId: singular !== undefined && agents === undefined ? singular : undefined,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function header(headers, name) {
|
|
48
|
+
const v = headers[name] ?? headers[name.toLowerCase()];
|
|
49
|
+
if (Array.isArray(v))
|
|
50
|
+
return v[0];
|
|
51
|
+
return typeof v === "string" ? v : undefined;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
|