@orygn/opa-mcp 0.3.0 → 0.5.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.
Files changed (157) hide show
  1. package/CHANGELOG.md +396 -3
  2. package/README.md +132 -98
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +8 -3
  5. package/dist/cli.js.map +1 -1
  6. package/dist/config.d.ts +15 -3
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +74 -14
  9. package/dist/config.js.map +1 -1
  10. package/dist/constants.d.ts +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/lib/bundle-signatures.d.ts +23 -0
  13. package/dist/lib/bundle-signatures.d.ts.map +1 -0
  14. package/dist/lib/bundle-signatures.js +152 -0
  15. package/dist/lib/bundle-signatures.js.map +1 -0
  16. package/dist/lib/child-env.d.ts +41 -0
  17. package/dist/lib/child-env.d.ts.map +1 -0
  18. package/dist/lib/child-env.js +176 -0
  19. package/dist/lib/child-env.js.map +1 -0
  20. package/dist/lib/conftest-cli.d.ts +25 -10
  21. package/dist/lib/conftest-cli.d.ts.map +1 -1
  22. package/dist/lib/conftest-cli.js +153 -33
  23. package/dist/lib/conftest-cli.js.map +1 -1
  24. package/dist/lib/install-id.d.ts.map +1 -1
  25. package/dist/lib/install-id.js +18 -3
  26. package/dist/lib/install-id.js.map +1 -1
  27. package/dist/lib/json-stream.d.ts +26 -0
  28. package/dist/lib/json-stream.d.ts.map +1 -0
  29. package/dist/lib/json-stream.js +69 -0
  30. package/dist/lib/json-stream.js.map +1 -0
  31. package/dist/lib/opa-cli.d.ts +64 -16
  32. package/dist/lib/opa-cli.d.ts.map +1 -1
  33. package/dist/lib/opa-cli.js +99 -28
  34. package/dist/lib/opa-cli.js.map +1 -1
  35. package/dist/lib/opa-paths.d.ts +24 -0
  36. package/dist/lib/opa-paths.d.ts.map +1 -0
  37. package/dist/lib/opa-paths.js +97 -0
  38. package/dist/lib/opa-paths.js.map +1 -0
  39. package/dist/lib/regal-cli.d.ts +16 -1
  40. package/dist/lib/regal-cli.d.ts.map +1 -1
  41. package/dist/lib/regal-cli.js +41 -6
  42. package/dist/lib/regal-cli.js.map +1 -1
  43. package/dist/lib/rego-ast-walker.d.ts.map +1 -1
  44. package/dist/lib/rego-ast-walker.js +141 -17
  45. package/dist/lib/rego-ast-walker.js.map +1 -1
  46. package/dist/lib/rego-counterexample.d.ts +1 -1
  47. package/dist/lib/rego-counterexample.d.ts.map +1 -1
  48. package/dist/lib/rego-counterexample.js +23 -5
  49. package/dist/lib/rego-counterexample.js.map +1 -1
  50. package/dist/lib/rego-ir.d.ts +32 -2
  51. package/dist/lib/rego-ir.d.ts.map +1 -1
  52. package/dist/lib/rego-smt-encoder.d.ts +53 -5
  53. package/dist/lib/rego-smt-encoder.d.ts.map +1 -1
  54. package/dist/lib/rego-smt-encoder.js +192 -26
  55. package/dist/lib/rego-smt-encoder.js.map +1 -1
  56. package/dist/lib/rego-type-inferencer.d.ts +1 -1
  57. package/dist/lib/rego-type-inferencer.d.ts.map +1 -1
  58. package/dist/lib/rego-type-inferencer.js +3 -3
  59. package/dist/lib/rego-type-inferencer.js.map +1 -1
  60. package/dist/lib/rego-verify-engine.d.ts.map +1 -1
  61. package/dist/lib/rego-verify-engine.js +109 -77
  62. package/dist/lib/rego-verify-engine.js.map +1 -1
  63. package/dist/lib/rego-z3.d.ts +10 -0
  64. package/dist/lib/rego-z3.d.ts.map +1 -1
  65. package/dist/lib/rego-z3.js +38 -0
  66. package/dist/lib/rego-z3.js.map +1 -1
  67. package/dist/lib/security.d.ts +8 -0
  68. package/dist/lib/security.d.ts.map +1 -1
  69. package/dist/lib/security.js +130 -54
  70. package/dist/lib/security.js.map +1 -1
  71. package/dist/lib/subprocess.d.ts +36 -3
  72. package/dist/lib/subprocess.d.ts.map +1 -1
  73. package/dist/lib/subprocess.js +121 -20
  74. package/dist/lib/subprocess.js.map +1 -1
  75. package/dist/lib/tool-helpers.d.ts.map +1 -1
  76. package/dist/lib/tool-helpers.js +10 -0
  77. package/dist/lib/tool-helpers.js.map +1 -1
  78. package/dist/resources/patterns.d.ts +1 -1
  79. package/dist/resources/patterns.d.ts.map +1 -1
  80. package/dist/resources/patterns.js +40 -12
  81. package/dist/resources/patterns.js.map +1 -1
  82. package/dist/server.d.ts.map +1 -1
  83. package/dist/server.js +10 -2
  84. package/dist/server.js.map +1 -1
  85. package/dist/tools/authoring/check-schema.js +1 -1
  86. package/dist/tools/authoring/check-schema.js.map +1 -1
  87. package/dist/tools/bundles/build.d.ts.map +1 -1
  88. package/dist/tools/bundles/build.js +12 -4
  89. package/dist/tools/bundles/build.js.map +1 -1
  90. package/dist/tools/bundles/sign.d.ts +9 -2
  91. package/dist/tools/bundles/sign.d.ts.map +1 -1
  92. package/dist/tools/bundles/sign.js +145 -19
  93. package/dist/tools/bundles/sign.js.map +1 -1
  94. package/dist/tools/bundles/verify.d.ts +1 -1
  95. package/dist/tools/bundles/verify.d.ts.map +1 -1
  96. package/dist/tools/bundles/verify.js +58 -19
  97. package/dist/tools/bundles/verify.js.map +1 -1
  98. package/dist/tools/conftest/pull.d.ts.map +1 -1
  99. package/dist/tools/conftest/pull.js +24 -10
  100. package/dist/tools/conftest/pull.js.map +1 -1
  101. package/dist/tools/conftest/push.d.ts.map +1 -1
  102. package/dist/tools/conftest/push.js +17 -7
  103. package/dist/tools/conftest/push.js.map +1 -1
  104. package/dist/tools/conftest/test.d.ts +10 -6
  105. package/dist/tools/conftest/test.d.ts.map +1 -1
  106. package/dist/tools/conftest/test.js +47 -24
  107. package/dist/tools/conftest/test.js.map +1 -1
  108. package/dist/tools/conftest/verify.d.ts +10 -6
  109. package/dist/tools/conftest/verify.d.ts.map +1 -1
  110. package/dist/tools/conftest/verify.js +30 -18
  111. package/dist/tools/conftest/verify.js.map +1 -1
  112. package/dist/tools/evaluation/bench.d.ts +16 -0
  113. package/dist/tools/evaluation/bench.d.ts.map +1 -1
  114. package/dist/tools/evaluation/bench.js +30 -5
  115. package/dist/tools/evaluation/bench.js.map +1 -1
  116. package/dist/tools/evaluation/exec.d.ts +16 -0
  117. package/dist/tools/evaluation/exec.d.ts.map +1 -1
  118. package/dist/tools/evaluation/exec.js +35 -2
  119. package/dist/tools/evaluation/exec.js.map +1 -1
  120. package/dist/tools/evaluation/test-multiroot.d.ts +4 -0
  121. package/dist/tools/evaluation/test-multiroot.d.ts.map +1 -1
  122. package/dist/tools/evaluation/test-multiroot.js +21 -14
  123. package/dist/tools/evaluation/test-multiroot.js.map +1 -1
  124. package/dist/tools/evaluation/test.d.ts +45 -0
  125. package/dist/tools/evaluation/test.d.ts.map +1 -1
  126. package/dist/tools/evaluation/test.js +146 -27
  127. package/dist/tools/evaluation/test.js.map +1 -1
  128. package/dist/tools/helpers/coverage-gaps.d.ts +11 -3
  129. package/dist/tools/helpers/coverage-gaps.d.ts.map +1 -1
  130. package/dist/tools/helpers/coverage-gaps.js +4 -3
  131. package/dist/tools/helpers/coverage-gaps.js.map +1 -1
  132. package/dist/tools/helpers/explain-undefined.d.ts +9 -3
  133. package/dist/tools/helpers/explain-undefined.d.ts.map +1 -1
  134. package/dist/tools/helpers/explain-undefined.js +83 -51
  135. package/dist/tools/helpers/explain-undefined.js.map +1 -1
  136. package/dist/tools/helpers/verify.d.ts.map +1 -1
  137. package/dist/tools/helpers/verify.js +5 -1
  138. package/dist/tools/helpers/verify.js.map +1 -1
  139. package/dist/tools/server-management/_shared.d.ts +15 -4
  140. package/dist/tools/server-management/_shared.d.ts.map +1 -1
  141. package/dist/tools/server-management/_shared.js +73 -12
  142. package/dist/tools/server-management/_shared.js.map +1 -1
  143. package/dist/tools/server-management/data.d.ts.map +1 -1
  144. package/dist/tools/server-management/data.js +88 -23
  145. package/dist/tools/server-management/data.js.map +1 -1
  146. package/dist/tools/server-management/decisions.d.ts.map +1 -1
  147. package/dist/tools/server-management/decisions.js +16 -3
  148. package/dist/tools/server-management/decisions.js.map +1 -1
  149. package/dist/tools/server-management/policies.d.ts.map +1 -1
  150. package/dist/tools/server-management/policies.js +44 -7
  151. package/dist/tools/server-management/policies.js.map +1 -1
  152. package/dist/tools/server-management/status.d.ts.map +1 -1
  153. package/dist/tools/server-management/status.js +80 -13
  154. package/dist/tools/server-management/status.js.map +1 -1
  155. package/dist/types.d.ts +10 -1
  156. package/dist/types.d.ts.map +1 -1
  157. package/package.json +2 -1
@@ -3,7 +3,7 @@ import { inferTypes } from './rego-type-inferencer.js';
3
3
  import { createInputVars, encodeRule } from './rego-smt-encoder.js';
4
4
  import { extractCounterexample, formatCounterexample, } from './rego-counterexample.js';
5
5
  import { describeProperty } from './rego-property-parser.js';
6
- import { getZ3 } from './rego-z3.js';
6
+ import { getZ3, withZ3Lock } from './rego-z3.js';
7
7
  // Monotonically increasing counter used to generate a unique prefix for all
8
8
  // Z3 constant names within each runVerify call. This prevents sort conflicts
9
9
  // when the same input path is inferred with different sorts across calls
@@ -59,98 +59,130 @@ export async function runVerify(ast, property, signal) {
59
59
  warnings.push(conflict.reason);
60
60
  }
61
61
  signal?.throwIfAborted();
62
- const Z3 = await getZ3();
63
- signal?.throwIfAborted();
64
- const callId = `v${_verifyCallCounter++}`;
65
- const inputVars = createInputVars(Z3, walked.inputPaths, typeResult.sorts, callId);
66
- const ctx = { Z3, inputVars, sorts: typeResult.sorts, callId };
67
- const encoded = encodeRule(targetClauses, ctx);
68
- warnings.push(...encoded.warnings);
69
- // Z3's high-level Solver and Model objects use FinalizationRegistry internally
70
- // (solver_dec_ref / model_dec_ref) so they are cleaned up when GC'd.
71
- // We avoid holding a reference to the Model beyond extractCounterexample so
72
- // it becomes eligible for GC as soon as the call returns, reducing WASM heap
73
- // pressure under high call volume.
74
- const solver = new Z3.Solver();
75
- // Set timeout to prevent hanging on complex policies
76
- solver.set('timeout', SOLVER_TIMEOUT_MS);
77
- switch (property.kind) {
78
- case 'always_true':
79
- // Prove rule is always true: check if NOT(rule) is satisfiable.
80
- // SAT → counterexample (input where rule is false)
81
- // UNSAT → proven always true
82
- solver.add(Z3.Not(encoded.formula));
83
- break;
84
- case 'never_true':
85
- // Prove rule is never true: check if rule IS satisfiable.
86
- // SAT → counterexample (input where rule fires, violating "never")
87
- // UNSAT → proven never true
88
- solver.add(encoded.formula);
89
- break;
90
- case 'satisfiable':
91
- // Check if any input satisfies the rule.
92
- // SAT → witness found (not a bug, just a satisfying input)
93
- // UNSAT → rule is vacuously false / dead code
94
- solver.add(encoded.formula);
95
- break;
96
- }
97
- signal?.throwIfAborted();
98
- const solverResult = await solver.check();
99
- if (solverResult === 'unknown') {
100
- return inconclusive(property, `Z3 solver returned "unknown" (timeout or resource limit reached after ${SOLVER_TIMEOUT_MS}ms). The policy may be too complex for automated verification.`, unsupportedInRule, warnings);
101
- }
102
- if (solverResult === 'unsat') {
62
+ // Everything below touches the shared Z3 Context, which is one
63
+ // single-threaded WASM heap. Concurrent MCP tool calls must not overlap
64
+ // here: two solves interleaving on that heap degraded verdicts to
65
+ // inconclusive and crashed the WASM allocator. The lock also makes the
66
+ // callId counter race-free.
67
+ return await withZ3Lock(async () => {
68
+ const Z3 = await getZ3();
69
+ signal?.throwIfAborted();
70
+ const callId = `v${_verifyCallCounter++}`;
71
+ const { vars: inputVars, presence: presenceVars } = createInputVars(Z3, walked.inputPaths, typeResult.sorts, callId);
72
+ const ctx = { Z3, inputVars, presenceVars, sorts: typeResult.sorts, callId };
73
+ // The rule's default participates in "is it true", so it must reach the
74
+ // encoder. Consulting it only when there were no clauses at all is what made
75
+ // `default allow := true` plus a guard clause verify as never-true.
76
+ const encoded = encodeRule(targetClauses, ctx, walked.defaults.get(property.ruleName));
77
+ warnings.push(...encoded.warnings);
78
+ if (encoded.unencodable) {
79
+ return inconclusive(property, `Rule "${property.ruleName}" contains a value or operand the encoder cannot represent (for example a null literal). Verification is inconclusive rather than guessed.`, unsupportedInRule, warnings);
80
+ }
81
+ // Z3's high-level Solver and Model objects use FinalizationRegistry internally
82
+ // (solver_dec_ref / model_dec_ref) so they are cleaned up when GC'd.
83
+ // We avoid holding a reference to the Model beyond extractCounterexample so
84
+ // it becomes eligible for GC as soon as the call returns, reducing WASM heap
85
+ // pressure under high call volume.
86
+ const solver = new Z3.Solver();
87
+ // Set timeout to prevent hanging on complex policies
88
+ solver.set('timeout', SOLVER_TIMEOUT_MS);
89
+ switch (property.kind) {
90
+ case 'always_true':
91
+ // Prove rule is always true: check if NOT(rule) is satisfiable.
92
+ // SAT → counterexample (input where rule is false)
93
+ // UNSAT → proven always true
94
+ solver.add(Z3.Not(encoded.formula));
95
+ break;
96
+ case 'never_true':
97
+ // Prove rule is never true: check if rule IS satisfiable.
98
+ // SAT → counterexample (input where rule fires, violating "never")
99
+ // UNSAT → proven never true
100
+ solver.add(encoded.formula);
101
+ break;
102
+ case 'satisfiable':
103
+ // Check if any input satisfies the rule.
104
+ // SAT → witness found (not a bug, just a satisfying input)
105
+ // UNSAT → rule is vacuously false / dead code
106
+ solver.add(encoded.formula);
107
+ break;
108
+ }
109
+ signal?.throwIfAborted();
110
+ let solverResult = await solver.check();
111
+ // Prefer a witness in which every field the rule reads is PRESENT.
112
+ //
113
+ // With absence modelled, Z3 will happily satisfy NOT(rule) by omitting a
114
+ // field, which is sound but unhelpful: "it fails when the input is empty"
115
+ // is rarely the case a reviewer is chasing. Re-ask with presence forced and
116
+ // keep that model when one exists, otherwise fall back to the original.
117
+ // Soundness is unaffected either way, since both are real models.
118
+ if (solverResult === 'sat' && presenceVars.size > 0) {
119
+ solver.push();
120
+ for (const present of presenceVars.values())
121
+ solver.add(present);
122
+ const withPresence = await solver.check();
123
+ if (withPresence === 'sat') {
124
+ solverResult = withPresence;
125
+ }
126
+ else {
127
+ solver.pop();
128
+ }
129
+ }
130
+ if (solverResult === 'unknown') {
131
+ return inconclusive(property, `Z3 solver returned "unknown" (timeout or resource limit reached after ${SOLVER_TIMEOUT_MS}ms). The policy may be too complex for automated verification.`, unsupportedInRule, warnings);
132
+ }
133
+ if (solverResult === 'unsat') {
134
+ if (property.kind === 'satisfiable') {
135
+ // No satisfying input exists -- rule is dead code or has contradictory conditions.
136
+ return {
137
+ verdict: 'unsatisfiable',
138
+ property: describeProperty(property),
139
+ rule: property.ruleName,
140
+ unsupportedConstructs: unsupportedInRule,
141
+ warnings,
142
+ message: `UNSATISFIABLE: No input can make "${property.ruleName}" true. The rule may be dead code or have contradictory conditions.`,
143
+ };
144
+ }
145
+ // For always_true / never_true: UNSAT on the negation = property proven
146
+ return {
147
+ verdict: 'proven',
148
+ property: describeProperty(property),
149
+ rule: property.ruleName,
150
+ unsupportedConstructs: unsupportedInRule,
151
+ warnings,
152
+ message: `PROVEN: ${describeProperty(property)}.`,
153
+ };
154
+ }
155
+ // SAT: pass solver.model() inline so the Model object is not kept alive
156
+ // beyond extractCounterexample -- it becomes GC-eligible immediately after.
157
+ const ce = extractCounterexample(solver.model(), inputVars, typeResult.sorts, presenceVars);
158
+ const ceFormatted = formatCounterexample(ce);
103
159
  if (property.kind === 'satisfiable') {
104
- // No satisfying input exists -- rule is dead code or has contradictory conditions.
105
160
  return {
106
- verdict: 'unsatisfiable',
161
+ verdict: 'proven',
107
162
  property: describeProperty(property),
108
163
  rule: property.ruleName,
164
+ counterexample: ce,
165
+ counterexampleFormatted: ceFormatted,
109
166
  unsupportedConstructs: unsupportedInRule,
110
167
  warnings,
111
- message: `UNSATISFIABLE: No input can make "${property.ruleName}" true. The rule may be dead code or have contradictory conditions.`,
168
+ message: `SATISFIABLE: Found an input that makes "${property.ruleName}" true.\n\nWitness input:\n${ceFormatted}`,
112
169
  };
113
170
  }
114
- // For always_true / never_true: UNSAT on the negation = property proven
171
+ // always_true / never_true: SAT means we found a violation
172
+ const ceLabel = property.kind === 'always_true'
173
+ ? 'input where rule is FALSE'
174
+ : 'input where rule is TRUE (violates "never")';
115
175
  return {
116
- verdict: 'proven',
117
- property: describeProperty(property),
118
- rule: property.ruleName,
119
- unsupportedConstructs: unsupportedInRule,
120
- warnings,
121
- message: `PROVEN: ${describeProperty(property)}.`,
122
- };
123
- }
124
- // SAT: pass solver.model() inline so the Model object is not kept alive
125
- // beyond extractCounterexample -- it becomes GC-eligible immediately after.
126
- const ce = extractCounterexample(solver.model(), inputVars, typeResult.sorts);
127
- const ceFormatted = formatCounterexample(ce);
128
- if (property.kind === 'satisfiable') {
129
- return {
130
- verdict: 'proven',
176
+ verdict: 'counterexample',
131
177
  property: describeProperty(property),
132
178
  rule: property.ruleName,
133
179
  counterexample: ce,
134
180
  counterexampleFormatted: ceFormatted,
135
181
  unsupportedConstructs: unsupportedInRule,
136
182
  warnings,
137
- message: `SATISFIABLE: Found an input that makes "${property.ruleName}" true.\n\nWitness input:\n${ceFormatted}`,
183
+ message: `COUNTEREXAMPLE: Property does NOT hold. Found ${ceLabel}:\n\n${ceFormatted}`,
138
184
  };
139
- }
140
- // always_true / never_true: SAT means we found a violation
141
- const ceLabel = property.kind === 'always_true'
142
- ? 'input where rule is FALSE'
143
- : 'input where rule is TRUE (violates "never")';
144
- return {
145
- verdict: 'counterexample',
146
- property: describeProperty(property),
147
- rule: property.ruleName,
148
- counterexample: ce,
149
- counterexampleFormatted: ceFormatted,
150
- unsupportedConstructs: unsupportedInRule,
151
- warnings,
152
- message: `COUNTEREXAMPLE: Property does NOT hold. Found ${ceLabel}:\n\n${ceFormatted}`,
153
- };
185
+ });
154
186
  }
155
187
  catch (e) {
156
188
  // A cancellation must propagate as a cancellation, not be masked as a
@@ -1 +1 @@
1
- {"version":3,"file":"rego-verify-engine.js","sourceRoot":"","sources":["../../src/lib/rego-verify-engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rego-verify-engine.js","sourceRoot":"","sources":["../../src/lib/rego-verify-engine.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,16 @@ export type Z3Context = ReturnType<Awaited<ReturnType<typeof Z3Init>>['Context']
5
5
  * Safe to call from concurrent async paths.
6
6
  */
7
7
  export declare function getZ3(): Promise<Z3Context>;
8
+ /**
9
+ * Run `fn` with exclusive access to the shared Z3 Context.
10
+ *
11
+ * Serializes rather than parallelizes: an MCP client is free to issue several
12
+ * rego_verify calls at once, and letting them into the WASM heap together
13
+ * crashes it. Solve times are in the tens of milliseconds, so queueing is
14
+ * cheaper than the alternative of one Context per call, which would re-pay the
15
+ * WASM init cost every time.
16
+ */
17
+ export declare function withZ3Lock<T>(fn: () => Promise<T>): Promise<T>;
8
18
  /**
9
19
  * Reset the singleton - intended for test teardown only.
10
20
  * Do NOT call in production paths; re-init is expensive.
@@ -1 +1 @@
1
- {"version":3,"file":"rego-z3.d.ts","sourceRoot":"","sources":["../../src/lib/rego-z3.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,WAAW,CAAC;AAKhD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAKlF;;;GAGG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,SAAS,CAAC,CAKhD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
1
+ {"version":3,"file":"rego-z3.d.ts","sourceRoot":"","sources":["../../src/lib/rego-z3.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,WAAW,CAAC;AAKhD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAKlF;;;GAGG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,SAAS,CAAC,CAKhD;AASD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAapE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
@@ -5,6 +5,13 @@
5
5
  * initialized once per process. Concurrent calls safely await the
6
6
  * same promise. Each verification call creates its own fresh Solver
7
7
  * from the shared Context, so contexts never accumulate stale state.
8
+ *
9
+ * A fresh Solver is NOT enough to make concurrent verification safe. The whole
10
+ * Context lives in one single-threaded WASM heap, and `check()` is async, so two
11
+ * overlapping solves interleave on that heap and corrupt each other: observed
12
+ * symptoms were verdicts degrading to `inconclusive` and an allocator crash
13
+ * inside the WASM module. Everything touching the Context must therefore run
14
+ * under `withZ3Lock`.
8
15
  */
9
16
  import { init } from 'z3-solver';
10
17
  // Module-level singleton
@@ -19,11 +26,42 @@ export async function getZ3() {
19
26
  }
20
27
  return z3InitPromise;
21
28
  }
29
+ /**
30
+ * Tail of the queue of pending Z3 critical sections. Each acquirer waits on the
31
+ * current tail and installs its own completion as the new tail, so sections run
32
+ * in call order with no overlap.
33
+ */
34
+ let z3LockTail = Promise.resolve();
35
+ /**
36
+ * Run `fn` with exclusive access to the shared Z3 Context.
37
+ *
38
+ * Serializes rather than parallelizes: an MCP client is free to issue several
39
+ * rego_verify calls at once, and letting them into the WASM heap together
40
+ * crashes it. Solve times are in the tens of milliseconds, so queueing is
41
+ * cheaper than the alternative of one Context per call, which would re-pay the
42
+ * WASM init cost every time.
43
+ */
44
+ export async function withZ3Lock(fn) {
45
+ let release;
46
+ const mine = new Promise((resolve) => {
47
+ release = resolve;
48
+ });
49
+ const predecessor = z3LockTail;
50
+ z3LockTail = predecessor.then(() => mine);
51
+ await predecessor;
52
+ try {
53
+ return await fn();
54
+ }
55
+ finally {
56
+ release();
57
+ }
58
+ }
22
59
  /**
23
60
  * Reset the singleton - intended for test teardown only.
24
61
  * Do NOT call in production paths; re-init is expensive.
25
62
  */
26
63
  export function resetZ3ForTesting() {
27
64
  z3InitPromise = null;
65
+ z3LockTail = Promise.resolve();
28
66
  }
29
67
  //# sourceMappingURL=rego-z3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rego-z3.js","sourceRoot":"","sources":["../../src/lib/rego-z3.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,yBAAyB;AACzB,IAAI,aAAa,GAA4B,IAAI,CAAC;AAElD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,aAAa,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,aAAmC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,aAAa,GAAG,IAAI,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"rego-z3.js","sourceRoot":"","sources":["../../src/lib/rego-z3.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,yBAAyB;AACzB,IAAI,aAAa,GAA4B,IAAI,CAAC;AAElD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,aAAa,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,aAAmC,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,IAAI,UAAU,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;AAElD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,EAAoB;IACtD,IAAI,OAAoB,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACzC,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,UAAU,CAAC;IAC/B,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,WAAW,CAAC;IAClB,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,aAAa,GAAG,IAAI,CAAC;IACrB,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;AACjC,CAAC"}
@@ -7,6 +7,14 @@ export interface PathValidationResult {
7
7
  /**
8
8
  * Resolve `inputPath` and confirm it is contained within at least one
9
9
  * `allowedRoots` entry. Returns the resolved absolute path on success.
10
+ *
11
+ * Two checks, both of which must pass. The first is syntactic: `..` segments
12
+ * are collapsed without touching the disk and the result must sit under a
13
+ * root as written. The second follows the filesystem: the path's real
14
+ * location, including the part of it that does not exist yet, must sit under
15
+ * a root's real location. A link is still followed at read or write time by
16
+ * the tool that receives the path, so the check is against the layout at the
17
+ * moment of validation.
10
18
  */
11
19
  export declare function validatePath(inputPath: string, allowedRoots: string[], options?: {
12
20
  mustExist?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,oBAAoB,CAwGtB;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;CAC7B;AA6ED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,oBAAoB,CAsGtB;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD"}
@@ -5,12 +5,90 @@
5
5
  * `validatePath` to prevent reading or writing outside the
6
6
  * agreed-upon roots.
7
7
  */
8
- import { existsSync, realpathSync, statSync } from 'node:fs';
9
- import { isAbsolute, resolve, sep } from 'node:path';
8
+ import { lstatSync, realpathSync, statSync } from 'node:fs';
9
+ import { basename, dirname, isAbsolute, join, resolve, sep } from 'node:path';
10
10
  import { err } from './errors.js';
11
+ const WINDOWS = process.platform === 'win32';
12
+ /**
13
+ * Canonical form of an existing path: every link resolved, and on Windows
14
+ * 8.3 short names expanded and on-disk casing restored. The JavaScript
15
+ * `realpathSync` resolves links but leaves short names and casing alone, so
16
+ * two spellings of one directory could compare unequal.
17
+ */
18
+ function canonical(p) {
19
+ return realpathSync.native(p);
20
+ }
21
+ /** Does `p` fall under at least one of `roots`? */
22
+ function isUnderRoots(p, roots, caseInsensitive) {
23
+ const fold = (s) => (caseInsensitive ? s.toLowerCase() : s);
24
+ const candidate = fold(p);
25
+ return roots.some((root) => {
26
+ const r = fold(root);
27
+ const rootWithSep = r.endsWith(sep) ? r : r + sep;
28
+ return candidate === r || candidate.startsWith(rootWithSep);
29
+ });
30
+ }
31
+ /**
32
+ * Where a path really leads, whether or not it exists yet.
33
+ *
34
+ * Walks up from `p` to the nearest entry that exists, resolves that entry's
35
+ * real location, and re-attaches the segments below it. A write to `p` lands
36
+ * under that real location, so that is what has to be checked against the
37
+ * roots. Checking only paths that already exist left every not-yet-created
38
+ * write target unchecked, and a junction or symlink inside a root could point
39
+ * it anywhere.
40
+ *
41
+ * An entry that exists only as a link to something that does not exist (a
42
+ * dangling link) is reported on its own: a write through it would create the
43
+ * target wherever the link points.
44
+ */
45
+ function realLocation(p) {
46
+ const below = [];
47
+ let cur = p;
48
+ for (;;) {
49
+ let entry;
50
+ try {
51
+ entry = lstatSync(cur);
52
+ }
53
+ catch (e) {
54
+ const code = e.code;
55
+ if (code === 'ENOENT' || code === 'ENOTDIR') {
56
+ const parent = dirname(cur);
57
+ if (parent === cur)
58
+ return { kind: 'unresolvable', reason: 'no existing ancestor' };
59
+ below.unshift(basename(cur));
60
+ cur = parent;
61
+ continue;
62
+ }
63
+ return { kind: 'unresolvable', reason: code ?? String(e) };
64
+ }
65
+ let real;
66
+ try {
67
+ real = canonical(cur);
68
+ }
69
+ catch (e) {
70
+ if (entry.isSymbolicLink())
71
+ return { kind: 'dangling', link: cur };
72
+ return { kind: 'unresolvable', reason: e.code ?? String(e) };
73
+ }
74
+ return {
75
+ kind: 'real',
76
+ path: below.length === 0 ? real : join(real, ...below),
77
+ exists: below.length === 0,
78
+ };
79
+ }
80
+ }
11
81
  /**
12
82
  * Resolve `inputPath` and confirm it is contained within at least one
13
83
  * `allowedRoots` entry. Returns the resolved absolute path on success.
84
+ *
85
+ * Two checks, both of which must pass. The first is syntactic: `..` segments
86
+ * are collapsed without touching the disk and the result must sit under a
87
+ * root as written. The second follows the filesystem: the path's real
88
+ * location, including the part of it that does not exist yet, must sit under
89
+ * a root's real location. A link is still followed at read or write time by
90
+ * the tool that receives the path, so the check is against the layout at the
91
+ * moment of validation.
14
92
  */
15
93
  export function validatePath(inputPath, allowedRoots, options = {}) {
16
94
  if (typeof inputPath !== 'string' || inputPath.length === 0) {
@@ -28,24 +106,42 @@ export function validatePath(inputPath, allowedRoots, options = {}) {
28
106
  };
29
107
  }
30
108
  const resolved = isAbsolute(inputPath) ? resolve(inputPath) : resolve(process.cwd(), inputPath);
31
- // Helper: confirm p falls under at least one of the provided root strings.
32
- const isUnderRoots = (p, roots) => roots.some((root) => {
33
- const rootWithSep = root.endsWith(sep) ? root : root + sep;
34
- return p === root || p.startsWith(rootWithSep);
35
- });
36
- // Phase 1: syntactic traversal check. path.resolve() collapses `..`
37
- // segments without I/O, so this catches plain traversal attacks cheaply.
38
109
  const resolvedRoots = allowedRoots.map((r) => resolve(r));
39
- if (!isUnderRoots(resolved, resolvedRoots)) {
110
+ const outsideHint = 'Set OPA_MCP_ALLOWED_PATHS to a comma-separated list of directories, or use a path under the current allowed roots.';
111
+ // Phase 1: syntactic containment, cheap and free of I/O. It is not the
112
+ // decision on its own: a root spelled through a link (macOS /var, a Windows
113
+ // short name, a junction) and a path spelled through the target land in the
114
+ // same real place and must be accepted. It settles which message an
115
+ // escaping path gets. Windows compares without regard to case.
116
+ const syntacticallyInside = isUnderRoots(resolved, resolvedRoots, WINDOWS);
117
+ const outsideRoots = () => err('PATH_NOT_ALLOWED', `Path is outside allowed roots: ${inputPath}`, {
118
+ hint: outsideHint,
119
+ details: { resolved, allowedRoots },
120
+ });
121
+ // Phase 2: real location. This is the decision.
122
+ const location = realLocation(resolved);
123
+ if (location.kind === 'dangling') {
124
+ return {
125
+ ok: false,
126
+ error: err('PATH_NOT_ALLOWED', `Path goes through a link whose target does not exist: ${inputPath}`, {
127
+ hint: 'A write through a dangling link would create its target wherever the link points. Remove the link or use a path that does not go through it.',
128
+ details: { resolved, link: location.link },
129
+ }),
130
+ };
131
+ }
132
+ if (location.kind === 'unresolvable') {
133
+ if (!syntacticallyInside)
134
+ return { ok: false, error: outsideRoots() };
40
135
  return {
41
136
  ok: false,
42
- error: err('PATH_NOT_ALLOWED', `Path is outside allowed roots: ${inputPath}`, {
43
- hint: 'Set OPA_MCP_ALLOWED_PATHS to a comma-separated list of directories, or use a path under the current allowed roots.',
44
- details: { resolved, allowedRoots },
137
+ error: err('PATH_NOT_FOUND', `Path could not be fully resolved: ${inputPath}`, {
138
+ details: { resolved, reason: location.reason },
45
139
  }),
46
140
  };
47
141
  }
48
- if (options.mustExist && !existsSync(resolved)) {
142
+ if (options.mustExist && !location.exists) {
143
+ if (!syntacticallyInside)
144
+ return { ok: false, error: outsideRoots() };
49
145
  return {
50
146
  ok: false,
51
147
  error: err('PATH_NOT_FOUND', `Path does not exist: ${inputPath}`, {
@@ -53,51 +149,31 @@ export function validatePath(inputPath, allowedRoots, options = {}) {
53
149
  }),
54
150
  };
55
151
  }
56
- // Phase 2: symlink resolution. path.resolve() is purely syntactic and
57
- // does not follow symlinks. A symlink inside an allowed root can point
58
- // arbitrarily outside. For any path that exists on disk, resolve the
59
- // real target and re-validate against the real allowed-root locations.
60
- //
61
- // We validate via realpath but return `resolved` (the syntactic path)
62
- // for backward compatibility across OSes where system directories are
63
- // themselves symlinks (e.g. macOS /var -> /private/var). Callers pass
64
- // the returned path to OPA/regal; the OS follows any remaining symlinks
65
- // at read time, which is safe because we have verified the real target.
66
- if (existsSync(resolved)) {
67
- let realPath;
152
+ // A root that is itself a link, or spelled with a short name, compares
153
+ // correctly only in canonical form. A root that does not exist stays as
154
+ // written; nothing under it can resolve to it anyway.
155
+ const realRoots = resolvedRoots.map((r) => {
68
156
  try {
69
- realPath = realpathSync(resolved);
157
+ return canonical(r);
70
158
  }
71
159
  catch {
72
- // Rare race: path removed between existsSync and realpathSync, or
73
- // insufficient permissions to read the symlink chain. Fail closed.
74
- return {
75
- ok: false,
76
- error: err('PATH_NOT_FOUND', `Path could not be fully resolved: ${inputPath}`, {
77
- details: { resolved },
78
- }),
79
- };
80
- }
81
- // Also realpath the roots themselves so that a root that is a symlink
82
- // compares correctly against the realpath of the input.
83
- const realRoots = resolvedRoots.map((r) => {
84
- try {
85
- return existsSync(r) ? realpathSync(r) : r;
86
- }
87
- catch {
88
- return r;
89
- }
90
- });
91
- if (!isUnderRoots(realPath, realRoots)) {
92
- return {
93
- ok: false,
94
- error: err('PATH_NOT_ALLOWED', `Path resolves outside allowed roots via symlink: ${inputPath}`, {
95
- hint: 'Set OPA_MCP_ALLOWED_PATHS to a comma-separated list of directories, or use a path under the current allowed roots.',
96
- details: { resolved, realPath, allowedRoots },
97
- }),
98
- };
160
+ return r;
99
161
  }
162
+ });
163
+ if (!isUnderRoots(location.path, realRoots, false)) {
164
+ if (!syntacticallyInside)
165
+ return { ok: false, error: outsideRoots() };
166
+ return {
167
+ ok: false,
168
+ error: err('PATH_NOT_ALLOWED', `Path resolves outside allowed roots via a link: ${inputPath}`, {
169
+ hint: outsideHint,
170
+ details: { resolved, realPath: location.path, allowedRoots },
171
+ }),
172
+ };
100
173
  }
174
+ // The syntactic path is returned, not the canonical one: on macOS the
175
+ // system temp directory is itself a link, and tools compare and report
176
+ // paths as the caller spelled them.
101
177
  return { ok: true, resolved };
102
178
  }
103
179
  /** Convenience: returns true if the path is a directory (after validation). */
@@ -1 +1 @@
1
- {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AASlC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAiB,EACjB,YAAsB,EACtB,UAAmC,EAAE;IAErC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CAAC,eAAe,EAAE,iCAAiC,CAAC;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CACR,kBAAkB,EAClB,uEAAuE,EACvE;gBACE,IAAI,EAAE,kGAAkG;aACzG,CACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAEhG,2EAA2E;IAC3E,MAAM,YAAY,GAAG,CAAC,CAAS,EAAE,KAAe,EAAW,EAAE,CAC3D,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QAClB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;QAC3D,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEL,oEAAoE;IACpE,yEAAyE;IACzE,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAE1D,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CAAC,kBAAkB,EAAE,kCAAkC,SAAS,EAAE,EAAE;gBAC5E,IAAI,EAAE,oHAAoH;gBAC1H,OAAO,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE;aACpC,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,CAAC,gBAAgB,EAAE,wBAAwB,SAAS,EAAE,EAAE;gBAChE,OAAO,EAAE,EAAE,QAAQ,EAAE;aACtB,CAAC;SACH,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,uEAAuE;IACvE,qEAAqE;IACrE,uEAAuE;IACvE,EAAE;IACF,sEAAsE;IACtE,sEAAsE;IACtE,sEAAsE;IACtE,wEAAwE;IACxE,wEAAwE;IACxE,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACH,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;YAClE,mEAAmE;YACnE,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,GAAG,CAAC,gBAAgB,EAAE,qCAAqC,SAAS,EAAE,EAAE;oBAC7E,OAAO,EAAE,EAAE,QAAQ,EAAE;iBACtB,CAAC;aACH,CAAC;QACJ,CAAC;QAED,sEAAsE;QACtE,wDAAwD;QACxD,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACxC,IAAI,CAAC;gBACH,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;YACvC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,GAAG,CACR,kBAAkB,EAClB,oDAAoD,SAAS,EAAE,EAC/D;oBACE,IAAI,EAAE,oHAAoH;oBAC1H,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE;iBAC9C,CACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"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"}