@navirondynamics/accord 1.0.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.
Files changed (42) hide show
  1. package/README.md +49 -0
  2. package/dist/accord.d.ts +16 -0
  3. package/dist/accord.d.ts.map +1 -0
  4. package/dist/accord.js +48 -0
  5. package/dist/accord.js.map +1 -0
  6. package/dist/adapters/express.d.ts +14 -0
  7. package/dist/adapters/express.d.ts.map +1 -0
  8. package/dist/adapters/express.js +48 -0
  9. package/dist/adapters/express.js.map +1 -0
  10. package/dist/cli/index.d.ts +2 -0
  11. package/dist/cli/index.d.ts.map +1 -0
  12. package/dist/cli/index.js +78 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/core/compiler.d.ts +7 -0
  15. package/dist/core/compiler.d.ts.map +1 -0
  16. package/dist/core/compiler.js +31 -0
  17. package/dist/core/compiler.js.map +1 -0
  18. package/dist/core/evaluator.d.ts +6 -0
  19. package/dist/core/evaluator.d.ts.map +1 -0
  20. package/dist/core/evaluator.js +148 -0
  21. package/dist/core/evaluator.js.map +1 -0
  22. package/dist/core/loader.d.ts +6 -0
  23. package/dist/core/loader.d.ts.map +1 -0
  24. package/dist/core/loader.js +53 -0
  25. package/dist/core/loader.js.map +1 -0
  26. package/dist/core/resolver.d.ts +12 -0
  27. package/dist/core/resolver.d.ts.map +1 -0
  28. package/dist/core/resolver.js +28 -0
  29. package/dist/core/resolver.js.map +1 -0
  30. package/dist/core/types.d.ts +72 -0
  31. package/dist/core/types.d.ts.map +1 -0
  32. package/dist/core/types.js +4 -0
  33. package/dist/core/types.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +23 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/store/identity.d.ts +28 -0
  39. package/dist/store/identity.d.ts.map +1 -0
  40. package/dist/store/identity.js +115 -0
  41. package/dist/store/identity.js.map +1 -0
  42. package/package.json +40 -0
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ Accord
2
+
3
+ Accord is a policy-first identity and access engine designed to unify identity representation, context resolution, and authorization under a single, declarative policy model.
4
+
5
+ Installation
6
+
7
+ `bashnpm install accord`
8
+
9
+ Quick Start
10
+
11
+ 1. Initialize Configuration
12
+
13
+ Create a config folder in your project root.
14
+
15
+ config/policies.json`json[ { "id": "policy-admin", "version": "1.0", "effect": "allow", "subject": { "type": "user", "attributes": { "role": "admin" } }, "action": ["delete"], "resource": { "type": "booking" } }]`
16
+
17
+ config/identities.json`json[ { "id": "admin_01", "type": "user", "status": "active", "attributes": { "role": "admin" } }]`
18
+
19
+ 2. Use in Code
20
+
21
+ ````typescriptimport
22
+
23
+ const accord = new Accord({ policyPath: './config/policies.json', identityPath: './config/identities.json'});
24
+
25
+ async function deleteBooking(bookingId: string, userId: string) { const decision = await accord.check(userId, 'delete', { type: 'booking', id: bookingId });
26
+
27
+ if (decision.decision === 'allow') { console.log('Access Granted'); // Perform delete... } else { console.log('Access Denied:', decision.reason); }}```
28
+
29
+ Express Middleware
30
+ Protect your routes easily:
31
+
32
+ ```typescriptimport express from 'express';import { Accord } from 'accord';import { protect } from 'accord/adapters/express'; // Note: Check actual path after build
33
+
34
+ const app = express();const accord = new Accord({ policyPath: './config/policies.json', ... });
35
+
36
+ // Protect this routeapp.delete('/bookings/:id', protect({ accordInstance: accord, action: 'delete', resourceType: 'booking' }), (req, res) => { // Only allowed users reach here res.send('Booking deleted'); });```
37
+
38
+ CLI Tool
39
+ Validate policies locally:
40
+
41
+ ```bashnpx accord-cli validate ./config/policies.json```
42
+
43
+ Test access logic:
44
+
45
+ ```bashnpx accord-cli eval -i user_123 -a delete -r booking```
46
+
47
+ License
48
+ ISC
49
+ ````
@@ -0,0 +1,16 @@
1
+ import { IdentityStore } from './store/identity';
2
+ import { Decision } from './core/types';
3
+ export interface AccordConfig {
4
+ policyPath: string;
5
+ identityPath: string;
6
+ }
7
+ export declare class Accord {
8
+ private policies;
9
+ private identityStore;
10
+ private resolver;
11
+ private config;
12
+ constructor(config: AccordConfig);
13
+ check(externalId: string, action: string, resource: any, context?: any): Promise<Decision>;
14
+ getStore(): IdentityStore;
15
+ }
16
+ //# sourceMappingURL=accord.d.ts.map
@@ -0,0 +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;gBAEjB,MAAM,EAAE,YAAY;IAc1B,KAAK,CACT,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,GAAG,EACb,OAAO,CAAC,EAAE,GAAG,GACZ,OAAO,CAAC,QAAQ,CAAC;IAyBpB,QAAQ,IAAI,aAAa;CAG1B"}
package/dist/accord.js ADDED
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Accord = void 0;
4
+ // src/accord.ts
5
+ const loader_1 = require("./core/loader");
6
+ const compiler_1 = require("./core/compiler"); // NEW
7
+ const identity_1 = require("./store/identity");
8
+ const resolver_1 = require("./core/resolver");
9
+ const evaluator_1 = require("./core/evaluator");
10
+ class Accord {
11
+ constructor(config) {
12
+ this.config = config;
13
+ // 1. Initialize Store
14
+ this.identityStore = new identity_1.IdentityStore(config.identityPath);
15
+ // 2. Initialize Resolver
16
+ this.resolver = new resolver_1.IdentityResolver(this.identityStore);
17
+ // 3. Load and COMPILE Policies
18
+ const rawPolicies = (0, loader_1.loadPolicies)(config.policyPath);
19
+ this.policies = (0, compiler_1.compilePolicies)(rawPolicies);
20
+ }
21
+ async check(externalId, action, resource, context) {
22
+ try {
23
+ // 1. Resolve Identity
24
+ const identity = this.resolver.resolve(externalId);
25
+ // 2. Construct AccessRequest
26
+ const request = {
27
+ subject: identity,
28
+ action: action,
29
+ resource: resource,
30
+ context: context || {}
31
+ };
32
+ // 3. Evaluate
33
+ const decision = await (0, evaluator_1.evaluate)(request, this.policies);
34
+ return decision;
35
+ }
36
+ catch (error) {
37
+ return {
38
+ decision: 'deny',
39
+ reason: error.message
40
+ };
41
+ }
42
+ }
43
+ getStore() {
44
+ return this.identityStore;
45
+ }
46
+ }
47
+ exports.Accord = Accord;
48
+ //# sourceMappingURL=accord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accord.js","sourceRoot":"","sources":["../src/accord.ts"],"names":[],"mappings":";;;AAAA,gBAAgB;AAChB,0CAA6C;AAC7C,8CAAkD,CAAC,MAAM;AACzD,+CAAiD;AACjD,8CAAmD;AACnD,gDAA4C;AAQ5C,MAAa,MAAM;IAMjB,YAAY,MAAoB;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,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,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,MAAM,QAAQ,GAAG,MAAM,IAAA,oBAAQ,EAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAExD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAG,KAAe,CAAC,OAAO;aACjC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;CACF;AArDD,wBAqDC"}
@@ -0,0 +1,14 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import { Accord } from '../accord';
3
+ export interface MiddlewareOptions {
4
+ accordInstance: Accord;
5
+ action: string;
6
+ resourceType: string;
7
+ getId?: (req: Request) => string;
8
+ }
9
+ /**
10
+ * Express Middleware Factory
11
+ * Usage: app.use(protect({ accord: myAccord, action: 'delete', resourceType: 'booking' }))
12
+ */
13
+ export declare function protect(options: MiddlewareOptions): (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
14
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,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,OAAO,KAAK,MAAM,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,iBAAiB,IAClC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,6DA6C9D"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.protect = protect;
4
+ /**
5
+ * Express Middleware Factory
6
+ * Usage: app.use(protect({ accord: myAccord, action: 'delete', resourceType: 'booking' }))
7
+ */
8
+ function protect(options) {
9
+ return async (req, res, next) => {
10
+ try {
11
+ // 1. Determine User ID
12
+ // In real app, this comes from JWT (req.user.sub).
13
+ // For v1, we support a custom getter or default to req.headers['x-user-id']
14
+ const userId = options.getId
15
+ ? options.getId(req)
16
+ : req.headers['x-user-id'];
17
+ if (!userId) {
18
+ return res.status(401).json({ error: 'User ID missing' });
19
+ }
20
+ // 2. Construct Resource Object
21
+ // We extract ID from route params (e.g., /bookings/:id)
22
+ const resource = {
23
+ type: options.resourceType,
24
+ id: req.params.id,
25
+ attributes: req.body || {} // Merge body attributes for ABAC checks
26
+ };
27
+ // 3. Check Policy
28
+ const decision = await options.accordInstance.check(userId, options.action, resource);
29
+ // 4. Enforce Decision
30
+ if (decision.decision === 'allow') {
31
+ // Optional: Attach decision to request for downstream use
32
+ req.authDecision = decision;
33
+ next();
34
+ }
35
+ else {
36
+ res.status(403).json({
37
+ error: 'Access Denied',
38
+ reason: decision.reason
39
+ });
40
+ }
41
+ }
42
+ catch (error) {
43
+ console.error('Middleware Error:', error);
44
+ res.status(500).json({ error: 'Internal Server Error' });
45
+ }
46
+ };
47
+ }
48
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":";;AAiBA,0BA8CC;AAlDD;;;GAGG;AACH,SAAgB,OAAO,CAAC,OAA0B;IAChD,OAAO,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAC/D,IAAI,CAAC;YACH,uBAAuB;YACvB,oDAAoD;YACpD,4EAA4E;YAC5E,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,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;YAC5D,CAAC;YAED,+BAA+B;YAC/B,wDAAwD;YACxD,MAAM,QAAQ,GAAG;gBACf,IAAI,EAAE,OAAO,CAAC,YAAY;gBAC1B,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE;gBACjB,UAAU,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,wCAAwC;aACpE,CAAC;YAEF,kBAAkB;YAClB,MAAM,QAAQ,GAAa,MAAM,OAAO,CAAC,cAAc,CAAC,KAAK,CAC3D,MAAM,EACN,OAAO,CAAC,MAAM,EACd,QAAQ,CACT,CAAC;YAEF,sBAAsB;YACtB,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBAClC,0DAA0D;gBACzD,GAAW,CAAC,YAAY,GAAG,QAAQ,CAAC;gBACrC,IAAI,EAAE,CAAC;YACT,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,eAAe;oBACtB,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;YACL,CAAC;QAEH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;YAC1C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // src/cli/index.ts
4
+ // #!/usr/bin/env node
5
+ const commander_1 = require("commander");
6
+ const accord_1 = require("../accord");
7
+ const loader_1 = require("../core/loader");
8
+ const program = new commander_1.Command();
9
+ program
10
+ .name('accord')
11
+ .description('Accord Policy Engine CLI')
12
+ .version('1.0.0');
13
+ // ---------------------------------------------------------
14
+ // Command: validate
15
+ // Checks if a policy file is valid JSON and loadable
16
+ // ---------------------------------------------------------
17
+ program
18
+ .command('validate <file>')
19
+ .description('Validate a policy JSON file')
20
+ .action((file) => {
21
+ try {
22
+ console.log(`Validating ${file}...`);
23
+ const policies = (0, loader_1.loadPolicies)(file);
24
+ console.log(`✓ Valid! Loaded ${policies.length} policies.`);
25
+ }
26
+ catch (error) {
27
+ console.error(`✗ Validation Failed:`);
28
+ console.error(error.message);
29
+ process.exit(1);
30
+ }
31
+ });
32
+ // ---------------------------------------------------------
33
+ // Command: eval
34
+ // Dry-run an access check
35
+ // Usage: accord eval --id u1 --action delete --resource booking
36
+ // ---------------------------------------------------------
37
+ program
38
+ .command('eval')
39
+ .description('Evaluate an access request')
40
+ .requiredOption('-i, --id <userId>', 'User ID')
41
+ .requiredOption('-a, --action <action>', 'Action (e.g., delete)')
42
+ .requiredOption('-r, --resource <type>', 'Resource Type (e.g., booking)')
43
+ .option('--rid <resourceId>', 'Resource ID (optional)')
44
+ .option('-p, --policy <path>', 'Path to policies file', './config/policies.json')
45
+ .option('-u, --user <path>', 'Path to identities file', './config/identities.json')
46
+ .action(async (options) => {
47
+ try {
48
+ // 1. Initialize Accord
49
+ const accord = new accord_1.Accord({
50
+ policyPath: options.policy,
51
+ identityPath: options.user
52
+ });
53
+ // 2. Construct Resource
54
+ const resource = {
55
+ type: options.resource,
56
+ attributes: {}
57
+ };
58
+ if (options.rid) {
59
+ resource.id = options.rid;
60
+ }
61
+ console.log(`Checking if '${options.id}' can '${options.action}' on '${options.resource}'...`);
62
+ // 3. Check Access
63
+ const decision = await accord.check(options.id, options.action, resource);
64
+ // 4. Output Result
65
+ console.log(JSON.stringify(decision, null, 2));
66
+ // Exit with error code if denied (useful for CI/CD)
67
+ if (decision.decision === 'deny') {
68
+ process.exit(1);
69
+ }
70
+ }
71
+ catch (error) {
72
+ console.error(`Error: ${error.message}`);
73
+ process.exit(1);
74
+ }
75
+ });
76
+ // Parse arguments
77
+ program.parse(process.argv);
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Policy, CompiledPolicy } from './types';
2
+ /**
3
+ * Compiles policy conditions into executable functions.
4
+ * This happens ONCE at startup.
5
+ */
6
+ export declare function compilePolicies(policies: Policy[]): CompiledPolicy[];
7
+ //# sourceMappingURL=compiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/core/compiler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGjD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAmBpE"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.compilePolicies = compilePolicies;
7
+ const jsonata_1 = __importDefault(require("jsonata"));
8
+ /**
9
+ * Compiles policy conditions into executable functions.
10
+ * This happens ONCE at startup.
11
+ */
12
+ function compilePolicies(policies) {
13
+ return policies.map(policy => {
14
+ const compiled = { ...policy };
15
+ // Only compile if a condition exists
16
+ if (policy.condition) {
17
+ try {
18
+ const expression = (0, jsonata_1.default)(policy.condition);
19
+ // Store the compiled function. We evaluate it later.
20
+ compiled.compiledCondition = expression.evaluate.bind(expression);
21
+ }
22
+ catch (error) {
23
+ console.error(`Failed to compile condition for policy ${policy.id}:`, error);
24
+ // If it fails to compile, it effectively becomes "false" (Deny)
25
+ compiled.compiledCondition = () => false;
26
+ }
27
+ }
28
+ return compiled;
29
+ });
30
+ }
31
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../src/core/compiler.ts"],"names":[],"mappings":";;;;;AAQA,0CAmBC;AAzBD,sDAA8B;AAE9B;;;GAGG;AACH,SAAgB,eAAe,CAAC,QAAkB;IAChD,OAAO,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;QAC3B,MAAM,QAAQ,GAAmB,EAAE,GAAG,MAAM,EAAE,CAAC;QAE/C,qCAAqC;QACrC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,IAAA,iBAAO,EAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBAC7C,qDAAqD;gBACrD,QAAQ,CAAC,iBAAiB,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACpE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,0CAA0C,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;gBAC7E,gEAAgE;gBAChE,QAAQ,CAAC,iBAAiB,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { CompiledPolicy, AccessRequest, Decision } from './types';
2
+ /**
3
+ * MAIN ENTRY POINT: The Brain.
4
+ */
5
+ export declare function evaluate(request: AccessRequest, policies: CompiledPolicy[]): Promise<Decision>;
6
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/core/evaluator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAY,MAAM,SAAS,CAAC;AA6H5E;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyCpG"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.evaluate = evaluate;
7
+ const jsonata_1 = __importDefault(require("jsonata"));
8
+ /**
9
+ * Helper: Matches attributes between policy and request.
10
+ */
11
+ function matchesAttributes(policyAttrs, requestSubject) {
12
+ if (!policyAttrs)
13
+ return true;
14
+ for (const key in policyAttrs) {
15
+ const expectedValue = policyAttrs[key];
16
+ if (key === 'status') {
17
+ if (requestSubject.status !== expectedValue)
18
+ return false;
19
+ }
20
+ else {
21
+ if (requestSubject.attributes?.[key] !== expectedValue) {
22
+ return false;
23
+ }
24
+ }
25
+ }
26
+ return true;
27
+ }
28
+ /**
29
+ * Helper: Checks if the policy subject matches the request subject.
30
+ */
31
+ function matchesSubject(policy, request) {
32
+ const pSub = policy.subject;
33
+ const rSub = request.subject;
34
+ if (pSub.type && pSub.type !== rSub.type) {
35
+ return false;
36
+ }
37
+ if (pSub.id && pSub.id !== rSub.id) {
38
+ return false;
39
+ }
40
+ if (!matchesAttributes(pSub.attributes, rSub)) {
41
+ return false;
42
+ }
43
+ return true;
44
+ }
45
+ /**
46
+ * Helper: Checks if the policy resource matches the request resource.
47
+ */
48
+ function matchesResource(policy, request) {
49
+ const pRes = policy.resource;
50
+ const rRes = request.resource;
51
+ if (pRes.type && pRes.type !== rRes.type) {
52
+ return false;
53
+ }
54
+ if (pRes.attributes) {
55
+ for (const key in pRes.attributes) {
56
+ if (rRes.attributes[key] !== pRes.attributes[key]) {
57
+ return false;
58
+ }
59
+ }
60
+ }
61
+ return true;
62
+ }
63
+ /**
64
+ * Helper: Checks if the action is covered by the policy.
65
+ */
66
+ function matchesAction(policy, request) {
67
+ return policy.action.includes(request.action);
68
+ }
69
+ /**
70
+ * Helper: Evaluates Condition using a PRE-COMPILED function.
71
+ * Falls back to runtime compilation if no pre-compiled function exists (for unit tests).
72
+ */
73
+ async function evaluateCondition(policy, request) {
74
+ // If no condition, it passes.
75
+ if (!policy.condition)
76
+ return true;
77
+ try {
78
+ const scope = {
79
+ subject: request.subject,
80
+ resource: request.resource,
81
+ context: request.context || {}
82
+ };
83
+ // 1. Optimized Path: Use pre-compiled function (Production)
84
+ if (policy.compiledCondition) {
85
+ const result = await policy.compiledCondition(scope);
86
+ return result === true;
87
+ }
88
+ // 2. Fallback Path: Compile and run immediately (Unit Tests / Raw Data)
89
+ // This ensures unit tests using raw Policy objects still work.
90
+ else {
91
+ const expression = (0, jsonata_1.default)(policy.condition);
92
+ const result = await expression.evaluate(scope);
93
+ return result === true;
94
+ }
95
+ }
96
+ catch (error) {
97
+ console.error(`Condition evaluation error for policy ${policy.id}:`, error);
98
+ return false;
99
+ }
100
+ }
101
+ /**
102
+ * CORE FUNCTION: Evaluates a single policy against a request.
103
+ */
104
+ async function isApplicable(policy, request) {
105
+ return (matchesSubject(policy, request) &&
106
+ matchesResource(policy, request) &&
107
+ matchesAction(policy, request) &&
108
+ (await evaluateCondition(policy, request)));
109
+ }
110
+ /**
111
+ * MAIN ENTRY POINT: The Brain.
112
+ */
113
+ async function evaluate(request, policies) {
114
+ let hasMatch = false;
115
+ let deniedBy;
116
+ // 1. Scan all policies
117
+ for (const policy of policies) {
118
+ if (await isApplicable(policy, request)) {
119
+ hasMatch = true;
120
+ // 2. Conflict Resolution: Explicit Deny wins immediately
121
+ if (policy.effect === 'deny') {
122
+ return {
123
+ decision: 'deny',
124
+ policy_id: policy.id,
125
+ reason: 'Explicit deny policy matched',
126
+ };
127
+ }
128
+ }
129
+ }
130
+ // 3. Final Decision
131
+ if (hasMatch) {
132
+ const allowingPolicy = policies.find(p => p.effect === 'allow' &&
133
+ matchesSubject(p, request) &&
134
+ matchesResource(p, request) &&
135
+ matchesAction(p, request));
136
+ return {
137
+ decision: 'allow',
138
+ policy_id: allowingPolicy?.id,
139
+ reason: 'Allowed by matching policy',
140
+ };
141
+ }
142
+ // 4. Default Deny
143
+ return {
144
+ decision: 'deny',
145
+ reason: 'No matching policy found (Default Deny)',
146
+ };
147
+ }
148
+ //# sourceMappingURL=evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../src/core/evaluator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Policy } from './types';
2
+ /**
3
+ * Loads Policies from a JSON file.
4
+ */
5
+ export declare function loadPolicies(filePath: string): Policy[];
6
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAY,MAAM,SAAS,CAAC;AAI3C;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CASvD"}
@@ -0,0 +1,53 @@
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.loadPolicies = loadPolicies;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Loads Policies from a JSON file.
41
+ */
42
+ function loadPolicies(filePath) {
43
+ try {
44
+ const absolutePath = path.resolve(filePath);
45
+ const fileContent = fs.readFileSync(absolutePath, 'utf-8');
46
+ return JSON.parse(fileContent);
47
+ }
48
+ catch (error) {
49
+ console.error(`Failed to load policies from ${filePath}:`, error);
50
+ return []; // Return empty array on failure to be safe
51
+ }
52
+ }
53
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,oCASC;AAfD,uCAAyB;AACzB,2CAA6B;AAE7B;;GAEG;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,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;QAClE,OAAO,EAAE,CAAC,CAAC,2CAA2C;IACxD,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Identity } from './types';
2
+ import { IdentityStore } from '../store/identity';
3
+ export declare class IdentityResolver {
4
+ private store;
5
+ constructor(identityStore: IdentityStore);
6
+ /**
7
+ * Resolves an external ID to an Internal Identity.
8
+ * This is the "Bridge" logic.
9
+ */
10
+ resolve(externalId: string): Identity;
11
+ }
12
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAgB;gBAEjB,aAAa,EAAE,aAAa;IAIxC;;;OAGG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ;CAiBtC"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IdentityResolver = void 0;
4
+ class IdentityResolver {
5
+ constructor(identityStore) {
6
+ this.store = identityStore;
7
+ }
8
+ /**
9
+ * Resolves an external ID to an Internal Identity.
10
+ * This is the "Bridge" logic.
11
+ */
12
+ resolve(externalId) {
13
+ const identity = this.store.getIdentity(externalId);
14
+ if (!identity) {
15
+ // In a real app, you might auto-provision here (Shadow Identity).
16
+ // For v1, we strictly require the user to exist in the DB.
17
+ throw new Error(`Identity not found for ID: ${externalId}`);
18
+ }
19
+ // ENFORCEMENT: The "Kill Switch"
20
+ // Even if the token is valid, if internal status is suspended, access is denied.
21
+ if (identity.status !== 'active') {
22
+ throw new Error(`Identity ${externalId} is ${identity.status}. Access denied.`);
23
+ }
24
+ return identity;
25
+ }
26
+ }
27
+ exports.IdentityResolver = IdentityResolver;
28
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":";;;AAIA,MAAa,gBAAgB;IAG3B,YAAY,aAA4B;QACtC,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,UAAkB;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAEpD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,kEAAkE;YAClE,2DAA2D;YAC3D,MAAM,IAAI,KAAK,CAAC,8BAA8B,UAAU,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,iCAAiC;QACjC,iFAAiF;QACjF,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,YAAY,UAAU,OAAO,QAAQ,CAAC,MAAM,kBAAkB,CAAC,CAAC;QAClF,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AA5BD,4CA4BC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * The fundamental primitive: Who is acting?
3
+ * In Accord v1, this is the Internal Identity profile.
4
+ */
5
+ export interface Identity {
6
+ id: string;
7
+ type: 'user' | 'service' | 'system' | 'agent';
8
+ status: 'active' | 'suspended' | 'revoked';
9
+ attributes: Record<string, any>;
10
+ }
11
+ /**
12
+ * The fundamental primitive: What is being acted upon?
13
+ */
14
+ export interface Resource {
15
+ type: string;
16
+ id?: string;
17
+ attributes: Record<string, any>;
18
+ }
19
+ /**
20
+ * The fundamental primitive: What is happening?
21
+ * Verb-based, not permission-based.
22
+ */
23
+ export type Action = string | string[];
24
+ /**
25
+ * The fundamental primitive: The situation.
26
+ * Runtime context like Tenant, Time, IP, etc.
27
+ */
28
+ export type Context = Record<string, any>;
29
+ /**
30
+ * Policy Definition (APL v1)
31
+ */
32
+ export interface Policy {
33
+ id: string;
34
+ version: string;
35
+ effect: 'allow' | 'deny';
36
+ subject: {
37
+ type?: string;
38
+ id?: string;
39
+ attributes?: Record<string, any>;
40
+ };
41
+ action: string[];
42
+ resource: {
43
+ type?: string;
44
+ attributes?: Record<string, any>;
45
+ };
46
+ condition?: string;
47
+ }
48
+ /**
49
+ * A Policy with a pre-compiled expression function.
50
+ * Used internally by Accord for performance.
51
+ */
52
+ export interface CompiledPolicy extends Policy {
53
+ compiledCondition?: ((scope: any) => any);
54
+ }
55
+ /**
56
+ * The Input Request for the Evaluation Engine
57
+ */
58
+ export interface AccessRequest {
59
+ subject: Identity;
60
+ action: string;
61
+ resource: Resource;
62
+ context?: Context;
63
+ }
64
+ /**
65
+ * The Output Decision
66
+ */
67
+ export interface Decision {
68
+ decision: 'allow' | 'deny';
69
+ policy_id?: string;
70
+ reason?: string;
71
+ }
72
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC9C,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAEvC;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;IAGzB,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAClC,CAAC;IAGF,MAAM,EAAE,MAAM,EAAE,CAAC;IAGjB,QAAQ,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAClC,CAAC;IAGF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAe,SAAQ,MAAM;IAC5C,iBAAiB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // src/core/types.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":";AAAA,oBAAoB"}
@@ -0,0 +1,3 @@
1
+ export { Accord, AccordConfig } from './accord';
2
+ export * from './core/types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Accord = void 0;
18
+ // src/index.ts
19
+ var accord_1 = require("./accord");
20
+ Object.defineProperty(exports, "Accord", { enumerable: true, get: function () { return accord_1.Accord; } });
21
+ // Re-export types for convenience if needed
22
+ __exportStar(require("./core/types"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"}
@@ -0,0 +1,28 @@
1
+ import { Identity } from '../core/types';
2
+ export declare class IdentityStore {
3
+ private filePath;
4
+ private identities;
5
+ constructor(filePath: string);
6
+ /**
7
+ * Loads identities from the JSON file into memory.
8
+ */
9
+ private load;
10
+ /**
11
+ * Saves the current in-memory identities back to the JSON file.
12
+ */
13
+ private save;
14
+ /**
15
+ * Retrieves an identity by ID.
16
+ */
17
+ getIdentity(id: string): Identity | undefined;
18
+ /**
19
+ * Updates attributes (including status) of a specific identity.
20
+ * If the identity doesn't exist, it can optionally create one (not implemented for v1 safety).
21
+ */
22
+ updateIdentity(id: string, updates: Partial<Identity>): Identity;
23
+ /**
24
+ * Helper to get all identities (useful for testing/debugging)
25
+ */
26
+ getAllIdentities(): Identity[];
27
+ }
28
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/store/identity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAkB;gBAExB,QAAQ,EAAE,MAAM;IAK5B;;OAEG;IACH,OAAO,CAAC,IAAI;IAeZ;;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;CAG/B"}
@@ -0,0 +1,115 @@
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.IdentityStore = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ class IdentityStore {
40
+ constructor(filePath) {
41
+ this.identities = [];
42
+ this.filePath = path.resolve(filePath);
43
+ this.load();
44
+ }
45
+ /**
46
+ * Loads identities from the JSON file into memory.
47
+ */
48
+ load() {
49
+ try {
50
+ if (fs.existsSync(this.filePath)) {
51
+ const fileContent = fs.readFileSync(this.filePath, 'utf-8');
52
+ this.identities = JSON.parse(fileContent);
53
+ }
54
+ else {
55
+ this.identities = [];
56
+ console.warn(`Identity file not found at ${this.filePath}, starting empty.`);
57
+ }
58
+ }
59
+ catch (error) {
60
+ console.error('Failed to load identities:', error);
61
+ this.identities = [];
62
+ }
63
+ }
64
+ /**
65
+ * Saves the current in-memory identities back to the JSON file.
66
+ */
67
+ save() {
68
+ try {
69
+ fs.writeFileSync(this.filePath, JSON.stringify(this.identities, null, 2), 'utf-8');
70
+ }
71
+ catch (error) {
72
+ console.error('Failed to save identities:', error);
73
+ throw new Error('Could not write to identity store');
74
+ }
75
+ }
76
+ /**
77
+ * Retrieves an identity by ID.
78
+ */
79
+ getIdentity(id) {
80
+ return this.identities.find(ident => ident.id === id);
81
+ }
82
+ /**
83
+ * Updates attributes (including status) of a specific identity.
84
+ * If the identity doesn't exist, it can optionally create one (not implemented for v1 safety).
85
+ */
86
+ updateIdentity(id, updates) {
87
+ const index = this.identities.findIndex(ident => ident.id === id);
88
+ if (index === -1) {
89
+ throw new Error(`Identity with ID ${id} not found.`);
90
+ }
91
+ // Merge updates (shallow merge for simplicity in v1)
92
+ // We specifically handle 'attributes' merging so we don't overwrite the whole attributes object
93
+ const current = this.identities[index];
94
+ if (updates.attributes) {
95
+ this.identities[index] = {
96
+ ...current,
97
+ ...updates,
98
+ attributes: { ...current.attributes, ...updates.attributes }
99
+ };
100
+ }
101
+ else {
102
+ this.identities[index] = { ...current, ...updates };
103
+ }
104
+ this.save(); // Persist to disk
105
+ return this.identities[index];
106
+ }
107
+ /**
108
+ * Helper to get all identities (useful for testing/debugging)
109
+ */
110
+ getAllIdentities() {
111
+ return this.identities;
112
+ }
113
+ }
114
+ exports.IdentityStore = IdentityStore;
115
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +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,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;gBACrB,OAAO,CAAC,IAAI,CAAC,8BAA8B,IAAI,CAAC,QAAQ,mBAAmB,CAAC,CAAC;YAC/E,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACnD,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,IAAI;QACV,IAAI,CAAC;YACH,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,EAAU,EAAE,OAA0B;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAElE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,EAAE,aAAa,CAAC,CAAC;QACvD,CAAC;QAED,qDAAqD;QACrD,gGAAgG;QAChG,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAEvC,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG;gBACvB,GAAG,OAAO;gBACV,GAAG,OAAO;gBACV,UAAU,EAAE,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE;aAC7D,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,kBAAkB;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF;AAjFD,sCAiFC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@navirondynamics/accord",
3
+ "version": "1.0.0",
4
+ "description": "A policy-first identity and access engine for modular systems.",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "test": "jest",
13
+ "build": "tsc",
14
+ "prepublishOnly": "npm run build",
15
+ "cli": "ts-node src/cli/index.ts"
16
+ },
17
+ "keywords": ["authorization", "access-control", "rbac", "abac", "policy"],
18
+ "author": "",
19
+ "license": "ISC",
20
+ "type": "commonjs",
21
+ "devDependencies": {
22
+ "@types/express": "^5.0.6",
23
+ "@types/jest": "^30.0.0",
24
+ "@types/jsonata": "^1.3.1",
25
+ "@types/node": "^25.0.10",
26
+ "@typescript-eslint/eslint-plugin": "^8.53.1",
27
+ "@typescript-eslint/parser": "^8.53.1",
28
+ "eslint": "^9.39.2",
29
+ "jest": "^30.2.0",
30
+ "prettier": "^3.8.1",
31
+ "ts-jest": "^29.4.6",
32
+ "ts-node": "^10.9.2",
33
+ "typescript": "^5.9.3"
34
+ },
35
+ "dependencies": {
36
+ "commander": "^14.0.2",
37
+ "express": "^5.2.1",
38
+ "jsonata": "^2.1.0"
39
+ }
40
+ }