From 234c16842635fcd5fa83a8b0d84e2eb4755ba18e Mon Sep 17 00:00:00 2001 From: Amit Saxena Date: Sun, 15 Mar 2026 18:22:36 +0530 Subject: [PATCH] wasm bindings added --- .cargo/config.toml | 7 +- .gitignore | 3 +- Cargo.toml | 5 +- bindings/wasm/Cargo.toml | 28 +++ bindings/wasm/LICENSE | 201 +++++++++++++++++++ bindings/wasm/src/lib.rs | 190 ++++++++++++++++++ bindings/wasm/test/browser_test.html | 25 +++ bindings/wasm/test/loader.js | 21 ++ bindings/wasm/test/node_test.js | 9 + bindings/wasm/test/package.json | 19 ++ core/Cargo.toml | 3 + core/src/ir.rs | 3 +- doc/actra-specifications/roadmap.md | 277 +++++++++++++++++++++++++++ scripts/test_py_sdk_build.sh | 6 +- scripts/wasm_pack.sh | 53 +++++ 15 files changed, 842 insertions(+), 8 deletions(-) create mode 100644 bindings/wasm/Cargo.toml create mode 100644 bindings/wasm/LICENSE create mode 100644 bindings/wasm/src/lib.rs create mode 100644 bindings/wasm/test/browser_test.html create mode 100644 bindings/wasm/test/loader.js create mode 100644 bindings/wasm/test/node_test.js create mode 100644 bindings/wasm/test/package.json create mode 100644 doc/actra-specifications/roadmap.md create mode 100644 scripts/wasm_pack.sh diff --git a/.cargo/config.toml b/.cargo/config.toml index 4405422..4ff08ab 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -5,4 +5,9 @@ target-dir = "target" rustflags = ["-C", "target-cpu=generic"] [target.aarch64-unknown-linux-gnu] -rustflags = ["-C", "target-cpu=generic"] \ No newline at end of file +rustflags = ["-C", "target-cpu=generic"] + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "opt-level=z" +] diff --git a/.gitignore b/.gitignore index 6b02796..0b2cbe7 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,5 @@ lib_actra_core.dylib.dSYM/ venv_test wheelhouse ____*/ -____* \ No newline at end of file +____* +bindings/wasm/pkg/ \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index e716667..d630af1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,13 +2,14 @@ members = [ "core", "bindings/python", - "bindings/node" + "bindings/node", + "bindings/wasm" ] resolver = "2" [workspace.package] -version = "0.5.0" +version = "0.5.1" edition = "2021" license = "Apache-2.0" authors = ["Amit Saxena"] diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml new file mode 100644 index 0000000..4cb9bf6 --- /dev/null +++ b/bindings/wasm/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "actra-wasm" +version.workspace = true +edition.workspace = true +license = "Apache-2.0" +repository.workspace = true +description.workspace = true +authors.workspace = true + +[lib] +crate-type = ["cdylib"] + +[dependencies] +actra = { path = "../../core" } +wasm-bindgen = "0.2" +console_error_panic_hook = "0.1" +serde_yaml = "0.9" +serde-wasm-bindgen = "0.6.5" +serde = "1.0.228" + +[package.metadata.wasm-pack.profile.release] +wasm-opt = false + +[profile.release] +opt-level = "z" +lto = true +codegen-units = 1 +panic = "abort" diff --git a/bindings/wasm/LICENSE b/bindings/wasm/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/bindings/wasm/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/bindings/wasm/src/lib.rs b/bindings/wasm/src/lib.rs new file mode 100644 index 0000000..63a0c35 --- /dev/null +++ b/bindings/wasm/src/lib.rs @@ -0,0 +1,190 @@ +//! WebAssembly bindings for Actra. +//! +//! This module exposes the Actra policy engine to JavaScript environments +//! using `wasm-bindgen`. The binding layer performs minimal work and +//! delegates all semantic processing to the Rust core. +//! +//! Responsibilities: +//! - Deserialize YAML schema and policy definitions +//! - Compile policies into IR +//! - Convert JavaScript objects into engine input +//! - Convert evaluation results back into JavaScript objects +//! +//! All validation and evaluation logic resides in `actra-core`. + +use wasm_bindgen::prelude::*; +use serde::{Deserialize, Serialize}; +use serde_wasm_bindgen::{from_value, to_value}; + +use actra::ast::PolicyAst; +use actra::compiler::{compile_policy, compile_with_governance}; +use actra::engine::{evaluate, EvaluationInput}; +use actra::governance::GovernanceAst; +use actra::ir::{CompiledPolicy, Effect}; +use actra::schema::{Schema, SchemaAst}; +use actra::compiler_version as core_compiler_version; + +/// JavaScript-facing evaluation input structure. +#[derive(Deserialize)] +pub struct JsEvaluationInput { + pub action: std::collections::HashMap, + pub actor: std::collections::HashMap, + pub snapshot: std::collections::HashMap, +} + +/// JavaScript-facing evaluation output. +#[derive(Serialize)] +pub struct JsEvaluationOutput { + pub effect: String, + pub matched_rule: String, +} + +/// JavaScript-exposed Actra class. +/// +/// The compiled policy is stored internally. +/// Evaluation operations are pure and deterministic. +#[wasm_bindgen] +pub struct Actra { + compiled_policy: CompiledPolicy, +} + +#[wasm_bindgen] +impl Actra { + /// Creates a new Actra engine instance. + /// + /// Compilation happens immediately during construction. + /// + /// Parameters + /// ---------- + /// schema_yaml: + /// YAML schema definition describing data structure. + /// + /// policy_yaml: + /// YAML policy rules. + /// + /// governance_yaml: + /// Optional governance constraints. + /// + /// Returns + /// ------- + /// Actra instance with compiled policy. + /// + /// Throws + /// ------ + /// JavaScript Error if parsing or compilation fails. + #[wasm_bindgen(constructor)] + pub fn new( + schema_yaml: String, + policy_yaml: String, + governance_yaml: Option, + ) -> Result { + + let schema_ast: SchemaAst = + serde_yaml::from_str(&schema_yaml).map_err(to_js_err)?; + + let schema = Schema::from_ast(schema_ast); + + let policy_ast: PolicyAst = + serde_yaml::from_str(&policy_yaml).map_err(to_js_err)?; + + let compiled_policy = if let Some(gov_yaml) = governance_yaml { + + let governance_ast: GovernanceAst = + serde_yaml::from_str(&gov_yaml).map_err(to_js_err)?; + + compile_with_governance( + &schema, + policy_ast, + &governance_ast, + ).map_err(to_js_err)? + + } else { + + compile_policy( + &schema, + policy_ast, + ).map_err(to_js_err)? + }; + + Ok(Self { compiled_policy }) + } + + /// Evaluates the compiled policy against runtime input. + /// + /// Expected input format: + /// + /// ``` + /// { + /// action: { ... }, + /// actor: { ... }, + /// snapshot: { ... } + /// } + /// ``` + /// + /// Returns: + /// + /// ``` + /// { + /// effect: "allow" | "block" | "require_approval", + /// matched_rule: string + /// } + /// ``` + #[wasm_bindgen] + pub fn evaluate(&self, input: JsValue) -> Result { + + let js_input: JsEvaluationInput = + from_value(input)?; + + let eval_input = EvaluationInput { + action: js_input.action, + actor: js_input.actor, + snapshot: js_input.snapshot, + }; + + let result = evaluate( + &self.compiled_policy, + &eval_input, + ); + + let output = JsEvaluationOutput { + effect: effect_to_str(&result.effect).to_string(), + matched_rule: result.matched_rule.unwrap_or_default(), + }; + + to_value(&output).map_err(|e| e.into()) + } + + /// Returns the deterministic policy hash. + /// + /// Useful for: + /// - caching + /// - auditing + /// - reproducibility + #[wasm_bindgen] + pub fn policy_hash(&self) -> String { + self.compiled_policy.policy_hash() + } + + /// Returns the compiler version of the Actra core. + /// + /// This can be used to verify compatibility between + /// compiled policies and runtime engines. + #[wasm_bindgen] + pub fn compiler_version() -> String { + core_compiler_version().to_string() + } +} + +/// Converts Rust errors into JavaScript errors. +fn to_js_err(err: E) -> JsValue { + JsValue::from_str(&err.to_string()) +} + +/// Converts internal effect enum to string representation. +fn effect_to_str(effect: &Effect) -> &'static str { + match effect { + Effect::Allow => "allow", + Effect::Block => "block", + Effect::RequireApproval => "require_approval", + } +} \ No newline at end of file diff --git a/bindings/wasm/test/browser_test.html b/bindings/wasm/test/browser_test.html new file mode 100644 index 0000000..88e60ca --- /dev/null +++ b/bindings/wasm/test/browser_test.html @@ -0,0 +1,25 @@ + + + + + Actra WASM Test + + +

Actra WASM Browser Test

+
+ + + + \ No newline at end of file diff --git a/bindings/wasm/test/loader.js b/bindings/wasm/test/loader.js new file mode 100644 index 0000000..d8bb474 --- /dev/null +++ b/bindings/wasm/test/loader.js @@ -0,0 +1,21 @@ +let wasmModule; + +export async function loadActra() { + if (!wasmModule) { + if (typeof window !== "undefined") { + // Browser + wasmModule = await import("../pkg/web/actra_wasm.js"); + // Prefer default export init (common in wasm-pack) + if (wasmModule.default) { + await wasmModule.default(); + } else if (wasmModule.init) { + await wasmModule.init(); + } + } else { + // Node, Bun, Cloudflare Workers, Lambda + wasmModule = await import("../pkg/all/actra_wasm.js"); + } + } + + return wasmModule; +} \ No newline at end of file diff --git a/bindings/wasm/test/node_test.js b/bindings/wasm/test/node_test.js new file mode 100644 index 0000000..550d5be --- /dev/null +++ b/bindings/wasm/test/node_test.js @@ -0,0 +1,9 @@ +import { loadActra } from "./loader.js"; + +async function run() { + const wasm = await loadActra(); + console.log("Actra WASM compiler version:", wasm.Actra.compiler_version()); + +} + +run(); \ No newline at end of file diff --git a/bindings/wasm/test/package.json b/bindings/wasm/test/package.json new file mode 100644 index 0000000..746685a --- /dev/null +++ b/bindings/wasm/test/package.json @@ -0,0 +1,19 @@ +{ + "name": "test", + "type": "module", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "start": "node --experimental-wasm-modules index.js" + }, + "keywords": [], + "author": "", + "license": "Apache-2.0", + "description": "", + "dependencies": { + "actra-wasm": "file:../pkg" + }, + "devDependencies": { + "esbuild": "^0.27.4" + } +} \ No newline at end of file diff --git a/core/Cargo.toml b/core/Cargo.toml index d31cbd8..0dab8b0 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -14,5 +14,8 @@ thiserror = "2.0.18" sha2 = "0.10" hex = "0.4" +[features] +default = [] + [lib] crate-type = ["rlib"] \ No newline at end of file diff --git a/core/src/ir.rs b/core/src/ir.rs index d13a95f..f05f423 100644 --- a/core/src/ir.rs +++ b/core/src/ir.rs @@ -14,6 +14,7 @@ use std::collections::HashMap; use sha2::{Digest, Sha256}; +use serde::{Deserialize, Serialize}; /// Fully compiled and validated policy. /// @@ -97,7 +98,7 @@ pub enum ValueRef { /// Scalar values supported by the engine. /// /// These correspond to validated schema field types. -#[derive(Debug, Clone)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub enum ScalarValue { String(String), Number(f64), diff --git a/doc/actra-specifications/roadmap.md b/doc/actra-specifications/roadmap.md new file mode 100644 index 0000000..cc6e754 --- /dev/null +++ b/doc/actra-specifications/roadmap.md @@ -0,0 +1,277 @@ +# TODO – Policy Required Actions + +## Overview + +Actra currently supports the following decision effects: + +* `allow` +* `block` +* `require_approval` + +However, for advanced governance scenarios (especially AI agents and automated workflows), policies should be able to **describe what action must happen next** when a rule is triggered. + +This feature introduces **Policy Required Actions**, allowing policies to return structured instructions such as: + +* human approval +* MFA verification +* external tool execution +* additional validation steps + +This enables Actra to support **policy-driven workflows** rather than simple allow/deny decisions. + +--- + +# Example Policy + +```yaml +rules: + + - id: high_value_refund + + when: + action: refund + amount > 1000 + + effect: require_approval + + required_actions: + - type: human_approval + role: finance_manager +``` + +Example evaluation result: + +```json +{ + "effect": "require_approval", + "matched_rule": "high_value_refund", + "required_actions": [ + { + "type": "human_approval", + "role": "finance_manager" + } + ] +} +``` + +--- + +# Implementation Plan + +## 1. Rust Core – Decision Model + +Extend the decision structure. + +Current: + +```rust +pub struct EvaluationResult { + pub effect: Effect, + pub matched_rule: Option, +} +``` + +New: + +```rust +pub struct EvaluationResult { + pub effect: Effect, + pub matched_rule: Option, + pub required_actions: Vec, +} +``` + +Define: + +```rust +pub struct RequiredAction { + pub action_type: String, + pub params: HashMap, +} +``` + +Notes: + +* Keep `RequiredAction` generic +* Do not hardcode approval or MFA logic +* Policies define semantics + +--- + +## 2. Rust Compiler + +Extend policy parsing to support: + +``` +required_actions +``` + +Compiler responsibilities: + +* Parse `required_actions` from rule definitions +* Validate structure +* Attach actions to compiled rule representation + +Example compiled rule: + +``` +CompiledRule + ├─ conditions + ├─ effect + └─ required_actions +``` + +--- + +## 3. Rust Evaluation Engine + +During rule match: + +``` +if rule matches: + decision.effect = rule.effect + decision.required_actions = rule.required_actions +``` + +No additional runtime logic is required. + +The engine only **returns the instructions**. + +--- + +## 4. Rust - Node Bridge + +Ensure the Rust binding returns `required_actions` in the serialized decision. + +Example JSON returned to Node: + +```json +{ + "effect": "require_approval", + "matched_rule": "high_value_refund", + "required_actions": [ + { "type": "human_approval", "role": "finance_manager" } + ] +} +``` + +--- + +## 5. Node SDK + +Minimal changes required. + +Extend the Decision type: + +```ts +export interface RequiredAction { + type: string + [key: string]: any +} + +export interface Decision { + effect: "allow" | "block" | "require_approval" + matched_rule?: string + required_actions?: RequiredAction[] +} +``` + +Node runtime should **not interpret required actions**. + +It simply forwards the result to the application. + +--- + +# Usage Scenarios + +This feature enables: + +### Human-in-the-loop + +``` +refund > 1000 + require finance manager approval +``` + +### Security verification + +``` +transfer > 10000 + require MFA verification +``` + +### Tool execution + +``` +deploy_production + require security scan +``` + +### AI agent governance + +``` +delete_database + require human approval +``` + +--- + +# Design Principles + +1. Engine remains **deterministic** +2. Required actions are **data only** +3. Runtime systems decide how to execute them +4. SDKs remain **thin wrappers** + +--- + +# Status + +Planned feature. + +Implementation will begin in: + +* Rust compiler +* Rust evaluation engine + +SDK changes are minimal. + + +# TODO Actra WASM Browser Roadmap (Precompiled Policy Workflow) + +## 1. Goal +- Ship Actra policies to the browser in a **precompiled binary format** +- Eliminate runtime YAML parsing to reduce WASM size and startup time +- Support deterministic, versioned, and cacheable policies + +## 2. Workflow Overview +1. **Precompile Policies** + - Convert schema + policy (+ optional governance) YAML files into a binary `.actra` format + - CLI or Rust tool handles compilation + - Happens once per policy update, not at runtime + +2. **Serve Precompiled Policy** + - Host `.actra` files on public folder or CDN + - Use versioned filenames to manage caching and updates + +3. **Load in Browser** + - Fetch `.actra` binary as `Uint8Array` + - Initialize Actra WASM engine from precompiled policy + - Evaluate policies without runtime compilation + +## 3. Benefits +- **Smaller WASM**: removes YAML parser and compiler +- **Faster startup**: only deserialization + evaluation +- **Deterministic**: precompiled policies are fixed and auditable +- **Edge-friendly**: minimal runtime footprint +- **Versioning & caching**: policy files can be hashed for safe updates + +## 4. Optional Enhancements +- Support multiple precompiled policies and dynamic selection +- Hot-reloading in development environment +- Serve policies via CDN with cache headers for performance +- Include policy hashes in the runtime for integrity checks + +## 5. Release Pipeline (Simplified) +1. Precompile policies: `actra compile --output policy-v1.actra` +2. Deploy `.actra` binaries along with application code instead of yaml policies \ No newline at end of file diff --git a/scripts/test_py_sdk_build.sh b/scripts/test_py_sdk_build.sh index 863c6f4..eebda60 100755 --- a/scripts/test_py_sdk_build.sh +++ b/scripts/test_py_sdk_build.sh @@ -2,9 +2,9 @@ set -euo pipefail echo "Cleaning previous builds..." -#rm -rf target -#rm -rf venv_test -#rm -rf sdk/python/target wheelhouse +rm -rf target +rm -rf venv_test +rm -rf sdk/python/target wheelhouse echo "Creating temporary Python virtualenv..." python3 -m venv venv_test diff --git a/scripts/wasm_pack.sh b/scripts/wasm_pack.sh new file mode 100644 index 0000000..eb22fbd --- /dev/null +++ b/scripts/wasm_pack.sh @@ -0,0 +1,53 @@ +# Install wasm target +rustup target add wasm32-unknown-unknown + +# Install wasm-pack +cargo install wasm-pack + +# Browser build +# wasm-pack build bindings/wasm --target web --out-dir pkg/web + +# Node build +# wasm-pack build bindings/wasm --target nodejs --out-dir pkg/node + +# Bundler +# wasm-pack build bindings/wasm --target bundler --out-dir pkg + +# Optimize Linux +# sudo apt install binaryen + +# Optimize Mac +# brew install binaryen + +# Post pack +# wasm-opt -Oz -o bindings/wasm/pkg/actra_wasm_bg.wasm bindings/wasm/pkg/actra_wasm_bg.wasm + + +### Release +# 1. Browser build +wasm-pack build bindings/wasm --target web --out-dir pkg/web --release + +# 2. Node build +wasm-pack build bindings/wasm --target nodejs --out-dir pkg/all --release + +# cargo install wasm-opt + +# Optimize wasm, option #1 +wasm-opt -Oz \ + -o bindings/wasm/pkg/actra_wasm_bg.wasm \ + bindings/wasm/pkg/actra_wasm_bg.wasm + +# Optimize all, option #2 +wasm-opt -Oz \ + --strip-debug \ + --strip-producers \ + -o bindings/wasm/pkg/all/actra_wasm_bg.wasm \ + bindings/wasm/pkg/all/actra_wasm_bg.wasm + + # Optimize web, option #2 +wasm-opt -Oz \ + --strip-debug \ + --strip-producers \ + -o bindings/wasm/pkg/web/actra_wasm_bg.wasm \ + bindings/wasm/pkg/web/actra_wasm_bg.wasm + \ No newline at end of file