@zanzojs/core 0.1.0-beta.0 → 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +54 -86
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,123 +1,91 @@
1
- # Zanzo 🛡️
1
+ # @zanzojs/core
2
2
 
3
- **Librería de autorización ReBAC (Relationship-Based Access Control) isomórfica para TypeScript. Inspirada en Google Zanzibar. 0 dependencias. Type-safe.**
3
+ [![npm version](https://img.shields.io/npm/v/@zanzojs/core.svg?style=flat-square)](https://www.npmjs.com/package/@zanzojs/core)
4
+ [![TypeScript Strict](https://img.shields.io/badge/TypeScript-Strict-blue.svg?style=flat-square)](https://www.typescriptlang.org)
5
+ [![Edge Compatible](https://img.shields.io/badge/edge-compatible-success.svg?style=flat-square)](https://vercel.com/docs/concepts/functions/edge-functions)
4
6
 
5
- Zanzo separa la complejidad del servidor (resolución de grafos relaciones) de la ligereza del cliente (Frontend / Edge), ofreciendo una Developer Experience (DX) inigualable mediante tipado estricto y utilidades de Query Pushdown.
7
+ The core engine of the Zanzo ReBAC ecosystem.
6
8
 
7
- ## 🌟 Características Principales
9
+ This package provides the core algorithms for schema building, relationship graph traversal, and AST compilation. It has **0 dependencies** and is strictly typed.
8
10
 
9
- - 🚀 **Isomórfico y 0 Dependencias:** Funciona nativamente en Node, Edge, Deno, Bun y Browser.
10
- - 🔒 **Type-Safe (Generics Avanzados):** Inferencia estricta de strings y acciones usando TypeScript avanzado. El compilador sabe exactamente qué puedes hacer y dónde.
11
- - 🌳 **Query Pushdown (AST):** No cargues miles de registros en memoria. Genera un Abstract Syntax Tree (AST) diagnóstico para que tu base de datos (Prisma, Mongo, SQL) haga el trabajo pesado de filtrar permisos.
12
- - ⚡ **Frontend Ultraligero:** Evaluación `O(1)` asíncrona o estática en el cliente usando mapeos planos JSON (o Bitmasks).
13
- - 🔄 **Graph Resolution & Relational Tuples:** Permite notación de puntos (ej. `team.member`) analizando tuplas en memoria de manera recursiva sin caer en bucles infinitos (Ciclic Safe).
11
+ ## Features
14
12
 
15
- ## 📦 Instalación
13
+ - **Fluent Schema Builder:** Define your access control policies with auto-completing generics. No string typos.
14
+ - **Isomorphic Engine:** Run the exact same permission checks on your backend server or your Vercel Edge functions.
15
+ - **Client Snapshots:** Compile a user's entire permission graph on the server and export it as a flat `O(1)` JSON dictionary for frontend hydration.
16
+ - **Transitive Expansion:** Safely compute and materialize nested relationship paths at write-time to guarantee read-time performance.
17
+
18
+ ## Installation
16
19
 
17
20
  ```bash
18
- npm install zanzo
21
+ pnpm add @zanzojs/core
19
22
  ```
20
23
 
21
- ## 🛠️ Cómo funciona (El Ciclo de Vida en Código)
22
-
23
- Zanzo se diseña para abarcar todo el ecosistema de tu aplicación, conectando Frontend, Backend y Bases de Datos a través del mismo contrato de tipos.
24
+ ## Usage Guide
24
25
 
25
- ### Paso 1: Define tu esquema (`ZanzoBuilder`)
26
+ ### 1. Defining your Schema
26
27
 
27
- Toda tu política de seguridad está centralizada en un esquema robusto y tipado, que se usará para retro-alimentar todas las comprobaciones a lo largo del stack:
28
+ The core concept of ReBAC is mapping actions to relationships. Use the `ZanzoBuilder` to define your domain entities.
28
29
 
29
30
  ```typescript
30
- import { ZanzoBuilder } from '@zanzojs/core';
31
+ import { ZanzoBuilder, ZanzoEngine } from '@zanzojs/core';
31
32
 
32
- const schema = new ZanzoBuilder()
33
- .entity('User', { actions: [] as const })
34
- .entity('Group', {
35
- actions: [] as const,
36
- relations: { member: 'User' } as const,
37
- })
33
+ export const schema = new ZanzoBuilder()
38
34
  .entity('Document', {
39
- actions: ['read', 'write', 'delete'] as const,
40
- relations: { owner: 'User', creator: 'User', team: 'Group' } as const,
35
+ actions: ['read', 'write'],
36
+ relations: { owner: 'User', viewer: 'User', container: 'Folder' },
41
37
  permissions: {
42
- // Define who can do what with direct relations and dot-notation inheritance
43
- read: ['owner', 'creator', 'team.member'],
38
+ // Users can write if they are the direct owner
44
39
  write: ['owner'],
45
- delete: [] // Admins super-pass this or explicitly disallow
46
- } as const,
40
+ // Users can read if they are a viewer, owner, OR if they have read
41
+ // access to the parent folder.
42
+ read: ['viewer', 'owner', 'container.read'],
43
+ },
44
+ })
45
+ .entity('Folder', {
46
+ actions: ['read'],
47
+ relations: { admin: 'User' },
48
+ permissions: {
49
+ read: ['admin'],
50
+ }
47
51
  })
52
+ .entity('User', { actions: [], relations: {} })
48
53
  .build();
49
- ```
50
-
51
- ### Paso 2: Valida en el Backend (`ZanzoEngine`)
52
54
 
53
- En memoria o evaluando tuplas interceptadas (útil para casos sencillos y endpoints seguros):
54
-
55
- ```typescript
56
- import { ZanzoEngine } from '@zanzojs/core';
57
-
58
- const engine = new ZanzoEngine(schema);
59
-
60
- // Inyecta tuplas desde tu DB (Relation Tuples)
61
- engine.addTuple({ subject: 'User:Ana', relation: 'owner', object: 'Document:123' });
62
- engine.addTuple({ subject: 'User:Carlos', relation: 'member', object: 'Group:Devs' });
63
- engine.addTuple({ subject: 'Group:Devs', relation: 'team', object: 'Document:456' });
64
-
65
- // TS Autocomplete estricto: ¿Puede Ana editar el documento?
66
- engine.can('User:Ana', 'write', 'Document:123'); // true
67
-
68
- // ¿Puede Carlos leer el documento dev a través del grupo?
69
- engine.can('User:Carlos', 'read', 'Document:456'); // true
55
+ export const engine = new ZanzoEngine(schema);
70
56
  ```
71
57
 
72
- ### Paso 3: Consulta a tu Base de Datos (`AST / Query Pushdown`)
58
+ ### 2. Basic In-Memory Evaluation
73
59
 
74
- Si la evaluación requiere una lista de documentos que el usuario *sí* puede ver para hacer una consulta a una BD con medio millón de registros, no cargues memoria. Pídele el `AST` al Engine para delegar el filtro al ORM:
60
+ If you already know the specific tuples (relationships) involved, you can pass them to the engine for an instant, synchronous check.
75
61
 
76
62
  ```typescript
77
- // ¿Qué patrón deben cumplir los registros para que Ana pueda leer un Document?
78
- const queryAst = engine.buildDatabaseQuery('User:Ana', 'read', 'Document');
79
-
80
- /* Result:
81
- {
82
- operator: 'OR',
83
- conditions: [
84
- { type: 'direct', relation: 'owner', targetSubject: 'User:Ana' },
85
- { type: 'direct', relation: 'creator', targetSubject: 'User:Ana' },
86
- { type: 'nested', relation: 'team', nextRelationPath: ['member'], targetSubject: 'User:Ana' }
87
- ]
88
- }
89
- */
90
- ```
63
+ // Register the relationships
64
+ engine.addTuple({ subject: 'User:1', relation: 'viewer', object: 'Document:xyz' });
91
65
 
92
- *(La comunidad puede extender este AST para crear adaptadores directo a Prisma, Drizzle, TypeORM, Mongo, etc.)*
66
+ // Ask the decisive question
67
+ const canRead = engine.can('User:1', 'read', 'Document:xyz');
68
+ console.log(canRead); // true
69
+ ```
93
70
 
94
- ### Paso 4: Envía al Frontend (`Client Editor Edge Compiled`)
71
+ ### 3. Creating Frontend Snapshots
95
72
 
96
- Al iniciar la sesión del usuario o refrescar datos (SSR / Next.js), compila el grafo ReBAC súper pesado del servidor en un JSON estático y ultrarapido para mandar al cliente:
73
+ For React/Vue SPAs, you don't want to traverse graphs locally. Instead, you extract a "flat snapshot" on your server and send it over an API block.
97
74
 
98
75
  ```typescript
99
- import { createZanzoSnapshot, ZanzoClient } from '@zanzojs/core';
100
-
101
- // Backend:
102
- const flatPermissions = createZanzoSnapshot(engine, 'User:Carlos');
103
- // flatPermissions = { "Document:456": ["read"] }
104
-
105
- // --- Envía el JSON por API ---
76
+ import { createZanzoSnapshot } from '@zanzojs/core';
106
77
 
107
- // Frontend (React, Vue, Edge Worker, etc.):
108
- // ¡0 Dependencias, 0 Conocimiento del Graph!
109
- const client = new ZanzoClient(flatPermissions);
78
+ // This output is what you would pass to the @zanzojs/react Provider
79
+ const snapshot = createZanzoSnapshot(engine, 'User:1');
110
80
 
111
- // Operación inmediata O(1)
112
- if (client.can('read', 'Document:456')) {
113
- // Show UI Component
114
- }
81
+ // Looks like:
82
+ // { "Document:xyz": ["read", "write"] }
115
83
  ```
116
84
 
117
- ## 🚀 Próximos pasos / Adaptadores
85
+ ## Security Limits
118
86
 
119
- Zanzo fue construido para ser agnóstico. El output de `buildDatabaseQuery()` está intencionalmente diseñado para que la comunidad (o tú) puedas implementar compiladores finales o adaptadores que traduzcan la representación analítica del AST en Data Queries nativas directas para integraciones específicas: `@zanzo/prisma`, `@zanzo/drizzle`, etc.
87
+ Unrestricted graphs can cause memory exhaustion (DoS). The `ZanzoEngine` natively prevents circular dependencies and caps graph traversal depth to 50 levels by default.
120
88
 
121
- ## 📜 Licencia
89
+ ## Documentation
122
90
 
123
- [MIT License](LICENSE) © Zanzo Contributors
91
+ For integration with databases and React, see the [ZanzoJS Monorepo](https://github.com/GonzaloJeria/zanzo).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zanzojs/core",
3
- "version": "0.1.0-beta.0",
3
+ "version": "0.1.0-beta.1",
4
4
  "description": "Isomorphic ReBAC Authorization for the Modern Web. Inspired by Google Zanzibar.",
5
5
  "keywords": [
6
6
  "rebac",