@independo/inderun-contracts 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/LICENSE +21 -0
- package/README.md +16 -0
- package/dist/generated/http-request.d.ts +34 -0
- package/dist/generated/http-request.d.ts.map +1 -0
- package/dist/generated/http-request.js +2 -0
- package/dist/generated/http-response.d.ts +25 -0
- package/dist/generated/http-response.d.ts.map +1 -0
- package/dist/generated/http-response.js +2 -0
- package/dist/generated/inderun-error.d.ts +45 -0
- package/dist/generated/inderun-error.d.ts.map +1 -0
- package/dist/generated/inderun-error.js +2 -0
- package/dist/generated/index.d.ts +10 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/index.js +2 -0
- package/dist/generated/route-plan.d.ts +59 -0
- package/dist/generated/route-plan.d.ts.map +1 -0
- package/dist/generated/route-plan.js +2 -0
- package/dist/generated/route-planner-input.d.ts +104 -0
- package/dist/generated/route-planner-input.d.ts.map +1 -0
- package/dist/generated/route-planner-input.js +2 -0
- package/dist/generated/schemas.d.ts +610 -0
- package/dist/generated/schemas.d.ts.map +1 -0
- package/dist/generated/schemas.js +773 -0
- package/dist/generated/task-request.d.ts +171 -0
- package/dist/generated/task-request.d.ts.map +1 -0
- package/dist/generated/task-request.js +2 -0
- package/dist/generated/task-result.d.ts +96 -0
- package/dist/generated/task-result.d.ts.map +1 -0
- package/dist/generated/task-result.js +2 -0
- package/dist/generated/telemetry-event.d.ts +29 -0
- package/dist/generated/telemetry-event.d.ts.map +1 -0
- package/dist/generated/telemetry-event.js +2 -0
- package/dist/host.d.ts +111 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/validators.d.ts +30 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +158 -0
- package/package.json +33 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import Ajv2020 from "ajv/dist/2020.js";
|
|
2
|
+
import { httpRequestSchema, httpResponseSchema, inderunErrorSchema, routePlanSchema, routePlannerInputSchema, taskRequestSchema, taskResultSchema, telemetryEventSchema } from "./generated/index.js";
|
|
3
|
+
const Ajv2020Constructor = Ajv2020;
|
|
4
|
+
const ajv = new Ajv2020Constructor({
|
|
5
|
+
allErrors: true,
|
|
6
|
+
strict: true,
|
|
7
|
+
strictRequired: false,
|
|
8
|
+
validateSchema: true
|
|
9
|
+
});
|
|
10
|
+
const validateTaskRequestSchema = ajv.compile(taskRequestSchema);
|
|
11
|
+
const validateTaskResultSchema = ajv.compile(taskResultSchema);
|
|
12
|
+
const validateIndeRunErrorSchema = ajv.compile(inderunErrorSchema);
|
|
13
|
+
const validateHttpRequestSchema = ajv.compile(httpRequestSchema);
|
|
14
|
+
const validateHttpResponseSchema = ajv.compile(httpResponseSchema);
|
|
15
|
+
const validateTelemetryEventSchema = ajv.compile(telemetryEventSchema);
|
|
16
|
+
const validateRoutePlannerInputSchema = ajv.compile(routePlannerInputSchema);
|
|
17
|
+
const validateRoutePlanSchema = ajv.compile(routePlanSchema);
|
|
18
|
+
export function validateTaskRequest(value) {
|
|
19
|
+
return getTaskRequestValidationIssues(value).length === 0;
|
|
20
|
+
}
|
|
21
|
+
export function validateTaskResult(value) {
|
|
22
|
+
return getTaskResultValidationIssues(value).length === 0;
|
|
23
|
+
}
|
|
24
|
+
export function validateIndeRunError(value) {
|
|
25
|
+
return getIndeRunErrorValidationIssues(value).length === 0;
|
|
26
|
+
}
|
|
27
|
+
export function validateHttpRequest(value) {
|
|
28
|
+
return getHttpRequestValidationIssues(value).length === 0;
|
|
29
|
+
}
|
|
30
|
+
export function validateHttpResponse(value) {
|
|
31
|
+
return getHttpResponseValidationIssues(value).length === 0;
|
|
32
|
+
}
|
|
33
|
+
export function validateTelemetryEvent(value) {
|
|
34
|
+
return getTelemetryEventValidationIssues(value).length === 0;
|
|
35
|
+
}
|
|
36
|
+
export function validateRoutePlannerInput(value) {
|
|
37
|
+
return getRoutePlannerInputValidationIssues(value).length === 0;
|
|
38
|
+
}
|
|
39
|
+
export function validateRoutePlan(value) {
|
|
40
|
+
return getRoutePlanValidationIssues(value).length === 0;
|
|
41
|
+
}
|
|
42
|
+
export function getTaskRequestValidationIssues(value) {
|
|
43
|
+
const issues = getValidationIssues(validateTaskRequestSchema, value, {
|
|
44
|
+
forbidInlineSecrets: true
|
|
45
|
+
});
|
|
46
|
+
issues.push(...findRoutingConstraintIssues(value));
|
|
47
|
+
return issues;
|
|
48
|
+
}
|
|
49
|
+
export function getTaskResultValidationIssues(value) {
|
|
50
|
+
return getValidationIssues(validateTaskResultSchema, value, {
|
|
51
|
+
forbidInlineSecrets: true
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export function getIndeRunErrorValidationIssues(value) {
|
|
55
|
+
return getValidationIssues(validateIndeRunErrorSchema, value, {
|
|
56
|
+
forbidInlineSecrets: true
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
export function getHttpRequestValidationIssues(value) {
|
|
60
|
+
return getValidationIssues(validateHttpRequestSchema, value);
|
|
61
|
+
}
|
|
62
|
+
export function getHttpResponseValidationIssues(value) {
|
|
63
|
+
return getValidationIssues(validateHttpResponseSchema, value);
|
|
64
|
+
}
|
|
65
|
+
export function getTelemetryEventValidationIssues(value) {
|
|
66
|
+
return getValidationIssues(validateTelemetryEventSchema, value, {
|
|
67
|
+
forbidInlineSecrets: true
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export function getRoutePlannerInputValidationIssues(value) {
|
|
71
|
+
return getValidationIssues(validateRoutePlannerInputSchema, value);
|
|
72
|
+
}
|
|
73
|
+
export function getRoutePlanValidationIssues(value) {
|
|
74
|
+
return getValidationIssues(validateRoutePlanSchema, value);
|
|
75
|
+
}
|
|
76
|
+
function getValidationIssues(validateSchema, value, options = {}) {
|
|
77
|
+
const issues = [];
|
|
78
|
+
if (!validateSchema(value)) {
|
|
79
|
+
issues.push(...formatAjvIssues(validateSchema.errors ?? []));
|
|
80
|
+
}
|
|
81
|
+
if (options.forbidInlineSecrets) {
|
|
82
|
+
issues.push(...findInlineSecretKeys(value));
|
|
83
|
+
}
|
|
84
|
+
return issues;
|
|
85
|
+
}
|
|
86
|
+
function formatAjvIssues(errors) {
|
|
87
|
+
return errors.map((error) => ({
|
|
88
|
+
path: error.instancePath || "/",
|
|
89
|
+
message: error.message ?? "Invalid value",
|
|
90
|
+
keyword: error.keyword
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
function findInlineSecretKeys(value, path = "") {
|
|
94
|
+
if (Array.isArray(value)) {
|
|
95
|
+
return value.flatMap((item, index) => findInlineSecretKeys(item, `${path}/${index}`));
|
|
96
|
+
}
|
|
97
|
+
if (!value || typeof value !== "object") {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
const issues = [];
|
|
101
|
+
for (const [key, child] of Object.entries(value)) {
|
|
102
|
+
const childPath = `${path}/${escapeJsonPointerSegment(key)}`;
|
|
103
|
+
if (isForbiddenSecretKey(key)) {
|
|
104
|
+
issues.push({
|
|
105
|
+
path: childPath,
|
|
106
|
+
message: "Inline secrets are not allowed; use authContextRef instead.",
|
|
107
|
+
keyword: "forbiddenSecretKey"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
issues.push(...findInlineSecretKeys(child, childPath));
|
|
111
|
+
}
|
|
112
|
+
return issues;
|
|
113
|
+
}
|
|
114
|
+
function findRoutingConstraintIssues(value) {
|
|
115
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
const request = value;
|
|
119
|
+
const constraints = request.constraints;
|
|
120
|
+
if (!constraints) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
const issues = [];
|
|
124
|
+
if (constraints.privacy === "local_required" && constraints.cloud === "required") {
|
|
125
|
+
issues.push({
|
|
126
|
+
path: "/constraints",
|
|
127
|
+
message: "privacy=local_required conflicts with cloud=required.",
|
|
128
|
+
keyword: "routingConstraintConflict"
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (constraints.privacy === "cloud_required" && constraints.cloud === "forbidden") {
|
|
132
|
+
issues.push({
|
|
133
|
+
path: "/constraints",
|
|
134
|
+
message: "privacy=cloud_required conflicts with cloud=forbidden.",
|
|
135
|
+
keyword: "routingConstraintConflict"
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return issues;
|
|
139
|
+
}
|
|
140
|
+
function normalizeKey(key) {
|
|
141
|
+
return key.replace(/[^a-z0-9]/gi, "").toLowerCase();
|
|
142
|
+
}
|
|
143
|
+
function isForbiddenSecretKey(key) {
|
|
144
|
+
const normalizedKey = normalizeKey(key);
|
|
145
|
+
if (normalizedKey.includes("authorization") ||
|
|
146
|
+
normalizedKey.includes("password") ||
|
|
147
|
+
normalizedKey.includes("secret") ||
|
|
148
|
+
normalizedKey.includes("apikey")) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
if (normalizedKey.includes("api") && normalizedKey.includes("key")) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
return normalizedKey === "token" || normalizedKey.endsWith("token");
|
|
155
|
+
}
|
|
156
|
+
function escapeJsonPointerSegment(segment) {
|
|
157
|
+
return segment.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
158
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@independo/inderun-contracts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Canonical JSON Schemas, generated TypeScript types, and validators for IndeRun contracts.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"ajv": "^8.20.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^24.13.2",
|
|
27
|
+
"vitest": "^3.2.6"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc -p tsconfig.json",
|
|
31
|
+
"test": "vitest run"
|
|
32
|
+
}
|
|
33
|
+
}
|