@navirondynamics/accord 1.0.0 → 1.1.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.
- package/README.md +212 -26
- package/dist/accord.d.ts +8 -0
- package/dist/accord.d.ts.map +1 -1
- package/dist/accord.js +43 -7
- package/dist/accord.js.map +1 -1
- package/dist/adapters/fastify.d.ts +14 -0
- package/dist/adapters/fastify.d.ts.map +1 -0
- package/dist/adapters/fastify.js +44 -0
- package/dist/adapters/fastify.js.map +1 -0
- package/dist/adapters/nest.d.ts +19 -0
- package/dist/adapters/nest.d.ts.map +1 -0
- package/dist/adapters/nest.js +95 -0
- package/dist/adapters/nest.js.map +1 -0
- package/dist/core/loader.d.ts +2 -1
- package/dist/core/loader.d.ts.map +1 -1
- package/dist/core/loader.js +25 -3
- package/dist/core/loader.js.map +1 -1
- package/dist/core/logger.d.ts +37 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +77 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/validation.d.ts +39 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +45 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/store/identity.d.ts +5 -0
- package/dist/store/identity.d.ts.map +1 -1
- package/dist/store/identity.js +18 -1
- package/dist/store/identity.js.map +1 -1
- package/package.json +28 -3
package/README.md
CHANGED
|
@@ -1,49 +1,235 @@
|
|
|
1
|
-
Accord
|
|
1
|
+
# Accord
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.npmjs.com/package/@navirondynamics/accord">
|
|
5
|
+
<img src="https://img.shields.io/npm/v/@navirondynamics/accord.svg" alt="npm version" />
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/@navirondynamics/accord">
|
|
8
|
+
<img src="https://img.shields.io/npm/dm/@navirondynamics/accord.svg" alt="npm downloads" />
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://github.com/bsen-alt/Accord">
|
|
11
|
+
<img src="https://img.shields.io/github/license/bsen-alt/Accord" alt="license" />
|
|
12
|
+
</a>
|
|
13
|
+
</p>
|
|
4
14
|
|
|
5
|
-
|
|
15
|
+
Accord is a **policy-first identity and access engine for Node.js**.
|
|
6
16
|
|
|
7
|
-
|
|
17
|
+
It treats access not as scattered application logic, but as a formal agreement between identities, systems, and resources - evaluated through declarative, versioned policies.
|
|
8
18
|
|
|
9
|
-
|
|
19
|
+
**New in v1.1:** Observability, YAML configuration, hot reload, and native NestJS support.
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
---
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
## Table of Contents
|
|
14
24
|
|
|
15
|
-
|
|
25
|
+
- [Why Accord](#-why-accord)
|
|
26
|
+
- [Key Features](#key-features)
|
|
27
|
+
- [Installation](#-installation)
|
|
28
|
+
- [Quick Start](#-quick-start-v11)
|
|
29
|
+
- [Framework Integration](#-framework-integration)
|
|
30
|
+
- [CLI Tool](#-cli-tool)
|
|
31
|
+
- [Documentation](#-documentation)
|
|
32
|
+
- [Roadmap](#-roadmap)
|
|
33
|
+
- [Contributing](#-contributing)
|
|
34
|
+
- [License](#-license)
|
|
16
35
|
|
|
17
|
-
|
|
36
|
+
---
|
|
18
37
|
|
|
19
|
-
|
|
38
|
+
## 🚀 Why Accord?
|
|
20
39
|
|
|
21
|
-
|
|
40
|
+
Modern authorization is fragmented:
|
|
22
41
|
|
|
23
|
-
|
|
42
|
+
- Authentication in one service
|
|
43
|
+
- Roles in another
|
|
44
|
+
- Access logic scattered across microservices
|
|
24
45
|
|
|
25
|
-
|
|
46
|
+
Accord centralizes authorization into a single **governance layer**, acting as the _System of Record_ for access control across your platform.
|
|
26
47
|
|
|
27
|
-
|
|
48
|
+
Instead of embedding authorization logic throughout your codebase, Accord externalizes it into auditable, inspectable, and versioned policy definitions.
|
|
28
49
|
|
|
29
|
-
|
|
30
|
-
Protect your routes easily:
|
|
50
|
+
---
|
|
31
51
|
|
|
32
|
-
|
|
52
|
+
## Key Features
|
|
33
53
|
|
|
34
|
-
|
|
54
|
+
- 🔍 **Observability** – Built-in audit logging (console & file)
|
|
55
|
+
- 📝 **Policy as Code** – JSON and YAML configuration support
|
|
56
|
+
- 🛡️ **Reliability** – Zod-based schema validation to prevent invalid policies
|
|
57
|
+
- 🔄 **Zero-Downtime Updates** – Hot reload policies without restarting services
|
|
58
|
+
- 🧩 **Framework Adapters** – Express, NestJS, and Fastify integrations
|
|
59
|
+
- 📦 **CLI Tooling** – Validate and simulate access decisions locally
|
|
35
60
|
|
|
36
|
-
|
|
61
|
+
---
|
|
37
62
|
|
|
38
|
-
|
|
39
|
-
Validate policies locally:
|
|
63
|
+
## 📦 Installation
|
|
40
64
|
|
|
41
|
-
```
|
|
65
|
+
```bash
|
|
66
|
+
npm install @navirondynamics/accord
|
|
67
|
+
```
|
|
42
68
|
|
|
43
|
-
|
|
69
|
+
---
|
|
44
70
|
|
|
45
|
-
|
|
71
|
+
## 🛠️ Quick Start (v1.1)
|
|
72
|
+
|
|
73
|
+
### 1. Define Policies (YAML supported)
|
|
74
|
+
|
|
75
|
+
Create `config/policies.yaml`:
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
- id: 'admin-delete'
|
|
79
|
+
version: '1.1'
|
|
80
|
+
effect: 'allow'
|
|
81
|
+
subject:
|
|
82
|
+
type: 'user'
|
|
83
|
+
attributes:
|
|
84
|
+
role: 'admin'
|
|
85
|
+
action: ['delete']
|
|
86
|
+
resource:
|
|
87
|
+
type: 'booking'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### 2. Initialize Accord
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const { Accord, ConsoleAuditLogger } = require('@navirondynamics/accord');
|
|
96
|
+
|
|
97
|
+
const accord = new Accord({
|
|
98
|
+
policyPath: './config/policies.yaml',
|
|
99
|
+
identityPath: './config/identities.json',
|
|
100
|
+
logger: new ConsoleAuditLogger(),
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### 3. Check Access
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
async function deleteUser(userId) {
|
|
110
|
+
const decision = await accord.check(userId, 'delete', {
|
|
111
|
+
type: 'user',
|
|
112
|
+
id: userId,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (decision.decision === 'allow') {
|
|
116
|
+
console.log('Permission Granted');
|
|
117
|
+
// Perform deletion...
|
|
118
|
+
} else {
|
|
119
|
+
console.log('Access Denied:', decision.reason);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 🛡️ Framework Integration
|
|
127
|
+
|
|
128
|
+
### NestJS
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { AccordGuard } from '@navirondynamics/accord/adapters/nest';
|
|
132
|
+
|
|
133
|
+
@Controller('bookings')
|
|
134
|
+
export class BookingController {
|
|
135
|
+
@UseGuards(
|
|
136
|
+
new AccordGuard({
|
|
137
|
+
accordInstance: accord,
|
|
138
|
+
action: 'delete',
|
|
139
|
+
resourceType: 'booking',
|
|
140
|
+
})
|
|
141
|
+
)
|
|
142
|
+
@Delete(':id')
|
|
143
|
+
deleteBooking(@Param('id') id: string) {
|
|
144
|
+
// Only authorized users reach here
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### Express
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
const { protect } = require('@navirondynamics/accord/adapters/express');
|
|
155
|
+
|
|
156
|
+
app.delete(
|
|
157
|
+
'/bookings/:id',
|
|
158
|
+
protect({
|
|
159
|
+
accordInstance: accord,
|
|
160
|
+
action: 'delete',
|
|
161
|
+
resourceType: 'booking',
|
|
162
|
+
}),
|
|
163
|
+
(req, res) => {
|
|
164
|
+
res.send('Deleted');
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Fastify support and advanced usage are available in the adapters documentation.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 🔧 CLI Tool
|
|
174
|
+
|
|
175
|
+
Validate policies or simulate access decisions directly from your terminal.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Validate policy syntax
|
|
179
|
+
npx @navirondynamics/accord validate ./config/policies.yaml
|
|
180
|
+
|
|
181
|
+
# Test access logic
|
|
182
|
+
npx @navirondynamics/accord eval -i user_123 -a delete -r booking
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 📚 Documentation
|
|
188
|
+
|
|
189
|
+
- **Getting Started** – Installation and core concepts
|
|
190
|
+
- **Configuration Guide** – Identities, policies, JSON vs YAML
|
|
191
|
+
- **Observability & Auditing** – Production logging setup
|
|
192
|
+
- **Framework Adapters** – Express, NestJS, Fastify usage
|
|
193
|
+
- **CLI Reference** – Full command list
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 🗺️ Roadmap
|
|
198
|
+
|
|
199
|
+
Planned improvements:
|
|
200
|
+
|
|
201
|
+
- Policy versioning & rollback
|
|
202
|
+
- Database-backed policy storage
|
|
203
|
+
- Web-based policy editor
|
|
204
|
+
- Decision caching
|
|
205
|
+
- OpenTelemetry tracing
|
|
206
|
+
- Distributed policy synchronization
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 🤝 Contributing
|
|
211
|
+
|
|
212
|
+
Contributions are welcome.
|
|
213
|
+
|
|
214
|
+
1. Fork the repository
|
|
215
|
+
2. Create a feature branch
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
git checkout -b feature/my-feature
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
3. Commit your changes
|
|
222
|
+
4. Push to your fork
|
|
223
|
+
5. Open a Pull Request
|
|
224
|
+
|
|
225
|
+
Please ensure tests pass and documentation is updated.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 📜 License
|
|
46
230
|
|
|
47
|
-
License
|
|
48
231
|
ISC
|
|
49
|
-
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
```
|
package/dist/accord.d.ts
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { IdentityStore } from './store/identity';
|
|
2
|
+
import { AuditLogger } from './core/logger';
|
|
2
3
|
import { Decision } from './core/types';
|
|
3
4
|
export interface AccordConfig {
|
|
4
5
|
policyPath: string;
|
|
5
6
|
identityPath: string;
|
|
7
|
+
logger?: AuditLogger;
|
|
6
8
|
}
|
|
7
9
|
export declare class Accord {
|
|
8
10
|
private policies;
|
|
9
11
|
private identityStore;
|
|
10
12
|
private resolver;
|
|
11
13
|
private config;
|
|
14
|
+
private logger;
|
|
12
15
|
constructor(config: AccordConfig);
|
|
13
16
|
check(externalId: string, action: string, resource: any, context?: any): Promise<Decision>;
|
|
14
17
|
getStore(): IdentityStore;
|
|
18
|
+
/**
|
|
19
|
+
* Reloads Policies and Identities from disk.
|
|
20
|
+
* SAFETY: If the new config is invalid, the old config remains active.
|
|
21
|
+
*/
|
|
22
|
+
reload(): void;
|
|
15
23
|
}
|
|
16
24
|
//# sourceMappingURL=accord.d.ts.map
|
package/dist/accord.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accord.d.ts","sourceRoot":"","sources":["../src/accord.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAiB,QAAQ,EAAkB,MAAM,cAAc,CAAC;AAEvE,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,MAAM,CAAe;
|
|
1
|
+
{"version":3,"file":"accord.d.ts","sourceRoot":"","sources":["../src/accord.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAkC,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAiB,QAAQ,EAAkB,MAAM,cAAc,CAAC;AAEvE,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,EAAE,YAAY;IAiB1B,KAAK,CACT,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,GAAG,EACb,OAAO,CAAC,EAAE,GAAG,GACZ,OAAO,CAAC,QAAQ,CAAC;IAwCpB,QAAQ,IAAI,aAAa;IAIzB;;;OAGG;IACH,MAAM,IAAI,IAAI;CAmBf"}
|
package/dist/accord.js
CHANGED
|
@@ -3,22 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Accord = void 0;
|
|
4
4
|
// src/accord.ts
|
|
5
5
|
const loader_1 = require("./core/loader");
|
|
6
|
-
const compiler_1 = require("./core/compiler");
|
|
6
|
+
const compiler_1 = require("./core/compiler");
|
|
7
7
|
const identity_1 = require("./store/identity");
|
|
8
8
|
const resolver_1 = require("./core/resolver");
|
|
9
9
|
const evaluator_1 = require("./core/evaluator");
|
|
10
|
+
const logger_1 = require("./core/logger"); // NEW IMPORTS
|
|
10
11
|
class Accord {
|
|
11
12
|
constructor(config) {
|
|
12
13
|
this.config = config;
|
|
13
|
-
// 1. Initialize
|
|
14
|
+
// 1. Initialize Logger (Default to ConsoleAuditLogger)
|
|
15
|
+
this.logger = config.logger || new logger_1.ConsoleAuditLogger();
|
|
16
|
+
// 2. Initialize Store
|
|
14
17
|
this.identityStore = new identity_1.IdentityStore(config.identityPath);
|
|
15
|
-
//
|
|
18
|
+
// 3. Initialize Resolver
|
|
16
19
|
this.resolver = new resolver_1.IdentityResolver(this.identityStore);
|
|
17
|
-
//
|
|
20
|
+
// 4. Load and COMPILE Policies
|
|
18
21
|
const rawPolicies = (0, loader_1.loadPolicies)(config.policyPath);
|
|
19
22
|
this.policies = (0, compiler_1.compilePolicies)(rawPolicies);
|
|
20
23
|
}
|
|
21
24
|
async check(externalId, action, resource, context) {
|
|
25
|
+
let decision;
|
|
22
26
|
try {
|
|
23
27
|
// 1. Resolve Identity
|
|
24
28
|
const identity = this.resolver.resolve(externalId);
|
|
@@ -30,19 +34,51 @@ class Accord {
|
|
|
30
34
|
context: context || {}
|
|
31
35
|
};
|
|
32
36
|
// 3. Evaluate
|
|
33
|
-
|
|
34
|
-
return decision;
|
|
37
|
+
decision = await (0, evaluator_1.evaluate)(request, this.policies);
|
|
35
38
|
}
|
|
36
39
|
catch (error) {
|
|
37
|
-
|
|
40
|
+
decision = {
|
|
38
41
|
decision: 'deny',
|
|
39
42
|
reason: error.message
|
|
40
43
|
};
|
|
41
44
|
}
|
|
45
|
+
// 4. AUDIT LOG (New Step)
|
|
46
|
+
this.logger.log({
|
|
47
|
+
timestamp: new Date(),
|
|
48
|
+
decision: decision.decision,
|
|
49
|
+
policyId: decision.policy_id,
|
|
50
|
+
reason: decision.reason,
|
|
51
|
+
userId: externalId,
|
|
52
|
+
action: action,
|
|
53
|
+
resourceType: resource.type,
|
|
54
|
+
resourceId: resource.id
|
|
55
|
+
});
|
|
56
|
+
return decision;
|
|
42
57
|
}
|
|
43
58
|
getStore() {
|
|
44
59
|
return this.identityStore;
|
|
45
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Reloads Policies and Identities from disk.
|
|
63
|
+
* SAFETY: If the new config is invalid, the old config remains active.
|
|
64
|
+
*/
|
|
65
|
+
reload() {
|
|
66
|
+
try {
|
|
67
|
+
// 1. Reload Policies
|
|
68
|
+
const newRawPolicies = (0, loader_1.loadPolicies)(this.config.policyPath);
|
|
69
|
+
const newCompiledPolicies = (0, compiler_1.compilePolicies)(newRawPolicies);
|
|
70
|
+
// 2. Reload Identities
|
|
71
|
+
this.identityStore.reload();
|
|
72
|
+
// 3. Swap Logic (Atomic Update)
|
|
73
|
+
this.policies = newCompiledPolicies;
|
|
74
|
+
console.log('✓ Accord Reloaded Successfully');
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('✗ Reload Failed. Old config is still active.');
|
|
78
|
+
console.error('Reason:', error.message);
|
|
79
|
+
// We do NOT throw here. We want the app to keep running on old config.
|
|
80
|
+
}
|
|
81
|
+
}
|
|
46
82
|
}
|
|
47
83
|
exports.Accord = Accord;
|
|
48
84
|
//# sourceMappingURL=accord.js.map
|
package/dist/accord.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accord.js","sourceRoot":"","sources":["../src/accord.ts"],"names":[],"mappings":";;;AAAA,gBAAgB;AAChB,0CAA6C;AAC7C,8CAAkD
|
|
1
|
+
{"version":3,"file":"accord.js","sourceRoot":"","sources":["../src/accord.ts"],"names":[],"mappings":";;;AAAA,gBAAgB;AAChB,0CAA6C;AAC7C,8CAAkD;AAClD,+CAAiD;AACjD,8CAAmD;AACnD,gDAA4C;AAC5C,0CAA4E,CAAC,cAAc;AAS3F,MAAa,MAAM;IAOjB,YAAY,MAAoB;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,uDAAuD;QACvD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,2BAAkB,EAAE,CAAC;QAExD,sBAAsB;QACtB,IAAI,CAAC,aAAa,GAAG,IAAI,wBAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAE5D,yBAAyB;QACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,2BAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAEzD,+BAA+B;QAC/B,MAAM,WAAW,GAAG,IAAA,qBAAY,EAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,GAAG,IAAA,0BAAe,EAAC,WAAW,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,KAAK,CACT,UAAkB,EAClB,MAAc,EACd,QAAa,EACb,OAAa;QAEb,IAAI,QAAkB,CAAC;QAEvB,IAAI,CAAC;YACH,sBAAsB;YACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAEnD,6BAA6B;YAC7B,MAAM,OAAO,GAAkB;gBAC7B,OAAO,EAAE,QAAQ;gBACjB,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,OAAO,IAAI,EAAE;aACvB,CAAC;YAEF,cAAc;YACd,QAAQ,GAAG,MAAM,IAAA,oBAAQ,EAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,GAAG;gBACT,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAG,KAAe,CAAC,OAAO;aACjC,CAAC;QACJ,CAAC;QAED,0BAA0B;QAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;YACd,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,QAAQ,EAAE,QAAQ,CAAC,SAAS;YAC5B,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,MAAM;YACd,YAAY,EAAE,QAAQ,CAAC,IAAI;YAC3B,UAAU,EAAE,QAAQ,CAAC,EAAE;SACxB,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,IAAI,CAAC;YACH,qBAAqB;YACrB,MAAM,cAAc,GAAG,IAAA,qBAAY,EAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC5D,MAAM,mBAAmB,GAAG,IAAA,0BAAe,EAAC,cAAc,CAAC,CAAC;YAE5D,uBAAuB;YACvB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YAE5B,gCAAgC;YAChC,IAAI,CAAC,QAAQ,GAAG,mBAAmB,CAAC;YAEpC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC9D,OAAO,CAAC,KAAK,CAAC,SAAS,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;YACnD,uEAAuE;QACzE,CAAC;IACH,CAAC;CACF;AAhGD,wBAgGC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FastifyRequest, FastifyReply } from 'fastify';
|
|
2
|
+
import { Accord } from '../accord';
|
|
3
|
+
export interface AccordHookOptions {
|
|
4
|
+
accordInstance: Accord;
|
|
5
|
+
action: string;
|
|
6
|
+
resourceType: string;
|
|
7
|
+
getId?: (req: FastifyRequest) => string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Fastify Hook Factory
|
|
11
|
+
* Usage: fastify.addHook('onRequest', accordHook({ ... }))
|
|
12
|
+
*/
|
|
13
|
+
export declare function accordHook(options: AccordHookOptions): (req: FastifyRequest, reply: FastifyReply) => Promise<undefined>;
|
|
14
|
+
//# sourceMappingURL=fastify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/adapters/fastify.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGnC,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IAErB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,MAAM,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,IACrC,KAAK,cAAc,EAAE,OAAO,YAAY,wBAwCvD"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.accordHook = accordHook;
|
|
4
|
+
/**
|
|
5
|
+
* Fastify Hook Factory
|
|
6
|
+
* Usage: fastify.addHook('onRequest', accordHook({ ... }))
|
|
7
|
+
*/
|
|
8
|
+
function accordHook(options) {
|
|
9
|
+
return async (req, reply) => {
|
|
10
|
+
try {
|
|
11
|
+
// 1. Determine User ID
|
|
12
|
+
const userId = options.getId
|
|
13
|
+
? options.getId(req)
|
|
14
|
+
: req.headers['x-user-id'];
|
|
15
|
+
if (!userId) {
|
|
16
|
+
return reply.status(401).send({ error: 'User ID missing' });
|
|
17
|
+
}
|
|
18
|
+
// 2. Construct Resource
|
|
19
|
+
const resource = {
|
|
20
|
+
type: options.resourceType,
|
|
21
|
+
id: req.params.id,
|
|
22
|
+
attributes: req.body || {}
|
|
23
|
+
};
|
|
24
|
+
// 3. Check Policy
|
|
25
|
+
const decision = await options.accordInstance.check(userId, options.action, resource);
|
|
26
|
+
// 4. Enforce
|
|
27
|
+
if (decision.decision === 'allow') {
|
|
28
|
+
req.authDecision = decision;
|
|
29
|
+
return; // Continue
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return reply.status(403).send({
|
|
33
|
+
error: 'Access Denied',
|
|
34
|
+
reason: decision.reason
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Fastify Accord Hook Error:', error);
|
|
40
|
+
return reply.status(500).send({ error: 'Internal Server Error' });
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=fastify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/adapters/fastify.ts"],"names":[],"mappings":";;AAiBA,gCAyCC;AA7CD;;;GAGG;AACH,SAAgB,UAAU,CAAC,OAA0B;IACnD,OAAO,KAAK,EAAE,GAAmB,EAAE,KAAmB,EAAE,EAAE;QACxD,IAAI,CAAC;YACH,uBAAuB;YACvB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK;gBAC1B,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;gBACpB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAW,CAAC;YAEvC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;YAC9D,CAAC;YAED,wBAAwB;YACxB,MAAM,QAAQ,GAAG;gBACf,IAAI,EAAE,OAAO,CAAC,YAAY;gBAC1B,EAAE,EAAG,GAAG,CAAC,MAAc,CAAC,EAAE;gBAC1B,UAAU,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;aAC3B,CAAC;YAEF,kBAAkB;YAClB,MAAM,QAAQ,GAAa,MAAM,OAAO,CAAC,cAAc,CAAC,KAAK,CAC3D,MAAM,EACN,OAAO,CAAC,MAAM,EACd,QAAQ,CACT,CAAC;YAEF,aAAa;YACb,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACjC,GAAW,CAAC,YAAY,GAAG,QAAQ,CAAC;gBACrC,OAAO,CAAC,WAAW;YACrB,CAAC;iBAAM,CAAC;gBACN,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBAC5B,KAAK,EAAE,eAAe;oBACtB,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACnD,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Accord } from '../accord';
|
|
3
|
+
/**
|
|
4
|
+
* Options for the NestJS Guard.
|
|
5
|
+
* For v1.1, we define Action/Resource statically on the guard.
|
|
6
|
+
* Future: Use Decorators to set metadata on routes.
|
|
7
|
+
*/
|
|
8
|
+
export interface AccordGuardOptions {
|
|
9
|
+
accordInstance: Accord;
|
|
10
|
+
action: string;
|
|
11
|
+
resourceType: string;
|
|
12
|
+
getId?: (req: any) => string;
|
|
13
|
+
}
|
|
14
|
+
export declare class AccordGuard implements CanActivate {
|
|
15
|
+
private options;
|
|
16
|
+
constructor(options: AccordGuardOptions);
|
|
17
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=nest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nest.d.ts","sourceRoot":"","sources":["../../src/adapters/nest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAc,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGnC;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IAErB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;CAC9B;AAED,qBACa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,OAAO,CAAqB;gBAExB,OAAO,EAAE,kBAAkB;IAIjC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAuC/D"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
3
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
4
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
5
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
6
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
7
|
+
var _, done = false;
|
|
8
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
9
|
+
var context = {};
|
|
10
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
11
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
12
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
13
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
14
|
+
if (kind === "accessor") {
|
|
15
|
+
if (result === void 0) continue;
|
|
16
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
17
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
18
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
19
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
20
|
+
}
|
|
21
|
+
else if (_ = accept(result)) {
|
|
22
|
+
if (kind === "field") initializers.unshift(_);
|
|
23
|
+
else descriptor[key] = _;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
27
|
+
done = true;
|
|
28
|
+
};
|
|
29
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
30
|
+
var useValue = arguments.length > 2;
|
|
31
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
32
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
33
|
+
}
|
|
34
|
+
return useValue ? value : void 0;
|
|
35
|
+
};
|
|
36
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
|
37
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
|
38
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
|
39
|
+
};
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.AccordGuard = void 0;
|
|
42
|
+
// src/adapters/nest.ts
|
|
43
|
+
const common_1 = require("@nestjs/common");
|
|
44
|
+
let AccordGuard = (() => {
|
|
45
|
+
let _classDecorators = [(0, common_1.Injectable)()];
|
|
46
|
+
let _classDescriptor;
|
|
47
|
+
let _classExtraInitializers = [];
|
|
48
|
+
let _classThis;
|
|
49
|
+
var AccordGuard = _classThis = class {
|
|
50
|
+
constructor(options) {
|
|
51
|
+
this.options = options;
|
|
52
|
+
}
|
|
53
|
+
async canActivate(context) {
|
|
54
|
+
const req = context.switchToHttp().getRequest();
|
|
55
|
+
const res = context.switchToHttp().getResponse();
|
|
56
|
+
try {
|
|
57
|
+
// 1. Determine User ID
|
|
58
|
+
const userId = this.options.getId
|
|
59
|
+
? this.options.getId(req)
|
|
60
|
+
: req.headers['x-user-id'];
|
|
61
|
+
if (!userId) {
|
|
62
|
+
// Nest often handles exceptions via Exception Filters,
|
|
63
|
+
// but returning false is standard for guards.
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
// 2. Construct Resource
|
|
67
|
+
const resource = {
|
|
68
|
+
type: this.options.resourceType,
|
|
69
|
+
id: req.params.id,
|
|
70
|
+
attributes: req.body || {}
|
|
71
|
+
};
|
|
72
|
+
// 3. Check Policy
|
|
73
|
+
const decision = await this.options.accordInstance.check(userId, this.options.action, resource);
|
|
74
|
+
// 4. Attach decision to request (useful for downstream logic)
|
|
75
|
+
req.authDecision = decision;
|
|
76
|
+
return decision.decision === 'allow';
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.error('NestJS Accord Guard Error:', error);
|
|
80
|
+
return false; // Fail safe: Deny
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
__setFunctionName(_classThis, "AccordGuard");
|
|
85
|
+
(() => {
|
|
86
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
87
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
88
|
+
AccordGuard = _classThis = _classDescriptor.value;
|
|
89
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
90
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
91
|
+
})();
|
|
92
|
+
return AccordGuard = _classThis;
|
|
93
|
+
})();
|
|
94
|
+
exports.AccordGuard = AccordGuard;
|
|
95
|
+
//# sourceMappingURL=nest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nest.js","sourceRoot":"","sources":["../../src/adapters/nest.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uBAAuB;AACvB,2CAA2E;IAkB9D,WAAW;4BADvB,IAAA,mBAAU,GAAE;;;;;QAIX,YAAY,OAA2B;YACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,OAAyB;YACzC,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,WAAW,EAAE,CAAC;YAEjD,IAAI,CAAC;gBACH,uBAAuB;gBACvB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK;oBAC/B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;oBACzB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAW,CAAC;gBAEvC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,wDAAwD;oBACxD,8CAA8C;oBAC9C,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,wBAAwB;gBACxB,MAAM,QAAQ,GAAG;oBACf,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY;oBAC/B,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE;oBACjB,UAAU,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;iBAC3B,CAAC;gBAEF,kBAAkB;gBAClB,MAAM,QAAQ,GAAa,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAChE,MAAM,EACN,IAAI,CAAC,OAAO,CAAC,MAAM,EACnB,QAAQ,CACT,CAAC;gBAEF,8DAA8D;gBAC7D,GAAW,CAAC,YAAY,GAAG,QAAQ,CAAC;gBAErC,OAAO,QAAQ,CAAC,QAAQ,KAAK,OAAO,CAAC;YACvC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;gBACnD,OAAO,KAAK,CAAC,CAAC,kBAAkB;YAClC,CAAC;QACH,CAAC;;;;;QA7CH,6KA8CC;;;QA9CY,uDAAW;;;;AAAX,kCAAW"}
|
package/dist/core/loader.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Policy } from './types';
|
|
2
2
|
/**
|
|
3
|
-
* Loads Policies from a JSON
|
|
3
|
+
* Loads Policies from a file (JSON or YAML).
|
|
4
|
+
* Validates structure using Zod.
|
|
4
5
|
*/
|
|
5
6
|
export declare function loadPolicies(filePath: string): Policy[];
|
|
6
7
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAY,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAY,MAAM,SAAS,CAAC;AAM3C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA+BvD"}
|
package/dist/core/loader.js
CHANGED
|
@@ -34,20 +34,42 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.loadPolicies = loadPolicies;
|
|
37
|
+
const validation_1 = require("./validation");
|
|
37
38
|
const fs = __importStar(require("fs"));
|
|
38
39
|
const path = __importStar(require("path"));
|
|
40
|
+
const yaml = __importStar(require("js-yaml"));
|
|
39
41
|
/**
|
|
40
|
-
* Loads Policies from a JSON
|
|
42
|
+
* Loads Policies from a file (JSON or YAML).
|
|
43
|
+
* Validates structure using Zod.
|
|
41
44
|
*/
|
|
42
45
|
function loadPolicies(filePath) {
|
|
43
46
|
try {
|
|
44
47
|
const absolutePath = path.resolve(filePath);
|
|
45
48
|
const fileContent = fs.readFileSync(absolutePath, 'utf-8');
|
|
46
|
-
|
|
49
|
+
let rawData;
|
|
50
|
+
// Detect extension and parse
|
|
51
|
+
if (filePath.endsWith('.yaml') || filePath.endsWith('.yml')) {
|
|
52
|
+
rawData = yaml.load(fileContent);
|
|
53
|
+
// Normalize to Array if YAML returns a single object (single policy in a file) -> wrapped in an array automatically.
|
|
54
|
+
if (!Array.isArray(rawData)) {
|
|
55
|
+
rawData = [rawData];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Default to JSON
|
|
60
|
+
rawData = JSON.parse(fileContent);
|
|
61
|
+
}
|
|
62
|
+
// VALIDATION STEP
|
|
63
|
+
const result = validation_1.Schemas.Policy.array().safeParse(rawData);
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
console.error('Invalid Policy Structure:', result.error.format());
|
|
66
|
+
throw new Error(`Policy validation failed for ${filePath}`);
|
|
67
|
+
}
|
|
68
|
+
return result.data; // Return validated, typed data
|
|
47
69
|
}
|
|
48
70
|
catch (error) {
|
|
49
71
|
console.error(`Failed to load policies from ${filePath}:`, error);
|
|
50
|
-
|
|
72
|
+
throw error; // Let application fail hard if config is bad.
|
|
51
73
|
}
|
|
52
74
|
}
|
|
53
75
|
//# sourceMappingURL=loader.js.map
|
package/dist/core/loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,oCA+BC;AAxCD,6CAAuC;AACvC,uCAAyB;AACzB,2CAA6B;AAC7B,8CAAgC;AAEhC;;;GAGG;AACH,SAAgB,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,OAAY,CAAC;QAEjB,6BAA6B;QAC7B,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5D,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACnC,qHAAqH;YACnH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,kBAAkB;YAClB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;QAED,kBAAkB;QAClB,MAAM,MAAM,GAAG,oBAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAEzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,+BAA+B;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;QAClE,MAAM,KAAK,CAAC,CAAC,8CAA8C;IAC7D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data shape for a single Audit Event.
|
|
3
|
+
*/
|
|
4
|
+
export interface AuditEvent {
|
|
5
|
+
timestamp: Date;
|
|
6
|
+
decision: 'allow' | 'deny';
|
|
7
|
+
policyId?: string;
|
|
8
|
+
reason?: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
action: string;
|
|
11
|
+
resourceType: string;
|
|
12
|
+
resourceId?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Interface for Audit Loggers.
|
|
16
|
+
* Allows users to implement custom loggers (e.g., send to Splunk).
|
|
17
|
+
*/
|
|
18
|
+
export interface AuditLogger {
|
|
19
|
+
log(event: AuditEvent): void | Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Console Logger: For local development.
|
|
23
|
+
* Color codes output (Green = Allow, Red = Deny).
|
|
24
|
+
*/
|
|
25
|
+
export declare class ConsoleAuditLogger implements AuditLogger {
|
|
26
|
+
log(event: AuditEvent): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* File Logger: For production/audit trails.
|
|
30
|
+
* Appends JSON lines to a file (Splunk/ELK friendly).
|
|
31
|
+
*/
|
|
32
|
+
export declare class FileAuditLogger implements AuditLogger {
|
|
33
|
+
private filePath;
|
|
34
|
+
constructor(filePath: string);
|
|
35
|
+
log(event: AuditEvent): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,WAAW;IACpD,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;CAY7B;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAI5B,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;CAS7B"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileAuditLogger = exports.ConsoleAuditLogger = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* Console Logger: For local development.
|
|
41
|
+
* Color codes output (Green = Allow, Red = Deny).
|
|
42
|
+
*/
|
|
43
|
+
class ConsoleAuditLogger {
|
|
44
|
+
log(event) {
|
|
45
|
+
const color = event.decision === 'allow' ? '\x1b[32m' : '\x1b[31m'; // Green or Red
|
|
46
|
+
const reset = '\x1b[0m';
|
|
47
|
+
const message = `${color}[${event.decision.toUpperCase()}]${reset} ${event.userId} -> ${event.action} on ${event.resourceType}${event.resourceId ? `/${event.resourceId}` : ''}`;
|
|
48
|
+
if (event.decision === 'deny') {
|
|
49
|
+
console.warn(message, `| Reason: ${event.reason}`);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log(message, `| Policy: ${event.policyId}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.ConsoleAuditLogger = ConsoleAuditLogger;
|
|
57
|
+
/**
|
|
58
|
+
* File Logger: For production/audit trails.
|
|
59
|
+
* Appends JSON lines to a file (Splunk/ELK friendly).
|
|
60
|
+
*/
|
|
61
|
+
class FileAuditLogger {
|
|
62
|
+
constructor(filePath) {
|
|
63
|
+
this.filePath = path.resolve(filePath);
|
|
64
|
+
}
|
|
65
|
+
log(event) {
|
|
66
|
+
try {
|
|
67
|
+
const logLine = JSON.stringify(event) + '\n';
|
|
68
|
+
fs.appendFileSync(this.filePath, logLine, 'utf-8');
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// Don't crash the app if logging fails, just warn
|
|
72
|
+
console.error('Failed to write audit log:', error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.FileAuditLogger = FileAuditLogger;
|
|
77
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,uCAAyB;AACzB,2CAA6B;AAwB7B;;;GAGG;AACH,MAAa,kBAAkB;IAC7B,GAAG,CAAC,KAAiB;QACnB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,eAAe;QACnF,MAAM,KAAK,GAAG,SAAS,CAAC;QAExB,MAAM,OAAO,GAAG,GAAG,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEjL,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;CACF;AAbD,gDAaC;AAED;;;GAGG;AACH,MAAa,eAAe;IAG1B,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,GAAG,CAAC,KAAiB;QACnB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;YAC7C,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kDAAkD;YAClD,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;CACF;AAhBD,0CAgBC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const Schemas: {
|
|
3
|
+
Policy: z.ZodObject<{
|
|
4
|
+
id: z.ZodString;
|
|
5
|
+
version: z.ZodString;
|
|
6
|
+
effect: z.ZodEnum<{
|
|
7
|
+
allow: "allow";
|
|
8
|
+
deny: "deny";
|
|
9
|
+
}>;
|
|
10
|
+
subject: z.ZodObject<{
|
|
11
|
+
type: z.ZodOptional<z.ZodString>;
|
|
12
|
+
id: z.ZodOptional<z.ZodString>;
|
|
13
|
+
attributes: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
action: z.ZodArray<z.ZodString>;
|
|
16
|
+
resource: z.ZodObject<{
|
|
17
|
+
type: z.ZodOptional<z.ZodString>;
|
|
18
|
+
id: z.ZodOptional<z.ZodString>;
|
|
19
|
+
attributes: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
Identity: z.ZodObject<{
|
|
24
|
+
id: z.ZodString;
|
|
25
|
+
type: z.ZodEnum<{
|
|
26
|
+
user: "user";
|
|
27
|
+
service: "service";
|
|
28
|
+
system: "system";
|
|
29
|
+
agent: "agent";
|
|
30
|
+
}>;
|
|
31
|
+
status: z.ZodEnum<{
|
|
32
|
+
active: "active";
|
|
33
|
+
suspended: "suspended";
|
|
34
|
+
revoked: "revoked";
|
|
35
|
+
}>;
|
|
36
|
+
attributes: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2CxB,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGnB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Schemas = void 0;
|
|
4
|
+
// src/core/validation.ts
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
/**
|
|
7
|
+
* Zod Schemas for Accord v1.1
|
|
8
|
+
* These ensure that config files are structurally correct before the engine runs.
|
|
9
|
+
*/
|
|
10
|
+
// Enums
|
|
11
|
+
const EffectSchema = zod_1.z.enum(['allow', 'deny']);
|
|
12
|
+
const StatusSchema = zod_1.z.enum(['active', 'suspended', 'revoked']);
|
|
13
|
+
const IdentityTypeSchema = zod_1.z.enum(['user', 'service', 'system', 'agent']);
|
|
14
|
+
// Objects
|
|
15
|
+
const ResourceSchema = zod_1.z.object({
|
|
16
|
+
type: zod_1.z.string().optional(),
|
|
17
|
+
id: zod_1.z.string().optional(),
|
|
18
|
+
attributes: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().default({}),
|
|
19
|
+
});
|
|
20
|
+
const SubjectSchema = zod_1.z.object({
|
|
21
|
+
type: zod_1.z.string().optional(),
|
|
22
|
+
id: zod_1.z.string().optional(),
|
|
23
|
+
attributes: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().default({}),
|
|
24
|
+
});
|
|
25
|
+
const PolicySchema = zod_1.z.object({
|
|
26
|
+
id: zod_1.z.string(),
|
|
27
|
+
version: zod_1.z.string(),
|
|
28
|
+
effect: EffectSchema,
|
|
29
|
+
subject: SubjectSchema,
|
|
30
|
+
action: zod_1.z.array(zod_1.z.string()),
|
|
31
|
+
resource: ResourceSchema,
|
|
32
|
+
condition: zod_1.z.string().optional(),
|
|
33
|
+
});
|
|
34
|
+
const IdentitySchema = zod_1.z.object({
|
|
35
|
+
id: zod_1.z.string(),
|
|
36
|
+
type: IdentityTypeSchema,
|
|
37
|
+
status: StatusSchema,
|
|
38
|
+
attributes: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().default({}),
|
|
39
|
+
});
|
|
40
|
+
// Export for use in Loaders
|
|
41
|
+
exports.Schemas = {
|
|
42
|
+
Policy: PolicySchema,
|
|
43
|
+
Identity: IdentitySchema,
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AACzB,6BAAwB;AAExB;;;GAGG;AAEH,QAAQ;AACR,MAAM,YAAY,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAC/C,MAAM,YAAY,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;AAChE,MAAM,kBAAkB,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1E,UAAU;AACV,MAAM,cAAc,GAAG,OAAC,CAAC,MAAM,CAAC;IAC9B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzB,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CACjE,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,OAAC,CAAC,MAAM,CAAC;IAC7B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzB,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CACjE,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5B,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,aAAa;IACtB,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,cAAc;IACxB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,OAAC,CAAC,MAAM,CAAC;IAC9B,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,YAAY;IACpB,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CACjE,CAAC,CAAC;AAEH,4BAA4B;AACf,QAAA,OAAO,GAAG;IACrB,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,cAAc;CACzB,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEhD,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEhD,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,10 +14,15 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.Accord = void 0;
|
|
17
|
+
exports.accordHook = exports.AccordGuard = exports.Accord = void 0;
|
|
18
18
|
// src/index.ts
|
|
19
19
|
var accord_1 = require("./accord");
|
|
20
20
|
Object.defineProperty(exports, "Accord", { enumerable: true, get: function () { return accord_1.Accord; } });
|
|
21
21
|
// Re-export types for convenience if needed
|
|
22
22
|
__exportStar(require("./core/types"), exports);
|
|
23
|
+
__exportStar(require("./adapters/express"), exports);
|
|
24
|
+
var nest_1 = require("./adapters/nest");
|
|
25
|
+
Object.defineProperty(exports, "AccordGuard", { enumerable: true, get: function () { return nest_1.AccordGuard; } });
|
|
26
|
+
var fastify_1 = require("./adapters/fastify");
|
|
27
|
+
Object.defineProperty(exports, "accordHook", { enumerable: true, get: function () { return fastify_1.accordHook; } });
|
|
23
28
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,eAAe;AACf,mCAAgD;AAAvC,gGAAA,MAAM,OAAA;AACf,4CAA4C;AAC5C,+CAA6B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,eAAe;AACf,mCAAgD;AAAvC,gGAAA,MAAM,OAAA;AACf,4CAA4C;AAC5C,+CAA6B;AAC7B,qDAAmC;AACnC,wCAA8C;AAArC,mGAAA,WAAW,OAAA;AACpB,8CAAgD;AAAvC,qGAAA,UAAU,OAAA"}
|
package/dist/store/identity.d.ts
CHANGED
|
@@ -24,5 +24,10 @@ export declare class IdentityStore {
|
|
|
24
24
|
* Helper to get all identities (useful for testing/debugging)
|
|
25
25
|
*/
|
|
26
26
|
getAllIdentities(): Identity[];
|
|
27
|
+
/**
|
|
28
|
+
* Reloads identities from disk.
|
|
29
|
+
* Useful if the file was edited externally.
|
|
30
|
+
*/
|
|
31
|
+
reload(): void;
|
|
27
32
|
}
|
|
28
33
|
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/store/identity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/store/identity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAkB;gBAExB,QAAQ,EAAE,MAAM;IAK5B;;OAEG;IACH,OAAO,CAAC,IAAI;IA2BZ;;OAEG;IACH,OAAO,CAAC,IAAI;IASZ;;OAEG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI7C;;;OAGG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ;IAyBhE;;OAEG;IACH,gBAAgB,IAAI,QAAQ,EAAE;IAI5B;;;KAGC;IACH,MAAM,IAAI,IAAI;CAGf"}
|
package/dist/store/identity.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.IdentityStore = void 0;
|
|
37
|
+
const validation_1 = require("../core/validation");
|
|
37
38
|
const fs = __importStar(require("fs"));
|
|
38
39
|
const path = __importStar(require("path"));
|
|
39
40
|
class IdentityStore {
|
|
@@ -49,7 +50,16 @@ class IdentityStore {
|
|
|
49
50
|
try {
|
|
50
51
|
if (fs.existsSync(this.filePath)) {
|
|
51
52
|
const fileContent = fs.readFileSync(this.filePath, 'utf-8');
|
|
52
|
-
|
|
53
|
+
const rawData = JSON.parse(fileContent);
|
|
54
|
+
// VALIDATION STEP
|
|
55
|
+
const result = validation_1.Schemas.Identity.array().safeParse(rawData);
|
|
56
|
+
if (!result.success) {
|
|
57
|
+
console.error('Invalid Identity Structure:', result.error.format());
|
|
58
|
+
// For v1, we start empty on fail to be safe, or throw.
|
|
59
|
+
// Let's throw to match enterprise behavior.
|
|
60
|
+
throw new Error(`Identity validation failed for ${this.filePath}`);
|
|
61
|
+
}
|
|
62
|
+
this.identities = result.data;
|
|
53
63
|
}
|
|
54
64
|
else {
|
|
55
65
|
this.identities = [];
|
|
@@ -110,6 +120,13 @@ class IdentityStore {
|
|
|
110
120
|
getAllIdentities() {
|
|
111
121
|
return this.identities;
|
|
112
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Reloads identities from disk.
|
|
125
|
+
* Useful if the file was edited externally.
|
|
126
|
+
*/
|
|
127
|
+
reload() {
|
|
128
|
+
this.load(); // Re-run the load logic
|
|
129
|
+
}
|
|
113
130
|
}
|
|
114
131
|
exports.IdentityStore = IdentityStore;
|
|
115
132
|
//# sourceMappingURL=identity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/store/identity.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,uCAAyB;AACzB,2CAA6B;AAE7B,MAAa,aAAa;IAIxB,YAAY,QAAgB;QAFpB,eAAU,GAAe,EAAE,CAAC;QAGlC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED;;OAEG;IACK,IAAI;QACV,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC5D,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/store/identity.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@navirondynamics/accord",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "A policy-first identity and access engine for modular systems.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -8,19 +8,38 @@
|
|
|
8
8
|
"dist",
|
|
9
9
|
"README.md"
|
|
10
10
|
],
|
|
11
|
+
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/bsen-alt/Accord.git"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/bsen-alt/Accord/issues"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/bsen-alt/Accord#readme",
|
|
20
|
+
|
|
21
|
+
|
|
11
22
|
"scripts": {
|
|
12
23
|
"test": "jest",
|
|
13
24
|
"build": "tsc",
|
|
14
25
|
"prepublishOnly": "npm run build",
|
|
15
26
|
"cli": "ts-node src/cli/index.ts"
|
|
16
27
|
},
|
|
17
|
-
"keywords": [
|
|
28
|
+
"keywords": [
|
|
29
|
+
"authorization",
|
|
30
|
+
"access-control",
|
|
31
|
+
"rbac",
|
|
32
|
+
"abac",
|
|
33
|
+
"policy"
|
|
34
|
+
],
|
|
18
35
|
"author": "",
|
|
19
36
|
"license": "ISC",
|
|
20
37
|
"type": "commonjs",
|
|
21
38
|
"devDependencies": {
|
|
39
|
+
"@nestjs/common": "^11.1.12",
|
|
22
40
|
"@types/express": "^5.0.6",
|
|
23
41
|
"@types/jest": "^30.0.0",
|
|
42
|
+
"@types/js-yaml": "^4.0.9",
|
|
24
43
|
"@types/jsonata": "^1.3.1",
|
|
25
44
|
"@types/node": "^25.0.10",
|
|
26
45
|
"@typescript-eslint/eslint-plugin": "^8.53.1",
|
|
@@ -28,13 +47,19 @@
|
|
|
28
47
|
"eslint": "^9.39.2",
|
|
29
48
|
"jest": "^30.2.0",
|
|
30
49
|
"prettier": "^3.8.1",
|
|
50
|
+
"reflect-metadata": "^0.2.2",
|
|
31
51
|
"ts-jest": "^29.4.6",
|
|
32
52
|
"ts-node": "^10.9.2",
|
|
53
|
+
"tslib": "^2.8.1",
|
|
33
54
|
"typescript": "^5.9.3"
|
|
34
55
|
},
|
|
35
56
|
"dependencies": {
|
|
57
|
+
"@nestjs/common": "^11.1.12",
|
|
36
58
|
"commander": "^14.0.2",
|
|
37
59
|
"express": "^5.2.1",
|
|
38
|
-
"
|
|
60
|
+
"fastify": "^5.7.1",
|
|
61
|
+
"js-yaml": "^4.1.1",
|
|
62
|
+
"jsonata": "^2.1.0",
|
|
63
|
+
"zod": "^4.3.6"
|
|
39
64
|
}
|
|
40
65
|
}
|