Compare commits

...

6 Commits

Author SHA1 Message Date
Anand Krishnamoorthi
5467cd9e69 refactor(azure_policy): reduce AliasRegistry allocations via Rc sharing (#725)
Replace the compiler's two cloned BTreeMap fields (alias_map and
alias_modifiable) with a single Option<Rc<AliasRegistry>>. This
eliminates cloning two 73K-entry maps on every compilation by sharing
the registry through a reference-counted pointer.

Additional improvements:
- alias_map()/alias_modifiable_map() return &BTreeMap (zero-copy)
- Safe .get() indexing in ingest_alias_entries and build_object_from_keys
- Null-tolerant deserialization for AliasEntry.paths (~97% of real
  Azure catalog entries emit "paths": null)

All changes are within the azure_policy feature gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 17:55:34 -05:00
Copilot
dae3052781 fix(interpreter,rvm): correct partial object rule iteration and classification (#718)
Partial object rules with dynamic keys (e.g. `violations[k] if { ... }`)
only produced a single entry instead of collecting all bindings. Two
independent bugs caused this:

1. Interpreter: the early-return optimization in eval_output_expr_in_loop
   checked whether the rule_ref was constant but never verified whether
   the key expression was also constant. A variable key like `k` was
   treated as constant output, causing the loop to exit after the first
   iteration. Fixed by gating early-return on key_expr constness.

2. RVM: compute_rule_type incorrectly classified `p[k] if { ... }` as
   PartialSet instead of PartialObject. OPA v1 semantics define this
   form as a partial object (key -> true). Fixed the classification and
   added compiler error guards for patterns the RVM codegen cannot yet
   handle (constant keys, nested bracket keys), ensuring graceful
   fallback to the interpreter.

The OPA test harness now skips RVM validation per-case when partial
object compiler errors are raised, rather than blanket-skipping entire
folders. This preserves RVM coverage for unrelated tests in the same
folders.

Closes #712

Co-authored-by: Anand Krishnamoorthi <anakrish@microsoft.com>
2026-05-18 15:14:08 -05:00
Anand Krishnamoorthi
3111bf58f2 perf(normalizer): use Rc<str> interning to reduce alias resolution allocations (#726)
Replace per-alias heap allocations with reference-counted string interning
throughout the normalizer's alias resolution pipeline:

- Store alias ARM path segments as Vec<Rc<str>> instead of Vec<String>,
  enabling zero-alloc BTreeMap lookups via Rc::clone (refcount bump)
  rather than Value::from() (heap allocation per lookup)

- Pre-compute lowercased short name (short_name_lc: Rc<str>) at
  registry-load time, enabling allocation-free insertion for the
  common case of non-dotted, non-collision alias short names

- Add rc_lowercase() fast-path that skips allocation when the input
  string is already lowercase ASCII (common for ARM property names)

- Update set_nested_lowercased/set_nested_inner/set_nested_in_btree to
  thread Rc<str> through intermediate object construction, avoiding
  String temporaries at every nesting level

- Replace to_ascii_lowercase().starts_with() in is_root_field_collision
  with a zero-alloc byte-level comparison

Measured 27-49% improvement in normalization time across a range of
Azure Policy alias-heavy resource types (293-608 aliases per type).

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
2026-05-18 15:13:11 -05:00
Anand Krishnamoorthi
be3fde7706 fix(copilot): robust diff computation for cloud agent environments (#709)
The cloud agent checks out a branch like copilot/review-pr-NNN which
may not have upstream/main or origin/main refs available for merge-base.

Changes:
- Use gh pr diff as primary method (always works in PR context)
- Fall back to git merge-base for local non-PR usage
- Remove path filters (*.rs *.toml examples/) — review full diff
- Remove head -2000 truncation — let agents see everything
- Explicitly fetch origin/main in copilot-setup-steps.yml as backup

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 15:12:29 -05:00
dependabot[bot]
d2c483e93e build(deps): bump the rust-dependencies group across 5 directories with 2 updates (#724)
* build(deps): bump the rust-dependencies group across 5 directories with 2 updates

Bumps the rust-dependencies group with 2 updates in the / directory: [hashbrown](https://github.com/rust-lang/hashbrown) and [jsonschema](https://github.com/Stranger6667/jsonschema).
Bumps the rust-dependencies group with 2 updates in the /bindings/ffi directory: [hashbrown](https://github.com/rust-lang/hashbrown) and [jsonschema](https://github.com/Stranger6667/jsonschema).
Bumps the rust-dependencies group with 2 updates in the /bindings/java directory: [hashbrown](https://github.com/rust-lang/hashbrown) and [jsonschema](https://github.com/Stranger6667/jsonschema).
Bumps the rust-dependencies group with 2 updates in the /bindings/python directory: [hashbrown](https://github.com/rust-lang/hashbrown) and [jsonschema](https://github.com/Stranger6667/jsonschema).
Bumps the rust-dependencies group with 2 updates in the /bindings/wasm directory: [hashbrown](https://github.com/rust-lang/hashbrown) and [jsonschema](https://github.com/Stranger6667/jsonschema).


Updates `hashbrown` from 0.17.0 to 0.17.1
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.17.0...v0.17.1)

Updates `jsonschema` from 0.46.4 to 0.46.5
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.46.4...ruby-v0.46.5)

Updates `hashbrown` from 0.17.0 to 0.17.1
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.17.0...v0.17.1)

Updates `jsonschema` from 0.46.4 to 0.46.5
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.46.4...ruby-v0.46.5)

Updates `hashbrown` from 0.17.0 to 0.17.1
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.17.0...v0.17.1)

Updates `jsonschema` from 0.46.4 to 0.46.5
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.46.4...ruby-v0.46.5)

Updates `hashbrown` from 0.17.0 to 0.17.1
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.17.0...v0.17.1)

Updates `jsonschema` from 0.46.4 to 0.46.5
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.46.4...ruby-v0.46.5)

Updates `hashbrown` from 0.17.0 to 0.17.1
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.17.0...v0.17.1)

Updates `jsonschema` from 0.46.4 to 0.46.5
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.46.4...ruby-v0.46.5)

---
updated-dependencies:
- dependency-name: hashbrown
  dependency-version: 0.17.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): refresh Cargo lockfiles

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-14 10:37:20 -05:00
dependabot[bot]
093e50f0a1 build(deps): bump the rust-dependencies group across 5 directories with 4 updates (#717)
* build(deps): bump the rust-dependencies group across 5 directories with 4 updates

Bumps the rust-dependencies group with 3 updates in the / directory: [hashbrown](https://github.com/rust-lang/hashbrown), [jsonschema](https://github.com/Stranger6667/jsonschema) and [lru](https://github.com/jeromefroe/lru-rs).
Bumps the rust-dependencies group with 3 updates in the /bindings/ffi directory: [hashbrown](https://github.com/rust-lang/hashbrown), [jsonschema](https://github.com/Stranger6667/jsonschema) and [lru](https://github.com/jeromefroe/lru-rs).
Bumps the rust-dependencies group with 3 updates in the /bindings/java directory: [hashbrown](https://github.com/rust-lang/hashbrown), [jsonschema](https://github.com/Stranger6667/jsonschema) and [lru](https://github.com/jeromefroe/lru-rs).
Bumps the rust-dependencies group with 3 updates in the /bindings/python directory: [hashbrown](https://github.com/rust-lang/hashbrown), [jsonschema](https://github.com/Stranger6667/jsonschema) and [lru](https://github.com/jeromefroe/lru-rs).
Bumps the rust-dependencies group with 4 updates in the /bindings/wasm directory: [hashbrown](https://github.com/rust-lang/hashbrown), [jsonschema](https://github.com/Stranger6667/jsonschema), [lru](https://github.com/jeromefroe/lru-rs) and [wasm-bindgen-test](https://github.com/wasm-bindgen/wasm-bindgen).


Updates `hashbrown` from 0.16.1 to 0.17.0
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.16.1...v0.17.0)

Updates `jsonschema` from 0.45.1 to 0.46.4
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.45.1...ruby-v0.46.4)

Updates `lru` from 0.16.4 to 0.18.0
- [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jeromefroe/lru-rs/compare/0.16.4...0.18.0)

Updates `hashbrown` from 0.16.1 to 0.17.0
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.16.1...v0.17.0)

Updates `jsonschema` from 0.45.1 to 0.46.4
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.45.1...ruby-v0.46.4)

Updates `lru` from 0.16.4 to 0.18.0
- [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jeromefroe/lru-rs/compare/0.16.4...0.18.0)

Updates `hashbrown` from 0.16.1 to 0.17.0
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.16.1...v0.17.0)

Updates `jsonschema` from 0.45.1 to 0.46.4
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.45.1...ruby-v0.46.4)

Updates `lru` from 0.16.4 to 0.18.0
- [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jeromefroe/lru-rs/compare/0.16.4...0.18.0)

Updates `hashbrown` from 0.16.1 to 0.17.0
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.16.1...v0.17.0)

Updates `jsonschema` from 0.45.1 to 0.46.4
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.45.1...ruby-v0.46.4)

Updates `lru` from 0.16.4 to 0.18.0
- [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jeromefroe/lru-rs/compare/0.16.4...0.18.0)

Updates `hashbrown` from 0.16.1 to 0.17.0
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.16.1...v0.17.0)

Updates `jsonschema` from 0.45.1 to 0.46.4
- [Release notes](https://github.com/Stranger6667/jsonschema/releases)
- [Changelog](https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stranger6667/jsonschema/compare/ruby-v0.45.1...ruby-v0.46.4)

Updates `lru` from 0.16.4 to 0.18.0
- [Changelog](https://github.com/jeromefroe/lru-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jeromefroe/lru-rs/compare/0.16.4...0.18.0)

Updates `wasm-bindgen-test` from 0.3.70 to 0.3.71
- [Release notes](https://github.com/wasm-bindgen/wasm-bindgen/releases)
- [Changelog](https://github.com/wasm-bindgen/wasm-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/wasm-bindgen/wasm-bindgen/commits)

---
updated-dependencies:
- dependency-name: hashbrown
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: lru
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: lru
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: lru
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: lru
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: jsonschema
  dependency-version: 0.46.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: lru
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: wasm-bindgen-test
  dependency-version: 0.3.71
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): refresh Cargo lockfiles

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-07 06:42:34 -05:00
27 changed files with 1669 additions and 318 deletions

View File

@@ -8,3 +8,5 @@ steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # full history needed for git diff against main
- run: git fetch origin main:refs/remotes/origin/main
name: Ensure origin/main ref is available for diff computation

View File

@@ -25,15 +25,21 @@ Key constraints (details in copilot-instructions.md):
## Step 1: Get the Diff
```bash
BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
|| git merge-base origin/main HEAD 2>/dev/null)
if [ -z "$BASE" ]; then
echo "ERROR: Cannot find upstream/main or origin/main. Cannot determine review scope."
exit 1
# Primary: use gh pr diff (works in cloud agent + any PR context).
# Fallback: git merge-base for local non-PR usage.
if gh pr diff --name-only >/dev/null 2>&1; then
echo "---STAT---"
gh pr diff --name-only
echo "---DIFF---"
gh pr diff
else
BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
|| git merge-base origin/main HEAD 2>/dev/null \
|| git merge-base main HEAD 2>/dev/null)
echo "Reviewing changes since: $BASE"
git diff "$BASE"..HEAD --stat
git diff "$BASE"..HEAD
fi
echo "Reviewing changes since: $BASE"
git diff "$BASE"..HEAD --stat
git diff "$BASE"..HEAD -- '*.rs' '*.toml' 'examples/'
```
If the diff is empty, stop and report: "No changes found to review."
@@ -196,3 +202,9 @@ one pass. If any were skipped, note them and briefly assess.
### Summary
X findings (N critical, N high, N medium, N low). One sentence overall assessment.
### Output
After generating the report above, write the COMPLETE report to `/tmp/code-review-report.md`
using the `create` tool or shell. This ensures the full report is preserved even if
display output is truncated.

View File

@@ -40,22 +40,25 @@ Use `read_agent` with `wait: true` to wait for each background agent.
## Step 1: Get the Diff and Build Inventory
```bash
BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
|| git merge-base origin/main HEAD 2>/dev/null)
if [ -z "$BASE" ]; then
echo "ERROR: Cannot find upstream/main or origin/main."
exit 1
# Primary: use gh pr diff (works in cloud agent + any PR context).
# Fallback: git merge-base for local non-PR usage.
if gh pr diff --name-only >/dev/null 2>&1; then
echo "---STAT---"
gh pr diff --name-only
echo "---DIFF---"
gh pr diff
else
BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
|| git merge-base origin/main HEAD 2>/dev/null \
|| git merge-base main HEAD 2>/dev/null)
echo "Reviewing changes since: $BASE"
git diff "$BASE"..HEAD --stat
git diff "$BASE"..HEAD
fi
echo "Reviewing changes since: $BASE"
git diff "$BASE"..HEAD --stat
git diff "$BASE"..HEAD -- '*.rs' '*.toml' 'examples/' | head -2000
```
If the diff is empty, stop and report: "No changes found to review."
**Scope rule:** Focus on code files (`*.rs`, `*.toml`, examples). Do NOT pass
docs/config diffs to agents.
**Build a risk-classified inventory.** List every changed function, struct,
impl, trait, pub item, and significant code block. Number them and tag with
risk predicates:
@@ -106,8 +109,10 @@ Use `model: "gpt-5.4"` in the task tool call (provides model diversity).
> Get the diff:
> ```
> BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
> || git merge-base origin/main HEAD 2>/dev/null)
> git diff "$BASE"..HEAD -- '*.rs' '*.toml' 'examples/'
> || git merge-base origin/main HEAD 2>/dev/null \
> || git merge-base main HEAD 2>/dev/null)
> # If no merge-base, use: gh pr diff
> git diff "$BASE"..HEAD # or: gh pr diff
> ```
>
> Key regorus constraints:
@@ -161,8 +166,10 @@ Use `model: "claude-opus-4.6"` in the task tool call.
> Get the diff AND read full source files for context:
> ```
> BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
> || git merge-base origin/main HEAD 2>/dev/null)
> git diff "$BASE"..HEAD -- '*.rs' '*.toml' 'examples/'
> || git merge-base origin/main HEAD 2>/dev/null \
> || git merge-base main HEAD 2>/dev/null)
> # If no merge-base, use: gh pr diff
> git diff "$BASE"..HEAD # or: gh pr diff
> ```
> Then use `view` to read the full source files that were changed.
>
@@ -219,8 +226,10 @@ Use the default model (no `model` parameter).
> Get the diff:
> ```
> BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
> || git merge-base origin/main HEAD 2>/dev/null)
> git diff "$BASE"..HEAD -- '*.rs' '*.toml' 'examples/'
> || git merge-base origin/main HEAD 2>/dev/null \
> || git merge-base main HEAD 2>/dev/null)
> # If no merge-base, use: gh pr diff
> git diff "$BASE"..HEAD # or: gh pr diff
> ```
> Use `view` to read surrounding context.
>
@@ -439,8 +448,10 @@ Launch **1 general-purpose agent in background mode**.
> Get the diff:
> ```
> BASE=$(git merge-base upstream/main HEAD 2>/dev/null \
> || git merge-base origin/main HEAD 2>/dev/null)
> git diff "$BASE"..HEAD -- '*.rs' '*.toml' 'examples/'
> || git merge-base origin/main HEAD 2>/dev/null \
> || git merge-base main HEAD 2>/dev/null)
> # If no merge-base, use: gh pr diff
> git diff "$BASE"..HEAD # or: gh pr diff
> ```
> Use `view` to read full source files.
>
@@ -481,8 +492,8 @@ Launch **1 general-purpose agent in background mode**.
## Step 5: Synthesize and Report
**IMPORTANT:** This is the primary output. Everything above was preparation.
Keep the report COMPACT — one finding per block, no filler prose.
**CRITICAL:** Write the report to `/tmp/deep-review-report.md` FIRST, then display it.
Use a shell command to write the file before any other output in this step.
Apply verdicts from the adversarial verifier:
- **CONFIRMED**: keep at stated severity
@@ -522,3 +533,9 @@ would catch it. If not, name the minimal test that should exist.
X findings (N critical, N high, N medium, N low). Y "likely" findings.
Z dropped (one-line reasons).
Risk assessment in one sentence.
---
**Remember:** The report above MUST be written to `/tmp/deep-review-report.md` at the
START of Step 5 (before displaying it). Use shell: `cat > /tmp/deep-review-report.md << 'REPORT_EOF'`
... report content ... `REPORT_EOF`

71
Cargo.lock generated
View File

@@ -180,9 +180,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.61"
version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -474,9 +474,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fancy-regex"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277"
dependencies = [
"bit-set",
"regex-automata",
@@ -650,9 +650,12 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.17.0"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
dependencies = [
"foldhash 0.2.0",
]
[[package]]
name = "heck"
@@ -832,7 +835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.0",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -866,9 +869,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.97"
version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf"
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -878,9 +881,9 @@ dependencies = [
[[package]]
name = "jsonschema"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257eb0e588b76827bbddc9e73945a9743693dd2adeaee9da26420f93cfedb798"
checksum = "6a5fe5206f06e589caf25e79fc05ccdf91fca745685fe9fe1a13bbdfb479a631"
dependencies = [
"ahash",
"bytecount",
@@ -947,9 +950,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "lru"
version = "0.16.4"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
[[package]]
name = "memchr"
@@ -957,6 +960,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "micromap"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -1344,14 +1353,16 @@ dependencies = [
[[package]]
name = "referencing"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2f38748ceca8d0b0013e60f534d94a6e23dfd89fd2a88318fc5a2d04fda1010"
checksum = "69e4e17ef386c5383591d07623d3de49cbc601156e7582973e6db98d66a57de2"
dependencies = [
"ahash",
"fluent-uri",
"getrandom 0.3.4",
"hashbrown 0.16.1",
"itoa",
"micromap",
"parking_lot",
"percent-encoding",
"serde_json",
@@ -1399,7 +1410,7 @@ dependencies = [
"dashmap",
"data-encoding",
"globset",
"hashbrown 0.16.1",
"hashbrown 0.17.1",
"icu_casemap",
"indexmap",
"ipnet",
@@ -1545,9 +1556,9 @@ checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
[[package]]
name = "siphasher"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -1830,9 +1841,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1"
checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -1843,9 +1854,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103"
checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote 1.0.45",
"wasm-bindgen-macro-support",
@@ -1853,9 +1864,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41"
checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2 1.0.106",
@@ -1866,9 +1877,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea"
checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
@@ -1909,9 +1920,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.97"
version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602"
checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2182,9 +2193,9 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]

View File

@@ -99,7 +99,7 @@ rand = ["dep:rand"]
anyhow = { version = "1.0.102", default-features = false }
serde = {version = "1.0.150", default-features = false, features = ["derive", "rc", "alloc"] }
serde_json = { version = "1.0.89", default-features = false, features = ["alloc"] }
hashbrown = { version = "0.16", default-features = false, features = ["default-hasher"], optional = true }
hashbrown = { version = "0.17", default-features = false, features = ["default-hasher"], optional = true }
lazy_static = { version = "1.4.0", default-features = false }
thiserror = { version = "2.0", default-features = false }
@@ -114,7 +114,7 @@ regex = {version = "1.12.3", optional = true, default-features = false }
semver = {version = "1.0.28", optional = true, default-features = false }
url = { version = "2.5.4", optional = true }
uuid = { version = "1.22.0", default-features = false, features = ["v4", "fast-rng"], optional = true }
jsonschema = { version = "0.45.1", default-features = false, optional = true }
jsonschema = { version = "0.46.5", default-features = false, optional = true }
chrono = { version = "0.4.44", optional = true }
chrono-tz = { version = "0.10.1", optional = true }
ipnet = { version = "2.12.0", optional = true, default-features = false }
@@ -127,7 +127,7 @@ rand = { version = "0.10.0", default-features = false, features = ["thread_rng"]
# Causes the project to link with the Spectre-mitigated CRT and libs.
msvc_spectre_libs = { version = "0.1", features = ["error"], optional = true }
dashmap = { version = "6.1", default-features = false, optional = true }
lru = { version = "0.16", default-features = false, optional = true }
lru = { version = "0.18", default-features = false, optional = true }
mimalloc = { package = "regorus-mimalloc", path = "mimalloc", version = "2.2.6", optional = true }
# rvm related deps

View File

@@ -172,9 +172,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.61"
version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -353,9 +353,9 @@ dependencies = [
[[package]]
name = "fancy-regex"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277"
dependencies = [
"bit-set",
"regex-automata",
@@ -508,9 +508,12 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.17.0"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
dependencies = [
"foldhash 0.2.0",
]
[[package]]
name = "heck"
@@ -684,7 +687,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.0",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -709,9 +712,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.97"
version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf"
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -721,9 +724,9 @@ dependencies = [
[[package]]
name = "jsonschema"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257eb0e588b76827bbddc9e73945a9743693dd2adeaee9da26420f93cfedb798"
checksum = "6a5fe5206f06e589caf25e79fc05ccdf91fca745685fe9fe1a13bbdfb479a631"
dependencies = [
"ahash",
"bytecount",
@@ -793,9 +796,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "lru"
version = "0.16.4"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
[[package]]
name = "memchr"
@@ -803,6 +806,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "micromap"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74"
[[package]]
name = "msvc_spectre_libs"
version = "0.1.3"
@@ -1073,14 +1082,16 @@ dependencies = [
[[package]]
name = "referencing"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2f38748ceca8d0b0013e60f534d94a6e23dfd89fd2a88318fc5a2d04fda1010"
checksum = "69e4e17ef386c5383591d07623d3de49cbc601156e7582973e6db98d66a57de2"
dependencies = [
"ahash",
"fluent-uri",
"getrandom 0.3.4",
"hashbrown 0.16.1",
"itoa",
"micromap",
"parking_lot",
"percent-encoding",
"serde_json",
@@ -1125,7 +1136,7 @@ dependencies = [
"dashmap",
"data-encoding",
"globset",
"hashbrown 0.16.1",
"hashbrown 0.17.1",
"icu_casemap",
"indexmap",
"ipnet",
@@ -1285,9 +1296,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -1524,9 +1535,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1"
checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -1537,9 +1548,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103"
checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1547,9 +1558,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41"
checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -1560,9 +1571,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea"
checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
@@ -1826,9 +1837,9 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]

View File

@@ -109,9 +109,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cc"
version = "1.2.61"
version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -237,9 +237,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fancy-regex"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277"
dependencies = [
"bit-set",
"regex-automata",
@@ -380,9 +380,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.17.0"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -530,7 +530,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.0",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -598,9 +598,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.97"
version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf"
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -610,9 +610,9 @@ dependencies = [
[[package]]
name = "jsonschema"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257eb0e588b76827bbddc9e73945a9743693dd2adeaee9da26420f93cfedb798"
checksum = "6a5fe5206f06e589caf25e79fc05ccdf91fca745685fe9fe1a13bbdfb479a631"
dependencies = [
"ahash",
"bytecount",
@@ -676,9 +676,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "lru"
version = "0.16.4"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
[[package]]
name = "memchr"
@@ -686,6 +686,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "micromap"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74"
[[package]]
name = "msvc_spectre_libs"
version = "0.1.3"
@@ -948,14 +954,16 @@ dependencies = [
[[package]]
name = "referencing"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2f38748ceca8d0b0013e60f534d94a6e23dfd89fd2a88318fc5a2d04fda1010"
checksum = "69e4e17ef386c5383591d07623d3de49cbc601156e7582973e6db98d66a57de2"
dependencies = [
"ahash",
"fluent-uri",
"getrandom 0.3.4",
"hashbrown 0.16.1",
"itoa",
"micromap",
"parking_lot",
"percent-encoding",
"serde_json",
@@ -1168,9 +1176,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "siphasher"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -1352,9 +1360,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1"
checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -1365,9 +1373,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103"
checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1375,9 +1383,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41"
checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -1388,9 +1396,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea"
checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
@@ -1651,9 +1659,9 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]

View File

@@ -103,9 +103,9 @@ checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
[[package]]
name = "cc"
version = "1.2.61"
version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -221,9 +221,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fancy-regex"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277"
dependencies = [
"bit-set",
"regex-automata",
@@ -364,9 +364,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.17.0"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -514,7 +514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.0",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -533,9 +533,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.97"
version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf"
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -545,9 +545,9 @@ dependencies = [
[[package]]
name = "jsonschema"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257eb0e588b76827bbddc9e73945a9743693dd2adeaee9da26420f93cfedb798"
checksum = "6a5fe5206f06e589caf25e79fc05ccdf91fca745685fe9fe1a13bbdfb479a631"
dependencies = [
"ahash",
"bytecount",
@@ -611,9 +611,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "lru"
version = "0.16.4"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
[[package]]
name = "memchr"
@@ -621,6 +621,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "micromap"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74"
[[package]]
name = "msvc_spectre_libs"
version = "0.1.3"
@@ -957,14 +963,16 @@ dependencies = [
[[package]]
name = "referencing"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2f38748ceca8d0b0013e60f534d94a6e23dfd89fd2a88318fc5a2d04fda1010"
checksum = "69e4e17ef386c5383591d07623d3de49cbc601156e7582973e6db98d66a57de2"
dependencies = [
"ahash",
"fluent-uri",
"getrandom 0.3.4",
"hashbrown 0.16.1",
"itoa",
"micromap",
"parking_lot",
"percent-encoding",
"serde_json",
@@ -1144,9 +1152,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -1324,9 +1332,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1"
checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -1337,9 +1345,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103"
checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1347,9 +1355,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41"
checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -1360,9 +1368,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea"
checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
@@ -1605,9 +1613,9 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]

View File

@@ -121,9 +121,9 @@ checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
[[package]]
name = "cc"
version = "1.2.61"
version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -244,9 +244,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fancy-regex"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277"
dependencies = [
"bit-set",
"regex-automata",
@@ -393,9 +393,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.17.0"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -543,7 +543,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.0",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -571,9 +571,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.97"
version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf"
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -583,9 +583,9 @@ dependencies = [
[[package]]
name = "jsonschema"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257eb0e588b76827bbddc9e73945a9743693dd2adeaee9da26420f93cfedb798"
checksum = "6a5fe5206f06e589caf25e79fc05ccdf91fca745685fe9fe1a13bbdfb479a631"
dependencies = [
"ahash",
"bytecount",
@@ -659,9 +659,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "lru"
version = "0.16.4"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
[[package]]
name = "magnus"
@@ -692,6 +692,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "micromap"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@@ -929,18 +935,18 @@ checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
[[package]]
name = "rb-sys"
version = "0.9.127"
version = "0.9.128"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7d7c9560fe42dcffa576941394075f18a17dce89fcf718a2fa90b7dc2134d12"
checksum = "45ca28513560e56cfb79a62b1fce363c73af170a182024ce880c77ee9429920a"
dependencies = [
"rb-sys-build",
]
[[package]]
name = "rb-sys-build"
version = "0.9.127"
version = "0.9.128"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1688e8f32967ba48c89e4dfa283b57f901075f542fc7ee9c3d7c5f9091ca1d9"
checksum = "ce04b2c55eff3a21aaa623fcc655d94373238e72cac6b3e1a3641ff31649f99a"
dependencies = [
"bindgen",
"lazy_static",
@@ -988,14 +994,16 @@ dependencies = [
[[package]]
name = "referencing"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2f38748ceca8d0b0013e60f534d94a6e23dfd89fd2a88318fc5a2d04fda1010"
checksum = "69e4e17ef386c5383591d07623d3de49cbc601156e7582973e6db98d66a57de2"
dependencies = [
"ahash",
"fluent-uri",
"getrandom 0.3.4",
"hashbrown 0.16.1",
"itoa",
"micromap",
"parking_lot",
"percent-encoding",
"serde_json",
@@ -1203,9 +1211,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -1383,9 +1391,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1"
checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -1396,9 +1404,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103"
checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1406,9 +1414,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41"
checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -1419,9 +1427,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea"
checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
@@ -1664,9 +1672,9 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]

View File

@@ -120,9 +120,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.61"
version = "1.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -238,9 +238,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fancy-regex"
version = "0.17.0"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8"
checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277"
dependencies = [
"bit-set",
"regex-automata",
@@ -396,9 +396,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.17.0"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -546,7 +546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.0",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -565,9 +565,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.97"
version = "0.3.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf"
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
dependencies = [
"cfg-if",
"futures-util",
@@ -577,9 +577,9 @@ dependencies = [
[[package]]
name = "jsonschema"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257eb0e588b76827bbddc9e73945a9743693dd2adeaee9da26420f93cfedb798"
checksum = "6a5fe5206f06e589caf25e79fc05ccdf91fca745685fe9fe1a13bbdfb479a631"
dependencies = [
"ahash",
"bytecount",
@@ -649,9 +649,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "lru"
version = "0.16.4"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
[[package]]
name = "memchr"
@@ -659,6 +659,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "micromap"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74"
[[package]]
name = "minicov"
version = "0.3.8"
@@ -947,14 +953,16 @@ dependencies = [
[[package]]
name = "referencing"
version = "0.45.1"
version = "0.46.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2f38748ceca8d0b0013e60f534d94a6e23dfd89fd2a88318fc5a2d04fda1010"
checksum = "69e4e17ef386c5383591d07623d3de49cbc601156e7582973e6db98d66a57de2"
dependencies = [
"ahash",
"fluent-uri",
"getrandom 0.3.4",
"hashbrown 0.16.1",
"itoa",
"micromap",
"parking_lot",
"percent-encoding",
"serde_json",
@@ -1144,9 +1152,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "siphasher"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "slab"
@@ -1336,9 +1344,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1"
checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
dependencies = [
"cfg-if",
"once_cell",
@@ -1349,9 +1357,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.70"
version = "0.4.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084"
checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -1359,9 +1367,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103"
checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1369,9 +1377,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41"
checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -1382,18 +1390,18 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea"
checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-bindgen-test"
version = "0.3.70"
version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29826f9d9ecaa314c480d376b276d1c790e6cb6a4681fab8532da69cbabf977d"
checksum = "af5ec93229ad9ccd0a545a516dec76dc276613f278f6a91aa6b463d5b33d42d0"
dependencies = [
"async-trait",
"cast",
@@ -1413,9 +1421,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.70"
version = "0.3.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c610311887f9e6599a546d278d12d69dfd3a3e92639b2129e4b11ad6cf1961d6"
checksum = "3c81b9fef827e575e0e54431736d1baa0d700315d8c62cfef1f61fa3aad0cbeb"
dependencies = [
"proc-macro2",
"quote",
@@ -1424,9 +1432,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-shared"
version = "0.2.120"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60238e5b4b1b295701d6f9a66d2a126fe19990348f5fb9dae3b623a370119d94"
checksum = "4f4d8ae7ad5440360e9799dfd42857d126454a88441ddf72d288ef83fa47f527"
[[package]]
name = "wasm-encoder"
@@ -1684,9 +1692,9 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]

View File

@@ -55,7 +55,7 @@ getrandom03 = { package = "getrandom", version = "0.3.1", features = ["std", "wa
getrandom = { version = "0.4.2", features = ["wasm_js"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.67"
wasm-bindgen-test = "0.3.71"
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(wasm_bindgen_unstable_test_coverage)'] }

View File

@@ -23,8 +23,7 @@ use regorus::languages::azure_policy::aliases::AliasRegistry;
use regorus::languages::azure_policy::compiler;
use regorus::languages::azure_policy::parser;
use regorus::rvm::RegoVM;
use regorus::Source;
use regorus::Value;
use regorus::{Rc, Source, Value};
/// Evaluate an Azure Policy definition against a resource.
///
@@ -60,11 +59,8 @@ pub fn azure_policy_eval(
println!("Parsed policy definition from {policy_definition}");
// 3. Compile to RVM bytecode.
let program = compiler::compile_policy_definition_with_aliases(
&defn,
registry.alias_map(),
registry.alias_modifiable_map(),
)?;
let registry = Rc::new(registry);
let program = compiler::compile_policy_definition_with_aliases(&defn, Rc::clone(&registry))?;
println!("Compiled policy to RVM bytecode");
// 4. Build normalized input.
@@ -138,7 +134,7 @@ pub fn azure_policy_aliases(aliases: String, resource_type: Option<String>) -> R
if let Some(ref rt) = resource_type {
let rt_lower = rt.to_lowercase();
let mut found = false;
for (alias_name, _) in registry.alias_map() {
for alias_name in registry.alias_map().keys() {
if alias_name.to_lowercase().starts_with(&rt_lower) {
println!(" {alias_name}");
found = true;
@@ -148,7 +144,7 @@ pub fn azure_policy_aliases(aliases: String, resource_type: Option<String>) -> R
bail!("no aliases found for resource type '{rt}'");
}
} else {
for (alias_name, _) in registry.alias_map() {
for alias_name in registry.alias_map().keys() {
println!(" {alias_name}");
}
}

View File

@@ -1782,6 +1782,7 @@ impl Interpreter {
let mut comps = self.eval_rule_ref(&rule_ref)?;
if let Some(ke) = &key_expr {
is_const_rule = is_const_rule && Self::is_simple_literal(ke)?;
comps.push(self.eval_expr(ke)?);
}
let output = if let Some(oe) = &output_expr {

View File

@@ -172,11 +172,31 @@ impl AliasRegistry {
let prefix = alloc::format!("{}/", fq_type);
for alias in aliases {
// Skip aliases without a default_path — the normalizer's
// resolve_resource_type also skips these, so inserting them into
// compiler maps would cause a divergence where the compiler
// resolves the alias but normalized input never contains the field.
if alias.default_path.is_none() {
continue;
}
// Derive the short name by stripping the resource type prefix.
let raw_short = if alias.name.len() > prefix.len()
&& alias.name[..prefix.len()].eq_ignore_ascii_case(&prefix)
&& alias
.name
.get(..prefix.len())
.is_some_and(|s| s.eq_ignore_ascii_case(&prefix))
{
alias.name[prefix.len()..].to_string()
// Both slice boundaries are valid: prefix is ASCII
// (resource type + '/'), so if `..prefix.len()` succeeded
// above, `prefix.len()..` is guaranteed to be on a char
// boundary too. The `unwrap_or` is a defensive fallback
// that can never trigger for well-formed Azure alias names.
alias
.name
.get(prefix.len()..)
.unwrap_or(&alias.name)
.to_string()
} else if let Some(rest) = alias
.name
.rfind('/')
@@ -260,20 +280,19 @@ impl AliasRegistry {
.map(String::as_str)
}
/// Return a clone of the alias-to-short-name map for use by the compiler.
/// Return a reference to the alias-to-short-name map.
///
/// The compiler stores this map internally so it can resolve fully-qualified
/// alias names without holding a reference to the registry.
pub fn alias_map(&self) -> BTreeMap<String, String> {
self.alias_to_short.clone()
/// Keys are lowercase fully-qualified alias names; values are short names.
pub const fn alias_map(&self) -> &BTreeMap<String, String> {
&self.alias_to_short
}
/// Return a clone of the alias-to-modifiable map for use by the compiler.
/// Return a reference to the alias-to-modifiable map.
///
/// Maps lowercase fully-qualified alias names to `true` when the alias
/// has `defaultMetadata.attributes = "Modifiable"`.
pub fn alias_modifiable_map(&self) -> BTreeMap<String, bool> {
self.alias_modifiable.clone()
/// Keys are lowercase fully-qualified alias names; values are `true` when
/// the alias has `defaultMetadata.attributes = "Modifiable"`.
pub const fn alias_modifiable_map(&self) -> &BTreeMap<String, bool> {
&self.alias_modifiable
}
/// Normalize a raw ARM resource and wrap it in the input envelope.

View File

@@ -4,14 +4,13 @@
//! Per-alias path resolution: reads values from versioned ARM paths and places
//! them at alias short name paths in the normalized output.
use alloc::string::String;
use crate::Rc;
use crate::Value;
use super::super::obj_map::remove_element_field;
use super::super::obj_map::{
collision_safe_key, is_root_field_collision, obj_contains, obj_insert, obj_remove,
set_nested_lowercased, ObjMap,
collision_safe_key, is_root_field_collision, obj_contains, obj_insert, obj_insert_rc,
obj_remove, set_nested_lowercased, ObjMap,
};
use super::super::types::ResolvedAliases;
use super::element_remap::apply_element_remap_precomputed;
@@ -48,12 +47,14 @@ pub fn apply_alias_entries(
if let Some(value) = value {
let value = normalize_value(&value, &entry.short_name, None);
let target = if is_root_field_collision(&entry.short_name, &entry.default_path) {
collision_safe_key(&entry.short_name)
if is_root_field_collision(&entry.short_name, &entry.default_path) {
let target = collision_safe_key(&entry.short_name);
set_nested_lowercased(result, &target, value);
} else if entry.short_name.contains('.') {
set_nested_lowercased(result, &entry.short_name, value);
} else {
entry.short_name.clone()
};
set_nested_lowercased(result, &target, value);
obj_insert_rc(result, Rc::clone(&entry.short_name_lc), value);
}
}
}
@@ -84,13 +85,13 @@ pub fn apply_alias_entries(
}
/// Navigate an ARM path using precomputed segments (avoids per-call split).
fn navigate_arm_path_segments(value: &Value, segments: &[String]) -> Option<Value> {
fn navigate_arm_path_segments(value: &Value, segments: &[Rc<str>]) -> Option<Value> {
let mut current = value;
for segment in segments {
current = current
.as_object()
.ok()?
.get(&Value::from(segment.as_str()))?;
.get(&Value::String(Rc::clone(segment)))?;
}
Some(current.clone())
}

View File

@@ -7,7 +7,7 @@
//! then converts to `Value::Object` (a `BTreeMap<Value, Value>`) only at
//! the output boundary via [`make_value`].
use alloc::string::{String, ToString as _};
use alloc::string::String;
use alloc::vec::Vec;
use hashbrown::HashMap;
@@ -41,6 +41,33 @@ pub fn obj_insert(map: &mut ObjMap, key: &str, val: Value) {
map.insert(Rc::from(key), val);
}
/// Insert a key-value pair using a pre-allocated `Rc<str>` key.
///
/// Avoids the `Rc::from(key)` heap allocation that [`obj_insert`] performs.
pub fn obj_insert_rc(map: &mut ObjMap, key: Rc<str>, val: Value) {
map.insert(key, val);
}
/// Lowercase a string, returning an `Rc<str>`.
///
/// Both paths allocate an `Rc<str>` (header + string bytes). The fast-path
/// avoids creating an intermediate lowercased `String` when the input is
/// already all-lowercase ASCII.
pub fn rc_lowercase(s: &str) -> Rc<str> {
if s.bytes().all(|b| !b.is_ascii_uppercase()) {
Rc::from(s)
} else {
Rc::from(s.to_ascii_lowercase())
}
}
/// Insert a key-value pair with the key lowercased, using [`rc_lowercase`]
/// for the allocation fast-path.
pub fn obj_insert_lc(map: &mut ObjMap, key: &str, val: Value) {
let lc = rc_lowercase(key);
map.insert(lc, val);
}
/// Check whether a key exists.
pub fn obj_contains(map: &ObjMap, key: &str) -> bool {
map.contains_key(key)
@@ -112,7 +139,7 @@ pub fn set_nested_lowercased(result: &mut ObjMap, path: &str, value: Value) {
}
if segments.len() == 1 {
if let Some(&seg) = segments.first() {
obj_insert(result, &seg.to_ascii_lowercase(), value);
obj_insert_lc(result, seg, value);
}
return;
}
@@ -144,28 +171,28 @@ fn set_nested_inner(obj: &mut ObjMap, segments: &[&str], value: Value, lowercase
};
if segments.len() == 1 {
let key = if lowercase {
first.to_ascii_lowercase()
let key: Rc<str> = if lowercase {
rc_lowercase(first)
} else {
first.to_string()
Rc::from(first)
};
obj_insert(obj, &key, value);
obj_insert_rc(obj, key, value);
return;
}
let seg = if lowercase {
first.to_ascii_lowercase()
let seg: Rc<str> = if lowercase {
rc_lowercase(first)
} else {
first.to_string()
Rc::from(first)
};
// Ensure an intermediate object exists at `seg`.
if !obj_contains(obj, &seg) {
obj_insert(obj, &seg, make_value(new_map()));
if !obj.contains_key(&*seg) {
obj_insert_rc(obj, Rc::clone(&seg), make_value(new_map()));
}
// Descend directly into the BTreeMap, avoiding ObjMap round-trip.
if let Some(Value::Object(inner_rc)) = obj_get_mut(obj, &seg) {
if let Some(Value::Object(inner_rc)) = obj.get_mut(&*seg) {
let inner_btree = Rc::make_mut(inner_rc);
set_nested_in_btree(
inner_btree,
@@ -191,12 +218,12 @@ pub fn set_nested_in_btree(
return;
};
let key_str: String = if lowercase {
first.to_ascii_lowercase()
let key_rc: Rc<str> = if lowercase {
rc_lowercase(first)
} else {
first.to_string()
Rc::from(first)
};
let key_val = Value::String(Rc::from(key_str.as_str()));
let key_val = Value::String(Rc::clone(&key_rc));
if segments.len() == 1 {
btree.insert(key_val, value);
@@ -243,13 +270,24 @@ pub const ROOT_FIELDS: &[&str] = &[
"extendedLocation",
];
const PROPERTIES_DOT: &[u8] = b"properties.";
/// Check whether an alias short name collides with a reserved ARM root field
/// and needs a collision-safe key.
pub fn is_root_field_collision(short_name: &str, default_path: &str) -> bool {
ROOT_FIELDS
.iter()
.any(|f| f.eq_ignore_ascii_case(short_name))
&& default_path.to_ascii_lowercase().starts_with("properties.")
&& default_path.len() > PROPERTIES_DOT.len()
&& default_path
.as_bytes()
.get(..PROPERTIES_DOT.len())
.is_some_and(|prefix| {
prefix
.iter()
.zip(PROPERTIES_DOT)
.all(|(a, b)| a.to_ascii_lowercase() == *b)
})
}
/// Return a collision-safe key for an alias whose short name collides with a

View File

@@ -18,6 +18,22 @@ use alloc::vec::Vec;
use serde::{Deserialize, Deserializer};
use crate::Rc;
// ---------------------------------------------------------------------------
// Deserialization helpers
// ---------------------------------------------------------------------------
/// Deserialize a `Vec<T>` that tolerates JSON `null` by mapping it to an
/// empty vector.
fn deserialize_null_as_empty_vec<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
Ok(Option::<Vec<T>>::deserialize(deserializer)?.unwrap_or_default())
}
// ─── Top-level response wrappers ────────────────────────────────────────────
/// ARM API response envelope: `{ "value": [...] }`
@@ -98,7 +114,10 @@ pub struct AliasEntry {
/// Versioned path entries. Empty for the vast majority of aliases that
/// have only a `defaultPath`.
#[serde(default)]
///
/// In real Azure catalog data (~97% of aliases), `az provider list` emits
/// `"paths": null` rather than an empty array.
#[serde(default, deserialize_with = "deserialize_null_as_empty_vec")]
pub paths: Vec<AliasPath>,
}
@@ -404,11 +423,13 @@ pub struct ResolvedEntry {
// ── Precomputed fields (derived at registry-load time) ──────────────
/// Whether `short_name` contains `[*]` (i.e., this is a wildcard/array alias).
pub is_wildcard: bool,
/// Pre-lowercased short name as `Rc<str>` for allocation-free common-case inserts.
pub(crate) short_name_lc: Rc<str>,
/// Precomputed `default_path.split('.').collect()` for fast ARM path navigation.
pub default_path_segments: Vec<String>,
pub(crate) default_path_segments: Vec<Rc<str>>,
/// Precomputed path segments for each versioned path, in the same order
/// as `versioned_paths`.
pub versioned_path_segments: Vec<Vec<String>>,
pub(crate) versioned_path_segments: Vec<Vec<Rc<str>>>,
}
impl ResolvedEntry {
@@ -420,10 +441,15 @@ impl ResolvedEntry {
metadata: Option<AliasPathMetadata>,
) -> Self {
let is_wildcard = short_name.contains("[*]");
let default_path_segments = default_path.split('.').map(String::from).collect();
let short_name_lc = if short_name.bytes().all(|b| !b.is_ascii_uppercase()) {
Rc::from(short_name.as_str())
} else {
Rc::from(short_name.to_ascii_lowercase())
};
let default_path_segments = default_path.split('.').map(Rc::from).collect();
let versioned_path_segments = versioned_paths
.iter()
.map(|(_, p)| p.split('.').map(String::from).collect())
.map(|(_, p)| p.split('.').map(Rc::from).collect())
.collect();
Self {
short_name,
@@ -431,6 +457,7 @@ impl ResolvedEntry {
versioned_paths,
metadata,
is_wildcard,
short_name_lc,
default_path_segments,
versioned_path_segments,
}
@@ -456,7 +483,7 @@ impl ResolvedEntry {
/// Returns the versioned segments if `api_version` matches, otherwise
/// the default segments. This avoids per-call `split('.')` for both
/// default and versioned scalar alias navigation.
pub fn select_path_segments(&self, api_version: Option<&str>) -> &[String] {
pub(crate) fn select_path_segments(&self, api_version: Option<&str>) -> &[Rc<str>] {
if let Some(ver) = api_version {
for (i, (v, _)) in self.versioned_paths.iter().enumerate() {
if v.eq_ignore_ascii_case(ver) {

View File

@@ -18,6 +18,7 @@ use crate::rvm::program::{Program, SpanInfo};
use crate::rvm::Instruction;
use crate::{Rc, Value};
use crate::languages::azure_policy::aliases::AliasRegistry;
use crate::languages::azure_policy::ast::PolicyRule;
// ---------------------------------------------------------------------------
@@ -44,10 +45,9 @@ pub(super) struct Compiler {
pub(super) cached_input_reg: Option<u8>,
/// Cached register for `LoadContext` — allocated once on first use.
pub(super) cached_context_reg: Option<u8>,
/// Map from lowercase fully-qualified alias name → short name.
pub(super) alias_map: BTreeMap<String, String>,
/// Map from lowercase fully-qualified alias name → modifiable flag.
pub(super) alias_modifiable: BTreeMap<String, bool>,
/// Alias registry for resolving fully-qualified alias names.
/// Shared via `Rc` to avoid cloning the 73K-entry alias maps.
pub(super) alias_registry: Option<Rc<AliasRegistry>>,
/// Default values for policy parameters.
pub(super) parameter_defaults: Option<Value>,
/// Cached literal-table index for `parameter_defaults` (or an empty object
@@ -338,8 +338,13 @@ impl Compiler {
path: &str,
span: &crate::lexer::Span,
) -> Result<String> {
let alias_map = match &self.alias_registry {
Some(reg) => reg.alias_map(),
None => return Ok(path.to_string()),
};
let lc = path.to_ascii_lowercase();
if let Some(short) = self.alias_map.get(&lc) {
if let Some(short) = alias_map.get(&lc) {
let resolved = short.clone();
let result = Self::strip_fq_prefix(&resolved).to_ascii_lowercase();
return Ok(result);
@@ -348,7 +353,7 @@ impl Compiler {
// Fallback: derive array path from a corresponding `[*]` alias.
if !lc.contains("[*]") {
let wildcard_key = alloc::format!("{}[*]", lc);
if let Some(short) = self.alias_map.get(&wildcard_key) {
if let Some(short) = alias_map.get(&wildcard_key) {
let resolved = Self::strip_fq_prefix(short).to_ascii_lowercase();
if let Some(base) = resolved.strip_suffix("[*]") {
return Ok(base.to_string());
@@ -356,14 +361,14 @@ impl Compiler {
}
}
if !self.alias_map.is_empty() && !self.alias_fallback_to_raw {
if !alias_map.is_empty() && !self.alias_fallback_to_raw {
bail!(span.error(&alloc::format!(
"unknown alias '{}': field references must use fully-qualified alias names when an alias catalog is loaded",
path
)));
}
if self.alias_map.is_empty() {
if alias_map.is_empty() {
Ok(path.to_string())
} else {
let result = Self::strip_fq_prefix(path).to_ascii_lowercase();

View File

@@ -998,7 +998,13 @@ impl Compiler {
return Ok(result);
}
}
Err(e) if !self.alias_map.is_empty() && !self.alias_fallback_to_raw => {
Err(e)
if self
.alias_registry
.as_ref()
.is_some_and(|r| !r.alias_map().is_empty())
&& !self.alias_fallback_to_raw =>
{
return Err(e);
}
_ => {}

View File

@@ -692,13 +692,18 @@ impl Compiler {
field_path: &str,
span: &crate::lexer::Span,
) -> Result<()> {
if self.alias_modifiable.is_empty() {
let modifiable_map = match &self.alias_registry {
Some(reg) => reg.alias_modifiable_map(),
None => return Ok(()),
};
if modifiable_map.is_empty() {
return Ok(());
}
let lc = field_path.to_lowercase();
if let Some(&modifiable) = self.alias_modifiable.get(&lc) {
if let Some(&modifiable) = modifiable_map.get(&lc) {
if !modifiable {
bail!(span.error(&format!(
"alias '{}' is not modifiable (defaultMetadata.attributes != 'Modifiable')",
@@ -803,7 +808,6 @@ fn unescape_arm_literal(s: &str) -> alloc::string::String {
/// 1. Build a template `BTreeMap` with `Value::Undefined` placeholders.
/// 2. Sort keys by their literal value (BTreeMap order).
/// 3. Emit `ObjectCreate`.
#[allow(clippy::indexing_slicing)]
pub(super) fn build_object_from_keys(
compiler: &mut Compiler,
mut keys: Vec<(u16, u8)>,
@@ -812,17 +816,33 @@ pub(super) fn build_object_from_keys(
// Build template: object with all keys set to Undefined.
let mut template = BTreeMap::new();
for &(key_idx, _) in &keys {
// SAFETY: key_idx was just returned by `add_literal_u16`, so the
// index is guaranteed to be in bounds.
let key_val = compiler.program.literals[usize::from(key_idx)].clone();
// key_idx was returned by `add_literal_u16` in the calling code,
// so it is always in bounds. We use `.get()` + `?` instead of
// direct indexing to satisfy the crate-wide `deny(indexing_slicing)`.
let key_val = compiler
.program
.literals
.get(usize::from(key_idx))
.ok_or_else(|| {
anyhow!(
"internal error in build_object_from_keys: \
literal index {} out of bounds (literals len = {})",
key_idx,
compiler.program.literals.len()
)
})?
.clone();
template.insert(key_val, Value::Undefined);
}
let template_idx = compiler.add_literal_u16(Value::Object(crate::Rc::new(template)))?;
// Sort keys by literal value (BTreeMap order).
// Sort keys by literal value (BTreeMap order). All indices were
// validated in the loop above (which returns Err for out-of-bounds),
// so `.get()` always returns `Some` here — `None` is unreachable.
keys.sort_by(|a, b| {
compiler.program.literals[usize::from(a.0)]
.cmp(&compiler.program.literals[usize::from(b.0)])
let a_val = compiler.program.literals.get(usize::from(a.0));
let b_val = compiler.program.literals.get(usize::from(b.0));
a_val.cmp(&b_val)
});
let dest = compiler.alloc_register()?;

View File

@@ -30,11 +30,11 @@ mod metadata;
mod template_dispatch;
mod utils;
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString as _};
use alloc::string::ToString as _;
use anyhow::Result;
use crate::languages::azure_policy::aliases::AliasRegistry;
use crate::languages::azure_policy::ast::{PolicyDefinition, PolicyRule};
use crate::rvm::program::Program;
use crate::{Rc, Value};
@@ -69,17 +69,14 @@ pub fn compile_policy_rule(rule: &PolicyRule) -> Result<Rc<Program>> {
/// Compile a parsed Azure Policy rule with alias resolution.
///
/// The `alias_map` maps lowercase fully-qualified alias names to their short
/// names. Obtain it from
/// [`AliasRegistry::alias_map()`](crate::languages::azure_policy::aliases::AliasRegistry::alias_map).
/// The registry provides alias-to-short-name resolution and modifiability
/// data. Pass it as an `Rc` to avoid cloning the internal alias maps.
pub fn compile_policy_rule_with_aliases(
rule: &PolicyRule,
alias_map: BTreeMap<String, String>,
alias_modifiable: BTreeMap<String, bool>,
registry: Rc<AliasRegistry>,
) -> Result<Rc<Program>> {
let mut compiler = Compiler::new();
compiler.alias_map = alias_map;
compiler.alias_modifiable = alias_modifiable;
compiler.alias_registry = Some(registry);
init_effect_annotation(&mut compiler, rule);
compiler.compile(rule)
}
@@ -100,12 +97,10 @@ pub fn compile_policy_definition(defn: &PolicyDefinition) -> Result<Rc<Program>>
/// Compile a parsed Azure Policy definition with alias resolution.
pub fn compile_policy_definition_with_aliases(
defn: &PolicyDefinition,
alias_map: BTreeMap<String, String>,
alias_modifiable: BTreeMap<String, bool>,
registry: Rc<AliasRegistry>,
) -> Result<Rc<Program>> {
let mut compiler = Compiler::new();
compiler.alias_map = alias_map;
compiler.alias_modifiable = alias_modifiable;
compiler.alias_registry = Some(registry);
compiler.parameter_defaults = Some(build_parameter_defaults(&defn.parameters)?);
compiler.populate_definition_metadata(defn);
init_effect_annotation(&mut compiler, &defn.policy_rule);
@@ -119,13 +114,11 @@ pub fn compile_policy_definition_with_aliases(
/// a known alias are silently treated as raw property paths.
pub fn compile_policy_definition_with_aliases_opts(
defn: &PolicyDefinition,
alias_map: BTreeMap<String, String>,
alias_modifiable: BTreeMap<String, bool>,
registry: Rc<AliasRegistry>,
alias_fallback_to_raw: bool,
) -> Result<Rc<Program>> {
let mut compiler = Compiler::new();
compiler.alias_map = alias_map;
compiler.alias_modifiable = alias_modifiable;
compiler.alias_registry = Some(registry);
compiler.alias_fallback_to_raw = alias_fallback_to_raw;
compiler.parameter_defaults = Some(build_parameter_defaults(&defn.parameters)?);
compiler.populate_definition_metadata(defn);

View File

@@ -63,6 +63,14 @@ pub enum CompilerError {
#[error("Invalid function expression with package")]
InvalidFunctionExpressionWithPackage,
#[error("partial object rules with constant keys are not yet supported by the RVM compiler")]
PartialObjectConstantKeyUnsupported,
#[error(
"partial object rules with nested bracket keys are not yet supported by the RVM compiler"
)]
PartialObjectNestedKeyUnsupported,
#[error("Compilation error: {message}")]
General { message: String },
}

View File

@@ -59,7 +59,7 @@ impl<'a> Compiler<'a> {
crate::ast::Expr::RefBrack { .. } if assign.is_some() => {
RuleType::PartialObject
}
crate::ast::Expr::RefBrack { .. } => RuleType::PartialSet,
crate::ast::Expr::RefBrack { .. } => RuleType::PartialObject,
_ => RuleType::Complete,
},
_ => RuleType::Complete,
@@ -88,6 +88,54 @@ impl<'a> Compiler<'a> {
})
}
fn validate_partial_object_shape(&self, refr: &ExprRef) -> Result<()> {
let Expr::RefBrack {
refr: prefix,
index,
..
} = refr.as_ref()
else {
return Ok(());
};
if Self::has_unsupported_bracket_prefix(prefix) {
return Err(CompilerError::PartialObjectNestedKeyUnsupported.at(refr.span()));
}
if Self::is_simple_literal(index) {
return Err(CompilerError::PartialObjectConstantKeyUnsupported.at(index.span()));
}
Ok(())
}
fn has_unsupported_bracket_prefix(expr: &ExprRef) -> bool {
match expr.as_ref() {
Expr::RefBrack { refr, index, .. } => {
!Self::is_string_literal(index) || Self::has_unsupported_bracket_prefix(refr)
}
Expr::RefDot { refr, .. } => Self::has_unsupported_bracket_prefix(refr),
_ => false,
}
}
fn is_string_literal(expr: &ExprRef) -> bool {
matches!(expr.as_ref(), Expr::String { .. } | Expr::RawString { .. })
}
fn is_simple_literal(expr: &ExprRef) -> bool {
match expr.as_ref() {
Expr::String { .. }
| Expr::RawString { .. }
| Expr::Number { .. }
| Expr::Bool { .. }
| Expr::Null { .. } => true,
// Unary expressions like `-1` are constant literals too.
Expr::UnaryExpr { expr, .. } => Self::is_simple_literal(expr),
_ => false,
}
}
pub(super) fn get_or_assign_rule_index(&mut self, rule_path: &str) -> Result<u16> {
if let Some(&index) = self.rule_index_map.get(rule_path) {
return Ok(index);
@@ -345,6 +393,10 @@ impl<'a> Compiler<'a> {
let (key_expr, value_expr) = match head {
RuleHead::Compr { refr, assign, .. } => {
if rule_type == RuleType::PartialObject {
self.validate_partial_object_shape(refr)?;
}
self.rule_definition_function_params[rule_index as usize].push(None);
self.rule_definition_destructuring_patterns[rule_index as usize]
.push(None);

View File

@@ -23,8 +23,7 @@ use regorus::languages::azure_policy::aliases::AliasRegistry;
use regorus::languages::azure_policy::compiler;
use regorus::languages::azure_policy::parser;
use regorus::rvm::RegoVM;
use regorus::Source;
use regorus::Value;
use regorus::{Rc, Source, Value};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fs;
@@ -194,7 +193,7 @@ fn yaml_test_impl(file: &str) -> Result<()> {
let test: YamlTest = serde_yaml::from_str(&yaml_str)?;
// Load alias registry if an aliases file is specified.
let alias_registry = if let Some(ref aliases_file) = test.aliases {
let alias_registry: Option<Rc<AliasRegistry>> = if let Some(ref aliases_file) = test.aliases {
let aliases_dir = Path::new(file)
.parent()
.unwrap_or_else(|| Path::new("."))
@@ -209,7 +208,7 @@ fn yaml_test_impl(file: &str) -> Result<()> {
})?;
let mut registry = AliasRegistry::new();
registry.load_from_json(&aliases_json)?;
Some(registry)
Some(Rc::new(registry))
} else {
None
};
@@ -281,11 +280,7 @@ fn yaml_test_impl(file: &str) -> Result<()> {
);
}
if let Some(ref registry) = alias_registry {
compiler::compile_policy_definition_with_aliases(
&defn,
registry.alias_map(),
registry.alias_modifiable_map(),
)
compiler::compile_policy_definition_with_aliases(&defn, Rc::clone(registry))
} else {
compiler::compile_policy_definition(&defn)
}
@@ -308,11 +303,7 @@ fn yaml_test_impl(file: &str) -> Result<()> {
);
}
if let Some(ref registry) = alias_registry {
compiler::compile_policy_rule_with_aliases(
&ast,
registry.alias_map(),
registry.alias_modifiable_map(),
)
compiler::compile_policy_rule_with_aliases(&ast, Rc::clone(registry))
} else {
compiler::compile_policy_rule(&ast)
}
@@ -366,7 +357,7 @@ fn yaml_test_impl(file: &str) -> Result<()> {
let mut vm = RegoVM::new();
vm.load_program(program);
vm.set_input(make_input(case, alias_registry.as_ref())?);
vm.set_input(make_input(case, alias_registry.as_deref())?);
vm.set_context(make_context(case)?);
// Load host-await responses (for auditIfNotExists / deployIfNotExists policies).
@@ -391,7 +382,11 @@ fn yaml_test_impl(file: &str) -> Result<()> {
if let Some(rt) = effective_type {
inject_type_field(&mut raw, rt);
}
normalizer::normalize(&raw, Some(registry), case.api_version.as_deref())
normalizer::normalize(
&raw,
Some(registry.as_ref()),
case.api_version.as_deref(),
)
} else {
raw
}

View File

@@ -0,0 +1,150 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
cases:
- note: constant_key_partial_object_v1
data: {}
input:
enabled: true
modules:
- |
package test
import rego.v1
p["fixed"] if {
input.enabled
}
query: data.test
want_result:
p:
fixed: true
- note: multilevel_partial_object_v1
data: {}
input:
nested:
app:
read: 1
write: 2
ops:
deploy: 3
modules:
- |
package test
import rego.v1
p[a][b] if {
some a, obj in input.nested
some b, _ in obj
}
query: data.test
want_result:
p:
app:
read: true
write: true
ops:
deploy: true
- note: constant_key_partial_object_explicit_value_v1
data: {}
input:
enabled: true
modules:
- |
package test
import rego.v1
p["fixed"] := 7 if {
input.enabled
}
query: data.test
want_result:
p:
fixed: 7
- note: multilevel_partial_object_explicit_value_v1
data: {}
input:
nested:
app:
read: 1
write: 2
ops:
deploy: 3
modules:
- |
package test
import rego.v1
p[a][b] := v if {
some a, obj in input.nested
some b, v in obj
}
query: data.test
want_result:
p:
app:
read: 1
write: 2
ops:
deploy: 3
- note: issue_712_reproducer_v0_partial_set
data: {}
input:
servers:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
import future.keywords.in
violations[k] {
some k, _ in input.servers
}
query: data.test.violations
want_result:
set!: ["BAR", "BAZ", "FOO"]
- note: issue_712_reproducer_v1_partial_object
data: {}
input:
servers:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
import rego.v1
violations[k] if {
some k, _ in input.servers
}
query: data.test.violations
want_result:
BAR: true
BAZ: true
FOO: true
- note: issue_712_reproducer_v1_contains_partial_set
data: {}
input:
servers:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
import rego.v1
violations contains k if {
some k, _ in input.servers
}
query: data.test.violations
want_result:
set!: ["BAR", "BAZ", "FOO"]

View File

@@ -275,6 +275,14 @@ fn is_with_keyword_unsupported_error(err: &anyhow::Error) -> bool {
})
}
fn is_partial_object_unsupported_error(err: &anyhow::Error) -> bool {
err.chain().any(|cause| {
let msg = cause.to_string();
msg.contains("partial object rules with constant keys are not yet supported")
|| msg.contains("partial object rules with nested bracket keys are not yet supported")
})
}
fn maybe_verify_rvm_case(case: &TestCase, is_rego_v0_test: bool, actual: &Value) -> Result<()> {
if case.note == "defaultkeyword/function with var arg, ref head query" {
println!(
@@ -308,6 +316,14 @@ fn maybe_verify_rvm_case(case: &TestCase, is_rego_v0_test: bool, actual: &Value)
return Ok(());
}
if is_partial_object_unsupported_error(&err) {
println!(
" skipping RVM check for '{}' (partial object pattern unsupported)",
case.note
);
return Ok(());
}
return Err(err);
}
};

View File

@@ -0,0 +1,939 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
cases:
- note: partial_object_variable_key_collects_all_bindings
data: {}
input:
items:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
p[k] if {
some k, _ in input.items
}
query: data.test.p
want_result:
BAR: true
BAZ: true
FOO: true
- note: partial_object_explicit_value_collects_all_bindings
data: {}
input:
items:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
p[k] := v if {
some k, v in input.items
}
query: data.test.p
want_result:
BAR: 2
BAZ: 3
FOO: 1
- note: partial_object_dynamic_expression_key_collects_all_bindings
data: {}
input:
items:
FOO: 1
BAR: 2
BAZ: 3
aliases:
FOO: alias-foo
BAR: alias-bar
BAZ: alias-baz
modules:
- |
package test
p[input.aliases[k]] := v if {
some k, v in input.items
}
query: data.test.p
want_result:
alias-bar: 2
alias-baz: 3
alias-foo: 1
- note: partial_object_undefined_key_skipped
# TODO(#719): RVM incorrectly materializes undefined keys instead of
# skipping iterations where the key is undefined.
skip: true
data: {}
input:
items:
FOO: 1
BAR: 2
aliases:
FOO: alias-foo
modules:
- |
package test
p[input.aliases[k]] := v if {
some k, v in input.items
}
query: data.test.p
want_result:
alias-foo: 1
- note: partial_object_duplicate_key_last_wins
# TODO(#719): regorus silently overwrites conflicting keys instead of
# erroring when the same key is produced with different values.
skip: true
data: {}
input: {}
modules:
- |
package test
p[k] := v if {
some k, v in {"a": 1}
}
p[k] := v if {
some k, v in {"a": 2}
}
query: data.test.p
want_error: "conflict"
- note: partial_object_duplicate_key_same_value_ok
data: {}
input: {}
modules:
- |
package test
p[k] if {
some k, _ in {"a": 1}
}
p[k] if {
some k, _ in {"a": 2}
}
query: data.test.p
want_result:
a: true
- note: partial_object_single_element_input
data: {}
input:
items:
ONLY: 1
modules:
- |
package test
p[k] if {
some k, _ in input.items
}
query: data.test.p
want_result:
ONLY: true
- note: partial_object_static_bracket_prefix_collects_all_bindings
data: {}
input:
items:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
p["a"][k] := v if {
some k, v in input.items
}
query: data.test.p.a
want_result:
BAR: 2
BAZ: 3
FOO: 1
- note: partial_object_constant_key_unsupported_in_rvm
data: {}
input:
enabled: true
modules:
- |
package test
p["fixed"] if {
input.enabled
}
query: data.test.p.fixed
want_error: "partial object rules with constant keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_constant_key_explicit_value_unsupported_in_rvm
data: {}
input:
enabled: true
modules:
- |
package test
p["fixed"] := 7 if {
input.enabled
}
query: data.test.p.fixed
want_error: "partial object rules with constant keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_multiple_bodies_collects_all_bindings
data: {}
input:
items:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
p[k] if {
some k, _ in input.items
k in {"FOO", "BAR"}
}
p[k] if {
some k, _ in input.items
k == "BAZ"
}
query: data.test.p
want_result:
BAR: true
BAZ: true
FOO: true
- note: partial_set_contains_collects_all_bindings
data: {}
input:
items:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
p contains k if {
some k, _ in input.items
}
query: data.test.p
want_result:
set!: ["BAR", "BAZ", "FOO"]
- note: issue_712_reproducer_v1_partial_object
data: {}
input:
servers:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
import rego.v1
violations[k] if {
some k, _ in input.servers
}
query: data.test.violations
want_result:
BAR: true
BAZ: true
FOO: true
- note: issue_712_reproducer_v1_contains_partial_set
data: {}
input:
servers:
FOO: 1
BAR: 2
BAZ: 3
modules:
- |
package test
import rego.v1
violations contains k if {
some k, _ in input.servers
}
query: data.test.violations
want_result:
set!: ["BAR", "BAZ", "FOO"]
- note: partial_object_multilevel_key_unsupported_in_rvm
data: {}
input:
nested:
app:
read: 1
write: 2
ops:
deploy: 3
modules:
- |
package test
p[a][b] if {
some a, obj in input.nested
some b, _ in obj
}
main := p
query: data.test.main
want_error: "partial object rules with nested bracket keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_multilevel_key_explicit_value_unsupported_in_rvm
data: {}
input:
nested:
app:
read: 1
write: 2
ops:
deploy: 3
modules:
- |
package test
p[a][b] := v if {
some a, obj in input.nested
some b, v in obj
}
main := p
query: data.test.main
want_error: "partial object rules with nested bracket keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_hidden_dynamic_prefix_unsupported_in_rvm
data: {}
input:
nested:
app:
q:
read: 1
write: 2
ops:
q:
deploy: 3
modules:
- |
package test
p[a].q[b] if {
some a, obj in input.nested
some b, _ in obj.q
}
main := p
query: data.test.main
want_error: "partial object rules with nested bracket keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_array_iteration_collects_all_bindings
data: {}
input:
items: ["FOO", "BAR", "BAZ"]
modules:
- |
package test
p[v] if {
some _, v in input.items
}
query: data.test.p
want_result:
BAR: true
BAZ: true
FOO: true
- note: partial_object_empty_input_is_empty_object
data: {}
input:
items: {}
modules:
- |
package test
p[k] if {
some k, _ in input.items
}
query: data.test.p
want_result: {}
- note: partial_object_duplicate_paths_same_key_same_value_deduplicates
data: {}
input:
pairs:
- alias: shared
value: 1
- alias: alpha
value: 10
- alias: shared
value: 1
modules:
- |
package test
p[entry.alias] := entry.value if {
some entry in input.pairs
}
query: data.test.p
want_result:
alpha: 10
shared: 1
- note: partial_object_duplicate_paths_same_key_different_values_conflict
# TODO(#719): regorus silently overwrites conflicting keys instead of
# erroring when the same key is produced with different values.
skip: true
data: {}
input:
pairs:
- alias: shared
value: 1
- alias: shared
value: 2
modules:
- |
package test
p[entry.alias] := entry.value if {
some entry in input.pairs
}
query: data.test.p
want_error: "conflict"
- note: partial_object_undefined_key_skips_iteration
# TODO(#719): RVM incorrectly materializes undefined keys instead of
# skipping iterations where the key is undefined.
skip: true
data: {}
input:
items:
FOO: 1
BAR: 2
BAZ: 3
aliases:
FOO: alias-foo
BAZ: alias-baz
modules:
- |
package test
p[input.aliases[k]] := v if {
some k, v in input.items
}
query: data.test.p
want_result:
alias-baz: 3
alias-foo: 1
- note: partial_object_undefined_value_skips_iteration
# TODO(#719): RVM incorrectly materializes undefined values instead of
# skipping iterations where the value is undefined.
skip: true
data: {}
input:
keys: ["FOO", "BAR", "BAZ"]
values:
FOO: 1
BAZ: 3
modules:
- |
package test
p[k] := input.values[k] if {
some _, k in input.keys
}
query: data.test.p
want_result:
BAZ: 3
FOO: 1
- note: partial_object_mixed_undefined_key_value_cases_skip_bad_iterations
# TODO(#719): RVM incorrectly materializes undefined keys/values instead of
# skipping iterations where the key or value is undefined.
skip: true
data: {}
input:
rows:
- src: keep
- src: missing_alias
- src: missing_value
- src: missing_both
aliases:
keep: alias-keep
missing_value: alias-no-value
values:
keep: 1
missing_alias: 2
modules:
- |
package test
p[input.aliases[row.src]] := input.values[row.src] if {
some row in input.rows
}
query: data.test.p
want_result:
alias-keep: 1
- note: partial_object_and_partial_set_same_name_conflict
data: {}
input:
items:
FOO: 1
modules:
- |
package test
p[k] if {
some k, _ in input.items
}
p contains "shadow" if {
true
}
query: data.test.p
want_error: "has multiple types"
- note: partial_object_complete_rule_conflicts_with_partial_object
data: {}
input:
items:
a: 1
modules:
- |
package test
p := {"fixed": 1}
p[k] := v if {
some k, v in input.items
}
query: data.test.p
want_error: "multiple types"
- note: partial_object_partial_set_conflicts_with_partial_object
data: {}
input:
items:
a: 1
modules:
- |
package test
p contains k if {
some k, _ in input.items
}
p[k] := 1 if {
some k, _ in input.items
}
query: data.test.p
want_error: "multiple types"
- note: partial_object_large_range_counts_all_entries
data: {}
input: {}
modules:
- |
package test
p[key] := n if {
n := numbers.range(0, 255)[_]
key := sprintf("k-%d", [n])
}
main := count(p)
query: data.test.main
want_result: 256
- note: partial_object_rbac_duplicate_actions_deduplicate
data:
role_permissions:
reader: ["read", "list"]
writer: ["read", "write"]
auditor: ["read", "list"]
input:
user_roles: ["reader", "writer", "auditor"]
modules:
- |
package test
allowed_actions[action] if {
some role in input.user_roles
some action in data.role_permissions[role]
}
query: data.test.allowed_actions
want_result:
list: true
read: true
write: true
- note: partial_object_violations_real_world_pattern
data: {}
input:
spec:
containers:
- name: api
securityContext:
readOnlyRootFilesystem: false
- name: worker
securityContext:
readOnlyRootFilesystem: true
- name: sidecar
modules:
- |
package test
violations[msg] if {
some container in input.spec.containers
not container.securityContext.readOnlyRootFilesystem
msg := sprintf("Container %s must use readOnlyRootFilesystem", [container.name])
}
query: data.test.violations
want_result:
Container api must use readOnlyRootFilesystem: true
Container sidecar must use readOnlyRootFilesystem: true
- note: partial_object_resource_mapping_filters_valid_resources
data: {}
input:
resources:
svc-api:
cpu: 1
job-cleanup:
cpu: 2
svc-worker:
cpu: 4
modules:
- |
package test
valid_resource(name) if {
startswith(name, "svc-")
}
resources[name] := config if {
some name, config in input.resources
valid_resource(name)
}
query: data.test.resources
want_result:
svc-api:
cpu: 1
svc-worker:
cpu: 4
- note: partial_object_computed_concat_key_constant_body
data: {}
modules:
- |
package test
p[concat("", ["edge", "-", "key"])] if {
true
}
query: data.test.p
want_result:
edge-key: true
- note: partial_object_duplicate_computed_key_same_value_merges
data: {}
input:
items:
A: 0
a: 0
modules:
- |
package test
p[lower(k)] := 1 if {
some k, _ in input.items
}
query: data.test.p
want_result:
a: 1
- note: partial_object_function_key_and_object_value
data: {}
input:
items:
a: 1
b: 2
modules:
- |
package test
f(x) := concat(":", [x, "suffix"])
p[f(k)] := {"nested": v + 1} if {
some k, v in input.items
}
query: data.test.p
want_result:
"a:suffix":
nested: 2
"b:suffix":
nested: 3
- note: partial_object_array_index_key_uses_selected_elements
data: {}
input:
keys: ["alpha", "beta"]
values: [10, 20]
modules:
- |
package test
p[input.keys[i]] := v if {
some i, v in input.values
}
query: data.test.p
want_result:
alpha: 10
beta: 20
- note: partial_object_computed_empty_and_special_string_keys
data: {}
modules:
- |
package test
p[concat("", [""])] := "empty" if {
true
}
p[concat("", ["a/b?c#d"])] := "special" if {
true
}
query: data.test.p
want_result:
"": "empty"
a/b?c#d: "special"
- note: partial_object_not_filters_blocked_entries
data: {}
input:
items:
allowed: true
blocked: true
blocked:
blocked: true
modules:
- |
package test
p[k] if {
some k, _ in input.items
not input.blocked[k]
}
query: data.test.p
want_result:
allowed: true
- note: partial_object_dot_bracket_object_value_collects_all_bindings
data: {}
input:
items:
a: 1
b: 2
modules:
- |
package test
p.config[k] := {"nested": v} if {
some k, v in input.items
}
query: data.test.p.config
want_result:
a:
nested: 1
b:
nested: 2
- note: partial_object_dynamic_prefix_static_suffix_unsupported_in_rvm
data: {}
input:
items:
a: 1
b: 2
modules:
- |
package test
p[k]["fixed"] := upper(k) if {
some k, _ in input.items
}
main := p
query: data.test.main
want_error: "partial object rules with nested bracket keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_literal_prefix_nested_unsupported_in_rvm
data: {}
input:
items:
a: 1
b: 2
modules:
- |
package test
p[1][k] := v if {
some k, v in input.items
}
main := p
query: data.test.main
want_error: "partial object rules with nested bracket keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_three_level_nested_dynamic_unsupported_in_rvm
data: {}
input:
nested:
app:
read: 1
write: 2
ops:
deploy: 3
modules:
- |
package test
p["root"][a][b] := v if {
some a, obj in input.nested
some b, v in obj
}
main := p
query: data.test.main
want_error: "partial object rules with nested bracket keys are not yet supported by the RVM compiler"
allow_interpreter_success: true
- note: partial_object_with_body_unsupported_in_rvm
data: {}
input:
enabled: false
items:
a: 1
modules:
- |
package test
gate if {
input.enabled
}
p[k] := v if {
some k, v in input.items
data.test.gate with input as {"enabled": true}
}
query: data.test.p
want_error: "the `with` keyword is not supported by the compiler yet"
allow_interpreter_success: true
- note: partial_object_every_vacuous_truth_collects_empty_arrays
# TODO(#719): RVM currently includes the failing `bad` group here, while the
# interpreter returns only `empty` and `ok` (expected per vacuous truth
# semantics).
skip: true
data: {}
input:
groups:
ok: [1, 2]
bad: [1, 0]
empty: []
modules:
- |
package test
p[k] if {
some k, arr in input.groups
every v in arr {
v > 0
}
}
query: data.test.p
want_result:
empty: true
ok: true
- note: partial_object_join_var_multiple_bindings
data:
a: ["1", "2", "3", "4"]
g:
a: ["1", "0", "0", "0"]
b: ["0", "2", "0", "0"]
c: ["0", "0", "0", "4"]
modules:
- |
package test
p[k] := v if {
data.a[i] = v
data.g[k][i] = v
}
query: data.test.p
want_result:
a: "1"
b: "2"
c: "4"
- note: partial_object_composite_value
data:
g:
a: [1, 0, 0, 0]
b: [0, 2, 0, 0]
c: [0, 0, 0, 4]
modules:
- |
package test
p[k] := [i, {"v2": v}] if {
data.g[k] = x
x[i] = v
v != 0
}
query: data.test.p
want_result:
a: [0, {v2: 1}]
b: [1, {v2: 2}]
c: [3, {v2: 4}]
- note: partial_object_true_semantics_dedupes_duplicate_keys
data: {}
modules:
- |
package test
p[k] if {
ks := ["a", "b", "c", "a"]
ks[_] = k
}
query: data.test.p
want_result:
a: true
b: true
c: true