Sign In

@ultimat3/policy

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ultimat3/policy - npm Package Compare versions

Comparing version
9.0.0
to
10.0.0
+8
-0
CLAUDE.md

@@ -35,2 +35,10 @@ # @ultimat3/policy

adapter to `surfaces.ts` — nothing else.
- **`enforce()` dispatches with `Object.hasOwn`, never a bare index** (`As of 2026-08-23`). The
adapter table is an object literal and so inherits `Object.prototype`: `adapters['valueOf']`
answered a FUNCTION, so `enforce('valueOf' as Surface, …)` called it with the table as receiver
and returned the table typed as a `SurfaceDenial` — truthy, so the public authz dispatcher failed
**closed with a denial carrying no code and no reason**. Same hazard, same fix and same reason as
the role map below (`Object.hasOwn`, `defineProperty`). An unknown surface is `X_POLICY_SURFACE_UNKNOWN`, whose `fix:`
lists `Object.keys(adapters)` so a fifth surface joins it by existing. Pinned in
`surfaces.test.ts`.
- **A derived question about a policy TREE is answered in this PACKAGE, once.** `policyPermissions`

@@ -37,0 +45,0 @@ (in `policy.ts`) and `admitsAnonymous` (in `policy-anonymous.ts`) both walk the combinators

+2
-2
{
"name": "@ultimat3/policy",
"version": "9.0.0",
"version": "10.0.0",
"description": "The one authz rule, evaluated identically in every surface",

@@ -34,4 +34,4 @@ "license": "MIT",

"dependencies": {
"@ultimat3/core": "9.0.0"
"@ultimat3/core": "10.0.0"
}
}

@@ -121,2 +121,8 @@ # @ultimat3/policy 🔐

`enforce(surface, policy, args)` dispatches over that table with `Object.hasOwn`, and a surface
with no adapter is `X_POLICY_SURFACE_UNKNOWN`. Not a formality: the table is an object literal, so
it inherits `Object.prototype` — `enforce('valueOf' as Surface, …)` used to call
`Object.prototype.valueOf` with the table as its receiver and return a truthy value, so an authz
dispatch failed **closed with a `SurfaceDenial` no caller could read**.
## Permissions and roles

@@ -174,3 +180,4 @@

`X_FORBIDDEN` · `X_POLICY_MISSING` · `X_PERMISSION_UNKNOWN` · `X_ROLE_REDEFINED`
`X_FORBIDDEN` · `X_POLICY_MISSING` · `X_PERMISSION_UNKNOWN` · `X_POLICY_SURFACE_UNKNOWN` ·
`X_ROLE_REDEFINED`

@@ -177,0 +184,0 @@ A missing policy is a **type** error, not a throw: `ActionDef.policy` is required, so an action

@@ -6,3 +6,3 @@ // The policy layer's stable error codes. `X_POLICY_MISSING` is enforced by the TYPE system,

// a policy resolved by name — and `policyMissing()` is how such a site says it.
import { nearestName, registerErrorCodes, UltimateError } from '@ultimat3/core';
import { nearestName, registerErrorCodes, renderCauseValue, UltimateError } from '@ultimat3/core';

@@ -13,2 +13,3 @@ export const POLICY_ERROR_CODES = [

'X_PERMISSION_UNKNOWN',
'X_POLICY_SURFACE_UNKNOWN',
'X_ROLE_REDEFINED',

@@ -23,2 +24,3 @@ ] as const;

X_PERMISSION_UNKNOWN: 'permission string is not in the permission set',
X_POLICY_SURFACE_UNKNOWN: 'enforce() was handed a surface no adapter answers to',
X_ROLE_REDEFINED: 'two modules define the same role differently',

@@ -43,3 +45,2 @@ };

fix: init.fix,
docs: `https://ultimate.dev/errors/${init.code}`,
});

@@ -112,1 +113,20 @@ }

};
/**
* `enforce()` was handed a surface with no adapter. Thrown rather than denied, because the value
* this reports on is one an index would have resolved to something: every object literal inherits
* `Object.prototype`, so `adapters['valueOf']` answers a function and `adapters['constructor']`
* answers a constructor. Both are truthy, so the dispatcher fails CLOSED and returns a
* `SurfaceDenial` no caller can read — a refusal with no code and no reason, which is worse than
* the refusal it is standing in for.
*
* `known` comes from the adapter table itself, so a fifth surface joins this fix line by existing.
* The received value goes through `renderCauseValue` and never `${}`: the parameter is typed
* `Surface`, and the call site this guard exists for is one no type reached.
*/
export const surfaceUnknown = (surface: unknown, known: readonly string[]): PolicyError =>
new PolicyError({
code: 'X_POLICY_SURFACE_UNKNOWN',
cause: `enforce() was handed surface ${renderCauseValue(surface)}, which no policy adapter answers to`,
fix: `pass one of ${known.join(', ')} — e.g. enforce('${known[0] ?? 'http'}', policy, args)`,
});

@@ -12,3 +12,3 @@ // Proof that one policy covers every surface. Each adapter is the same three lines:

import { forbidden } from './errors';
import { forbidden, surfaceUnknown } from './errors';
import { codeOf, type EvaluateArgs, evaluate, type PolicyEvaluation, reasonOf } from './evaluate';

@@ -125,3 +125,15 @@ import type { Policy } from './policy';

/** Dispatcher for code that is generic over surfaces (the action projector). */
/** The surfaces that have an adapter, derived from the table so the two cannot disagree. */
const SURFACES: readonly string[] = Object.keys(adapters);
/**
* Dispatcher for code that is generic over surfaces (the action projector).
*
* `Object.hasOwn` and not a truthiness check on `adapters[surface]`: the table is an object
* literal, so it inherits `Object.prototype`, and `enforce('valueOf' as Surface, …)` called
* `Object.prototype.valueOf` with `adapters` as its receiver — a truthy return, so the call failed
* CLOSED, and the adapter table typed as a `SurfaceDenial`, so nothing downstream could say what
* was denied. Every in-repo caller passes a literal; a config-driven table, a surface name off the
* wire or a JS host does not, and this is a public authz entry point.
*/
export const enforce = <I, R = unknown>(

@@ -131,3 +143,6 @@ surface: Surface,

args: EvaluateArgs<I, R>,
): SurfaceDenial | undefined => adapters[surface](policy, args);
): SurfaceDenial | undefined => {
if (!Object.hasOwn(adapters, surface)) throw surfaceUnknown(surface, SURFACES);
return adapters[surface](policy, args);
};

@@ -134,0 +149,0 @@ /** For call sites that would rather throw than branch. Same decision, same reason. */