@fuzdev/fuz_app 0.29.0 → 0.31.0
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/CLAUDE.md +630 -0
- package/dist/actions/action_rpc.d.ts +29 -0
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +42 -6
- package/dist/actions/action_types.d.ts +2 -2
- package/dist/actions/cancel.d.ts +12 -13
- package/dist/actions/cancel.d.ts.map +1 -1
- package/dist/actions/cancel.js +10 -13
- package/dist/actions/heartbeat.d.ts +8 -13
- package/dist/actions/heartbeat.d.ts.map +1 -1
- package/dist/actions/heartbeat.js +5 -8
- package/dist/actions/register_action_ws.d.ts +3 -3
- package/dist/actions/register_action_ws.js +2 -2
- package/dist/actions/register_ws_endpoint.d.ts +4 -4
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +3 -3
- package/dist/actions/socket.svelte.d.ts +16 -16
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +15 -15
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.d.ts +15 -0
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +17 -0
- package/dist/auth/CLAUDE.md +923 -0
- package/dist/auth/account_action_specs.d.ts +216 -0
- package/dist/auth/account_action_specs.d.ts.map +1 -0
- package/dist/auth/account_action_specs.js +159 -0
- package/dist/auth/account_actions.d.ts +51 -0
- package/dist/auth/account_actions.d.ts.map +1 -0
- package/dist/auth/account_actions.js +119 -0
- package/dist/auth/account_queries.d.ts +6 -2
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +40 -4
- package/dist/auth/account_routes.d.ts +94 -16
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +108 -180
- package/dist/auth/account_schema.d.ts +85 -30
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +40 -8
- package/dist/auth/admin_action_specs.d.ts +674 -0
- package/dist/auth/admin_action_specs.d.ts.map +1 -0
- package/dist/auth/admin_action_specs.js +287 -0
- package/dist/auth/admin_actions.d.ts +69 -0
- package/dist/auth/admin_actions.d.ts.map +1 -0
- package/dist/auth/admin_actions.js +256 -0
- package/dist/auth/api_token.d.ts +10 -0
- package/dist/auth/api_token.d.ts.map +1 -1
- package/dist/auth/api_token.js +9 -0
- package/dist/auth/api_token_queries.d.ts +3 -3
- package/dist/auth/api_token_queries.js +3 -3
- package/dist/auth/app_settings_schema.d.ts +4 -3
- package/dist/auth/app_settings_schema.d.ts.map +1 -1
- package/dist/auth/app_settings_schema.js +2 -1
- package/dist/auth/audit_log_routes.d.ts +14 -6
- package/dist/auth/audit_log_routes.d.ts.map +1 -1
- package/dist/auth/audit_log_routes.js +22 -79
- package/dist/auth/audit_log_schema.d.ts +100 -29
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +83 -11
- package/dist/auth/bootstrap_routes.d.ts +14 -0
- package/dist/auth/bootstrap_routes.d.ts.map +1 -1
- package/dist/auth/bootstrap_routes.js +10 -3
- package/dist/auth/cleanup.d.ts +63 -0
- package/dist/auth/cleanup.d.ts.map +1 -0
- package/dist/auth/cleanup.js +80 -0
- package/dist/auth/invite_schema.d.ts +11 -10
- package/dist/auth/invite_schema.d.ts.map +1 -1
- package/dist/auth/invite_schema.js +4 -3
- package/dist/auth/migrations.d.ts +6 -0
- package/dist/auth/migrations.d.ts.map +1 -1
- package/dist/auth/migrations.js +28 -0
- package/dist/auth/permit_offer_action_specs.d.ts +364 -0
- package/dist/auth/permit_offer_action_specs.d.ts.map +1 -0
- package/dist/auth/permit_offer_action_specs.js +216 -0
- package/dist/auth/permit_offer_actions.d.ts +96 -0
- package/dist/auth/permit_offer_actions.d.ts.map +1 -0
- package/dist/auth/permit_offer_actions.js +428 -0
- package/dist/auth/permit_offer_notifications.d.ts +361 -0
- package/dist/auth/permit_offer_notifications.d.ts.map +1 -0
- package/dist/auth/permit_offer_notifications.js +179 -0
- package/dist/auth/permit_offer_queries.d.ts +165 -0
- package/dist/auth/permit_offer_queries.d.ts.map +1 -0
- package/dist/auth/permit_offer_queries.js +390 -0
- package/dist/auth/permit_offer_schema.d.ts +103 -0
- package/dist/auth/permit_offer_schema.d.ts.map +1 -0
- package/dist/auth/permit_offer_schema.js +142 -0
- package/dist/auth/permit_queries.d.ts +77 -14
- package/dist/auth/permit_queries.d.ts.map +1 -1
- package/dist/auth/permit_queries.js +119 -24
- package/dist/auth/session_queries.d.ts +4 -2
- package/dist/auth/session_queries.d.ts.map +1 -1
- package/dist/auth/session_queries.js +4 -2
- package/dist/auth/signup_routes.d.ts +13 -0
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +14 -7
- package/dist/http/CLAUDE.md +584 -0
- package/dist/http/pending_effects.d.ts +29 -0
- package/dist/http/pending_effects.d.ts.map +1 -0
- package/dist/http/pending_effects.js +31 -0
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +4 -3
- package/dist/rate_limiter.d.ts +30 -0
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +25 -2
- package/dist/realtime/sse_auth_guard.d.ts +2 -0
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +5 -3
- package/dist/testing/CLAUDE.md +668 -1
- package/dist/testing/admin_integration.d.ts +10 -7
- package/dist/testing/admin_integration.d.ts.map +1 -1
- package/dist/testing/admin_integration.js +382 -482
- package/dist/testing/app_server.d.ts +7 -6
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/attack_surface.d.ts +9 -3
- package/dist/testing/attack_surface.d.ts.map +1 -1
- package/dist/testing/attack_surface.js +4 -4
- package/dist/testing/audit_completeness.d.ts +6 -0
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +158 -134
- package/dist/testing/auth_apps.d.ts.map +1 -1
- package/dist/testing/auth_apps.js +4 -33
- package/dist/testing/db.d.ts +1 -1
- package/dist/testing/db.d.ts.map +1 -1
- package/dist/testing/db.js +2 -0
- package/dist/testing/entities.d.ts +35 -13
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +17 -0
- package/dist/testing/integration.d.ts +10 -0
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +352 -340
- package/dist/testing/integration_helpers.d.ts +16 -5
- package/dist/testing/integration_helpers.d.ts.map +1 -1
- package/dist/testing/integration_helpers.js +24 -4
- package/dist/testing/rate_limiting.d.ts +7 -0
- package/dist/testing/rate_limiting.d.ts.map +1 -1
- package/dist/testing/rate_limiting.js +41 -10
- package/dist/testing/rpc_helpers.d.ts +153 -1
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +184 -8
- package/dist/testing/sse_round_trip.d.ts +8 -0
- package/dist/testing/sse_round_trip.d.ts.map +1 -1
- package/dist/testing/sse_round_trip.js +10 -3
- package/dist/testing/standard.d.ts +9 -1
- package/dist/testing/standard.d.ts.map +1 -1
- package/dist/testing/standard.js +6 -2
- package/dist/testing/surface_invariants.d.ts +7 -3
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +5 -4
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +9 -38
- package/dist/ui/AccountSessions.svelte +8 -4
- package/dist/ui/AccountSessions.svelte.d.ts.map +1 -1
- package/dist/ui/AdminAccounts.svelte +61 -33
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
- package/dist/ui/AdminAuditLog.svelte +3 -2
- package/dist/ui/AdminAuditLog.svelte.d.ts.map +1 -1
- package/dist/ui/AdminInvites.svelte +3 -2
- package/dist/ui/AdminInvites.svelte.d.ts.map +1 -1
- package/dist/ui/AdminOverview.svelte +14 -9
- package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
- package/dist/ui/AdminPermitHistory.svelte +3 -2
- package/dist/ui/AdminPermitHistory.svelte.d.ts.map +1 -1
- package/dist/ui/AdminSessions.svelte +29 -25
- package/dist/ui/AdminSessions.svelte.d.ts.map +1 -1
- package/dist/ui/CLAUDE.md +351 -0
- package/dist/ui/OpenSignupToggle.svelte +6 -3
- package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -1
- package/dist/ui/PermitOfferForm.svelte +141 -0
- package/dist/ui/PermitOfferForm.svelte.d.ts +14 -0
- package/dist/ui/PermitOfferForm.svelte.d.ts.map +1 -0
- package/dist/ui/PermitOfferHistory.svelte +109 -0
- package/dist/ui/PermitOfferHistory.svelte.d.ts +11 -0
- package/dist/ui/PermitOfferHistory.svelte.d.ts.map +1 -0
- package/dist/ui/PermitOfferInbox.svelte +121 -0
- package/dist/ui/PermitOfferInbox.svelte.d.ts +12 -0
- package/dist/ui/PermitOfferInbox.svelte.d.ts.map +1 -0
- package/dist/ui/account_sessions_state.svelte.d.ts +53 -3
- package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.js +39 -16
- package/dist/ui/admin_accounts_state.svelte.d.ts +118 -2
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +99 -23
- package/dist/ui/admin_invites_state.svelte.d.ts +47 -1
- package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_invites_state.svelte.js +38 -26
- package/dist/ui/admin_sessions_state.svelte.d.ts +26 -0
- package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_sessions_state.svelte.js +35 -21
- package/dist/ui/app_settings_state.svelte.d.ts +39 -0
- package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
- package/dist/ui/app_settings_state.svelte.js +34 -18
- package/dist/ui/audit_log_state.svelte.d.ts +40 -3
- package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
- package/dist/ui/audit_log_state.svelte.js +36 -42
- package/dist/ui/auth_state.svelte.d.ts +4 -3
- package/dist/ui/auth_state.svelte.d.ts.map +1 -1
- package/dist/ui/auth_state.svelte.js +4 -1
- package/dist/ui/permit_offers_state.svelte.d.ts +125 -0
- package/dist/ui/permit_offers_state.svelte.d.ts.map +1 -0
- package/dist/ui/permit_offers_state.svelte.js +197 -0
- package/package.json +3 -3
- package/dist/auth/admin_routes.d.ts +0 -29
- package/dist/auth/admin_routes.d.ts.map +0 -1
- package/dist/auth/admin_routes.js +0 -226
- package/dist/auth/app_settings_routes.d.ts +0 -27
- package/dist/auth/app_settings_routes.d.ts.map +0 -1
- package/dist/auth/app_settings_routes.js +0 -66
- package/dist/auth/invite_routes.d.ts +0 -18
- package/dist/auth/invite_routes.d.ts.map +0 -1
- package/dist/auth/invite_routes.js +0 -129
|
@@ -94,9 +94,9 @@ export const query_api_token_list_for_account = async (deps, account_id) => {
|
|
|
94
94
|
* Enforce a per-account token limit by evicting the oldest tokens.
|
|
95
95
|
*
|
|
96
96
|
* Race safety: this function must run inside a transaction alongside the
|
|
97
|
-
* INSERT that created the new token. The caller (
|
|
98
|
-
*
|
|
99
|
-
*
|
|
97
|
+
* INSERT that created the new token. The caller (the `account_token_create`
|
|
98
|
+
* RPC handler) runs under the dispatcher's transaction path because the
|
|
99
|
+
* spec declares `side_effects: true`, ensuring the INSERT + enforce_limit
|
|
100
100
|
* pair is atomic — concurrent token creation cannot interleave.
|
|
101
101
|
*
|
|
102
102
|
* @param deps - query dependencies (must be transaction-scoped)
|
|
@@ -6,24 +6,25 @@
|
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
8
|
import { z } from 'zod';
|
|
9
|
+
import { Uuid } from '../uuid.js';
|
|
9
10
|
/** App settings row from the database. */
|
|
10
11
|
export interface AppSettings {
|
|
11
12
|
open_signup: boolean;
|
|
12
13
|
updated_at: string | null;
|
|
13
|
-
updated_by:
|
|
14
|
+
updated_by: Uuid | null;
|
|
14
15
|
}
|
|
15
16
|
/** Zod schema for client-safe app settings data. */
|
|
16
17
|
export declare const AppSettingsJson: z.ZodObject<{
|
|
17
18
|
open_signup: z.ZodBoolean;
|
|
18
19
|
updated_at: z.ZodNullable<z.ZodString>;
|
|
19
|
-
updated_by: z.ZodNullable<z.
|
|
20
|
+
updated_by: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
20
21
|
}, z.core.$strict>;
|
|
21
22
|
export type AppSettingsJson = z.infer<typeof AppSettingsJson>;
|
|
22
23
|
/** Zod schema for admin app settings with resolved updater username. */
|
|
23
24
|
export declare const AppSettingsWithUsernameJson: z.ZodObject<{
|
|
24
25
|
open_signup: z.ZodBoolean;
|
|
25
26
|
updated_at: z.ZodNullable<z.ZodString>;
|
|
26
|
-
updated_by: z.ZodNullable<z.
|
|
27
|
+
updated_by: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
27
28
|
updated_by_username: z.ZodNullable<z.ZodString>;
|
|
28
29
|
}, z.core.$strict>;
|
|
29
30
|
export type AppSettingsWithUsernameJson = z.infer<typeof AppSettingsWithUsernameJson>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_settings_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/app_settings_schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,0CAA0C;AAC1C,MAAM,WAAW,WAAW;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"app_settings_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/app_settings_schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AAEhC,0CAA0C;AAC1C,MAAM,WAAW,WAAW;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB;AAED,oDAAoD;AACpD,eAAO,MAAM,eAAe;;;;kBAI1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,wEAAwE;AACxE,eAAO,MAAM,2BAA2B;;;;;kBAEtC,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEtF,4CAA4C;AAC5C,eAAO,MAAM,sBAAsB;;kBAEjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
8
|
import { z } from 'zod';
|
|
9
|
+
import { Uuid } from '../uuid.js';
|
|
9
10
|
/** Zod schema for client-safe app settings data. */
|
|
10
11
|
export const AppSettingsJson = z.strictObject({
|
|
11
12
|
open_signup: z.boolean(),
|
|
12
13
|
updated_at: z.string().nullable(),
|
|
13
|
-
updated_by:
|
|
14
|
+
updated_by: Uuid.nullable(),
|
|
14
15
|
});
|
|
15
16
|
/** Zod schema for admin app settings with resolved updater username. */
|
|
16
17
|
export const AppSettingsWithUsernameJson = AppSettingsJson.extend({
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Audit log
|
|
2
|
+
* Audit log SSE stream route.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* The two list-reads (`audit_log_list`, `audit_log_permit_history`) moved to
|
|
5
|
+
* RPC in `admin_actions.ts`, and the admin session listing moved to
|
|
6
|
+
* `admin_session_list` on the same file. What remains here is the optional
|
|
7
|
+
* `GET /audit-log/stream` SSE route — streams aren't an action-kind, so they
|
|
8
|
+
* stay on REST. The event payload broadcast on the stream surfaces via
|
|
9
|
+
* `AUDIT_LOG_EVENT_SPECS` (one `EventSpec` per audit event type) declared
|
|
10
|
+
* alongside the broadcaster in `../realtime/sse_auth_guard.ts`.
|
|
6
11
|
*
|
|
7
12
|
* @module
|
|
8
13
|
*/
|
|
@@ -25,10 +30,13 @@ export interface AuditLogRouteOptions {
|
|
|
25
30
|
};
|
|
26
31
|
}
|
|
27
32
|
/**
|
|
28
|
-
* Create audit
|
|
33
|
+
* Create the optional audit-log SSE route spec.
|
|
29
34
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
35
|
+
* Returns an empty array when `options.stream` is not set — no REST routes
|
|
36
|
+
* live here apart from the stream.
|
|
37
|
+
*
|
|
38
|
+
* @param options - optional stream wiring + role override
|
|
39
|
+
* @returns the SSE route spec (when `options.stream` is provided) or an empty array
|
|
32
40
|
*/
|
|
33
41
|
export declare const create_audit_log_route_specs: (options?: AuditLogRouteOptions) => Array<RouteSpec>;
|
|
34
42
|
//# sourceMappingURL=audit_log_routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit_log_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_routes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"audit_log_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAsB,KAAK,SAAS,EAAE,KAAK,eAAe,EAAC,MAAM,oBAAoB,CAAC;AAC7F,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAC;AAIzE,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACpC,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QACR,SAAS,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,MAAM,IAAI,CAAC;QAC1F,GAAG,EAAE,MAAM,CAAC;KACZ,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GAAI,UAAU,oBAAoB,KAAG,KAAK,CAAC,SAAS,CAgC5F,CAAC"}
|
|
@@ -1,92 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Audit log
|
|
2
|
+
* Audit log SSE stream route.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* The two list-reads (`audit_log_list`, `audit_log_permit_history`) moved to
|
|
5
|
+
* RPC in `admin_actions.ts`, and the admin session listing moved to
|
|
6
|
+
* `admin_session_list` on the same file. What remains here is the optional
|
|
7
|
+
* `GET /audit-log/stream` SSE route — streams aren't an action-kind, so they
|
|
8
|
+
* stay on REST. The event payload broadcast on the stream surfaces via
|
|
9
|
+
* `AUDIT_LOG_EVENT_SPECS` (one `EventSpec` per audit event type) declared
|
|
10
|
+
* alongside the broadcaster in `../realtime/sse_auth_guard.ts`.
|
|
6
11
|
*
|
|
7
12
|
* @module
|
|
8
13
|
*/
|
|
9
14
|
import { z } from 'zod';
|
|
10
|
-
import { AuditLogEventWithUsernamesJson, AdminSessionJson, AuditEventType, PermitHistoryEventJson, } from './audit_log_schema.js';
|
|
11
|
-
import { AUDIT_LOG_DEFAULT_LIMIT, query_audit_log_list_with_usernames, query_audit_log_list_permit_history, } from './audit_log_queries.js';
|
|
12
|
-
import { query_session_list_all_active } from './session_queries.js';
|
|
13
|
-
import { ERROR_INVALID_EVENT_TYPE } from '../http/error_schemas.js';
|
|
14
15
|
import { create_sse_response } from '../realtime/sse.js';
|
|
15
16
|
import { AUTH_SESSION_TOKEN_HASH_KEY, require_request_context } from './request_context.js';
|
|
16
|
-
|
|
17
|
-
/** Parse a string to an integer, returning `undefined` for non-numeric input (including `NaN`). */
|
|
18
|
-
const parse_int_or_undefined = (value) => {
|
|
19
|
-
const n = parseInt(value, 10);
|
|
20
|
-
return Number.isFinite(n) ? n : undefined;
|
|
21
|
-
};
|
|
17
|
+
import { AUDIT_LOG_CHANNEL } from '../realtime/sse_auth_guard.js';
|
|
22
18
|
/**
|
|
23
|
-
* Create audit
|
|
19
|
+
* Create the optional audit-log SSE route spec.
|
|
20
|
+
*
|
|
21
|
+
* Returns an empty array when `options.stream` is not set — no REST routes
|
|
22
|
+
* live here apart from the stream.
|
|
24
23
|
*
|
|
25
|
-
* @param options - optional
|
|
26
|
-
* @returns route
|
|
24
|
+
* @param options - optional stream wiring + role override
|
|
25
|
+
* @returns the SSE route spec (when `options.stream` is provided) or an empty array
|
|
27
26
|
*/
|
|
28
27
|
export const create_audit_log_route_specs = (options) => {
|
|
29
28
|
const role = options?.required_role ?? 'admin';
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
auth: { type: 'role', role },
|
|
35
|
-
description: 'List audit log events with optional filters',
|
|
36
|
-
input: z.null(),
|
|
37
|
-
output: z.strictObject({ events: z.array(AuditLogEventWithUsernamesJson) }),
|
|
38
|
-
errors: { 400: z.looseObject({ error: z.literal(ERROR_INVALID_EVENT_TYPE) }) },
|
|
39
|
-
handler: async (c, route) => {
|
|
40
|
-
const raw_event_type = c.req.query('event_type') || undefined;
|
|
41
|
-
if (raw_event_type && !AuditEventType.safeParse(raw_event_type).success) {
|
|
42
|
-
return c.json({ error: ERROR_INVALID_EVENT_TYPE }, 400);
|
|
43
|
-
}
|
|
44
|
-
const event_type = raw_event_type;
|
|
45
|
-
const account_id = c.req.query('account_id') || undefined;
|
|
46
|
-
const limit = Math.max(1, Math.min(200, parseInt(c.req.query('limit') ?? '', 10) || AUDIT_LOG_DEFAULT_LIMIT));
|
|
47
|
-
const offset = Math.max(0, parseInt(c.req.query('offset') ?? '', 10) || 0);
|
|
48
|
-
const raw_since_seq = c.req.query('since_seq');
|
|
49
|
-
const since_seq = raw_since_seq != null ? parse_int_or_undefined(raw_since_seq) : undefined;
|
|
50
|
-
const events = await query_audit_log_list_with_usernames(route, {
|
|
51
|
-
event_type,
|
|
52
|
-
account_id,
|
|
53
|
-
limit,
|
|
54
|
-
offset,
|
|
55
|
-
since_seq,
|
|
56
|
-
});
|
|
57
|
-
return c.json({ events });
|
|
58
|
-
},
|
|
59
|
-
},
|
|
29
|
+
if (!options?.stream)
|
|
30
|
+
return [];
|
|
31
|
+
const { subscribe, log } = options.stream;
|
|
32
|
+
return [
|
|
60
33
|
{
|
|
61
|
-
method: 'GET',
|
|
62
|
-
path: '/audit-log/permit-history',
|
|
63
|
-
auth: { type: 'role', role },
|
|
64
|
-
description: 'List permit grant and revoke events with usernames',
|
|
65
|
-
input: z.null(),
|
|
66
|
-
output: z.strictObject({ events: z.array(PermitHistoryEventJson) }),
|
|
67
|
-
handler: async (c, route) => {
|
|
68
|
-
const limit = Math.max(1, Math.min(200, parseInt(c.req.query('limit') ?? '', 10) || AUDIT_LOG_DEFAULT_LIMIT));
|
|
69
|
-
const offset = Math.max(0, parseInt(c.req.query('offset') ?? '', 10) || 0);
|
|
70
|
-
const events = await query_audit_log_list_permit_history(route, limit, offset);
|
|
71
|
-
return c.json({ events });
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
method: 'GET',
|
|
76
|
-
path: '/sessions',
|
|
77
|
-
auth: { type: 'role', role },
|
|
78
|
-
description: 'List all active sessions across all accounts',
|
|
79
|
-
input: z.null(),
|
|
80
|
-
output: z.strictObject({ sessions: z.array(AdminSessionJson) }),
|
|
81
|
-
handler: async (c, route) => {
|
|
82
|
-
const sessions = await query_session_list_all_active(route);
|
|
83
|
-
return c.json({ sessions });
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
];
|
|
87
|
-
if (options?.stream) {
|
|
88
|
-
const { subscribe, log } = options.stream;
|
|
89
|
-
routes.push({
|
|
90
34
|
method: 'GET',
|
|
91
35
|
path: '/audit-log/stream',
|
|
92
36
|
auth: { type: 'role', role },
|
|
@@ -102,14 +46,13 @@ export const create_audit_log_route_specs = (options) => {
|
|
|
102
46
|
const token_hash = c.get(AUTH_SESSION_TOKEN_HASH_KEY) ?? null;
|
|
103
47
|
const { response, stream } = create_sse_response(c, log);
|
|
104
48
|
const unsubscribe = subscribe(stream, {
|
|
105
|
-
channels: [
|
|
49
|
+
channels: [AUDIT_LOG_CHANNEL],
|
|
106
50
|
scope: token_hash ?? undefined,
|
|
107
51
|
groups: [ctx.account.id],
|
|
108
52
|
});
|
|
109
53
|
stream.on_close(unsubscribe);
|
|
110
54
|
return response;
|
|
111
55
|
},
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return routes;
|
|
56
|
+
},
|
|
57
|
+
];
|
|
115
58
|
};
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
9
|
import { z } from 'zod';
|
|
10
|
+
import { Uuid } from '../uuid.js';
|
|
10
11
|
/** All tracked auth event types. */
|
|
11
|
-
export declare const AUDIT_EVENT_TYPES: readonly ["login", "logout", "bootstrap", "signup", "password_change", "session_revoke", "session_revoke_all", "token_create", "token_revoke", "token_revoke_all", "permit_grant", "permit_revoke", "invite_create", "invite_delete", "app_settings_update"];
|
|
12
|
+
export declare const AUDIT_EVENT_TYPES: readonly ["login", "logout", "bootstrap", "signup", "password_change", "session_revoke", "session_revoke_all", "token_create", "token_revoke", "token_revoke_all", "permit_grant", "permit_revoke", "permit_offer_create", "permit_offer_accept", "permit_offer_decline", "permit_offer_retract", "permit_offer_expire", "permit_offer_supersede", "invite_create", "invite_delete", "app_settings_update"];
|
|
12
13
|
/** Zod schema for audit event types. */
|
|
13
14
|
export declare const AuditEventType: z.ZodEnum<{
|
|
14
15
|
login: "login";
|
|
@@ -23,6 +24,12 @@ export declare const AuditEventType: z.ZodEnum<{
|
|
|
23
24
|
token_revoke_all: "token_revoke_all";
|
|
24
25
|
permit_grant: "permit_grant";
|
|
25
26
|
permit_revoke: "permit_revoke";
|
|
27
|
+
permit_offer_create: "permit_offer_create";
|
|
28
|
+
permit_offer_accept: "permit_offer_accept";
|
|
29
|
+
permit_offer_decline: "permit_offer_decline";
|
|
30
|
+
permit_offer_retract: "permit_offer_retract";
|
|
31
|
+
permit_offer_expire: "permit_offer_expire";
|
|
32
|
+
permit_offer_supersede: "permit_offer_supersede";
|
|
26
33
|
invite_create: "invite_create";
|
|
27
34
|
invite_delete: "invite_delete";
|
|
28
35
|
app_settings_update: "app_settings_update";
|
|
@@ -51,7 +58,7 @@ export declare const AUDIT_METADATA_SCHEMAS: {
|
|
|
51
58
|
}, z.core.$loose>>;
|
|
52
59
|
signup: z.ZodObject<{
|
|
53
60
|
username: z.ZodString;
|
|
54
|
-
invite_id: z.ZodOptional<z.
|
|
61
|
+
invite_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
55
62
|
open_signup: z.ZodOptional<z.ZodBoolean>;
|
|
56
63
|
}, z.core.$loose>;
|
|
57
64
|
password_change: z.ZodNullable<z.ZodObject<{
|
|
@@ -61,7 +68,9 @@ export declare const AUDIT_METADATA_SCHEMAS: {
|
|
|
61
68
|
session_id: z.ZodString;
|
|
62
69
|
}, z.core.$loose>;
|
|
63
70
|
session_revoke_all: z.ZodObject<{
|
|
64
|
-
count: z.ZodNumber
|
|
71
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
72
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
73
|
+
attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
65
74
|
}, z.core.$loose>;
|
|
66
75
|
token_create: z.ZodObject<{
|
|
67
76
|
token_id: z.ZodString;
|
|
@@ -71,23 +80,67 @@ export declare const AUDIT_METADATA_SCHEMAS: {
|
|
|
71
80
|
token_id: z.ZodString;
|
|
72
81
|
}, z.core.$loose>;
|
|
73
82
|
token_revoke_all: z.ZodObject<{
|
|
74
|
-
count: z.ZodNumber
|
|
83
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
84
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
85
|
+
attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
75
86
|
}, z.core.$loose>;
|
|
76
87
|
permit_grant: z.ZodObject<{
|
|
77
88
|
role: z.ZodString;
|
|
78
|
-
permit_id: z.ZodOptional<z.
|
|
89
|
+
permit_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
90
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
91
|
+
source_offer_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
79
92
|
}, z.core.$loose>;
|
|
80
93
|
permit_revoke: z.ZodObject<{
|
|
81
94
|
role: z.ZodString;
|
|
82
|
-
permit_id: z.
|
|
95
|
+
permit_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
96
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
97
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
98
|
+
}, z.core.$loose>;
|
|
99
|
+
permit_offer_create: z.ZodObject<{
|
|
100
|
+
offer_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
101
|
+
role: z.ZodString;
|
|
102
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
103
|
+
to_account_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
104
|
+
}, z.core.$loose>;
|
|
105
|
+
permit_offer_accept: z.ZodObject<{
|
|
106
|
+
offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
107
|
+
permit_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
108
|
+
role: z.ZodString;
|
|
109
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
110
|
+
}, z.core.$loose>;
|
|
111
|
+
permit_offer_decline: z.ZodObject<{
|
|
112
|
+
offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
113
|
+
role: z.ZodString;
|
|
114
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
115
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
116
|
+
}, z.core.$loose>;
|
|
117
|
+
permit_offer_retract: z.ZodObject<{
|
|
118
|
+
offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
119
|
+
role: z.ZodString;
|
|
120
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
121
|
+
}, z.core.$loose>;
|
|
122
|
+
permit_offer_expire: z.ZodObject<{
|
|
123
|
+
offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
124
|
+
role: z.ZodString;
|
|
125
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
126
|
+
}, z.core.$loose>;
|
|
127
|
+
permit_offer_supersede: z.ZodObject<{
|
|
128
|
+
offer_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
129
|
+
role: z.ZodString;
|
|
130
|
+
scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
|
|
131
|
+
reason: z.ZodEnum<{
|
|
132
|
+
sibling_accepted: "sibling_accepted";
|
|
133
|
+
permit_revoked: "permit_revoked";
|
|
134
|
+
}>;
|
|
135
|
+
cause_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
83
136
|
}, z.core.$loose>;
|
|
84
137
|
invite_create: z.ZodObject<{
|
|
85
|
-
invite_id: z.
|
|
138
|
+
invite_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
86
139
|
email: z.ZodNullable<z.ZodString>;
|
|
87
140
|
username: z.ZodNullable<z.ZodString>;
|
|
88
141
|
}, z.core.$loose>;
|
|
89
142
|
invite_delete: z.ZodObject<{
|
|
90
|
-
invite_id: z.
|
|
143
|
+
invite_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
91
144
|
}, z.core.$loose>;
|
|
92
145
|
app_settings_update: z.ZodObject<{
|
|
93
146
|
setting: z.ZodString;
|
|
@@ -101,13 +154,13 @@ export type AuditMetadataMap = {
|
|
|
101
154
|
};
|
|
102
155
|
/** Audit log row from the database. */
|
|
103
156
|
export interface AuditLogEvent {
|
|
104
|
-
id:
|
|
157
|
+
id: Uuid;
|
|
105
158
|
seq: number;
|
|
106
159
|
event_type: AuditEventType;
|
|
107
160
|
outcome: AuditOutcome;
|
|
108
|
-
actor_id:
|
|
109
|
-
account_id:
|
|
110
|
-
target_account_id:
|
|
161
|
+
actor_id: Uuid | null;
|
|
162
|
+
account_id: Uuid | null;
|
|
163
|
+
target_account_id: Uuid | null;
|
|
111
164
|
ip: string | null;
|
|
112
165
|
created_at: string;
|
|
113
166
|
metadata: Record<string, unknown> | null;
|
|
@@ -124,9 +177,9 @@ export declare const get_audit_metadata: <T extends AuditEventType>(event: Audit
|
|
|
124
177
|
export interface AuditLogInput<T extends AuditEventType = AuditEventType> {
|
|
125
178
|
event_type: T;
|
|
126
179
|
outcome?: AuditOutcome;
|
|
127
|
-
actor_id?:
|
|
128
|
-
account_id?:
|
|
129
|
-
target_account_id?:
|
|
180
|
+
actor_id?: Uuid | null;
|
|
181
|
+
account_id?: Uuid | null;
|
|
182
|
+
target_account_id?: Uuid | null;
|
|
130
183
|
ip?: string | null;
|
|
131
184
|
metadata?: (AuditMetadataMap[T] & Record<string, unknown>) | null;
|
|
132
185
|
}
|
|
@@ -136,14 +189,14 @@ export interface AuditLogListOptions {
|
|
|
136
189
|
offset?: number;
|
|
137
190
|
event_type?: AuditEventType;
|
|
138
191
|
event_type_in?: Array<AuditEventType>;
|
|
139
|
-
account_id?:
|
|
192
|
+
account_id?: Uuid;
|
|
140
193
|
outcome?: AuditOutcome;
|
|
141
194
|
/** When set, only return events with `seq` greater than this value. Enables SSE reconnection gap fill. */
|
|
142
195
|
since_seq?: number;
|
|
143
196
|
}
|
|
144
197
|
/** Zod schema for client-safe audit log event. */
|
|
145
198
|
export declare const AuditLogEventJson: z.ZodObject<{
|
|
146
|
-
id: z.
|
|
199
|
+
id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
147
200
|
seq: z.ZodNumber;
|
|
148
201
|
event_type: z.ZodEnum<{
|
|
149
202
|
login: "login";
|
|
@@ -158,6 +211,12 @@ export declare const AuditLogEventJson: z.ZodObject<{
|
|
|
158
211
|
token_revoke_all: "token_revoke_all";
|
|
159
212
|
permit_grant: "permit_grant";
|
|
160
213
|
permit_revoke: "permit_revoke";
|
|
214
|
+
permit_offer_create: "permit_offer_create";
|
|
215
|
+
permit_offer_accept: "permit_offer_accept";
|
|
216
|
+
permit_offer_decline: "permit_offer_decline";
|
|
217
|
+
permit_offer_retract: "permit_offer_retract";
|
|
218
|
+
permit_offer_expire: "permit_offer_expire";
|
|
219
|
+
permit_offer_supersede: "permit_offer_supersede";
|
|
161
220
|
invite_create: "invite_create";
|
|
162
221
|
invite_delete: "invite_delete";
|
|
163
222
|
app_settings_update: "app_settings_update";
|
|
@@ -166,9 +225,9 @@ export declare const AuditLogEventJson: z.ZodObject<{
|
|
|
166
225
|
success: "success";
|
|
167
226
|
failure: "failure";
|
|
168
227
|
}>;
|
|
169
|
-
actor_id: z.ZodNullable<z.
|
|
170
|
-
account_id: z.ZodNullable<z.
|
|
171
|
-
target_account_id: z.ZodNullable<z.
|
|
228
|
+
actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
229
|
+
account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
230
|
+
target_account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
172
231
|
ip: z.ZodNullable<z.ZodString>;
|
|
173
232
|
created_at: z.ZodString;
|
|
174
233
|
metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
@@ -176,7 +235,7 @@ export declare const AuditLogEventJson: z.ZodObject<{
|
|
|
176
235
|
export type AuditLogEventJson = z.infer<typeof AuditLogEventJson>;
|
|
177
236
|
/** Zod schema for audit log events with resolved usernames. */
|
|
178
237
|
export declare const AuditLogEventWithUsernamesJson: z.ZodObject<{
|
|
179
|
-
id: z.
|
|
238
|
+
id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
180
239
|
seq: z.ZodNumber;
|
|
181
240
|
event_type: z.ZodEnum<{
|
|
182
241
|
login: "login";
|
|
@@ -191,6 +250,12 @@ export declare const AuditLogEventWithUsernamesJson: z.ZodObject<{
|
|
|
191
250
|
token_revoke_all: "token_revoke_all";
|
|
192
251
|
permit_grant: "permit_grant";
|
|
193
252
|
permit_revoke: "permit_revoke";
|
|
253
|
+
permit_offer_create: "permit_offer_create";
|
|
254
|
+
permit_offer_accept: "permit_offer_accept";
|
|
255
|
+
permit_offer_decline: "permit_offer_decline";
|
|
256
|
+
permit_offer_retract: "permit_offer_retract";
|
|
257
|
+
permit_offer_expire: "permit_offer_expire";
|
|
258
|
+
permit_offer_supersede: "permit_offer_supersede";
|
|
194
259
|
invite_create: "invite_create";
|
|
195
260
|
invite_delete: "invite_delete";
|
|
196
261
|
app_settings_update: "app_settings_update";
|
|
@@ -199,9 +264,9 @@ export declare const AuditLogEventWithUsernamesJson: z.ZodObject<{
|
|
|
199
264
|
success: "success";
|
|
200
265
|
failure: "failure";
|
|
201
266
|
}>;
|
|
202
|
-
actor_id: z.ZodNullable<z.
|
|
203
|
-
account_id: z.ZodNullable<z.
|
|
204
|
-
target_account_id: z.ZodNullable<z.
|
|
267
|
+
actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
268
|
+
account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
269
|
+
target_account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
205
270
|
ip: z.ZodNullable<z.ZodString>;
|
|
206
271
|
created_at: z.ZodString;
|
|
207
272
|
metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
@@ -211,7 +276,7 @@ export declare const AuditLogEventWithUsernamesJson: z.ZodObject<{
|
|
|
211
276
|
export type AuditLogEventWithUsernamesJson = z.infer<typeof AuditLogEventWithUsernamesJson>;
|
|
212
277
|
/** Zod schema for permit history events with resolved usernames. */
|
|
213
278
|
export declare const PermitHistoryEventJson: z.ZodObject<{
|
|
214
|
-
id: z.
|
|
279
|
+
id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
215
280
|
seq: z.ZodNumber;
|
|
216
281
|
event_type: z.ZodEnum<{
|
|
217
282
|
login: "login";
|
|
@@ -226,6 +291,12 @@ export declare const PermitHistoryEventJson: z.ZodObject<{
|
|
|
226
291
|
token_revoke_all: "token_revoke_all";
|
|
227
292
|
permit_grant: "permit_grant";
|
|
228
293
|
permit_revoke: "permit_revoke";
|
|
294
|
+
permit_offer_create: "permit_offer_create";
|
|
295
|
+
permit_offer_accept: "permit_offer_accept";
|
|
296
|
+
permit_offer_decline: "permit_offer_decline";
|
|
297
|
+
permit_offer_retract: "permit_offer_retract";
|
|
298
|
+
permit_offer_expire: "permit_offer_expire";
|
|
299
|
+
permit_offer_supersede: "permit_offer_supersede";
|
|
229
300
|
invite_create: "invite_create";
|
|
230
301
|
invite_delete: "invite_delete";
|
|
231
302
|
app_settings_update: "app_settings_update";
|
|
@@ -234,9 +305,9 @@ export declare const PermitHistoryEventJson: z.ZodObject<{
|
|
|
234
305
|
success: "success";
|
|
235
306
|
failure: "failure";
|
|
236
307
|
}>;
|
|
237
|
-
actor_id: z.ZodNullable<z.
|
|
238
|
-
account_id: z.ZodNullable<z.
|
|
239
|
-
target_account_id: z.ZodNullable<z.
|
|
308
|
+
actor_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
309
|
+
account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
310
|
+
target_account_id: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
240
311
|
ip: z.ZodNullable<z.ZodString>;
|
|
241
312
|
created_at: z.ZodString;
|
|
242
313
|
metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
@@ -247,7 +318,7 @@ export type PermitHistoryEventJson = z.infer<typeof PermitHistoryEventJson>;
|
|
|
247
318
|
/** Zod schema for admin session listing (session + username). */
|
|
248
319
|
export declare const AdminSessionJson: z.ZodObject<{
|
|
249
320
|
id: z.ZodString;
|
|
250
|
-
account_id: z.
|
|
321
|
+
account_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
251
322
|
created_at: z.ZodString;
|
|
252
323
|
expires_at: z.ZodString;
|
|
253
324
|
last_seen_at: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit_log_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"audit_log_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AAGhC,oCAAoC;AACpC,eAAO,MAAM,iBAAiB,6YAsBpB,CAAC;AAEX,wCAAwC;AACxC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;EAA4B,CAAC;AACxD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,2CAA2C;AAC3C,eAAO,MAAM,YAAY;;;EAAiC,CAAC;AAC3D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+FU,CAAC;AAE9C,+EAA+E;AAC/E,MAAM,MAAM,gBAAgB,GAAG;KAC7B,CAAC,IAAI,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;CAClE,CAAC;AAEF,uCAAuC;AACvC,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,iBAAiB,EAAE,IAAI,GAAG,IAAI,CAAC;IAC/B,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,cAAc,EAC1D,OAAO,aAAa,GAAG;IAAC,UAAU,EAAE,CAAC,CAAA;CAAC,KACpC,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAExB,CAAC;AAEF,6CAA6C;AAC7C,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc;IACvE,UAAU,EAAE,CAAC,CAAC;IACd,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAChC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;CAClE;AAED,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,aAAa,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACtC,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,0GAA0G;IAC1G,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,kDAAkD;AAClD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAW5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,+DAA+D;AAC/D,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAGzC,CAAC;AACH,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAE5F,oEAAoE;AACpE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAGjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,iEAAiE;AACjE,eAAO,MAAM,gBAAgB;;;;;;;kBAE3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAIhE,eAAO,MAAM,gBAAgB,gdAY3B,CAAC;AAEH,eAAO,MAAM,iBAAiB,UAK7B,CAAC"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
9
|
import { z } from 'zod';
|
|
10
|
+
import { Uuid } from '../uuid.js';
|
|
10
11
|
import { AuthSessionJson } from './account_schema.js';
|
|
11
12
|
/** All tracked auth event types. */
|
|
12
13
|
export const AUDIT_EVENT_TYPES = [
|
|
@@ -22,6 +23,12 @@ export const AUDIT_EVENT_TYPES = [
|
|
|
22
23
|
'token_revoke_all',
|
|
23
24
|
'permit_grant',
|
|
24
25
|
'permit_revoke',
|
|
26
|
+
'permit_offer_create',
|
|
27
|
+
'permit_offer_accept',
|
|
28
|
+
'permit_offer_decline',
|
|
29
|
+
'permit_offer_retract',
|
|
30
|
+
'permit_offer_expire',
|
|
31
|
+
'permit_offer_supersede',
|
|
25
32
|
'invite_create',
|
|
26
33
|
'invite_delete',
|
|
27
34
|
'app_settings_update',
|
|
@@ -43,25 +50,90 @@ export const AUDIT_METADATA_SCHEMAS = {
|
|
|
43
50
|
bootstrap: z.looseObject({ error: z.string() }).nullable(),
|
|
44
51
|
signup: z.looseObject({
|
|
45
52
|
username: z.string(),
|
|
46
|
-
invite_id:
|
|
53
|
+
invite_id: Uuid.optional(),
|
|
47
54
|
open_signup: z.boolean().optional(),
|
|
48
55
|
}),
|
|
49
56
|
password_change: z.looseObject({ sessions_revoked: z.number() }).nullable(),
|
|
50
57
|
session_revoke: z.looseObject({ session_id: z.string() }),
|
|
51
|
-
session_revoke_all: z.looseObject({
|
|
58
|
+
session_revoke_all: z.looseObject({
|
|
59
|
+
// Omitted on `outcome='failure'` (no revocation attempted — e.g. target
|
|
60
|
+
// account not found); `reason` carries the failure category, and
|
|
61
|
+
// `attempted_account_id` preserves the probed id (the `target_account_id`
|
|
62
|
+
// column is null in that case because it's a FK to `account`).
|
|
63
|
+
count: z.number().optional(),
|
|
64
|
+
reason: z.string().optional(),
|
|
65
|
+
attempted_account_id: Uuid.optional(),
|
|
66
|
+
}),
|
|
52
67
|
token_create: z.looseObject({ token_id: z.string(), name: z.string() }),
|
|
53
68
|
token_revoke: z.looseObject({ token_id: z.string() }),
|
|
54
|
-
token_revoke_all: z.looseObject({
|
|
69
|
+
token_revoke_all: z.looseObject({
|
|
70
|
+
// Same shape as `session_revoke_all` for failures.
|
|
71
|
+
count: z.number().optional(),
|
|
72
|
+
reason: z.string().optional(),
|
|
73
|
+
attempted_account_id: Uuid.optional(),
|
|
74
|
+
}),
|
|
55
75
|
// `permit_id` is optional on `permit_grant` because failed grants
|
|
56
76
|
// (e.g. `web_grantable` denied) never produce a permit row.
|
|
57
|
-
permit_grant: z.looseObject({
|
|
58
|
-
|
|
77
|
+
permit_grant: z.looseObject({
|
|
78
|
+
role: z.string(),
|
|
79
|
+
permit_id: Uuid.optional(),
|
|
80
|
+
scope_id: Uuid.nullish(),
|
|
81
|
+
source_offer_id: Uuid.optional(),
|
|
82
|
+
}),
|
|
83
|
+
permit_revoke: z.looseObject({
|
|
84
|
+
role: z.string(),
|
|
85
|
+
permit_id: Uuid,
|
|
86
|
+
scope_id: Uuid.nullish(),
|
|
87
|
+
reason: z.string().optional(),
|
|
88
|
+
}),
|
|
89
|
+
// `offer_id` is optional because failed creates (e.g. `web_grantable`
|
|
90
|
+
// denied, `authorize` callback denied) never produce an offer row.
|
|
91
|
+
permit_offer_create: z.looseObject({
|
|
92
|
+
offer_id: Uuid.optional(),
|
|
93
|
+
role: z.string(),
|
|
94
|
+
scope_id: Uuid.nullish(),
|
|
95
|
+
to_account_id: Uuid,
|
|
96
|
+
}),
|
|
97
|
+
// `permit_grant` is emitted alongside on accept — two events per accept by
|
|
98
|
+
// design: offer-lifecycle audit + permit-lifecycle audit.
|
|
99
|
+
permit_offer_accept: z.looseObject({
|
|
100
|
+
offer_id: Uuid,
|
|
101
|
+
permit_id: Uuid,
|
|
102
|
+
role: z.string(),
|
|
103
|
+
scope_id: Uuid.nullish(),
|
|
104
|
+
}),
|
|
105
|
+
permit_offer_decline: z.looseObject({
|
|
106
|
+
offer_id: Uuid,
|
|
107
|
+
role: z.string(),
|
|
108
|
+
scope_id: Uuid.nullish(),
|
|
109
|
+
reason: z.string().optional(),
|
|
110
|
+
}),
|
|
111
|
+
permit_offer_retract: z.looseObject({
|
|
112
|
+
offer_id: Uuid,
|
|
113
|
+
role: z.string(),
|
|
114
|
+
scope_id: Uuid.nullish(),
|
|
115
|
+
}),
|
|
116
|
+
permit_offer_expire: z.looseObject({
|
|
117
|
+
offer_id: Uuid,
|
|
118
|
+
role: z.string(),
|
|
119
|
+
scope_id: Uuid.nullish(),
|
|
120
|
+
}),
|
|
121
|
+
// Emitted when an offer is obsoleted by an external event. `reason`
|
|
122
|
+
// distinguishes the trigger; `cause_id` points to the accepted offer
|
|
123
|
+
// (for `sibling_accepted`) or the revoked permit (for `permit_revoked`).
|
|
124
|
+
permit_offer_supersede: z.looseObject({
|
|
125
|
+
offer_id: Uuid,
|
|
126
|
+
role: z.string(),
|
|
127
|
+
scope_id: Uuid.nullish(),
|
|
128
|
+
reason: z.enum(['sibling_accepted', 'permit_revoked']),
|
|
129
|
+
cause_id: Uuid,
|
|
130
|
+
}),
|
|
59
131
|
invite_create: z.looseObject({
|
|
60
|
-
invite_id:
|
|
132
|
+
invite_id: Uuid,
|
|
61
133
|
email: z.string().nullable(),
|
|
62
134
|
username: z.string().nullable(),
|
|
63
135
|
}),
|
|
64
|
-
invite_delete: z.looseObject({ invite_id:
|
|
136
|
+
invite_delete: z.looseObject({ invite_id: Uuid }),
|
|
65
137
|
app_settings_update: z.looseObject({
|
|
66
138
|
setting: z.string(),
|
|
67
139
|
old_value: z.unknown(),
|
|
@@ -78,13 +150,13 @@ export const get_audit_metadata = (event) => {
|
|
|
78
150
|
};
|
|
79
151
|
/** Zod schema for client-safe audit log event. */
|
|
80
152
|
export const AuditLogEventJson = z.strictObject({
|
|
81
|
-
id:
|
|
153
|
+
id: Uuid,
|
|
82
154
|
seq: z.number().int(),
|
|
83
155
|
event_type: AuditEventType,
|
|
84
156
|
outcome: AuditOutcome,
|
|
85
|
-
actor_id:
|
|
86
|
-
account_id:
|
|
87
|
-
target_account_id:
|
|
157
|
+
actor_id: Uuid.nullable(),
|
|
158
|
+
account_id: Uuid.nullable(),
|
|
159
|
+
target_account_id: Uuid.nullable(),
|
|
88
160
|
ip: z.string().nullable(),
|
|
89
161
|
created_at: z.string(),
|
|
90
162
|
metadata: z.record(z.string(), z.unknown()).nullable(),
|