@cocreate/authorize 1.17.2 → 1.17.4
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.
- package/CHANGELOG.md +7 -0
- package/README.md +154 -43
- package/package.json +13 -10
- package/src/index.js +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [1.17.3](https://github.com/CoCreate-app/CoCreate-authorize/compare/v1.17.2...v1.17.3) (2026-07-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* update package description and keywords for clarity and accuracy ([cc9ae48](https://github.com/CoCreate-app/CoCreate-authorize/commit/cc9ae48c1c42e2f7c4bca9a2b10112888ea84547))
|
|
7
|
+
|
|
1
8
|
## [1.17.2](https://github.com/CoCreate-app/CoCreate-authorize/compare/v1.17.1...v1.17.2) (2026-07-19)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -1,78 +1,189 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @cocreate/authorization
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A high-performance, real-time multi-tenant authorization framework, permission evaluation engine, and data sanitization firewall. Scoped entirely to single-tenant memory landscapes using an ESM singleton cache layer (`organizations`), this engine interprets granular database-backed action matrices, handles recursive role inheritance, applies dynamic query filter injections, and runs deep field-level payload sanitization (inclusions and exclusions) to enforce bulletproof access controls across distributed networks.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-

|
|
7
|
-

|
|
5
|
+
---
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
## Table of Contents
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
* [Features](#features)
|
|
10
|
+
* [Dynamic Rule Operators](#dynamic-rule-operators)
|
|
11
|
+
* [Installation](#installation)
|
|
12
|
+
* [Usage](#usage)
|
|
13
|
+
* [How it Works](#how-it-works)
|
|
14
|
+
* [Architecture and Payload Specs](#architecture-and-payload-specs)
|
|
15
|
+
* [Security & Sanitization Firewall](#security--sanitization-firewall)
|
|
16
|
+
* [How to Contribute](#how-to-contribute)
|
|
17
|
+
* [License](#license)
|
|
18
|
+
---
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
## Features
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
* **Multi-Tenant Memory Caching:** Maintains isolated authorization indices in-memory (`organizations`), matching active requests instantly without generating endless round-trip database lookup overhead.
|
|
23
|
+
* **Reactive Event-Driven Cache Invalidation:** Plugs into client and server CRUD listener matrices (`object.update`, `object.delete`), automatically performing hot cache updates or targeted purging whenever authorization keys are modified.
|
|
24
|
+
* **Hierarchical Dot-Notation Routing:** Cascades down specific action hierarchies automatically (e.g., checking permission for `object.read.user` will seamlessly fall back to `object.read` or `*` global wildcards if explicit rules aren't found).
|
|
25
|
+
* **Deep Role Inheritance & Merging:** Compiles comprehensive baseline configurations by fetching assigned collection roles, dynamically transforming flat dot-notated entries into deep-merged privilege trees.
|
|
26
|
+
* **Dynamic Query Filter Injections:** Injects complex MongoDB-style query filters (`$eq`, `$ne`, `$in`, etc.) directly into outgoing execution targets based on tenant permission configurations (e.g., locking access bounds to active user states).
|
|
27
|
+
* **Payload Field Sanitization Firewall:** Segregates input and output object surfaces by evaluating raw arrays against strict field permissions, filtering properties instantly using absolute priority inclusion or exclusion logic.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Dynamic Rule Operators
|
|
32
|
+
|
|
33
|
+
The engine reads specific evaluation tokens within your permission definitions to perform inline data injection and structural assertions:
|
|
34
|
+
|
|
35
|
+
| Core Rule Operator | Action Evaluation & Resolution |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| **`$user_id`** | Resolves dynamically against session properties, pulling the verified user ID from active socket or request configurations. |
|
|
38
|
+
| **`$storage` / `$database**` | Intercepts validation cycles, checking incoming parameters explicitly against target database partitions. |
|
|
39
|
+
| **`$array` / `$index**` | Scans collection array parameters dynamically to verify target indices or resource keys align with tenant scopes. |
|
|
40
|
+
| **`$keys`** | Triggers the field-level data sanitization firewall, identifying fields allowed for reading/writing. |
|
|
41
|
+
| **`$filter`** | Enforces row-level constraints by modifying the active request query with runtime operators. |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @cocreate/authorization
|
|
16
49
|
|
|
17
|
-
```shell
|
|
18
|
-
$ npm i @cocreate/authorize
|
|
19
50
|
```
|
|
20
51
|
|
|
21
|
-
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
### Programmatic Authorization Check
|
|
57
|
+
|
|
58
|
+
Evaluate a user session or API key against an incoming execution request. The engine processes the user credential first and gracefully falls back to the payload API key if necessary:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
import { check } from '@cocreate/authorization';
|
|
62
|
+
|
|
63
|
+
const requestPayload = {
|
|
64
|
+
organization_id: "64b9a32e18f21bc56789abcd",
|
|
65
|
+
method: "object.read.profile",
|
|
66
|
+
host: "app.cocreate.js",
|
|
67
|
+
apikey: "cc-sk-live-90210xfdsa...",
|
|
68
|
+
// Targets to evaluate/sanitize
|
|
69
|
+
object: {
|
|
70
|
+
name: "user-profiles",
|
|
71
|
+
secretField: "sensitive-data",
|
|
72
|
+
publicField: "hello world"
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const activeUserId = "64b9a35f18f21bc5e9812456";
|
|
77
|
+
|
|
78
|
+
// Evaluates permissions, handles inheritance, and optimizes payload properties inline
|
|
79
|
+
const evaluationResult = await check(requestPayload, activeUserId);
|
|
80
|
+
|
|
81
|
+
if (evaluationResult === false) {
|
|
82
|
+
console.log("Access Denied: Unauthorized operation.");
|
|
83
|
+
} else {
|
|
84
|
+
console.log("Authorized payload (sanitized):", evaluationResult.authorized);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Manual Authorization Fetching
|
|
90
|
+
|
|
91
|
+
Manually extract a tenant's fully compiled, role-inherited authorization profile from the cache layer or database:
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
import { getAuthorization } from '@cocreate/authorization';
|
|
95
|
+
|
|
96
|
+
const queryContext = {
|
|
97
|
+
organization_id: "64b9a32e18f21bc56789abcd",
|
|
98
|
+
host: "app.cocreate.js"
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const targetKey = "64b9a35f18f21bc5e9812456"; // User ID or API Key string
|
|
102
|
+
|
|
103
|
+
const fullAuthProfile = await getAuthorization(targetKey, queryContext);
|
|
104
|
+
console.log(fullAuthProfile);
|
|
105
|
+
/*
|
|
106
|
+
Outputs compiled configuration:
|
|
107
|
+
{
|
|
108
|
+
_id: "...",
|
|
109
|
+
key: "64b9a35f18f21bc56789abcd",
|
|
110
|
+
organization_id: "64b9a32e18f21bc56789abcd",
|
|
111
|
+
admin: false,
|
|
112
|
+
roles: ["manager", "employee"],
|
|
113
|
+
actions: {
|
|
114
|
+
"object.read": true,
|
|
115
|
+
"object.write": { "$keys": { "secretField": false } }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
*/
|
|
22
119
|
|
|
23
|
-
```shell
|
|
24
|
-
$ yarn add @cocreate/authorize
|
|
25
120
|
```
|
|
26
121
|
|
|
27
|
-
|
|
122
|
+
---
|
|
28
123
|
|
|
29
|
-
|
|
30
|
-
- [Announcements](#announcements)
|
|
31
|
-
- [Roadmap](#roadmap)
|
|
32
|
-
- [How to Contribute](#how-to-contribute)
|
|
33
|
-
- [About](#about)
|
|
34
|
-
- [License](#license)
|
|
124
|
+
## How it Works
|
|
35
125
|
|
|
36
|
-
|
|
126
|
+
1. **Context Interception & Fallback:** The execution pipeline enters through `check()`. The framework initializes checking structures against the explicit `user_id` context. If the resolution returns `false` or errors out, it intercepts request metrics and retries using `data.apikey`.
|
|
127
|
+
2. **Deterministic Cache Evaluation:** `getAuthorization()` checks if the target `organization_id` profile exists in memory. If absent, it issues a database query through the CRUD gateway (`readAuthorization`) to pull both default configurations (`default: true`) and key-specific rules concurrently.
|
|
128
|
+
3. **Role Expansion & Deep Merging:** The engine reads the fetched rules, maps associated arrays via `dotNotationToObject`, gathers any assigned structural roles (`roles`), and issues secondary pipelines to retrieve each role profile. It then executes deep-merging loops to fold role rules into a single authorization blueprint.
|
|
129
|
+
4. **Hierarchical Action Mapping:** When validating actions via `checkMethod()`, the system performs full string match scans. If missing, it systematically splits the action parameter across period boundaries (e.g., `object.update.status` $\rightarrow$ `object.update` $\rightarrow$ `*`), climbing up the matrix to find an applicable rule block.
|
|
130
|
+
5. **Dynamic Filter Injection:** If rule evaluations match parameter queries, `applyFilter()` isolates operators like `$eq` or `$ne`. It automatically maps contextual criteria (such as shifting `$user_id` into the user's active session ID) and transforms the target query structure directly.
|
|
131
|
+
6. **Payload Cleansing:** Finally, fields pass through `parsePermissions()` to filter out restricted parameters. It yields clear inclusion or exclusion criteria, sending variables down to `sanitizeData()` where deep properties are safely pruned before execution blocks are returned.
|
|
37
132
|
|
|
38
|
-
|
|
133
|
+
---
|
|
39
134
|
|
|
40
|
-
|
|
135
|
+
## Architecture and Payload Specs
|
|
41
136
|
|
|
42
|
-
|
|
137
|
+
### Check Parameter Schema
|
|
43
138
|
|
|
44
|
-
|
|
139
|
+
The framework expects standard transaction blocks containing routing properties and environmental identifiers:
|
|
45
140
|
|
|
46
|
-
|
|
141
|
+
| Field Element | Type | Role |
|
|
142
|
+
| --- | --- | --- |
|
|
143
|
+
| `organization_id` | `String` | **Required.** Anchors the request context to isolated tenant databases. |
|
|
144
|
+
| `method` | `String` | **Required.** The namespace path of the active request (e.g., `"object.write.users"`). |
|
|
145
|
+
| `host` | `String` | Environmental host context checked against explicit key domain limitations. |
|
|
146
|
+
| `apikey` | `String` | Authentication token utilized as a fallback routing vector if no explicit user context exists. |
|
|
147
|
+
| `object` | `Object|Array` | The primary data payload structural container undergoing field-level sanitization. |
|
|
47
148
|
|
|
48
|
-
|
|
149
|
+
---
|
|
49
150
|
|
|
50
|
-
|
|
151
|
+
## Security & Sanitization Firewall
|
|
51
152
|
|
|
52
|
-
|
|
153
|
+
> [!NOTE]
|
|
154
|
+
> Inclusion rules always take absolute priority over exclusion boundaries. If an authorization entry contains even one explicit `true` attribute mapping inside its field specification array, all other sister fields are immediately treated as restricted and stripped.
|
|
53
155
|
|
|
54
|
-
|
|
156
|
+
### Sanitization Prioritization Logic
|
|
55
157
|
|
|
56
|
-
|
|
158
|
+
The module routes all calculated configurations through an isolated evaluation step to determine how properties are processed:
|
|
57
159
|
|
|
58
|
-
|
|
160
|
+
```javascript
|
|
161
|
+
if (inclusion.length > 0) {
|
|
162
|
+
// If any explicit inclusion exists, exclusions are entirely ignored
|
|
163
|
+
return { inclusion, exclusion: null };
|
|
164
|
+
} else if (exclusion.length > 0) {
|
|
165
|
+
// If only exclusions exist, inclusions remain null
|
|
166
|
+
return { inclusion: null, exclusion };
|
|
167
|
+
}
|
|
59
168
|
|
|
60
|
-
|
|
169
|
+
```
|
|
61
170
|
|
|
62
|
-
|
|
171
|
+
* **Inclusion Mode:** Keeps *only* the specific fields matching dot-notation rules exactly (e.g. `profile.name`). All unspecified object fields are stripped.
|
|
172
|
+
* **Exclusion Mode:** Preserves the entire object surface area *except* the properties explicitly blacklisted (e.g. mapping a field to `false` or `undefined`), which are completely expunged before returning.
|
|
63
173
|
|
|
64
|
-
|
|
174
|
+
---
|
|
65
175
|
|
|
66
|
-
|
|
176
|
+
## How to Contribute
|
|
67
177
|
|
|
68
|
-
|
|
178
|
+
We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING.md](https://github.com/CoCreate-app/CoCreate-authorization/blob/master/CONTRIBUTING.md) guide for details. If you encounter any bugs or wish to make feature requests, please submit an issue on our [GitHub Issues](https://github.com/CoCreate-app/CoCreate-authorization/issues) tracker. We want this library to be community-driven, and CoCreate led. We need your help to realize this goal.
|
|
69
179
|
|
|
70
|
-
|
|
180
|
+
For broader system configurations and API guides, please visit our [CoCreate Authorization Documentation](https://cocreatejs.com/docs/authorization).
|
|
71
181
|
|
|
72
|
-
|
|
182
|
+
---
|
|
73
183
|
|
|
74
|
-
|
|
184
|
+
## License
|
|
75
185
|
|
|
76
|
-
|
|
186
|
+
This software is dual-licensed under the GNU Affero General Public License version 3 (AGPLv3) and a commercial license.
|
|
77
187
|
|
|
78
|
-
|
|
188
|
+
* **Open Source Use:** For open-source projects and non-commercial use, this software is available under the AGPLv3. For the full license text, see the LICENSE file.
|
|
189
|
+
* **Commercial Use:** For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our website.
|
package/package.json
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/authorize",
|
|
3
|
-
"version": "1.17.
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "1.17.4",
|
|
4
|
+
"description": "A secure, real-time multi-tenant authorization framework and permission evaluation engine featuring hierarchical dot-notation routing, dynamic query filter injection, and deep payload field sanitization.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
6
|
+
"authorization",
|
|
7
|
+
"permission-engine",
|
|
8
|
+
"role-inheritance",
|
|
9
|
+
"data-sanitization",
|
|
10
|
+
"multi-tenant",
|
|
11
|
+
"cache-invalidation",
|
|
12
|
+
"query-filter-injection",
|
|
13
|
+
"field-level-security",
|
|
14
|
+
"access-control",
|
|
15
|
+
"rbac",
|
|
16
|
+
"abac"
|
|
14
17
|
],
|
|
15
18
|
"publishConfig": {
|
|
16
19
|
"access": "public"
|
package/src/index.js
CHANGED
|
@@ -18,9 +18,6 @@
|
|
|
18
18
|
import { getValueFromObject, dotNotationToObject } from "@cocreate/utils";
|
|
19
19
|
import crud from "@cocreate/crud-server";
|
|
20
20
|
|
|
21
|
-
// ==========================================
|
|
22
|
-
// Module-Level Sandbox State (ESM Singleton)
|
|
23
|
-
// ==========================================
|
|
24
21
|
const organizations = {};
|
|
25
22
|
|
|
26
23
|
// ==========================================
|