@rogatio/cli 1.9.0 → 2.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.
@@ -14,6 +14,1160 @@ var __export = (target, all) => {
14
14
  __defProp(target, name, { get: all[name], enumerable: true });
15
15
  };
16
16
 
17
+ // packages/schema/dist/node/index.js
18
+ import { Ajv2020 } from "ajv/dist/2020.js";
19
+ function hasControl(value) {
20
+ for (let index = 0; index < value.length; index += 1) {
21
+ const code = value.charCodeAt(index);
22
+ if (code <= 31 || code === 127) return true;
23
+ }
24
+ return false;
25
+ }
26
+ function formatSha256(hex) {
27
+ return `sha256:${hex}`;
28
+ }
29
+ function isSha256Digest(value) {
30
+ return /^sha256:[0-9a-f]{64}$/.test(value);
31
+ }
32
+ function isForbiddenHeader(name, direction) {
33
+ const normalized = name.toLowerCase();
34
+ const forbidden = direction === "request" ? FORBIDDEN_REQUEST_HEADERS : FORBIDDEN_RESPONSE_HEADERS;
35
+ return forbidden.includes(normalized) || direction === "request" && FORBIDDEN_REQUEST_PREFIXES.some(
36
+ (prefix) => normalized.startsWith(prefix)
37
+ );
38
+ }
39
+ function normalizeSiteOrigin(value) {
40
+ if (typeof value !== "string" || value.length === 0 || value.trim() !== value)
41
+ return null;
42
+ if (value.includes("?") || value.includes("#")) return null;
43
+ const match = /^(https?):\/\/([^/?#\\\s]+)(\/)?$/i.exec(value);
44
+ if (!match || match[2].includes("@")) return null;
45
+ let url;
46
+ try {
47
+ url = new URL(value);
48
+ } catch {
49
+ return null;
50
+ }
51
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
52
+ if (url.origin === "null" || url.hostname.length === 0) return null;
53
+ if (url.username.length > 0 || url.password.length > 0) return null;
54
+ if (url.hostname.includes("*")) return null;
55
+ if (url.hostname.endsWith(".")) return null;
56
+ if (url.pathname !== "/") return null;
57
+ return url.origin;
58
+ }
59
+ function isSiteOrigin(value) {
60
+ return typeof value === "string" && normalizeSiteOrigin(value) !== null;
61
+ }
62
+ function compileUrlRegex(value) {
63
+ if (typeof value !== "string" || value.length === 0 || value.length > LIMITS.maxUrlRegexLength)
64
+ return null;
65
+ try {
66
+ return new RegExp(value);
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+ function ajvIssues(errors) {
72
+ return (errors ?? []).map((error) => ({
73
+ instancePath: error.instancePath,
74
+ keyword: error.keyword,
75
+ message: error.message ?? "validation failed",
76
+ params: error.params
77
+ }));
78
+ }
79
+ function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
80
+ if (value === null || typeof value !== "object") {
81
+ return { valid: true, value };
82
+ }
83
+ if (ancestors.has(value)) return { valid: false };
84
+ ancestors.add(value);
85
+ try {
86
+ if (Object.getOwnPropertySymbols(value).length > 0) {
87
+ return { valid: false };
88
+ }
89
+ if (Array.isArray(value)) {
90
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
91
+ if (lengthDescriptor === void 0 || !("value" in lengthDescriptor) || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0 || lengthDescriptor.value > LIMITS.maxRulesPerProject) {
92
+ return { valid: false };
93
+ }
94
+ const length = lengthDescriptor.value;
95
+ for (const propertyName of Object.getOwnPropertyNames(value)) {
96
+ if (propertyName === "length") continue;
97
+ const index = Number(propertyName);
98
+ if (!Number.isInteger(index) || index < 0 || index >= length || String(index) !== propertyName) {
99
+ return { valid: false };
100
+ }
101
+ }
102
+ const snapshot2 = new Array(length);
103
+ for (let index = 0; index < length; index += 1) {
104
+ const descriptor = Object.getOwnPropertyDescriptor(
105
+ value,
106
+ String(index)
107
+ );
108
+ if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
109
+ return { valid: false };
110
+ }
111
+ const child = snapshotOwnData(descriptor.value, ancestors);
112
+ if (!child.valid) return child;
113
+ snapshot2[index] = child.value;
114
+ }
115
+ return { valid: true, value: snapshot2 };
116
+ }
117
+ const snapshot = /* @__PURE__ */ Object.create(null);
118
+ for (const key of Object.getOwnPropertyNames(value)) {
119
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
120
+ if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
121
+ return { valid: false };
122
+ }
123
+ const child = snapshotOwnData(descriptor.value, ancestors);
124
+ if (!child.valid) return child;
125
+ Object.defineProperty(snapshot, key, {
126
+ configurable: true,
127
+ enumerable: true,
128
+ value: child.value,
129
+ writable: true
130
+ });
131
+ }
132
+ return { valid: true, value: snapshot };
133
+ } catch {
134
+ return { valid: false };
135
+ } finally {
136
+ ancestors.delete(value);
137
+ }
138
+ }
139
+ function semanticIssues(project) {
140
+ const issues = [];
141
+ const ids = /* @__PURE__ */ new Map();
142
+ let ruleCount = 0;
143
+ for (let groupIndex = 0; groupIndex < project.groups.length; groupIndex += 1) {
144
+ const group = project.groups[groupIndex];
145
+ const groupPath = `/groups/${groupIndex}`;
146
+ const existingGroup = ids.get(group.id);
147
+ if (existingGroup) {
148
+ issues.push({
149
+ instancePath: `${groupPath}/id`,
150
+ keyword: "uniqueId",
151
+ message: `must be unique; already used at ${existingGroup}`,
152
+ params: { previousPath: existingGroup }
153
+ });
154
+ } else {
155
+ ids.set(group.id, `${groupPath}/id`);
156
+ }
157
+ for (let ruleIndex = 0; ruleIndex < group.rules.length; ruleIndex += 1) {
158
+ let hasLoneSurrogate22 = function(value) {
159
+ for (let i = 0; i < value.length; i += 1) {
160
+ const code = value.charCodeAt(i);
161
+ if (code >= 55296 && code <= 56319) {
162
+ if (i + 1 >= value.length) return true;
163
+ const next = value.charCodeAt(i + 1);
164
+ if (next < 56320 || next > 57343) return true;
165
+ } else if (code >= 56320 && code <= 57343) {
166
+ if (i === 0) return true;
167
+ const prev = value.charCodeAt(i - 1);
168
+ if (prev < 55296 || prev > 56319) return true;
169
+ }
170
+ }
171
+ return false;
172
+ };
173
+ var hasLoneSurrogate3 = hasLoneSurrogate22;
174
+ const rule = group.rules[ruleIndex];
175
+ ruleCount += 1;
176
+ const rulePath = `${groupPath}/rules/${ruleIndex}`;
177
+ const existingRule = ids.get(rule.id);
178
+ if (existingRule) {
179
+ issues.push({
180
+ instancePath: `${rulePath}/id`,
181
+ keyword: "uniqueId",
182
+ message: `must be unique; already used at ${existingRule}`,
183
+ params: { previousPath: existingRule }
184
+ });
185
+ } else {
186
+ ids.set(rule.id, `${rulePath}/id`);
187
+ }
188
+ if (rule.type !== void 0 && rule.type !== "redirect" && rule.type !== "query" && rule.type !== "header" && rule.type !== "mock" && rule.type !== "response-body" && rule.type !== "request-body") {
189
+ issues.push({
190
+ instancePath: `${rulePath}/type`,
191
+ keyword: "enum",
192
+ message: 'must be "redirect", "query", "header", "mock", "response-body", or "request-body"',
193
+ params: {
194
+ allowedValues: [
195
+ "redirect",
196
+ "query",
197
+ "header",
198
+ "mock",
199
+ "response-body",
200
+ "request-body"
201
+ ]
202
+ }
203
+ });
204
+ }
205
+ if (rule.type === "redirect") {
206
+ const destination = rule.redirect !== void 0 ? rule.redirect.destination : void 0;
207
+ if (rule.redirect === void 0 || typeof destination !== "string") {
208
+ issues.push({
209
+ instancePath: `${rulePath}/redirect/destination`,
210
+ keyword: "required",
211
+ message: "Redirect rules require a destination string.",
212
+ params: {}
213
+ });
214
+ } else {
215
+ for (const issue of validateRedirectDestination(
216
+ destination,
217
+ rule.urlRegex
218
+ )) {
219
+ issues.push({
220
+ instancePath: `${rulePath}/redirect/destination`,
221
+ keyword: issue.code,
222
+ message: issue.message,
223
+ params: {}
224
+ });
225
+ }
226
+ }
227
+ }
228
+ const effectiveOrigins = /* @__PURE__ */ new Set();
229
+ for (let originIndex = 0; originIndex < group.origins.length; originIndex += 1) {
230
+ const origin = normalizeSiteOrigin(group.origins[originIndex]);
231
+ if (origin !== null) effectiveOrigins.add(origin);
232
+ }
233
+ for (let originIndex = 0; originIndex < rule.origins.length; originIndex += 1) {
234
+ const origin = normalizeSiteOrigin(rule.origins[originIndex]);
235
+ if (origin !== null) effectiveOrigins.add(origin);
236
+ }
237
+ if (effectiveOrigins.size === 0) {
238
+ issues.push({
239
+ instancePath: `${rulePath}/origins`,
240
+ keyword: "effectiveOrigin",
241
+ message: "must combine with group origins to contain at least one origin",
242
+ params: {}
243
+ });
244
+ }
245
+ const action = rule.action;
246
+ if (action && "type" in action && action.type === "query") {
247
+ const seenNames = /* @__PURE__ */ new Set();
248
+ for (let p = 0; p < action.params.length; p += 1) {
249
+ const param = action.params[p];
250
+ if (!param) continue;
251
+ const paramName = param.name;
252
+ if (seenNames.has(paramName)) {
253
+ issues.push({
254
+ instancePath: `${rulePath}/action/params/${p}/name`,
255
+ keyword: "uniqueQueryParamName",
256
+ message: `query param name must be unique; duplicate "${paramName}"`,
257
+ params: { name: paramName }
258
+ });
259
+ } else {
260
+ seenNames.add(paramName);
261
+ }
262
+ }
263
+ }
264
+ if (rule.type === "header" && rule.headerName !== void 0) {
265
+ const direction = rule.headerDirection ?? "request";
266
+ if (isForbiddenHeader(rule.headerName, direction)) {
267
+ issues.push({
268
+ instancePath: `${rulePath}/headerName`,
269
+ keyword: "forbiddenHeader",
270
+ message: `Header "${rule.headerName}" is forbidden for ${direction} headers.`,
271
+ params: {
272
+ headerName: rule.headerName,
273
+ headerDirection: direction
274
+ }
275
+ });
276
+ }
277
+ }
278
+ if (rule.type === "response-body") {
279
+ const action2 = rule.responseBody;
280
+ const actionPath = `${rulePath}/responseBody`;
281
+ if (!action2 || !Array.isArray(action2.replacements) || action2.replacements.length === 0) {
282
+ issues.push({
283
+ instancePath: `${actionPath}/replacements`,
284
+ keyword: "response-body-replacements",
285
+ message: "A response-body rule must define at least one replacement.",
286
+ params: {}
287
+ });
288
+ } else {
289
+ for (let index = 0; index < action2.replacements.length; index += 1) {
290
+ const replacement = action2.replacements[index];
291
+ if (compileUrlRegex(replacement.pattern) === null) {
292
+ issues.push({
293
+ instancePath: `${actionPath}/replacements/${index}/pattern`,
294
+ keyword: "response-body-pattern",
295
+ message: "Response-body replacement patterns must be valid regular expressions.",
296
+ params: {}
297
+ });
298
+ }
299
+ }
300
+ }
301
+ }
302
+ if (rule.type === "request-body") {
303
+ const action2 = rule.requestBody;
304
+ const actionPath = `${rulePath}/requestBody`;
305
+ if (!action2) {
306
+ issues.push({
307
+ instancePath: actionPath,
308
+ keyword: "request-body-action",
309
+ message: "A request-body rule must define a requestBody action.",
310
+ params: {}
311
+ });
312
+ } else {
313
+ const mode = action2.mode;
314
+ if (mode !== "replace" && mode !== "regex") {
315
+ issues.push({
316
+ instancePath: `${actionPath}/mode`,
317
+ keyword: "request-body-mode",
318
+ message: 'requestBody.mode must be "replace" or "regex"',
319
+ params: { mode }
320
+ });
321
+ }
322
+ if (action2.mode === "replace") {
323
+ if (typeof action2.body !== "string") {
324
+ issues.push({
325
+ instancePath: `${actionPath}/body`,
326
+ keyword: "request-body-replace-body",
327
+ message: "Replace mode requires a body string.",
328
+ params: {}
329
+ });
330
+ } else if (action2.body.length > LIMITS.maxRequestBodyBytes) {
331
+ issues.push({
332
+ instancePath: `${actionPath}/body`,
333
+ keyword: "request-body-replace-body",
334
+ message: `Replace body exceeds the maximum size of ${LIMITS.maxRequestBodyBytes} bytes.`,
335
+ params: { limit: LIMITS.maxRequestBodyBytes }
336
+ });
337
+ } else if (hasLoneSurrogate22(action2.body)) {
338
+ issues.push({
339
+ instancePath: `${actionPath}/body`,
340
+ keyword: "request-body-lone-surrogate",
341
+ message: "Replace body must not contain lone UTF-16 surrogates.",
342
+ params: {}
343
+ });
344
+ }
345
+ }
346
+ if (action2.mode === "regex") {
347
+ if (typeof action2.pattern !== "string" || action2.pattern.length === 0) {
348
+ issues.push({
349
+ instancePath: `${actionPath}/pattern`,
350
+ keyword: "request-body-pattern",
351
+ message: "Regex mode requires a non-empty pattern string.",
352
+ params: {}
353
+ });
354
+ } else if (action2.pattern.length > LIMITS.maxRequestBodyPatternLength) {
355
+ issues.push({
356
+ instancePath: `${actionPath}/pattern`,
357
+ keyword: "request-body-pattern",
358
+ message: `Regex pattern exceeds the maximum length of ${LIMITS.maxRequestBodyPatternLength} characters.`,
359
+ params: { limit: LIMITS.maxRequestBodyPatternLength }
360
+ });
361
+ } else if (compileUrlRegex(action2.pattern) === null) {
362
+ issues.push({
363
+ instancePath: `${actionPath}/pattern`,
364
+ keyword: "request-body-pattern",
365
+ message: "Regex pattern must be a valid regular expression.",
366
+ params: {}
367
+ });
368
+ }
369
+ if (typeof action2.replacement !== "string" || action2.replacement.length > LIMITS.maxRequestBodyReplacementLength) {
370
+ issues.push({
371
+ instancePath: `${actionPath}/replacement`,
372
+ keyword: "request-body-replacement",
373
+ message: `Regex replacement exceeds the maximum length of ${LIMITS.maxRequestBodyReplacementLength} characters.`,
374
+ params: { limit: LIMITS.maxRequestBodyReplacementLength }
375
+ });
376
+ } else if (hasLoneSurrogate22(action2.pattern)) {
377
+ issues.push({
378
+ instancePath: `${actionPath}/pattern`,
379
+ keyword: "request-body-lone-surrogate",
380
+ message: "Regex pattern must not contain lone UTF-16 surrogates.",
381
+ params: {}
382
+ });
383
+ } else if (hasLoneSurrogate22(action2.replacement)) {
384
+ issues.push({
385
+ instancePath: `${actionPath}/replacement`,
386
+ keyword: "request-body-lone-surrogate",
387
+ message: "Regex replacement must not contain lone UTF-16 surrogates.",
388
+ params: {}
389
+ });
390
+ }
391
+ }
392
+ }
393
+ if (rule.method !== "POST" && rule.method !== "PUT" && rule.method !== "PATCH") {
394
+ issues.push({
395
+ instancePath: `${rulePath}/method`,
396
+ keyword: "request-body-method",
397
+ message: 'Request-body rules require method "POST", "PUT", or "PATCH".',
398
+ params: { method: rule.method }
399
+ });
400
+ }
401
+ const resourceTypes = rule.resourceTypes;
402
+ if (!Array.isArray(resourceTypes) || resourceTypes.length !== 1 || resourceTypes[0] !== "xmlhttprequest") {
403
+ issues.push({
404
+ instancePath: `${rulePath}/resourceTypes`,
405
+ keyword: "request-body-resource-types",
406
+ message: 'Request-body rules require exactly one resource type: "xmlhttprequest".',
407
+ params: { resourceTypes }
408
+ });
409
+ }
410
+ }
411
+ if (rule.type === "mock") {
412
+ const mock = rule.mock;
413
+ const mockPath = `${rulePath}/mock`;
414
+ const bodySet = mock?.body !== void 0;
415
+ const fileSet = mock?.file !== void 0;
416
+ if (bodySet === fileSet) {
417
+ issues.push({
418
+ instancePath: mockPath,
419
+ keyword: "mock-body-source",
420
+ message: "A mock rule must set exactly one of body or file.",
421
+ params: {}
422
+ });
423
+ }
424
+ if (mock?.headers !== void 0) {
425
+ for (let h = 0; h < mock.headers.length; h += 1) {
426
+ const header = mock.headers[h];
427
+ if (header === void 0) continue;
428
+ if (hasControl(header.name) || header.name.includes(":")) {
429
+ issues.push({
430
+ instancePath: `${mockPath}/headers/${h}/name`,
431
+ keyword: "mock-header-name",
432
+ message: "Mock header names must not contain control characters or ':'.",
433
+ params: {}
434
+ });
435
+ }
436
+ }
437
+ }
438
+ if (mock?.file !== void 0 && hasControl(mock.file)) {
439
+ issues.push({
440
+ instancePath: `${mockPath}/file`,
441
+ keyword: "mock-file-path",
442
+ message: "Mock file paths must not contain control characters.",
443
+ params: {}
444
+ });
445
+ }
446
+ }
447
+ }
448
+ }
449
+ if (project.requestBodyPolicy !== void 0) {
450
+ const policy = project.requestBodyPolicy;
451
+ if (typeof policy.localOrigins !== "undefined") {
452
+ if (!Array.isArray(policy.localOrigins)) {
453
+ issues.push({
454
+ instancePath: "/requestBodyPolicy/localOrigins",
455
+ keyword: "request-body-policy-local-origins",
456
+ message: "localOrigins must be an array.",
457
+ params: {}
458
+ });
459
+ } else {
460
+ const seen = /* @__PURE__ */ new Set();
461
+ for (let i = 0; i < policy.localOrigins.length; i += 1) {
462
+ const origin = policy.localOrigins[i];
463
+ if (typeof origin !== "string") {
464
+ issues.push({
465
+ instancePath: `/requestBodyPolicy/localOrigins/${i}`,
466
+ keyword: "request-body-policy-local-origin",
467
+ message: "Each local origin must be a string.",
468
+ params: {}
469
+ });
470
+ continue;
471
+ }
472
+ const normalized = normalizeSiteOrigin(origin);
473
+ if (normalized === null) {
474
+ issues.push({
475
+ instancePath: `/requestBodyPolicy/localOrigins/${i}`,
476
+ keyword: "request-body-policy-local-origin",
477
+ message: "Each local origin must be a valid exact HTTP(S) origin with no credentials, path, query, fragment, wildcard, backslash, invalid port, or trailing-dot hostname.",
478
+ params: { origin }
479
+ });
480
+ } else if (seen.has(normalized)) {
481
+ issues.push({
482
+ instancePath: `/requestBodyPolicy/localOrigins/${i}`,
483
+ keyword: "request-body-policy-local-origin",
484
+ message: "Local origins must be unique.",
485
+ params: { origin: normalized }
486
+ });
487
+ } else {
488
+ seen.add(normalized);
489
+ }
490
+ }
491
+ if (policy.localOrigins.length > LIMITS.maxLocalOrigins) {
492
+ issues.push({
493
+ instancePath: "/requestBodyPolicy/localOrigins",
494
+ keyword: "request-body-policy-local-origins",
495
+ message: `localOrigins must contain at most ${LIMITS.maxLocalOrigins} entries.`,
496
+ params: { limit: LIMITS.maxLocalOrigins }
497
+ });
498
+ }
499
+ }
500
+ }
501
+ }
502
+ if (ruleCount > LIMITS.maxRulesPerProject) {
503
+ issues.push({
504
+ instancePath: "/groups",
505
+ keyword: "maxRulesPerProject",
506
+ message: `must contain at most ${LIMITS.maxRulesPerProject} rules in total`,
507
+ params: { limit: LIMITS.maxRulesPerProject, actual: ruleCount }
508
+ });
509
+ }
510
+ return issues;
511
+ }
512
+ function skipBalancedGroup(source, start) {
513
+ let depth = 0;
514
+ let index = start;
515
+ const length = source.length;
516
+ while (index < length) {
517
+ const char = source[index];
518
+ if (char === "\\") {
519
+ index += 2;
520
+ continue;
521
+ }
522
+ if (char === "(") {
523
+ depth += 1;
524
+ } else if (char === ")") {
525
+ depth -= 1;
526
+ if (depth === 0) return index;
527
+ }
528
+ index += 1;
529
+ }
530
+ return length;
531
+ }
532
+ function countCapturingGroups(urlRegex) {
533
+ let count = 0;
534
+ let index = 0;
535
+ const length = urlRegex.length;
536
+ while (index < length) {
537
+ const char = urlRegex[index];
538
+ if (char === "\\") {
539
+ index += 2;
540
+ continue;
541
+ }
542
+ if (char === "(") {
543
+ if (urlRegex[index + 1] === "?") {
544
+ index = skipBalancedGroup(urlRegex, index);
545
+ continue;
546
+ }
547
+ count += 1;
548
+ }
549
+ index += 1;
550
+ }
551
+ return count;
552
+ }
553
+ function validateRedirectDestination(destination, urlRegex) {
554
+ const issues = [];
555
+ if (typeof destination !== "string" || destination.length === 0) {
556
+ issues.push({
557
+ code: "schema.required",
558
+ message: "Redirect destination must be a non-empty string."
559
+ });
560
+ return issues;
561
+ }
562
+ if (destination.length > LIMITS.maxRedirectDestinationLength) {
563
+ issues.push({
564
+ code: "schema.out-of-range",
565
+ message: `Redirect destination must be at most ${LIMITS.maxRedirectDestinationLength} characters.`
566
+ });
567
+ return issues;
568
+ }
569
+ let url;
570
+ try {
571
+ url = new URL(destination);
572
+ } catch {
573
+ issues.push({
574
+ code: "schema.invalid-format",
575
+ message: "Redirect destination must be an absolute URL."
576
+ });
577
+ return issues;
578
+ }
579
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
580
+ issues.push({
581
+ code: "schema.invalid-value",
582
+ message: "Redirect destination must use the http or https scheme."
583
+ });
584
+ return issues;
585
+ }
586
+ if (url.username.length > 0 || url.password.length > 0) {
587
+ issues.push({
588
+ code: "schema.invalid-value",
589
+ message: "Redirect destination must not contain credentials."
590
+ });
591
+ return issues;
592
+ }
593
+ if (url.hostname.length === 0 || url.hostname.includes("*")) {
594
+ issues.push({
595
+ code: "schema.invalid-format",
596
+ message: "Redirect destination must have a valid host."
597
+ });
598
+ return issues;
599
+ }
600
+ const groups = countCapturingGroups(urlRegex);
601
+ const backreference = /\\([1-9])/g;
602
+ let match = backreference.exec(destination);
603
+ while (match !== null) {
604
+ const referenced = Number(match[1]);
605
+ if (referenced > groups) {
606
+ issues.push({
607
+ code: "schema.invalid-value",
608
+ message: `Redirect destination references capture group ${referenced} but the URL pattern defines ${groups}.`
609
+ });
610
+ }
611
+ match = backreference.exec(destination);
612
+ }
613
+ return issues;
614
+ }
615
+ function validateProjectDetailed(value) {
616
+ const snapshot = snapshotOwnData(value);
617
+ if (!snapshot.valid) {
618
+ return {
619
+ valid: false,
620
+ errors: [
621
+ {
622
+ instancePath: "",
623
+ keyword: "ownProperties",
624
+ message: "must contain only own array entries",
625
+ params: {}
626
+ }
627
+ ]
628
+ };
629
+ }
630
+ if (!projectValidator(snapshot.value)) {
631
+ return { valid: false, errors: ajvIssues(projectValidator.errors) };
632
+ }
633
+ const errors = semanticIssues(snapshot.value);
634
+ return errors.length > 0 ? { valid: false, errors } : { valid: true, data: value };
635
+ }
636
+ var FORBIDDEN_REQUEST_HEADERS, FORBIDDEN_RESPONSE_HEADERS, FORBIDDEN_REQUEST_PREFIXES, LIMITS, PROJECT_VERSION, RESOURCE_TYPES, HTTP_METHODS, label, id, projectSchemaDefinition, projectSchema, ajv, compiledProjectValidator, ownArrayEntriesError, guardedProjectValidator, projectValidator;
637
+ var init_node = __esm({
638
+ "packages/schema/dist/node/index.js"() {
639
+ "use strict";
640
+ FORBIDDEN_REQUEST_HEADERS = Object.freeze([
641
+ "accept-charset",
642
+ "accept-encoding",
643
+ "access-control-request-headers",
644
+ "access-control-request-method",
645
+ "connection",
646
+ "content-length",
647
+ "cookie",
648
+ "cookie2",
649
+ "date",
650
+ "dnt",
651
+ "expect",
652
+ "host",
653
+ "keep-alive",
654
+ "origin",
655
+ "proxy-authenticate",
656
+ "proxy-authorization",
657
+ "te",
658
+ "trailer",
659
+ "transfer-encoding",
660
+ "upgrade",
661
+ "via"
662
+ ]);
663
+ FORBIDDEN_RESPONSE_HEADERS = Object.freeze([
664
+ "connection",
665
+ "content-encoding",
666
+ "content-length",
667
+ "date",
668
+ "keep-alive",
669
+ "proxy-authenticate",
670
+ "proxy-authorization",
671
+ "set-cookie",
672
+ "set-cookie2",
673
+ "te",
674
+ "trailer",
675
+ "transfer-encoding",
676
+ "upgrade",
677
+ "via"
678
+ ]);
679
+ FORBIDDEN_REQUEST_PREFIXES = Object.freeze(["proxy-", "sec-"]);
680
+ LIMITS = Object.freeze({
681
+ maxGroups: 64,
682
+ maxRulesPerGroup: 256,
683
+ maxRulesPerProject: 4096,
684
+ maxOriginsPerScope: 32,
685
+ maxIdLength: 64,
686
+ maxLabelLength: 100,
687
+ maxDescriptionLength: 1e3,
688
+ maxUrlRegexLength: 2048,
689
+ maxResourceTypesPerRule: 16,
690
+ minPriority: 1,
691
+ maxPriority: 1e3,
692
+ maxRedirectDestinationLength: 2048,
693
+ maxCaptureGroups: 9,
694
+ maxQueryParamsPerRule: 64,
695
+ maxQueryNameLength: 256,
696
+ maxQueryValueLength: 2048,
697
+ maxHeaderNameLength: 256,
698
+ maxHeaderValueLength: 4096,
699
+ minMockStatus: 200,
700
+ maxMockStatus: 599,
701
+ maxMockHeadersPerRule: 32,
702
+ maxMockHeaderNameLength: 256,
703
+ maxMockHeaderValueLength: 4096,
704
+ maxMockInlineBodyLength: 65536,
705
+ maxMockDelayMs: 3e4,
706
+ maxMockFilePathLength: 2048,
707
+ maxResponseBodyReplacements: 64,
708
+ maxResponseBodyPatternLength: 2048,
709
+ maxResponseBodyReplacementLength: 4096,
710
+ maxRequestBodyBytes: 4 * 1024 * 1024,
711
+ maxRequestBodyPatternLength: 2048,
712
+ maxRequestBodyReplacementLength: 4096,
713
+ maxRequestBodyOperations: 32,
714
+ maxLocalOrigins: 32
715
+ });
716
+ PROJECT_VERSION = 1;
717
+ RESOURCE_TYPES = Object.freeze([
718
+ "main_frame",
719
+ "sub_frame",
720
+ "stylesheet",
721
+ "script",
722
+ "image",
723
+ "font",
724
+ "object",
725
+ "media",
726
+ "xmlhttprequest",
727
+ "ping",
728
+ "csp_report",
729
+ "websocket",
730
+ "webtransport",
731
+ "webbundle",
732
+ "other"
733
+ ]);
734
+ HTTP_METHODS = Object.freeze([
735
+ "GET",
736
+ "POST",
737
+ "PUT",
738
+ "PATCH",
739
+ "DELETE",
740
+ "HEAD",
741
+ "OPTIONS",
742
+ "CONNECT",
743
+ "TRACE"
744
+ ]);
745
+ label = {
746
+ type: "string",
747
+ minLength: 1,
748
+ maxLength: LIMITS.maxLabelLength,
749
+ pattern: "\\S"
750
+ };
751
+ id = {
752
+ type: "string",
753
+ minLength: 1,
754
+ maxLength: LIMITS.maxIdLength,
755
+ pattern: "^[A-Za-z0-9][A-Za-z0-9._-]*$"
756
+ };
757
+ projectSchemaDefinition = {
758
+ $schema: "https://json-schema.org/draft/2020-12/schema",
759
+ $id: "https://rogatio.dev/schema/project-v1.json",
760
+ type: "object",
761
+ additionalProperties: false,
762
+ required: ["version", "name", "groups"],
763
+ properties: {
764
+ version: { type: "integer", const: PROJECT_VERSION },
765
+ name: label,
766
+ description: {
767
+ type: "string",
768
+ maxLength: LIMITS.maxDescriptionLength
769
+ },
770
+ groups: {
771
+ type: "array",
772
+ maxItems: LIMITS.maxGroups,
773
+ items: { $ref: "#/$defs/group" }
774
+ },
775
+ requestBodyPolicy: { $ref: "#/$defs/requestBodyPolicyConfig" }
776
+ },
777
+ $defs: {
778
+ group: {
779
+ type: "object",
780
+ additionalProperties: false,
781
+ required: ["id", "name", "origins", "rules"],
782
+ properties: {
783
+ id,
784
+ name: label,
785
+ origins: {
786
+ type: "array",
787
+ maxItems: LIMITS.maxOriginsPerScope,
788
+ uniqueItems: true,
789
+ items: { type: "string", format: "rogatio-origin" }
790
+ },
791
+ rules: {
792
+ type: "array",
793
+ maxItems: LIMITS.maxRulesPerGroup,
794
+ items: { $ref: "#/$defs/rule" }
795
+ }
796
+ }
797
+ },
798
+ rule: {
799
+ type: "object",
800
+ additionalProperties: false,
801
+ required: [
802
+ "id",
803
+ "name",
804
+ "urlRegex",
805
+ "origins",
806
+ "resourceTypes",
807
+ "priority"
808
+ ],
809
+ properties: {
810
+ id,
811
+ name: label,
812
+ urlRegex: {
813
+ type: "string",
814
+ minLength: 1,
815
+ maxLength: LIMITS.maxUrlRegexLength,
816
+ format: "rogatio-url-regex"
817
+ },
818
+ origins: {
819
+ type: "array",
820
+ maxItems: LIMITS.maxOriginsPerScope,
821
+ uniqueItems: true,
822
+ items: { type: "string", format: "rogatio-origin" }
823
+ },
824
+ resourceTypes: {
825
+ type: "array",
826
+ minItems: 1,
827
+ maxItems: LIMITS.maxResourceTypesPerRule,
828
+ uniqueItems: true,
829
+ items: { type: "string", enum: [...RESOURCE_TYPES] }
830
+ },
831
+ priority: {
832
+ type: "integer",
833
+ minimum: LIMITS.minPriority,
834
+ maximum: LIMITS.maxPriority
835
+ },
836
+ method: { type: "string", enum: [...HTTP_METHODS] },
837
+ type: {
838
+ type: "string",
839
+ enum: [
840
+ "redirect",
841
+ "query",
842
+ "header",
843
+ "mock",
844
+ "response-body",
845
+ "request-body"
846
+ ]
847
+ },
848
+ redirect: {
849
+ type: "object",
850
+ additionalProperties: false,
851
+ required: ["destination"],
852
+ properties: {
853
+ destination: { type: "string" }
854
+ }
855
+ },
856
+ action: { $ref: "#/$defs/queryAction" },
857
+ headerDirection: { type: "string", enum: ["request", "response"] },
858
+ headerOperation: { type: "string", enum: ["set", "append", "remove"] },
859
+ headerName: {
860
+ type: "string",
861
+ minLength: 1,
862
+ maxLength: LIMITS.maxHeaderNameLength
863
+ },
864
+ headerValue: {
865
+ type: "string",
866
+ maxLength: LIMITS.maxHeaderValueLength
867
+ },
868
+ mock: { $ref: "#/$defs/mockAction" },
869
+ responseBody: { $ref: "#/$defs/responseBodyAction" },
870
+ requestBody: { $ref: "#/$defs/requestBodyAction" }
871
+ },
872
+ allOf: [
873
+ {
874
+ if: {
875
+ required: ["type"],
876
+ properties: { type: { const: "redirect" } }
877
+ },
878
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
879
+ then: {
880
+ required: ["redirect"]
881
+ }
882
+ },
883
+ {
884
+ if: {
885
+ required: ["type"],
886
+ properties: { type: { const: "query" } }
887
+ },
888
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
889
+ then: {
890
+ required: ["action"]
891
+ }
892
+ },
893
+ {
894
+ if: {
895
+ required: ["type"],
896
+ properties: { type: { const: "header" } }
897
+ },
898
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
899
+ then: {
900
+ required: ["headerDirection", "headerOperation", "headerName"]
901
+ }
902
+ },
903
+ {
904
+ if: {
905
+ required: ["type"],
906
+ properties: { type: { const: "mock" } }
907
+ },
908
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
909
+ then: {
910
+ required: ["mock"]
911
+ }
912
+ },
913
+ {
914
+ if: {
915
+ required: ["type"],
916
+ properties: { type: { const: "response-body" } }
917
+ },
918
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
919
+ then: {
920
+ required: ["responseBody"]
921
+ }
922
+ },
923
+ {
924
+ if: {
925
+ required: ["headerOperation"],
926
+ properties: { headerOperation: { const: "set" } }
927
+ },
928
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
929
+ then: {
930
+ required: ["headerValue"]
931
+ }
932
+ },
933
+ {
934
+ if: {
935
+ required: ["headerOperation"],
936
+ properties: { headerOperation: { const: "append" } }
937
+ },
938
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
939
+ then: {
940
+ required: ["headerValue"]
941
+ }
942
+ },
943
+ {
944
+ if: {
945
+ required: ["type"],
946
+ properties: { type: { const: "response-body" } }
947
+ },
948
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
949
+ then: {
950
+ required: ["responseBody"]
951
+ }
952
+ },
953
+ {
954
+ if: {
955
+ required: ["type"],
956
+ properties: { type: { const: "request-body" } }
957
+ },
958
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
959
+ then: {
960
+ required: ["requestBody", "method", "resourceTypes"]
961
+ }
962
+ }
963
+ ]
964
+ },
965
+ queryParam: {
966
+ type: "object",
967
+ additionalProperties: false,
968
+ required: ["name", "value"],
969
+ properties: {
970
+ name: {
971
+ type: "string",
972
+ minLength: 1,
973
+ maxLength: LIMITS.maxQueryNameLength
974
+ },
975
+ value: {
976
+ type: "string",
977
+ minLength: 1,
978
+ maxLength: LIMITS.maxQueryValueLength
979
+ }
980
+ }
981
+ },
982
+ queryAction: {
983
+ type: "object",
984
+ additionalProperties: false,
985
+ required: ["type", "params"],
986
+ properties: {
987
+ type: { const: "query" },
988
+ params: {
989
+ type: "array",
990
+ minItems: 1,
991
+ maxItems: LIMITS.maxQueryParamsPerRule,
992
+ items: { $ref: "#/$defs/queryParam" }
993
+ }
994
+ }
995
+ },
996
+ mockHeader: {
997
+ type: "object",
998
+ additionalProperties: false,
999
+ required: ["name", "value"],
1000
+ properties: {
1001
+ name: {
1002
+ type: "string",
1003
+ minLength: 1,
1004
+ maxLength: LIMITS.maxMockHeaderNameLength
1005
+ },
1006
+ value: {
1007
+ type: "string",
1008
+ maxLength: LIMITS.maxMockHeaderValueLength
1009
+ }
1010
+ }
1011
+ },
1012
+ mockAction: {
1013
+ type: "object",
1014
+ additionalProperties: false,
1015
+ required: ["status"],
1016
+ properties: {
1017
+ status: {
1018
+ type: "integer",
1019
+ minimum: LIMITS.minMockStatus,
1020
+ maximum: LIMITS.maxMockStatus
1021
+ },
1022
+ headers: {
1023
+ type: "array",
1024
+ maxItems: LIMITS.maxMockHeadersPerRule,
1025
+ items: { $ref: "#/$defs/mockHeader" }
1026
+ },
1027
+ delayMs: {
1028
+ type: "integer",
1029
+ minimum: 0,
1030
+ maximum: LIMITS.maxMockDelayMs
1031
+ },
1032
+ body: {
1033
+ type: "string",
1034
+ maxLength: LIMITS.maxMockInlineBodyLength
1035
+ },
1036
+ file: {
1037
+ type: "string",
1038
+ minLength: 1,
1039
+ maxLength: LIMITS.maxMockFilePathLength
1040
+ }
1041
+ }
1042
+ },
1043
+ responseBodyReplacement: {
1044
+ type: "object",
1045
+ additionalProperties: false,
1046
+ required: ["pattern", "replacement"],
1047
+ properties: {
1048
+ pattern: {
1049
+ type: "string",
1050
+ minLength: 1,
1051
+ maxLength: LIMITS.maxResponseBodyPatternLength,
1052
+ format: "rogatio-url-regex"
1053
+ },
1054
+ replacement: {
1055
+ type: "string",
1056
+ maxLength: LIMITS.maxResponseBodyReplacementLength
1057
+ }
1058
+ }
1059
+ },
1060
+ responseBodyAction: {
1061
+ type: "object",
1062
+ additionalProperties: false,
1063
+ required: ["replacements"],
1064
+ properties: {
1065
+ replacements: {
1066
+ type: "array",
1067
+ minItems: 1,
1068
+ maxItems: LIMITS.maxResponseBodyReplacements,
1069
+ items: { $ref: "#/$defs/responseBodyReplacement" }
1070
+ }
1071
+ }
1072
+ },
1073
+ requestBodyReplaceAction: {
1074
+ type: "object",
1075
+ additionalProperties: false,
1076
+ required: ["mode", "body"],
1077
+ properties: {
1078
+ mode: { const: "replace" },
1079
+ body: {
1080
+ type: "string",
1081
+ maxLength: LIMITS.maxRequestBodyBytes
1082
+ }
1083
+ }
1084
+ },
1085
+ requestBodyRegexAction: {
1086
+ type: "object",
1087
+ additionalProperties: false,
1088
+ required: ["mode", "pattern", "replacement"],
1089
+ properties: {
1090
+ mode: { const: "regex" },
1091
+ pattern: {
1092
+ type: "string",
1093
+ minLength: 1,
1094
+ maxLength: LIMITS.maxRequestBodyPatternLength,
1095
+ format: "rogatio-url-regex"
1096
+ },
1097
+ replacement: {
1098
+ type: "string",
1099
+ maxLength: LIMITS.maxRequestBodyReplacementLength
1100
+ }
1101
+ }
1102
+ },
1103
+ requestBodyAction: {
1104
+ oneOf: [
1105
+ { $ref: "#/$defs/requestBodyReplaceAction" },
1106
+ { $ref: "#/$defs/requestBodyRegexAction" }
1107
+ ]
1108
+ },
1109
+ requestBodyPolicyConfig: {
1110
+ type: "object",
1111
+ additionalProperties: false,
1112
+ properties: {
1113
+ localOrigins: {
1114
+ type: "array",
1115
+ maxItems: LIMITS.maxLocalOrigins,
1116
+ uniqueItems: true,
1117
+ items: { type: "string", format: "rogatio-origin" }
1118
+ }
1119
+ }
1120
+ }
1121
+ }
1122
+ };
1123
+ projectSchema = projectSchemaDefinition;
1124
+ ajv = new Ajv2020({
1125
+ allErrors: true,
1126
+ coerceTypes: false,
1127
+ removeAdditional: false,
1128
+ useDefaults: false,
1129
+ ownProperties: true,
1130
+ // The redirect `then` clause requires `redirect` via `if/then` while the
1131
+ // property is declared on the enclosing rule, which strictRequired forbids.
1132
+ strictRequired: false
1133
+ });
1134
+ ajv.addFormat("rogatio-origin", {
1135
+ type: "string",
1136
+ validate: isSiteOrigin
1137
+ });
1138
+ ajv.addFormat("rogatio-url-regex", {
1139
+ type: "string",
1140
+ validate: (value) => compileUrlRegex(value) !== null
1141
+ });
1142
+ compiledProjectValidator = ajv.compile(projectSchema);
1143
+ ownArrayEntriesError = {
1144
+ instancePath: "",
1145
+ keyword: "ownProperties",
1146
+ message: "must contain only own array entries",
1147
+ params: {},
1148
+ schemaPath: ""
1149
+ };
1150
+ guardedProjectValidator = Object.assign(
1151
+ (value) => {
1152
+ const snapshot = snapshotOwnData(value);
1153
+ if (!snapshot.valid) {
1154
+ guardedProjectValidator.errors = [ownArrayEntriesError];
1155
+ return false;
1156
+ }
1157
+ const valid = compiledProjectValidator(snapshot.value);
1158
+ guardedProjectValidator.errors = compiledProjectValidator.errors ?? null;
1159
+ return valid;
1160
+ },
1161
+ {
1162
+ errors: null,
1163
+ schema: compiledProjectValidator.schema,
1164
+ schemaEnv: compiledProjectValidator.schemaEnv
1165
+ }
1166
+ );
1167
+ projectValidator = guardedProjectValidator;
1168
+ }
1169
+ });
1170
+
17
1171
  // packages/runtime/dist/node/index.js
18
1172
  var node_exports = {};
19
1173
  __export(node_exports, {
@@ -88,42 +1242,22 @@ __export(node_exports, {
88
1242
  verifyMarker: () => verifyMarker
89
1243
  });
90
1244
  import { isIP } from "node:net";
91
- import { HTTP_METHODS as HTTP_METHODS2 } from "@rogatio/schema";
92
- import { hasControl } from "@rogatio/schema";
93
1245
  import { isIP as isIP2 } from "node:net";
94
- import { hasControl as hasControl2, normalizeSiteOrigin } from "@rogatio/schema";
95
1246
  import { constants } from "node:fs";
96
1247
  import { realpath } from "node:fs/promises";
97
1248
  import { isAbsolute, relative } from "node:path";
98
1249
  import { Buffer as Buffer2 } from "node:buffer";
99
1250
  import { createServer as createServer2 } from "node:http";
100
1251
  import { createHash, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
101
- import { isSha256Digest } from "@rogatio/schema";
102
- import { normalizeSiteOrigin as normalizeSiteOrigin2 } from "@rogatio/schema";
103
1252
  import { randomBytes as randomBytes22 } from "node:crypto";
104
1253
  import { readFile as readFile3, realpath as realpath2, stat } from "node:fs/promises";
105
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3, sep } from "node:path";
1254
+ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve4, sep } from "node:path";
106
1255
  import { lookup as dnsLookup } from "node:dns/promises";
107
1256
  import { request as httpRequest } from "node:http";
108
1257
  import { request as httpsRequest } from "node:https";
109
1258
  import { createHash as createHash2 } from "node:crypto";
110
- import {
111
- compileUrlRegex as compileUrlRegex2,
112
- HTTP_METHODS as HTTP_METHODS22,
113
- hasControl as hasControl3,
114
- LIMITS,
115
- normalizeSiteOrigin as normalizeSiteOrigin3,
116
- RESOURCE_TYPES as RESOURCE_TYPES2
117
- } from "@rogatio/schema";
118
1259
  import { createHash as createHash3 } from "node:crypto";
119
- import { formatSha256 } from "@rogatio/schema";
120
1260
  import { Worker } from "node:worker_threads";
121
- import { LIMITS as LIMITS2 } from "@rogatio/schema";
122
- import { LIMITS as LIMITS3 } from "@rogatio/schema";
123
- import {
124
- compileUrlRegex as compileUrlRegex22,
125
- normalizeSiteOrigin as normalizeSiteOrigin4
126
- } from "@rogatio/schema";
127
1261
  import {
128
1262
  createPrivateKey,
129
1263
  createSign,
@@ -132,7 +1266,7 @@ import {
132
1266
  } from "node:crypto";
133
1267
  import { readFileSync } from "node:fs";
134
1268
  import { mkdir as mkdir2, readFile as readFile22, rename as rename2, rm, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
135
- import { basename as basename3, dirname as dirname2, isAbsolute as isAbsolute3, join as join2, relative as relative3 } from "node:path";
1269
+ import { basename as basename3, dirname as dirname3, isAbsolute as isAbsolute3, join as join2, relative as relative3 } from "node:path";
136
1270
  import { generateKeyPairSync as generateKeyPairSync2 } from "node:crypto";
137
1271
  function parseIPv4(value) {
138
1272
  const parts = value.split(".");
@@ -284,7 +1418,7 @@ function normalizeLogicalPath(value) {
284
1418
  }
285
1419
  return parts.join("/");
286
1420
  }
287
- function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
1421
+ function snapshotOwnData3(value, ancestors = /* @__PURE__ */ new WeakSet()) {
288
1422
  if (value === null || typeof value !== "object") {
289
1423
  return { valid: true, value };
290
1424
  }
@@ -316,7 +1450,7 @@ function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
316
1450
  if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
317
1451
  return { valid: false };
318
1452
  }
319
- const child = snapshotOwnData(descriptor.value, ancestors);
1453
+ const child = snapshotOwnData3(descriptor.value, ancestors);
320
1454
  if (!child.valid) return child;
321
1455
  snapshot2[index] = child.value;
322
1456
  }
@@ -330,7 +1464,7 @@ function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
330
1464
  if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
331
1465
  return { valid: false };
332
1466
  }
333
- const child = snapshotOwnData(descriptor.value, ancestors);
1467
+ const child = snapshotOwnData3(descriptor.value, ancestors);
334
1468
  if (!child.valid) return child;
335
1469
  Object.defineProperty(snapshot, key, {
336
1470
  configurable: true,
@@ -381,11 +1515,11 @@ function validHostname(hostname) {
381
1515
  if (unbracketed.includes("%") || unbracketed.endsWith(".")) return false;
382
1516
  if (isIP2(unbracketed) !== 0) return true;
383
1517
  if (unbracketed.length === 0 || unbracketed.length > 253) return false;
384
- return unbracketed.split(".").every((label) => ID_PATTERN.test(label));
1518
+ return unbracketed.split(".").every((label2) => ID_PATTERN.test(label2));
385
1519
  }
386
1520
  function canonicalizeOutboundTarget(value) {
387
1521
  if (typeof value !== "string" || value.length === 0) return null;
388
- if (value.trim() !== value || hasControl2(value)) return null;
1522
+ if (value.trim() !== value || hasControl(value)) return null;
389
1523
  if (value.includes("\\") || value.includes("#")) return null;
390
1524
  if (!hasValidPercentEncoding(value)) return null;
391
1525
  if (/%(?:2f|2F|5c|5C)/.test(value)) return null;
@@ -422,13 +1556,13 @@ function isOriginAllowed(target, origins) {
422
1556
  return origin !== null && origins.includes(origin);
423
1557
  }
424
1558
  function validMethod(value) {
425
- return typeof value === "string" && HTTP_METHODS2.includes(value);
1559
+ return typeof value === "string" && HTTP_METHODS.includes(value);
426
1560
  }
427
1561
  function validId(value) {
428
1562
  return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(value);
429
1563
  }
430
1564
  function exactDescriptor(value) {
431
- const snapshot = snapshotOwnData(value);
1565
+ const snapshot = snapshotOwnData3(value);
432
1566
  if (!snapshot.valid || snapshot.value === null || typeof snapshot.value !== "object" || Array.isArray(snapshot.value))
433
1567
  return null;
434
1568
  const record = snapshot.value;
@@ -755,7 +1889,7 @@ function generatePacScript(origins, endpoint, options) {
755
1889
  }
756
1890
  const valid = [];
757
1891
  for (const origin of origins) {
758
- const normalized = normalizeSiteOrigin2(origin);
1892
+ const normalized = normalizeSiteOrigin(origin);
759
1893
  if (normalized !== null) valid.push(normalized);
760
1894
  }
761
1895
  const unique = Array.from(new Set(valid)).sort();
@@ -927,7 +2061,7 @@ async function readMockFile(root, logicalPath) {
927
2061
  if (normalized === null) return failure("runtime.file-denied");
928
2062
  try {
929
2063
  const canonicalRoot = await realpath2(root);
930
- const candidate = resolve3(canonicalRoot, ...normalized.split("/"));
2064
+ const candidate = resolve4(canonicalRoot, ...normalized.split("/"));
931
2065
  const actualPath = await realpath2(candidate);
932
2066
  if (!withinRoot2(canonicalRoot, actualPath))
933
2067
  return failure("runtime.file-denied");
@@ -1839,14 +2973,14 @@ function validId2(value) {
1839
2973
  return typeof value === "string" && ID_PATTERN2.test(value);
1840
2974
  }
1841
2975
  function validMethod2(value) {
1842
- return typeof value === "string" && HTTP_METHODS22.includes(value);
2976
+ return typeof value === "string" && HTTP_METHODS.includes(value);
1843
2977
  }
1844
2978
  function normalizeMockHeader(value) {
1845
2979
  if (value === null || typeof value !== "object" || Array.isArray(value))
1846
2980
  return null;
1847
2981
  if (!exactKeys(value, ["name", "value"])) return null;
1848
2982
  const record = value;
1849
- if (typeof record.name !== "string" || record.name.length === 0 || record.name.length > LIMITS.maxMockHeaderNameLength || hasControl3(record.name) || record.name.includes(":"))
2983
+ if (typeof record.name !== "string" || record.name.length === 0 || record.name.length > LIMITS.maxMockHeaderNameLength || hasControl(record.name) || record.name.includes(":"))
1850
2984
  return null;
1851
2985
  if (typeof record.value !== "string" || record.value.length > LIMITS.maxMockHeaderValueLength)
1852
2986
  return null;
@@ -1894,7 +3028,7 @@ function normalizeMockConfig(value, matcherById) {
1894
3028
  if (bodySet === fileSet) return null;
1895
3029
  if (bodySet && body.length > LIMITS.maxMockInlineBodyLength) return null;
1896
3030
  if (fileSet) {
1897
- if (file.length === 0 || file.length > LIMITS.maxMockFilePathLength || hasControl3(file))
3031
+ if (file.length === 0 || file.length > LIMITS.maxMockFilePathLength || hasControl(file))
1898
3032
  return null;
1899
3033
  }
1900
3034
  return Object.freeze({
@@ -1907,7 +3041,7 @@ function normalizeMockConfig(value, matcherById) {
1907
3041
  });
1908
3042
  }
1909
3043
  function validResourceType(value) {
1910
- return typeof value === "string" && RESOURCE_TYPES2.includes(value);
3044
+ return typeof value === "string" && RESOURCE_TYPES.includes(value);
1911
3045
  }
1912
3046
  function freezeMatcher(operation) {
1913
3047
  const matcher = Object.freeze({
@@ -1959,14 +3093,14 @@ function normalizeMatcher(value) {
1959
3093
  return null;
1960
3094
  }
1961
3095
  const regex = regexValue;
1962
- if (typeof regex.source !== "string" || regex.source.length > LIMITS.maxUrlRegexLength || regex.flags !== "" || compileUrlRegex2(regex.source) === null) {
3096
+ if (typeof regex.source !== "string" || regex.source.length > LIMITS.maxUrlRegexLength || regex.flags !== "" || compileUrlRegex(regex.source) === null) {
1963
3097
  return null;
1964
3098
  }
1965
3099
  if (!Array.isArray(matcher.origins) || matcher.origins.length === 0 || matcher.origins.length > LIMITS.maxOriginsPerScope)
1966
3100
  return null;
1967
3101
  const origins = [];
1968
3102
  for (const value2 of matcher.origins) {
1969
- const normalized = normalizeSiteOrigin3(value2);
3103
+ const normalized = normalizeSiteOrigin(value2);
1970
3104
  if (normalized === null || origins.includes(normalized)) return null;
1971
3105
  origins.push(normalized);
1972
3106
  }
@@ -1978,7 +3112,7 @@ function normalizeMatcher(value) {
1978
3112
  resourceTypes.push(value2);
1979
3113
  }
1980
3114
  resourceTypes.sort(
1981
- (left, right) => RESOURCE_TYPES2.indexOf(left) - RESOURCE_TYPES2.indexOf(right)
3115
+ (left, right) => RESOURCE_TYPES.indexOf(left) - RESOURCE_TYPES.indexOf(right)
1982
3116
  );
1983
3117
  if (typeof matcher.priority !== "number" || !Number.isSafeInteger(matcher.priority) || matcher.priority < LIMITS.minPriority || matcher.priority > LIMITS.maxPriority)
1984
3118
  return null;
@@ -2052,7 +3186,7 @@ function makeGrant(value, matcherById) {
2052
3186
  });
2053
3187
  }
2054
3188
  function normalizeRuntimePreset(value) {
2055
- const snapshot = snapshotOwnData(value);
3189
+ const snapshot = snapshotOwnData3(value);
2056
3190
  if (!snapshot.valid || snapshot.value === null || typeof snapshot.value !== "object" || Array.isArray(snapshot.value)) {
2057
3191
  return failure("runtime.invalid-preset");
2058
3192
  }
@@ -2540,10 +3674,10 @@ async function rewriteRequestBody(input, action) {
2540
3674
  if (action.pattern.length === 0) {
2541
3675
  return failure("runtime.request-body-regex-missing-pattern");
2542
3676
  }
2543
- if (action.pattern.length > LIMITS2.maxRequestBodyPatternLength) {
3677
+ if (action.pattern.length > LIMITS.maxRequestBodyPatternLength) {
2544
3678
  return failure("runtime.request-body-regex-pattern-too-large");
2545
3679
  }
2546
- if (action.replacement.length > LIMITS2.maxRequestBodyReplacementLength) {
3680
+ if (action.replacement.length > LIMITS.maxRequestBodyReplacementLength) {
2547
3681
  return failure("runtime.request-body-regex-replacement-too-large");
2548
3682
  }
2549
3683
  if (hasLoneSurrogate2(action.replacement)) {
@@ -2588,7 +3722,7 @@ async function rewriteResponseBody(input, replacements) {
2588
3722
  return failure("runtime.size-limit");
2589
3723
  if (input.contentEncoding !== void 0 && input.contentEncoding !== "identity")
2590
3724
  return failure("runtime.size-limit");
2591
- if (input.body.byteLength > RUNTIME_LIMITS.maxResponseBodyBytes || replacements.length === 0 || replacements.length > LIMITS3.maxResponseBodyReplacements)
3725
+ if (input.body.byteLength > RUNTIME_LIMITS.maxResponseBodyBytes || replacements.length === 0 || replacements.length > LIMITS.maxResponseBodyReplacements)
2592
3726
  return failure("runtime.size-limit");
2593
3727
  let text;
2594
3728
  try {
@@ -2598,7 +3732,7 @@ async function rewriteResponseBody(input, replacements) {
2598
3732
  }
2599
3733
  try {
2600
3734
  for (const entry of replacements) {
2601
- if (entry.pattern.length === 0 || entry.pattern.length > LIMITS3.maxResponseBodyPatternLength || entry.replacement.length > LIMITS3.maxResponseBodyReplacementLength)
3735
+ if (entry.pattern.length === 0 || entry.pattern.length > LIMITS.maxResponseBodyPatternLength || entry.replacement.length > LIMITS.maxResponseBodyReplacementLength)
2602
3736
  return failure("runtime.size-limit");
2603
3737
  const regex = new RegExp(entry.pattern, "gu");
2604
3738
  text = text.replace(regex, entry.replacement);
@@ -2643,10 +3777,10 @@ async function fetchAndRewriteAuthorizedResponse(operation, replacements, option
2643
3777
  };
2644
3778
  }
2645
3779
  function originOf(value) {
2646
- const direct = normalizeSiteOrigin4(value);
3780
+ const direct = normalizeSiteOrigin(value);
2647
3781
  if (direct !== null) return direct;
2648
3782
  try {
2649
- return normalizeSiteOrigin4(new URL(value).origin);
3783
+ return normalizeSiteOrigin(new URL(value).origin);
2650
3784
  } catch {
2651
3785
  return null;
2652
3786
  }
@@ -2658,11 +3792,11 @@ function projectHasRule(project, groupId, ruleId) {
2658
3792
  return group.rules.some((rule) => rule.id === ruleId);
2659
3793
  }
2660
3794
  function revalidateAuthority(project, operations, request) {
2661
- const projectSnap = snapshotOwnData(project);
3795
+ const projectSnap = snapshotOwnData3(project);
2662
3796
  if (!projectSnap.valid) return { allowed: false, reason: "project-invalid" };
2663
- const opsSnap = snapshotOwnData(operations);
3797
+ const opsSnap = snapshotOwnData3(operations);
2664
3798
  if (!opsSnap.valid) return { allowed: false, reason: "project-invalid" };
2665
- const reqSnap = snapshotOwnData(request);
3799
+ const reqSnap = snapshotOwnData3(request);
2666
3800
  if (!reqSnap.valid) return { allowed: false, reason: "project-invalid" };
2667
3801
  const operation = operations.find(
2668
3802
  (candidate) => candidate.groupId === request.groupId && candidate.ruleId === request.ruleId && "matcher" in candidate
@@ -2678,7 +3812,7 @@ function revalidateAuthority(project, operations, request) {
2678
3812
  return { allowed: false, reason: "project-inconsistent" };
2679
3813
  }
2680
3814
  const matcher = operation.matcher;
2681
- const regex = compileUrlRegex22(matcher.urlRegex.source);
3815
+ const regex = compileUrlRegex(matcher.urlRegex.source);
2682
3816
  if (regex === null || !regex.test(request.url)) {
2683
3817
  return { allowed: false, reason: "url-mismatch" };
2684
3818
  }
@@ -2858,7 +3992,7 @@ function isWellFormedManifest(value) {
2858
3992
  return typeof m.name === "string" && typeof m.path === "string" && m.type === "stdio" && Array.isArray(m.allowed_origins) && m.allowed_origins.every((o) => typeof o === "string");
2859
3993
  }
2860
3994
  async function writeFileAtomic(path, data) {
2861
- const dir = dirname2(path);
3995
+ const dir = dirname3(path);
2862
3996
  await mkdir2(dir, { recursive: true });
2863
3997
  const tmp = join2(dir, `.${basename3(path)}.${process.pid}.tmp`);
2864
3998
  await writeFile2(tmp, data, "utf8");
@@ -3025,9 +4159,19 @@ function createRequestBodyTrustController(options = {}) {
3025
4159
  return { install, uninstall, trust, untrust, status };
3026
4160
  }
3027
4161
  var MAX_ARRAY_LENGTH, MAX_OBJECT_PROPERTIES, ID_PATTERN, RUNTIME_LIMITS, RUNTIME_PROTOCOL, PROTOCOL, ENVELOPE_MAX_BYTES, MAX_PAC_ORIGINS, MAX_CONCURRENT_TRANSFORMS, REVALIDATION_INTERVAL_MS, FORBIDDEN_BODY_KEYS, MOCK_BODY_KEY, MOCK_BODY_ALLOWED_TYPES, ENVELOPE_MESSAGE_TYPES, EnvelopeError, TOKEN_BYTES, TOKEN_LENGTH, registeredProvider, currentSession, NATIVE_FRAME_MAX_BYTES, NATIVE_POLICY_MAX_BYTES, NATIVE_POLICY_MAX_FRAMES, NATIVE_POLICY_STAGE_TIMEOUT_MS, NativeFrameType, defaultResolver, defaultTransport, ID_PATTERN2, PRIVATE_RANGES, SUPPORTED_MIME_TYPES, SUPPORTED_MIME_PREFIXES, FORBIDDEN_HEADERS, FORBIDDEN_CONTENT_ENCODINGS, RESERVED_MARKER_PREFIX, MARKER_SEPARATOR, pendingAuths, cachedContext, TRUST_LIMITS, TrustError, ORIGIN_RE, DEFAULT_CAPABILITIES;
3028
- var init_node = __esm({
4162
+ var init_node2 = __esm({
3029
4163
  "packages/runtime/dist/node/index.js"() {
3030
4164
  "use strict";
4165
+ init_node();
4166
+ init_node();
4167
+ init_node();
4168
+ init_node();
4169
+ init_node();
4170
+ init_node();
4171
+ init_node();
4172
+ init_node();
4173
+ init_node();
4174
+ init_node();
3031
4175
  MAX_ARRAY_LENGTH = 4096;
3032
4176
  MAX_OBJECT_PROPERTIES = 256;
3033
4177
  ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
@@ -3227,12 +4371,11 @@ var init_node = __esm({
3227
4371
 
3228
4372
  // packages/cli/src/index.ts
3229
4373
  import { realpathSync } from "node:fs";
3230
- import { basename as basename4, dirname as dirname4, resolve as resolve7 } from "node:path";
4374
+ import { basename as basename4, dirname as dirname5, resolve as resolve8 } from "node:path";
3231
4375
  import { fileURLToPath as fileURLToPath2 } from "node:url";
3232
4376
 
3233
4377
  // packages/cli/src/commands/edit.ts
3234
- import { resolve as resolve2 } from "node:path";
3235
- import { fileURLToPath } from "node:url";
4378
+ import { resolve as resolve3 } from "node:path";
3236
4379
 
3237
4380
  // packages/cli/src/server/http.ts
3238
4381
  import { randomInt } from "node:crypto";
@@ -3253,11 +4396,11 @@ function createServer(handler, options = {}) {
3253
4396
  let port = null;
3254
4397
  let started = false;
3255
4398
  async function listenOn(candidatePort) {
3256
- await new Promise((resolve8, reject) => {
4399
+ await new Promise((resolve9, reject) => {
3257
4400
  server.once("error", reject);
3258
4401
  server.listen(candidatePort, "127.0.0.1", () => {
3259
4402
  server.off("error", reject);
3260
- resolve8();
4403
+ resolve9();
3261
4404
  });
3262
4405
  });
3263
4406
  }
@@ -3312,8 +4455,8 @@ function createServer(handler, options = {}) {
3312
4455
  },
3313
4456
  async stop() {
3314
4457
  if (!started) return;
3315
- await new Promise((resolve8) => {
3316
- server.close(() => resolve8());
4458
+ await new Promise((resolve9) => {
4459
+ server.close(() => resolve9());
3317
4460
  });
3318
4461
  started = false;
3319
4462
  }
@@ -3324,10 +4467,360 @@ function createServer(handler, options = {}) {
3324
4467
  import { randomBytes } from "node:crypto";
3325
4468
  import { readFile } from "node:fs/promises";
3326
4469
  import { resolve } from "node:path";
3327
- import { compileProject } from "@rogatio/compiler";
4470
+
4471
+ // packages/compiler/dist/node/index.js
4472
+ init_node();
4473
+ init_node();
4474
+ var ISSUE_CODES = {
4475
+ required: "schema.required",
4476
+ additionalProperties: "schema.unknown-property",
4477
+ type: "schema.invalid-type",
4478
+ format: "schema.invalid-format",
4479
+ const: "schema.invalid-value",
4480
+ enum: "schema.invalid-value",
4481
+ pattern: "schema.invalid-value",
4482
+ minLength: "schema.out-of-range",
4483
+ maxLength: "schema.out-of-range",
4484
+ minItems: "schema.out-of-range",
4485
+ maxItems: "schema.out-of-range",
4486
+ minimum: "schema.out-of-range",
4487
+ maximum: "schema.out-of-range",
4488
+ uniqueItems: "schema.out-of-range",
4489
+ ownProperties: "schema.invalid-structure",
4490
+ uniqueId: "schema.duplicate-id",
4491
+ effectiveOrigin: "schema.no-effective-origin",
4492
+ maxRulesPerProject: "schema.rule-limit"
4493
+ };
4494
+ var SAFE_PARAM_KEYS = /* @__PURE__ */ new Set([
4495
+ "additionalProperty",
4496
+ "actual",
4497
+ "allowedValue",
4498
+ "allowedValues",
4499
+ "format",
4500
+ "i",
4501
+ "j",
4502
+ "limit",
4503
+ "missingProperty",
4504
+ "previousPath",
4505
+ "type",
4506
+ "headerName",
4507
+ "headerOperation",
4508
+ "headerDirection"
4509
+ ]);
4510
+ var MESSAGES = {
4511
+ "schema.required": "Required project data is missing.",
4512
+ "schema.unknown-property": "The project contains an unknown property.",
4513
+ "schema.invalid-type": "The project contains a value with an invalid type.",
4514
+ "schema.invalid-format": "The project contains a value with an invalid format.",
4515
+ "schema.invalid-value": "The project contains an invalid value.",
4516
+ "schema.out-of-range": "The project contains a value outside its allowed bounds.",
4517
+ "schema.invalid-structure": "The project contains invalid structure.",
4518
+ "schema.duplicate-id": "Project and rule IDs must be unique.",
4519
+ "schema.no-effective-origin": "Each rule must have at least one effective origin.",
4520
+ "schema.rule-limit": "The project contains too many rules.",
4521
+ "compiler.invariant": "The compiler could not normalize validated project data.",
4522
+ "compiler.forbidden-header": "The header name is forbidden for this direction.",
4523
+ "compiler.header-value-required": "Header value is required for set and append operations.",
4524
+ "compiler.header-value-unexpected": "Header value must not be provided for remove operation.",
4525
+ "compiler.invalid-header-direction": "Invalid header direction.",
4526
+ "compiler.invalid-header-operation": "Invalid header operation."
4527
+ };
4528
+ function copySafeParams(params) {
4529
+ const safe = {};
4530
+ for (const key of Object.keys(params)) {
4531
+ if (!SAFE_PARAM_KEYS.has(key)) continue;
4532
+ const value = params[key];
4533
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
4534
+ safe[key] = value;
4535
+ continue;
4536
+ }
4537
+ if (Array.isArray(value)) {
4538
+ const values = [];
4539
+ for (let index = 0; index < value.length; index += 1) {
4540
+ const item = value[index];
4541
+ if (typeof item === "string" || typeof item === "number" || typeof item === "boolean" || item === null) {
4542
+ values.push(item);
4543
+ }
4544
+ }
4545
+ safe[key] = values;
4546
+ }
4547
+ }
4548
+ return safe;
4549
+ }
4550
+ function compareCodeUnits(left, right) {
4551
+ if (left < right) return -1;
4552
+ if (left > right) return 1;
4553
+ return 0;
4554
+ }
4555
+ function compareDiagnostics(left, right) {
4556
+ const leftParams = stableParams(left.params);
4557
+ const rightParams = stableParams(right.params);
4558
+ return compareCodeUnits(left.path, right.path) || compareCodeUnits(left.code, right.code) || compareCodeUnits(left.message, right.message) || compareCodeUnits(leftParams, rightParams);
4559
+ }
4560
+ function stableParams(params) {
4561
+ const keys = Object.keys(params).sort(compareCodeUnits);
4562
+ return keys.map((key) => `${JSON.stringify(key)}:${JSON.stringify(params[key])}`).join(",");
4563
+ }
4564
+ function mapValidationIssues(issues) {
4565
+ return issues.map((issue) => {
4566
+ const code = Object.hasOwn(ISSUE_CODES, issue.keyword) ? ISSUE_CODES[issue.keyword] : "schema.invalid-value";
4567
+ return {
4568
+ code,
4569
+ severity: "error",
4570
+ path: issue.instancePath,
4571
+ message: MESSAGES[code],
4572
+ params: copySafeParams(issue.params)
4573
+ };
4574
+ }).sort(compareDiagnostics);
4575
+ }
4576
+ function invariantDiagnostic(path = "") {
4577
+ return {
4578
+ code: "compiler.invariant",
4579
+ severity: "error",
4580
+ path,
4581
+ message: MESSAGES["compiler.invariant"],
4582
+ params: {}
4583
+ };
4584
+ }
4585
+ function compareCodeUnits2(left, right) {
4586
+ if (left < right) return -1;
4587
+ if (left > right) return 1;
4588
+ return 0;
4589
+ }
4590
+ function snapshotOwnData2(value, ancestors = /* @__PURE__ */ new WeakSet()) {
4591
+ if (value === null || typeof value !== "object") {
4592
+ return { valid: true, value };
4593
+ }
4594
+ if (ancestors.has(value)) return { valid: false };
4595
+ ancestors.add(value);
4596
+ try {
4597
+ if (Object.getOwnPropertySymbols(value).length > 0) {
4598
+ return { valid: false };
4599
+ }
4600
+ if (Array.isArray(value)) {
4601
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
4602
+ if (lengthDescriptor === void 0 || !("value" in lengthDescriptor) || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0 || lengthDescriptor.value > LIMITS.maxRulesPerProject) {
4603
+ return { valid: false };
4604
+ }
4605
+ const length = lengthDescriptor.value;
4606
+ for (const propertyName of Object.getOwnPropertyNames(value)) {
4607
+ if (propertyName === "length") continue;
4608
+ const index = Number(propertyName);
4609
+ if (!Number.isInteger(index) || index < 0 || index >= length || String(index) !== propertyName) {
4610
+ return { valid: false };
4611
+ }
4612
+ }
4613
+ const snapshot2 = new Array(length);
4614
+ for (let index = 0; index < length; index += 1) {
4615
+ const descriptor = Object.getOwnPropertyDescriptor(
4616
+ value,
4617
+ String(index)
4618
+ );
4619
+ if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
4620
+ return { valid: false };
4621
+ }
4622
+ const child = snapshotOwnData2(descriptor.value, ancestors);
4623
+ if (!child.valid) return child;
4624
+ snapshot2[index] = child.value;
4625
+ }
4626
+ return { valid: true, value: snapshot2 };
4627
+ }
4628
+ const snapshot = /* @__PURE__ */ Object.create(null);
4629
+ for (const key of Object.getOwnPropertyNames(value)) {
4630
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
4631
+ if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
4632
+ return { valid: false };
4633
+ }
4634
+ const child = snapshotOwnData2(descriptor.value, ancestors);
4635
+ if (!child.valid) return child;
4636
+ Object.defineProperty(snapshot, key, {
4637
+ configurable: true,
4638
+ enumerable: true,
4639
+ value: child.value,
4640
+ writable: true
4641
+ });
4642
+ }
4643
+ return { valid: true, value: snapshot };
4644
+ } catch {
4645
+ return { valid: false };
4646
+ } finally {
4647
+ ancestors.delete(value);
4648
+ }
4649
+ }
4650
+ var CompilerInvariantError = class extends Error {
4651
+ constructor(path) {
4652
+ super("invalid normalized origin");
4653
+ this.path = path;
4654
+ this.name = "CompilerInvariantError";
4655
+ }
4656
+ path;
4657
+ };
4658
+ function normalizeOrigins(group, rule, groupIndex, ruleIndex) {
4659
+ const origins = /* @__PURE__ */ new Set();
4660
+ const sourceArrays = [group.origins, rule.origins];
4661
+ for (let sourceIndex = 0; sourceIndex < sourceArrays.length; sourceIndex += 1) {
4662
+ const source = sourceArrays[sourceIndex];
4663
+ for (let originIndex = 0; originIndex < source.length; originIndex += 1) {
4664
+ const normalized = normalizeSiteOrigin(source[originIndex]);
4665
+ if (normalized === null) {
4666
+ const path = sourceIndex === 0 ? `/groups/${groupIndex}/origins/${originIndex}` : `/groups/${groupIndex}/rules/${ruleIndex}/origins/${originIndex}`;
4667
+ throw new CompilerInvariantError(path);
4668
+ }
4669
+ origins.add(normalized);
4670
+ }
4671
+ }
4672
+ const normalizedOrigins = [];
4673
+ for (const origin of origins) normalizedOrigins.push(origin);
4674
+ normalizedOrigins.sort(compareCodeUnits2);
4675
+ return normalizedOrigins;
4676
+ }
4677
+ function canonicalResourceTypes(resourceTypes) {
4678
+ const ordered = [];
4679
+ for (let canonicalIndex = 0; canonicalIndex < RESOURCE_TYPES.length; canonicalIndex += 1) {
4680
+ const canonical = RESOURCE_TYPES[canonicalIndex];
4681
+ for (let sourceIndex = 0; sourceIndex < resourceTypes.length; sourceIndex += 1) {
4682
+ if (resourceTypes[sourceIndex] === canonical) ordered.push(canonical);
4683
+ }
4684
+ }
4685
+ return ordered;
4686
+ }
4687
+ function compileMatcher(group, rule, groupIndex, ruleIndex) {
4688
+ const matcher = {
4689
+ urlRegex: { source: rule.urlRegex, flags: "" },
4690
+ origins: normalizeOrigins(group, rule, groupIndex, ruleIndex),
4691
+ resourceTypes: canonicalResourceTypes(rule.resourceTypes),
4692
+ priority: rule.priority
4693
+ };
4694
+ if (rule.method !== void 0) matcher.method = rule.method;
4695
+ return matcher;
4696
+ }
4697
+ function compileOperations(project) {
4698
+ const operations = [];
4699
+ for (let groupIndex = 0; groupIndex < project.groups.length; groupIndex += 1) {
4700
+ const group = project.groups[groupIndex];
4701
+ for (let ruleIndex = 0; ruleIndex < group.rules.length; ruleIndex += 1) {
4702
+ const rule = group.rules[ruleIndex];
4703
+ const matcher = compileMatcher(group, rule, groupIndex, ruleIndex);
4704
+ if (rule.type === "redirect") {
4705
+ const operation = {
4706
+ kind: "redirect",
4707
+ groupId: group.id,
4708
+ ruleId: rule.id,
4709
+ matcher,
4710
+ redirect: { destination: rule.redirect?.destination ?? "" }
4711
+ };
4712
+ operations.push(operation);
4713
+ } else if (rule.type === "query" && rule.action && "type" in rule.action && rule.action.type === "query") {
4714
+ const action = rule.action;
4715
+ const operation = {
4716
+ kind: "query",
4717
+ groupId: group.id,
4718
+ ruleId: rule.id,
4719
+ matcher,
4720
+ action
4721
+ };
4722
+ operations.push(operation);
4723
+ } else if (rule.type === "header") {
4724
+ const operation = {
4725
+ kind: "header",
4726
+ groupId: group.id,
4727
+ ruleId: rule.id,
4728
+ matcher,
4729
+ header: {
4730
+ direction: rule.headerDirection ?? "request",
4731
+ operation: rule.headerOperation ?? "set",
4732
+ name: rule.headerName ?? "",
4733
+ ...rule.headerValue !== void 0 ? { value: rule.headerValue } : {}
4734
+ }
4735
+ };
4736
+ operations.push(operation);
4737
+ } else if (rule.type === "mock") {
4738
+ const operation = {
4739
+ kind: "mock",
4740
+ groupId: group.id,
4741
+ ruleId: rule.id,
4742
+ matcher,
4743
+ mock: rule.mock ?? { status: 200, body: "" }
4744
+ };
4745
+ operations.push(operation);
4746
+ } else if (rule.type === "response-body") {
4747
+ const operation = {
4748
+ kind: "response-body",
4749
+ groupId: group.id,
4750
+ ruleId: rule.id,
4751
+ matcher,
4752
+ responseBody: rule.responseBody ?? { replacements: [] }
4753
+ };
4754
+ operations.push(operation);
4755
+ } else if (rule.type === "request-body") {
4756
+ const operation = {
4757
+ kind: "request-body",
4758
+ groupId: group.id,
4759
+ ruleId: rule.id,
4760
+ matcher,
4761
+ requestBody: rule.requestBody ?? { mode: "replace", body: "" }
4762
+ };
4763
+ operations.push(operation);
4764
+ } else {
4765
+ const operation = {
4766
+ kind: "matcher",
4767
+ groupId: group.id,
4768
+ ruleId: rule.id,
4769
+ matcher
4770
+ };
4771
+ operations.push(operation);
4772
+ }
4773
+ }
4774
+ }
4775
+ return operations;
4776
+ }
4777
+ function compileProject(value) {
4778
+ const snapshot = snapshotOwnData2(value);
4779
+ if (!snapshot.valid) {
4780
+ return {
4781
+ ok: false,
4782
+ operations: [],
4783
+ diagnostics: mapValidationIssues([
4784
+ {
4785
+ instancePath: "",
4786
+ keyword: "ownProperties",
4787
+ message: "must contain only own data properties",
4788
+ params: {}
4789
+ }
4790
+ ])
4791
+ };
4792
+ }
4793
+ let validation;
4794
+ try {
4795
+ validation = validateProjectDetailed(snapshot.value);
4796
+ } catch {
4797
+ return { ok: false, operations: [], diagnostics: [invariantDiagnostic()] };
4798
+ }
4799
+ if (!validation.valid) {
4800
+ return {
4801
+ ok: false,
4802
+ operations: [],
4803
+ diagnostics: mapValidationIssues(validation.errors)
4804
+ };
4805
+ }
4806
+ try {
4807
+ return {
4808
+ ok: true,
4809
+ operations: compileOperations(validation.data),
4810
+ diagnostics: []
4811
+ };
4812
+ } catch (error) {
4813
+ const path = error instanceof CompilerInvariantError ? error.path : "";
4814
+ return {
4815
+ ok: false,
4816
+ operations: [],
4817
+ diagnostics: [invariantDiagnostic(path)]
4818
+ };
4819
+ }
4820
+ }
3328
4821
 
3329
4822
  // packages/dry-run/dist/node/index.js
3330
- import { compileUrlRegex, HTTP_METHODS, RESOURCE_TYPES } from "@rogatio/schema";
4823
+ init_node();
3331
4824
  function parseTestUrl(input) {
3332
4825
  if (typeof input !== "string" || input.length === 0) {
3333
4826
  return { ok: false };
@@ -3633,7 +5126,7 @@ function dryRunProject(operations, cases, options) {
3633
5126
  }
3634
5127
 
3635
5128
  // packages/cli/src/server/routes.ts
3636
- import { validateProjectDetailed } from "@rogatio/schema";
5129
+ init_node();
3637
5130
 
3638
5131
  // packages/cli/src/utils/mock-preview.ts
3639
5132
  import { basename } from "node:path";
@@ -3678,7 +5171,7 @@ var RequestBodyError = class extends Error {
3678
5171
  code = "request-body-too-large";
3679
5172
  };
3680
5173
  function getRequestBody(req) {
3681
- return new Promise((resolve8, reject) => {
5174
+ return new Promise((resolve9, reject) => {
3682
5175
  let body = "";
3683
5176
  let bytes = 0;
3684
5177
  let settled = false;
@@ -3708,7 +5201,7 @@ function getRequestBody(req) {
3708
5201
  req.on("end", () => {
3709
5202
  if (!settled) {
3710
5203
  settled = true;
3711
- resolve8(body);
5204
+ resolve9(body);
3712
5205
  }
3713
5206
  });
3714
5207
  req.on("error", (error) => {
@@ -4052,6 +5545,21 @@ function createRoutes(context) {
4052
5545
  };
4053
5546
  }
4054
5547
 
5548
+ // packages/cli/src/utils/asset-paths.ts
5549
+ import { dirname, resolve as resolve2 } from "node:path";
5550
+ import { fileURLToPath } from "node:url";
5551
+ function isDistBuild(here = dirname(fileURLToPath(import.meta.url))) {
5552
+ return here.includes("/dist/") || here.includes("\\dist\\");
5553
+ }
5554
+ function editorAssetPaths(here = dirname(fileURLToPath(import.meta.url))) {
5555
+ const editorRoot = isDistBuild(here) ? resolve2(here, "..", "editor") : resolve2(here, "..", "..", "..", "editor", "dist", "browser");
5556
+ return {
5557
+ bundle: resolve2(editorRoot, "index.js"),
5558
+ css: resolve2(editorRoot, "index.css"),
5559
+ fonts: resolve2(editorRoot, "fonts")
5560
+ };
5561
+ }
5562
+
4055
5563
  // packages/cli/src/utils/browser.ts
4056
5564
  import { spawn } from "node:child_process";
4057
5565
  var BrowserLaunchError = class extends Error {
@@ -4088,7 +5596,7 @@ async function launchBrowser(url) {
4088
5596
  `Unsupported platform: ${platform}`
4089
5597
  );
4090
5598
  }
4091
- return new Promise((resolve8) => {
5599
+ return new Promise((resolve9) => {
4092
5600
  const child = spawn(command, args, {
4093
5601
  detached: true,
4094
5602
  stdio: "ignore"
@@ -4096,13 +5604,13 @@ async function launchBrowser(url) {
4096
5604
  child.unref();
4097
5605
  child.on("error", (err) => {
4098
5606
  if (err.code === "ENOENT") {
4099
- resolve8(false);
5607
+ resolve9(false);
4100
5608
  } else {
4101
- resolve8(false);
5609
+ resolve9(false);
4102
5610
  }
4103
5611
  });
4104
5612
  child.on("close", (code) => {
4105
- resolve8(code === 0);
5613
+ resolve9(code === 0);
4106
5614
  });
4107
5615
  });
4108
5616
  }
@@ -4110,7 +5618,7 @@ async function launchBrowser(url) {
4110
5618
  // packages/cli/src/utils/file.ts
4111
5619
  import { randomBytes as randomBytes2 } from "node:crypto";
4112
5620
  import { mkdir, readFile as readFile2, rename, writeFile } from "node:fs/promises";
4113
- import { basename as basename2, dirname, join } from "node:path";
5621
+ import { basename as basename2, dirname as dirname2, join } from "node:path";
4114
5622
  var ProjectFileError = class extends Error {
4115
5623
  code;
4116
5624
  path;
@@ -4160,10 +5668,10 @@ async function readProject(path) {
4160
5668
  }
4161
5669
  }
4162
5670
  async function writeProject(path, data) {
4163
- const tempName = `.${basename2(dirname(path))}.${randomBytes2(8).toString("hex")}.tmp`;
4164
- const tempPath = join(dirname(path), tempName);
5671
+ const tempName = `.${basename2(dirname2(path))}.${randomBytes2(8).toString("hex")}.tmp`;
5672
+ const tempPath = join(dirname2(path), tempName);
4165
5673
  try {
4166
- await mkdir(dirname(path), { recursive: true });
5674
+ await mkdir(dirname2(path), { recursive: true });
4167
5675
  await writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
4168
5676
  await rename(tempPath, path);
4169
5677
  } catch (e) {
@@ -4224,9 +5732,9 @@ Options:
4224
5732
  }
4225
5733
  let filePath;
4226
5734
  if (positionalArgs[0]) {
4227
- filePath = resolve2(positionalArgs[0]);
5735
+ filePath = resolve3(positionalArgs[0]);
4228
5736
  } else {
4229
- filePath = resolve2(process.cwd(), ".rogatio.json");
5737
+ filePath = resolve3(process.cwd(), ".rogatio.json");
4230
5738
  }
4231
5739
  try {
4232
5740
  const stat3 = await import("node:fs/promises").then(
@@ -4295,17 +5803,11 @@ Options:
4295
5803
  }
4296
5804
  const serverUrl = `http://127.0.0.1:${server.port}`;
4297
5805
  const editorUrl = `${serverUrl}/editor.html`;
4298
- let editorBundlePath;
4299
- try {
4300
- editorBundlePath = fileURLToPath(import.meta.resolve("@rogatio/editor"));
4301
- } catch (e) {
4302
- console.error(`Error: cannot resolve @rogatio/editor bundle: ${e}`);
4303
- await server.stop();
4304
- return { exitCode: Promise.resolve(2), shutdown: () => {
4305
- } };
4306
- }
4307
- const editorCssPath = editorBundlePath.replace(/index\.js$/u, "index.css");
4308
- const editorFontsPath = resolve2(editorBundlePath, "..", "fonts");
5806
+ const {
5807
+ bundle: editorBundlePath,
5808
+ css: editorCssPath,
5809
+ fonts: editorFontsPath
5810
+ } = editorAssetPaths();
4309
5811
  context.editorHtml = generateEditorHtml(serverUrl, csrfToken, filePath);
4310
5812
  context.editorBundlePath = editorBundlePath;
4311
5813
  context.editorCssPath = editorCssPath;
@@ -4322,11 +5824,11 @@ Options:
4322
5824
  console.log(`Editor available at: ${editorUrl}`);
4323
5825
  console.log("Open this URL in your browser to edit the project.");
4324
5826
  }
4325
- const exitCodePromise = new Promise((resolve8) => {
5827
+ const exitCodePromise = new Promise((resolve9) => {
4326
5828
  const checkShutdown = setInterval(() => {
4327
5829
  if (shutdownCalled) {
4328
5830
  clearInterval(checkShutdown);
4329
- resolve8(0);
5831
+ resolve9(0);
4330
5832
  }
4331
5833
  }, 100);
4332
5834
  const handleSignal = () => {
@@ -4334,8 +5836,8 @@ Options:
4334
5836
  };
4335
5837
  process.on("SIGINT", handleSignal);
4336
5838
  process.on("SIGTERM", handleSignal);
4337
- const originalResolve = resolve8;
4338
- resolve8 = (code) => {
5839
+ const originalResolve = resolve9;
5840
+ resolve9 = (code) => {
4339
5841
  clearInterval(checkShutdown);
4340
5842
  process.off("SIGINT", handleSignal);
4341
5843
  process.off("SIGTERM", handleSignal);
@@ -4460,18 +5962,17 @@ function generateEditorHtml(apiBase, csrfToken, filePath) {
4460
5962
  }
4461
5963
 
4462
5964
  // packages/cli/src/commands/runtime.ts
5965
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join3, relative as relative4, resolve as resolve5, sep as sep2 } from "node:path";
5966
+ init_node2();
4463
5967
  init_node();
4464
- import { dirname as dirname3, isAbsolute as isAbsolute4, join as join3, relative as relative4, resolve as resolve4, sep as sep2 } from "node:path";
4465
- import { compileProject as compileProject2 } from "@rogatio/compiler";
4466
- import { validateProjectDetailed as validateProjectDetailed2 } from "@rogatio/schema";
4467
5968
  function showRuntimeHelp() {
4468
5969
  console.log(`Usage: rogatio runtime <command> [options]
4469
5970
 
4470
5971
  Native messaging runtime control for response-body and request-body rules.
4471
5972
 
4472
5973
  Native runtime commands:
4473
- start Start the runtime (explicit, no auto-start)
4474
- stop Stop the runtime (idempotent)
5974
+ activate Activate the runtime (explicit, no auto-activation)
5975
+ deactivate Deactivate the runtime (idempotent)
4475
5976
  status Show the current runtime and trust state
4476
5977
 
4477
5978
  Request-body trust commands:
@@ -4482,10 +5983,10 @@ Request-body trust commands:
4482
5983
  uninstall Uninstall the native-messaging host manifest (idempotent)
4483
5984
 
4484
5985
  Native host command:
4485
- runtime-host [path] Run the consolidated native-messaging runtime host,
4486
- reading pairing/authorization/mock envelopes from stdin
4487
- and writing responses to stdout. This process is what the
4488
- browser launches via the native-messaging manifest.
5986
+ host [path] Run the consolidated native-messaging runtime host, reading
5987
+ pairing/authorization/mock envelopes from stdin and writing
5988
+ responses to stdout. This process is what the browser launches
5989
+ via the native-messaging manifest.
4489
5990
 
4490
5991
  Options:
4491
5992
  --extension-id Extension ID for native messaging manifest (required for install)
@@ -4506,7 +6007,7 @@ function toMatcherOperations2(operations) {
4506
6007
  }
4507
6008
  function resolveMockFile(root, filePath) {
4508
6009
  if (filePath.includes("\0")) return null;
4509
- const absolute = isAbsolute4(filePath) ? filePath : resolve4(root, filePath);
6010
+ const absolute = isAbsolute4(filePath) ? filePath : resolve5(root, filePath);
4510
6011
  const rel = relative4(root, absolute);
4511
6012
  if (rel.startsWith("..") || isAbsolute4(rel)) return null;
4512
6013
  const logical = rel.split(sep2).join("/");
@@ -4545,16 +6046,16 @@ async function nativeRuntimeCommand(args) {
4545
6046
  preset: await loadControlPreset()
4546
6047
  });
4547
6048
  switch (subcommand) {
4548
- case "start": {
6049
+ case "activate": {
4549
6050
  const result = await controller.start();
4550
6051
  if (result.state === "running") {
4551
- console.log("runtime started");
6052
+ console.log("runtime activated");
4552
6053
  return 0;
4553
6054
  }
4554
- console.error(`runtime start failed: ${result.state}`);
6055
+ console.error(`runtime activate failed: ${result.state}`);
4555
6056
  return 1;
4556
6057
  }
4557
- case "stop": {
6058
+ case "deactivate": {
4558
6059
  const result = await controller.stop();
4559
6060
  console.log(`runtime ${result.state}`);
4560
6061
  return 0;
@@ -4663,7 +6164,7 @@ async function runtimeStatusCommand(_args) {
4663
6164
  return 0;
4664
6165
  }
4665
6166
  async function loadControlPreset() {
4666
- const { normalizeRuntimePreset: normalizeRuntimePreset2 } = await Promise.resolve().then(() => (init_node(), node_exports));
6167
+ const { normalizeRuntimePreset: normalizeRuntimePreset2 } = await Promise.resolve().then(() => (init_node2(), node_exports));
4667
6168
  const result = normalizeRuntimePreset2({
4668
6169
  version: 1,
4669
6170
  limits: RUNTIME_LIMITS,
@@ -4681,7 +6182,7 @@ async function runtimeHostCommand(args) {
4681
6182
  for (let index = 0; index < args.length; index += 1) {
4682
6183
  const arg = args[index];
4683
6184
  if (arg === "--root" && index + 1 < args.length) {
4684
- root = resolve4(args[++index]);
6185
+ root = resolve5(args[++index]);
4685
6186
  } else if (arg === "--root") {
4686
6187
  argumentError = "--root requires a value";
4687
6188
  } else if (arg === "--mock-port" && index + 1 < args.length) {
@@ -4715,7 +6216,7 @@ async function runtimeHostCommand(args) {
4715
6216
  filePath = "<stdin>";
4716
6217
  projectData = JSON.parse(chunks.join(""));
4717
6218
  } else {
4718
- filePath = inputPath ? resolve4(inputPath) : resolve4(process.cwd(), ".rogatio.json");
6219
+ filePath = inputPath ? resolve5(inputPath) : resolve5(process.cwd(), ".rogatio.json");
4719
6220
  projectData = await readProject(filePath);
4720
6221
  }
4721
6222
  } catch (error) {
@@ -4723,7 +6224,7 @@ async function runtimeHostCommand(args) {
4723
6224
  console.error(`Error: ${message}`);
4724
6225
  return 2;
4725
6226
  }
4726
- const schemaResult = validateProjectDetailed2(projectData);
6227
+ const schemaResult = validateProjectDetailed(projectData);
4727
6228
  if (!schemaResult.valid) {
4728
6229
  for (const issue of schemaResult.errors) {
4729
6230
  console.error(
@@ -4732,7 +6233,7 @@ async function runtimeHostCommand(args) {
4732
6233
  }
4733
6234
  return 1;
4734
6235
  }
4735
- const compileResult = compileProject2(schemaResult.data);
6236
+ const compileResult = compileProject(schemaResult.data);
4736
6237
  if (!compileResult.ok) {
4737
6238
  for (const diagnostic of compileResult.diagnostics) {
4738
6239
  console.error(
@@ -4741,7 +6242,7 @@ async function runtimeHostCommand(args) {
4741
6242
  }
4742
6243
  return 1;
4743
6244
  }
4744
- const rootDir = root ?? (inputPath === "-" ? process.cwd() : dirname3(filePath));
6245
+ const rootDir = root ?? (inputPath === "-" ? process.cwd() : dirname4(filePath));
4745
6246
  const mocksResult = buildMockConfigs(compileResult.operations, rootDir);
4746
6247
  if (!mocksResult.ok) {
4747
6248
  console.error(`Error: ${mocksResult.message}`);
@@ -4775,10 +6276,11 @@ async function runtimeCommand(args, _options = {}) {
4775
6276
  if (first === "install" || first === "trust" || first === "untrust" || first === "uninstall")
4776
6277
  return trustRuntimeCommand(args);
4777
6278
  if (first === "status") return runtimeStatusCommand(args);
4778
- if (first === "start" || first === "stop") return nativeRuntimeCommand(args);
4779
- if (first === "runtime-host") return runtimeHostCommand(args.slice(1));
6279
+ if (first === "activate" || first === "deactivate")
6280
+ return nativeRuntimeCommand(args);
6281
+ if (first === "host") return runtimeHostCommand(args.slice(1));
4780
6282
  console.error(
4781
- `Error: 'rogatio runtime' no longer starts an HTTP mock server. Use 'rogatio runtime-host [path]' to run the native-messaging host, or one of: start, stop, status, install, trust, untrust, uninstall.`
6283
+ `Error: 'rogatio runtime' no longer starts an HTTP mock server. Use 'rogatio runtime host [path]' to run the native-messaging host, or one of: activate, deactivate, status, install, trust, untrust, uninstall.`
4782
6284
  );
4783
6285
  showRuntimeHelp();
4784
6286
  return 2;
@@ -4790,9 +6292,8 @@ async function runRuntimeHostEntry() {
4790
6292
 
4791
6293
  // packages/cli/src/commands/test.ts
4792
6294
  import { readFile as readFile4 } from "node:fs/promises";
4793
- import { resolve as resolve5 } from "node:path";
4794
- import { compileProject as compileProject3 } from "@rogatio/compiler";
4795
- import { validateProjectDetailed as validateProjectDetailed3 } from "@rogatio/schema";
6295
+ import { resolve as resolve6 } from "node:path";
6296
+ init_node();
4796
6297
  function usageError(message) {
4797
6298
  return `Error: ${message}
4798
6299
  `;
@@ -4865,7 +6366,7 @@ function resultOptions(maxCases, operations) {
4865
6366
  return options;
4866
6367
  }
4867
6368
  function diagnosticsFromSchema(projectData) {
4868
- const result = validateProjectDetailed3(projectData);
6369
+ const result = validateProjectDetailed(projectData);
4869
6370
  if (result.valid) return [];
4870
6371
  return result.errors.map((error) => ({
4871
6372
  code: `schema.${error.keyword}`,
@@ -4914,7 +6415,7 @@ function testCommandNeedsStdin(args) {
4914
6415
  return !hasUrlSource && positionalUrls.length === 0;
4915
6416
  }
4916
6417
  async function testCommandImpl(args, stdinInput, captureOutput) {
4917
- let filePath = resolve5(process.cwd(), ".rogatio.json");
6418
+ let filePath = resolve6(process.cwd(), ".rogatio.json");
4918
6419
  let jsonMode = false;
4919
6420
  let maxCases;
4920
6421
  const urlCases = [];
@@ -4973,7 +6474,7 @@ async function testCommandImpl(args, stdinInput, captureOutput) {
4973
6474
  }
4974
6475
  filePath = "<stdin>";
4975
6476
  } else if (inputPath) {
4976
- filePath = resolve5(inputPath);
6477
+ filePath = resolve6(inputPath);
4977
6478
  }
4978
6479
  for (const url of positionalUrls) urlCases.push({ url });
4979
6480
  if (urlsFile) {
@@ -5025,7 +6526,7 @@ async function testCommandImpl(args, stdinInput, captureOutput) {
5025
6526
  console.error(output.trim());
5026
6527
  return 2;
5027
6528
  }
5028
- const schemaResult = validateProjectDetailed3(projectData);
6529
+ const schemaResult = validateProjectDetailed(projectData);
5029
6530
  let diagnostics = diagnosticsFromSchema(projectData);
5030
6531
  if (!schemaResult.valid) {
5031
6532
  const output = jsonMode ? jsonOutput({ diagnostics }) : diagnostics.map(
@@ -5037,7 +6538,7 @@ async function testCommandImpl(args, stdinInput, captureOutput) {
5037
6538
  else console.error(output.trim());
5038
6539
  return 1;
5039
6540
  }
5040
- const compileResult = compileProject3(schemaResult.data);
6541
+ const compileResult = compileProject(schemaResult.data);
5041
6542
  diagnostics = diagnosticsFromCompiler(compileResult);
5042
6543
  if (!compileResult.ok) {
5043
6544
  const output = jsonMode ? jsonOutput({ diagnostics }) : diagnostics.map(
@@ -5115,9 +6616,8 @@ async function testCommand(args, stdinInput, captureOutput = false) {
5115
6616
  }
5116
6617
 
5117
6618
  // packages/cli/src/commands/verify.ts
5118
- import { resolve as resolve6 } from "node:path";
5119
- import { compileProject as compileProject4 } from "@rogatio/compiler";
5120
- import { validateProjectDetailed as validateProjectDetailed4 } from "@rogatio/schema";
6619
+ import { resolve as resolve7 } from "node:path";
6620
+ init_node();
5121
6621
  async function verifyCommandImpl(args, stdinInput, captureOutput) {
5122
6622
  let filePath;
5123
6623
  let jsonOutput2 = false;
@@ -5143,9 +6643,9 @@ async function verifyCommandImpl(args, stdinInput, captureOutput) {
5143
6643
  }
5144
6644
  filePath = "<stdin>";
5145
6645
  } else if (inputPath) {
5146
- filePath = resolve6(inputPath);
6646
+ filePath = resolve7(inputPath);
5147
6647
  } else {
5148
- filePath = resolve6(process.cwd(), ".rogatio.json");
6648
+ filePath = resolve7(process.cwd(), ".rogatio.json");
5149
6649
  }
5150
6650
  let projectData;
5151
6651
  try {
@@ -5163,7 +6663,7 @@ async function verifyCommandImpl(args, stdinInput, captureOutput) {
5163
6663
  console.error(output2.trim());
5164
6664
  return 2;
5165
6665
  }
5166
- const schemaResult = validateProjectDetailed4(projectData);
6666
+ const schemaResult = validateProjectDetailed(projectData);
5167
6667
  const diagnostics = [];
5168
6668
  if (!schemaResult.valid) {
5169
6669
  for (const error of schemaResult.errors) {
@@ -5176,7 +6676,7 @@ async function verifyCommandImpl(args, stdinInput, captureOutput) {
5176
6676
  });
5177
6677
  }
5178
6678
  } else {
5179
- const compileResult = compileProject4(schemaResult.data);
6679
+ const compileResult = compileProject(schemaResult.data);
5180
6680
  if (!compileResult.ok) {
5181
6681
  for (const diag of compileResult.diagnostics) {
5182
6682
  diagnostics.push({
@@ -5213,11 +6713,10 @@ async function verifyCommand(args, stdinInput, captureOutput = false) {
5213
6713
  }
5214
6714
 
5215
6715
  // packages/cli/src/index.ts
5216
- var __dirname = dirname4(fileURLToPath2(import.meta.url));
5217
- var isDist = __dirname.includes("/dist/") || __dirname.includes("\\dist\\");
5218
- var packageJsonPath = resolve7(
6716
+ var __dirname = dirname5(fileURLToPath2(import.meta.url));
6717
+ var packageJsonPath = resolve8(
5219
6718
  __dirname,
5220
- isDist ? "../../package.json" : "../package.json"
6719
+ isDistBuild(__dirname) ? "../../package.json" : "../package.json"
5221
6720
  );
5222
6721
  var packageJson = JSON.parse(
5223
6722
  await import("node:fs/promises").then(
@@ -5309,8 +6808,8 @@ Commands:
5309
6808
  edit [path] Launch browser editor for .rogatio.json
5310
6809
  test [path] [url...] Run offline dry-run tests against .rogatio.json
5311
6810
  verify [path] Validate .rogatio.json file
5312
- runtime <start|stop|status|install|trust|untrust|uninstall> Native messaging runtime and request-body trust control
5313
- runtime-host [path] Run the consolidated native-messaging runtime host
6811
+ runtime <activate|deactivate|status|install|trust|untrust|uninstall> Native messaging runtime activation and request-body trust control
6812
+ runtime host [path] Run the consolidated native-messaging runtime host
5314
6813
 
5315
6814
  Global Options:
5316
6815
  --help, -h Show help
@@ -5354,16 +6853,17 @@ Exit codes:
5354
6853
  }
5355
6854
  function showRuntimeHelp2() {
5356
6855
  console.log(`Usage: rogatio runtime <command> [options]
5357
- rogatio runtime-host [path]
6856
+ rogatio runtime host [path]
5358
6857
 
5359
6858
  Native messaging runtime control for response-body and request-body rules. The
5360
6859
  runtime no longer serves an HTTP mock server; mock delivery happens in the
5361
6860
  consolidated native-messaging host (spec REQ-001..REQ-005).
5362
6861
 
5363
6862
  Native runtime commands:
5364
- start Start the runtime (explicit, no auto-start)
5365
- stop Stop the runtime (idempotent)
5366
- status Show the current runtime and trust state
6863
+ activate Activate the runtime (explicit, no auto-activation)
6864
+ deactivate Deactivate the runtime (idempotent)
6865
+ host [path] Run the consolidated native-messaging runtime host
6866
+ status Show the current runtime and trust state
5367
6867
 
5368
6868
  Request-body trust commands:
5369
6869
  install Install the native-messaging host manifest (requires --extension-id)
@@ -5372,17 +6872,17 @@ Request-body trust commands:
5372
6872
  uninstall Uninstall the native-messaging host manifest (idempotent)
5373
6873
 
5374
6874
  Native host command:
5375
- runtime-host [path] Run the consolidated native-messaging runtime host. The
5376
- browser launches this process via the native-messaging
5377
- manifest; it reads pairing/authorization/mock envelopes from
5378
- stdin and writes responses to stdout.
6875
+ host [path] Run the consolidated native-messaging runtime host. The browser
6876
+ launches this process via the native-messaging manifest; it reads
6877
+ pairing/authorization/mock envelopes from stdin and writes
6878
+ responses to stdout.
5379
6879
 
5380
6880
  Options:
5381
6881
  --root <dir> Root for confined file mocks (default: project directory)
5382
6882
  --extension-id Extension ID for native messaging manifest (required for install)
5383
6883
  --help, -h Show this help
5384
6884
 
5385
- The native runtime activates unconditionally once started; the device-local CA /
6885
+ The native runtime activates unconditionally once activated; the device-local CA /
5386
6886
  PAC routing capability only affects request-body interception, not the host
5387
6887
  control plane.
5388
6888
 
@@ -5423,7 +6923,7 @@ Exit codes:
5423
6923
  1 Validation/compile/test errors
5424
6924
  2 Usage error (invalid arguments, missing input)`);
5425
6925
  }
5426
- if (process.argv[1] !== void 0 && realpathSync.native(fileURLToPath2(import.meta.url)) === realpathSync.native(resolve7(process.argv[1]))) {
6926
+ if (process.argv[1] !== void 0 && realpathSync.native(fileURLToPath2(import.meta.url)) === realpathSync.native(resolve8(process.argv[1]))) {
5427
6927
  if (basename4(process.argv[1]) === "runtime-host") {
5428
6928
  runRuntimeHostEntry().catch((err) => {
5429
6929
  console.error(err);