@atlasauth/emulator-core 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/LICENSE +21 -0
  2. package/dist/custom-html.d.ts +57 -0
  3. package/dist/custom-html.js +491 -0
  4. package/dist/custom-html.js.map +1 -0
  5. package/dist/engine.d.ts +1 -1
  6. package/dist/engine.js +5 -1
  7. package/dist/engine.js.map +1 -1
  8. package/dist/error-catalog.js +8 -0
  9. package/dist/error-catalog.js.map +1 -1
  10. package/dist/event-gate.js +60 -2
  11. package/dist/event-gate.js.map +1 -1
  12. package/dist/generic.js +5 -1
  13. package/dist/generic.js.map +1 -1
  14. package/dist/handlers/access-signals.d.ts +48 -0
  15. package/dist/handlers/access-signals.js +76 -0
  16. package/dist/handlers/access-signals.js.map +1 -0
  17. package/dist/handlers/approvals.js +54 -1
  18. package/dist/handlers/approvals.js.map +1 -1
  19. package/dist/handlers/authz-data.d.ts +2 -0
  20. package/dist/handlers/authz-data.js +627 -0
  21. package/dist/handlers/authz-data.js.map +1 -0
  22. package/dist/handlers/authz-layers.d.ts +229 -0
  23. package/dist/handlers/authz-layers.js +786 -0
  24. package/dist/handlers/authz-layers.js.map +1 -0
  25. package/dist/handlers/authz-state.d.ts +80 -0
  26. package/dist/handlers/authz-state.js +175 -0
  27. package/dist/handlers/authz-state.js.map +1 -0
  28. package/dist/handlers/authz.js +240 -177
  29. package/dist/handlers/authz.js.map +1 -1
  30. package/dist/handlers/billing.d.ts +99 -1
  31. package/dist/handlers/billing.js +556 -77
  32. package/dist/handlers/billing.js.map +1 -1
  33. package/dist/handlers/cedar-ext.d.ts +35 -0
  34. package/dist/handlers/cedar-ext.js +174 -0
  35. package/dist/handlers/cedar-ext.js.map +1 -0
  36. package/dist/handlers/cedar.d.ts +146 -0
  37. package/dist/handlers/cedar.js +689 -0
  38. package/dist/handlers/cedar.js.map +1 -0
  39. package/dist/handlers/connections.d.ts +4 -1
  40. package/dist/handlers/connections.js +267 -38
  41. package/dist/handlers/connections.js.map +1 -1
  42. package/dist/handlers/control.js +6 -1
  43. package/dist/handlers/control.js.map +1 -1
  44. package/dist/handlers/device.js +18 -1
  45. package/dist/handlers/device.js.map +1 -1
  46. package/dist/handlers/emu3-misc.d.ts +38 -0
  47. package/dist/handlers/emu3-misc.js +1056 -0
  48. package/dist/handlers/emu3-misc.js.map +1 -0
  49. package/dist/handlers/emu4-actions-access.d.ts +46 -0
  50. package/dist/handlers/emu4-actions-access.js +107 -0
  51. package/dist/handlers/emu4-actions-access.js.map +1 -0
  52. package/dist/handlers/emu4-actions-catalog-extra.d.ts +3 -0
  53. package/dist/handlers/emu4-actions-catalog-extra.js +204 -0
  54. package/dist/handlers/emu4-actions-catalog-extra.js.map +1 -0
  55. package/dist/handlers/emu4-actions-catalog.d.ts +3 -0
  56. package/dist/handlers/emu4-actions-catalog.js +143 -0
  57. package/dist/handlers/emu4-actions-catalog.js.map +1 -0
  58. package/dist/handlers/emu4-actions-def.d.ts +50 -0
  59. package/dist/handlers/emu4-actions-def.js +250 -0
  60. package/dist/handlers/emu4-actions-def.js.map +1 -0
  61. package/dist/handlers/emu4-actions-sandbox.d.ts +36 -0
  62. package/dist/handlers/emu4-actions-sandbox.js +318 -0
  63. package/dist/handlers/emu4-actions-sandbox.js.map +1 -0
  64. package/dist/handlers/emu4-actions-typegen.d.ts +5 -0
  65. package/dist/handlers/emu4-actions-typegen.js +73 -0
  66. package/dist/handlers/emu4-actions-typegen.js.map +1 -0
  67. package/dist/handlers/emu4-actions.d.ts +2 -0
  68. package/dist/handlers/emu4-actions.js +506 -0
  69. package/dist/handlers/emu4-actions.js.map +1 -0
  70. package/dist/handlers/emu4-authz-trust.d.ts +40 -0
  71. package/dist/handlers/emu4-authz-trust.js +488 -0
  72. package/dist/handlers/emu4-authz-trust.js.map +1 -0
  73. package/dist/handlers/emu4-authz.d.ts +2 -0
  74. package/dist/handlers/emu4-authz.js +752 -0
  75. package/dist/handlers/emu4-authz.js.map +1 -0
  76. package/dist/handlers/emu4-billing-core.d.ts +23 -0
  77. package/dist/handlers/emu4-billing-core.js +22 -0
  78. package/dist/handlers/emu4-billing-core.js.map +1 -0
  79. package/dist/handlers/emu4-billing-x.d.ts +2 -0
  80. package/dist/handlers/emu4-billing-x.js +489 -0
  81. package/dist/handlers/emu4-billing-x.js.map +1 -0
  82. package/dist/handlers/emu4-billing.d.ts +14 -0
  83. package/dist/handlers/emu4-billing.js +846 -0
  84. package/dist/handlers/emu4-billing.js.map +1 -0
  85. package/dist/handlers/emu4-clones.d.ts +2 -0
  86. package/dist/handlers/emu4-clones.js +322 -0
  87. package/dist/handlers/emu4-clones.js.map +1 -0
  88. package/dist/handlers/emu4-compliance.d.ts +8 -0
  89. package/dist/handlers/emu4-compliance.js +39 -0
  90. package/dist/handlers/emu4-compliance.js.map +1 -0
  91. package/dist/handlers/emu4-config.d.ts +14 -0
  92. package/dist/handlers/emu4-config.js +148 -0
  93. package/dist/handlers/emu4-config.js.map +1 -0
  94. package/dist/handlers/emu4-cookies.d.ts +8 -0
  95. package/dist/handlers/emu4-cookies.js +248 -0
  96. package/dist/handlers/emu4-cookies.js.map +1 -0
  97. package/dist/handlers/emu4-erasure.d.ts +2 -0
  98. package/dist/handlers/emu4-erasure.js +587 -0
  99. package/dist/handlers/emu4-erasure.js.map +1 -0
  100. package/dist/handlers/emu4-federation.d.ts +8 -0
  101. package/dist/handlers/emu4-federation.js +18 -0
  102. package/dist/handlers/emu4-federation.js.map +1 -0
  103. package/dist/handlers/emu4-journey-math.d.ts +42 -0
  104. package/dist/handlers/emu4-journey-math.js +99 -0
  105. package/dist/handlers/emu4-journey-math.js.map +1 -0
  106. package/dist/handlers/emu4-messaging.d.ts +21 -0
  107. package/dist/handlers/emu4-messaging.js +595 -0
  108. package/dist/handlers/emu4-messaging.js.map +1 -0
  109. package/dist/handlers/emu4-minors.d.ts +7 -0
  110. package/dist/handlers/emu4-minors.js +408 -0
  111. package/dist/handlers/emu4-minors.js.map +1 -0
  112. package/dist/handlers/emu4-oauth-audit.d.ts +5 -0
  113. package/dist/handlers/emu4-oauth-audit.js +17 -0
  114. package/dist/handlers/emu4-oauth-audit.js.map +1 -0
  115. package/dist/handlers/emu4-oauth-auth.d.ts +83 -0
  116. package/dist/handlers/emu4-oauth-auth.js +363 -0
  117. package/dist/handlers/emu4-oauth-auth.js.map +1 -0
  118. package/dist/handlers/emu4-oauth-delivery.d.ts +68 -0
  119. package/dist/handlers/emu4-oauth-delivery.js +207 -0
  120. package/dist/handlers/emu4-oauth-delivery.js.map +1 -0
  121. package/dist/handlers/emu4-oauth-keys.d.ts +11 -0
  122. package/dist/handlers/emu4-oauth-keys.js +268 -0
  123. package/dist/handlers/emu4-oauth-keys.js.map +1 -0
  124. package/dist/handlers/emu4-oauth-pub.d.ts +36 -0
  125. package/dist/handlers/emu4-oauth-pub.js +420 -0
  126. package/dist/handlers/emu4-oauth-pub.js.map +1 -0
  127. package/dist/handlers/emu4-oauth.d.ts +10 -0
  128. package/dist/handlers/emu4-oauth.js +23 -0
  129. package/dist/handlers/emu4-oauth.js.map +1 -0
  130. package/dist/handlers/emu4-policies.d.ts +2 -0
  131. package/dist/handlers/emu4-policies.js +408 -0
  132. package/dist/handlers/emu4-policies.js.map +1 -0
  133. package/dist/handlers/emu4-region.d.ts +2 -0
  134. package/dist/handlers/emu4-region.js +189 -0
  135. package/dist/handlers/emu4-region.js.map +1 -0
  136. package/dist/handlers/emu4-saml.d.ts +12 -0
  137. package/dist/handlers/emu4-saml.js +532 -0
  138. package/dist/handlers/emu4-saml.js.map +1 -0
  139. package/dist/handlers/emu4-shared.d.ts +44 -0
  140. package/dist/handlers/emu4-shared.js +90 -0
  141. package/dist/handlers/emu4-shared.js.map +1 -0
  142. package/dist/handlers/emu4-snapshots.d.ts +38 -0
  143. package/dist/handlers/emu4-snapshots.js +231 -0
  144. package/dist/handlers/emu4-snapshots.js.map +1 -0
  145. package/dist/handlers/emu4-sns.d.ts +9 -0
  146. package/dist/handlers/emu4-sns.js +21 -0
  147. package/dist/handlers/emu4-sns.js.map +1 -0
  148. package/dist/handlers/emu4-trust-binding.d.ts +27 -0
  149. package/dist/handlers/emu4-trust-binding.js +344 -0
  150. package/dist/handlers/emu4-trust-binding.js.map +1 -0
  151. package/dist/handlers/emu4-trust.d.ts +35 -0
  152. package/dist/handlers/emu4-trust.js +543 -0
  153. package/dist/handlers/emu4-trust.js.map +1 -0
  154. package/dist/handlers/fga-engine.d.ts +78 -0
  155. package/dist/handlers/fga-engine.js +663 -0
  156. package/dist/handlers/fga-engine.js.map +1 -0
  157. package/dist/handlers/governance.js +3 -2
  158. package/dist/handlers/governance.js.map +1 -1
  159. package/dist/handlers/hooks.js +13 -0
  160. package/dist/handlers/hooks.js.map +1 -1
  161. package/dist/handlers/index.js +14 -1
  162. package/dist/handlers/index.js.map +1 -1
  163. package/dist/handlers/machines.js +6 -0
  164. package/dist/handlers/machines.js.map +1 -1
  165. package/dist/handlers/messaging.d.ts +3 -1
  166. package/dist/handlers/messaging.js +455 -48
  167. package/dist/handlers/messaging.js.map +1 -1
  168. package/dist/handlers/oauth-adv.d.ts +191 -0
  169. package/dist/handlers/oauth-adv.js +1305 -0
  170. package/dist/handlers/oauth-adv.js.map +1 -0
  171. package/dist/handlers/oauth-flows.d.ts +25 -1
  172. package/dist/handlers/oauth-flows.js +111 -50
  173. package/dist/handlers/oauth-flows.js.map +1 -1
  174. package/dist/handlers/oauth.d.ts +24 -3
  175. package/dist/handlers/oauth.js +245 -60
  176. package/dist/handlers/oauth.js.map +1 -1
  177. package/dist/handlers/orgs.js +6 -0
  178. package/dist/handlers/orgs.js.map +1 -1
  179. package/dist/handlers/platform.d.ts +5 -0
  180. package/dist/handlers/platform.js +33 -15
  181. package/dist/handlers/platform.js.map +1 -1
  182. package/dist/handlers/scim.d.ts +2 -0
  183. package/dist/handlers/scim.js +198 -11
  184. package/dist/handlers/scim.js.map +1 -1
  185. package/dist/handlers/sessions.d.ts +2 -0
  186. package/dist/handlers/sessions.js +24 -16
  187. package/dist/handlers/sessions.js.map +1 -1
  188. package/dist/handlers/users.js +3 -0
  189. package/dist/handlers/users.js.map +1 -1
  190. package/dist/jwe.d.ts +18 -0
  191. package/dist/jwe.js +101 -0
  192. package/dist/jwe.js.map +1 -0
  193. package/dist/jws.js +2 -0
  194. package/dist/jws.js.map +1 -1
  195. package/dist/messaging-callbacks.d.ts +100 -0
  196. package/dist/messaging-callbacks.js +767 -0
  197. package/dist/messaging-callbacks.js.map +1 -0
  198. package/dist/openapi.d.ts +1 -0
  199. package/dist/openapi.js +44 -2
  200. package/dist/openapi.js.map +1 -1
  201. package/dist/parity-emu3-authz.d.ts +3 -0
  202. package/dist/parity-emu3-authz.js +61 -0
  203. package/dist/parity-emu3-authz.js.map +1 -0
  204. package/dist/parity-emu3-billing.d.ts +3 -0
  205. package/dist/parity-emu3-billing.js +25 -0
  206. package/dist/parity-emu3-billing.js.map +1 -0
  207. package/dist/parity-emu3-messaging.d.ts +3 -0
  208. package/dist/parity-emu3-messaging.js +27 -0
  209. package/dist/parity-emu3-messaging.js.map +1 -0
  210. package/dist/parity-emu3-misc.d.ts +2 -0
  211. package/dist/parity-emu3-misc.js +63 -0
  212. package/dist/parity-emu3-misc.js.map +1 -0
  213. package/dist/parity-emu3-oauth.d.ts +2 -0
  214. package/dist/parity-emu3-oauth.js +39 -0
  215. package/dist/parity-emu3-oauth.js.map +1 -0
  216. package/dist/parity-emu4-actions.d.ts +2 -0
  217. package/dist/parity-emu4-actions.js +38 -0
  218. package/dist/parity-emu4-actions.js.map +1 -0
  219. package/dist/parity-emu4-authz.d.ts +3 -0
  220. package/dist/parity-emu4-authz.js +68 -0
  221. package/dist/parity-emu4-authz.js.map +1 -0
  222. package/dist/parity-emu4-billing.d.ts +6 -0
  223. package/dist/parity-emu4-billing.js +44 -0
  224. package/dist/parity-emu4-billing.js.map +1 -0
  225. package/dist/parity-emu4-compliance.d.ts +2 -0
  226. package/dist/parity-emu4-compliance.js +92 -0
  227. package/dist/parity-emu4-compliance.js.map +1 -0
  228. package/dist/parity-emu4-federation.d.ts +2 -0
  229. package/dist/parity-emu4-federation.js +33 -0
  230. package/dist/parity-emu4-federation.js.map +1 -0
  231. package/dist/parity-emu4-messaging.d.ts +3 -0
  232. package/dist/parity-emu4-messaging.js +42 -0
  233. package/dist/parity-emu4-messaging.js.map +1 -0
  234. package/dist/parity-emu4-oauth.d.ts +2 -0
  235. package/dist/parity-emu4-oauth.js +55 -0
  236. package/dist/parity-emu4-oauth.js.map +1 -0
  237. package/dist/parity-emu4-trust.d.ts +2 -0
  238. package/dist/parity-emu4-trust.js +41 -0
  239. package/dist/parity-emu4-trust.js.map +1 -0
  240. package/dist/parity-routes.js +19 -1
  241. package/dist/parity-routes.js.map +1 -1
  242. package/dist/sns-cert.d.ts +9 -0
  243. package/dist/sns-cert.js +101 -0
  244. package/dist/sns-cert.js.map +1 -0
  245. package/dist/tokens.d.ts +69 -4
  246. package/dist/tokens.js +164 -38
  247. package/dist/tokens.js.map +1 -1
  248. package/package.json +2 -2
@@ -0,0 +1,689 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cedarTemplateSlots = exports.CedarLinkError = exports.CedarParseError = void 0;
4
+ exports.parseCedar = parseCedar;
5
+ exports.parseCedarTemplate = parseCedarTemplate;
6
+ exports.linkCedarTemplate = linkCedarTemplate;
7
+ exports.traceCedar = traceCedar;
8
+ exports.decideCedar = decideCedar;
9
+ /* eslint-disable @typescript-eslint/no-explicit-any */
10
+ /**
11
+ * A small Cedar-subset evaluator for the emulator's ABAC layer.
12
+ *
13
+ * shortcut: supports permit/forbid; `@annotations` (ignored); scope constraints `==`, `in` (entity or list) and `is`
14
+ * on principal, action and resource; `when` / `unless` clauses; `&& || !`, `== != < <= > >=`, `in`, `has`, `like`
15
+ * (`*` wildcard), `is`, `+ - *`, `if/then/else`, `.attr` and `["attr"]` access, set and record literals and the
16
+ * `contains` / `containsAll` / `containsAny` methods, policy templates (`?principal` / `?resource` slots, linked with
17
+ * `linkCedarTemplate`) and the `decimal()` / `ip()` extension types with their methods. No `fga.check(...)`: a policy that
18
+ * uses it does not parse and is skipped, like any unparseable policy. No schema validation.
19
+ * Upgrade by running the real engine if you need the full language.
20
+ */
21
+ const cedar_ext_1 = require("./cedar-ext");
22
+ class CedarParseError extends Error {
23
+ position;
24
+ constructor(message, position) {
25
+ super(message);
26
+ this.position = position;
27
+ }
28
+ }
29
+ exports.CedarParseError = CedarParseError;
30
+ class EvalError extends Error {
31
+ }
32
+ function lex(src) {
33
+ const out = [];
34
+ let i = 0;
35
+ while (i < src.length) {
36
+ const c = src[i];
37
+ if (/\s/.test(c))
38
+ i++;
39
+ else if (c === '/' && src[i + 1] === '/')
40
+ while (i < src.length && src[i] !== '\n')
41
+ i++;
42
+ else if (c === '"') {
43
+ let j = i + 1;
44
+ let v = '';
45
+ while (j < src.length && src[j] !== '"') {
46
+ if (src[j] === '\\') {
47
+ const n = src[j + 1];
48
+ v += n === 'n' ? '\n' : n === 't' ? '\t' : n === '0' ? '\0' : n === '*' ? '\\*' : (n ?? '');
49
+ j += 2;
50
+ }
51
+ else
52
+ v += src[j++];
53
+ }
54
+ if (j >= src.length)
55
+ throw new CedarParseError('Unterminated string.', i);
56
+ out.push({ t: 'str', v, pos: i });
57
+ i = j + 1;
58
+ }
59
+ else if (/[A-Za-z_]/.test(c)) {
60
+ let j = i;
61
+ while (j < src.length && /[A-Za-z0-9_]/.test(src[j]))
62
+ j++;
63
+ out.push({ t: 'id', v: src.slice(i, j), pos: i });
64
+ i = j;
65
+ }
66
+ else if (/[0-9]/.test(c)) {
67
+ let j = i;
68
+ while (j < src.length && /[0-9]/.test(src[j]))
69
+ j++;
70
+ out.push({ t: 'int', v: src.slice(i, j), pos: i });
71
+ i = j;
72
+ }
73
+ else {
74
+ const two = src.slice(i, i + 2);
75
+ if (['::', '==', '!=', '<=', '>=', '&&', '||'].includes(two)) {
76
+ out.push({ t: 'p', v: two, pos: i });
77
+ i += 2;
78
+ }
79
+ else if ('(){}[],;.<>!@:+-*?'.includes(c)) {
80
+ out.push({ t: 'p', v: c, pos: i });
81
+ i++;
82
+ }
83
+ else
84
+ throw new CedarParseError(`Unexpected character "${c}".`, i);
85
+ }
86
+ }
87
+ out.push({ t: 'eof', v: '', pos: src.length });
88
+ return out;
89
+ }
90
+ class Parser {
91
+ toks;
92
+ templates;
93
+ i = 0;
94
+ constructor(toks, templates = false) {
95
+ this.toks = toks;
96
+ this.templates = templates;
97
+ }
98
+ get cur() {
99
+ return this.toks[this.i];
100
+ }
101
+ is(v) {
102
+ return this.cur.t !== 'str' && this.cur.v === v && this.cur.t !== 'eof';
103
+ }
104
+ // Read the current token fresh: `cur` is a getter, so TS would otherwise keep an earlier narrowing after tokens are consumed.
105
+ isId(v) {
106
+ const c = this.cur;
107
+ return c.t === 'id' && c.v === v;
108
+ }
109
+ isStr() {
110
+ return this.cur.t === 'str';
111
+ }
112
+ eat(v) {
113
+ if (!this.is(v))
114
+ return false;
115
+ this.i++;
116
+ return true;
117
+ }
118
+ need(v) {
119
+ if (!this.eat(v))
120
+ throw new CedarParseError(`Expected "${v}".`, this.cur.pos);
121
+ }
122
+ ident() {
123
+ if (this.cur.t !== 'id')
124
+ throw new CedarParseError('Expected a name.', this.cur.pos);
125
+ return this.toks[this.i++].v;
126
+ }
127
+ str() {
128
+ if (this.cur.t !== 'str')
129
+ throw new CedarParseError('Expected a string.', this.cur.pos);
130
+ return this.toks[this.i++].v;
131
+ }
132
+ policies() {
133
+ const out = [];
134
+ while (this.cur.t !== 'eof')
135
+ out.push(this.policy());
136
+ return out;
137
+ }
138
+ policy() {
139
+ while (this.eat('@')) {
140
+ this.ident();
141
+ if (this.eat('(')) {
142
+ this.str();
143
+ this.need(')');
144
+ }
145
+ }
146
+ const effect = this.ident();
147
+ if (effect !== 'permit' && effect !== 'forbid')
148
+ throw new CedarParseError('A policy starts with permit or forbid.', this.toks[this.i - 1].pos);
149
+ this.need('(');
150
+ const principal = this.scope('principal');
151
+ this.need(',');
152
+ const action = this.scope('action');
153
+ this.need(',');
154
+ const resource = this.scope('resource');
155
+ this.need(')');
156
+ const conditions = [];
157
+ while (this.cur.t === 'id' && (this.cur.v === 'when' || this.cur.v === 'unless')) {
158
+ const unless = this.ident() === 'unless';
159
+ this.need('{');
160
+ const e = this.expr();
161
+ this.need('}');
162
+ conditions.push(unless ? { k: 'not', e } : e);
163
+ }
164
+ this.need(';');
165
+ return { effect, principal, action, resource, conditions };
166
+ }
167
+ entity() {
168
+ const parts = [this.ident()];
169
+ this.need('::');
170
+ while (this.cur.t === 'id') {
171
+ parts.push(this.ident());
172
+ this.need('::');
173
+ }
174
+ return { type: parts.join('::'), id: this.str() };
175
+ }
176
+ slot(name) {
177
+ if (!this.is('?'))
178
+ return null;
179
+ const pos = this.cur.pos;
180
+ this.i++;
181
+ if (!this.templates)
182
+ throw new CedarParseError('A slot is only allowed in a policy template.', pos);
183
+ if (this.ident() !== name)
184
+ throw new CedarParseError(`The ${name} scope takes ?${name}.`, pos);
185
+ return `?${name}`;
186
+ }
187
+ scope(name) {
188
+ if (this.ident() !== name)
189
+ throw new CedarParseError(`Expected ${name}.`, this.toks[this.i - 1].pos);
190
+ const slotName = name === 'principal' || name === 'resource' ? name : null;
191
+ if (this.eat('==')) {
192
+ const sl = slotName && this.slot(slotName);
193
+ return sl ? { op: 'slot==', slot: sl } : { op: '==', e: this.entity() };
194
+ }
195
+ if (this.cur.t === 'id' && this.cur.v === 'in') {
196
+ this.i++;
197
+ const sl = slotName && this.slot(slotName);
198
+ if (sl)
199
+ return { op: 'slot_in', slot: sl };
200
+ if (this.eat('[')) {
201
+ const es = [];
202
+ while (!this.is(']')) {
203
+ es.push(this.entity());
204
+ if (!this.eat(','))
205
+ break;
206
+ }
207
+ this.need(']');
208
+ return { op: 'in', es };
209
+ }
210
+ return { op: 'in', es: [this.entity()] };
211
+ }
212
+ if (this.cur.t === 'id' && this.cur.v === 'is') {
213
+ this.i++;
214
+ const parts = [this.ident()];
215
+ while (this.eat('::'))
216
+ parts.push(this.ident());
217
+ const type = parts.join('::');
218
+ if (this.isId('in')) {
219
+ this.i++;
220
+ const sl = slotName && this.slot(slotName);
221
+ return sl ? { op: 'is_slot_in', type, slot: sl } : { op: 'is', type, in: this.entity() };
222
+ }
223
+ return { op: 'is', type };
224
+ }
225
+ return { op: 'any' };
226
+ }
227
+ expr() {
228
+ if (this.cur.t === 'id' && this.cur.v === 'if') {
229
+ this.i++;
230
+ const c = this.expr();
231
+ if (this.ident() !== 'then')
232
+ throw new CedarParseError('Expected then.', this.cur.pos);
233
+ const t = this.expr();
234
+ if (this.ident() !== 'else')
235
+ throw new CedarParseError('Expected else.', this.cur.pos);
236
+ return { k: 'if', c, t, f: this.expr() };
237
+ }
238
+ return this.or();
239
+ }
240
+ or() {
241
+ let l = this.and();
242
+ while (this.eat('||'))
243
+ l = { k: 'bin', op: '||', l, r: this.and() };
244
+ return l;
245
+ }
246
+ and() {
247
+ let l = this.rel();
248
+ while (this.eat('&&'))
249
+ l = { k: 'bin', op: '&&', l, r: this.rel() };
250
+ return l;
251
+ }
252
+ rel() {
253
+ const l = this.add();
254
+ for (const op of ['==', '!=', '<=', '>=', '<', '>'])
255
+ if (this.eat(op))
256
+ return { k: 'bin', op, l, r: this.add() };
257
+ if (this.cur.t === 'id') {
258
+ const w = this.cur.v;
259
+ if (w === 'in') {
260
+ this.i++;
261
+ return { k: 'bin', op: 'in', l, r: this.add() };
262
+ }
263
+ if (w === 'has') {
264
+ this.i++;
265
+ return { k: 'has', of: l, name: this.isStr() ? this.str() : this.ident() };
266
+ }
267
+ if (w === 'like') {
268
+ this.i++;
269
+ return { k: 'like', e: l, pattern: this.str() };
270
+ }
271
+ if (w === 'is') {
272
+ this.i++;
273
+ const parts = [this.ident()];
274
+ while (this.eat('::'))
275
+ parts.push(this.ident());
276
+ if (this.cur.t === 'id' && this.cur.v === 'in') {
277
+ this.i++;
278
+ return { k: 'is', e: l, type: parts.join('::'), in: this.add() };
279
+ }
280
+ return { k: 'is', e: l, type: parts.join('::') };
281
+ }
282
+ }
283
+ return l;
284
+ }
285
+ add() {
286
+ let l = this.mul();
287
+ for (;;) {
288
+ if (this.eat('+'))
289
+ l = { k: 'bin', op: '+', l, r: this.mul() };
290
+ else if (this.eat('-'))
291
+ l = { k: 'bin', op: '-', l, r: this.mul() };
292
+ else
293
+ return l;
294
+ }
295
+ }
296
+ mul() {
297
+ let l = this.unary();
298
+ while (this.eat('*'))
299
+ l = { k: 'bin', op: '*', l, r: this.unary() };
300
+ return l;
301
+ }
302
+ unary() {
303
+ if (this.eat('!'))
304
+ return { k: 'not', e: this.unary() };
305
+ if (this.eat('-'))
306
+ return { k: 'neg', e: this.unary() };
307
+ return this.postfix();
308
+ }
309
+ postfix() {
310
+ let e = this.primary();
311
+ for (;;) {
312
+ if (this.eat('.')) {
313
+ const name = this.ident();
314
+ if (this.eat('(')) {
315
+ const args = [];
316
+ while (!this.is(')')) {
317
+ args.push(this.expr());
318
+ if (!this.eat(','))
319
+ break;
320
+ }
321
+ this.need(')');
322
+ if (!['contains', 'containsAll', 'containsAny', ...cedar_ext_1.EXT_METHODS].includes(name))
323
+ throw new CedarParseError(`Unsupported method "${name}".`, this.toks[this.i - 1].pos);
324
+ e = { k: 'call', of: e, name, args };
325
+ }
326
+ else
327
+ e = { k: 'attr', of: e, name };
328
+ }
329
+ else if (this.is('[')) {
330
+ this.i++;
331
+ const name = this.str();
332
+ this.need(']');
333
+ e = { k: 'attr', of: e, name };
334
+ }
335
+ else
336
+ return e;
337
+ }
338
+ }
339
+ primary() {
340
+ const t = this.cur;
341
+ if (t.t === 'int') {
342
+ this.i++;
343
+ return { k: 'lit', v: Number(t.v) };
344
+ }
345
+ if (t.t === 'str') {
346
+ this.i++;
347
+ return { k: 'lit', v: t.v };
348
+ }
349
+ if (this.eat('(')) {
350
+ const e = this.expr();
351
+ this.need(')');
352
+ return e;
353
+ }
354
+ if (this.eat('[')) {
355
+ const items = [];
356
+ while (!this.is(']')) {
357
+ items.push(this.expr());
358
+ if (!this.eat(','))
359
+ break;
360
+ }
361
+ this.need(']');
362
+ return { k: 'set', items };
363
+ }
364
+ if (this.eat('{')) {
365
+ const fields = [];
366
+ while (!this.is('}')) {
367
+ const key = this.cur.t === 'str' ? this.str() : this.ident();
368
+ this.need(':');
369
+ fields.push([key, this.expr()]);
370
+ if (!this.eat(','))
371
+ break;
372
+ }
373
+ this.need('}');
374
+ return { k: 'record', fields };
375
+ }
376
+ if (t.t === 'id') {
377
+ if (t.v === 'true' || t.v === 'false') {
378
+ this.i++;
379
+ return { k: 'lit', v: t.v === 'true' };
380
+ }
381
+ if (['principal', 'action', 'resource', 'context'].includes(t.v)) {
382
+ this.i++;
383
+ return { k: 'var', name: t.v };
384
+ }
385
+ if ((t.v === 'ip' || t.v === 'decimal') && this.toks[this.i + 1]?.v === '(') {
386
+ this.i += 2;
387
+ const arg = this.str();
388
+ this.need(')');
389
+ try {
390
+ (0, cedar_ext_1.extConstructor)(t.v, arg);
391
+ }
392
+ catch (err) {
393
+ throw new CedarParseError(err instanceof cedar_ext_1.AbacExtError ? err.message : 'Invalid extension value.', t.pos);
394
+ }
395
+ return { k: 'ext', name: t.v, arg };
396
+ }
397
+ if (this.toks[this.i + 1]?.v === '::')
398
+ return { k: 'ent', e: this.entity() };
399
+ }
400
+ throw new CedarParseError(`Unexpected "${t.v || 'end of input'}".`, t.pos);
401
+ }
402
+ }
403
+ /** Parse a policy set; throws CedarParseError with the character position. */
404
+ function parseCedar(source) {
405
+ return new Parser(lex(source)).policies();
406
+ }
407
+ /** Parse policy templates: like a policy set, but the principal and resource scopes may hold `?principal` / `?resource`. */
408
+ function parseCedarTemplate(source) {
409
+ return new Parser(lex(source), true).policies();
410
+ }
411
+ class CedarLinkError extends Error {
412
+ }
413
+ exports.CedarLinkError = CedarLinkError;
414
+ const SLOTS = (p) => [p.principal, p.resource].flatMap((s) => (s.op === 'slot==' || s.op === 'slot_in' || s.op === 'is_slot_in' ? [s.slot] : []));
415
+ /** The slots a template uses, sorted. */
416
+ const cedarTemplateSlots = (policies) => [...new Set(policies.flatMap(SLOTS))].sort();
417
+ exports.cedarTemplateSlots = cedarTemplateSlots;
418
+ /** Fill a template's slots with entities, giving ordinary policies. A slot without an entity is an error. */
419
+ function linkCedarTemplate(policies, values) {
420
+ const need = (slot) => {
421
+ const v = slot === '?principal' ? values.principal : values.resource;
422
+ if (!v)
423
+ throw new CedarLinkError(`The template uses ${slot}; give it a ${slot.slice(1)} entity.`);
424
+ return v;
425
+ };
426
+ const fill = (c) => (c.op === 'slot==' ? { op: '==', e: need(c.slot) } : c.op === 'slot_in' ? { op: 'in', es: [need(c.slot)] } : c.op === 'is_slot_in' ? { op: 'is', type: c.type, in: need(c.slot) } : c);
427
+ return policies.map((p) => ({ ...p, principal: fill(p.principal), resource: fill(p.resource) }));
428
+ }
429
+ // ── evaluation ──
430
+ class Ent {
431
+ type;
432
+ id;
433
+ constructor(type, id) {
434
+ this.type = type;
435
+ this.id = id;
436
+ }
437
+ get uid() {
438
+ return `${this.type}::${this.id}`;
439
+ }
440
+ }
441
+ const uid = (e) => `${e.type}::${e.id}`;
442
+ function like(s, pattern) {
443
+ const re = pattern
444
+ .split(/(\\\*|\*)/)
445
+ .map((p) => (p === '*' ? '.*' : p === '\\*' ? '\\*' : p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')))
446
+ .join('');
447
+ return new RegExp(`^${re}$`, 's').test(s);
448
+ }
449
+ class Evaluator {
450
+ req;
451
+ byUid = new Map();
452
+ constructor(req) {
453
+ this.req = req;
454
+ for (const e of req.entities ?? [])
455
+ this.byUid.set(uid(e), e);
456
+ this.byUid.set(uid(req.principal), req.principal);
457
+ this.byUid.set(uid(req.resource), req.resource);
458
+ }
459
+ ancestors(u) {
460
+ const seen = new Set();
461
+ const stack = [u];
462
+ while (stack.length)
463
+ for (const p of this.byUid.get(stack.pop())?.parents ?? [])
464
+ if (!seen.has(p))
465
+ (seen.add(p), stack.push(p));
466
+ return seen;
467
+ }
468
+ isIn(a, b) {
469
+ return a.uid === b.uid || this.ancestors(a.uid).has(b.uid);
470
+ }
471
+ conv(raw) {
472
+ if (Array.isArray(raw))
473
+ return raw.map((x) => this.conv(x));
474
+ if (raw && typeof raw === 'object') {
475
+ const o = raw;
476
+ const extn = o.__extn;
477
+ if (extn && typeof extn === 'object') {
478
+ try {
479
+ return (0, cedar_ext_1.extConstructor)(String(extn.fn), extn.arg);
480
+ }
481
+ catch (err) {
482
+ throw new EvalError(err instanceof Error ? err.message : 'Invalid extension value.');
483
+ }
484
+ }
485
+ const ent = (o.__entity ?? (typeof o.type === 'string' && typeof o.id === 'string' && Object.keys(o).length === 2 ? o : null));
486
+ if (ent)
487
+ return new Ent(ent.type, ent.id);
488
+ return Object.fromEntries(Object.entries(o).map(([k, v]) => [k, this.conv(v)]));
489
+ }
490
+ if (typeof raw === 'number' && !Number.isInteger(raw))
491
+ throw new EvalError('Decimals are not supported.');
492
+ if (raw === null || raw === undefined)
493
+ throw new EvalError('Null is not a Cedar value.');
494
+ return raw;
495
+ }
496
+ subject(s, v) {
497
+ if (s.op === 'any')
498
+ return true;
499
+ if (s.op === 'slot==' || s.op === 'slot_in' || s.op === 'is_slot_in')
500
+ return false; // an unlinked template never applies
501
+ if (s.op === '==')
502
+ return v.uid === uid(s.e);
503
+ if (s.op === 'in')
504
+ return s.es.some((e) => this.isIn(v, new Ent(e.type, e.id)));
505
+ return v.type === s.type && (!s.in || this.isIn(v, new Ent(s.in.type, s.in.id)));
506
+ }
507
+ scoped(p) {
508
+ const r = this.req;
509
+ return this.subject(p.principal, new Ent(r.principal.type, r.principal.id)) && this.subject(p.action, new Ent(r.action.type ?? 'Action', r.action.id)) && this.subject(p.resource, new Ent(r.resource.type, r.resource.id));
510
+ }
511
+ eq(a, b) {
512
+ if (a instanceof cedar_ext_1.AbacDecimal || a instanceof cedar_ext_1.AbacIp || b instanceof cedar_ext_1.AbacDecimal || b instanceof cedar_ext_1.AbacIp)
513
+ return (a instanceof cedar_ext_1.AbacDecimal || a instanceof cedar_ext_1.AbacIp) && (b instanceof cedar_ext_1.AbacDecimal || b instanceof cedar_ext_1.AbacIp) && (0, cedar_ext_1.extEqual)(a, b);
514
+ if (a instanceof Ent || b instanceof Ent)
515
+ return a instanceof Ent && b instanceof Ent && a.uid === b.uid;
516
+ if (Array.isArray(a) && Array.isArray(b))
517
+ return a.length === b.length && a.every((x) => b.some((y) => this.eq(x, y)));
518
+ if (a && b && typeof a === 'object' && typeof b === 'object') {
519
+ const ka = Object.keys(a);
520
+ return ka.length === Object.keys(b).length && ka.every((k) => k in b && this.eq(a[k], b[k]));
521
+ }
522
+ return a === b;
523
+ }
524
+ bool(v) {
525
+ if (typeof v !== 'boolean')
526
+ throw new EvalError('Expected a boolean.');
527
+ return v;
528
+ }
529
+ num(v) {
530
+ if (typeof v !== 'number')
531
+ throw new EvalError('Expected a number.');
532
+ return v;
533
+ }
534
+ attrOf(of, name) {
535
+ if (of instanceof Ent) {
536
+ const a = this.byUid.get(of.uid)?.attributes;
537
+ if (!a || !(name in a) || a[name] === undefined)
538
+ throw new EvalError(`${of.uid} has no attribute "${name}".`);
539
+ return this.conv(a[name]);
540
+ }
541
+ if (of && typeof of === 'object' && !Array.isArray(of)) {
542
+ if (!(name in of))
543
+ throw new EvalError(`No attribute "${name}".`);
544
+ return of[name];
545
+ }
546
+ throw new EvalError(`Cannot read "${name}" of a non-record.`);
547
+ }
548
+ ev(x) {
549
+ const r = this.req;
550
+ switch (x.k) {
551
+ case 'lit':
552
+ return x.v;
553
+ case 'ent':
554
+ return new Ent(x.e.type, x.e.id);
555
+ case 'var':
556
+ return x.name === 'principal' ? new Ent(r.principal.type, r.principal.id) : x.name === 'action' ? new Ent(r.action.type ?? 'Action', r.action.id) : x.name === 'resource' ? new Ent(r.resource.type, r.resource.id) : this.conv(r.context ?? {});
557
+ case 'attr':
558
+ return this.attrOf(this.ev(x.of), x.name);
559
+ case 'has': {
560
+ const of = this.ev(x.of);
561
+ if (of instanceof Ent) {
562
+ const a = this.byUid.get(of.uid)?.attributes;
563
+ return !!a && x.name in a && a[x.name] !== undefined && a[x.name] !== null;
564
+ }
565
+ if (of && typeof of === 'object' && !Array.isArray(of))
566
+ return x.name in of;
567
+ throw new EvalError('has needs a record or entity.');
568
+ }
569
+ case 'not':
570
+ return !this.bool(this.ev(x.e));
571
+ case 'neg':
572
+ return -this.num(this.ev(x.e));
573
+ case 'like': {
574
+ const v = this.ev(x.e);
575
+ if (typeof v !== 'string')
576
+ throw new EvalError('like needs a string.');
577
+ return like(v, x.pattern);
578
+ }
579
+ case 'is': {
580
+ const v = this.ev(x.e);
581
+ if (!(v instanceof Ent))
582
+ throw new EvalError('is needs an entity.');
583
+ return v.type === x.type && (!x.in || this.isInAny(v, this.ev(x.in)));
584
+ }
585
+ case 'if':
586
+ return this.bool(this.ev(x.c)) ? this.ev(x.t) : this.ev(x.f);
587
+ case 'set':
588
+ return x.items.map((i) => this.ev(i));
589
+ case 'record':
590
+ return Object.fromEntries(x.fields.map(([k, v]) => [k, this.ev(v)]));
591
+ case 'ext':
592
+ return (0, cedar_ext_1.extConstructor)(x.name, x.arg);
593
+ case 'call': {
594
+ const of = this.ev(x.of);
595
+ if (of instanceof cedar_ext_1.AbacDecimal || of instanceof cedar_ext_1.AbacIp) {
596
+ try {
597
+ return (0, cedar_ext_1.extMethod)(x.name, of, x.args.map((a) => this.ev(a)));
598
+ }
599
+ catch (err) {
600
+ throw new EvalError(err instanceof Error ? err.message : 'Invalid extension call.');
601
+ }
602
+ }
603
+ if (!Array.isArray(of))
604
+ throw new EvalError(`${x.name} needs a set.`);
605
+ const arg = this.ev(x.args[0]);
606
+ if (x.name === 'contains')
607
+ return of.some((i) => this.eq(i, arg));
608
+ if (!Array.isArray(arg))
609
+ throw new EvalError(`${x.name} needs a set.`);
610
+ return x.name === 'containsAll' ? arg.every((a) => of.some((i) => this.eq(i, a))) : arg.some((a) => of.some((i) => this.eq(i, a)));
611
+ }
612
+ case 'bin': {
613
+ if (x.op === '&&')
614
+ return this.bool(this.ev(x.l)) && this.bool(this.ev(x.r));
615
+ if (x.op === '||')
616
+ return this.bool(this.ev(x.l)) || this.bool(this.ev(x.r));
617
+ const l = this.ev(x.l);
618
+ const rr = this.ev(x.r);
619
+ switch (x.op) {
620
+ case '==':
621
+ return this.eq(l, rr);
622
+ case '!=':
623
+ return !this.eq(l, rr);
624
+ case '<':
625
+ return this.num(l) < this.num(rr);
626
+ case '<=':
627
+ return this.num(l) <= this.num(rr);
628
+ case '>':
629
+ return this.num(l) > this.num(rr);
630
+ case '>=':
631
+ return this.num(l) >= this.num(rr);
632
+ case '+':
633
+ return this.num(l) + this.num(rr);
634
+ case '-':
635
+ return this.num(l) - this.num(rr);
636
+ case '*':
637
+ return this.num(l) * this.num(rr);
638
+ default:
639
+ if (!(l instanceof Ent))
640
+ throw new EvalError('in needs an entity on the left.');
641
+ return this.isInAny(l, rr);
642
+ }
643
+ }
644
+ }
645
+ }
646
+ isInAny(l, r) {
647
+ if (r instanceof Ent)
648
+ return this.isIn(l, r);
649
+ if (Array.isArray(r) && r.every((x) => x instanceof Ent))
650
+ return r.some((x) => this.isIn(l, x));
651
+ throw new EvalError('in needs an entity or a set of entities on the right.');
652
+ }
653
+ }
654
+ /** Every policy's outcome for a request. A policy that errors is reported with `error` and never matches. */
655
+ function traceCedar(policies, req) {
656
+ const ev = new Evaluator(req);
657
+ return policies.map((p, index) => {
658
+ const scoped = ev.scoped(p);
659
+ if (!scoped)
660
+ return { index, effect: p.effect, matched: false, scoped };
661
+ try {
662
+ let ok = true;
663
+ for (const c of p.conditions) {
664
+ const v = ev.ev(c);
665
+ if (typeof v !== 'boolean')
666
+ throw new EvalError('A condition must be a boolean.');
667
+ if (!v) {
668
+ ok = false;
669
+ break;
670
+ }
671
+ }
672
+ return { index, effect: p.effect, matched: ok, scoped };
673
+ }
674
+ catch (e) {
675
+ return { index, effect: p.effect, matched: false, scoped, error: e instanceof Error ? e.message : 'Evaluation failed.' };
676
+ }
677
+ });
678
+ }
679
+ /** Cedar's rule: a matching forbid denies, otherwise a matching permit allows, otherwise deny. `determining` are the policy indexes that decided. */
680
+ function decideCedar(outcomes) {
681
+ const hit = (eff) => outcomes.filter((o) => o.matched && o.effect === eff).map((o) => o.index);
682
+ const errors = outcomes.filter((o) => o.error).map((o) => ({ index: o.index, message: o.error }));
683
+ const forbids = hit('forbid');
684
+ if (forbids.length)
685
+ return { decision: 'deny', determining: forbids, errors };
686
+ const permits = hit('permit');
687
+ return { decision: permits.length ? 'allow' : 'deny', determining: permits, errors };
688
+ }
689
+ //# sourceMappingURL=cedar.js.map