@navirondynamics/accord 1.0.0 → 1.1.0
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 +134 -28
- 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,155 @@
|
|
|
1
|
-
Accord
|
|
1
|
+
# Accord
|
|
2
2
|
|
|
3
|
-
Accord is a policy-first identity and access engine designed to unify identity representation, context resolution, and authorization under a single, declarative
|
|
3
|
+
**Accord** is a policy-first identity and access engine designed to unify identity representation, context resolution, and authorization under a single, declarative model.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It treats access not as scattered checks embedded in application code, but as a **formal agreement** between identities, systems, and resources.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 🧠 The System of Agreement
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Modern authorization is often fragmented:
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- Authentication handled in one service.
|
|
12
|
+
- Roles defined in another.
|
|
13
|
+
- Access logic scattered across codebases.
|
|
14
|
+
|
|
15
|
+
**Accord** reframes this as a governance layer. Instead of embedding `if (user.admin)` checks, Accord externalizes rules into explicit, versioned policies.
|
|
16
|
+
|
|
17
|
+
- **Explicit:** Access rules are defined before execution.
|
|
18
|
+
- **Inspectable:** Every decision returns a reason.
|
|
19
|
+
- **Centralized:** One source of truth for multiple services.
|
|
20
|
+
|
|
21
|
+
## 📦 Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @navirondynamics/accord
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 🚀 Quick Start
|
|
28
|
+
|
|
29
|
+
### 1. Define Your Configuration
|
|
30
|
+
|
|
31
|
+
Create a `config` folder in your project root.
|
|
32
|
+
|
|
33
|
+
**`config/policies.json`**
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
[
|
|
37
|
+
{
|
|
38
|
+
"id": "policy-admin",
|
|
39
|
+
"version": "1.0",
|
|
40
|
+
"effect": "allow",
|
|
41
|
+
"subject": {
|
|
42
|
+
"type": "user",
|
|
43
|
+
"attributes": { "role": "admin" }
|
|
44
|
+
},
|
|
45
|
+
"action": ["delete"],
|
|
46
|
+
"resource": { "type": "booking" }
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
```
|
|
12
50
|
|
|
13
|
-
|
|
51
|
+
**`config/identities.json`**
|
|
14
52
|
|
|
15
|
-
|
|
53
|
+
```json
|
|
54
|
+
[
|
|
55
|
+
{
|
|
56
|
+
"id": "alice",
|
|
57
|
+
"type": "user",
|
|
58
|
+
"status": "active",
|
|
59
|
+
"attributes": { "role": "admin" }
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
```
|
|
16
63
|
|
|
17
|
-
|
|
64
|
+
### 2. Use in Your Code
|
|
18
65
|
|
|
19
|
-
|
|
66
|
+
```javascript
|
|
67
|
+
const { Accord } = require('@navirondynamics/accord');
|
|
20
68
|
|
|
21
|
-
|
|
69
|
+
// 1. Initialize the Engine
|
|
70
|
+
const accord = new Accord({
|
|
71
|
+
policyPath: './config/policies.json',
|
|
72
|
+
identityPath: './config/identities.json',
|
|
73
|
+
});
|
|
22
74
|
|
|
23
|
-
|
|
75
|
+
async function deleteBooking(bookingId, userId) {
|
|
76
|
+
// 2. Check Access
|
|
77
|
+
const decision = await accord.check(userId, 'delete', {
|
|
78
|
+
type: 'booking',
|
|
79
|
+
id: bookingId,
|
|
80
|
+
});
|
|
24
81
|
|
|
25
|
-
|
|
82
|
+
// 3. Enforce Decision
|
|
83
|
+
if (decision.decision === 'allow') {
|
|
84
|
+
console.log('Access Granted');
|
|
85
|
+
// Perform delete...
|
|
86
|
+
} else {
|
|
87
|
+
console.log('Access Denied:', decision.reason);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
26
90
|
|
|
27
|
-
|
|
91
|
+
deleteBooking('b1', 'alice');
|
|
92
|
+
```
|
|
28
93
|
|
|
29
|
-
Express Middleware
|
|
30
|
-
Protect your routes easily:
|
|
94
|
+
## 🛡️ Express Middleware
|
|
31
95
|
|
|
32
|
-
|
|
96
|
+
Protect your routes without cluttering your controller logic.
|
|
33
97
|
|
|
34
|
-
|
|
98
|
+
```javascript
|
|
99
|
+
const express = require('express');
|
|
100
|
+
const { Accord } = require('@navirondynamics/accord');
|
|
101
|
+
const { protect } = require('@navirondynamics/accord/adapters/express');
|
|
35
102
|
|
|
36
|
-
|
|
103
|
+
const app = express();
|
|
104
|
+
const accord = new Accord({
|
|
105
|
+
policyPath: './config/policies.json',
|
|
106
|
+
identityPath: './config/identities.json',
|
|
107
|
+
});
|
|
37
108
|
|
|
38
|
-
|
|
39
|
-
|
|
109
|
+
// Protect this route
|
|
110
|
+
app.delete(
|
|
111
|
+
'/bookings/:id',
|
|
112
|
+
protect({
|
|
113
|
+
accordInstance: accord,
|
|
114
|
+
action: 'delete',
|
|
115
|
+
resourceType: 'booking',
|
|
116
|
+
}),
|
|
117
|
+
(req, res) => {
|
|
118
|
+
// Only allowed users reach here
|
|
119
|
+
res.send('Booking deleted');
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
app.listen(3000);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 🛠️ CLI Tool
|
|
127
|
+
|
|
128
|
+
Validate policies and test access logic from your terminal.
|
|
129
|
+
|
|
130
|
+
**Validate Configuration:**
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npx @navirondynamics/accord validate ./config/policies.json
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Dry-Run Access Check:**
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npx @navirondynamics/accord eval -i alice -a delete -r booking
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## ⚙️ Core Concepts
|
|
143
|
+
|
|
144
|
+
- **Identity:** Represents who is acting (User, Service, Agent). Includes a `status` (active/suspended) allowing for a "Kill Switch".
|
|
145
|
+
- **Resource:** Represents what is being accessed.
|
|
146
|
+
- **Policy:** The agreement linking Identity, Action, and Resource. Supports RBAC (Roles) and ABAC (Attributes).
|
|
147
|
+
- **Decision:** The output (`allow`/`deny`) including a `reason` for auditing.
|
|
148
|
+
|
|
149
|
+
## 📜 License
|
|
40
150
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Test access logic:
|
|
151
|
+
ISC
|
|
44
152
|
|
|
45
|
-
```
|
|
153
|
+
```
|
|
46
154
|
|
|
47
|
-
|
|
48
|
-
ISC
|
|
49
|
-
````
|
|
155
|
+
```
|
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.0",
|
|
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
|
}
|