kadi-harness-runtime 0.1.8

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.
Files changed (86) hide show
  1. package/README.md +20 -0
  2. package/dist/adapter-loader.d.ts +35 -0
  3. package/dist/adapter-loader.d.ts.map +1 -0
  4. package/dist/adapter-loader.js +109 -0
  5. package/dist/adapter-loader.js.map +1 -0
  6. package/dist/event-bus.d.ts +55 -0
  7. package/dist/event-bus.d.ts.map +1 -0
  8. package/dist/event-bus.js +170 -0
  9. package/dist/event-bus.js.map +1 -0
  10. package/dist/event-normalizer.d.ts +41 -0
  11. package/dist/event-normalizer.d.ts.map +1 -0
  12. package/dist/event-normalizer.js +68 -0
  13. package/dist/event-normalizer.js.map +1 -0
  14. package/dist/gateways/artifacts.d.ts +24 -0
  15. package/dist/gateways/artifacts.d.ts.map +1 -0
  16. package/dist/gateways/artifacts.js +128 -0
  17. package/dist/gateways/artifacts.js.map +1 -0
  18. package/dist/gateways/authorization.d.ts +38 -0
  19. package/dist/gateways/authorization.d.ts.map +1 -0
  20. package/dist/gateways/authorization.js +118 -0
  21. package/dist/gateways/authorization.js.map +1 -0
  22. package/dist/gateways/events.d.ts +31 -0
  23. package/dist/gateways/events.d.ts.map +1 -0
  24. package/dist/gateways/events.js +135 -0
  25. package/dist/gateways/events.js.map +1 -0
  26. package/dist/gateways/redaction.d.ts +2 -0
  27. package/dist/gateways/redaction.d.ts.map +1 -0
  28. package/dist/gateways/redaction.js +2 -0
  29. package/dist/gateways/redaction.js.map +1 -0
  30. package/dist/gateways/sessions.d.ts +27 -0
  31. package/dist/gateways/sessions.d.ts.map +1 -0
  32. package/dist/gateways/sessions.js +167 -0
  33. package/dist/gateways/sessions.js.map +1 -0
  34. package/dist/gateways/tools.d.ts +36 -0
  35. package/dist/gateways/tools.d.ts.map +1 -0
  36. package/dist/gateways/tools.js +135 -0
  37. package/dist/gateways/tools.js.map +1 -0
  38. package/dist/index.d.ts +82 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +27 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/lifecycle.d.ts +23 -0
  43. package/dist/lifecycle.d.ts.map +1 -0
  44. package/dist/lifecycle.js +63 -0
  45. package/dist/lifecycle.js.map +1 -0
  46. package/dist/policy/redaction.d.ts +10 -0
  47. package/dist/policy/redaction.d.ts.map +1 -0
  48. package/dist/policy/redaction.js +48 -0
  49. package/dist/policy/redaction.js.map +1 -0
  50. package/dist/protocol/context-client.d.ts +50 -0
  51. package/dist/protocol/context-client.d.ts.map +1 -0
  52. package/dist/protocol/context-client.js +49 -0
  53. package/dist/protocol/context-client.js.map +1 -0
  54. package/dist/protocol/context-server.d.ts +19 -0
  55. package/dist/protocol/context-server.d.ts.map +1 -0
  56. package/dist/protocol/context-server.js +103 -0
  57. package/dist/protocol/context-server.js.map +1 -0
  58. package/dist/registry.d.ts +42 -0
  59. package/dist/registry.d.ts.map +1 -0
  60. package/dist/registry.js +210 -0
  61. package/dist/registry.js.map +1 -0
  62. package/dist/run-coordinator.d.ts +47 -0
  63. package/dist/run-coordinator.d.ts.map +1 -0
  64. package/dist/run-coordinator.js +241 -0
  65. package/dist/run-coordinator.js.map +1 -0
  66. package/dist/runner/cli.d.ts +18 -0
  67. package/dist/runner/cli.d.ts.map +1 -0
  68. package/dist/runner/cli.js +54 -0
  69. package/dist/runner/cli.js.map +1 -0
  70. package/dist/runner/runner-service.d.ts +88 -0
  71. package/dist/runner/runner-service.d.ts.map +1 -0
  72. package/dist/runner/runner-service.js +138 -0
  73. package/dist/runner/runner-service.js.map +1 -0
  74. package/dist/runtime.d.ts +96 -0
  75. package/dist/runtime.d.ts.map +1 -0
  76. package/dist/runtime.js +330 -0
  77. package/dist/runtime.js.map +1 -0
  78. package/dist/scheduling/request-store.d.ts +71 -0
  79. package/dist/scheduling/request-store.d.ts.map +1 -0
  80. package/dist/scheduling/request-store.js +173 -0
  81. package/dist/scheduling/request-store.js.map +1 -0
  82. package/dist/scheduling/signing.d.ts +57 -0
  83. package/dist/scheduling/signing.d.ts.map +1 -0
  84. package/dist/scheduling/signing.js +142 -0
  85. package/dist/scheduling/signing.js.map +1 -0
  86. package/package.json +47 -0
@@ -0,0 +1,173 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { RunRequestSchema, } from "@kadi.build/kadi-harness-contracts";
5
+ /** Maximum size of the serialized request kept in the request store. */
6
+ export const MAX_REQUEST_PAYLOAD_BYTES = 64 * 1024;
7
+ const SENSITIVE_KEY = /token|secret|password|authorization|credential|api[-_]?key|private[-_]?key/i;
8
+ export class ScheduledRequestStoreError extends Error {
9
+ code;
10
+ constructor(code, message) {
11
+ super(message);
12
+ this.name = "ScheduledRequestStoreError";
13
+ this.code = code;
14
+ }
15
+ }
16
+ function isRecord(value) {
17
+ return typeof value === "object" && value !== null && !Array.isArray(value);
18
+ }
19
+ function assertSerializable(value, path) {
20
+ if (value === null || typeof value === "string" || typeof value === "boolean")
21
+ return;
22
+ if (typeof value === "number") {
23
+ if (Number.isFinite(value))
24
+ return;
25
+ throw new ScheduledRequestStoreError("invalid_request", `${path} must contain finite numbers`);
26
+ }
27
+ if (Array.isArray(value)) {
28
+ value.forEach((item, index) => assertSerializable(item, `${path}[${index}]`));
29
+ return;
30
+ }
31
+ if (!isRecord(value) || Object.getPrototypeOf(value) !== Object.prototype) {
32
+ throw new ScheduledRequestStoreError("invalid_request", `${path} must be JSON-serializable`);
33
+ }
34
+ for (const [key, child] of Object.entries(value)) {
35
+ if (child === undefined) {
36
+ throw new ScheduledRequestStoreError("invalid_request", `${path}.${key} cannot be undefined`);
37
+ }
38
+ if (SENSITIVE_KEY.test(key)) {
39
+ throw new ScheduledRequestStoreError("sensitive_data", `${path}.${key} contains credential material and cannot be scheduled`);
40
+ }
41
+ assertSerializable(child, `${path}.${key}`);
42
+ }
43
+ }
44
+ function validateSpec(spec) {
45
+ if (!isRecord(spec)) {
46
+ throw new ScheduledRequestStoreError("invalid_request", "ScheduledRunSpec must be an object");
47
+ }
48
+ if (!spec.idempotencyPrefix || typeof spec.idempotencyPrefix !== "string") {
49
+ throw new ScheduledRequestStoreError("invalid_request", "idempotencyPrefix is required");
50
+ }
51
+ try {
52
+ RunRequestSchema.parse(spec.run);
53
+ }
54
+ catch (error) {
55
+ throw new ScheduledRequestStoreError("invalid_request", `run request failed contract validation: ${error instanceof Error ? error.message : String(error)}`);
56
+ }
57
+ assertSerializable(spec, "spec");
58
+ }
59
+ /**
60
+ * Serialize JSON with recursively sorted object keys. This produces the same
61
+ * bytes across processes and languages for the same scheduled request.
62
+ */
63
+ export function canonicalizeJson(value) {
64
+ assertSerializable(value, "value");
65
+ const encode = (input) => {
66
+ if (input === null || typeof input === "string" || typeof input === "boolean") {
67
+ return JSON.stringify(input);
68
+ }
69
+ if (typeof input === "number")
70
+ return JSON.stringify(input);
71
+ if (Array.isArray(input))
72
+ return `[${input.map(encode).join(",")}]`;
73
+ return `{${Object.keys(input).sort().map((key) => `${JSON.stringify(key)}:${encode(input[key])}`).join(",")}}`;
74
+ };
75
+ return encode(value);
76
+ }
77
+ export function sha256Digest(canonicalPayload) {
78
+ return createHash("sha256").update(canonicalPayload, "utf8").digest("hex");
79
+ }
80
+ /** In-memory reference store used by tests and embedders that provide a durable wrapper. */
81
+ export class InMemoryScheduledRequestStore {
82
+ records = new Map();
83
+ refFactory;
84
+ clock;
85
+ constructor(options = {}) {
86
+ this.refFactory = options.refFactory ?? randomUUID;
87
+ this.clock = options.clock ?? (() => new Date());
88
+ }
89
+ async put(spec, options = {}) {
90
+ validateSpec(spec);
91
+ const canonicalPayload = canonicalizeJson(spec);
92
+ if (Buffer.byteLength(canonicalPayload, "utf8") > MAX_REQUEST_PAYLOAD_BYTES) {
93
+ throw new ScheduledRequestStoreError("request_too_large", `serialized request exceeds the ${MAX_REQUEST_PAYLOAD_BYTES}-byte limit`);
94
+ }
95
+ const record = {
96
+ requestRef: options.requestRef ?? this.refFactory(),
97
+ canonicalPayload,
98
+ payloadDigest: sha256Digest(canonicalPayload),
99
+ spec,
100
+ createdAt: (options.createdAt ?? this.clock()).toISOString(),
101
+ };
102
+ if (this.records.has(record.requestRef)) {
103
+ throw new ScheduledRequestStoreError("invalid_request", `request reference already exists: ${record.requestRef}`);
104
+ }
105
+ this.records.set(record.requestRef, record);
106
+ return record;
107
+ }
108
+ async get(requestRef) {
109
+ return this.records.get(requestRef);
110
+ }
111
+ }
112
+ /**
113
+ * Small durable request store for a runner host. Deployments can replace this
114
+ * with an encrypted KADI artifact/database implementation without changing
115
+ * signing or verification.
116
+ */
117
+ export class FileScheduledRequestStore {
118
+ directory;
119
+ refFactory;
120
+ clock;
121
+ constructor(options) {
122
+ this.directory = options.directory;
123
+ this.refFactory = options.refFactory ?? randomUUID;
124
+ this.clock = options.clock ?? (() => new Date());
125
+ }
126
+ async put(spec, options = {}) {
127
+ validateSpec(spec);
128
+ const canonicalPayload = canonicalizeJson(spec);
129
+ if (Buffer.byteLength(canonicalPayload, "utf8") > MAX_REQUEST_PAYLOAD_BYTES) {
130
+ throw new ScheduledRequestStoreError("request_too_large", `serialized request exceeds the ${MAX_REQUEST_PAYLOAD_BYTES}-byte limit`);
131
+ }
132
+ const record = {
133
+ requestRef: options.requestRef ?? this.refFactory(),
134
+ canonicalPayload,
135
+ payloadDigest: sha256Digest(canonicalPayload),
136
+ spec,
137
+ createdAt: (options.createdAt ?? this.clock()).toISOString(),
138
+ };
139
+ const path = this.pathFor(record.requestRef);
140
+ await mkdir(this.directory, { recursive: true, mode: 0o700 });
141
+ try {
142
+ await readFile(path);
143
+ throw new ScheduledRequestStoreError("invalid_request", `request reference already exists: ${record.requestRef}`);
144
+ }
145
+ catch (error) {
146
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT")
147
+ throw error;
148
+ }
149
+ const temporaryPath = `${path}.${randomUUID()}.tmp`;
150
+ await writeFile(temporaryPath, JSON.stringify(record), { encoding: "utf8", mode: 0o600 });
151
+ await rename(temporaryPath, path);
152
+ return record;
153
+ }
154
+ async get(requestRef) {
155
+ const path = this.pathFor(requestRef);
156
+ try {
157
+ const content = await readFile(path, "utf8");
158
+ return JSON.parse(content);
159
+ }
160
+ catch (error) {
161
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
162
+ return undefined;
163
+ throw error;
164
+ }
165
+ }
166
+ pathFor(requestRef) {
167
+ if (!/^[A-Za-z0-9._:-]+$/.test(requestRef)) {
168
+ throw new ScheduledRequestStoreError("invalid_request", "request reference contains unsafe path characters");
169
+ }
170
+ return join(this.directory, `${requestRef}.json`);
171
+ }
172
+ }
173
+ //# sourceMappingURL=request-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-store.js","sourceRoot":"","sources":["../../src/scheduling/request-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { type KeyLike } from "node:crypto";
2
+ import { type ScheduledRunSpec, type ScheduledRequestStore, type StoredScheduledRequest } from "./request-store.js";
3
+ export declare const RUNNER_AUDIENCE = "kadi-harness-runner";
4
+ export interface SigningKey {
5
+ readonly keyId: string;
6
+ readonly privateKey: KeyLike;
7
+ readonly publicKey?: KeyLike;
8
+ }
9
+ /** Adapter for secret-ability or another durable KADI key-management service. */
10
+ export interface SigningKeyProvider {
11
+ getActiveKey(): Promise<SigningKey>;
12
+ getPublicKey(keyId: string): Promise<KeyLike | undefined>;
13
+ }
14
+ export interface ReplayGuard {
15
+ claim(idempotencyKey: string, expiresAt: string): Promise<boolean>;
16
+ }
17
+ export declare class InMemoryReplayGuard implements ReplayGuard {
18
+ private readonly claims;
19
+ private readonly now;
20
+ constructor(now?: () => number);
21
+ claim(idempotencyKey: string, expiresAt: string): Promise<boolean>;
22
+ }
23
+ export interface SignedScheduledRequest {
24
+ readonly requestRef: string;
25
+ readonly payloadDigest: string;
26
+ readonly keyId: string;
27
+ readonly audience: string;
28
+ readonly createdAt: string;
29
+ readonly expiresAt: string;
30
+ readonly idempotencyKey: string;
31
+ readonly signature: string;
32
+ }
33
+ export interface CreateSignedRequestOptions {
34
+ readonly expiresAt: Date | string;
35
+ readonly createdAt?: Date | string;
36
+ readonly idempotencyKey?: string;
37
+ readonly firingId?: string;
38
+ readonly audience?: string;
39
+ readonly requestRef?: string;
40
+ }
41
+ export interface VerifySignedRequestOptions {
42
+ readonly store: ScheduledRequestStore;
43
+ readonly keyProvider: SigningKeyProvider;
44
+ readonly replayGuard: ReplayGuard;
45
+ readonly now?: () => Date;
46
+ readonly audience?: string;
47
+ }
48
+ export declare class ScheduledRequestSigningError extends Error {
49
+ readonly code: "invalid_signature" | "unknown_key" | "expired" | "wrong_audience" | "request_not_found" | "payload_mismatch" | "replayed" | "invalid_envelope";
50
+ constructor(code: ScheduledRequestSigningError["code"], message: string);
51
+ }
52
+ export declare function createSignedScheduledRequest(store: ScheduledRequestStore, keyProvider: SigningKeyProvider, spec: ScheduledRunSpec, options: CreateSignedRequestOptions): Promise<{
53
+ readonly reference: SignedScheduledRequest;
54
+ readonly stored: StoredScheduledRequest;
55
+ }>;
56
+ export declare function verifySignedScheduledRequest(reference: SignedScheduledRequest, options: VerifySignedRequestOptions): Promise<StoredScheduledRequest>;
57
+ //# sourceMappingURL=signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/scheduling/signing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ import { sign as ed25519Sign, timingSafeEqual, verify as ed25519Verify, } from "node:crypto";
2
+ import { canonicalizeJson, sha256Digest } from "./request-store.js";
3
+ export const RUNNER_AUDIENCE = "kadi-harness-runner";
4
+ export class InMemoryReplayGuard {
5
+ claims = new Map();
6
+ now;
7
+ constructor(now = Date.now) {
8
+ this.now = now;
9
+ }
10
+ async claim(idempotencyKey, expiresAt) {
11
+ const now = this.now();
12
+ for (const [key, expiry] of this.claims) {
13
+ if (expiry <= now)
14
+ this.claims.delete(key);
15
+ }
16
+ if (this.claims.has(idempotencyKey))
17
+ return false;
18
+ this.claims.set(idempotencyKey, Date.parse(expiresAt));
19
+ return true;
20
+ }
21
+ }
22
+ export class ScheduledRequestSigningError extends Error {
23
+ code;
24
+ constructor(code, message) {
25
+ super(message);
26
+ this.name = "ScheduledRequestSigningError";
27
+ this.code = code;
28
+ }
29
+ }
30
+ function canonicalClaims(input) {
31
+ return JSON.stringify({
32
+ audience: input.audience,
33
+ createdAt: input.createdAt,
34
+ expiresAt: input.expiresAt,
35
+ idempotencyKey: input.idempotencyKey,
36
+ keyId: input.keyId,
37
+ payloadDigest: input.payloadDigest,
38
+ requestRef: input.requestRef,
39
+ });
40
+ }
41
+ function cryptoBytes(value, encoding = "utf8") {
42
+ const source = Buffer.from(value, encoding);
43
+ const copy = new Uint8Array(source.byteLength);
44
+ copy.set(source);
45
+ return copy;
46
+ }
47
+ function asIso(value, field) {
48
+ const date = value instanceof Date ? value : new Date(value);
49
+ if (Number.isNaN(date.getTime()))
50
+ throw new ScheduledRequestSigningError("invalid_envelope", `${field} must be a valid date`);
51
+ return date.toISOString();
52
+ }
53
+ function constantTimeEqual(left, right) {
54
+ const a = cryptoBytes(left);
55
+ const b = cryptoBytes(right);
56
+ return a.length === b.length && timingSafeEqual(a, b);
57
+ }
58
+ function resolveIdempotencyKey(spec, options, requestRef) {
59
+ const key = options.idempotencyKey ?? spec.run.idempotencyKey ??
60
+ `${spec.idempotencyPrefix}:${options.firingId ?? spec.scheduleId ?? requestRef}`;
61
+ if (!key || key.length > 512)
62
+ throw new ScheduledRequestSigningError("invalid_envelope", "idempotency key is required and must be <= 512 characters");
63
+ return key;
64
+ }
65
+ export async function createSignedScheduledRequest(store, keyProvider, spec, options) {
66
+ const stored = await store.put(spec, { requestRef: options.requestRef, createdAt: options.createdAt instanceof Date ? options.createdAt : options.createdAt ? new Date(options.createdAt) : undefined });
67
+ const key = await keyProvider.getActiveKey();
68
+ if (!key.keyId || !key.privateKey)
69
+ throw new ScheduledRequestSigningError("invalid_envelope", "active signing key must include keyId and privateKey");
70
+ const audience = options.audience ?? RUNNER_AUDIENCE;
71
+ const createdAt = stored.createdAt;
72
+ const expiresAt = asIso(options.expiresAt, "expiresAt");
73
+ if (Date.parse(expiresAt) <= Date.parse(createdAt))
74
+ throw new ScheduledRequestSigningError("invalid_envelope", "expiresAt must be after createdAt");
75
+ const idempotencyKey = resolveIdempotencyKey(spec, options, stored.requestRef);
76
+ const claims = canonicalClaims({
77
+ requestRef: stored.requestRef,
78
+ payloadDigest: stored.payloadDigest,
79
+ keyId: key.keyId,
80
+ audience,
81
+ createdAt,
82
+ expiresAt,
83
+ idempotencyKey,
84
+ });
85
+ const signature = ed25519Sign(null, cryptoBytes(claims), key.privateKey).toString("base64url");
86
+ return {
87
+ stored,
88
+ reference: { requestRef: stored.requestRef, payloadDigest: stored.payloadDigest, keyId: key.keyId, audience, createdAt, expiresAt, idempotencyKey, signature },
89
+ };
90
+ }
91
+ export async function verifySignedScheduledRequest(reference, options) {
92
+ const audience = options.audience ?? RUNNER_AUDIENCE;
93
+ if (reference.audience !== audience)
94
+ throw new ScheduledRequestSigningError("wrong_audience", `expected audience ${audience}`);
95
+ if (!reference.requestRef || !reference.payloadDigest || !reference.keyId || !reference.signature || !reference.idempotencyKey) {
96
+ throw new ScheduledRequestSigningError("invalid_envelope", "signed request is missing required fields");
97
+ }
98
+ const expiresAt = Date.parse(reference.expiresAt);
99
+ const createdAt = Date.parse(reference.createdAt);
100
+ const now = (options.now ?? (() => new Date()))().getTime();
101
+ if (!Number.isFinite(createdAt) || !Number.isFinite(expiresAt) || expiresAt <= createdAt) {
102
+ throw new ScheduledRequestSigningError("invalid_envelope", "signed request has invalid timestamps");
103
+ }
104
+ if (createdAt > now)
105
+ throw new ScheduledRequestSigningError("invalid_envelope", "scheduled request was created in the future");
106
+ if (expiresAt <= now)
107
+ throw new ScheduledRequestSigningError("expired", "scheduled request has expired");
108
+ const stored = await options.store.get(reference.requestRef);
109
+ if (!stored)
110
+ throw new ScheduledRequestSigningError("request_not_found", `request reference not found: ${reference.requestRef}`);
111
+ try {
112
+ const canonicalPayload = canonicalizeJson(stored.spec);
113
+ if (canonicalPayload !== stored.canonicalPayload ||
114
+ !constantTimeEqual(sha256Digest(canonicalPayload), stored.payloadDigest) ||
115
+ !constantTimeEqual(stored.payloadDigest, reference.payloadDigest)) {
116
+ throw new ScheduledRequestSigningError("payload_mismatch", "stored request contents do not match the signed digest");
117
+ }
118
+ }
119
+ catch (error) {
120
+ if (error instanceof ScheduledRequestSigningError)
121
+ throw error;
122
+ throw new ScheduledRequestSigningError("payload_mismatch", "stored request contents are invalid");
123
+ }
124
+ const publicKey = await options.keyProvider.getPublicKey(reference.keyId);
125
+ if (!publicKey)
126
+ throw new ScheduledRequestSigningError("unknown_key", `unknown signing key: ${reference.keyId}`);
127
+ const claims = canonicalClaims(reference);
128
+ let valid = false;
129
+ try {
130
+ valid = ed25519Verify(null, cryptoBytes(claims), publicKey, cryptoBytes(reference.signature, "base64url"));
131
+ }
132
+ catch {
133
+ valid = false;
134
+ }
135
+ if (!valid)
136
+ throw new ScheduledRequestSigningError("invalid_signature", "signed request signature is invalid");
137
+ if (!(await options.replayGuard.claim(reference.idempotencyKey, reference.expiresAt))) {
138
+ throw new ScheduledRequestSigningError("replayed", `idempotency key already consumed: ${reference.idempotencyKey}`);
139
+ }
140
+ return stored;
141
+ }
142
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.js","sourceRoot":"","sources":["../../src/scheduling/signing.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "kadi-harness-runtime",
3
+ "version": "0.1.8",
4
+ "description": "Frontend-neutral KADI harness execution runtime API",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "kadi-harness-runner": "./dist/runner/cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "clean": "rm -rf dist",
24
+ "typecheck": "tsc --noEmit",
25
+ "test": "vitest run"
26
+ },
27
+ "keywords": [
28
+ "kadi",
29
+ "harness",
30
+ "runtime",
31
+ "adapter",
32
+ "execution"
33
+ ],
34
+ "author": "KADI Team",
35
+ "license": "MIT",
36
+ "devDependencies": {
37
+ "@types/node": "^20.0.0",
38
+ "typescript": "^5.9.2",
39
+ "vitest": "^3.2.7"
40
+ },
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ },
44
+ "dependencies": {
45
+ "@kadi.build/kadi-harness-contracts": "^0.1.4"
46
+ }
47
+ }