@dszp/netsapiens-lib 0.1.8 → 0.1.9

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/dist/policy.d.ts CHANGED
@@ -36,13 +36,19 @@ export interface PolicyRule {
36
36
  /** Effective identity (`user@domain`) must be one of these. */
37
37
  users?: string[];
38
38
  /**
39
- * Effective identity (`user@domain`) must NOT be one of these — a denial that ANDs with the rest of
40
- * the rule, narrowing it.
39
+ * Accounts this rule EXCLUDES — a denial that ANDs with the rest of the rule, narrowing it.
41
40
  *
42
41
  * ⚠️ It is NOT a condition on its own. A rule carrying only `notUsers` never matches, deliberately:
43
42
  * "everybody except X" as a standalone rule would be an allow-all wearing an exception, and this
44
43
  * engine's whole shape is that a rule must say who it admits before it says who it doesn't. Pair it
45
44
  * with `scopes`/`domains`/`users` — see `hasCondition` in {@link ruleMatches}.
45
+ *
46
+ * ⚠️ **It matches the effective identity OR the operator behind a mask** — the one place this engine
47
+ * is deliberately asymmetric. Every positive condition sees the EFFECTIVE principal, so a grant
48
+ * follows the role currently being performed; masquerading is full impersonation and is meant to be.
49
+ * A denial is not about a role. It names a person, and a denial that evaporates the moment that
50
+ * person masquerades into someone else is not a denial — it is a suggestion. So this one condition
51
+ * asks both "who is acting" and "who is behind this", and refuses if either is named.
46
52
  */
47
53
  notUsers?: string[];
48
54
  /** Requires masking, AND the operator's `user@domain` (mask_chain) is one of these. */
package/dist/policy.js CHANGED
@@ -35,7 +35,9 @@ export function ruleMatches(p, rule) {
35
35
  return false;
36
36
  if (rule.users && !inList(p.id, rule.users))
37
37
  return false;
38
- if (rule.notUsers && inList(p.id, rule.notUsers))
38
+ // Both identities, unlike every positive condition above — see the field's own note. A grant follows
39
+ // the role being performed; a denial follows the person performing it, through a mask.
40
+ if (rule.notUsers && (inList(p.id, rule.notUsers) || (p.operator && inList(p.operator.id, rule.notUsers))))
39
41
  return false;
40
42
  if (rule.operators) {
41
43
  if (!p.operator || !inList(p.operator.id, rule.operators))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dszp/netsapiens-lib",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Portable, Node-free NetSapiens toolkit: split read/write API clients, JWT (ns_t) validation, and a snapshot -> FlowGraph -> Mermaid call-flow resolver/renderer. Runs unchanged in a Cloudflare Worker, Node, or the browser.",
5
5
  "type": "module",
6
6
  "license": "MIT",