@fuzdev/fuz_app 0.40.0 → 0.41.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.
- package/dist/actions/action_codegen.d.ts +0 -9
- package/dist/actions/action_codegen.d.ts.map +1 -1
- package/dist/actions/action_codegen.js +2 -35
- package/dist/actions/action_event.d.ts.map +1 -1
- package/dist/actions/action_event.js +1 -1
- package/dist/actions/action_types.d.ts +1 -1
- package/dist/actions/action_types.d.ts.map +1 -1
- package/dist/actions/register_action_ws.d.ts +1 -1
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.d.ts +1 -1
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +1 -1
- package/dist/auth/CLAUDE.md +29 -6
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_schema.d.ts +1 -1
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +1 -1
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +2 -3
- package/dist/auth/admin_actions.js +2 -1
- package/dist/auth/app_settings_schema.d.ts +1 -1
- package/dist/auth/app_settings_schema.d.ts.map +1 -1
- package/dist/auth/app_settings_schema.js +1 -1
- package/dist/auth/audit_log_queries.d.ts +0 -2
- package/dist/auth/audit_log_queries.d.ts.map +1 -1
- package/dist/auth/audit_log_queries.js +1 -3
- package/dist/auth/audit_log_schema.d.ts +4 -1
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +6 -3
- package/dist/auth/invite_schema.d.ts +1 -1
- package/dist/auth/invite_schema.d.ts.map +1 -1
- package/dist/auth/invite_schema.js +1 -1
- package/dist/auth/permit_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/permit_offer_action_specs.js +1 -1
- package/dist/auth/permit_offer_notifications.d.ts +11 -6
- package/dist/auth/permit_offer_notifications.d.ts.map +1 -1
- package/dist/auth/permit_offer_notifications.js +11 -8
- package/dist/auth/permit_offer_queries.d.ts +1 -1
- package/dist/auth/permit_offer_queries.d.ts.map +1 -1
- package/dist/auth/permit_offer_schema.d.ts +1 -1
- package/dist/auth/permit_offer_schema.d.ts.map +1 -1
- package/dist/auth/permit_offer_schema.js +1 -1
- package/dist/auth/permit_queries.d.ts +50 -1
- package/dist/auth/permit_queries.d.ts.map +1 -1
- package/dist/auth/permit_queries.js +55 -0
- package/dist/auth/self_service_role_action_specs.d.ts +83 -0
- package/dist/auth/self_service_role_action_specs.d.ts.map +1 -0
- package/dist/auth/self_service_role_action_specs.js +71 -0
- package/dist/auth/self_service_role_actions.d.ts +5 -74
- package/dist/auth/self_service_role_actions.d.ts.map +1 -1
- package/dist/auth/self_service_role_actions.js +5 -64
- package/dist/http/jsonrpc_errors.d.ts +6 -5
- package/dist/http/jsonrpc_errors.d.ts.map +1 -1
- package/dist/http/jsonrpc_errors.js +8 -7
- package/dist/testing/CLAUDE.md +1 -1
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/app_server.d.ts +13 -2
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +6 -1
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.d.ts +1 -1
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +1 -1
- package/package.json +4 -4
- package/dist/uuid.d.ts +0 -12
- package/dist/uuid.d.ts.map +0 -1
- package/dist/uuid.js +0 -9
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* - `permit_offer_retracted` → recipient's sockets when a grantor retracts
|
|
11
11
|
* - `permit_offer_accepted` → grantor's sockets when the recipient accepts
|
|
12
12
|
* - `permit_offer_declined` → grantor's sockets when the recipient declines
|
|
13
|
-
* - `permit_offer_supersede` → grantor's sockets when a sibling accept
|
|
14
|
-
* a revoke of the resulting permit
|
|
13
|
+
* - `permit_offer_supersede` → grantor's sockets when a sibling accept,
|
|
14
|
+
* a revoke of the resulting permit, or destruction of the parent scope
|
|
15
|
+
* row obsoletes their pending offer
|
|
15
16
|
* - `permit_revoke` → revokee's sockets when one of their active permits
|
|
16
17
|
* is revoked (companion to the `permit_revoke` audit event)
|
|
17
18
|
*
|
|
@@ -29,9 +30,9 @@
|
|
|
29
30
|
* @module
|
|
30
31
|
*/
|
|
31
32
|
import { z } from 'zod';
|
|
33
|
+
import { type Uuid } from '@fuzdev/fuz_util/id.js';
|
|
32
34
|
import type { EventSpec } from '../realtime/sse.js';
|
|
33
35
|
import type { JsonrpcNotification } from '../http/jsonrpc.js';
|
|
34
|
-
import { type Uuid } from '../uuid.js';
|
|
35
36
|
/**
|
|
36
37
|
* Narrow structural capability for sending a JSON-RPC notification to every
|
|
37
38
|
* socket bound to an account.
|
|
@@ -142,9 +143,11 @@ export type PermitOfferDeclinedParams = z.infer<typeof PermitOfferDeclinedParams
|
|
|
142
143
|
/**
|
|
143
144
|
* Params for `permit_offer_supersede`. Fires to the grantor's sockets when
|
|
144
145
|
* their pending offer is obsoleted — either by a sibling accept
|
|
145
|
-
* (`reason: 'sibling_accepted'`)
|
|
146
|
-
* (`reason: 'permit_revoked'`)
|
|
147
|
-
*
|
|
146
|
+
* (`reason: 'sibling_accepted'`), by revoke of the resulting permit
|
|
147
|
+
* (`reason: 'permit_revoked'`), or by deletion of the parent scope row
|
|
148
|
+
* the offer was bound to (`reason: 'scope_destroyed'`). `cause_id` points
|
|
149
|
+
* at the accepted offer id, the revoked permit id, or the destroyed scope
|
|
150
|
+
* row id respectively.
|
|
148
151
|
*/
|
|
149
152
|
export declare const PermitOfferSupersedeParams: z.ZodObject<{
|
|
150
153
|
offer: z.ZodObject<{
|
|
@@ -166,6 +169,7 @@ export declare const PermitOfferSupersedeParams: z.ZodObject<{
|
|
|
166
169
|
reason: z.ZodEnum<{
|
|
167
170
|
sibling_accepted: "sibling_accepted";
|
|
168
171
|
permit_revoked: "permit_revoked";
|
|
172
|
+
scope_destroyed: "scope_destroyed";
|
|
169
173
|
}>;
|
|
170
174
|
cause_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
171
175
|
}, z.core.$strict>;
|
|
@@ -322,6 +326,7 @@ export declare const permit_offer_supersede_notification_spec: {
|
|
|
322
326
|
reason: z.ZodEnum<{
|
|
323
327
|
sibling_accepted: "sibling_accepted";
|
|
324
328
|
permit_revoked: "permit_revoked";
|
|
329
|
+
scope_destroyed: "scope_destroyed";
|
|
325
330
|
}>;
|
|
326
331
|
cause_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
327
332
|
}, z.core.$strict>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permit_offer_notifications.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_notifications.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"permit_offer_notifications.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_notifications.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* - `permit_offer_retracted` → recipient's sockets when a grantor retracts
|
|
11
11
|
* - `permit_offer_accepted` → grantor's sockets when the recipient accepts
|
|
12
12
|
* - `permit_offer_declined` → grantor's sockets when the recipient declines
|
|
13
|
-
* - `permit_offer_supersede` → grantor's sockets when a sibling accept
|
|
14
|
-
* a revoke of the resulting permit
|
|
13
|
+
* - `permit_offer_supersede` → grantor's sockets when a sibling accept,
|
|
14
|
+
* a revoke of the resulting permit, or destruction of the parent scope
|
|
15
|
+
* row obsoletes their pending offer
|
|
15
16
|
* - `permit_revoke` → revokee's sockets when one of their active permits
|
|
16
17
|
* is revoked (companion to the `permit_revoke` audit event)
|
|
17
18
|
*
|
|
@@ -29,9 +30,9 @@
|
|
|
29
30
|
* @module
|
|
30
31
|
*/
|
|
31
32
|
import { z } from 'zod';
|
|
33
|
+
import { Uuid as UuidSchema } from '@fuzdev/fuz_util/id.js';
|
|
32
34
|
import { create_action_event_spec } from '../actions/action_bridge.js';
|
|
33
35
|
import { create_jsonrpc_notification } from '../http/jsonrpc_helpers.js';
|
|
34
|
-
import { Uuid as UuidSchema } from '../uuid.js';
|
|
35
36
|
import { RoleName } from './role_schema.js';
|
|
36
37
|
import { PermitOfferJson } from './permit_offer_schema.js';
|
|
37
38
|
import { PERMIT_REVOKED_REASON_LENGTH_MAX } from './account_schema.js';
|
|
@@ -66,13 +67,15 @@ export const PermitOfferDeclinedParams = z.strictObject({
|
|
|
66
67
|
/**
|
|
67
68
|
* Params for `permit_offer_supersede`. Fires to the grantor's sockets when
|
|
68
69
|
* their pending offer is obsoleted — either by a sibling accept
|
|
69
|
-
* (`reason: 'sibling_accepted'`)
|
|
70
|
-
* (`reason: 'permit_revoked'`)
|
|
71
|
-
*
|
|
70
|
+
* (`reason: 'sibling_accepted'`), by revoke of the resulting permit
|
|
71
|
+
* (`reason: 'permit_revoked'`), or by deletion of the parent scope row
|
|
72
|
+
* the offer was bound to (`reason: 'scope_destroyed'`). `cause_id` points
|
|
73
|
+
* at the accepted offer id, the revoked permit id, or the destroyed scope
|
|
74
|
+
* row id respectively.
|
|
72
75
|
*/
|
|
73
76
|
export const PermitOfferSupersedeParams = z.strictObject({
|
|
74
77
|
offer: PermitOfferJson,
|
|
75
|
-
reason: z.enum(['sibling_accepted', 'permit_revoked']),
|
|
78
|
+
reason: z.enum(['sibling_accepted', 'permit_revoked', 'scope_destroyed']),
|
|
76
79
|
cause_id: UuidSchema,
|
|
77
80
|
});
|
|
78
81
|
/**
|
|
@@ -142,7 +145,7 @@ export const permit_offer_supersede_notification_spec = {
|
|
|
142
145
|
input: PermitOfferSupersedeParams,
|
|
143
146
|
output: z.void(),
|
|
144
147
|
async: true,
|
|
145
|
-
description: 'A grantor’s pending permit offer was obsoleted by a sibling accept
|
|
148
|
+
description: 'A grantor’s pending permit offer was obsoleted by a sibling accept, by revoke of the resulting permit, or by destruction of the parent scope row.',
|
|
146
149
|
};
|
|
147
150
|
export const permit_revoke_notification_spec = {
|
|
148
151
|
method: PERMIT_REVOKE_NOTIFICATION_METHOD,
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module
|
|
13
13
|
*/
|
|
14
|
+
import type { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
14
15
|
import type { QueryDeps } from '../db/query_deps.js';
|
|
15
|
-
import type { Uuid } from '../uuid.js';
|
|
16
16
|
import type { Permit } from './account_schema.js';
|
|
17
17
|
import { type CreatePermitOfferInput, type PermitOffer, type SupersededOffer } from './permit_offer_schema.js';
|
|
18
18
|
import type { AuditLogEvent } from './audit_log_schema.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permit_offer_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"permit_offer_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAEjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAC;AAEhD,OAAO,EAEN,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAEzD;;;;;GAKG;AACH,qBAAa,+BAAgC,SAAQ,KAAK;gBAC7C,QAAQ,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBACrC,QAAQ,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACtC,QAAQ,EAAE,MAAM;CAI5B;AAED;;;;;;GAMG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;;CAKpD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,SAAS,EACf,OAAO,sBAAsB,KAC3B,OAAO,CAAC,WAAW,CAyBrB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,GACtC,MAAM,SAAS,EACf,UAAU,MAAM,EAChB,eAAe,MAAM,EACrB,QAAQ,MAAM,GAAG,IAAI,KACnB,OAAO,CAAC,WAAW,GAAG,IAAI,CAe5B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,GACtC,MAAM,SAAS,EACf,UAAU,MAAM,EAChB,eAAe,MAAM,KACnB,OAAO,CAAC,WAAW,GAAG,IAAI,CAe5B,CAAC;AA8BF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,eAAe,MAAM,KACnB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAY5B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sCAAsC,GAClD,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAAW,EACX,eAAU,KACR,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAS5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,+BAA+B,GAC3C,MAAM,SAAS,EACf,UAAU,MAAM,KACd,OAAO,CAAC,WAAW,GAAG,IAAI,CAY5B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,KACb,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAU5B,CAAC;AAEF,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,IAAI,CAAC;IACf,mGAAmG;IACnG,aAAa,EAAE,IAAI,CAAC;IACpB,gDAAgD;IAChD,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnB;AAED,yHAAyH;AACzH,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,4IAA4I;IAC5I,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,iBAAiB,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;IAC1C,sLAAsL;IACtL,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,kBAAkB,GAC9B,MAAM,SAAS,EACf,OAAO,gBAAgB,KACrB,OAAO,CAAC,iBAAiB,CAqK3B,CAAC"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* @module
|
|
11
11
|
*/
|
|
12
12
|
import { z } from 'zod';
|
|
13
|
-
import { Uuid } from '
|
|
13
|
+
import { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
14
14
|
/** Sentinel UUID used inside the partial unique indexes to collapse `scope_id IS NULL` into a comparable value. */
|
|
15
15
|
export declare const PERMIT_OFFER_SCOPE_SENTINEL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
16
16
|
/** Maximum length of the optional message attached to an offer. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permit_offer_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"permit_offer_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAI5C,mHAAmH;AACnH,eAAO,MAAM,gCAAgC,yCAAyC,CAAC;AAEvF,mEAAmE;AACnE,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,yFAAyF;AACzF,eAAO,MAAM,2BAA2B,QAA2B,CAAC;AAEpE,eAAO,MAAM,mBAAmB,6kCA6B9B,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iCAAiC,8UAWhB,CAAC;AAE/B,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,0NAMP,CAAC;AAE/B,oDAAoD;AACpD,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,IAAI,CAAC;IACT,aAAa,EAAE,IAAI,CAAC;IACpB,aAAa,EAAE,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;;OAKG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mBAAmB,EAAE,IAAI,GAAG,IAAI,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAgB,SAAQ,WAAW;IACnD,eAAe,EAAE,IAAI,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACtC,aAAa,EAAE,IAAI,CAAC;IACpB,aAAa,EAAE,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED,oDAAoD;AACpD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;kBA4CyD,CAAC;AACtF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,6DAA6D;AAC7D,eAAO,MAAM,oBAAoB,GAAI,OAAO,WAAW,KAAG,eAexD,CAAC"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* @module
|
|
11
11
|
*/
|
|
12
12
|
import { z } from 'zod';
|
|
13
|
-
import { Uuid } from '
|
|
13
|
+
import { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
14
14
|
import { RoleName } from './role_schema.js';
|
|
15
15
|
/** Sentinel UUID used inside the partial unique indexes to collapse `scope_id IS NULL` into a comparable value. */
|
|
16
16
|
export const PERMIT_OFFER_SCOPE_SENTINEL_UUID = '00000000-0000-0000-0000-000000000000';
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
+
import type { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
9
10
|
import type { QueryDeps } from '../db/query_deps.js';
|
|
10
|
-
import type { Uuid } from '../uuid.js';
|
|
11
11
|
import type { Permit, GrantPermitInput } from './account_schema.js';
|
|
12
12
|
import { type SupersededOffer } from './permit_offer_schema.js';
|
|
13
13
|
/**
|
|
@@ -110,6 +110,55 @@ export declare const query_permit_list_for_actor: (deps: QueryDeps, actor_id: st
|
|
|
110
110
|
* @returns the account ID, or `null`
|
|
111
111
|
*/
|
|
112
112
|
export declare const query_permit_find_account_id_for_role: (deps: QueryDeps, role: string) => Promise<string | null>;
|
|
113
|
+
/** Result of `query_permit_revoke_for_scope` — every permit revoked plus every pending offer superseded by the scope-wide cascade. */
|
|
114
|
+
export interface RevokeForScopeResult {
|
|
115
|
+
/**
|
|
116
|
+
* One entry per permit revoked by this call. Carries the revokee's
|
|
117
|
+
* `account_id` so callers can fan out a `permit_revoke` notification per
|
|
118
|
+
* permit. Empty array means no active permit was bound to the scope.
|
|
119
|
+
*/
|
|
120
|
+
revoked: Array<{
|
|
121
|
+
permit_id: Uuid;
|
|
122
|
+
role: string;
|
|
123
|
+
scope_id: Uuid;
|
|
124
|
+
account_id: Uuid;
|
|
125
|
+
}>;
|
|
126
|
+
/**
|
|
127
|
+
* Every pending offer at the scope — tuple-matched and orphan, undifferentiated
|
|
128
|
+
* — superseded in the same cascade. Each entry carries its grantor's
|
|
129
|
+
* `from_account_id` for `permit_offer_supersede` notification fan-out.
|
|
130
|
+
*
|
|
131
|
+
* The caller is responsible for emitting `permit_offer_supersede` audit
|
|
132
|
+
* events with `reason: 'scope_destroyed'` and `cause_id: <destroyed scope row id>`
|
|
133
|
+
* per entry — the cause of every supersede here is the scope deletion,
|
|
134
|
+
* not any individual permit revoke (the revokes are themselves
|
|
135
|
+
* consequences of the scope going away).
|
|
136
|
+
*/
|
|
137
|
+
superseded_offers: Array<SupersededOffer>;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Revoke every active permit bound to a scope and supersede every pending
|
|
141
|
+
* offer at the scope, in one cascade.
|
|
142
|
+
*
|
|
143
|
+
* Use this from a consumer's parent-scope delete handler (e.g., classroom
|
|
144
|
+
* deletion) — `permit.scope_id` and `permit_offer.scope_id` are polymorphic
|
|
145
|
+
* with no FK constraint by design, so a parent row deletion would otherwise
|
|
146
|
+
* orphan permits and offers. The cascade is **role-agnostic**: anything
|
|
147
|
+
* attached to the destroyed scope is cleaned up.
|
|
148
|
+
*
|
|
149
|
+
* Both updates run as separate statements inside the caller's transaction
|
|
150
|
+
* (mirrors `query_permit_revoke_role`'s shape). The two halves are
|
|
151
|
+
* independent — orphan pending offers can exist at a scope with no active
|
|
152
|
+
* permits, so the supersede half always runs even when no permit was
|
|
153
|
+
* revoked.
|
|
154
|
+
*
|
|
155
|
+
* @param deps - query dependencies
|
|
156
|
+
* @param scope_id - the scope whose permits and offers to terminate
|
|
157
|
+
* @param revoked_by - the actor performing the cascade (audit trail)
|
|
158
|
+
* @param reason - optional free-form reason, stamped on `permit.revoked_reason`.
|
|
159
|
+
* @returns the revoked permits (with `account_id` for fan-out) and superseded offers (with `from_account_id` for fan-out)
|
|
160
|
+
*/
|
|
161
|
+
export declare const query_permit_revoke_for_scope: (deps: QueryDeps, scope_id: Uuid, revoked_by: Uuid | null, reason?: string | null) => Promise<RevokeForScopeResult>;
|
|
113
162
|
/** Result of `query_permit_revoke_role` — every permit revoked plus the pending offers superseded by the bulk revoke. */
|
|
114
163
|
export interface RevokeRoleResult {
|
|
115
164
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permit_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"permit_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -178,6 +178,61 @@ export const query_permit_find_account_id_for_role = async (deps, role) => {
|
|
|
178
178
|
LIMIT 1`, [role]);
|
|
179
179
|
return row?.account_id ?? null;
|
|
180
180
|
};
|
|
181
|
+
/**
|
|
182
|
+
* Revoke every active permit bound to a scope and supersede every pending
|
|
183
|
+
* offer at the scope, in one cascade.
|
|
184
|
+
*
|
|
185
|
+
* Use this from a consumer's parent-scope delete handler (e.g., classroom
|
|
186
|
+
* deletion) — `permit.scope_id` and `permit_offer.scope_id` are polymorphic
|
|
187
|
+
* with no FK constraint by design, so a parent row deletion would otherwise
|
|
188
|
+
* orphan permits and offers. The cascade is **role-agnostic**: anything
|
|
189
|
+
* attached to the destroyed scope is cleaned up.
|
|
190
|
+
*
|
|
191
|
+
* Both updates run as separate statements inside the caller's transaction
|
|
192
|
+
* (mirrors `query_permit_revoke_role`'s shape). The two halves are
|
|
193
|
+
* independent — orphan pending offers can exist at a scope with no active
|
|
194
|
+
* permits, so the supersede half always runs even when no permit was
|
|
195
|
+
* revoked.
|
|
196
|
+
*
|
|
197
|
+
* @param deps - query dependencies
|
|
198
|
+
* @param scope_id - the scope whose permits and offers to terminate
|
|
199
|
+
* @param revoked_by - the actor performing the cascade (audit trail)
|
|
200
|
+
* @param reason - optional free-form reason, stamped on `permit.revoked_reason`.
|
|
201
|
+
* @returns the revoked permits (with `account_id` for fan-out) and superseded offers (with `from_account_id` for fan-out)
|
|
202
|
+
*/
|
|
203
|
+
export const query_permit_revoke_for_scope = async (deps, scope_id, revoked_by, reason) => {
|
|
204
|
+
// Revoke every active permit at the scope. CTE pulls `account_id` via a
|
|
205
|
+
// join on `actor` so callers fan out `permit_revoke` notifications without
|
|
206
|
+
// an extra round-trip.
|
|
207
|
+
const revoked = await deps.db.query(`WITH updated AS (
|
|
208
|
+
UPDATE permit
|
|
209
|
+
SET revoked_at = NOW(), revoked_by = $2, revoked_reason = $3
|
|
210
|
+
WHERE scope_id = $1 AND revoked_at IS NULL
|
|
211
|
+
RETURNING id, role, scope_id, actor_id
|
|
212
|
+
)
|
|
213
|
+
SELECT u.id AS permit_id, u.role, u.scope_id, a.account_id
|
|
214
|
+
FROM updated u
|
|
215
|
+
JOIN actor a ON a.id = u.actor_id`, [scope_id, revoked_by ?? null, reason ?? null]);
|
|
216
|
+
// Supersede every pending offer at the scope — tuple-matched or orphan,
|
|
217
|
+
// no distinction. The cause of every supersede in this cascade is the
|
|
218
|
+
// scope deletion; offers tuple-matched to a revoked permit are not
|
|
219
|
+
// tagged separately because the revoke is itself a consequence of the
|
|
220
|
+
// scope going away.
|
|
221
|
+
const superseded_offers = await deps.db.query(`WITH updated AS (
|
|
222
|
+
UPDATE permit_offer o
|
|
223
|
+
SET superseded_at = NOW()
|
|
224
|
+
WHERE o.scope_id = $1
|
|
225
|
+
AND o.accepted_at IS NULL
|
|
226
|
+
AND o.declined_at IS NULL
|
|
227
|
+
AND o.retracted_at IS NULL
|
|
228
|
+
AND o.superseded_at IS NULL
|
|
229
|
+
RETURNING o.*
|
|
230
|
+
)
|
|
231
|
+
SELECT u.*, grantor.account_id AS from_account_id
|
|
232
|
+
FROM updated u
|
|
233
|
+
JOIN actor grantor ON grantor.id = u.from_actor_id`, [scope_id]);
|
|
234
|
+
return { revoked, superseded_offers };
|
|
235
|
+
};
|
|
181
236
|
/**
|
|
182
237
|
* Revoke every active permit an actor holds for a given role.
|
|
183
238
|
*
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-service role grant/revoke action specs — schemas, error reasons,
|
|
3
|
+
* and the codegen-ready registry.
|
|
4
|
+
*
|
|
5
|
+
* Client-safe: no query-layer or audit-write imports. Handler factory
|
|
6
|
+
* lives in `self_service_role_actions.ts`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import type { RequestResponseActionSpec } from '../actions/action_spec.js';
|
|
12
|
+
/** Error reason — caller asked to self-toggle a role outside the configured allowlist. */
|
|
13
|
+
export declare const ERROR_ROLE_NOT_SELF_SERVICE_ELIGIBLE: "role_not_self_service_eligible";
|
|
14
|
+
/** Input for `self_service_role_grant`. */
|
|
15
|
+
export declare const SelfServiceRoleGrantInput: z.ZodObject<{
|
|
16
|
+
role: z.ZodString;
|
|
17
|
+
}, z.core.$strict>;
|
|
18
|
+
export type SelfServiceRoleGrantInput = z.infer<typeof SelfServiceRoleGrantInput>;
|
|
19
|
+
/**
|
|
20
|
+
* Output for `self_service_role_grant`. `granted` is `false` on idempotent
|
|
21
|
+
* re-grant (caller already held the role globally); `permit_id` is set on
|
|
22
|
+
* new grants only.
|
|
23
|
+
*/
|
|
24
|
+
export declare const SelfServiceRoleGrantOutput: z.ZodObject<{
|
|
25
|
+
ok: z.ZodLiteral<true>;
|
|
26
|
+
granted: z.ZodBoolean;
|
|
27
|
+
permit_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
export type SelfServiceRoleGrantOutput = z.infer<typeof SelfServiceRoleGrantOutput>;
|
|
30
|
+
/** Input for `self_service_role_revoke`. */
|
|
31
|
+
export declare const SelfServiceRoleRevokeInput: z.ZodObject<{
|
|
32
|
+
role: z.ZodString;
|
|
33
|
+
}, z.core.$strict>;
|
|
34
|
+
export type SelfServiceRoleRevokeInput = z.infer<typeof SelfServiceRoleRevokeInput>;
|
|
35
|
+
/**
|
|
36
|
+
* Output for `self_service_role_revoke`. `revoked` is `false` when the
|
|
37
|
+
* caller held no active global permit for the role (idempotent).
|
|
38
|
+
*/
|
|
39
|
+
export declare const SelfServiceRoleRevokeOutput: z.ZodObject<{
|
|
40
|
+
ok: z.ZodLiteral<true>;
|
|
41
|
+
revoked: z.ZodBoolean;
|
|
42
|
+
}, z.core.$strict>;
|
|
43
|
+
export type SelfServiceRoleRevokeOutput = z.infer<typeof SelfServiceRoleRevokeOutput>;
|
|
44
|
+
export declare const self_service_role_grant_action_spec: {
|
|
45
|
+
method: string;
|
|
46
|
+
kind: "request_response";
|
|
47
|
+
initiator: "frontend";
|
|
48
|
+
auth: "authenticated";
|
|
49
|
+
side_effects: true;
|
|
50
|
+
input: z.ZodObject<{
|
|
51
|
+
role: z.ZodString;
|
|
52
|
+
}, z.core.$strict>;
|
|
53
|
+
output: z.ZodObject<{
|
|
54
|
+
ok: z.ZodLiteral<true>;
|
|
55
|
+
granted: z.ZodBoolean;
|
|
56
|
+
permit_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
57
|
+
}, z.core.$strict>;
|
|
58
|
+
async: true;
|
|
59
|
+
description: string;
|
|
60
|
+
};
|
|
61
|
+
export declare const self_service_role_revoke_action_spec: {
|
|
62
|
+
method: string;
|
|
63
|
+
kind: "request_response";
|
|
64
|
+
initiator: "frontend";
|
|
65
|
+
auth: "authenticated";
|
|
66
|
+
side_effects: true;
|
|
67
|
+
input: z.ZodObject<{
|
|
68
|
+
role: z.ZodString;
|
|
69
|
+
}, z.core.$strict>;
|
|
70
|
+
output: z.ZodObject<{
|
|
71
|
+
ok: z.ZodLiteral<true>;
|
|
72
|
+
revoked: z.ZodBoolean;
|
|
73
|
+
}, z.core.$strict>;
|
|
74
|
+
async: true;
|
|
75
|
+
description: string;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* All self-service role action specs — a codegen-ready registry. Method
|
|
79
|
+
* names are static, so consumer typed-client codegen picks them up the
|
|
80
|
+
* same way it picks up `account_*_action_specs`.
|
|
81
|
+
*/
|
|
82
|
+
export declare const all_self_service_role_action_specs: Array<RequestResponseActionSpec>;
|
|
83
|
+
//# sourceMappingURL=self_service_role_action_specs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self_service_role_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/self_service_role_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAGtB,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,2BAA2B,CAAC;AAGzE,0FAA0F;AAC1F,eAAO,MAAM,oCAAoC,EAAG,gCAAyC,CAAC;AAE9F,2CAA2C;AAC3C,eAAO,MAAM,yBAAyB;;kBAEpC,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAElF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;kBAIrC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEpF,4CAA4C;AAC5C,eAAO,MAAM,0BAA0B;;kBAErC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEpF;;;GAGG;AACH,eAAO,MAAM,2BAA2B;;;kBAGtC,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEtF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;CAWX,CAAC;AAEtC,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;CAWZ,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,EAAE,KAAK,CAAC,yBAAyB,CAG/E,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-service role grant/revoke action specs — schemas, error reasons,
|
|
3
|
+
* and the codegen-ready registry.
|
|
4
|
+
*
|
|
5
|
+
* Client-safe: no query-layer or audit-write imports. Handler factory
|
|
6
|
+
* lives in `self_service_role_actions.ts`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
12
|
+
import { RoleName } from './role_schema.js';
|
|
13
|
+
/** Error reason — caller asked to self-toggle a role outside the configured allowlist. */
|
|
14
|
+
export const ERROR_ROLE_NOT_SELF_SERVICE_ELIGIBLE = 'role_not_self_service_eligible';
|
|
15
|
+
/** Input for `self_service_role_grant`. */
|
|
16
|
+
export const SelfServiceRoleGrantInput = z.strictObject({
|
|
17
|
+
role: RoleName.meta({ description: 'Role to self-grant. Must be in the configured allowlist.' }),
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Output for `self_service_role_grant`. `granted` is `false` on idempotent
|
|
21
|
+
* re-grant (caller already held the role globally); `permit_id` is set on
|
|
22
|
+
* new grants only.
|
|
23
|
+
*/
|
|
24
|
+
export const SelfServiceRoleGrantOutput = z.strictObject({
|
|
25
|
+
ok: z.literal(true),
|
|
26
|
+
granted: z.boolean(),
|
|
27
|
+
permit_id: Uuid.optional(),
|
|
28
|
+
});
|
|
29
|
+
/** Input for `self_service_role_revoke`. */
|
|
30
|
+
export const SelfServiceRoleRevokeInput = z.strictObject({
|
|
31
|
+
role: RoleName.meta({ description: 'Role to self-revoke. Must be in the configured allowlist.' }),
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Output for `self_service_role_revoke`. `revoked` is `false` when the
|
|
35
|
+
* caller held no active global permit for the role (idempotent).
|
|
36
|
+
*/
|
|
37
|
+
export const SelfServiceRoleRevokeOutput = z.strictObject({
|
|
38
|
+
ok: z.literal(true),
|
|
39
|
+
revoked: z.boolean(),
|
|
40
|
+
});
|
|
41
|
+
export const self_service_role_grant_action_spec = {
|
|
42
|
+
method: 'self_service_role_grant',
|
|
43
|
+
kind: 'request_response',
|
|
44
|
+
initiator: 'frontend',
|
|
45
|
+
auth: 'authenticated',
|
|
46
|
+
side_effects: true,
|
|
47
|
+
input: SelfServiceRoleGrantInput,
|
|
48
|
+
output: SelfServiceRoleGrantOutput,
|
|
49
|
+
async: true,
|
|
50
|
+
description: 'Self-grant an active permit for an allowlisted role. Idempotent — already-granted callers receive `granted: false`.',
|
|
51
|
+
};
|
|
52
|
+
export const self_service_role_revoke_action_spec = {
|
|
53
|
+
method: 'self_service_role_revoke',
|
|
54
|
+
kind: 'request_response',
|
|
55
|
+
initiator: 'frontend',
|
|
56
|
+
auth: 'authenticated',
|
|
57
|
+
side_effects: true,
|
|
58
|
+
input: SelfServiceRoleRevokeInput,
|
|
59
|
+
output: SelfServiceRoleRevokeOutput,
|
|
60
|
+
async: true,
|
|
61
|
+
description: 'Self-revoke an active global permit for an allowlisted role. Idempotent — callers without an active permit receive `revoked: false`.',
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* All self-service role action specs — a codegen-ready registry. Method
|
|
65
|
+
* names are static, so consumer typed-client codegen picks them up the
|
|
66
|
+
* same way it picks up `account_*_action_specs`.
|
|
67
|
+
*/
|
|
68
|
+
export const all_self_service_role_action_specs = [
|
|
69
|
+
self_service_role_grant_action_spec,
|
|
70
|
+
self_service_role_revoke_action_spec,
|
|
71
|
+
];
|
|
@@ -25,84 +25,15 @@
|
|
|
25
25
|
* the existing `permit_offer_create({role})` precedent rather than
|
|
26
26
|
* generating per-role methods.
|
|
27
27
|
*
|
|
28
|
+
* Specs and schemas live in `self_service_role_action_specs.ts` so
|
|
29
|
+
* client-side codegen can import the surface without dragging in the
|
|
30
|
+
* query layer.
|
|
31
|
+
*
|
|
28
32
|
* @module
|
|
29
33
|
*/
|
|
30
|
-
import { z } from 'zod';
|
|
31
34
|
import { type RpcAction } from '../actions/action_rpc.js';
|
|
32
|
-
import type {
|
|
33
|
-
import { type RoleSchemaResult } from './role_schema.js';
|
|
35
|
+
import type { RoleSchemaResult } from './role_schema.js';
|
|
34
36
|
import type { RouteFactoryDeps } from './deps.js';
|
|
35
|
-
/** Error reason — caller asked to self-toggle a role outside the configured allowlist. */
|
|
36
|
-
export declare const ERROR_ROLE_NOT_SELF_SERVICE_ELIGIBLE: "role_not_self_service_eligible";
|
|
37
|
-
/** Input for `self_service_role_grant`. */
|
|
38
|
-
export declare const SelfServiceRoleGrantInput: z.ZodObject<{
|
|
39
|
-
role: z.ZodString;
|
|
40
|
-
}, z.core.$strict>;
|
|
41
|
-
export type SelfServiceRoleGrantInput = z.infer<typeof SelfServiceRoleGrantInput>;
|
|
42
|
-
/**
|
|
43
|
-
* Output for `self_service_role_grant`. `granted` is `false` on idempotent
|
|
44
|
-
* re-grant (caller already held the role globally); `permit_id` is set on
|
|
45
|
-
* new grants only.
|
|
46
|
-
*/
|
|
47
|
-
export declare const SelfServiceRoleGrantOutput: z.ZodObject<{
|
|
48
|
-
ok: z.ZodLiteral<true>;
|
|
49
|
-
granted: z.ZodBoolean;
|
|
50
|
-
permit_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
51
|
-
}, z.core.$strict>;
|
|
52
|
-
export type SelfServiceRoleGrantOutput = z.infer<typeof SelfServiceRoleGrantOutput>;
|
|
53
|
-
/** Input for `self_service_role_revoke`. */
|
|
54
|
-
export declare const SelfServiceRoleRevokeInput: z.ZodObject<{
|
|
55
|
-
role: z.ZodString;
|
|
56
|
-
}, z.core.$strict>;
|
|
57
|
-
export type SelfServiceRoleRevokeInput = z.infer<typeof SelfServiceRoleRevokeInput>;
|
|
58
|
-
/**
|
|
59
|
-
* Output for `self_service_role_revoke`. `revoked` is `false` when the
|
|
60
|
-
* caller held no active global permit for the role (idempotent).
|
|
61
|
-
*/
|
|
62
|
-
export declare const SelfServiceRoleRevokeOutput: z.ZodObject<{
|
|
63
|
-
ok: z.ZodLiteral<true>;
|
|
64
|
-
revoked: z.ZodBoolean;
|
|
65
|
-
}, z.core.$strict>;
|
|
66
|
-
export type SelfServiceRoleRevokeOutput = z.infer<typeof SelfServiceRoleRevokeOutput>;
|
|
67
|
-
export declare const self_service_role_grant_action_spec: {
|
|
68
|
-
method: string;
|
|
69
|
-
kind: "request_response";
|
|
70
|
-
initiator: "frontend";
|
|
71
|
-
auth: "authenticated";
|
|
72
|
-
side_effects: true;
|
|
73
|
-
input: z.ZodObject<{
|
|
74
|
-
role: z.ZodString;
|
|
75
|
-
}, z.core.$strict>;
|
|
76
|
-
output: z.ZodObject<{
|
|
77
|
-
ok: z.ZodLiteral<true>;
|
|
78
|
-
granted: z.ZodBoolean;
|
|
79
|
-
permit_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
80
|
-
}, z.core.$strict>;
|
|
81
|
-
async: true;
|
|
82
|
-
description: string;
|
|
83
|
-
};
|
|
84
|
-
export declare const self_service_role_revoke_action_spec: {
|
|
85
|
-
method: string;
|
|
86
|
-
kind: "request_response";
|
|
87
|
-
initiator: "frontend";
|
|
88
|
-
auth: "authenticated";
|
|
89
|
-
side_effects: true;
|
|
90
|
-
input: z.ZodObject<{
|
|
91
|
-
role: z.ZodString;
|
|
92
|
-
}, z.core.$strict>;
|
|
93
|
-
output: z.ZodObject<{
|
|
94
|
-
ok: z.ZodLiteral<true>;
|
|
95
|
-
revoked: z.ZodBoolean;
|
|
96
|
-
}, z.core.$strict>;
|
|
97
|
-
async: true;
|
|
98
|
-
description: string;
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* All self-service role action specs — a codegen-ready registry. Method
|
|
102
|
-
* names are static, so consumer typed-client codegen picks them up the
|
|
103
|
-
* same way it picks up `account_*_action_specs`.
|
|
104
|
-
*/
|
|
105
|
-
export declare const all_self_service_role_action_specs: Array<RequestResponseActionSpec>;
|
|
106
37
|
/** Options for `create_self_service_role_actions`. */
|
|
107
38
|
export interface SelfServiceRoleActionsOptions {
|
|
108
39
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self_service_role_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/self_service_role_actions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"self_service_role_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/self_service_role_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAiC,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAExF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAmBhD,sDAAsD;AACtD,MAAM,WAAW,6BAA6B;IAC7C;;;;OAIG;IACH,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC3C,gBAAgB,EAChB,KAAK,GAAG,gBAAgB,GAAG,kBAAkB,CAC7C,CAAC;AAOF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,yBAAyB,EAC/B,SAAS,6BAA6B,KACpC,KAAK,CAAC,SAAS,CAqHjB,CAAC"}
|