@fuzdev/fuz_app 0.141.0 → 0.142.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 +10 -5
- package/dist/actions/connection_closer.d.ts +19 -2
- package/dist/actions/connection_closer.d.ts.map +1 -1
- package/dist/actions/connection_closer.js +25 -2
- package/dist/actions/perform_action.d.ts +10 -0
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +23 -9
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +5 -2
- package/dist/auth/CLAUDE.md +33 -13
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +12 -1
- package/dist/auth/account_route_schema.d.ts.map +1 -1
- package/dist/auth/account_route_schema.js +8 -0
- package/dist/auth/account_routes.d.ts +7 -2
- package/dist/auth/account_routes.d.ts.map +1 -1
- package/dist/auth/account_routes.js +240 -187
- package/dist/auth/admin_action_specs.d.ts +6 -1
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +6 -1
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +14 -2
- package/dist/auth/bootstrap_routes.d.ts.map +1 -1
- package/dist/auth/bootstrap_routes.js +85 -76
- package/dist/auth/cell_action_specs.d.ts +7 -3
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +9 -5
- package/dist/auth/cell_actions.d.ts +3 -3
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +67 -38
- package/dist/auth/cell_authorize.d.ts +69 -8
- package/dist/auth/cell_authorize.d.ts.map +1 -1
- package/dist/auth/cell_authorize.js +89 -9
- package/dist/auth/cell_field_action_specs.d.ts +5 -4
- package/dist/auth/cell_field_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_field_action_specs.js +7 -7
- package/dist/auth/cell_field_actions.d.ts +7 -5
- package/dist/auth/cell_field_actions.d.ts.map +1 -1
- package/dist/auth/cell_field_actions.js +24 -22
- package/dist/auth/cell_grant_action_specs.d.ts +6 -0
- package/dist/auth/cell_grant_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_grant_action_specs.js +6 -0
- package/dist/auth/cell_grant_actions.d.ts +3 -1
- package/dist/auth/cell_grant_actions.d.ts.map +1 -1
- package/dist/auth/cell_grant_actions.js +16 -2
- package/dist/auth/cell_item_action_specs.d.ts +5 -4
- package/dist/auth/cell_item_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_item_action_specs.js +7 -7
- package/dist/auth/cell_item_actions.d.ts +6 -5
- package/dist/auth/cell_item_actions.d.ts.map +1 -1
- package/dist/auth/cell_item_actions.js +23 -22
- package/dist/auth/cell_relation_list_limit.d.ts +20 -0
- package/dist/auth/cell_relation_list_limit.d.ts.map +1 -0
- package/dist/auth/cell_relation_list_limit.js +27 -0
- package/dist/auth/cell_relation_visibility.d.ts +4 -3
- package/dist/auth/cell_relation_visibility.d.ts.map +1 -1
- package/dist/auth/cell_relation_visibility.js +6 -5
- package/dist/auth/cell_steward.d.ts +45 -0
- package/dist/auth/cell_steward.d.ts.map +1 -0
- package/dist/auth/cell_steward.js +53 -0
- package/dist/auth/request_context.d.ts +4 -0
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +6 -1
- package/dist/auth/role_grant_offer_action_specs.d.ts +5 -0
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +6 -1
- package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_actions.js +23 -16
- package/dist/auth/role_grant_offer_queries.d.ts +8 -6
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_queries.js +16 -8
- package/dist/auth/signup_routes.d.ts +4 -3
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +157 -134
- package/dist/auth/token_scope.d.ts +7 -1
- package/dist/auth/token_scope.d.ts.map +1 -1
- package/dist/auth/token_scope.js +8 -2
- package/dist/db/CLAUDE.md +32 -19
- package/dist/db/cell_ddl.d.ts +1 -2
- package/dist/db/cell_ddl.d.ts.map +1 -1
- package/dist/db/cell_ddl.js +1 -2
- package/dist/db/cell_field_queries.d.ts +20 -18
- package/dist/db/cell_field_queries.d.ts.map +1 -1
- package/dist/db/cell_field_queries.js +28 -22
- package/dist/db/cell_item_queries.d.ts +20 -14
- package/dist/db/cell_item_queries.d.ts.map +1 -1
- package/dist/db/cell_item_queries.js +28 -18
- package/dist/db/cell_moderation.d.ts +67 -0
- package/dist/db/cell_moderation.d.ts.map +1 -0
- package/dist/db/cell_moderation.js +66 -0
- package/dist/db/cell_queries.d.ts +44 -14
- package/dist/db/cell_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.js +68 -45
- package/dist/db/cell_view_sql.d.ts +102 -0
- package/dist/db/cell_view_sql.d.ts.map +1 -0
- package/dist/db/cell_view_sql.js +112 -0
- package/dist/db/db_pg.d.ts +1 -1
- package/dist/db/db_pg.js +1 -1
- package/dist/http/auth_shape.d.ts +5 -2
- package/dist/http/auth_shape.d.ts.map +1 -1
- package/dist/http/auth_shape.js +5 -2
- package/dist/http/ip_canonical.d.ts +30 -3
- package/dist/http/ip_canonical.d.ts.map +1 -1
- package/dist/http/ip_canonical.js +50 -3
- package/dist/primitive_schemas.d.ts +10 -1
- package/dist/primitive_schemas.d.ts.map +1 -1
- package/dist/primitive_schemas.js +11 -2
- package/dist/rate_limiter.d.ts +179 -12
- package/dist/rate_limiter.d.ts.map +1 -1
- package/dist/rate_limiter.js +352 -42
- package/dist/server/serve_fact_route.d.ts +8 -4
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +15 -6
- package/dist/testing/CLAUDE.md +10 -3
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/account_lifecycle.js +37 -2
- package/dist/testing/cross_backend/cell_gated_create.d.ts +38 -0
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +401 -5
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_relations.js +145 -2
- package/dist/testing/cross_backend/expected_schema.json +0 -1
- package/dist/testing/cross_backend/login_security.d.ts +16 -0
- package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
- package/dist/testing/cross_backend/login_security.js +154 -0
- package/dist/testing/cross_backend/query_shape.d.ts.map +1 -1
- package/dist/testing/cross_backend/query_shape.js +24 -2
- package/dist/testing/cross_backend/role_grant_participation.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_participation.js +64 -0
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +1 -1
- package/dist/testing/cross_backend/ws_action_rate_limit.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_action_rate_limit.js +21 -1
- package/dist/testing/schema_introspect.js +1 -1
- package/dist/testing/schema_parity.d.ts +4 -3
- package/dist/testing/schema_parity.d.ts.map +1 -1
- package/dist/testing/schema_parity.js +4 -3
- package/dist/testing/schema_ready_fixture.d.ts +2 -4
- package/dist/testing/schema_ready_fixture.d.ts.map +1 -1
- package/dist/testing/schema_ready_fixture.js +2 -4
- package/dist/ui/auth_state.svelte.d.ts +10 -0
- package/dist/ui/auth_state.svelte.d.ts.map +1 -1
- package/dist/ui/auth_state.svelte.js +22 -4
- package/package.json +1 -1
- package/dist/db/cell_history_ddl.d.ts +0 -38
- package/dist/db/cell_history_ddl.d.ts.map +0 -1
- package/dist/db/cell_history_ddl.js +0 -61
package/dist/actions/CLAUDE.md
CHANGED
|
@@ -641,16 +641,21 @@ closed) — so a closed transport or registry hosts nothing more. Its Rust
|
|
|
641
641
|
counterpart is `ShutdownCloser::close_all_sockets`, a supertrait of
|
|
642
642
|
`SocketRevoker`.
|
|
643
643
|
|
|
644
|
-
**Every revocation closes after its commit.** A handler
|
|
645
|
-
inline: it calls
|
|
644
|
+
**Every revocation closes after its commit.** A handler inside a route or
|
|
645
|
+
action transaction never calls a closer inline: it calls
|
|
646
|
+
`queue_connection_close(ctx, deps.connection_closer, target)`,
|
|
646
647
|
which puts the close on the request's post-commit queue (`emit_after_commit`).
|
|
647
648
|
The close runs once the handler's transaction has committed and is discarded
|
|
648
649
|
when the handler throws — a rolled-back revocation closes nothing. `target` is
|
|
649
650
|
a `ConnectionCloseTarget` (`{kind: 'session', session_token_hash}` /
|
|
650
651
|
`{kind: 'token', api_token_id}` / `{kind: 'account', account_id}` /
|
|
651
652
|
`{kind: 'role', account_id, role}`);
|
|
652
|
-
`close_connections(closer, target)` is the immediate form the queue runs.
|
|
653
|
-
|
|
653
|
+
`close_connections(closer, target)` is the immediate form the queue runs. A
|
|
654
|
+
handler with no wrapping transaction (`/login`, `/password`) opens its own
|
|
655
|
+
around its writes and closes straight after that commit with
|
|
656
|
+
`close_connections_after_commit(closer, target, log)`, which logs a failing
|
|
657
|
+
close as the post-commit flush does. Twin of `queue_socket_close` /
|
|
658
|
+
`SocketCloseTarget`.
|
|
654
659
|
|
|
655
660
|
The order is load-bearing for admission: a connection registers, then re-reads
|
|
656
661
|
its credential, so a close that missed the registration must belong to a
|
|
@@ -812,7 +817,7 @@ Composes the standard upgrade stack:
|
|
|
812
817
|
1. `verify_request_source(allowed_origins)`
|
|
813
818
|
2. `require_auth`
|
|
814
819
|
3. `require_token_scope('surface:ws_upgrade')` — a narrowed token cannot hold a socket
|
|
815
|
-
4. Upgrade-time authorization phase — resolves the acting actor, seeds `REQUEST_CONTEXT_KEY` for the inner `register_action_ws`
|
|
820
|
+
4. Upgrade-time authorization phase — resolves the acting actor (`?acting=` through `parse_acting`; malformed reads as omitted), seeds `REQUEST_CONTEXT_KEY` for the inner `register_action_ws`
|
|
816
821
|
5. Optional `require_role(required_roles)` — any-of disjunction (coarse upgrade-time gate; per-action `auth` in each spec still applies at dispatch time)
|
|
817
822
|
6. Delegates to `register_action_ws`
|
|
818
823
|
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
* @module
|
|
47
47
|
*/
|
|
48
48
|
import type { Uuid } from '../primitive_schemas.js';
|
|
49
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
49
50
|
import { type EmitAfterCommitContext } from '../http/pending_effects.js';
|
|
50
51
|
/**
|
|
51
52
|
* Close live connections by identity, or all of them.
|
|
@@ -127,6 +128,21 @@ export type ConnectionCloseTarget = {
|
|
|
127
128
|
* @returns how many connections closed
|
|
128
129
|
*/
|
|
129
130
|
export declare const close_connections: (closer: ConnectionCloser, target: ConnectionCloseTarget) => number;
|
|
131
|
+
/**
|
|
132
|
+
* Close the connections `target` names, now, for a revocation that has
|
|
133
|
+
* already committed — logging a close that throws instead of throwing it.
|
|
134
|
+
*
|
|
135
|
+
* For a handler with no route transaction, closing straight after its own
|
|
136
|
+
* commit: a throw there would fail a request whose revocation stands, and skip
|
|
137
|
+
* the work after the close (the response, the audit row). A closer over several
|
|
138
|
+
* transports closes the rest before it rethrows, so catching loses no close.
|
|
139
|
+
* The twin of the post-commit flush, which catches and logs the same way.
|
|
140
|
+
*
|
|
141
|
+
* @param closer - the closer to run, `deps.connection_closer` in a handler
|
|
142
|
+
* @param target - the connections to close
|
|
143
|
+
* @param log - where a failing close is reported
|
|
144
|
+
*/
|
|
145
|
+
export declare const close_connections_after_commit: (closer: ConnectionCloser, target: ConnectionCloseTarget, log: Logger) => void;
|
|
130
146
|
/**
|
|
131
147
|
* Queue a connection close on `ctx`'s post-commit queue, so it runs only after
|
|
132
148
|
* the request's transaction commits and never when the handler throws.
|
|
@@ -135,8 +151,9 @@ export declare const close_connections: (closer: ConnectionCloser, target: Conne
|
|
|
135
151
|
* why an in-transaction revocation must not close inline.
|
|
136
152
|
*
|
|
137
153
|
* In a handler with no wrapping transaction a throw still drops the queued
|
|
138
|
-
* close while an autocommit write stays;
|
|
139
|
-
*
|
|
154
|
+
* close while an autocommit write stays; such a handler closes inline straight
|
|
155
|
+
* after its own commit instead, with `close_connections_after_commit`, which
|
|
156
|
+
* catches and logs a failing close as the post-commit flush does.
|
|
140
157
|
*
|
|
141
158
|
* @param ctx - the route or action context of the request doing the revoking
|
|
142
159
|
* @param closer - the closer to run, `deps.connection_closer` in a handler
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection_closer.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/connection_closer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"connection_closer.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/connection_closer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAE5F;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,gBAAgB;IAChC,qGAAqG;IACrG,yBAAyB,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,MAAM,CAAC;IAClE,4EAA4E;IAC5E,uBAAuB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1D;;;;OAIG;IACH,yBAAyB,EAAE,CAAC,UAAU,EAAE,IAAI,KAAK,MAAM,CAAC;IACxD;;;;;;;;;;;;OAYG;IACH,sBAAsB,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACnE;;;;;;;OAOG;IACH,iBAAiB,EAAE,MAAM,MAAM,CAAC;CAChC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAC7B,QAAQ,gBAAgB,EACxB,QAAQ,qBAAqB,KAC3B,MAaF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,8BAA8B,GAC1C,QAAQ,gBAAgB,EACxB,QAAQ,qBAAqB,EAC7B,KAAK,MAAM,KACT,IAMF,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,GAClC,KAAK,sBAAsB,EAC3B,QAAQ,gBAAgB,EACxB,QAAQ,qBAAqB,KAC3B,IAIF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,gBAMnC,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACvD;;;;;;;;;;;;;;;OAeG;IACH,GAAG,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,MAAM,IAAI,CAAC;IAC9C,2EAA2E;IAC3E,YAAY,EAAE,MAAM,MAAM,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,QAAO,cA8CzC,CAAC"}
|
|
@@ -69,6 +69,28 @@ export const close_connections = (closer, target) => {
|
|
|
69
69
|
throw new UnreachableError(target);
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Close the connections `target` names, now, for a revocation that has
|
|
74
|
+
* already committed — logging a close that throws instead of throwing it.
|
|
75
|
+
*
|
|
76
|
+
* For a handler with no route transaction, closing straight after its own
|
|
77
|
+
* commit: a throw there would fail a request whose revocation stands, and skip
|
|
78
|
+
* the work after the close (the response, the audit row). A closer over several
|
|
79
|
+
* transports closes the rest before it rethrows, so catching loses no close.
|
|
80
|
+
* The twin of the post-commit flush, which catches and logs the same way.
|
|
81
|
+
*
|
|
82
|
+
* @param closer - the closer to run, `deps.connection_closer` in a handler
|
|
83
|
+
* @param target - the connections to close
|
|
84
|
+
* @param log - where a failing close is reported
|
|
85
|
+
*/
|
|
86
|
+
export const close_connections_after_commit = (closer, target, log) => {
|
|
87
|
+
try {
|
|
88
|
+
close_connections(closer, target);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
log.error('connection close after commit failed:', err);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
72
94
|
/**
|
|
73
95
|
* Queue a connection close on `ctx`'s post-commit queue, so it runs only after
|
|
74
96
|
* the request's transaction commits and never when the handler throws.
|
|
@@ -77,8 +99,9 @@ export const close_connections = (closer, target) => {
|
|
|
77
99
|
* why an in-transaction revocation must not close inline.
|
|
78
100
|
*
|
|
79
101
|
* In a handler with no wrapping transaction a throw still drops the queued
|
|
80
|
-
* close while an autocommit write stays;
|
|
81
|
-
*
|
|
102
|
+
* close while an autocommit write stays; such a handler closes inline straight
|
|
103
|
+
* after its own commit instead, with `close_connections_after_commit`, which
|
|
104
|
+
* catches and logs a failing close as the post-commit flush does.
|
|
82
105
|
*
|
|
83
106
|
* @param ctx - the route or action context of the request doing the revoking
|
|
84
107
|
* @param closer - the closer to run, `deps.connection_closer` in a handler
|
|
@@ -163,6 +163,16 @@ export type PerformActionResult = {
|
|
|
163
163
|
* the harness omits `account_id`.
|
|
164
164
|
*/
|
|
165
165
|
export declare const perform_action: (input: PerformActionInput, deps: PerformActionDeps) => Promise<PerformActionResult>;
|
|
166
|
+
/**
|
|
167
|
+
* The credential-type 403 — one builder, so the dispatcher's gate below and a
|
|
168
|
+
* handler that gates a credential channel on its input (`account_delete`'s
|
|
169
|
+
* self path) emit a byte-identical error. Twin of the Rust
|
|
170
|
+
* `fuz_auth::credential_type_required`.
|
|
171
|
+
*
|
|
172
|
+
* @param required_credential_types - the channels that would be admitted
|
|
173
|
+
* @returns the `forbidden` error object with reason `credential_type_required`
|
|
174
|
+
*/
|
|
175
|
+
export declare const credential_type_required_error: (required_credential_types: ReadonlyArray<string>) => JsonrpcErrorObject;
|
|
166
176
|
/**
|
|
167
177
|
* Build a JSON-RPC response envelope from a `PerformActionResult` for
|
|
168
178
|
* transports that wire over the JSON-RPC 2.0 message shape (HTTP RPC + WS).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perform_action.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/perform_action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"perform_action.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/perform_action.ts"],"names":[],"mappings":"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"}
|
|
@@ -58,6 +58,7 @@ import { DEV } from 'esm-env';
|
|
|
58
58
|
import { apply_authorization_phase, has_any_scoped_role } from '../auth/request_context.js';
|
|
59
59
|
import {} from '../hono_context.js';
|
|
60
60
|
import { to_input_params } from '../http/schema_helpers.js';
|
|
61
|
+
import { rate_limit_ip_key } from '../http/ip_canonical.js';
|
|
61
62
|
import { dispatch_with_post_commit_rollback } from '../http/pending_effects.js';
|
|
62
63
|
import { JSONRPC_VERSION } from '../http/jsonrpc.js';
|
|
63
64
|
import { jsonrpc_error_messages, jsonrpc_error_code_to_http_status, http_status_to_jsonrpc_error_code, JSONRPC_ERROR_CODES, dev_only } from '../http/jsonrpc_errors.js';
|
|
@@ -119,14 +120,17 @@ export const perform_action = async (input, deps) => {
|
|
|
119
120
|
// budget it should, and so a throttled caller pays no schema work.
|
|
120
121
|
const rate_limit = spec.rate_limit;
|
|
121
122
|
if (rate_limit) {
|
|
122
|
-
const
|
|
123
|
+
const ip_limiter = rate_limit === 'ip' || rate_limit === 'both' ? action_ip_rate_limiter : null;
|
|
123
124
|
const account_keyed_context = action_account_rate_limiter &&
|
|
124
125
|
request_context !== null &&
|
|
125
126
|
(rate_limit === 'account' || rate_limit === 'both')
|
|
126
127
|
? request_context
|
|
127
128
|
: null;
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
// keyed by the address's rate-limit key (an IPv6 client's /64); the
|
|
130
|
+
// audit trail keeps `client_ip` whole
|
|
131
|
+
const ip_key = ip_limiter ? rate_limit_ip_key(client_ip) : '';
|
|
132
|
+
if (ip_limiter) {
|
|
133
|
+
const result = ip_limiter.check(ip_key);
|
|
130
134
|
if (!result.allowed)
|
|
131
135
|
return rate_limited_result(result.retry_after);
|
|
132
136
|
}
|
|
@@ -135,8 +139,8 @@ export const perform_action = async (input, deps) => {
|
|
|
135
139
|
if (!result.allowed)
|
|
136
140
|
return rate_limited_result(result.retry_after);
|
|
137
141
|
}
|
|
138
|
-
if (
|
|
139
|
-
|
|
142
|
+
if (ip_limiter)
|
|
143
|
+
ip_limiter.record(ip_key);
|
|
140
144
|
if (account_keyed_context) {
|
|
141
145
|
action_account_rate_limiter.record(account_keyed_context.account.id);
|
|
142
146
|
}
|
|
@@ -262,6 +266,19 @@ const check_action_auth_pre_authorization = (auth, account_id) => {
|
|
|
262
266
|
}
|
|
263
267
|
return null;
|
|
264
268
|
};
|
|
269
|
+
/**
|
|
270
|
+
* The credential-type 403 — one builder, so the dispatcher's gate below and a
|
|
271
|
+
* handler that gates a credential channel on its input (`account_delete`'s
|
|
272
|
+
* self path) emit a byte-identical error. Twin of the Rust
|
|
273
|
+
* `fuz_auth::credential_type_required`.
|
|
274
|
+
*
|
|
275
|
+
* @param required_credential_types - the channels that would be admitted
|
|
276
|
+
* @returns the `forbidden` error object with reason `credential_type_required`
|
|
277
|
+
*/
|
|
278
|
+
export const credential_type_required_error = (required_credential_types) => jsonrpc_error_messages.forbidden('forbidden', {
|
|
279
|
+
reason: ERROR_CREDENTIAL_TYPE_REQUIRED,
|
|
280
|
+
required_credential_types
|
|
281
|
+
});
|
|
265
282
|
/**
|
|
266
283
|
* Post-authorization auth gate — fires after the authorization phase
|
|
267
284
|
* resolved the actor + role_grants. Enforces `auth.credential_types` and
|
|
@@ -289,10 +306,7 @@ const check_action_auth_pre_authorization = (auth, account_id) => {
|
|
|
289
306
|
const check_action_auth_post_authorization = (auth, request_context, credential_type, method, token_scope) => {
|
|
290
307
|
if (auth.credential_types?.length) {
|
|
291
308
|
if (!credential_type || !auth.credential_types.includes(credential_type)) {
|
|
292
|
-
return
|
|
293
|
-
reason: ERROR_CREDENTIAL_TYPE_REQUIRED,
|
|
294
|
-
required_credential_types: auth.credential_types
|
|
295
|
-
});
|
|
309
|
+
return credential_type_required_error(auth.credential_types);
|
|
296
310
|
}
|
|
297
311
|
}
|
|
298
312
|
// Token-scope gate — second of three. See the doc comment for why the order
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register_ws_endpoint.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/register_ws_endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;
|
|
1
|
+
{"version":3,"file":"register_ws_endpoint.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/register_ws_endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAcH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAEN,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,MAAM,yBAAyB,CAAC;AAEjC,0CAA0C;AAC1C,MAAM,WAAW,yBAA0B,SAAQ,uBAAuB;IACzE;;;;OAIG;IACH,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CACzC;AA6CD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,yBAAyB,KAChC,sBAoBF,CAAC"}
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
import { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
36
36
|
import { apply_authorization_phase, REQUEST_CONTEXT_KEY, require_auth, require_role, require_token_scope } from '../auth/request_context.js';
|
|
37
37
|
import { verify_request_source } from '../http/origin.js';
|
|
38
|
+
import { parse_acting } from '../http/auth_shape.js';
|
|
38
39
|
import { ACCOUNT_ID_KEY, TEST_CONTEXT_PRESET_KEY } from '../hono_context.js';
|
|
39
40
|
import { register_action_ws } from './register_action_ws.js';
|
|
40
41
|
/** Synthesized auth shape for WS upgrade: account + actor both required. */
|
|
@@ -62,9 +63,11 @@ const create_ws_authorization_middleware = (db) => {
|
|
|
62
63
|
await next();
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
// through the `ActingActor` schema like every other selector: lowercased,
|
|
67
|
+
// and a malformed value reads as omitted (`parse_acting`)
|
|
68
|
+
const acting = parse_acting(c.req.query('acting'));
|
|
66
69
|
const account_id = c.get(ACCOUNT_ID_KEY) ?? null;
|
|
67
|
-
const result = await apply_authorization_phase({ db }, account_id, WS_UPGRADE_AUTH,
|
|
70
|
+
const result = await apply_authorization_phase({ db }, account_id, WS_UPGRADE_AUTH, acting);
|
|
68
71
|
if (!result.ok)
|
|
69
72
|
return c.json(result.body, result.status);
|
|
70
73
|
if (result.request_context !== null) {
|
package/dist/auth/CLAUDE.md
CHANGED
|
@@ -269,16 +269,33 @@ delete / list / clone / moderate`), error reasons, and `all_cell_action_specs`
|
|
|
269
269
|
manage grants or read the audit timeline. NULL
|
|
270
270
|
`created_by` (system origin) is admin-only for edit/manage (explicit
|
|
271
271
|
defense-in-depth). "Admin" on every tier is the **global** grant — a
|
|
272
|
-
scoped `admin` row bypasses nothing.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
272
|
+
scoped `admin` row bypasses nothing. `can_view_cell`'s public and grant
|
|
273
|
+
arms also require the cell's `moderation` to admit an audience
|
|
274
|
+
(`db/cell_moderation.ts`: unmoderated or `approved`), so a pending or
|
|
275
|
+
rejected contribution is its author's and admins' alone; `can_edit_cell`'s
|
|
276
|
+
editor-grant arm requires the same admission. `can_steward_cell`
|
|
277
|
+
is the separate moderator read: the governing root's manager on a pending or
|
|
278
|
+
rejected contribution under a live root.
|
|
279
|
+
- `auth/cell_steward.ts` — `cell_steward_admits(deps, auth, cell)`: the steward
|
|
280
|
+
arm with its governing-root load, run only after `can_view_cell` denies. Its
|
|
281
|
+
module doc names where the arm applies (`cell_get`, `cell_moderate`, the
|
|
282
|
+
cell-scoped fact route, `cell_list`'s SQL) and where it must not (clone,
|
|
283
|
+
contribution parents, relation reads, `shared_with`, grant recompute).
|
|
284
|
+
- Strict relation-read visibility — every relation read drops edges whose far
|
|
285
|
+
endpoint the caller can't view, so a viewer of a parent can't enumerate
|
|
286
|
+
private linked cells by id. **Forward and reverse** `cell_field_list` /
|
|
287
|
+
`cell_item_list` filter in SQL before their limit
|
|
288
|
+
(`db/cell_view_sql.ts`'s `can_view_cell_sql`, bound through
|
|
289
|
+
`cell_viewer_from_auth`), so a page is up to `limit` edges whose other end
|
|
290
|
+
the caller can view — `CELL_RELATION_LIST_LIMIT_DEFAULT` (50) when omitted,
|
|
291
|
+
`CELL_RELATION_LIST_LIMIT_MAX` (500) at most
|
|
292
|
+
(`auth/cell_relation_list_limit.ts`), and hidden ends never crowd out
|
|
293
|
+
visible ones. The `cell_get` bundle (whose `*_truncated` counts raw edges)
|
|
294
|
+
and the clone walk read with `CELL_VIEWER_UNRESTRICTED` and filter after,
|
|
295
|
+
through `auth/cell_relation_visibility.ts`'s `filter_visible_target_ids(deps,
|
|
296
|
+
auth, ids)`: two queries for the whole id-set, the cells read through the
|
|
297
|
+
narrow `CELL_VIEW_COLUMNS` projection (`query_cell_view_load_many`), never
|
|
298
|
+
the payload.
|
|
282
299
|
- `auth/cell_actions.ts` — `create_cell_actions(deps)`, the generic
|
|
283
300
|
handlers. `cell_create` stamps `created_by` + writes the top-level `kind`
|
|
284
301
|
column; `path` writes are admin-only. It also resolves the directory tree:
|
|
@@ -296,7 +313,9 @@ auth, ids)`: batched strict relation-read filter. Every relation read —
|
|
|
296
313
|
parent-aware `authorize_create` dep (`CellCreateAuthorize` — wider input
|
|
297
314
|
`{kind, data, parent_id, root_id, root_data, scope_id}` than `validate_data`,
|
|
298
315
|
returning a `CellCreateVerdict` `{allow:false} | {allow:true, moderation_required}`)
|
|
299
|
-
gates create by capability; it runs after the validator + the parent-resolve
|
|
316
|
+
gates create by capability; it runs after the validator + the parent-resolve
|
|
317
|
+
(which **404**s `cell_not_found` on a missing or soft-deleted root as on a
|
|
318
|
+
missing parent, authorizer or not).
|
|
300
319
|
A **viewable**-parent / root-creation deny is **403** `cell_create_forbidden`
|
|
301
320
|
(the create-path **404** mask is reserved for a hidden parent); `Allow` folds
|
|
302
321
|
the moderation outcome (born `pending`+private vs `approved`+author-visibility).
|
|
@@ -306,7 +325,8 @@ auth, ids)`: batched strict relation-read filter. Every relation read —
|
|
|
306
325
|
single-connection deadlock of the in-memory drivers). `None`/omitted = open create (the default;
|
|
307
326
|
mirrors `validate_data`). `cell_moderate` is the `pending → approved | rejected`
|
|
308
327
|
transition, gated on `can_manage_cell` of the **governing root** (admin / root
|
|
309
|
-
owner — the author lands a 403, the anti-self-approval guard
|
|
328
|
+
owner — the author lands a 403, the anti-self-approval guard; a root owner
|
|
329
|
+
reaches the check through the steward arm); approve flips
|
|
310
330
|
`moderation → approved` + `visibility → public`, reject sets `rejected`.
|
|
311
331
|
- `auth/cell_grant_actions.ts` / `cell_field_actions.ts` /
|
|
312
332
|
`cell_item_actions.ts` / `cell_audit_actions.ts` — the relation + ACL +
|
|
@@ -588,7 +608,7 @@ reactivation has no self path because a soft-deleted account can't
|
|
|
588
608
|
authenticate.
|
|
589
609
|
|
|
590
610
|
- `admin_account_list_action_spec` — read; input `{limit?, offset?, include_deleted?}`; output `{accounts, grantable_roles}`. `include_deleted` (default false) surfaces soft-deleted rows (with `account.deleted_at` set) for the admin UI's reactivation view.
|
|
591
|
-
- `account_delete_action_spec` — mutation (soft delete); self-or-admin (`{account, actor}`, handler elevates to admin when `account_id` ≠ self); input `{account_id?}`; output `{ok, deleted}`. Tombstones account + actor(s), revokes sessions/tokens, emits `account_delete` + per-actor `actor_delete`. Refuses a keeper-role target (`ERROR_CANNOT_DELETE_KEEPER`) or the sole active admin (`ERROR_CANNOT_DELETE_LAST_ADMIN`) — both fail-loud with a failure-audit row.
|
|
611
|
+
- `account_delete_action_spec` — mutation (soft delete); self-or-admin (`{account, actor}`, handler elevates to admin when `account_id` ≠ self); the self path is session-only, handler-enforced ahead of the target guards (an API or daemon token gets the dispatcher's `ERROR_CREDENTIAL_TYPE_REQUIRED` 403 via `credential_type_required_error`), while an admin deleting another account keeps any credential; input `{account_id?}`; output `{ok, deleted}`. Tombstones account + actor(s), revokes sessions/tokens, emits `account_delete` + per-actor `actor_delete`. Refuses a keeper-role target (`ERROR_CANNOT_DELETE_KEEPER`) or the sole active admin (`ERROR_CANNOT_DELETE_LAST_ADMIN`) — both fail-loud with a failure-audit row.
|
|
592
612
|
- `account_purge_action_spec` — mutation (hard purge); keeper-only (`credential_types: ['daemon_token']` + `roles: ['keeper']`) + `confirm: true` + WARN; input `{account_id, confirm?}`; output `{ok, purged}`. Cascading delete; emits `account_purge` + per-actor `actor_purge` (identity snapshot survives in metadata since `audit_log` ids carry no FK). Refuses a keeper-role target (`ERROR_CANNOT_DELETE_KEEPER`) or the sole active admin (`ERROR_CANNOT_DELETE_LAST_ADMIN`).
|
|
593
613
|
- `account_undelete_action_spec` — mutation (reactivation, inverse of soft delete); admin-only (`roles: ['admin']` — no self path, a tombstoned account can't authenticate); input `{account_id}`; output `{ok, undeleted}`. Clears the `deleted_at` tombstone on the account + its actor(s), emits `account_undelete` + per-actor `actor_undelete`. Does not restore revoked sessions/tokens.
|
|
594
614
|
- `admin_session_list_action_spec` — read; input `{acting?}` (`.default({})`); output `{sessions}`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;
|
|
1
|
+
{"version":3,"file":"account_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAwB9F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAyB3D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,yBAAyB,EAC/B,UAAS,oBAAyB,KAChC,KAAK,CAAC,SAAS,CAsLjB,CAAC"}
|
|
@@ -27,12 +27,14 @@
|
|
|
27
27
|
*
|
|
28
28
|
* @module
|
|
29
29
|
*/
|
|
30
|
+
import { to_error_message } from '@fuzdev/fuz_util/error.ts';
|
|
30
31
|
import { rpc_action } from '../actions/action_rpc.js';
|
|
32
|
+
import { jsonrpc_errors } from '../http/jsonrpc_errors.js';
|
|
31
33
|
import { queue_connection_close } from '../actions/connection_closer.js';
|
|
32
34
|
import { to_session_account } from './account_schema.js';
|
|
33
35
|
import { query_session_list_for_account, query_session_revoke_for_account, query_session_revoke_all_for_account } from './session_queries.js';
|
|
34
36
|
import { query_api_token_enforce_limit, query_api_token_list_for_account, query_create_api_token, query_revoke_api_token_for_account } from './api_token_queries.js';
|
|
35
|
-
import { parse_stored_token_scope, token_scope_from_input, token_scope_label } from './token_scope.js';
|
|
37
|
+
import { parse_stored_token_scope, serialize_token_scope, token_scope_from_input, token_scope_label } from './token_scope.js';
|
|
36
38
|
import { token_lifetime_to_expires_at } from './token_lifetime.js';
|
|
37
39
|
import { generate_api_token } from './api_token.js';
|
|
38
40
|
import { DEFAULT_MAX_TOKENS } from './account_route_schema.js';
|
|
@@ -108,6 +110,15 @@ export const create_account_actions = (deps, options = {}) => {
|
|
|
108
110
|
// There is deliberately no permissive fallback here: an omitted scope is
|
|
109
111
|
// a validation error upstream, not a full-authority token.
|
|
110
112
|
const scope = token_scope_from_input(input.scope);
|
|
113
|
+
// Over the stored-document cap is a malformed request, refused before
|
|
114
|
+
// any write (the insert would otherwise throw it as a 500). Twin of the
|
|
115
|
+
// Rust spine's `invalid_params` on `TokenScopeError::TooLarge`.
|
|
116
|
+
try {
|
|
117
|
+
serialize_token_scope(scope);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
throw jsonrpc_errors.invalid_params(`invalid scope: ${to_error_message(err)}`);
|
|
121
|
+
}
|
|
111
122
|
// `input.lifetime` is required for the same reason — an omitted lifetime
|
|
112
123
|
// is a validation error, never an eternal token.
|
|
113
124
|
const expires_at = token_lifetime_to_expires_at(input.lifetime);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_route_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_route_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAQvD,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAC3C,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;kBAI9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,4EAA4E;AAC5E,eAAO,MAAM,iCAAiC;;;iBAG5C,CAAC;AACH,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAElG,oFAAoF;AACpF,eAAO,MAAM,UAAU;;;kBAGrB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD,6EAA6E;AAC7E,eAAO,MAAM,WAAW;;kBAEtB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,2EAA2E;AAC3E,eAAO,MAAM,WAAW,WAAW,CAAC;AACpC,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,wFAAwF;AACxF,eAAO,MAAM,YAAY;;;kBAGvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD,sHAAsH;AACtH,eAAO,MAAM,mBAAmB;;;kBAG9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,uGAAuG;AACvG,eAAO,MAAM,oBAAoB;;;;kBAI/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,8CAA8C;AAC9C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAaD,CAAC;AAEvC,8EAA8E;AAC9E,MAAM,WAAW,wBAAwB;IACxC,8FAA8F;IAC9F,0BAA0B,EAAE,OAAO,CAAC;CACpC;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,GACvC,SAAS,wBAAwB,KAC/B,CACF,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAC1B,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAC1B,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAC1B,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"account_route_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_route_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAQvD,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAC3C,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;kBAI9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,4EAA4E;AAC5E,eAAO,MAAM,iCAAiC;;;iBAG5C,CAAC;AACH,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAElG,oFAAoF;AACpF,eAAO,MAAM,UAAU;;;kBAGrB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD,6EAA6E;AAC7E,eAAO,MAAM,WAAW;;kBAEtB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,2EAA2E;AAC3E,eAAO,MAAM,WAAW,WAAW,CAAC;AACpC,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,wFAAwF;AACxF,eAAO,MAAM,YAAY;;;kBAGvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD,sHAAsH;AACtH,eAAO,MAAM,mBAAmB;;;kBAG9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,uGAAuG;AACvG,eAAO,MAAM,oBAAoB;;;;kBAI/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,8CAA8C;AAC9C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAaD,CAAC;AAEvC,8EAA8E;AAC9E,MAAM,WAAW,wBAAwB;IACxC,8FAA8F;IAC9F,0BAA0B,EAAE,OAAO,CAAC;CACpC;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,GACvC,SAAS,wBAAwB,KAC/B,CACF,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAC1B,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAC1B,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAC1B,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CA6D1B,CAAC"}
|
|
@@ -123,6 +123,10 @@ export const create_account_route_shapes = (options) => [
|
|
|
123
123
|
input: LoginInput,
|
|
124
124
|
output: LoginOutput,
|
|
125
125
|
rate_limit: 'both',
|
|
126
|
+
// The handler opens its own transaction around just the session writes,
|
|
127
|
+
// so a reservation waiting for a slot, and the Argon2 verify, hold no
|
|
128
|
+
// database connection.
|
|
129
|
+
transaction: false,
|
|
126
130
|
errors: {
|
|
127
131
|
400: z.looseObject({
|
|
128
132
|
error: z.enum([ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY])
|
|
@@ -151,6 +155,10 @@ export const create_account_route_shapes = (options) => [
|
|
|
151
155
|
input: PasswordChangeInput,
|
|
152
156
|
output: PasswordChangeOutput,
|
|
153
157
|
rate_limit: options.login_account_rate_limited ? 'both' : 'ip',
|
|
158
|
+
// The handler opens its own transaction around just the password update
|
|
159
|
+
// and the revocations, so a reservation waiting for a slot, and the
|
|
160
|
+
// Argon2 verify and hash, hold no database connection.
|
|
161
|
+
transaction: false,
|
|
154
162
|
errors: {
|
|
155
163
|
400: z.looseObject({
|
|
156
164
|
error: z.enum([ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY])
|
|
@@ -134,8 +134,13 @@ export interface AccountRouteOptions extends AuthSessionRouteOptions {
|
|
|
134
134
|
* Self-service session/token management is on `auth/account_actions.ts`.
|
|
135
135
|
*
|
|
136
136
|
* `/login` closes the connections of the sessions its cap evicts, and
|
|
137
|
-
* `/logout` and `/password` close the account's, each
|
|
138
|
-
*
|
|
137
|
+
* `/logout` and `/password` close the account's, each once its revocation has
|
|
138
|
+
* committed: `/logout` through the route transaction's post-commit queue
|
|
139
|
+
* (`queue_connection_close`), `/login` and `/password` — which open their own
|
|
140
|
+
* transaction around just their writes — straight after it commits
|
|
141
|
+
* (`close_connections_after_commit`, which logs a failing close rather than
|
|
142
|
+
* failing the committed request), so a later throw can't drop a close a
|
|
143
|
+
* committed revocation owes. All on `deps.connection_closer`.
|
|
139
144
|
*
|
|
140
145
|
* @param deps - stateless capabilities (keyring, password, log, audit, connection_closer)
|
|
141
146
|
* @param options - per-factory configuration (session_options, login_ip_rate_limiter, login_account_rate_limiter, bootstrap_status)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA4B1D,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"account_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA4B1D,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIxE,OAAO,EAGN,KAAK,WAAW,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAOlD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gCAAgC,GAAI,UAAU,oBAAoB,KAAG,SAkFhF,CAAC;AAEH,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACpC,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAQ/C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,uBAAuB;IACvC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,uBAAuB;IACnE;;;;;;;OAOG;IACH,qBAAqB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1C,4FAA4F;IAC5F,0BAA0B,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,2FAA2F;IAC3F,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C;AAID;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,0BAA0B,GACtC,MAAM,gBAAgB,EACtB,SAAS,mBAAmB,KAC1B,KAAK,CAAC,SAAS,CA+VjB,CAAC"}
|