@owlmeans/iam 0.1.18-rc.9 → 0.1.18
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 +185 -15
- package/agent-meta/manifest.json +92 -4
- package/agent-meta/skills/iam/SKILL.md +91 -177
- package/agent-meta/skills/iam/parts/clients.md +93 -0
- package/agent-meta/skills/iam/parts/permissions.md +106 -0
- package/agent-meta/skills/iam/parts/service.md +115 -0
- package/agent-meta/skills/iam/parts/tenancy.md +72 -0
- package/build/consts.d.ts +170 -1
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +221 -0
- package/build/consts.js.map +1 -1
- package/build/consts.local.d.ts +58 -0
- package/build/consts.local.d.ts.map +1 -0
- package/build/consts.local.js +21 -0
- package/build/consts.local.js.map +1 -0
- package/build/errors.d.ts +26 -0
- package/build/errors.d.ts.map +1 -1
- package/build/errors.js +38 -0
- package/build/errors.js.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/consts.local.d.ts +2 -0
- package/build/gate/consts.local.d.ts.map +1 -0
- package/build/gate/consts.local.js +3 -0
- package/build/gate/consts.local.js.map +1 -0
- package/build/gate/index.d.ts +4 -0
- package/build/gate/index.d.ts.map +1 -0
- package/build/gate/index.js +4 -0
- package/build/gate/index.js.map +1 -0
- package/build/gate/param.d.ts +6 -0
- package/build/gate/param.d.ts.map +1 -0
- package/build/gate/param.js +83 -0
- package/build/gate/param.js.map +1 -0
- package/build/gate/resolve.d.ts +10 -0
- package/build/gate/resolve.d.ts.map +1 -0
- package/build/gate/resolve.js +93 -0
- package/build/gate/resolve.js.map +1 -0
- 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/types.local.d.ts +5 -0
- package/build/gate/types.local.d.ts.map +1 -0
- package/build/gate/types.local.js +2 -0
- package/build/gate/types.local.js.map +1 -0
- package/build/gate/validate.d.ts +4 -0
- package/build/gate/validate.d.ts.map +1 -0
- package/build/gate/validate.js +100 -0
- package/build/gate/validate.js.map +1 -0
- package/build/index.d.ts +9 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -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 +8 -0
- package/build/permission.d.ts.map +1 -0
- package/build/permission.js +34 -0
- package/build/permission.js.map +1 -0
- 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 +75 -0
- package/build/runtime.d.ts.map +1 -0
- package/build/runtime.js +75 -0
- package/build/runtime.js.map +1 -0
- package/build/schemas.d.ts +13 -0
- package/build/schemas.d.ts.map +1 -0
- package/build/schemas.js +108 -0
- package/build/schemas.js.map +1 -0
- package/build/types.d.ts +429 -30
- 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 +7 -6
- package/build/utils.d.ts.map +1 -1
- package/build/utils.js +10 -1
- package/build/utils.js.map +1 -1
- package/package.json +12 -7
- package/src/consts.local.ts +26 -0
- package/src/consts.ts +241 -1
- package/src/errors.ts +44 -0
- package/src/facet.ts +17 -0
- package/src/gate/consts.local.ts +3 -0
- package/src/gate/index.ts +3 -0
- package/src/gate/param.ts +108 -0
- package/src/gate/resolve.ts +114 -0
- package/src/gate/types.local.ts +4 -0
- package/src/gate/types.ts +117 -0
- package/src/gate/validate.ts +123 -0
- package/src/index.ts +9 -0
- package/src/permission/types.ts +33 -0
- package/src/permission.ts +48 -0
- package/src/runtime/types.ts +107 -0
- package/src/runtime.ts +142 -0
- package/src/schemas.ts +122 -0
- package/src/types.ts +492 -31
- package/src/utils/types.ts +11 -0
- package/src/utils.ts +12 -7
- package/tests/gate-param.spec.ts +233 -0
- package/tests/runtime.spec.ts +101 -0
- package/tests/tsconfig.json +12 -0
- package/tests/utils.spec.ts +47 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clients
|
|
3
|
+
description: Provisioning OIDC clients — globally unique client ids, the realm field, issuer and redirect-URI rules — and selecting the IAM backend.
|
|
4
|
+
metadata:
|
|
5
|
+
purposes: auth, config
|
|
6
|
+
mentions: claimClient, deleteClient, getIssuerUrl, redirectUris, IamClientError, IAM_MODE_INTEGRATED, IAM_MODE_KEYCLOAK, iamMode, IamClient
|
|
7
|
+
---
|
|
8
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
9
|
+
|
|
10
|
+
# @owlmeans/iam — Clients, issuers and backend selection
|
|
11
|
+
|
|
12
|
+
## A client id is a global name
|
|
13
|
+
|
|
14
|
+
A provider resolves a client from the bare `client_id` a relying party sends — the adapter gets no
|
|
15
|
+
tenant context — so the id is unique across the whole deployment, not per entity, and the store
|
|
16
|
+
cannot namespace it on a consumer's behalf. Uniqueness has to be *in the id*.
|
|
17
|
+
|
|
18
|
+
- Compose it with the owning entity in it. A name derived from a project's own name alone lets two
|
|
19
|
+
organizations share one registration: one secret, one redirect-URI list, one permission-definition
|
|
20
|
+
set, and one grant namespace, because `PermissionSet.scope` is that same string.
|
|
21
|
+
- `ensureClient` refuses a record belonging to another entity rather than returning it. The failure
|
|
22
|
+
is deliberate — a loud provisioning error is the only alternative to a silent cross-tenant handover.
|
|
23
|
+
- Assign an id **once** and reserve it with `claimClient`. Whatever a consumer derives ids from
|
|
24
|
+
(a project alias, a slug) may later be released and re-used by a sibling, so only the registry can
|
|
25
|
+
say whether an id is free. `deleteClient` gives it back, or a deleted project's name is burned.
|
|
26
|
+
- Backends whose clients are already per-tenant (keycloak realms) satisfy this by construction:
|
|
27
|
+
`claimClient` returns true and `deleteClient` may be `IamUnsupported`.
|
|
28
|
+
|
|
29
|
+
## `IamClient.realm` field
|
|
30
|
+
|
|
31
|
+
Every implementation sets `realm` to the entity id, so read `client.realm ?? fallbackEntityId` and
|
|
32
|
+
never reach into an adapter's own internals (`(client as any)._realm`) for the same value.
|
|
33
|
+
|
|
34
|
+
## Issuer & redirect URIs
|
|
35
|
+
|
|
36
|
+
**`getIssuerUrl(entityId)` is the only place an issuer URL may be composed.** Consumers pass the
|
|
37
|
+
result straight through as `OidcProviderDescriptor.discoveryUrl`; they must never rebuild it from a
|
|
38
|
+
host plus a base path. Each backend owns its own shape (keycloak `{iam-host}/realms/{entityId}`,
|
|
39
|
+
integrated `{provider-host}/{basePath}`), and an implementation must:
|
|
40
|
+
|
|
41
|
+
- resolve it from configuration only — no admin round-trip, so a consumer that just needs the issuer
|
|
42
|
+
never pays for or fails on a token grant;
|
|
43
|
+
- return exactly what the provider advertises as `issuer` (`openid-client` compares the two and fails
|
|
44
|
+
discovery on any difference — build it with the same `makeUrl(..., { base: true })` call
|
|
45
|
+
`@owlmeans/server-oidc-provider` uses);
|
|
46
|
+
- throw `IamClientError` when the provider's service route is missing, never fall back silently.
|
|
47
|
+
|
|
48
|
+
`getEntityAdminConfig` additionally carries the same value as `discoveryUrl`, so the admin provider
|
|
49
|
+
config is self-sufficient too.
|
|
50
|
+
|
|
51
|
+
**Always pass `redirectUris`.** Omitting them is a keycloak-only legacy default (`['*']`, which
|
|
52
|
+
Keycloak expands per-origin). The integrated provider does exact `redirect_uri` matching and
|
|
53
|
+
`oidc-provider` refuses to load a client whose `redirect_uris` are not absolute URIs — so an
|
|
54
|
+
integrated backend's `ensureClient` throws `IamClientError('redirect-uris')` on creation rather than
|
|
55
|
+
registering a client that can never complete a callback. An omitted list never widens an existing
|
|
56
|
+
hardened client.
|
|
57
|
+
|
|
58
|
+
## Selecting the IAM backend
|
|
59
|
+
|
|
60
|
+
The choice is made **once, in a service factory**, and nowhere else. Feature code depends on
|
|
61
|
+
`IamService` and never learns which implementation answers it. `IAM_MODE_INTEGRATED` /
|
|
62
|
+
`IAM_MODE_KEYCLOAK` and `OidcIamConfig.iamMode` (`@owlmeans/oidc`) exist so a deployment can carry
|
|
63
|
+
that choice as ordinary configuration rather than as a branch scattered through handlers. No OwlMeans
|
|
64
|
+
package reads `iamMode`; it is declared for the consumer's own factory to switch on, which is the
|
|
65
|
+
only thing that may branch.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { DEFAULT_ALIAS, IAM_MODE_INTEGRATED, IAM_MODE_KEYCLOAK } from '@owlmeans/iam'
|
|
69
|
+
import type { IamMode, IamService } from '@owlmeans/iam'
|
|
70
|
+
|
|
71
|
+
// makeKeycloakAdapter / makeIntegratedAdapter are PLACEHOLDER names standing in for whichever
|
|
72
|
+
// adapter packages the deployment installs — this factory is the one place either is named, and
|
|
73
|
+
// every consumer resolves IamService by alias instead. An adapter exposes a
|
|
74
|
+
// `(alias?: string, options?: object) => IamService` factory whose alias defaults to DEFAULT_ALIAS.
|
|
75
|
+
export const makeIamService = (mode: IamMode = IAM_MODE_INTEGRATED): IamService =>
|
|
76
|
+
mode === IAM_MODE_KEYCLOAK
|
|
77
|
+
? makeKeycloakAdapter(DEFAULT_ALIAS, /* adapter options */)
|
|
78
|
+
: makeIntegratedAdapter(DEFAULT_ALIAS, /* adapter options */)
|
|
79
|
+
|
|
80
|
+
// cfg.oidc typed as OidcSharedConfig & OidcIamConfig is what carries the mode
|
|
81
|
+
context.registerService(makeIamService(cfg.oidc?.iamMode))
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
An adapter that reassembles the issuer from a registered service alias plus a base path must be given
|
|
85
|
+
the **consumer's own** alias and path. Whatever an adapter defaults to is a placeholder, and a
|
|
86
|
+
mismatch makes every service lookup behind `getIssuerUrl` miss.
|
|
87
|
+
|
|
88
|
+
An integrated backend — one built on `@owlmeans/server-oidc-provider`, so the deployment hosts its
|
|
89
|
+
own provider — is the default choice; a Keycloak-backed adapter exists for deployments that already
|
|
90
|
+
run one.
|
|
91
|
+
|
|
92
|
+
When a context hosts **more than one** `IamService` instance, every instance must be constructed with
|
|
93
|
+
the same options — otherwise they disagree about the issuer, and only one of them can be right.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: permissions
|
|
3
|
+
description: Permission names and grant forms, IamGrantMode, the four permission kinds, default classes and restrictions.
|
|
4
|
+
metadata:
|
|
5
|
+
purposes: auth
|
|
6
|
+
mentions: hasPermission, grantPermission, revokePermission, ensurePermission, IamGrantMode, IamDefaultClass, composePermissionName, parsePermissionName, entityScoped, resourceScoped, defaultClass
|
|
7
|
+
---
|
|
8
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
9
|
+
|
|
10
|
+
# @owlmeans/iam — Permission model
|
|
11
|
+
|
|
12
|
+
## Permission model (kinds and grant forms)
|
|
13
|
+
|
|
14
|
+
Permissions are declared per entity client (project) with `ensurePermission` and granted to end-user
|
|
15
|
+
subjects with `grantPermission`:
|
|
16
|
+
|
|
17
|
+
- **Unscoped (project-wide)**: `grantPermission(entityId, clientId, profileId, 'article--modify')`
|
|
18
|
+
- **Resource-scoped**: `grantPermission(entityId, clientId, profileId, 'department--modify', { resources: ['dep-123'] })` —
|
|
19
|
+
the grant only applies to the listed resource ids.
|
|
20
|
+
|
|
21
|
+
Grants materialize as OwlMeans `PermissionSet[]` (`scope` = clientId; resource-scoped grants live in a
|
|
22
|
+
dedicated set per permission carrying `resources[]`, because `resources` applies to all keys of a set).
|
|
23
|
+
|
|
24
|
+
A **name** is `<resource>--<action>`, with two hyphens. One hyphen is not a separator: `enquiry-view`
|
|
25
|
+
is a resource named `enquiry-view` with no action, and it must keep parsing that way, because a name
|
|
26
|
+
already granted somewhere cannot be reinterpreted without orphaning the grant. Build and read names
|
|
27
|
+
through `composePermissionName` / `parsePermissionName` rather than splitting strings.
|
|
28
|
+
|
|
29
|
+
`resourceScoped: true` says a permission *may* be bound to resource ids, not that it must be. The
|
|
30
|
+
same name is grantable in both forms and they are stored separately, which is what `IamGrantMode`
|
|
31
|
+
addresses: `Blanket` is the set carrying no `resources` (and `hasPermission` reads it as covering
|
|
32
|
+
every id), `Resources` is an explicit id list, `All` (revoke-only) is every form, and `Inherit`
|
|
33
|
+
(revoke-only) is the subject's own blanket value — see "Restrictions". A grant in `All` or `Inherit`
|
|
34
|
+
is refused (`IamGrantError('mode:all-is-revoke-only')`, `'mode:inherit-is-revoke-only'`). The
|
|
35
|
+
defaults are asymmetric on purpose — `grantPermission` defaults to `Blanket`, `revokePermission` to
|
|
36
|
+
`All`, because a bare revoke has always meant "remove it everywhere". Pass `mode` explicitly rather
|
|
37
|
+
than relying on either.
|
|
38
|
+
|
|
39
|
+
`area` is a presentational grouping tag (`IAM_AREAS`, or any string a deployment defines) and decides
|
|
40
|
+
nothing at request time. `managed: true` marks a definition the platform owns: an operator cannot
|
|
41
|
+
revoke it from an undifferentiated list, and a repair that deletes "definitions no declaration names"
|
|
42
|
+
must not reach one.
|
|
43
|
+
|
|
44
|
+
### Permission kinds
|
|
45
|
+
|
|
46
|
+
What a grant binds to is a property of the DEFINITION, and grants follow it:
|
|
47
|
+
|
|
48
|
+
| Kind | Definition flags | Grant stored on | Applies |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| unbound | none | the subject's primary row, or a group | everywhere |
|
|
51
|
+
| entity-bound | `entityScoped` | the subject's row of THAT organization, or a group of it | only while acting in that organization |
|
|
52
|
+
| resource-bound | `resourceScoped` | the primary row, a titled set with `resources` | to those resource ids |
|
|
53
|
+
| both | both | that organization's row, a titled set with `resources` | both checks |
|
|
54
|
+
|
|
55
|
+
- Granting an `entityScoped` definition REQUIRES `args.entitySlug`, which names the subject's row
|
|
56
|
+
there — the subject must be a member. Any other definition refuses `args.entitySlug`. Turning
|
|
57
|
+
`entityScoped` off while grants exist is refused: every bound grant would silently widen.
|
|
58
|
+
- Stored sets carry the organization's id; CLAIM sets (provider → relying party only) carry its
|
|
59
|
+
`entitySlug` instead (`OidcPermissionSetClaim`). The relying party keeps the unbound sets and the
|
|
60
|
+
acting organization's, strips the binding, and drops the rest — a browser token never carries a
|
|
61
|
+
bound set of another organization.
|
|
62
|
+
- `hasPermission(auth, name, { entitySlug })` applies a set without `entitySlug` everywhere and a
|
|
63
|
+
bound one only when `opts.entitySlug` names its organization — fail-closed, so a bound set that
|
|
64
|
+
leaked into a token never counts where the caller named no organization.
|
|
65
|
+
|
|
66
|
+
### Default classes
|
|
67
|
+
|
|
68
|
+
`defaultClass` says who holds a definition without an explicit grant. It is evaluated when claims and
|
|
69
|
+
grant listings are built — never written onto a row:
|
|
70
|
+
|
|
71
|
+
- `User` — every signed-in subject of the client. Requires an unbound, unmanaged `user`-area definition.
|
|
72
|
+
- `Member` / `Owner` — every member / owner of the organization the subject acts in. Requires
|
|
73
|
+
`entityScoped`.
|
|
74
|
+
- `None` — nobody.
|
|
75
|
+
|
|
76
|
+
A class default is a BLANKET set, so `Owner` on a resource-scoped definition is its all-records form.
|
|
77
|
+
A listing marks each grant's `origin`: `Direct`, `Default`, or `Group` with `through` naming the
|
|
78
|
+
group. A backend that cannot evaluate classes (Keycloak) refuses any `defaultClass` other than
|
|
79
|
+
`None` with `IamUnsupported`.
|
|
80
|
+
|
|
81
|
+
### Restrictions
|
|
82
|
+
|
|
83
|
+
Every subject — a person or a group — has ONE blanket value of its own per binding: `true` grants,
|
|
84
|
+
`false` RESTRICTS, absent inherits. A subject holds a name when its own value is `true`, or when it is
|
|
85
|
+
not `false` and something it inherits grants it.
|
|
86
|
+
|
|
87
|
+
| Subject | Inherits from | Its own value lives on |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| person | class defaults, its groups' grants and its groups' bundles | the primary row (unbound definition); the row of the binding's organization (bound — for a group-derived name, the row that names the group) |
|
|
90
|
+
| group | its bundles | the group's own blanket set |
|
|
91
|
+
|
|
92
|
+
- A restriction withholds every INHERITED form of the name in that binding — a class default, a
|
|
93
|
+
group's blanket grant, a group's per-record grant, a bundle's selection. The subject's OWN grants,
|
|
94
|
+
per-record ones included, are never cut. A group's restriction cuts only its own bundles, for all
|
|
95
|
+
its members; another group granting the name still grants it.
|
|
96
|
+
- A `Blanket` or `All` revoke of a DECLARED definition writes the restriction (an undeclared name gets
|
|
97
|
+
none). `Inherit` drops the subject's own value — grant or restriction — writes nothing in its
|
|
98
|
+
place, leaves resource-scoped sets alone and ignores `resources`; a bound definition needs
|
|
99
|
+
`entitySlug` for it as for `Blanket`. A later `Blanket` grant overwrites a restriction with `true`.
|
|
100
|
+
- Tokens carry only what is held: a relying party never sees a restriction, only fewer permissions.
|
|
101
|
+
- Listings (`listGrants`, `groups.grants`) answer what is held; `IamGrantListArgs.restricted` adds
|
|
102
|
+
the inherited grants the subject's own restriction withholds as `restricted: true` (same `origin` /
|
|
103
|
+
`through` as the held form), so a console can show them and lift them with `Inherit`. A user's
|
|
104
|
+
`grantCount` counts held grants only.
|
|
105
|
+
- A backend without inheritance (Keycloak) has nothing to restrict: every revoke, `Inherit`
|
|
106
|
+
included, removes the role, and a listing ignores `restricted`.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: service
|
|
3
|
+
description: The full IamService interface with its per-method contracts, and the per-client user operations.
|
|
4
|
+
metadata:
|
|
5
|
+
purposes: auth, server-api
|
|
6
|
+
mentions: IamService, getEntityAdminConfig, ensureClient, getClient, grantBundle, listGrants, listUsers, inviteUser, updateUser, removeUser, syncStaff, normalizePermissions, deletePermission
|
|
7
|
+
---
|
|
8
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
9
|
+
|
|
10
|
+
# @owlmeans/iam — The IamService interface
|
|
11
|
+
|
|
12
|
+
## `IamService` interface
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
interface IamService extends InitializedService {
|
|
16
|
+
// The tenant's admin OIDC provider config, and a raw admin { token, realm } pair.
|
|
17
|
+
getEntityAdminConfig: (entityId: string) => Promise<OidcProviderConfig>
|
|
18
|
+
getCredentialsPair: (entityId: string) => Promise<IamCredentialsPair>
|
|
19
|
+
|
|
20
|
+
// The tenant's public issuer URL — see "Issuer & redirect URIs" (the clients part).
|
|
21
|
+
getIssuerUrl: (entityId: string) => Promise<string>
|
|
22
|
+
|
|
23
|
+
// Provision an OIDC client for a tenant — see "Issuer & redirect URIs" and
|
|
24
|
+
// "A client id is a global name" (the clients part) for the two rules it has to obey.
|
|
25
|
+
ensureClient: (entityId: string, clientId: string, options?: IamClientOptions) => Promise<IamClient>
|
|
26
|
+
|
|
27
|
+
// The entity's client without its secret, or null. Never provisions.
|
|
28
|
+
getClient: (entityId: string, clientId: string) => Promise<IamClientInfo | null>
|
|
29
|
+
|
|
30
|
+
// Reserve a free client id without provisioning it; false when anyone else holds it.
|
|
31
|
+
claimClient: (entityId: string, clientId: string) => Promise<boolean>
|
|
32
|
+
|
|
33
|
+
// Release a client id and everything keyed by it — its subjects' rows, its groups, its
|
|
34
|
+
// definitions (called when a project/slot is deleted).
|
|
35
|
+
deleteClient: (entityId: string, clientId: string) => Promise<void>
|
|
36
|
+
|
|
37
|
+
// Declare a permission. Returns the canonical name. MERGES into an existing definition —
|
|
38
|
+
// resource/action re-derived, omitted flags kept — and NEVER rewrites the name. Refuses a
|
|
39
|
+
// `resource` carrying an `@` selector.
|
|
40
|
+
ensurePermission: (entityId: string, clientId: string, resource?: string, args?: IamPermissionArgs) => Promise<string>
|
|
41
|
+
|
|
42
|
+
// Remove definitions BY NAME, and by default their grants. Idempotent ({ found: false } when
|
|
43
|
+
// absent). Grants go first: a crash between the stores must leave a definition with no grants,
|
|
44
|
+
// never grants with no definition. A `managed` definition needs args.managed === true.
|
|
45
|
+
deletePermission: (entityId: string, clientId: string, permission: string | string[], args?: IamPermissionDeleteArgs) => Promise<IamPermissionRemoval[]>
|
|
46
|
+
|
|
47
|
+
// Repair definitions whose stored name leaked a gate selector, moving grants in the same write.
|
|
48
|
+
// A rename and a merge — never a delete, never an invention.
|
|
49
|
+
normalizePermissions: (entityId: string, clientId: string, args?: IamNormalizeArgs) => Promise<IamNormalizationReport>
|
|
50
|
+
|
|
51
|
+
// Provision a resource and assign it to the tenant's owner role (keycloak). A no-op on the
|
|
52
|
+
// integrated backend, which has no owner role to assign to.
|
|
53
|
+
ensureResourceOwnership: (entityId: string, clientId: string, resource: IamResourceSpec) => Promise<void>
|
|
54
|
+
|
|
55
|
+
// --- Authorization (permission definitions & grants) ---
|
|
56
|
+
|
|
57
|
+
listPermissions: (entityId: string, clientId: string, filter?: IamPermissionFilter) => Promise<IamPermissionDefinition[]>
|
|
58
|
+
|
|
59
|
+
// args.resources selects the resource-scoped form, args.entitySlug the binding of an entityScoped
|
|
60
|
+
// definition; see "Permission model (kinds and grant forms)" in the permissions part. A
|
|
61
|
+
// blanket/all revoke of a declared definition RESTRICTS; mode Inherit takes the own value
|
|
62
|
+
// back — see "Restrictions" there
|
|
63
|
+
grantPermission: (entityId: string, clientId: string, profileId: string, permission: string, args?: IamGrantArgs) => Promise<IamGrant>
|
|
64
|
+
revokePermission: (entityId: string, clientId: string, profileId: string, permission: string, args?: IamGrantArgs) => Promise<void>
|
|
65
|
+
|
|
66
|
+
// Grant everything a bundle selects to each subject, idempotently, in ONE read and write per
|
|
67
|
+
// subject. Returns what each subject now holds, not what changed. Use it instead of looping over
|
|
68
|
+
// grantPermission, which costs N·M writes and N·M lost-update windows on the same records.
|
|
69
|
+
grantBundle: (entityId: string, clientId: string, profileIds: string[], bundle: IamGrantBundle) => Promise<IamGrant[]>
|
|
70
|
+
|
|
71
|
+
// Direct, default-class and group grants, each with its `origin` — what is HELD; args.restricted
|
|
72
|
+
// adds what the subject's own restrictions withhold (`restricted: true`).
|
|
73
|
+
listGrants: (entityId: string, clientId: string, profileId?: string, args?: IamGrantListArgs) => Promise<IamGrant[]>
|
|
74
|
+
|
|
75
|
+
// --- Users of one client — see "Users are per client" ---
|
|
76
|
+
|
|
77
|
+
listUsers: (entityId: string, clientId?: string) => Promise<IamUser[]>
|
|
78
|
+
getUser: (entityId: string, clientId: string, profileId: string) => Promise<IamUser | null>
|
|
79
|
+
inviteUser: (entityId: string, clientId: string, invite: IamUserInvite) => Promise<IamUser>
|
|
80
|
+
updateUser: (entityId: string, clientId: string, profileId: string, update: IamUserUpdate) => Promise<IamUser>
|
|
81
|
+
removeUser: (entityId: string, clientId: string, profileId: string) => Promise<void>
|
|
82
|
+
|
|
83
|
+
// The owning organization's staff, admitted to the client through the managed `members` group.
|
|
84
|
+
syncStaff: (entityId: string, clientId: string, args: IamStaffSyncArgs) => Promise<IamStaffSyncReport>
|
|
85
|
+
|
|
86
|
+
// --- Tenancy facets — see "Organizations, groups and subjects" (the tenancy part) ---
|
|
87
|
+
organizations: IamOrganizationFacet
|
|
88
|
+
groups: IamGroupFacet
|
|
89
|
+
subjects: IamSubjectFacet
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The first parameter of every method is `entityId` — the organization that OWNS the client — and
|
|
94
|
+
every `(entityId, clientId)` method verifies that ownership before it reads or writes anything. The
|
|
95
|
+
organizations a client's subjects act in are a different thing, named by `entitySlug` inside the
|
|
96
|
+
facets.
|
|
97
|
+
|
|
98
|
+
## Users are per client
|
|
99
|
+
|
|
100
|
+
A person is ONE account (one per e-mail address); what a client sees of it are its rows of that app —
|
|
101
|
+
one per (account, app, organization), the PRIMARY one in the account's own organization. The
|
|
102
|
+
`profileId` a client knows is the pairwise subject, the same on every row of one (account, app) and
|
|
103
|
+
different for every app, so two apps of one customer cannot correlate their users by it.
|
|
104
|
+
|
|
105
|
+
- `listUsers(entityId, clientId)` lists every account holding a row of the client, in whichever
|
|
106
|
+
organization. Without `clientId` it is a read-only aggregate over the entity's clients, for a
|
|
107
|
+
console — nothing is written through it.
|
|
108
|
+
- `getUser` / `inviteUser` / `updateUser` / `removeUser` take the client. `removeUser` deletes this
|
|
109
|
+
account's rows of THAT app only — the account, and its rows of other apps, stay. `updateUser`
|
|
110
|
+
writes `disabled` on the primary row, which is what refuses the subject at the provider.
|
|
111
|
+
- `inviteUser` is idempotent by email, which is what lets an invitation and a first sign-in converge on
|
|
112
|
+
one record instead of accumulating twins.
|
|
113
|
+
|
|
114
|
+
A backend with no user store of its own — one where the customer manages users in the provider's own
|
|
115
|
+
console — throws `IamUnsupported('user-management')` from all five methods.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tenancy
|
|
3
|
+
description: The organizations, groups and subjects facets of IamService, and the runtime IAM API a tenanted client's server calls.
|
|
4
|
+
metadata:
|
|
5
|
+
purposes: auth, server-api
|
|
6
|
+
mentions: IamOrganizationFacet, IamGroupFacet, IamSubjectFacet, unsupportedFacet, IAM_MEMBERS_GROUP, makeIamRuntimeProtocols, IAM_RUNTIME_GUARD, IAM_RUNTIME_ROUTES, IAM_RUNTIME_PATH, iamRuntime
|
|
7
|
+
---
|
|
8
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
9
|
+
|
|
10
|
+
# @owlmeans/iam — Organizations, groups, subjects and the runtime API
|
|
11
|
+
|
|
12
|
+
## Organizations, groups and subjects
|
|
13
|
+
|
|
14
|
+
The three facets of `IamService` carry tenancy. A backend that cannot provide one answers
|
|
15
|
+
`unsupportedFacet<IamOrganizationFacet>('organizations')` (and so on): every method of it throws
|
|
16
|
+
`IamUnsupported(what)` SYNCHRONOUSLY, because `subjects.identify` is synchronous and a rejected
|
|
17
|
+
promise would hand it the wrong type — an awaited call rejects either way.
|
|
18
|
+
|
|
19
|
+
- **Tenancy is the client's configuration.** `IamClientConfig.users` / `.operators` turn it on: with
|
|
20
|
+
neither flag, every subject acts in the client's owning organization (a single-tenant app); with
|
|
21
|
+
either, each subject acts in organizations of its own and the provider claims them under the
|
|
22
|
+
`organizations` scope (`@owlmeans/oidc`). The flags also gate the runtime API's writes by area.
|
|
23
|
+
- **`organizations`** — `list`, `get`, `create({ title?, profileId? })` (that subject becomes the
|
|
24
|
+
owner), `update({ title })`, `members`, `addMember` (find-or-create by e-mail, idempotent, refused
|
|
25
|
+
past the membership cap), `updateMember`, `removeMember`. The last owner cannot be demoted or
|
|
26
|
+
removed (`IamOrganizationError`).
|
|
27
|
+
- **`groups`** — a group is (organization, client, key), kept inside the organization record; one
|
|
28
|
+
client never reads or writes another's. `list`, `ensure`, `remove`, `members`, `addMembers`,
|
|
29
|
+
`removeMembers`, `grant` / `revoke` (bound to the group's organization; a revoke restricts, as for
|
|
30
|
+
a person), `grants(…, key, args?)` (its own grants as `Direct`, the names its bundles select as
|
|
31
|
+
`Bundle`, minus what it restricts; `args.restricted` adds the cut bundle names), and `setBundles` —
|
|
32
|
+
a bundle (`{ filter?, permissions? }`) grants every definition it selects to the group's members at
|
|
33
|
+
claim time. `IAM_MEMBERS_GROUP` is the managed group `syncStaff` keeps in the owning organization:
|
|
34
|
+
its existence, key, membership and bundles are the sync's (`ensure`, `remove`, `addMembers`,
|
|
35
|
+
`removeMembers`, `setBundles` → `IamGroupError('managed:members')`), while its grants and
|
|
36
|
+
restrictions are the operator's (`grant` / `revoke`) and survive every sync.
|
|
37
|
+
- **`subjects`** — the provider's half, keyed by the ACCOUNT, which never leaves the provider.
|
|
38
|
+
`signIn(clientId, { email })` finds or creates the account and its rows for the client;
|
|
39
|
+
`resolve(clientId, accountId)` builds the `IamSubject` the claims come from (`null` = not admitted:
|
|
40
|
+
no row, or a disabled primary row); `identify(clientId, accountId)` is the pairwise `sub`.
|
|
41
|
+
|
|
42
|
+
## Runtime IAM API
|
|
43
|
+
|
|
44
|
+
`makeIamRuntimeProtocols({ service, path? })` declares the provider-side API a tenanted client's
|
|
45
|
+
server calls on behalf of its signed-in subject. It is declarations only: the provider binds it, and
|
|
46
|
+
a relying party calls it through `iamRuntime` (`@owlmeans/server-iam`) over plain `fetch`.
|
|
47
|
+
|
|
48
|
+
| Route (under `path`, default `IAM_RUNTIME_PATH`) | Tree | Who |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `GET /organizations` | `organizations.list` | any subject — its own |
|
|
51
|
+
| `POST /organizations` `{ title? }` | `organizations.create` | any subject of a tenanted client; it becomes owner |
|
|
52
|
+
| `POST /organizations/:entitySlug` `{ title }` | `organizations.update` | owner |
|
|
53
|
+
| `GET /organizations/:entitySlug/members` | `members.list` | member |
|
|
54
|
+
| `POST /organizations/:entitySlug/members` `{ email, name?, owner? }` | `members.add` | owner; idempotent by e-mail |
|
|
55
|
+
| `POST …/members/:profileId` `{ owner?, groups? }` | `members.update` | owner |
|
|
56
|
+
| `POST …/members/:profileId/remove` | `members.remove` | owner, or the member itself |
|
|
57
|
+
| `GET …/permissions` | `permissions.list` | member |
|
|
58
|
+
| `GET …/grants` `?profileId` | `grants.list` | owner |
|
|
59
|
+
| `POST …/grants`, `POST …/grants/revoke` `{ profileId, permission, resources?, mode? }` | `grants.assign` / `grants.revoke` (a revoke restricts; `mode: inherit` takes the own value back) | owner |
|
|
60
|
+
|
|
61
|
+
- **Every route, the base included, is pinned to `service`** — a route's service is never inherited
|
|
62
|
+
from its parent — and every leaf hangs under ONE base carrying `IAM_RUNTIME_GUARD`. The serving
|
|
63
|
+
process registers that guard: it admits only a bearer access token the provider issued, and takes
|
|
64
|
+
the client and the account from it, never from the request.
|
|
65
|
+
- **The wire names organizations by `entitySlug` and subjects by the calling client's pairwise
|
|
66
|
+
`profileId`** — no organization or account id appears in any shape. Every schema is closed, since
|
|
67
|
+
the server's AJV strips an undeclared key silently. `IAM_RUNTIME_ROUTES` is the one leaf-path table
|
|
68
|
+
the declarations and the fetch client share.
|
|
69
|
+
- The serving process enforces the write rules: only `entityScoped`, unmanaged definitions of the
|
|
70
|
+
CALLING client, binding forced to the path's organization, the last owner protected, the
|
|
71
|
+
membership cap, and only for an area the client's tenancy config opens (`users` → `user`,
|
|
72
|
+
`operators` → `operator`). A non-owner write is `AuthForbidden(ORGANIZATION_OWNER_REFUSAL)`.
|
package/build/consts.d.ts
CHANGED
|
@@ -1,5 +1,174 @@
|
|
|
1
|
+
import type { IamRuntimeAck, IamRuntimeGrantQuery, IamRuntimeMemberInvite, IamRuntimeMemberParams, IamRuntimeOrganizationCreate, IamRuntimeOrganizationParams, IamRuntimeOrganizationUpdate } from './runtime/types.js';
|
|
2
|
+
import type { JSONSchemaType } from 'ajv';
|
|
1
3
|
export declare const DEFAULT_ALIAS = "iam-service";
|
|
2
4
|
export declare const IAM_MODE_KEYCLOAK = "keycloak";
|
|
3
5
|
export declare const IAM_MODE_INTEGRATED = "integrated";
|
|
4
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Gate-param syntax: `<permission>[@<selector>]`.
|
|
8
|
+
*
|
|
9
|
+
* The `@` belongs to the GATE and to nothing else. It says where a resource id is read from at
|
|
10
|
+
* request time; it is never part of a permission's stored NAME. A definition or a grant whose name
|
|
11
|
+
* carries one is a key nothing ever looks up, so every grant against it is a silent no-op.
|
|
12
|
+
*/
|
|
13
|
+
export declare const RESOURCE_PARAM_SEPARATOR = "@";
|
|
14
|
+
/**
|
|
15
|
+
* Separates an explicit source from its path: `@body:order.id`.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately `:` rather than a dot. Under a dotted-only form the meaning of a selector changes the
|
|
18
|
+
* moment a route gains a param named like a source keyword — `/report/:query` with `@query.id` flips
|
|
19
|
+
* from "the route param literally named `query.id`" to "the query string's `id`", redirecting an
|
|
20
|
+
* authorization lookup from a router-matched value to attacker-supplied input, caused by an
|
|
21
|
+
* unrelated route rename. `:` is decidable in one character, and no gate-param string written before
|
|
22
|
+
* this existed can contain one.
|
|
23
|
+
*/
|
|
24
|
+
export declare const RESOURCE_SOURCE_SEPARATOR = ":";
|
|
25
|
+
/** Separates path segments inside a qualified selector: `@body:order.id`. */
|
|
26
|
+
export declare const RESOURCE_PATH_SEPARATOR = ".";
|
|
27
|
+
/** Where a qualified selector may read a resource id from. */
|
|
28
|
+
export declare enum GateParamSource {
|
|
29
|
+
Params = "params",
|
|
30
|
+
Query = "query",
|
|
31
|
+
Body = "body",
|
|
32
|
+
Headers = "headers",
|
|
33
|
+
Auth = "auth"
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* What the bare form (`@enquiryId`) searches, in order.
|
|
37
|
+
*
|
|
38
|
+
* Params first, then query. The query fallback is legacy and deliberately kept: removing it would
|
|
39
|
+
* silently deny already-deployed applications whose selector happens to name a query key, and a
|
|
40
|
+
* silent denial inside a customer's running app is the worst available outcome.
|
|
41
|
+
*/
|
|
42
|
+
export declare const DEFAULT_GATE_PARAM_SOURCES: GateParamSource[];
|
|
43
|
+
/** Why a gate param is structurally wrong — a misconfiguration, not a failed authorization. */
|
|
44
|
+
export declare enum GateParamErrorCode {
|
|
45
|
+
UnknownSource = "gate-param:unknown-source",
|
|
46
|
+
EmptySelector = "gate-param:empty-selector",
|
|
47
|
+
EmptySegment = "gate-param:empty-segment",
|
|
48
|
+
/** Named a request key the entrypoint's filter does not declare — AJV strips it before the gate. */
|
|
49
|
+
UnreachableKey = "gate-param:unreachable-key",
|
|
50
|
+
/** Named a route param the entrypoint's own path does not carry. */
|
|
51
|
+
UnknownRouteParam = "gate-param:unknown-route-param"
|
|
52
|
+
}
|
|
53
|
+
/** Why a selector produced no resource id. */
|
|
54
|
+
export declare enum GateResolutionFailure {
|
|
55
|
+
/** The source exists, the path does not. */
|
|
56
|
+
NotProvided = "not-provided",
|
|
57
|
+
/** The request carries no such source at all. */
|
|
58
|
+
SourceMissing = "source-missing",
|
|
59
|
+
/** Resolved to an object or a multi-element array — refused rather than stringified. */
|
|
60
|
+
NotScalar = "not-scalar",
|
|
61
|
+
/** The selector itself did not parse. */
|
|
62
|
+
Malformed = "malformed"
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Which FORM of a grant an operation addresses.
|
|
66
|
+
*
|
|
67
|
+
* A resource-scoped permission is grantable two ways, under one name: `Blanket` (a PermissionSet
|
|
68
|
+
* carrying no `resources`, which `hasPermission` reads as covering every id) and `Resources` (an
|
|
69
|
+
* explicit id list). They are stored separately and must be revoked separately, or a UI offering
|
|
70
|
+
* both controls would have one silently wipe the other.
|
|
71
|
+
*
|
|
72
|
+
* Every subject, person or group, also has ONE blanket value of its own per binding: `true` grants,
|
|
73
|
+
* `false` RESTRICTS (it cuts what the subject would inherit from a default class, a group or a
|
|
74
|
+
* bundle), absent inherits. A `Blanket` or `All` revoke of a declared definition writes the
|
|
75
|
+
* restriction; `Inherit` takes the subject's own value back.
|
|
76
|
+
*/
|
|
77
|
+
export declare enum IamGrantMode {
|
|
78
|
+
Blanket = "blanket",
|
|
79
|
+
Resources = "resources",
|
|
80
|
+
/** Revoke-only: every form. Illegal on a grant. */
|
|
81
|
+
All = "all",
|
|
82
|
+
/**
|
|
83
|
+
* Revoke-only: drop the subject's OWN blanket value in the binding — a grant or a restriction —
|
|
84
|
+
* so it holds exactly what it inherits. Resource-scoped sets are untouched. Illegal on a grant.
|
|
85
|
+
*/
|
|
86
|
+
Inherit = "inherit"
|
|
87
|
+
}
|
|
88
|
+
/** What to do about grants that still reference a definition being removed. */
|
|
89
|
+
export declare enum IamRemovalPolicy {
|
|
90
|
+
/** Strip the permission from every subject of the entity, then drop the definition. */
|
|
91
|
+
Cascade = "cascade",
|
|
92
|
+
/** Refuse while any subject still holds it; the holders travel in the error. */
|
|
93
|
+
Refuse = "refuse"
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The grouping tiers a permission definition may be tagged with.
|
|
97
|
+
*
|
|
98
|
+
* A tag decides NOTHING at request time — `hasPermission` and every gate treat a permission name as
|
|
99
|
+
* one opaque string — and only groups the permission in an administrator's screen. `guest` is
|
|
100
|
+
* deliberately absent: a public surface declares no permissions, and adding an area later would
|
|
101
|
+
* re-classify names already tagged.
|
|
102
|
+
*/
|
|
103
|
+
export declare const IAM_AREAS: readonly ['user', 'operator', 'admin'];
|
|
104
|
+
/** Separates the resource from the action in a permission name. TWO hyphens, never one. */
|
|
105
|
+
export declare const PERMISSION_ACTION_SEPARATOR = "--";
|
|
106
|
+
/**
|
|
107
|
+
* Who holds a permission without an explicit grant — a property of the DEFINITION, evaluated when
|
|
108
|
+
* claims are built and never written onto a profile.
|
|
109
|
+
*
|
|
110
|
+
* `User` is every signed-in subject of the client (an unbound, unmanaged `user`-area definition
|
|
111
|
+
* only); `Member` and `Owner` are every member / owner of the organization the subject acts in, so
|
|
112
|
+
* they require an `entityScoped` definition. A class default is a BLANKET set: `Owner` on a
|
|
113
|
+
* resource-scoped definition is its all-records form.
|
|
114
|
+
*/
|
|
115
|
+
export declare enum IamDefaultClass {
|
|
116
|
+
None = "none",
|
|
117
|
+
User = "user",
|
|
118
|
+
Member = "member",
|
|
119
|
+
Owner = "owner"
|
|
120
|
+
}
|
|
121
|
+
/** Why a subject holds a grant, as a listing reports it. */
|
|
122
|
+
export declare enum IamGrantOrigin {
|
|
123
|
+
/** Written on the subject's own row. */
|
|
124
|
+
Direct = "direct",
|
|
125
|
+
/** The definition's `defaultClass` covers the subject. */
|
|
126
|
+
Default = "default",
|
|
127
|
+
/** Held by a group the subject is a member of — `IamGrant.through` names it. */
|
|
128
|
+
Group = "group",
|
|
129
|
+
/** A group's own listing only: the names its bundles select; its own grants are `Direct`. */
|
|
130
|
+
Bundle = "bundle"
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The managed group `syncStaff` keeps in a client's owning organization: the owner's own staff,
|
|
134
|
+
* admitted to the client with the bundles the sync hands it. Its key, membership, bundles and
|
|
135
|
+
* existence are the synchronization's alone; its grants and restrictions are the operator's and
|
|
136
|
+
* survive every sync.
|
|
137
|
+
*/
|
|
138
|
+
export declare const IAM_MEMBERS_GROUP = "members";
|
|
139
|
+
/**
|
|
140
|
+
* The `profileId` of a credential that proves an e-mail address and identifies nobody yet: what the
|
|
141
|
+
* end-user sign-in hands the provider's finalizer, which then resolves the account itself. It carries
|
|
142
|
+
* no `entitySlug` — a proof bound to an organization is something else.
|
|
143
|
+
*/
|
|
144
|
+
export declare const IAM_EMAIL_PROOF = "proof:email";
|
|
145
|
+
/**
|
|
146
|
+
* The guard of the runtime IAM API (`makeIamRuntimeProtocols`). The serving process registers it: it
|
|
147
|
+
* admits a bearer access token the provider itself issued, and takes the client and the account from
|
|
148
|
+
* that token, never from the request.
|
|
149
|
+
*/
|
|
150
|
+
export declare const IAM_RUNTIME_GUARD = "iam-runtime-guard";
|
|
151
|
+
/** Where the runtime IAM API mounts under its service unless the declaration names another path. */
|
|
152
|
+
export declare const IAM_RUNTIME_PATH = "/runtime";
|
|
153
|
+
/**
|
|
154
|
+
* The runtime API's leaf paths under its base. One table so the declarations and a fetch-only client
|
|
155
|
+
* (a target's server, which binds no entrypoint of the provider's tree) cannot disagree on a segment.
|
|
156
|
+
*/
|
|
157
|
+
export declare const IAM_RUNTIME_ROUTES: {
|
|
158
|
+
readonly organizations: '/organizations';
|
|
159
|
+
readonly organization: '/organizations/:entitySlug';
|
|
160
|
+
readonly members: '/organizations/:entitySlug/members';
|
|
161
|
+
readonly member: '/organizations/:entitySlug/members/:profileId';
|
|
162
|
+
readonly memberRemove: '/organizations/:entitySlug/members/:profileId/remove';
|
|
163
|
+
readonly permissions: '/organizations/:entitySlug/permissions';
|
|
164
|
+
readonly grants: '/organizations/:entitySlug/grants';
|
|
165
|
+
readonly grantsRevoke: '/organizations/:entitySlug/grants/revoke';
|
|
166
|
+
};
|
|
167
|
+
export declare const IamRuntimeOrganizationCreateSchema: JSONSchemaType<IamRuntimeOrganizationCreate>;
|
|
168
|
+
export declare const IamRuntimeOrganizationUpdateSchema: JSONSchemaType<IamRuntimeOrganizationUpdate>;
|
|
169
|
+
export declare const IamRuntimeOrganizationParamsSchema: JSONSchemaType<IamRuntimeOrganizationParams>;
|
|
170
|
+
export declare const IamRuntimeMemberInviteSchema: JSONSchemaType<IamRuntimeMemberInvite>;
|
|
171
|
+
export declare const IamRuntimeMemberParamsSchema: JSONSchemaType<IamRuntimeMemberParams>;
|
|
172
|
+
export declare const IamRuntimeGrantQuerySchema: JSONSchemaType<IamRuntimeGrantQuery>;
|
|
173
|
+
export declare const IamRuntimeAckSchema: JSONSchemaType<IamRuntimeAck>;
|
|
5
174
|
//# sourceMappingURL=consts.d.ts.map
|
package/build/consts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"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"}
|