Added LICENSE
This commit is contained in:
95
LICENSE
Normal file
95
LICENSE
Normal file
@@ -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.
|
||||
142
README.md
142
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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -10,5 +10,5 @@
|
||||
"devDependencies": {
|
||||
"bun-types": "latest"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"svelte": ">=4",
|
||||
"@mizan/base": ">=0.1.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
"@mizan/base": "*",
|
||||
"@tauri-apps/api": "^2"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"vue": ">=3",
|
||||
"@mizan/base": ">=0.1.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -10,5 +10,5 @@
|
||||
"peerDependencies": {
|
||||
"@mizan/base": "*"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
"bin": {
|
||||
"mizan-generate": "./bin/launcher.mjs"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-dom": "^19.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
"license": "Elastic-2.0"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user