From 4effcc7597f1d8300414b68b4e577214ddec840b Mon Sep 17 00:00:00 2001 From: Ryth Azhur Date: Thu, 4 Jun 2026 03:38:26 -0400 Subject: [PATCH] Added LICENSE --- LICENSE | 95 ++++++++++++ README.md | 142 +++++++++++------- backends/mizan-django/pyproject.toml | 1 + backends/mizan-fastapi/pyproject.toml | 1 + backends/mizan-rust-axum/Cargo.toml | 2 +- backends/mizan-tauri/Cargo.toml | 2 +- backends/mizan-ts/package.json | 2 +- cores/mizan-python/pyproject.toml | 1 + cores/mizan-rust-macros/Cargo.toml | 2 +- cores/mizan-rust/Cargo.toml | 2 +- frontends/mizan-base/package.json | 2 +- frontends/mizan-react/package.json | 1 + frontends/mizan-rust/Cargo.toml | 2 +- frontends/mizan-svelte/package.json | 2 +- frontends/mizan-tauri-transport/package.json | 2 +- frontends/mizan-vue/package.json | 2 +- frontends/mizan-webview-channels/package.json | 2 +- .../mizan-webview-transport/package.json | 2 +- protocol/mizan-codegen/Cargo.toml | 2 +- protocol/mizan-generate/package.json | 2 +- workers/mizan-ssr/package.json | 2 +- 21 files changed, 201 insertions(+), 70 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b430d60 --- /dev/null +++ b/LICENSE @@ -0,0 +1,95 @@ +Copyright (c) 2026 Ryth Azhur + +Elastic License 2.0 + +URL: https://www.elastic.co/licensing/elastic-license + +## Acceptance + +By using the software, you agree to all of the terms and conditions below. + +## Copyright License + +The licensor grants you a non-exclusive, royalty-free, worldwide, +non-sublicensable, non-transferable license to use, copy, distribute, make +available, and prepare derivative works of the software, in each case subject to +the limitations and conditions below. + +## Limitations + +You may not provide the software to third parties as a hosted or managed +service, where the service provides users with access to any substantial set of +the features or functionality of the software. + +You may not move, change, disable, or circumvent the license key functionality +in the software, and you may not remove or obscure any functionality in the +software that is protected by the license key. + +You may not alter, remove, or obscure any licensing, copyright, or other notices +of the licensor in the software. Any use of the licensor’s trademarks is subject +to applicable law. + +## Patents + +The licensor grants you a license, under any patent claims the licensor can +license, or becomes able to license, to make, have made, use, sell, offer for +sale, import and have imported the software, in each case subject to the +limitations and conditions in this license. This license does not cover any +patent claims that you cause to be infringed by modifications or additions to +the software. If you or your company make any written claim that the software +infringes or contributes to infringement of any patent, your patent license for +the software granted under these terms ends immediately. If your company makes +such a claim, your patent license ends immediately for work on behalf of your +company. + +## Notices + +You must ensure that anyone who gets a copy of any part of the software from you +also gets a copy of these terms. + +If you modify the software, you must include in any modified copies of the +software prominent notices stating that you have modified the software. + +## No Other Rights + +These terms do not imply any licenses other than those expressly granted in +these terms. + +## Termination + +If you use the software in violation of these terms, such use is not licensed, +and your licenses will automatically terminate. If the licensor provides you +with a notice of your violation, and you cease all violation of this license no +later than 30 days after you receive that notice, your licenses will be +reinstated retroactively. However, if you violate these terms after such +reinstatement, any additional violation of these terms will cause your licenses +to terminate automatically and permanently. + +## No Liability + +*As far as the law allows, the software comes as is, without any warranty or +condition, and the licensor will not be liable to you for any damages arising +out of these terms or the use or nature of the software, under any kind of +legal claim.* + +## Definitions + +The **licensor** is the entity offering these terms, and the **software** is the +software the licensor makes available under these terms, including any portion +of it. + +**you** refers to the individual or entity agreeing to these terms. + +**your company** is any legal entity, sole proprietorship, or other kind of +organization that you work for, plus all organizations that have control over, +are under the control of, or are under common control with that +organization. **control** means ownership of substantially all the assets of an +entity, or the power to direct its management and policies by vote, contract, or +otherwise. Control can be direct or indirect. + +**your licenses** are all the licenses granted to you for the software under +these terms. + +**use** means anything you do with the software requiring one of your licenses. + +**trademark** means trademarks, service marks, and similar rights. diff --git a/README.md b/README.md index 9aa80e2..a95d543 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,122 @@ # Mizan -An **Application Framework Interface (AFI)** — one decorator on a server function, a -typed client generated, invalidation automatic, caching protocol-driven. Any backend, -any frontend, one wire protocol. +Mizan is an Application Framework Interface (AFI). A single `@client` decorator on a +server function generates a typed frontend client; cache invalidation and caching are +handled by the protocol. -For the wire protocol, package layout, and codegen state, see [`CLAUDE.md`](CLAUDE.md). -Architecture deep-dives live in [`docs/`](docs/). Open work is tracked in -[`ROADMAP.md`](ROADMAP.md) and [`ISSUES.md`](ISSUES.md). +```python +from mizan import client, ReactContext ---- +UserContext = ReactContext('user') -## Backend Adapter Parity +# Context function — bundled into GET /api/mizan/ctx/user/ +@client(context=UserContext) +def user_profile(request, user_id: int) -> UserShape: + return UserShape.query(lambda qs: qs.filter(pk=user_id))[0] -**Django is the maximal rubric** — it implements the full AFI surface. Every other -adapter is measured against it. A cell is marked supported only when *that adapter* -wires the capability into its own dispatch surface (not merely that a shared core -primitive exists). +# Mutation — invalidation scoped automatically by matching param name +@client(affects=UserContext) +def update_profile(request, user_id: int, name: str) -> dict: + ... +``` -Legend: ✅ full · ◑ partial · ❌ absent · — not applicable to this transport +Adapters exist for Django, FastAPI, Rust/Axum, Tauri, and TypeScript. Django is the +reference implementation; per-adapter support is inventoried below. + +> **Status:** Mizan is not production-tested. It passes its own test suites but has not +> been run in a production deployment. Treat it as pre-release. + +## Documentation + +- [`docs/`](docs/) — architecture references: AFI, SSR, cache keying, MWT, PSR vs. Edge +- [`ROADMAP.md`](ROADMAP.md) · [`ISSUES.md`](ISSUES.md) — planned work and known gaps + +## Backend adapters + +Every adapter implements the same AFI wire protocol. The matrix below inventories +support per adapter, grouped to separate protocol guarantees from Django-specific +features (forms, ORM projection, auth providers, SSR). A cell counts as supported only +when that adapter wires the capability into its own dispatch surface, not merely that a +shared core primitive exists. + +Legend: ✅ supported · ◑ partial · ❌ not implemented · — not applicable to this transport + +### Protocol core + +The surface every Mizan adapter implements. | Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript | |---|:---:|:---:|:---:|:---:|:---:| | RPC call dispatch (`{result, invalidate}`) | ✅ | ✅ | ✅ | ✅ ¹ | ✅ | | Named-context bundle fetch | ✅ | ✅ | ✅ | ✅ | ✅ | | Invalidation — JSON body | ✅ | ✅ | ✅ | ✅ | ✅ | -| Invalidation — `X-Mizan-Invalidate` header | ✅ | ❌ | ❌ | — ¹ | ✅ | | Invalidation auto-scoping (three-tier) | ✅ | ✅ | ✅ | ✅ | ✅ | +| Function discovery / registration | ✅ | ✅ | ✅ | ✅ | ✅ | +| Codegen IR export (KDL) | ✅ | ✅ | ✅ ⁶ | ✅ ⁶ | — ⁸ | + +### Edge, cache & enforcement + +Protocol transports and guarantees co-equal with the body channel in the spec. + +| Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript | +|---|:---:|:---:|:---:|:---:|:---:| +| Invalidation — `X-Mizan-Invalidate` header | ✅ | ❌ | ❌ | — ¹ | ✅ | +| Auth-guard enforcement (`auth=…` rejects) | ✅ | ✅ | ❌ ⁵ | ◑ ⁵ | ❌ | | Origin-side HMAC cache | ✅ | ❌ | ❌ | ❌ | ✅ | -| WebSocket channels | ✅ | ❌ | ◑ ² | ❌ | ❌ | +| Edge manifest export | ✅ | ❌ | ❌ | — | ✅ | +| PSR (`render_strategy` in manifest) | ✅ | ❌ | ❌ | — | ✅ | +| Session / CSRF init endpoint | ✅ | ◑ ⁷ | ◑ ⁷ | — | ❌ | + +> **Caveat:** Rust/Axum and Tauri accept `auth=` on a function but do not yet enforce +> it — do not rely on `auth=` for access control on those adapters. + +### Stack extensions (Django) + +Django ecosystem features Mizan wraps. Other adapters provide these only where the +target stack calls for them. + +| Capability | Django | FastAPI | Rust / Axum | Tauri | TypeScript | +|---|:---:|:---:|:---:|:---:|:---:| +| WebSocket channels (declared transport) | ✅ | ❌ | ◑ ² | ❌ | ❌ | | Forms (schema / validate / submit) | ✅ | ❌ | ◑ ³ | ❌ | ❌ | | Formsets | ✅ | ❌ | ❌ | ❌ | ❌ | | API shapes (ORM query projection) ⁴ | ✅ | — | — | — | — | -| Auth guards (`auth=True/'staff'/'superuser'/callable`) | ✅ | ✅ | ❌ | ◑ ⁵ | ❌ | | JWT auth (access / refresh, session validation) | ✅ | ❌ | ❌ | ❌ | ❌ | | MWT (edge identity token) | ✅ | ❌ | ❌ | — | ❌ | | SSR bridge | ✅ | ❌ | ❌ | — | ❌ | -| PSR (`render_strategy` in manifest) | ✅ | ❌ | ❌ | — | ✅ | -| Edge manifest export | ✅ | ❌ | ❌ | — | ✅ | -| Codegen IR export (KDL) | ✅ | ✅ | ✅ ⁶ | ✅ ⁶ | ❌ | -| Session / CSRF init endpoint | ✅ | ◑ ⁷ | ◑ ⁷ | — | ❌ | -| Function discovery / registration | ✅ | ✅ | ✅ | ✅ | ✅ | | Auth-provider integration (allauth) | ✅ | ❌ | ❌ | ❌ | ❌ | **Notes** 1. Tauri's transport is Tauri IPC (a single `#[tauri::command]` envelope), not HTTP. - Invalidation rides in the JSON response body; there is no header channel, so the - header row is N/A. + Invalidation rides in the JSON response body; there is no header channel. 2. Rust/Axum declares `Transport::Websocket` in the IR/macro but routes no Axum WebSocket handler yet. -3. Rust/Axum carries `is_form`/`form_role` trait stubs but no validate/submit - endpoint. +3. Rust/Axum carries `is_form`/`form_role` trait stubs but no validate/submit endpoint. 4. "API shapes" is Django's django-readers queryset projection — ORM-coupled. Every - adapter carries typed input/output through the KDL IR; the *projection primitive* + adapter carries typed input/output through the KDL IR; the projection primitive itself is Django-only. -5. Tauri's `FunctionSpec` carries `auth`/`private` fields, but the dispatch path does - not enforce them. -6. Rust/Axum and Tauri *are* the IR authority via the `#[mizan::client]` macro + - linkme registry; the codegen links the crate directly (`build_ir()` / the - `export-ir` bin) rather than fetching over HTTP. +5. Tauri's `FunctionSpec` carries `auth`/`private` fields; the dispatch path does not + enforce them. Rust/Axum has no enforcement either. +6. Rust/Axum and Tauri are the IR authority via the `#[mizan::client]` macro + linkme + registry; the codegen links the crate directly (`build_ir()` / the `export-ir` bin) + rather than fetching over HTTP. 7. FastAPI and Rust/Axum expose `GET /session/` returning a null CSRF token for wire - parity; real CSRF is Django-only. + parity; CSRF is Django-only. +8. TypeScript is an edge/protocol-reference adapter (HMAC cache, manifest, PSR), not a + codegen source — it demonstrates the cache + invalidation protocol is + language-agnostic. -### Reading the columns +## Conformance -- **FastAPI** — the AFI-common HTTP subset: dispatch, contexts, body invalidation, - auth guards, IR export. Channels / forms / SSR / cache are deliberately delegated to - native FastAPI equivalents. -- **Rust / Axum** — core dispatch + context bundling + compile-time registry, and the - *server-side* IR authority. No HTTP-layer cache, auth enforcement, or edge surface - yet. -- **Tauri** — the same Rust core over IPC for desktop/mobile. Edge, SSR, MWT, and CSRF - are structurally inapplicable to a local app. -- **TypeScript** — the edge/protocol reference: HMAC cache, edge manifest, and PSR - strategy, proving the cache + invalidation protocol is language-agnostic. It is not a - codegen IR source. +Adapter parity is gated by the AFI conformance suite in [`tests/afi/`](tests/afi/). It +currently asserts **IR-shape parity** — the same fixture through Django, FastAPI, and +the Rust adapter emits byte-identical KDL (`test_codegen_parity.py`). Per-capability +runtime assertions (header transport, `auth=` enforcement, cache behavior) are planned. -### Keeping this honest +## License -This table is a **snapshot**, and a hand-maintained snapshot drifts the moment an -adapter gains or loses a target. The enforcing layer is the AFI conformance suite at -[`tests/afi/`](tests/afi/), which today gates **IR-shape parity** — the same fixture -through Django, FastAPI, and the Rust adapter must emit byte-identical KDL -(`test_codegen_parity.py`). It does **not yet** assert *runtime capability* parity -(e.g. "every adapter that claims the header transport actually emits -`X-Mizan-Invalidate`," "every adapter that claims `auth=` actually rejects an -unauthorized call"). Extending `tests/afi/` with per-capability assertions — one row of -this table per asserted behavior — is what turns the table from documentation into a -red-on-regression contract. +Mizan is licensed under the [Elastic License 2.0](LICENSE) (SPDX: `Elastic-2.0`). You +may use, copy, modify, and distribute it freely, including in commercial products you +build on top of it. You may **not** provide Mizan to third parties as a hosted or +managed service that exposes a substantial set of its features. diff --git a/backends/mizan-django/pyproject.toml b/backends/mizan-django/pyproject.toml index e48d80a..a2f1ea4 100644 --- a/backends/mizan-django/pyproject.toml +++ b/backends/mizan-django/pyproject.toml @@ -1,6 +1,7 @@ [project] name = "mizan" version = "1.0.1" +license = "Elastic-2.0" description = "Django + React server functions framework" readme = "README.md" requires-python = ">=3.10" diff --git a/backends/mizan-fastapi/pyproject.toml b/backends/mizan-fastapi/pyproject.toml index d7b5a9d..029d485 100644 --- a/backends/mizan-fastapi/pyproject.toml +++ b/backends/mizan-fastapi/pyproject.toml @@ -1,6 +1,7 @@ [project] name = "mizan-fastapi" version = "0.1.0" +license = "Elastic-2.0" description = "Mizan FastAPI backend adapter — HTTP RPC dispatch + context bundling, built on mizan-core." requires-python = ">=3.10" dependencies = [ diff --git a/backends/mizan-rust-axum/Cargo.toml b/backends/mizan-rust-axum/Cargo.toml index a54be20..62b89ad 100644 --- a/backends/mizan-rust-axum/Cargo.toml +++ b/backends/mizan-rust-axum/Cargo.toml @@ -3,7 +3,7 @@ name = "mizan-axum" version = "0.1.0" edition = "2021" description = "axum HTTP adapter for Mizan — typed RPC dispatch + context-bundle fetch on top of mizan-core's compile-time function registry." -license = "MIT" +license = "Elastic-2.0" [dependencies] mizan-core = { path = "../../cores/mizan-rust" } diff --git a/backends/mizan-tauri/Cargo.toml b/backends/mizan-tauri/Cargo.toml index 33af8a0..9278ece 100644 --- a/backends/mizan-tauri/Cargo.toml +++ b/backends/mizan-tauri/Cargo.toml @@ -3,7 +3,7 @@ name = "mizan-tauri" version = "0.1.0" edition = "2021" description = "Tauri backend adapter for Mizan — typed RPC dispatch over Tauri's IPC. Single `mizan_invoke` command routes through mizan-core's compile-time function registry." -license = "MIT" +license = "Elastic-2.0" [dependencies] mizan-core = { path = "../../cores/mizan-rust" } diff --git a/backends/mizan-ts/package.json b/backends/mizan-ts/package.json index ea368ce..59bac8c 100644 --- a/backends/mizan-ts/package.json +++ b/backends/mizan-ts/package.json @@ -10,5 +10,5 @@ "devDependencies": { "bun-types": "latest" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/cores/mizan-python/pyproject.toml b/cores/mizan-python/pyproject.toml index 72b8786..5259805 100644 --- a/cores/mizan-python/pyproject.toml +++ b/cores/mizan-python/pyproject.toml @@ -1,6 +1,7 @@ [project] name = "mizan-core" version = "0.1.0" +license = "Elastic-2.0" description = "Mizan Python core — HMAC cache keys, MWT identity. Framework-agnostic primitives shared by every Python backend adapter." requires-python = ">=3.10" dependencies = [ diff --git a/cores/mizan-rust-macros/Cargo.toml b/cores/mizan-rust-macros/Cargo.toml index a1f6580..9e91f61 100644 --- a/cores/mizan-rust-macros/Cargo.toml +++ b/cores/mizan-rust-macros/Cargo.toml @@ -3,7 +3,7 @@ name = "mizan-macros" version = "0.1.0" edition = "2021" description = "Proc macros for mizan-core: #[derive(Mizan)], #[mizan::context], #[mizan(...)]. Emits MizanType / ContextMarker / FunctionSpec impls plus linkme registrations." -license = "MIT" +license = "Elastic-2.0" [lib] proc-macro = true diff --git a/cores/mizan-rust/Cargo.toml b/cores/mizan-rust/Cargo.toml index dda843e..9ee85bb 100644 --- a/cores/mizan-rust/Cargo.toml +++ b/cores/mizan-rust/Cargo.toml @@ -3,7 +3,7 @@ name = "mizan-core" version = "0.1.0" edition = "2021" description = "Mizan server-side IR substrate — types, traits, KDL emitter, registry. Rust analog of cores/mizan-python/src/mizan_core/." -license = "MIT" +license = "Elastic-2.0" [dependencies] linkme = "0.3" diff --git a/frontends/mizan-base/package.json b/frontends/mizan-base/package.json index 3eb7a05..7be8685 100644 --- a/frontends/mizan-base/package.json +++ b/frontends/mizan-base/package.json @@ -7,5 +7,5 @@ "exports": { ".": "./src/index.ts" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/frontends/mizan-react/package.json b/frontends/mizan-react/package.json index f4b41e9..f51fe9c 100644 --- a/frontends/mizan-react/package.json +++ b/frontends/mizan-react/package.json @@ -1,6 +1,7 @@ { "name": "@rythazhur/mizan", "version": "0.1.1", + "license": "Elastic-2.0", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/frontends/mizan-rust/Cargo.toml b/frontends/mizan-rust/Cargo.toml index de9a11d..00c324b 100644 --- a/frontends/mizan-rust/Cargo.toml +++ b/frontends/mizan-rust/Cargo.toml @@ -3,7 +3,7 @@ name = "mizan-rust" version = "0.1.0" edition = "2021" description = "Mizan client kernel — Rust port of @mizan/base. Context registry, fetch/call, merge, invalidation, error envelope parsing. Same wire as the TS / Vue / Svelte clients." -license = "MIT" +license = "Elastic-2.0" [features] default = [] diff --git a/frontends/mizan-svelte/package.json b/frontends/mizan-svelte/package.json index 1f1e92f..a5a96cd 100644 --- a/frontends/mizan-svelte/package.json +++ b/frontends/mizan-svelte/package.json @@ -7,5 +7,5 @@ "svelte": ">=4", "@mizan/base": ">=0.1.0" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/frontends/mizan-tauri-transport/package.json b/frontends/mizan-tauri-transport/package.json index 58c736c..0980a34 100644 --- a/frontends/mizan-tauri-transport/package.json +++ b/frontends/mizan-tauri-transport/package.json @@ -11,5 +11,5 @@ "@mizan/base": "*", "@tauri-apps/api": "^2" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/frontends/mizan-vue/package.json b/frontends/mizan-vue/package.json index 8102e1e..75145af 100644 --- a/frontends/mizan-vue/package.json +++ b/frontends/mizan-vue/package.json @@ -7,5 +7,5 @@ "vue": ">=3", "@mizan/base": ">=0.1.0" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/frontends/mizan-webview-channels/package.json b/frontends/mizan-webview-channels/package.json index b8ac50d..ddd9a6c 100644 --- a/frontends/mizan-webview-channels/package.json +++ b/frontends/mizan-webview-channels/package.json @@ -7,5 +7,5 @@ "exports": { ".": "./src/index.ts" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/frontends/mizan-webview-transport/package.json b/frontends/mizan-webview-transport/package.json index 1de5fe8..5121ff1 100644 --- a/frontends/mizan-webview-transport/package.json +++ b/frontends/mizan-webview-transport/package.json @@ -10,5 +10,5 @@ "peerDependencies": { "@mizan/base": "*" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/protocol/mizan-codegen/Cargo.toml b/protocol/mizan-codegen/Cargo.toml index 686b644..c5c1519 100644 --- a/protocol/mizan-codegen/Cargo.toml +++ b/protocol/mizan-codegen/Cargo.toml @@ -3,7 +3,7 @@ name = "mizan-codegen" version = "0.1.0" edition = "2021" description = "Mizan codegen substrate — consumes Mizan IR; emits typed clients for React/Vue/Svelte/Rust/Python." -license = "MIT" +license = "Elastic-2.0" [[bin]] name = "mizan-generate" diff --git a/protocol/mizan-generate/package.json b/protocol/mizan-generate/package.json index 8806f46..ae39cbd 100644 --- a/protocol/mizan-generate/package.json +++ b/protocol/mizan-generate/package.json @@ -6,5 +6,5 @@ "bin": { "mizan-generate": "./bin/launcher.mjs" }, - "license": "MIT" + "license": "Elastic-2.0" } diff --git a/workers/mizan-ssr/package.json b/workers/mizan-ssr/package.json index 174980d..48c01d2 100644 --- a/workers/mizan-ssr/package.json +++ b/workers/mizan-ssr/package.json @@ -16,5 +16,5 @@ "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0" }, - "license": "MIT" + "license": "Elastic-2.0" }