Skip to content
Merged

Dev #26

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
db39b59
Prevent napi build from overwriting Node index.js.
ehs22n Sep 1, 2026
a79bbfc
Strengthen gitignore and stop tracking build artifacts.
ehs22n Sep 1, 2026
007c612
Vendor Swagger UI assets for offline docs.
ehs22n Sep 1, 2026
4d4960d
Add Tera 2 template engine with FusionBaseTemplate across bindings.
ehs22n Sep 1, 2026
3304460
Add local dev install scripts and documentation.
ehs22n Sep 1, 2026
6f76d13
Add dual-mode FusionBaseTemplate GET via content negotiation.
ehs22n Sep 1, 2026
e442c44
Split CI and publish workflows for dev/main branch flow.
ehs22n Sep 1, 2026
437c3be
Fix Swagger version navbar after vendored Swagger UI 5.x.
ehs22n Sep 1, 2026
31b863f
Merge pull request #6 from cipherunits/feature/ci-cd-main-dev
ehs22n Sep 1, 2026
bd5fc9e
Merge pull request #7 from cipherunits/feature/swagger-version-navbar
ehs22n Sep 1, 2026
73c9687
Add optional auto-reload on source changes for all bindings.
ehs22n Sep 2, 2026
574b86a
Make all middleware opt-in; disable wire fingerprint by default.
ehs22n Sep 2, 2026
25fd9ca
chore(middleware): fix middelwares
ehs22n Sep 2, 2026
e146bb7
Merge pull request #8 from cipherunits/feature/middleware-opt-in
ehs22n Sep 2, 2026
c1464ff
Merge pull request #9 from cipherunits/feature/dev-reload
ehs22n Sep 2, 2026
4379cf1
Exclude FusionBaseTemplate routes from Swagger OpenAPI specs.
ehs22n Sep 2, 2026
1e774eb
Merge pull request #10 from cipherunits/feature/exclude-template-rout…
ehs22n Sep 2, 2026
c4c7c96
Replace route roles with custom permissions and Swagger lock metadata.
ehs22n Sep 2, 2026
b50f836
Add centralized tests/ layout and move Python suite out of the package.
ehs22n Sep 2, 2026
b7421cc
Add agent skills, coding standards, and fusion-cli documentation.
ehs22n Sep 3, 2026
fab0478
Add Node and C# unit tests to the centralized harness.
ehs22n Sep 3, 2026
4955ce1
Merge pull request #11 from cipherunits/feature/agent-skills
ehs22n Sep 3, 2026
fa7ef43
Merge pull request #13 from cipherunits/feature/unit-test
ehs22n Sep 3, 2026
b5aa585
Merge origin/dev into feature/route-permissions.
ehs22n Sep 3, 2026
3549505
Merge pull request #14 from cipherunits/feature/route-permissions
ehs22n Sep 3, 2026
4709667
Add WhiteNoise-style static_files middleware across bindings.
ehs22n Sep 3, 2026
009b830
Mount static_files as real routes on listen.
ehs22n Sep 3, 2026
3ea8ab3
Support async template context across Python, Node, and C#.
ehs22n Sep 3, 2026
7f85cbb
Merge pull request #15 from cipherunits/feature/static-files-middleware
ehs22n Sep 3, 2026
f2fe995
Merge pull request #16 from cipherunits/feature/async-template-context
ehs22n Sep 3, 2026
728157c
feat(ui): add default ui component
ehs22n Sep 3, 2026
664f53e
Merge pull request #17 from cipherunits/feature/ui-welcome-components
ehs22n Sep 3, 2026
38ae45a
feat(cache): add moka cache and standard api
ehs22n Sep 4, 2026
2e60eb3
Merge pull request #18 from cipherunits/feature/cache-moka
ehs22n Sep 4, 2026
3a27927
feat(monitoring): add default cache monitorin panel
ehs22n Sep 4, 2026
2413861
feat(tasks): add process-wide Tokio background tasks across bindings
ehs22n Sep 4, 2026
0ef20a8
Merge pull request #20 from cipherunits/feature/background-tasks
ehs22n Sep 4, 2026
1b66b3f
feat(monitor): list tasks in an independent Fusion monitor panel
ehs22n Sep 4, 2026
3d6a2d1
Merge pull request #21 from cipherunits/feature/tasks-monitor
ehs22n Sep 4, 2026
5891429
feat(node): Nest-style fusion scripts and richer package metadata
MohammadTahaBatoomi Sep 5, 2026
6934a5c
Merge pull request #22 from cipherunits/feature/fusion-node-package-json
ehs22n Sep 5, 2026
f1dc937
feat(templates): add shared UI components gallery with theme tokens
MohammadTahaBatoomi Sep 5, 2026
be5ee19
Merge pull request #23 from cipherunits/feature/components-share
ehs22n Sep 5, 2026
62dee33
feat(template): add spa style to template
ehs22n Sep 8, 2026
6dc4342
release v2.0.0
ehs22n Sep 8, 2026
69febd4
Merge pull request #24 from cipherunits/feature/spa
ehs22n Sep 8, 2026
1776f61
Merge pull request #25 from cipherunits/stable/2
ehs22n Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
24 changes: 18 additions & 6 deletions .agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,30 @@ Project-local skills for Cursor agents working on this repository.

```
.agents/skills/<skill-name>/SKILL.md
.cursor/rules/*.mdc # always-on / scoped project rules
```

Each skill teaches the agent domain-specific workflows for Fusion (Rust core + Python / Node / C# bindings).
Each skill teaches domain-specific workflows for Fusion (Rust core + Python / Node / C# bindings) and the companion `fusion` CLI.

## Available skills

| Skill | Use when |
|-------|----------|
| `fusion-architecture` | Understanding repo layout, binding layers, where logic belongs |
| `fusion-bindings-parity` | Changing behavior that must stay aligned across Python, Node, C# |
| `fusion-http-routes` | Routes, `@http_get` / `[HttpGet]`, `[module]`, `[action]`, Swagger |
| `fusion-architecture` | Repo layout, binding layers, where logic belongs |
| `fusion-bindings-parity` | Feature must land in Python **and** Node **and** C# |
| `fusion-coding-standards` | Comments, tests preference, git staging, skill/doc hygiene |
| `fusion-cli` | `fusion init` / commands / scaffold tree / CLI ↔ framework |
| `fusion-http-routes` | Routes, `http_get` / `[HttpGet]`, `[module]`, `[action]`, Swagger |
| `fusion-release` | Version bumps, manifests, publish prep |
| `fusion-testing` | Running checks and binding-specific tests |
| `fusion-testing` | Running checks; investigating failed tests |
| `fusion-cache` | Application cache (moka default; Redis later) |
| `fusion-background-tasks` | Tokio spawn / cancel / status / snapshot |
| `fusion-template-forms` | Template `form` / `ok` / `fail` + SPA `data-fusion-form` |

Skills are loaded when the task matches the skill description (or when you name the skill explicitly).
## Always-on rules

`.cursor/rules/fusion-engineering.mdc` applies every session: parity across bindings, **examples in all three languages for new features**, function comments, prefer tests, never `git add .`, investigate failures, update skills when needed.

## Hygiene

When you add a new concept agents must remember, either extend an existing skill or add `.agents/skills/<name>/SKILL.md` and a row in this table.
28 changes: 19 additions & 9 deletions .agents/skills/fusion-architecture/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
---
name: fusion-architecture
description: >-
Explains Fusion Framework repository layout, crate boundaries, and where
new logic belongs (fusion-core vs Python/Node/C# bindings). Use when
navigating the codebase, adding features, or deciding which layer to change.
Explains Fusion Framework repository layout, crate boundaries, where new
logic belongs (fusion-core vs Python/Node/C# bindings), tests layout, and
relationship to the fusion CLI. Use when navigating the codebase, adding
features, or deciding which layer to change.
---

# Fusion Architecture
Expand All @@ -12,18 +13,24 @@ description: >-

| Path | Role |
|------|------|
| `crates/fusion-core/` | Shared Rust: naming, route tokens, HTTP conventions |
| `crates/fusion-core/` | Shared Rust: naming, route tokens, HTTP conventions, settings helpers |
| `crates/fusion-py/` | Python binding (PyO3) + `python/fusion_framework/` package |
| `crates/fusion-node/` | Node binding (`index.js`, N-API) |
| `bindings/csharp/FusionFramework/` | C# binding (source of truth for NuGet layout) |
| `crates/fusion-ffi/` | C ABI for the C# binding |
| `bindings/csharp/FusionFramework/` | C# binding (NuGet layout source of truth) |
| `tests/` | Executable tests (Python / Node / C#) — not inside installable packages |
| `examples/` | Runnable samples per binding |
| `scripts/` | Release tooling (`set-version.sh`) |
| `scripts/` | Dev install, version bumps (`set-version.sh`) |
| `.agents/skills/` | Agent skills for this repo |

**Related external repo:** [fusion-tool](https://github.com/cipherunits/fusion-tool) — `fusion` CLI that scaffolds apps. See `fusion-cli` skill.

## Layering rules

1. **Put shared semantics in `fusion-core`** — route token resolution (`[module]`, `[action]`), path joining, handler naming. Bindings should call Rust helpers via FFI where possible.
2. **Bindings mirror behavior** — Python decorators, Node functions, C# attributes must produce the same mount paths and OpenAPI shapes.
3. **Do not duplicate business logic in three languages** — only binding-specific glue (decorators, reflection, module registration).
4. **Tests live under `tests/`** — do not add `test_*.py` inside `fusion_framework/` package sources.

## Key entry points

Expand All @@ -33,6 +40,9 @@ description: >-

## When adding a feature

1. Identify if it is cross-binding (yes → start in `fusion-core`).
2. Implement mount + OpenAPI in all three bindings in one PR when possible.
3. Add or extend an example under `examples/`.
1. Identify if it is cross-binding (yes → start in `fusion-core` when semantics are shared).
2. Implement in **Python, Node, and C#** in one change set (see `fusion-bindings-parity`).
3. Add tests under `tests/` (preferred) and/or Rust unit tests.
4. Add **usage examples in all three languages** under `examples/` (`<feature>.py` / `.mjs` / `.cs`) so the API shape is visible.
5. If scaffolds or env JSON contracts change, update the `fusion-cli` skill and consider fusion-tool templates.
6. Comment new functions; document dense logic (see `fusion-coding-standards`).
63 changes: 63 additions & 0 deletions .agents/skills/fusion-background-tasks/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: fusion-background-tasks
description: >-
Documents Fusion process-wide Tokio background tasks (spawn, spawn_after,
cancel, status, snapshot) across Python, Node, and C#. Use when scheduling
fire-and-forget or delayed work off the request path, or when inspecting tasks
via the Fusion monitor panel.
---

# Fusion background tasks

In-process jobs on a dedicated **Tokio** multi-thread runtime in `fusion-core`.
Not a durable queue (no Redis/persistence).

## API

| Python | Node | C# |
|--------|------|-----|
| `tasks.spawn(fn)` | `tasks.spawn(fn)` | `BackgroundTasks.Spawn(action)` |
| `tasks.spawn_after(ms, fn)` | `tasks.spawnAfter(ms, fn)` | `BackgroundTasks.SpawnAfter(ms, action)` |
| `tasks.cancel(id)` | `tasks.cancel(id)` | `BackgroundTasks.Cancel(id)` |
| `tasks.status(id)` | `tasks.status(id)` | `BackgroundTasks.Status(id)` |
| `tasks.snapshot()` | `tasks.snapshot()` | `BackgroundTasks.Snapshot()` |
| `tasks.reset()` | `tasks.reset()` | `BackgroundTasks.Reset()` |

Status values: `pending` | `running` | `done` | `cancelled` | `failed`.

`snapshot()` returns `{ task_count, active_count, tasks: [{ id, status, delay_ms, created_at_ms }] }`.
Terminal tasks are pruned (keep last 100) so the registry cannot grow forever.

### Pass a callable

```python
# Correct — defer the call:
tasks.spawn(lambda: test_task(name))

# Wrong — calls test_task immediately and passes None:
# tasks.spawn(test_task(name)) # TypeError: callback must be callable
```

## Fusion monitor

When `monitor.enabled` is true, the Fusion monitor HTML and `{path}/json` embed the
task list under `tasks` / a **Background tasks** card. Settings live under top-level
`monitor.*` (not under `cache.monitor`).

## Notes

- Callbacks may run on Tokio worker threads (Python holds the GIL only for the call).
- Tasks are process-wide and outlive HTTP requests.
- Cancel before run aborts the delay; host userdata is freed (C# GCHandle).

## Examples

`examples/background_tasks.py` / `.mjs` / `.cs`
`examples/monitor.*` (spawns sample tasks for the panel)

## Implementation

- Core: `crates/fusion-core/src/tasks.rs`
- Python: `fusion_framework.tasks`
- Node: `tasks` export
- C#: `BackgroundTasks` + FFI
42 changes: 36 additions & 6 deletions .agents/skills/fusion-bindings-parity/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,39 @@
name: fusion-bindings-parity
description: >-
Keeps Python, Node, and C# Fusion bindings aligned when changing APIs, routes,
Swagger, or middleware. Use when editing more than one binding or adding
cross-language behavior.
Swagger, middleware, or permissions. Use when editing more than one binding
or when the user asks to add a feature (always implement all three languages
unless they limit scope).
---

# Bindings Parity

## Hard rule

If the user says “add X” (permissions, middleware, route option, Swagger behavior, settings key, etc.) and X is framework surface area, implement it for:

1. **Python**
2. **Node**
3. **C#**

in the **same** change set unless they explicitly say “only Python” (or only one binding).

Do not leave one language behind “for later” without saying so and getting confirmation.

## Checklist (every cross-binding change)

- [ ] `fusion-core` updated if semantics are shared
- [ ] Python: `fusion_framework/` + `crates/fusion-py/src/api_types.rs`
- [ ] Node: `crates/fusion-node/index.js`
- [ ] Python: `fusion_framework/` + `crates/fusion-py/src/api_types.rs` as needed
- [ ] Node: `crates/fusion-node/index.js` (+ `index.d.ts` if public types change)
- [ ] C#: `bindings/csharp/FusionFramework/*.cs`
- [ ] Example snippet in `examples/` (at least one runnable file + others documented)
- [ ] Tests under `tests/python/`, `tests/node/`, and/or `tests/csharp/` when behavior is testable
- [ ] **Examples in all three languages** under `examples/` (`<feature>.py`, `<feature>.mjs`, `<feature>.cs`) showing how to use the new API
- [ ] README in C# binding updated if public API changed
- [ ] Skills/docs updated if agents need new knowledge (`fusion-cli`, `fusion-http-routes`, …)

## Examples rule

New public surface → show usage in **Python + Node + C#**. Prefer the same basename for the trio (see `custom_http_routes.*`, `pagination.*`). Examples should be short and runnable enough to see the API shape, not full apps.

## Parity matrix

Expand All @@ -24,8 +43,16 @@ description: >-
| Module route | `@route("/api/[module]")` | `route('/api/[module]')(Cls)` | `[Route("/api/[module]")]` |
| Convention HTTP | `def get(self)` | `get()` method | `Get()` method |
| Custom HTTP | `@http_get("path/[action]")` | `httpGet('path/[action]')(proto.method)` | `[HttpGet("path/[action]")]` |
| Middleware | `middleware.py` factories | factories in `index.js` | `Middleware.cs` |
| Static files | `static_files()` | `staticFiles()` | `Middleware.StaticFiles()` |
| Cache | `fusion_framework.cache` (moka) | `cache` export | `Cache` |
| Fusion monitor | `monitor.mount_monitor` | `mountMonitor` | `FusionMonitor` |
| Background tasks | `fusion_framework.tasks` (+ snapshot; in monitor) | `tasks` export | `BackgroundTasks` |
| Permissions | `permissions=` / `require_permissions` | `permissions` / `requirePermissions` | `PermissionTypes` / `RequirePermissions` |
| OpenAPI / Swagger | `app.py` + `api_types.rs` | `buildOpenApi` in `index.js` | `Swagger.cs` |
| Version navbar | per-version OpenAPI routes | same | same |
| Template routes | omit from OpenAPI | omit | omit |
| Template forms | `form` / `ok` / `fail` + `data-fusion-form` | same | `Form` / `Ok` / `Fail` |

## Verification commands

Expand All @@ -34,10 +61,13 @@ cargo test -p fusion-core naming
cargo check -p fusion-py
node --check crates/fusion-node/index.js
dotnet build bindings/csharp/FusionFramework/FusionFramework.csproj
python -m pytest crates/fusion-py/python/fusion_framework/test_http_route.py -q
./tests/scripts/run-python.sh -q
./tests/scripts/run-node.sh
./tests/scripts/run-csharp.sh -q
```

## Style

- Match existing naming in each language (snake_case Python, camelCase Node helpers, PascalCase C#).
- Prefer minimal diffs; do not refactor unrelated binding code.
- Comment new exported helpers (see `fusion-coding-standards`).
118 changes: 118 additions & 0 deletions .agents/skills/fusion-cache/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
name: fusion-cache
description: >-
Documents Fusion application cache (default moka driver, Redis reserved),
settings under fusion.<env>.json, sync/async APIs, TTL rules, the optional
Fusion monitor panel (cache + tasks), and clear across Python, Node, and C#.
Use when adding cache usage or changing drivers.
---

# Fusion cache

Process-wide cache shared by Python / Node / C# via `fusion-core`.

## Default driver

**moka** (in-process Rust cache). Settings alias `mako` is accepted and maps to `moka`.

Redis (`cache.driver = "redis"`) is reserved in settings but **not implemented yet**.

## Settings (`fusion.dev.json` / stage / prod)

```json
"cache": {
"driver": "moka",
"max_capacity": 10000,
"default_ttl": null,
"max_events": 50,
"connection_string": null,
"host": "127.0.0.1",
"port": 6379,
"username": null,
"password": null,
"db": 0
},
"monitor": {
"enabled": true,
"path": "/__fusion/monitor"
}
```

| Key | Purpose |
|-----|---------|
| `driver` | `moka` (default) or future `redis` |
| `max_capacity` | moka max entries |
| `default_ttl` | seconds, or **`null` = no expiry** unless code passes `ttl=` |
| `max_events` | Ring-buffer size for recent set/delete/clear events (legacy: `cache.monitor.max_events`) |
| `connection_string` / `host` / `port` / `username` / `password` / `db` | Redis connection (future) |
| `monitor.enabled` | Mount HTML + JSON monitor routes (dev scaffold: `true`; stage/prod: `false`) |
| `monitor.path` | UI path; JSON at `{path}/json` (default `/__fusion/monitor`) |

When `monitor.enabled` is **false**, bindings must **not** register the monitor endpoints (security: disable routes, not only UI). Legacy `cache.monitor.enabled` / `cache.monitor.path` still work.

The HTML panel and `{path}/json` include **cache entries**, **recent cache events**, and **background tasks**.

### TTL rules

1. `cache.set("k", value, ttl=200)` → expires in 200 seconds (always wins).
2. `cache.set("k", value)` with `default_ttl: null` → **forever** (until delete/clear).
3. `cache.set("k", value)` with `default_ttl: 3600` → expires in 3600 seconds.

Same rules apply to `get_or_set` / `delete_or_set` / `exists_or_set` and their async variants.

## Sync API

| Python | Node | C# |
|--------|------|-----|
| `cache.set(..., ttl=?)` | `cache.set(..., ttl?)` | `Cache.Set(..., ttlSeconds?)` |
| `cache.get` | `cache.get` | `Cache.Get` |
| `cache.delete` | `cache.delete` | `Cache.Delete` |
| `cache.exists` | `cache.exists` | `Cache.Exists` |
| `cache.get_or_set` | `cache.getOrSet` | `Cache.GetOrSet` |
| `cache.delete_or_set` | `cache.deleteOrSet` | `Cache.DeleteOrSet` |
| `cache.exists_or_set` | `cache.existsOrSet` | `Cache.ExistsOrSet` |
| `cache.clear` | `cache.clear` | `Cache.Clear` |
| `cache.snapshot` | `cache.snapshot` | `Cache.Snapshot` |
| `cache.panel_context` | `cache.panelContext` | `Cache.PanelContext` |

## Async API

| Python | Node | C# |
|--------|------|-----|
| `await cache.aset` | `await cache.aset` | `await Cache.SetAsync` |
| `await cache.aget` | `await cache.aget` | `await Cache.GetAsync` |
| `await cache.adelete` | `await cache.adelete` | `await Cache.DeleteAsync` |
| `await cache.aexists` | `await cache.aexists` | `await Cache.ExistsAsync` |
| `await cache.aget_or_set` | `await cache.agetOrSet` | `await Cache.GetOrSetAsync` |
| `await cache.adelete_or_set` | `await cache.adeleteOrSet` | `await Cache.DeleteOrSetAsync` |
| `await cache.aexists_or_set` | `await cache.aexistsOrSet` | `await Cache.ExistsOrSetAsync` |
| `await cache.aclear` | `await cache.aclear` | `await Cache.ClearAsync` |

Notes:

- **clear** — drop all keys (keeps the cache instance); **reset** (tests) drops the global instance
- **snapshot** — entries + recent events + embedded `tasks` object (monitor JSON)
- **panel_context** — template vars for `fusion/monitor.html` (including task table)

Values must be JSON-compatible.

## Fusion monitor panel

Built-in HTML panel auto-mounted on `listen` / `Mount` when `monitor.enabled` is true:

- `GET {path}` — HTML (auto-refresh every 5s): cache entries, recent events, background tasks
- `GET {path}/json` — raw snapshot (includes top-level `tasks`)

Scaffold (fusion-tool): **dev** `enabled: true`; **stage/prod** `enabled: false`.

## Examples

`examples/cache.py` / `.mjs` / `.cs`
`examples/monitor.py` / `.mjs` / `.cs`

## Implementation

- Core: `crates/fusion-core/src/cache.rs` + `monitor.rs` + `assets/templates/fusion/monitor.html`
- Python: `fusion_framework.cache` + `monitor.mount_monitor`
- Node: `cache` export + `mountMonitor` in `FusionApp.mount`
- C#: `Cache` + `FusionMonitor.Mount` via FFI
Loading
Loading