endpoint-permissions-kit 0.2.0 → 0.2.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.
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/cli/child.ts", "../../src/errors.ts", "../../src/constants.ts", "../../src/identifiers.ts", "../../src/state.ts", "../../src/context.ts", "../../src/cli/protocol.ts"],
3
+ "sources": ["../../src/cli/child.ts", "../../src/errors.ts", "../../src/constants.ts", "../../src/identifiers.ts", "../../src/properties.ts", "../../src/state.ts", "../../src/context.ts", "../../src/cli/protocol.ts"],
4
4
  "sourcesContent": [
5
5
  "import { pathToFileURL } from 'node:url';\nimport { resolve } from 'node:path';\nimport context from '../context';\nimport protocol from './protocol';\n\nconst configPath = process.argv[2];\n\nif (configPath === undefined) {\n console.error('usage: child <pkit.config.js>');\n process.exit(protocol.EXIT_CODE.usage);\n}\n\nawait import(pathToFileURL(resolve(configPath)).href);\n\n/** The leading newline closes any line the config left open on stdout, so the marker always starts a line of its own. */\nprocess.stdout.write(`\\n${protocol.CATALOG_MARKER}${JSON.stringify({ roles: context.get('roles') })}\\n`);\n",
6
6
  "import type { PkitErrorCode } from './types';\n\nconst errors = {\n create<ErrorCode extends PkitErrorCode>(code: ErrorCode, message: string): Error & { name: 'PkitError'; code: ErrorCode } {\n return Object.assign(new Error(message), { name: 'PkitError' as const, code });\n },\n\n /**\n * Renders an untrusted value for an error message.\n * A value with no reachable `toString`, such as `Object.create(null)`, makes\n * plain interpolation throw a `TypeError` that would escape as the wrong code.\n */\n describe(value: unknown): string {\n try {\n return String(value);\n } catch {\n return typeof value;\n }\n },\n};\n\nexport default errors;\n",
7
7
  "const constants = {\n METHODS: Object.freeze(['find', 'update', 'create', 'remove'] as const),\n\n GENERAL_ROLE: 'general',\n\n GLOBAL_HOOK_OWNER: '*',\n\n ALL_FIELDS: '*',\n\n MODULE_SEPARATOR: '.',\n\n PERMISSION_ID_SEPARATOR: '::',\n} as const;\n\nexport default constants;\n",
8
8
  "import constants from './constants';\nimport errors from './errors';\nimport type { PermissionId, PkitErrorCode } from './types';\n\n/** The three components a permission identifier is made of, already split. */\nexport interface PermissionReference {\n readonly role: string;\n readonly action: string;\n readonly name: string;\n}\n\nconst identifiers = {\n build(role: string, action: string, name: string): PermissionId {\n return `${role}${constants.PERMISSION_ID_SEPARATOR}${action}${constants.PERMISSION_ID_SEPARATOR}${name}` as PermissionId;\n },\n\n /**\n * Splits `role::module::name` and checks every component.\n * The caller supplies the code and the subject of the message because the same\n * syntax rule is reported as a definition error when registering and as an\n * input error when validating a request.\n */\n parse(value: unknown, code: PkitErrorCode, subject: string): PermissionReference {\n if (typeof value !== 'string') throw invalidIdentifier(value, code, subject);\n\n const parts = value.split(constants.PERMISSION_ID_SEPARATOR);\n const [role, action, name] = parts;\n\n if (parts.length !== 3 || role === undefined || action === undefined || name === undefined) {\n throw invalidIdentifier(value, code, subject);\n }\n\n const isValidRole = isCleanSegment(role) && role !== constants.GLOBAL_HOOK_OWNER;\n const isValidName = isCleanSegment(name) && name !== constants.GLOBAL_HOOK_OWNER;\n const isValidAction = action.split(constants.MODULE_SEPARATOR).every(isCleanSegment);\n\n if (!isValidRole || !isValidName || !isValidAction) throw invalidIdentifier(value, code, subject);\n\n return { role, action, name };\n },\n\n checkRole(role: unknown): void {\n if (typeof role === 'string' && isCleanSegment(role) && role !== constants.GLOBAL_HOOK_OWNER) return;\n\n throw errors.create('INVALID_DEFINITION',\n `invalid role: \"${errors.describe(role)}\" (non-empty string, no \":\" or surrounding whitespace; \"${constants.GLOBAL_HOOK_OWNER}\" is reserved for global hooks)`,\n );\n },\n\n checkModuleSegment(segment: unknown): void {\n if (typeof segment === 'string' && isCleanSegment(segment) && !segment.includes(constants.MODULE_SEPARATOR)) return;\n\n throw errors.create('INVALID_DEFINITION',\n `invalid module name: \"${errors.describe(segment)}\" (non-empty string, no dots, no \":\" or surrounding whitespace)`,\n );\n },\n\n checkName(name: unknown): void {\n if (typeof name === 'string' && isCleanSegment(name) && name !== constants.GLOBAL_HOOK_OWNER) return;\n\n throw errors.create('INVALID_DEFINITION',\n `invalid permission name: \"${errors.describe(name)}\" (non-empty string, no \":\" or surrounding whitespace; \"*\" is reserved)`,\n );\n },\n};\n\nfunction isCleanSegment(value: string): boolean {\n return value.length > 0 && value.trim() === value && !value.includes(':');\n}\n\nfunction invalidIdentifier(value: unknown, code: PkitErrorCode, subject: string): Error {\n return errors.create(code, `${subject}: \"${errors.describe(value)}\" (format role::module::name)`);\n}\n\nexport default identifiers;\n",
9
- "import type { PermissionReference } from './identifiers';\nimport type { ActionDefs, GrantDefs, HookFn, Method, NamedPermissionCatalog } from './types';\nimport constants from './constants';\nimport errors from './errors';\n\ninterface GrantEntry {\n readonly source: PermissionReference;\n readonly actions: GrantDefs;\n}\n\nexport interface NameEntry {\n readonly actions: Map<string, ActionDefs>;\n readonly grants: Map<string, GrantEntry>;\n readonly hooks: Map<string, Map<Method, HookFn[]>>;\n}\n\nexport interface ModuleEntry {\n readonly names: Map<string, NameEntry>;\n readonly hooks: Map<Method, HookFn[]>;\n}\n\nexport interface Snapshot {\n readonly named: NamedPermissionCatalog;\n readonly assignable: ReadonlySet<string>;\n}\n\nexport interface State {\n roles: Set<string>;\n cropper: boolean;\n readonly modules: Map<string, ModuleEntry>;\n snapshot: Snapshot | null;\n}\n\n/**\n * The registry lives on globalThis so the ESM and CJS builds of the package\n * share one catalog inside a process.\n */\nconst STATE_KEY = Symbol.for('endpoint-permissions-kit');\n\nconst state = {\n getOrCreate(): State {\n const stateHost = globalThis as typeof globalThis & { [STATE_KEY]?: State };\n\n if (stateHost[STATE_KEY] === undefined) {\n stateHost[STATE_KEY] = { roles: new Set([constants.GENERAL_ROLE]), cropper: false, modules: new Map(), snapshot: null };\n }\n\n return stateHost[STATE_KEY];\n },\n\n /** Every write to the registry goes through this: sealing freezes the configuration. */\n requireOpen(currentState: State): void {\n if (currentState.snapshot) throw errors.create('SEALED', 'pkit.seal() was already called: no more registrations allowed');\n },\n\n /** Every read of a materialized view goes through this. */\n requireSnapshot(currentState: State): Snapshot {\n if (currentState.snapshot === null) {\n throw errors.create('NOT_SEALED', 'pkit.seal() has not been called: call it after importing every permission file');\n }\n\n return currentState.snapshot;\n },\n};\n\nexport default state;\n",
10
- "import errors from './errors';\nimport identifiers from './identifiers';\nimport state from './state';\nimport type { ContextKey, ContextValues } from './types';\n\nconst context = Object.freeze({\n set<Key extends ContextKey>(key: Key, value: ContextValues[Key]): void {\n const contextKey = checkKey(key);\n const currentState = state.getOrCreate();\n\n state.requireOpen(currentState);\n\n if (contextKey === 'cropper') {\n if (typeof value !== 'boolean') throw errors.create('INVALID_DEFINITION', 'cropper must be a boolean');\n\n currentState.cropper = value;\n\n return;\n }\n\n currentState.roles = new Set(readRoleCatalog(value, currentState.modules.size));\n },\n\n get<Key extends ContextKey>(key: Key): ContextValues[Key] {\n const contextKey = checkKey(key);\n const currentState = state.getOrCreate();\n\n return (contextKey === 'cropper' ? currentState.cropper : [...currentState.roles]) as ContextValues[Key];\n },\n});\n\nfunction checkKey(key: unknown): ContextKey {\n if (key === 'roles' || key === 'cropper') return key;\n\n throw errors.create('INVALID_DEFINITION', `unknown context key: \"${errors.describe(key)}\"`);\n}\n\n/**\n * The catalog replaces the default `['general']` instead of extending it, so it\n * has to be declared before any permission is registered against a role.\n */\nfunction readRoleCatalog(value: unknown, registeredModuleCount: number): readonly string[] {\n if (registeredModuleCount > 0) {\n throw errors.create('INVALID_DEFINITION', 'roles must be declared before registering permissions: import pkit.config.js first');\n }\n\n if (!Array.isArray(value)) throw errors.create('INVALID_DEFINITION', 'roles must be an array of non-empty strings');\n\n for (const role of value) {\n if (typeof role !== 'string' || role.length === 0) {\n throw errors.create('INVALID_DEFINITION', 'roles must be an array of non-empty strings');\n }\n }\n\n const catalog = value as readonly string[];\n\n if (catalog.length === 0) throw errors.create('INVALID_DEFINITION', 'roles must declare at least one role');\n\n for (const role of catalog) identifiers.checkRole(role);\n\n return catalog;\n}\n\nexport default context;\n",
9
+ "import constants from './constants';\nimport errors from './errors';\nimport type { Data, Properties } from './types';\n\nconst PRUNED = Symbol('pruned');\n\nconst MAX_DEPTH = 1000;\n\ntype PathPattern = readonly string[];\n\ninterface Walk {\n readonly patterns: readonly PathPattern[];\n readonly segments: string[];\n readonly ancestors: Set<object>;\n}\n\nconst properties = {\n checkDeclaredPath(property: string, permissionPath: string): void {\n if (property.includes('[') || property.includes(']')) {\n throw errors.create('INVALID_DEFINITION', `${permissionPath}: array indexes are not allowed in properties: \"${property}\"`);\n }\n\n const segments = segmentsOf(property);\n\n for (const segment of segments) {\n if (segment.length === 0) throw errors.create('INVALID_DEFINITION', `${permissionPath}: empty segment in property path: \"${property}\"`);\n }\n\n if (segments[0] === constants.ALL_FIELDS) {\n throw errors.create('INVALID_DEFINITION', `${permissionPath}: a property path cannot start with \"${constants.ALL_FIELDS}\": \"${property}\"`);\n }\n },\n\n resolve(data: Data, allowed: Properties, reserved: readonly string[], cropper: boolean): Data {\n if (allowed === constants.ALL_FIELDS) return data;\n\n const patterns: PathPattern[] = [];\n\n for (const pattern of allowed.concat(reserved)) patterns.push(segmentsOf(pattern));\n\n const walk: Walk = { patterns, segments: [], ancestors: new Set([data]) };\n\n if (cropper) return cropData(data, walk);\n\n rejectForbiddenPaths(data, walk);\n\n return data;\n },\n};\n\nfunction segmentsOf(path: string): readonly string[] {\n const segments: string[] = [];\n\n let segment = '';\n\n let index = 0;\n\n while (index < path.length) {\n const character = path[index] as string;\n\n if (character === '\\\\') {\n segment += path[index + 1] ?? '';\n index += 2;\n\n continue;\n }\n\n if (character === '.') {\n segments.push(segment);\n\n segment = '';\n index += 1;\n\n continue;\n }\n\n segment += character;\n index += 1;\n }\n\n segments.push(segment);\n\n return segments;\n}\n\nfunction isAllowedPath(segments: readonly string[], patterns: readonly PathPattern[]): boolean {\n for (const pattern of patterns) {\n if (pattern.length !== segments.length) continue;\n\n let isMatch = true;\n\n for (let index = 0; index < segments.length; index += 1) {\n const patternSegment = pattern[index];\n\n if (patternSegment === constants.ALL_FIELDS) continue;\n if (patternSegment === segments[index]) continue;\n\n isMatch = false;\n\n break;\n }\n\n if (isMatch) return true;\n }\n\n return false;\n}\n\nfunction isPlainObject(value: unknown): boolean {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n\n const prototype: unknown = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction requireDepth(walk: Walk): void {\n if (walk.ancestors.size < MAX_DEPTH) return;\n\n throw new RangeError(`data is nested deeper than ${MAX_DEPTH} levels`);\n}\n\nfunction setField(target: Data, key: string, value: unknown): void {\n if (key === '__proto__') {\n Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });\n\n return;\n }\n\n target[key] = value;\n}\n\nfunction cropValue(value: unknown, walk: Walk): unknown {\n if (Array.isArray(value)) {\n if (value.length === 0) return isAllowedPath(walk.segments, walk.patterns) ? [] : PRUNED;\n\n if (walk.ancestors.has(value)) throw new RangeError('data contains a circular reference');\n\n requireDepth(walk);\n\n walk.ancestors.add(value);\n\n const items: unknown[] = [];\n\n for (const item of value) {\n const croppedItem = cropValue(item, walk);\n\n if (croppedItem === PRUNED) continue;\n\n items.push(croppedItem);\n }\n\n walk.ancestors.delete(value);\n\n return items.length === 0 ? PRUNED : items;\n }\n\n if (isPlainObject(value)) {\n const container = value as Data;\n\n const keys = Object.keys(container);\n\n if (keys.length === 0) return isAllowedPath(walk.segments, walk.patterns) ? {} : PRUNED;\n\n if (walk.ancestors.has(container)) throw new RangeError('data contains a circular reference');\n\n requireDepth(walk);\n\n walk.ancestors.add(container);\n\n const cropped: Data = {};\n\n let keptCount = 0;\n\n for (const key of keys) {\n walk.segments.push(key);\n\n const croppedValue = cropValue(container[key], walk);\n\n walk.segments.pop();\n\n if (croppedValue === PRUNED) continue;\n\n setField(cropped, key, croppedValue);\n\n keptCount += 1;\n }\n\n walk.ancestors.delete(container);\n\n return keptCount === 0 ? PRUNED : cropped;\n }\n\n return isAllowedPath(walk.segments, walk.patterns) ? value : PRUNED;\n}\n\nfunction cropData(data: Data, walk: Walk): Data {\n const cropped: Data = {};\n\n for (const key of Object.keys(data)) {\n walk.segments.push(key);\n\n const croppedValue = cropValue(data[key], walk);\n\n walk.segments.pop();\n\n if (croppedValue === PRUNED) continue;\n\n setField(cropped, key, croppedValue);\n }\n\n return cropped;\n}\n\nfunction collectForbiddenPaths(value: unknown, walk: Walk, forbidden: Set<string>): void {\n if (Array.isArray(value)) {\n if (value.length === 0 || walk.ancestors.has(value)) {\n reportPath(walk, forbidden);\n\n return;\n }\n\n requireDepth(walk);\n\n walk.ancestors.add(value);\n\n for (const item of value) collectForbiddenPaths(item, walk, forbidden);\n\n walk.ancestors.delete(value);\n\n return;\n }\n\n if (isPlainObject(value)) {\n const container = value as Data;\n\n const keys = Object.keys(container);\n\n if (keys.length === 0 || walk.ancestors.has(container)) {\n reportPath(walk, forbidden);\n\n return;\n }\n\n requireDepth(walk);\n\n walk.ancestors.add(container);\n\n for (const key of keys) {\n walk.segments.push(key);\n\n collectForbiddenPaths(container[key], walk, forbidden);\n\n walk.segments.pop();\n }\n\n walk.ancestors.delete(container);\n\n return;\n }\n\n reportPath(walk, forbidden);\n}\n\nfunction reportPath(walk: Walk, forbidden: Set<string>): void {\n if (isAllowedPath(walk.segments, walk.patterns)) return;\n\n forbidden.add(walk.segments.join('.'));\n}\n\nfunction rejectForbiddenPaths(data: Data, walk: Walk): void {\n const forbidden = new Set<string>();\n\n for (const key of Object.keys(data)) {\n walk.segments.push(key);\n\n collectForbiddenPaths(data[key], walk, forbidden);\n\n walk.segments.pop();\n }\n\n if (forbidden.size === 0) return;\n\n const fields = [...forbidden];\n\n const error = errors.create('PROPERTIES_NOT_ALLOWED', `fields not allowed: ${fields.join(', ')}`);\n\n throw Object.assign(error, { fields });\n}\n\nexport default properties;\n",
10
+ "import type { PermissionReference } from './identifiers';\nimport type { ActionDefs, GrantDefs, HookFn, Method, NamedPermissionCatalog } from './types';\nimport constants from './constants';\nimport errors from './errors';\n\ninterface GrantEntry {\n readonly source: PermissionReference;\n readonly actions: GrantDefs;\n}\n\nexport interface NameEntry {\n readonly actions: Map<string, ActionDefs>;\n readonly grants: Map<string, GrantEntry>;\n readonly hooks: Map<string, Map<Method, HookFn[]>>;\n}\n\nexport interface ModuleEntry {\n readonly names: Map<string, NameEntry>;\n readonly hooks: Map<Method, HookFn[]>;\n}\n\nexport interface Snapshot {\n readonly named: NamedPermissionCatalog;\n readonly assignable: ReadonlySet<string>;\n}\n\nexport interface State {\n roles: Set<string>;\n cropper: boolean;\n reservedFields: readonly string[];\n readonly modules: Map<string, ModuleEntry>;\n snapshot: Snapshot | null;\n}\n\nconst STATE_KEY = Symbol.for('endpoint-permissions-kit');\n\nconst state = {\n getOrCreate(): State {\n const stateHost = globalThis as typeof globalThis & { [STATE_KEY]?: State };\n\n if (stateHost[STATE_KEY] === undefined) {\n stateHost[STATE_KEY] = {\n roles: new Set([constants.GENERAL_ROLE]),\n cropper: false,\n reservedFields: [],\n modules: new Map(),\n snapshot: null,\n };\n }\n\n return stateHost[STATE_KEY];\n },\n\n requireOpen(currentState: State): void {\n if (currentState.snapshot) throw errors.create('SEALED', 'pkit.seal() was already called: no more registrations allowed');\n },\n\n requireSnapshot(currentState: State): Snapshot {\n if (currentState.snapshot === null) {\n throw errors.create('NOT_SEALED', 'pkit.seal() has not been called: call it after importing every permission file');\n }\n\n return currentState.snapshot;\n },\n};\n\nexport default state;\n",
11
+ "import errors from './errors';\nimport identifiers from './identifiers';\nimport properties from './properties';\nimport state from './state';\nimport type { ContextKey, ContextValues } from './types';\n\nconst context = Object.freeze({\n set<Key extends ContextKey>(key: Key, value: ContextValues[Key]): void {\n const contextKey = checkKey(key);\n\n const currentState = state.getOrCreate();\n\n state.requireOpen(currentState);\n\n if (contextKey === 'cropper') {\n if (typeof value !== 'boolean') throw errors.create('INVALID_DEFINITION', 'cropper must be a boolean');\n\n currentState.cropper = value;\n\n return;\n }\n\n if (contextKey === 'reservedFields') {\n currentState.reservedFields = Object.freeze(readReservedFields(value));\n\n return;\n }\n\n currentState.roles = new Set(readRoleCatalog(value, currentState.modules.size));\n },\n\n get<Key extends ContextKey>(key: Key): ContextValues[Key] {\n const contextKey = checkKey(key);\n\n const currentState = state.getOrCreate();\n\n if (contextKey === 'cropper') return currentState.cropper as ContextValues[Key];\n\n const paths: readonly string[] = contextKey === 'roles' ? [...currentState.roles] : [...currentState.reservedFields];\n\n return paths as ContextValues[Key];\n },\n});\n\nfunction checkKey(key: unknown): ContextKey {\n if (key === 'roles' || key === 'cropper' || key === 'reservedFields') return key;\n\n throw errors.create('INVALID_DEFINITION', `unknown context key: \"${errors.describe(key)}\"`);\n}\n\nfunction readRoleCatalog(value: unknown, registeredModuleCount: number): readonly string[] {\n if (registeredModuleCount > 0) {\n throw errors.create('INVALID_DEFINITION', 'roles must be declared before registering permissions: import pkit.config.js first');\n }\n\n if (!Array.isArray(value)) throw errors.create('INVALID_DEFINITION', 'roles must be an array of non-empty strings');\n\n for (const role of value) {\n if (typeof role !== 'string' || role.length === 0) {\n throw errors.create('INVALID_DEFINITION', 'roles must be an array of non-empty strings');\n }\n }\n\n const catalog = value as readonly string[];\n\n if (catalog.length === 0) throw errors.create('INVALID_DEFINITION', 'roles must declare at least one role');\n\n for (const role of catalog) identifiers.checkRole(role);\n\n return catalog;\n}\n\nfunction readReservedFields(value: unknown): string[] {\n if (!Array.isArray(value)) throw errors.create('INVALID_DEFINITION', 'reservedFields must be an array of property paths');\n\n const fields: string[] = [];\n\n for (const field of value) {\n if (typeof field !== 'string') throw errors.create('INVALID_DEFINITION', 'reservedFields must be an array of property paths');\n\n properties.checkDeclaredPath(field, 'reservedFields');\n\n fields.push(field);\n }\n\n return fields;\n}\n\nexport default context;\n",
11
12
  "const protocol = {\n EXIT_CODE: { success: 0, failure: 1, usage: 2 },\n\n CATALOG_MARKER: '__PKIT_CATALOG__',\n\n CHILD_TIMEOUT_MS: 30000,\n\n CHILD_MAX_BUFFER_BYTES: 1048576,\n} as const;\n\nexport default protocol;\n"
12
13
  ],
13
- "mappings": "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",
14
- "debugId": "E06FAADB234DDEA064756E2164756E21",
14
+ "mappings": "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",
15
+ "debugId": "D66DB9FE1DACA1BA64756E2164756E21",
15
16
  "names": []
16
17
  }
package/dist/esm/index.js CHANGED
@@ -68,13 +68,216 @@ function invalidIdentifier(value, code, subject) {
68
68
  }
69
69
  var identifiers_default = identifiers;
70
70
 
71
+ // src/properties.ts
72
+ var PRUNED = Symbol("pruned");
73
+ var MAX_DEPTH = 1000;
74
+ var properties = {
75
+ checkDeclaredPath(property, permissionPath) {
76
+ if (property.includes("[") || property.includes("]")) {
77
+ throw errors_default.create("INVALID_DEFINITION", `${permissionPath}: array indexes are not allowed in properties: "${property}"`);
78
+ }
79
+ const segments = segmentsOf(property);
80
+ for (const segment of segments) {
81
+ if (segment.length === 0)
82
+ throw errors_default.create("INVALID_DEFINITION", `${permissionPath}: empty segment in property path: "${property}"`);
83
+ }
84
+ if (segments[0] === constants_default.ALL_FIELDS) {
85
+ throw errors_default.create("INVALID_DEFINITION", `${permissionPath}: a property path cannot start with "${constants_default.ALL_FIELDS}": "${property}"`);
86
+ }
87
+ },
88
+ resolve(data, allowed, reserved, cropper) {
89
+ if (allowed === constants_default.ALL_FIELDS)
90
+ return data;
91
+ const patterns = [];
92
+ for (const pattern of allowed.concat(reserved))
93
+ patterns.push(segmentsOf(pattern));
94
+ const walk = { patterns, segments: [], ancestors: new Set([data]) };
95
+ if (cropper)
96
+ return cropData(data, walk);
97
+ rejectForbiddenPaths(data, walk);
98
+ return data;
99
+ }
100
+ };
101
+ function segmentsOf(path) {
102
+ const segments = [];
103
+ let segment = "";
104
+ let index = 0;
105
+ while (index < path.length) {
106
+ const character = path[index];
107
+ if (character === "\\") {
108
+ segment += path[index + 1] ?? "";
109
+ index += 2;
110
+ continue;
111
+ }
112
+ if (character === ".") {
113
+ segments.push(segment);
114
+ segment = "";
115
+ index += 1;
116
+ continue;
117
+ }
118
+ segment += character;
119
+ index += 1;
120
+ }
121
+ segments.push(segment);
122
+ return segments;
123
+ }
124
+ function isAllowedPath(segments, patterns) {
125
+ for (const pattern of patterns) {
126
+ if (pattern.length !== segments.length)
127
+ continue;
128
+ let isMatch = true;
129
+ for (let index = 0;index < segments.length; index += 1) {
130
+ const patternSegment = pattern[index];
131
+ if (patternSegment === constants_default.ALL_FIELDS)
132
+ continue;
133
+ if (patternSegment === segments[index])
134
+ continue;
135
+ isMatch = false;
136
+ break;
137
+ }
138
+ if (isMatch)
139
+ return true;
140
+ }
141
+ return false;
142
+ }
143
+ function isPlainObject(value) {
144
+ if (value === null || typeof value !== "object" || Array.isArray(value))
145
+ return false;
146
+ const prototype = Object.getPrototypeOf(value);
147
+ return prototype === Object.prototype || prototype === null;
148
+ }
149
+ function requireDepth(walk) {
150
+ if (walk.ancestors.size < MAX_DEPTH)
151
+ return;
152
+ throw new RangeError(`data is nested deeper than ${MAX_DEPTH} levels`);
153
+ }
154
+ function setField(target, key, value) {
155
+ if (key === "__proto__") {
156
+ Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });
157
+ return;
158
+ }
159
+ target[key] = value;
160
+ }
161
+ function cropValue(value, walk) {
162
+ if (Array.isArray(value)) {
163
+ if (value.length === 0)
164
+ return isAllowedPath(walk.segments, walk.patterns) ? [] : PRUNED;
165
+ if (walk.ancestors.has(value))
166
+ throw new RangeError("data contains a circular reference");
167
+ requireDepth(walk);
168
+ walk.ancestors.add(value);
169
+ const items = [];
170
+ for (const item of value) {
171
+ const croppedItem = cropValue(item, walk);
172
+ if (croppedItem === PRUNED)
173
+ continue;
174
+ items.push(croppedItem);
175
+ }
176
+ walk.ancestors.delete(value);
177
+ return items.length === 0 ? PRUNED : items;
178
+ }
179
+ if (isPlainObject(value)) {
180
+ const container = value;
181
+ const keys = Object.keys(container);
182
+ if (keys.length === 0)
183
+ return isAllowedPath(walk.segments, walk.patterns) ? {} : PRUNED;
184
+ if (walk.ancestors.has(container))
185
+ throw new RangeError("data contains a circular reference");
186
+ requireDepth(walk);
187
+ walk.ancestors.add(container);
188
+ const cropped = {};
189
+ let keptCount = 0;
190
+ for (const key of keys) {
191
+ walk.segments.push(key);
192
+ const croppedValue = cropValue(container[key], walk);
193
+ walk.segments.pop();
194
+ if (croppedValue === PRUNED)
195
+ continue;
196
+ setField(cropped, key, croppedValue);
197
+ keptCount += 1;
198
+ }
199
+ walk.ancestors.delete(container);
200
+ return keptCount === 0 ? PRUNED : cropped;
201
+ }
202
+ return isAllowedPath(walk.segments, walk.patterns) ? value : PRUNED;
203
+ }
204
+ function cropData(data, walk) {
205
+ const cropped = {};
206
+ for (const key of Object.keys(data)) {
207
+ walk.segments.push(key);
208
+ const croppedValue = cropValue(data[key], walk);
209
+ walk.segments.pop();
210
+ if (croppedValue === PRUNED)
211
+ continue;
212
+ setField(cropped, key, croppedValue);
213
+ }
214
+ return cropped;
215
+ }
216
+ function collectForbiddenPaths(value, walk, forbidden) {
217
+ if (Array.isArray(value)) {
218
+ if (value.length === 0 || walk.ancestors.has(value)) {
219
+ reportPath(walk, forbidden);
220
+ return;
221
+ }
222
+ requireDepth(walk);
223
+ walk.ancestors.add(value);
224
+ for (const item of value)
225
+ collectForbiddenPaths(item, walk, forbidden);
226
+ walk.ancestors.delete(value);
227
+ return;
228
+ }
229
+ if (isPlainObject(value)) {
230
+ const container = value;
231
+ const keys = Object.keys(container);
232
+ if (keys.length === 0 || walk.ancestors.has(container)) {
233
+ reportPath(walk, forbidden);
234
+ return;
235
+ }
236
+ requireDepth(walk);
237
+ walk.ancestors.add(container);
238
+ for (const key of keys) {
239
+ walk.segments.push(key);
240
+ collectForbiddenPaths(container[key], walk, forbidden);
241
+ walk.segments.pop();
242
+ }
243
+ walk.ancestors.delete(container);
244
+ return;
245
+ }
246
+ reportPath(walk, forbidden);
247
+ }
248
+ function reportPath(walk, forbidden) {
249
+ if (isAllowedPath(walk.segments, walk.patterns))
250
+ return;
251
+ forbidden.add(walk.segments.join("."));
252
+ }
253
+ function rejectForbiddenPaths(data, walk) {
254
+ const forbidden = new Set;
255
+ for (const key of Object.keys(data)) {
256
+ walk.segments.push(key);
257
+ collectForbiddenPaths(data[key], walk, forbidden);
258
+ walk.segments.pop();
259
+ }
260
+ if (forbidden.size === 0)
261
+ return;
262
+ const fields = [...forbidden];
263
+ const error = errors_default.create("PROPERTIES_NOT_ALLOWED", `fields not allowed: ${fields.join(", ")}`);
264
+ throw Object.assign(error, { fields });
265
+ }
266
+ var properties_default = properties;
267
+
71
268
  // src/state.ts
72
269
  var STATE_KEY = Symbol.for("endpoint-permissions-kit");
73
270
  var state = {
74
271
  getOrCreate() {
75
272
  const stateHost = globalThis;
76
273
  if (stateHost[STATE_KEY] === undefined) {
77
- stateHost[STATE_KEY] = { roles: new Set([constants_default.GENERAL_ROLE]), cropper: false, modules: new Map, snapshot: null };
274
+ stateHost[STATE_KEY] = {
275
+ roles: new Set([constants_default.GENERAL_ROLE]),
276
+ cropper: false,
277
+ reservedFields: [],
278
+ modules: new Map,
279
+ snapshot: null
280
+ };
78
281
  }
79
282
  return stateHost[STATE_KEY];
80
283
  },
@@ -103,16 +306,23 @@ var context = Object.freeze({
103
306
  currentState.cropper = value;
104
307
  return;
105
308
  }
309
+ if (contextKey === "reservedFields") {
310
+ currentState.reservedFields = Object.freeze(readReservedFields(value));
311
+ return;
312
+ }
106
313
  currentState.roles = new Set(readRoleCatalog(value, currentState.modules.size));
107
314
  },
108
315
  get(key) {
109
316
  const contextKey = checkKey(key);
110
317
  const currentState = state_default.getOrCreate();
111
- return contextKey === "cropper" ? currentState.cropper : [...currentState.roles];
318
+ if (contextKey === "cropper")
319
+ return currentState.cropper;
320
+ const paths = contextKey === "roles" ? [...currentState.roles] : [...currentState.reservedFields];
321
+ return paths;
112
322
  }
113
323
  });
114
324
  function checkKey(key) {
115
- if (key === "roles" || key === "cropper")
325
+ if (key === "roles" || key === "cropper" || key === "reservedFields")
116
326
  return key;
117
327
  throw errors_default.create("INVALID_DEFINITION", `unknown context key: "${errors_default.describe(key)}"`);
118
328
  }
@@ -134,6 +344,18 @@ function readRoleCatalog(value, registeredModuleCount) {
134
344
  identifiers_default.checkRole(role);
135
345
  return catalog;
136
346
  }
347
+ function readReservedFields(value) {
348
+ if (!Array.isArray(value))
349
+ throw errors_default.create("INVALID_DEFINITION", "reservedFields must be an array of property paths");
350
+ const fields = [];
351
+ for (const field of value) {
352
+ if (typeof field !== "string")
353
+ throw errors_default.create("INVALID_DEFINITION", "reservedFields must be an array of property paths");
354
+ properties_default.checkDeclaredPath(field, "reservedFields");
355
+ fields.push(field);
356
+ }
357
+ return fields;
358
+ }
137
359
  var context_default = context;
138
360
 
139
361
  // src/resolve.ts
@@ -265,202 +487,6 @@ var permissions = Object.freeze({
265
487
  });
266
488
  var permissions_default = permissions;
267
489
 
268
- // src/properties.ts
269
- var PRUNED = Symbol("pruned");
270
- var MAX_DEPTH = 1000;
271
- var properties = {
272
- checkDeclaredPath(property, permissionPath) {
273
- if (property.includes("[") || property.includes("]")) {
274
- throw errors_default.create("INVALID_DEFINITION", `${permissionPath}: array indexes are not allowed in properties: "${property}"`);
275
- }
276
- const segments = segmentsOf(property);
277
- for (const segment of segments) {
278
- if (segment.length === 0)
279
- throw errors_default.create("INVALID_DEFINITION", `${permissionPath}: empty segment in property path: "${property}"`);
280
- }
281
- if (segments[0] === constants_default.ALL_FIELDS) {
282
- throw errors_default.create("INVALID_DEFINITION", `${permissionPath}: a property path cannot start with "${constants_default.ALL_FIELDS}": "${property}"`);
283
- }
284
- },
285
- resolve(data, allowed, cropper) {
286
- if (allowed === constants_default.ALL_FIELDS)
287
- return data;
288
- const patterns = [];
289
- for (const pattern of allowed)
290
- patterns.push(segmentsOf(pattern));
291
- const walk = { patterns, segments: [], ancestors: new Set([data]) };
292
- if (cropper)
293
- return cropData(data, walk);
294
- rejectForbiddenPaths(data, walk);
295
- return data;
296
- }
297
- };
298
- function segmentsOf(path) {
299
- const segments = [];
300
- let segment = "";
301
- let index = 0;
302
- while (index < path.length) {
303
- const character = path[index];
304
- if (character === "\\") {
305
- segment += path[index + 1] ?? "";
306
- index += 2;
307
- continue;
308
- }
309
- if (character === ".") {
310
- segments.push(segment);
311
- segment = "";
312
- index += 1;
313
- continue;
314
- }
315
- segment += character;
316
- index += 1;
317
- }
318
- segments.push(segment);
319
- return segments;
320
- }
321
- function isAllowedPath(segments, patterns) {
322
- for (const pattern of patterns) {
323
- if (pattern.length !== segments.length)
324
- continue;
325
- let isMatch = true;
326
- for (let index = 0;index < segments.length; index += 1) {
327
- const patternSegment = pattern[index];
328
- if (patternSegment === constants_default.ALL_FIELDS)
329
- continue;
330
- if (patternSegment === segments[index])
331
- continue;
332
- isMatch = false;
333
- break;
334
- }
335
- if (isMatch)
336
- return true;
337
- }
338
- return false;
339
- }
340
- function isPlainObject(value) {
341
- if (value === null || typeof value !== "object" || Array.isArray(value))
342
- return false;
343
- const prototype = Object.getPrototypeOf(value);
344
- return prototype === Object.prototype || prototype === null;
345
- }
346
- function requireDepth(walk) {
347
- if (walk.ancestors.size < MAX_DEPTH)
348
- return;
349
- throw new RangeError(`data is nested deeper than ${MAX_DEPTH} levels`);
350
- }
351
- function setField(target, key, value) {
352
- if (key === "__proto__") {
353
- Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });
354
- return;
355
- }
356
- target[key] = value;
357
- }
358
- function cropValue(value, walk) {
359
- if (Array.isArray(value)) {
360
- if (value.length === 0)
361
- return isAllowedPath(walk.segments, walk.patterns) ? [] : PRUNED;
362
- if (walk.ancestors.has(value))
363
- throw new RangeError("data contains a circular reference");
364
- requireDepth(walk);
365
- walk.ancestors.add(value);
366
- const items = [];
367
- for (const item of value) {
368
- const croppedItem = cropValue(item, walk);
369
- if (croppedItem === PRUNED)
370
- continue;
371
- items.push(croppedItem);
372
- }
373
- walk.ancestors.delete(value);
374
- return items.length === 0 ? PRUNED : items;
375
- }
376
- if (isPlainObject(value)) {
377
- const container = value;
378
- const keys = Object.keys(container);
379
- if (keys.length === 0)
380
- return isAllowedPath(walk.segments, walk.patterns) ? {} : PRUNED;
381
- if (walk.ancestors.has(container))
382
- throw new RangeError("data contains a circular reference");
383
- requireDepth(walk);
384
- walk.ancestors.add(container);
385
- const cropped = {};
386
- let keptCount = 0;
387
- for (const key of keys) {
388
- walk.segments.push(key);
389
- const croppedValue = cropValue(container[key], walk);
390
- walk.segments.pop();
391
- if (croppedValue === PRUNED)
392
- continue;
393
- setField(cropped, key, croppedValue);
394
- keptCount += 1;
395
- }
396
- walk.ancestors.delete(container);
397
- return keptCount === 0 ? PRUNED : cropped;
398
- }
399
- return isAllowedPath(walk.segments, walk.patterns) ? value : PRUNED;
400
- }
401
- function cropData(data, walk) {
402
- const cropped = {};
403
- for (const key of Object.keys(data)) {
404
- walk.segments.push(key);
405
- const croppedValue = cropValue(data[key], walk);
406
- walk.segments.pop();
407
- if (croppedValue === PRUNED)
408
- continue;
409
- setField(cropped, key, croppedValue);
410
- }
411
- return cropped;
412
- }
413
- function collectForbiddenPaths(value, walk, forbidden) {
414
- if (Array.isArray(value)) {
415
- if (value.length === 0 || walk.ancestors.has(value)) {
416
- reportPath(walk, forbidden);
417
- return;
418
- }
419
- requireDepth(walk);
420
- walk.ancestors.add(value);
421
- for (const item of value)
422
- collectForbiddenPaths(item, walk, forbidden);
423
- walk.ancestors.delete(value);
424
- return;
425
- }
426
- if (isPlainObject(value)) {
427
- const container = value;
428
- const keys = Object.keys(container);
429
- if (keys.length === 0 || walk.ancestors.has(container)) {
430
- reportPath(walk, forbidden);
431
- return;
432
- }
433
- requireDepth(walk);
434
- walk.ancestors.add(container);
435
- for (const key of keys) {
436
- walk.segments.push(key);
437
- collectForbiddenPaths(container[key], walk, forbidden);
438
- walk.segments.pop();
439
- }
440
- walk.ancestors.delete(container);
441
- return;
442
- }
443
- reportPath(walk, forbidden);
444
- }
445
- function reportPath(walk, forbidden) {
446
- if (isAllowedPath(walk.segments, walk.patterns))
447
- return;
448
- forbidden.add(walk.segments.join("."));
449
- }
450
- function rejectForbiddenPaths(data, walk) {
451
- const forbidden = new Set;
452
- for (const key of Object.keys(data)) {
453
- walk.segments.push(key);
454
- collectForbiddenPaths(data[key], walk, forbidden);
455
- walk.segments.pop();
456
- }
457
- if (forbidden.size === 0)
458
- return;
459
- const fields = [...forbidden];
460
- throw Object.assign(errors_default.create("PROPERTIES_NOT_ALLOWED", `fields not allowed: ${fields.join(", ")}`), { fields });
461
- }
462
- var properties_default = properties;
463
-
464
490
  // src/definitions.ts
465
491
  var METHODS = new Set(constants_default.METHODS);
466
492
  var definitions = {
@@ -785,7 +811,8 @@ function prepareRequest(input, currentState) {
785
811
  if (group)
786
812
  hooks.push(...group);
787
813
  }
788
- return { hooks, context, permissions, data: properties_default.resolve(data, access.properties, currentState.cropper) };
814
+ const allowedData = properties_default.resolve(data, access.properties, currentState.reservedFields, currentState.cropper);
815
+ return { hooks, context, permissions, data: allowedData };
789
816
  }
790
817
  function readOptionalObject(value, message) {
791
818
  if (value === undefined)
@@ -834,4 +861,4 @@ export {
834
861
  validate
835
862
  };
836
863
 
837
- //# debugId=20E6942DE80D350864756E2164756E21
864
+ //# debugId=659F54F36460059464756E2164756E21