@owlmeans/iam 0.1.18-rc.49 → 0.1.18-rc.50
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/README.md +2 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/iam/SKILL.md +1 -1
- package/build/consts.d.ts +1 -1
- package/build/consts.d.ts.map +1 -1
- package/build/facet.d.ts +10 -0
- package/build/facet.d.ts.map +1 -0
- package/build/facet.js +16 -0
- package/build/facet.js.map +1 -0
- package/build/gate/param.d.ts +4 -29
- package/build/gate/param.d.ts.map +1 -1
- package/build/gate/param.js +72 -88
- package/build/gate/param.js.map +1 -1
- package/build/gate/resolve.d.ts +1 -1
- package/build/gate/resolve.d.ts.map +1 -1
- package/build/gate/types.d.ts +109 -0
- package/build/gate/types.d.ts.map +1 -0
- package/build/gate/types.js +2 -0
- package/build/gate/types.js.map +1 -0
- package/build/gate/validate.d.ts +3 -14
- package/build/gate/validate.d.ts.map +1 -1
- package/build/gate/validate.js +88 -95
- package/build/gate/validate.js.map +1 -1
- package/build/index.d.ts +5 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/permission/types.d.ts +35 -0
- package/build/permission/types.d.ts.map +1 -0
- package/build/permission/types.js +2 -0
- package/build/permission/types.js.map +1 -0
- package/build/permission.d.ts +5 -18
- package/build/permission.d.ts.map +1 -1
- package/build/permission.js +29 -34
- package/build/permission.js.map +1 -1
- package/build/runtime/types.d.ts +90 -0
- package/build/runtime/types.d.ts.map +1 -0
- package/build/runtime/types.js +2 -0
- package/build/runtime/types.js.map +1 -0
- package/build/runtime.d.ts +1 -1
- package/build/runtime.d.ts.map +1 -1
- package/build/schemas.d.ts +1 -1
- package/build/schemas.d.ts.map +1 -1
- package/build/types.d.ts +3 -172
- package/build/types.d.ts.map +1 -1
- package/build/utils/types.d.ts +12 -0
- package/build/utils/types.d.ts.map +1 -0
- package/build/utils/types.js +2 -0
- package/build/utils/types.js.map +1 -0
- package/build/utils.d.ts +1 -10
- package/build/utils.d.ts.map +1 -1
- package/build/utils.js +0 -15
- package/build/utils.js.map +1 -1
- package/package.json +7 -7
- package/src/consts.ts +1 -1
- package/src/facet.ts +17 -0
- package/src/gate/param.ts +79 -92
- package/src/gate/resolve.ts +1 -1
- package/src/gate/types.ts +117 -0
- package/src/gate/validate.ts +93 -98
- package/src/index.ts +5 -0
- package/src/permission/types.ts +33 -0
- package/src/permission.ts +39 -39
- package/src/runtime/types.ts +107 -0
- package/src/runtime.ts +2 -2
- package/src/schemas.ts +1 -1
- package/src/types.ts +3 -199
- package/src/utils/types.ts +11 -0
- package/src/utils.ts +1 -18
- package/tests/gate-param.spec.ts +25 -26
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Provider-agnostic IAM abstraction for the OwlMeans framework — `IamService` in
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
bun add @owlmeans/iam@^0.1.18-rc.
|
|
18
|
+
bun add @owlmeans/iam@^0.1.18-rc.50
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
@@ -38,7 +38,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
38
38
|
your project's skill store (`.agents/skills/`):
|
|
39
39
|
|
|
40
40
|
```sh
|
|
41
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
41
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.49
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/iam",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.50",
|
|
5
|
+
"generatedAt": "2026-10-05T21:03:06.386Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -8,7 +8,7 @@ metadata:
|
|
|
8
8
|
|
|
9
9
|
# Using `@owlmeans/iam`
|
|
10
10
|
|
|
11
|
-
**Install:** `"@owlmeans/iam": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/iam": "^0.1.18-rc.50"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
Provider-agnostic IAM abstraction: the `IamService` interface, the permission and grant shapes, the
|
|
14
14
|
gate-param grammar, `hasPermission`, and the declarations of the provider's runtime IAM API. It
|
package/build/consts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IamRuntimeAck, IamRuntimeGrantQuery, IamRuntimeMemberInvite, IamRuntimeMemberParams, IamRuntimeOrganizationCreate, IamRuntimeOrganizationParams, IamRuntimeOrganizationUpdate } from './types.js';
|
|
1
|
+
import type { IamRuntimeAck, IamRuntimeGrantQuery, IamRuntimeMemberInvite, IamRuntimeMemberParams, IamRuntimeOrganizationCreate, IamRuntimeOrganizationParams, IamRuntimeOrganizationUpdate } from './runtime/types.js';
|
|
2
2
|
import type { JSONSchemaType } from 'ajv';
|
|
3
3
|
export declare const DEFAULT_ALIAS = "iam-service";
|
|
4
4
|
export declare const IAM_MODE_KEYCLOAK = "keycloak";
|
package/build/consts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"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"}
|
package/build/facet.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A facet a backend cannot provide: every method throws `IamUnsupported(what)`.
|
|
3
|
+
*
|
|
4
|
+
* It throws SYNCHRONOUSLY, because a facet may carry synchronous methods (`subjects.identify`) and a
|
|
5
|
+
* rejected promise would hand those a value of the wrong type; an awaited call rejects the same way
|
|
6
|
+
* either way. Caller code turns the refusal into a fallback, exactly as for any other unsupported
|
|
7
|
+
* operation.
|
|
8
|
+
*/
|
|
9
|
+
export declare const unsupportedFacet: <T extends object>(what: string) => T;
|
|
10
|
+
//# sourceMappingURL=facet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facet.d.ts","sourceRoot":"","sources":["../src/facet.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,QAAQ,MAAM,KAAG,CAK9D,CAAA"}
|
package/build/facet.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IamUnsupported } from './errors.js';
|
|
2
|
+
import { INERT_KEYS } from './consts.local.js';
|
|
3
|
+
/**
|
|
4
|
+
* A facet a backend cannot provide: every method throws `IamUnsupported(what)`.
|
|
5
|
+
*
|
|
6
|
+
* It throws SYNCHRONOUSLY, because a facet may carry synchronous methods (`subjects.identify`) and a
|
|
7
|
+
* rejected promise would hand those a value of the wrong type; an awaited call rejects the same way
|
|
8
|
+
* either way. Caller code turns the refusal into a fallback, exactly as for any other unsupported
|
|
9
|
+
* operation.
|
|
10
|
+
*/
|
|
11
|
+
export const unsupportedFacet = (what) => new Proxy(Object.freeze({}), {
|
|
12
|
+
get: (_, key) => typeof key === 'symbol' || INERT_KEYS.has(key)
|
|
13
|
+
? undefined
|
|
14
|
+
: () => { throw new IamUnsupported(what); },
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=facet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facet.js","sourceRoot":"","sources":["../src/facet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAmB,IAAY,EAAK,EAAE,CACpE,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAM,EAAE;IAChC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;QAC7D,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,cAAc,CAAC,IAAI,CAAC,CAAA,CAAC,CAAC;CAC7C,CAAC,CAAA"}
|
package/build/gate/param.d.ts
CHANGED
|
@@ -1,31 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* Two forms, and the difference between them is deliberate:
|
|
7
|
-
*
|
|
8
|
-
* `@enquiryId` — bare. A FLAT key, searched in `params` then `query`. It is never split on
|
|
9
|
-
* a dot, because a query key legally contains one and splitting it would
|
|
10
|
-
* change the meaning of selectors already deployed.
|
|
11
|
-
* `@body:order.id` — qualified. An explicit source and a nested path.
|
|
12
|
-
*
|
|
13
|
-
* The rule worth remembering: the bare form is lenient and flat, the qualified form is strict and
|
|
14
|
-
* nested.
|
|
15
|
-
*/
|
|
16
|
-
export declare const parseGateSelector: (selector: string) => GateResourceSelector | GateParamProblem;
|
|
17
|
-
/**
|
|
18
|
-
* Split a gate param into the permission it checks and where the resource id comes from.
|
|
19
|
-
*
|
|
20
|
-
* Splits at the FIRST `@`. Everything before it is the permission name looked up in the subject's
|
|
21
|
-
* grants; everything after says where to read the resource id at request time. The suffix is the
|
|
22
|
-
* gate's syntax and nothing else's — a permission stored or granted under a name containing one is a
|
|
23
|
-
* key nothing ever looks up.
|
|
24
|
-
*/
|
|
1
|
+
import type { GateParamHelper, ParsedGateParam } from './types.js';
|
|
2
|
+
export declare const createGateParamHelper: () => GateParamHelper;
|
|
3
|
+
export declare const gateParamHelper: GateParamHelper;
|
|
4
|
+
/** @deprecated compat:factory-refactor — use `gateParamHelper.parseGateParam(…)` */
|
|
25
5
|
export declare const parseGateParam: (param: string) => ParsedGateParam;
|
|
26
|
-
/** Compose a gate param. The inverse of `parseGateParam` for every selector it accepts. */
|
|
27
|
-
export declare const formatGateParam: (permission: string, selector?: string | {
|
|
28
|
-
source?: GateParamSource;
|
|
29
|
-
path: string[];
|
|
30
|
-
}) => string;
|
|
31
6
|
//# sourceMappingURL=param.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"param.d.ts","sourceRoot":"","sources":["../../src/gate/param.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"param.d.ts","sourceRoot":"","sources":["../../src/gate/param.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAA0C,eAAe,EAAE,MAAM,YAAY,CAAA;AAG1G,eAAO,MAAM,qBAAqB,QAAO,eA+FxC,CAAA;AAED,eAAO,MAAM,eAAe,iBAA0B,CAAA;AAEtD,oFAAoF;AACpF,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,eAAwD,CAAA"}
|
package/build/gate/param.js
CHANGED
|
@@ -1,99 +1,83 @@
|
|
|
1
1
|
import { RESOURCE_PARAM_SEPARATOR, RESOURCE_SOURCE_SEPARATOR, RESOURCE_PATH_SEPARATOR, GateParamErrorCode, DEFAULT_GATE_PARAM_SOURCES } from '../consts.js';
|
|
2
2
|
import { SOURCES } from './consts.local.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
3
|
+
export const createGateParamHelper = () => {
|
|
4
|
+
const parseGateSelector = (selector) => {
|
|
5
|
+
if (selector === '') {
|
|
6
|
+
return { code: GateParamErrorCode.EmptySelector, detail: 'the selector after "@" is empty' };
|
|
7
|
+
}
|
|
8
|
+
const idx = selector.indexOf(RESOURCE_SOURCE_SEPARATOR);
|
|
9
|
+
if (idx < 0) {
|
|
10
|
+
return {
|
|
11
|
+
selector,
|
|
12
|
+
path: [selector],
|
|
13
|
+
sources: DEFAULT_GATE_PARAM_SOURCES
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const source = selector.slice(0, idx);
|
|
17
|
+
const rest = selector.slice(idx + 1);
|
|
18
|
+
if (!SOURCES.includes(source)) {
|
|
19
|
+
return {
|
|
20
|
+
code: GateParamErrorCode.UnknownSource,
|
|
21
|
+
detail: `"${source}" is not one of ${SOURCES.join(', ')}`
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (rest === '') {
|
|
25
|
+
return {
|
|
26
|
+
code: GateParamErrorCode.EmptySelector,
|
|
27
|
+
detail: `"${source}:" names no path`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const path = rest.split(RESOURCE_PATH_SEPARATOR);
|
|
31
|
+
if (path.some(segment => segment === '')) {
|
|
32
|
+
return {
|
|
33
|
+
code: GateParamErrorCode.EmptySegment,
|
|
34
|
+
detail: `"${rest}" has an empty path segment`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
22
37
|
return {
|
|
23
38
|
selector,
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
source: source,
|
|
40
|
+
path,
|
|
41
|
+
sources: [source]
|
|
26
42
|
};
|
|
27
|
-
}
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
detail: `"${source}:" names no path`
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const path = rest.split(RESOURCE_PATH_SEPARATOR);
|
|
43
|
-
if (path.some(segment => segment === '')) {
|
|
43
|
+
};
|
|
44
|
+
const parseGateParam = (param) => {
|
|
45
|
+
const idx = param.indexOf(RESOURCE_PARAM_SEPARATOR);
|
|
46
|
+
if (idx < 0) {
|
|
47
|
+
return { permission: param };
|
|
48
|
+
}
|
|
49
|
+
const permission = param.slice(0, idx);
|
|
50
|
+
const selector = param.slice(idx + 1);
|
|
51
|
+
const parsed = parseGateSelector(selector);
|
|
52
|
+
if ('code' in parsed) {
|
|
53
|
+
return { permission, resourceParam: selector, error: parsed };
|
|
54
|
+
}
|
|
44
55
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
permission,
|
|
57
|
+
// Kept for readers written against the flat form. Only meaningful when the form IS flat.
|
|
58
|
+
...(parsed.source == null ? { resourceParam: selector } : {}),
|
|
59
|
+
resource: parsed
|
|
47
60
|
};
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
selector,
|
|
51
|
-
source: source,
|
|
52
|
-
path,
|
|
53
|
-
sources: [source]
|
|
54
61
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const selector = param.slice(idx + 1);
|
|
71
|
-
const parsed = parseGateSelector(selector);
|
|
72
|
-
if ('code' in parsed) {
|
|
73
|
-
return { permission, resourceParam: selector, error: parsed };
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
permission,
|
|
77
|
-
// Kept for readers written against the flat form. Only meaningful when the form IS flat.
|
|
78
|
-
...(parsed.source == null ? { resourceParam: selector } : {}),
|
|
79
|
-
resource: parsed
|
|
62
|
+
const formatGateParam = (permission, selector) => {
|
|
63
|
+
if (selector == null) {
|
|
64
|
+
return permission;
|
|
65
|
+
}
|
|
66
|
+
if (typeof selector === 'string') {
|
|
67
|
+
return selector === '' ? permission : `${permission}${RESOURCE_PARAM_SEPARATOR}${selector}`;
|
|
68
|
+
}
|
|
69
|
+
if (selector.path.length < 1) {
|
|
70
|
+
return permission;
|
|
71
|
+
}
|
|
72
|
+
const path = selector.path.join(RESOURCE_PATH_SEPARATOR);
|
|
73
|
+
const tail = selector.source == null
|
|
74
|
+
? path
|
|
75
|
+
: `${selector.source}${RESOURCE_SOURCE_SEPARATOR}${path}`;
|
|
76
|
+
return `${permission}${RESOURCE_PARAM_SEPARATOR}${tail}`;
|
|
80
77
|
};
|
|
78
|
+
return { parseGateSelector, parseGateParam, formatGateParam };
|
|
81
79
|
};
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return permission;
|
|
86
|
-
}
|
|
87
|
-
if (typeof selector === 'string') {
|
|
88
|
-
return selector === '' ? permission : `${permission}${RESOURCE_PARAM_SEPARATOR}${selector}`;
|
|
89
|
-
}
|
|
90
|
-
if (selector.path.length < 1) {
|
|
91
|
-
return permission;
|
|
92
|
-
}
|
|
93
|
-
const path = selector.path.join(RESOURCE_PATH_SEPARATOR);
|
|
94
|
-
const tail = selector.source == null
|
|
95
|
-
? path
|
|
96
|
-
: `${selector.source}${RESOURCE_SOURCE_SEPARATOR}${path}`;
|
|
97
|
-
return `${permission}${RESOURCE_PARAM_SEPARATOR}${tail}`;
|
|
98
|
-
};
|
|
80
|
+
export const gateParamHelper = createGateParamHelper();
|
|
81
|
+
/** @deprecated compat:factory-refactor — use `gateParamHelper.parseGateParam(…)` */
|
|
82
|
+
export const parseGateParam = (param) => gateParamHelper.parseGateParam(param);
|
|
99
83
|
//# sourceMappingURL=param.js.map
|
package/build/gate/param.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"param.js","sourceRoot":"","sources":["../../src/gate/param.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EAAE,yBAAyB,EAAE,uBAAuB,EAC3D,kBAAkB,EAAE,0BAA0B,EAChE,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE3C
|
|
1
|
+
{"version":3,"file":"param.js","sourceRoot":"","sources":["../../src/gate/param.ts"],"names":[],"mappings":"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"}
|
package/build/gate/resolve.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/gate/resolve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/gate/resolve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AA4E/F;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,QACzB,eAAe,YAAY,oBAAoB,KACnD,sBA2BF,CAAA"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { GateParamSource, GateParamErrorCode, GateResolutionFailure } from '../consts.js';
|
|
2
|
+
/**
|
|
3
|
+
* The parts of a request a gate selector may read.
|
|
4
|
+
*
|
|
5
|
+
* Structural on purpose: `AbstractRequest` is assignable to it, so `@owlmeans/server-iam` passes its
|
|
6
|
+
* request straight through, while tooling outside the server stack can resolve a selector against a
|
|
7
|
+
* plain object without taking a dependency on `@owlmeans/entrypoint`.
|
|
8
|
+
*/
|
|
9
|
+
export interface GateRequestLike {
|
|
10
|
+
params?: unknown;
|
|
11
|
+
query?: unknown;
|
|
12
|
+
body?: unknown;
|
|
13
|
+
headers?: unknown;
|
|
14
|
+
auth?: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** Where one gate param reads its resource id from. */
|
|
17
|
+
export interface GateResourceSelector {
|
|
18
|
+
/** The selector text exactly as written, for diagnostics. */
|
|
19
|
+
readonly selector: string;
|
|
20
|
+
/** Undefined for the bare form, which searches `sources` in order. */
|
|
21
|
+
readonly source?: GateParamSource;
|
|
22
|
+
/** Length 1 and UNSPLIT for the bare form — a bare key may legally contain dots. */
|
|
23
|
+
readonly path: string[];
|
|
24
|
+
/** The explicit source, or `DEFAULT_GATE_PARAM_SOURCES`. */
|
|
25
|
+
readonly sources: GateParamSource[];
|
|
26
|
+
}
|
|
27
|
+
export interface GateParamProblem {
|
|
28
|
+
code: GateParamErrorCode;
|
|
29
|
+
detail: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ParsedGateParam {
|
|
32
|
+
permission: string;
|
|
33
|
+
/**
|
|
34
|
+
* @deprecated The bare-form flat key, kept so existing readers keep compiling. Read `resource`,
|
|
35
|
+
* which carries the source and the path for both forms.
|
|
36
|
+
*/
|
|
37
|
+
resourceParam?: string;
|
|
38
|
+
resource?: GateResourceSelector;
|
|
39
|
+
error?: GateParamProblem;
|
|
40
|
+
}
|
|
41
|
+
export interface GateResourceResolution {
|
|
42
|
+
id?: string;
|
|
43
|
+
from?: GateParamSource;
|
|
44
|
+
reason?: GateResolutionFailure;
|
|
45
|
+
}
|
|
46
|
+
/** What an entrypoint declares, so a selector can be checked against it before it is ever deployed. */
|
|
47
|
+
export interface GateParamAudit {
|
|
48
|
+
routePath?: string;
|
|
49
|
+
routeParams?: string[];
|
|
50
|
+
filter?: {
|
|
51
|
+
query?: object;
|
|
52
|
+
params?: object;
|
|
53
|
+
body?: object;
|
|
54
|
+
headers?: object;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export interface GateParamIssue {
|
|
58
|
+
param: string;
|
|
59
|
+
code: GateParamErrorCode;
|
|
60
|
+
detail: string;
|
|
61
|
+
}
|
|
62
|
+
/** The gate-param grammar: `<permission>@<selector>` read, written and taken apart. */
|
|
63
|
+
export interface GateParamHelper {
|
|
64
|
+
/**
|
|
65
|
+
* Read the `@…` half of a gate param.
|
|
66
|
+
*
|
|
67
|
+
* Two forms, and the difference between them is deliberate:
|
|
68
|
+
*
|
|
69
|
+
* `@enquiryId` — bare. A FLAT key, searched in `params` then `query`. It is never split on
|
|
70
|
+
* a dot, because a query key legally contains one and splitting it would
|
|
71
|
+
* change the meaning of selectors already deployed.
|
|
72
|
+
* `@body:order.id` — qualified. An explicit source and a nested path.
|
|
73
|
+
*
|
|
74
|
+
* The rule worth remembering: the bare form is lenient and flat, the qualified form is strict and
|
|
75
|
+
* nested.
|
|
76
|
+
*/
|
|
77
|
+
parseGateSelector: (selector: string) => GateResourceSelector | GateParamProblem;
|
|
78
|
+
/**
|
|
79
|
+
* Split a gate param into the permission it checks and where the resource id comes from.
|
|
80
|
+
*
|
|
81
|
+
* Splits at the FIRST `@`. Everything before it is the permission name looked up in the subject's
|
|
82
|
+
* grants; everything after says where to read the resource id at request time. The suffix is the
|
|
83
|
+
* gate's syntax and nothing else's — a permission stored or granted under a name containing one is a
|
|
84
|
+
* key nothing ever looks up.
|
|
85
|
+
*/
|
|
86
|
+
parseGateParam: (param: string) => ParsedGateParam;
|
|
87
|
+
/** Compose a gate param. The inverse of `parseGateParam` for every selector it accepts. */
|
|
88
|
+
formatGateParam: (permission: string, selector?: string | {
|
|
89
|
+
source?: GateParamSource;
|
|
90
|
+
path: string[];
|
|
91
|
+
}) => string;
|
|
92
|
+
}
|
|
93
|
+
/** Gate params checked against the entrypoint that declares them. */
|
|
94
|
+
export interface GateValidationHelper {
|
|
95
|
+
/** The `:name` segments of a route template. */
|
|
96
|
+
routeParamsOf: (path: string) => string[];
|
|
97
|
+
/**
|
|
98
|
+
* Check gate params against what their entrypoint declares.
|
|
99
|
+
*
|
|
100
|
+
* Reports only what is provable from the declaration itself. Anything that would need a guess is
|
|
101
|
+
* left alone: a check that fires on correct code stops being read.
|
|
102
|
+
*
|
|
103
|
+
* Meant to run where a mistake can still be fixed — while code is being generated, or once per alias
|
|
104
|
+
* as a diagnostic. It must never decide a request: with `some()` semantics across params, one
|
|
105
|
+
* malformed sibling must not be able to refuse a legitimately passing one.
|
|
106
|
+
*/
|
|
107
|
+
validateGateParams: (params: string[], audit?: GateParamAudit) => GateParamIssue[];
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gate/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAE9F;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sEAAsE;IACtE,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAA;IACjC,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,kBAAkB,CAAA;IACxB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,oBAAoB,CAAA;IAC/B,KAAK,CAAC,EAAE,gBAAgB,CAAA;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,MAAM,CAAC,EAAE,qBAAqB,CAAA;CAC/B;AAED,uGAAuG;AACvG,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,kBAAkB,CAAA;IACxB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,uFAAuF;AACvF,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;;;OAYG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,oBAAoB,GAAG,gBAAgB,CAAA;IAChF;;;;;;;OAOG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,eAAe,CAAA;IAClD,2FAA2F;IAC3F,eAAe,EAAE,CACf,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,eAAe,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,KAC7D,MAAM,CAAA;CACZ;AAED,qEAAqE;AACrE,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;IACzC;;;;;;;;;OASG;IACH,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,cAAc,KAAK,cAAc,EAAE,CAAA;CACnF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/gate/types.ts"],"names":[],"mappings":""}
|
package/build/gate/validate.d.ts
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
4
|
-
/**
|
|
5
|
-
* Check gate params against what their entrypoint declares.
|
|
6
|
-
*
|
|
7
|
-
* Reports only what is provable from the declaration itself. Anything that would need a guess is
|
|
8
|
-
* left alone: a check that fires on correct code stops being read.
|
|
9
|
-
*
|
|
10
|
-
* Meant to run where a mistake can still be fixed — while code is being generated, or once per alias
|
|
11
|
-
* as a diagnostic. It must never decide a request: with `some()` semantics across params, one
|
|
12
|
-
* malformed sibling must not be able to refuse a legitimately passing one.
|
|
13
|
-
*/
|
|
14
|
-
export declare const validateGateParams: (params: string[], audit?: GateParamAudit) => GateParamIssue[];
|
|
1
|
+
import type { GateValidationHelper } from './types.js';
|
|
2
|
+
export declare const createGateValidationHelper: () => GateValidationHelper;
|
|
3
|
+
export declare const gateValidationHelper: GateValidationHelper;
|
|
15
4
|
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/gate/validate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/gate/validate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAwD,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAI5G,eAAO,MAAM,0BAA0B,QAAO,oBAkH7C,CAAA;AAED,eAAO,MAAM,oBAAoB,sBAA+B,CAAA"}
|