@fuzdev/fuz_app 0.67.1 → 0.69.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/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +10 -3
- package/dist/auth/CLAUDE.md +99 -5
- package/dist/auth/account_queries.d.ts +87 -4
- package/dist/auth/account_queries.d.ts.map +1 -1
- package/dist/auth/account_queries.js +107 -17
- package/dist/auth/account_schema.d.ts +19 -0
- package/dist/auth/account_schema.d.ts.map +1 -1
- package/dist/auth/account_schema.js +8 -0
- package/dist/auth/admin_action_specs.d.ts +170 -3
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +148 -4
- package/dist/auth/admin_actions.d.ts +4 -14
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +246 -40
- package/dist/auth/audit_log_ddl.d.ts +10 -1
- package/dist/auth/audit_log_ddl.d.ts.map +1 -1
- package/dist/auth/audit_log_ddl.js +13 -4
- package/dist/auth/audit_log_schema.d.ts +34 -1
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +73 -0
- package/dist/auth/auth_ddl.d.ts +2 -2
- package/dist/auth/auth_ddl.d.ts.map +1 -1
- package/dist/auth/auth_ddl.js +10 -2
- package/dist/auth/cell_action_specs.d.ts +1295 -0
- package/dist/auth/cell_action_specs.d.ts.map +1 -0
- package/dist/auth/cell_action_specs.js +397 -0
- package/dist/auth/cell_actions.d.ts +63 -0
- package/dist/auth/cell_actions.d.ts.map +1 -0
- package/dist/auth/cell_actions.js +546 -0
- package/dist/auth/cell_audit_action_specs.d.ts +131 -0
- package/dist/auth/cell_audit_action_specs.d.ts.map +1 -0
- package/dist/auth/cell_audit_action_specs.js +70 -0
- package/dist/auth/cell_audit_actions.d.ts +18 -0
- package/dist/auth/cell_audit_actions.d.ts.map +1 -0
- package/dist/auth/cell_audit_actions.js +59 -0
- package/dist/auth/cell_audit_events.d.ts +28 -0
- package/dist/auth/cell_audit_events.d.ts.map +1 -0
- package/dist/auth/cell_audit_events.js +42 -0
- package/dist/auth/cell_audit_metadata.d.ts +48 -0
- package/dist/auth/cell_audit_metadata.d.ts.map +1 -0
- package/dist/auth/cell_audit_metadata.js +46 -0
- package/dist/auth/cell_authorize.d.ts +88 -0
- package/dist/auth/cell_authorize.d.ts.map +1 -0
- package/dist/auth/cell_authorize.js +172 -0
- package/dist/auth/cell_data_schema.d.ts +44 -0
- package/dist/auth/cell_data_schema.d.ts.map +1 -0
- package/dist/auth/cell_data_schema.js +42 -0
- package/dist/auth/cell_field_action_specs.d.ts +244 -0
- package/dist/auth/cell_field_action_specs.d.ts.map +1 -0
- package/dist/auth/cell_field_action_specs.js +136 -0
- package/dist/auth/cell_field_actions.d.ts +34 -0
- package/dist/auth/cell_field_actions.d.ts.map +1 -0
- package/dist/auth/cell_field_actions.js +153 -0
- package/dist/auth/cell_field_audit_metadata.d.ts +30 -0
- package/dist/auth/cell_field_audit_metadata.d.ts.map +1 -0
- package/dist/auth/cell_field_audit_metadata.js +28 -0
- package/dist/auth/cell_grant_action_specs.d.ts +333 -0
- package/dist/auth/cell_grant_action_specs.d.ts.map +1 -0
- package/dist/auth/cell_grant_action_specs.js +148 -0
- package/dist/auth/cell_grant_actions.d.ts +50 -0
- package/dist/auth/cell_grant_actions.d.ts.map +1 -0
- package/dist/auth/cell_grant_actions.js +208 -0
- package/dist/auth/cell_grant_audit_metadata.d.ts +75 -0
- package/dist/auth/cell_grant_audit_metadata.d.ts.map +1 -0
- package/dist/auth/cell_grant_audit_metadata.js +54 -0
- package/dist/auth/cell_item_action_specs.d.ts +331 -0
- package/dist/auth/cell_item_action_specs.d.ts.map +1 -0
- package/dist/auth/cell_item_action_specs.js +182 -0
- package/dist/auth/cell_item_actions.d.ts +37 -0
- package/dist/auth/cell_item_actions.d.ts.map +1 -0
- package/dist/auth/cell_item_actions.js +204 -0
- package/dist/auth/cell_item_audit_metadata.d.ts +35 -0
- package/dist/auth/cell_item_audit_metadata.d.ts.map +1 -0
- package/dist/auth/cell_item_audit_metadata.js +32 -0
- package/dist/auth/cell_relation_visibility.d.ts +32 -0
- package/dist/auth/cell_relation_visibility.d.ts.map +1 -0
- package/dist/auth/cell_relation_visibility.js +57 -0
- package/dist/auth/deps.d.ts +9 -0
- package/dist/auth/deps.d.ts.map +1 -1
- package/dist/auth/role_grant_queries.d.ts +30 -0
- package/dist/auth/role_grant_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_queries.js +54 -0
- package/dist/auth/signup_routes.d.ts +0 -3
- package/dist/auth/signup_routes.d.ts.map +1 -1
- package/dist/auth/signup_routes.js +9 -3
- package/dist/auth/standard_rpc_actions.d.ts +5 -5
- package/dist/auth/standard_rpc_actions.js +4 -4
- package/dist/db/CLAUDE.md +118 -0
- package/dist/db/cell_audit_queries.d.ts +26 -0
- package/dist/db/cell_audit_queries.d.ts.map +1 -0
- package/dist/db/cell_audit_queries.js +53 -0
- package/dist/db/cell_ddl.d.ts +151 -0
- package/dist/db/cell_ddl.d.ts.map +1 -0
- package/dist/db/cell_ddl.js +247 -0
- package/dist/db/cell_field_queries.d.ts +105 -0
- package/dist/db/cell_field_queries.d.ts.map +1 -0
- package/dist/db/cell_field_queries.js +113 -0
- package/dist/db/cell_grant_queries.d.ts +132 -0
- package/dist/db/cell_grant_queries.d.ts.map +1 -0
- package/dist/db/cell_grant_queries.js +145 -0
- package/dist/db/cell_history_ddl.d.ts +38 -0
- package/dist/db/cell_history_ddl.d.ts.map +1 -0
- package/dist/db/cell_history_ddl.js +61 -0
- package/dist/db/cell_item_queries.d.ts +107 -0
- package/dist/db/cell_item_queries.d.ts.map +1 -0
- package/dist/db/cell_item_queries.js +119 -0
- package/dist/db/cell_queries.d.ts +327 -0
- package/dist/db/cell_queries.d.ts.map +1 -0
- package/dist/db/cell_queries.js +431 -0
- package/dist/db/fact_ddl.d.ts +38 -0
- package/dist/db/fact_ddl.d.ts.map +1 -0
- package/dist/db/fact_ddl.js +71 -0
- package/dist/db/fact_queries.d.ts +140 -0
- package/dist/db/fact_queries.d.ts.map +1 -0
- package/dist/db/fact_queries.js +161 -0
- package/dist/db/fact_store.d.ts +112 -0
- package/dist/db/fact_store.d.ts.map +1 -0
- package/dist/db/fact_store.js +225 -0
- package/dist/server/app_server.d.ts +1 -7
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +1 -5
- package/dist/server/env.d.ts +2 -0
- package/dist/server/env.d.ts.map +1 -1
- package/dist/server/env.js +6 -0
- package/dist/server/fact_write.d.ts +32 -0
- package/dist/server/fact_write.d.ts.map +1 -0
- package/dist/server/fact_write.js +56 -0
- package/dist/server/file_fact_fetcher.d.ts +42 -0
- package/dist/server/file_fact_fetcher.d.ts.map +1 -0
- package/dist/server/file_fact_fetcher.js +60 -0
- package/dist/server/file_fact_url.d.ts +53 -0
- package/dist/server/file_fact_url.d.ts.map +1 -0
- package/dist/server/file_fact_url.js +52 -0
- package/dist/server/serve_fact_route.d.ts +78 -0
- package/dist/server/serve_fact_route.d.ts.map +1 -0
- package/dist/server/serve_fact_route.js +205 -0
- package/dist/testing/CLAUDE.md +142 -6
- package/dist/testing/app_server.d.ts +46 -0
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +67 -8
- package/dist/testing/audit_completeness.d.ts.map +1 -1
- package/dist/testing/audit_completeness.js +67 -1
- package/dist/testing/cross_backend/account_lifecycle.d.ts +10 -0
- package/dist/testing/cross_backend/account_lifecycle.d.ts.map +1 -0
- package/dist/testing/cross_backend/account_lifecycle.js +144 -0
- package/dist/testing/cross_backend/actor_lookup.d.ts +10 -0
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -0
- package/dist/testing/cross_backend/actor_lookup.js +83 -0
- package/dist/testing/cross_backend/actor_search.d.ts +6 -0
- package/dist/testing/cross_backend/actor_search.d.ts.map +1 -0
- package/dist/testing/cross_backend/actor_search.js +92 -0
- package/dist/testing/cross_backend/app_settings.d.ts +6 -0
- package/dist/testing/cross_backend/app_settings.d.ts.map +1 -0
- package/dist/testing/cross_backend/app_settings.js +95 -0
- package/dist/testing/cross_backend/backend_config.d.ts +1 -1
- package/dist/testing/cross_backend/capabilities.d.ts +29 -7
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +3 -1
- package/dist/testing/cross_backend/cell_cross_helpers.d.ts +39 -0
- package/dist/testing/cross_backend/cell_cross_helpers.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_cross_helpers.js +45 -0
- package/dist/testing/cross_backend/cell_crud.d.ts +4 -0
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_crud.js +168 -0
- package/dist/testing/cross_backend/cell_grant_role.d.ts +8 -0
- package/dist/testing/cross_backend/cell_grant_role.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_grant_role.js +102 -0
- package/dist/testing/cross_backend/cell_relations.d.ts +4 -0
- package/dist/testing/cross_backend/cell_relations.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_relations.js +229 -0
- package/dist/testing/cross_backend/conformance_case.d.ts +144 -0
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -0
- package/dist/testing/cross_backend/conformance_case.js +132 -0
- package/dist/testing/cross_backend/conformance_table.d.ts +46 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -0
- package/dist/testing/cross_backend/conformance_table.js +199 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +6 -2
- package/dist/testing/cross_backend/default_spine_surface.d.ts +17 -9
- package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_spine_surface.js +20 -12
- package/dist/testing/cross_backend/origin.d.ts +10 -0
- package/dist/testing/cross_backend/origin.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin.js +73 -0
- package/dist/testing/cross_backend/setup.d.ts +22 -40
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +39 -5
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +90 -2
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +91 -3
- package/dist/testing/cross_backend/xfail.d.ts +15 -0
- package/dist/testing/cross_backend/xfail.d.ts.map +1 -0
- package/dist/testing/cross_backend/xfail.js +37 -0
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +4 -0
- package/dist/testing/integration.d.ts +2 -3
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +20 -85
- package/dist/testing/rate_limiting.d.ts +1 -1
- package/dist/testing/rpc_helpers.d.ts +3 -3
- package/dist/testing/sse_round_trip.d.ts +1 -1
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +0 -1
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +4 -0
- package/dist/ui/AdminAccounts.svelte +84 -35
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
- package/dist/ui/AdminSessions.svelte +21 -23
- package/dist/ui/AdminSessions.svelte.d.ts.map +1 -1
- package/dist/ui/CLAUDE.md +17 -26
- package/dist/ui/OpenSignupToggle.svelte +2 -5
- package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.d.ts +9 -10
- package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/account_sessions_state.svelte.js +7 -17
- package/dist/ui/admin_accounts_state.svelte.d.ts +41 -20
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +52 -22
- package/dist/ui/admin_invites_state.svelte.d.ts +8 -11
- package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_invites_state.svelte.js +7 -16
- package/dist/ui/admin_rpc_adapters.d.ts +6 -2
- package/dist/ui/admin_rpc_adapters.d.ts.map +1 -1
- package/dist/ui/admin_rpc_adapters.js +5 -1
- package/dist/ui/admin_sessions_state.svelte.d.ts +6 -10
- package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_sessions_state.svelte.js +4 -14
- package/dist/ui/app_settings_state.svelte.d.ts +8 -12
- package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
- package/dist/ui/app_settings_state.svelte.js +6 -16
- package/dist/ui/audit_log_state.svelte.d.ts +9 -8
- package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
- package/dist/ui/audit_log_state.svelte.js +8 -20
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perform_action.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/perform_action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,KAAK,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAEpC,OAAO,EAEN,KAAK,gBAAgB,EAErB,KAAK,kBAAkB,EACvB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"perform_action.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/actions/perform_action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,KAAK,cAAc,EAAC,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAEpC,OAAO,EAEN,KAAK,gBAAgB,EAErB,KAAK,kBAAkB,EACvB,MAAM,oBAAoB,CAAC;AAY5B,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAEpD,OAAO,KAAK,EAA+B,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE7E;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAClC,kEAAkE;IAClE,MAAM,EAAE,SAAS,CAAC;IAClB,mGAAmG;IACnG,UAAU,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,UAAU,EAAE,gBAAgB,CAAC;IAC7B,yDAAyD;IACzD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,uEAAuE;IACvE,eAAe,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,oGAAoG;IACpG,MAAM,EAAE,WAAW,CAAC;IACpB,sFAAsF;IACtF,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,uDAAuD;IACvD,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAC,eAAe,EAAE,cAAc,GAAG,IAAI,CAAA;KAAC,CAAC;CAClD;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IACjC,gGAAgG;IAChG,EAAE,EAAE,EAAE,CAAC;IACP;;;OAGG;IACH,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC;;;OAGG;IACH,mBAAmB,EAAE,KAAK,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,uEAAuE;IACvE,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;CAChD;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAC5B;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC,GAC7B;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AAE9D;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,GAC1B,OAAO,kBAAkB,EACzB,MAAM,iBAAiB,KACrB,OAAO,CAAC,mBAAmB,CAwJ7B,CAAC;AAoFF;;;GAGG;AACH,eAAO,MAAM,iCAAiC,GAC7C,IAAI,gBAAgB,EACpB,QAAQ,mBAAmB,KACzB;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,gBAAgB,CAAA;CAAC,GAAG,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC,GAAG;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAC,CAK5F,CAAC"}
|
|
@@ -43,7 +43,7 @@ import {} from '../hono_context.js';
|
|
|
43
43
|
import { is_void_schema } from '../http/schema_helpers.js';
|
|
44
44
|
import { JSONRPC_VERSION, } from '../http/jsonrpc.js';
|
|
45
45
|
import { jsonrpc_error_messages, jsonrpc_error_code_to_http_status, http_status_to_jsonrpc_error_code, JSONRPC_ERROR_CODES, } from '../http/jsonrpc_errors.js';
|
|
46
|
-
import { ERROR_INSUFFICIENT_PERMISSIONS, ERROR_CREDENTIAL_TYPE_REQUIRED, } from '../http/error_schemas.js';
|
|
46
|
+
import { ERROR_AUTHENTICATION_REQUIRED, ERROR_INSUFFICIENT_PERMISSIONS, ERROR_CREDENTIAL_TYPE_REQUIRED, } from '../http/error_schemas.js';
|
|
47
47
|
import { is_public_auth } from '../http/auth_shape.js';
|
|
48
48
|
/**
|
|
49
49
|
* The shared dispatch core. Pure data — no Hono context, no socket. Each
|
|
@@ -208,8 +208,15 @@ const rate_limited_result = (retry_after) => {
|
|
|
208
208
|
*/
|
|
209
209
|
const check_action_auth_pre_validation = (auth, account_id) => {
|
|
210
210
|
if (auth.account === 'required' || auth.actor === 'required') {
|
|
211
|
-
if (account_id == null)
|
|
212
|
-
|
|
211
|
+
if (account_id == null) {
|
|
212
|
+
// Carry the reason on `error.data.reason` (symmetric with the 403
|
|
213
|
+
// credential / role gates) so a 401 can be asserted on reason, not
|
|
214
|
+
// just status. The reason is generic — it leaks nothing about
|
|
215
|
+
// whether a credential was present or what the route demanded.
|
|
216
|
+
return jsonrpc_error_messages.unauthenticated('unauthenticated', {
|
|
217
|
+
reason: ERROR_AUTHENTICATION_REQUIRED,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
213
220
|
}
|
|
214
221
|
return null;
|
|
215
222
|
};
|
package/dist/auth/CLAUDE.md
CHANGED
|
@@ -62,7 +62,7 @@ Convention — `*_schema.ts` is Zod-only; `*_ddl.ts` holds DDL strings.
|
|
|
62
62
|
- `auth/credential_type_schema.ts` — `CredentialTypeName`, `CREDENTIAL_TYPE_SESSION` / `_API_TOKEN` / `_DAEMON_TOKEN`, `create_credential_type_schema`.
|
|
63
63
|
- `auth/grant_path_schema.ts` — `GrantPathName`, `GRANT_PATH_ADMIN` / `_SELF_SERVICE` / `_SYSTEM` / `_BOOTSTRAP`, `create_grant_path_schema`.
|
|
64
64
|
- `auth/auth_ddl.ts` — `CREATE TABLE` / index / seed strings for the core identity tables.
|
|
65
|
-
- `auth/audit_log_schema.ts` — `AUDIT_EVENT_TYPES` (
|
|
65
|
+
- `auth/audit_log_schema.ts` — `AUDIT_EVENT_TYPES` (27 builtins), `AuditEventType` / `AuditEventTypeName`, `audit_metadata_schemas`, `AuditLogEvent`, `AuditLogInput`, `AuditLogConfig`, `create_audit_log_config`.
|
|
66
66
|
- `auth/audit_log_ddl.ts` — `audit_log` table DDL with `seq BIGSERIAL` for cursor-based gap fill (BIGSERIAL converges with the Rust spine; `create_db` registers a `pg.types` int8 parser so `seq` still reads as a JS number).
|
|
67
67
|
- `auth/invite_schema.ts` — `Invite`, `CreateInviteInput`.
|
|
68
68
|
- `auth/app_settings_schema.ts` — `AppSettings`, `UpdateAppSettingsInput` (single-row via `CHECK (id = 1)`).
|
|
@@ -148,6 +148,68 @@ See root ../../../CLAUDE.md §Middleware Ordering for canonical assembly
|
|
|
148
148
|
order. The auth-specific invariants are described below in §Cross-cutting
|
|
149
149
|
invariants.
|
|
150
150
|
|
|
151
|
+
### Cell layer
|
|
152
|
+
|
|
153
|
+
The cell content primitive's wire schemas, RPC handlers, and authz live
|
|
154
|
+
here; the schema + queries live in `db/` (see `db/CLAUDE.md` §Cell layer).
|
|
155
|
+
Generic-only — no app vocabulary on the wire; per-kind shape is the
|
|
156
|
+
consumer's `validate_data` pass-through callback on `CellActionDeps`.
|
|
157
|
+
|
|
158
|
+
- `auth/cell_data_schema.ts` — `CellData` base (`z.looseObject` with
|
|
159
|
+
optional `kind` / `label` / `summary`); per-kind sub-API extends it.
|
|
160
|
+
- `auth/cell_action_specs.ts` — `CellVisibility` enum, `CellPath` brand,
|
|
161
|
+
`CellJson`, the six generic verb specs (`cell_create / get / update /
|
|
162
|
+
delete / list / clone`), error reasons, and `all_cell_action_specs`
|
|
163
|
+
(spreads in the grant / field / item / audit registries so codegen + UI
|
|
164
|
+
see one cell namespace). `CellJson` has no hub axis; `path` is global.
|
|
165
|
+
- `auth/cell_grant_action_specs.ts` / `cell_field_action_specs.ts` /
|
|
166
|
+
`cell_item_action_specs.ts` / `cell_audit_action_specs.ts` — the
|
|
167
|
+
`cell_grant_*` (3) / `cell_field_*` (3) / `cell_item_*` (4) /
|
|
168
|
+
`cell_audit_list` (1) specs + their wire JSON shapes.
|
|
169
|
+
- `auth/cell_authorize.ts` — pure predicates over
|
|
170
|
+
`(RequestContext | null, CellRow, grants)`: `can_view_cell`,
|
|
171
|
+
`can_edit_cell`, and `can_manage_cell` (= admin ‖ owner, where owner is
|
|
172
|
+
the `cell.created_by` actor field). The manage tier gates visibility
|
|
173
|
+
writes, all grant management (`cell_grant_create` / `_list` /
|
|
174
|
+
`_revoke`), and the per-cell audit timeline (`cell_audit_list`, D14 —
|
|
175
|
+
it surfaces who-touched-the-cell); it is not a grant level and not
|
|
176
|
+
delegable. Editor-grant holders edit content + relations but cannot
|
|
177
|
+
manage grants or read the audit timeline. NULL
|
|
178
|
+
`created_by` (system origin) is admin-only for edit/manage (explicit
|
|
179
|
+
defense-in-depth).
|
|
180
|
+
- `auth/cell_relation_visibility.ts` — `filter_visible_target_ids(deps,
|
|
181
|
+
auth, ids)`: batched strict relation-read filter. Every relation read —
|
|
182
|
+
the `cell_get` bundle, **forward and reverse** `cell_field_list` /
|
|
183
|
+
`cell_item_list`, and the deep-clone walk (children bulk-loaded via
|
|
184
|
+
`query_cell_load_many`) — drops edges whose far endpoint the caller can't
|
|
185
|
+
view, so a viewer of a parent can't enumerate private linked cells by id.
|
|
186
|
+
Two queries for the whole id-set (avoids the N+1 of a per-row check). The
|
|
187
|
+
reverse list verbs additionally cap the fetch by the wire `limit` so a
|
|
188
|
+
heavily inbound-linked target can't force an unbounded scan.
|
|
189
|
+
- `auth/cell_actions.ts` — `create_cell_actions(deps)`, the six generic
|
|
190
|
+
handlers. `cell_create` stamps `created_by`; `path` writes are
|
|
191
|
+
admin-only. `cell_update` gates `visibility` writes on `can_manage_cell`
|
|
192
|
+
(`ERROR_CELL_VISIBILITY_MANAGE_ONLY`). `cell_get` bundles
|
|
193
|
+
visibility-filtered `fields` + `items` (one over the cap for truncation
|
|
194
|
+
detection). `cell_clone` deep-walks viewable children only.
|
|
195
|
+
- `auth/cell_grant_actions.ts` / `cell_field_actions.ts` /
|
|
196
|
+
`cell_item_actions.ts` / `cell_audit_actions.ts` — the relation + ACL +
|
|
197
|
+
audit handlers, exporting `to_grant_json` / `to_field_json` /
|
|
198
|
+
`to_item_json` reused by the `cell_get` bundle.
|
|
199
|
+
- `auth/cell_audit_metadata.ts` + `cell_grant_audit_metadata.ts` +
|
|
200
|
+
`cell_field_audit_metadata.ts` + `cell_item_audit_metadata.ts` — audit
|
|
201
|
+
metadata envelopes (IDs only), registered via `extra_events:` on the
|
|
202
|
+
consumer's `create_audit_log_config`.
|
|
203
|
+
- `auth/cell_audit_events.ts` — `cell_audit_events`, the canonical
|
|
204
|
+
`event_type → metadata` map bundling every cell-domain audit event.
|
|
205
|
+
Consumers spread it into `extra_events` to register the whole layer in
|
|
206
|
+
one call (aggregator by design, not a compat shim).
|
|
207
|
+
|
|
208
|
+
The cell event types (`cell_create` / `_update` / `_delete` / `_clone`,
|
|
209
|
+
`cell_grant_create` / `_revoke`, `cell_field_set` / `_delete`,
|
|
210
|
+
`cell_item_insert` / `_move` / `_delete`) are consumer-registered extras,
|
|
211
|
+
not built-ins — see §Audit event extensibility.
|
|
212
|
+
|
|
151
213
|
## Cross-cutting invariants
|
|
152
214
|
|
|
153
215
|
The things that span multiple files and don't fit on any one symbol's TSDoc.
|
|
@@ -259,9 +321,21 @@ session_revoke_all role_grant_offer_expire
|
|
|
259
321
|
token_create role_grant_offer_supersede
|
|
260
322
|
token_revoke invite_create
|
|
261
323
|
token_revoke_all invite_delete
|
|
262
|
-
|
|
324
|
+
account_delete app_settings_update
|
|
325
|
+
account_purge
|
|
326
|
+
account_undelete
|
|
327
|
+
actor_delete
|
|
328
|
+
actor_purge
|
|
329
|
+
actor_undelete
|
|
263
330
|
```
|
|
264
331
|
|
|
332
|
+
`account_delete` / `account_purge` / `account_undelete` snapshot
|
|
333
|
+
`{username, email}` into metadata; `actor_delete` / `actor_purge` /
|
|
334
|
+
`actor_undelete` snapshot `{name}`. The account-level handlers emit the
|
|
335
|
+
account event plus one per-actor event (`delete` = soft, `purge` = hard,
|
|
336
|
+
`undelete` = reactivation — see ../../../docs/security.md §Authorization,
|
|
337
|
+
"Account-removal target guards").
|
|
338
|
+
|
|
265
339
|
`role_grant_offer_supersede` carries
|
|
266
340
|
`reason: 'sibling_accepted' | 'role_grant_revoked' | 'scope_destroyed'`
|
|
267
341
|
plus `cause_id` pointing to the row that triggered the supersede.
|
|
@@ -336,11 +410,23 @@ are excluded.
|
|
|
336
410
|
records, regardless of outcome. Default
|
|
337
411
|
`default_action_account_rate_limit` is 1200/15min per actor.
|
|
338
412
|
|
|
339
|
-
### Admin actions —
|
|
413
|
+
### Admin actions — fourteen specs
|
|
340
414
|
|
|
341
415
|
`create_admin_actions(deps, options?)` in `auth/admin_actions.ts`.
|
|
342
416
|
|
|
343
|
-
|
|
417
|
+
Three of these — `account_delete` / `account_purge` / `account_undelete` —
|
|
418
|
+
carry `account_*` method names (not `admin_`): privilege lives in the auth
|
|
419
|
+
spec, not the name, so soft-delete stays self-service-capable. They sit in
|
|
420
|
+
the admin factory because their `actor: 'required'` shape + account-management
|
|
421
|
+
queries match the rest of this registry (mixed-auth in one factory is
|
|
422
|
+
fine — same as `role_grant_revoke`). `account_undelete` is admin-only —
|
|
423
|
+
reactivation has no self path because a soft-deleted account can't
|
|
424
|
+
authenticate.
|
|
425
|
+
|
|
426
|
+
- `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.
|
|
427
|
+
- `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.
|
|
428
|
+
- `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`).
|
|
429
|
+
- `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.
|
|
344
430
|
- `admin_session_list_action_spec` — read; input `z.void()`; output `{sessions}`.
|
|
345
431
|
- `admin_session_revoke_all_action_spec` — mutation; input `{account_id}`; output `{ok, count}`.
|
|
346
432
|
- `admin_token_revoke_all_action_spec` — mutation; input `{account_id}`; output `{ok, count}`.
|
|
@@ -356,7 +442,15 @@ Constants: `AUDIT_LOG_LIST_LIMIT_MAX = 200`, `ADMIN_ACCOUNT_LIST_DEFAULT_LIMIT =
|
|
|
356
442
|
`ADMIN_ACCOUNT_LIST_LIMIT_MAX = 200`.
|
|
357
443
|
|
|
358
444
|
Error reasons via `error.data.reason`: `ERROR_ACCOUNT_NOT_FOUND` (404 via
|
|
359
|
-
`jsonrpc_errors.not_found`) on admin revoke-all
|
|
445
|
+
`jsonrpc_errors.not_found`) on admin revoke-all + account delete/purge,
|
|
446
|
+
`ERROR_INSUFFICIENT_PERMISSIONS` (403) when `account_delete` targets another
|
|
447
|
+
account without admin, `ERROR_PURGE_NOT_CONFIRMED` (400) when `account_purge`
|
|
448
|
+
omits `confirm: true`, `ERROR_CANNOT_DELETE_KEEPER` (403) when `account_delete` /
|
|
449
|
+
`account_purge` targets a keeper-role account (the keeper account is never
|
|
450
|
+
API-removable — auth + daemon-token both pivot on it),
|
|
451
|
+
`ERROR_CANNOT_DELETE_LAST_ADMIN` (403) when `account_delete` / `account_purge`
|
|
452
|
+
targets the sole remaining active admin (keeper-recoverable, but not in one
|
|
453
|
+
click; soft-deleted admins don't count), `ERROR_INVITE_ACCOUNT_EXISTS_USERNAME` /
|
|
360
454
|
`_EMAIL` / `ERROR_INVITE_DUPLICATE` on invite create, `ERROR_INVITE_NOT_FOUND`
|
|
361
455
|
on invite delete. `invite_create` empty input is rejected at the schema via
|
|
362
456
|
`.refine()` and surfaces as `invalid_params` with `error.data.issues`.
|
|
@@ -18,7 +18,13 @@ import { type Account, type Actor, type CreateAccountInput, type AdminAccountEnt
|
|
|
18
18
|
*/
|
|
19
19
|
export declare const query_create_account: (deps: QueryDeps, input: CreateAccountInput) => Promise<Account>;
|
|
20
20
|
/**
|
|
21
|
-
* Find an account by id.
|
|
21
|
+
* Find an **active** account by id (`deleted_at IS NULL`).
|
|
22
|
+
*
|
|
23
|
+
* This is the auth-resolution workhorse (`build_request_context` /
|
|
24
|
+
* `build_account_context`) and the admin-target lookup, so it
|
|
25
|
+
* deliberately excludes soft-deleted accounts: a tombstoned account must
|
|
26
|
+
* not authenticate (`delete` = soft, `purge` = hard). Purge, which must operate on
|
|
27
|
+
* soft-deleted rows too, uses `query_purge_account` directly.
|
|
22
28
|
*/
|
|
23
29
|
export declare const query_account_by_id: (deps: QueryDeps, id: string) => Promise<Account | undefined>;
|
|
24
30
|
/**
|
|
@@ -36,9 +42,15 @@ export declare const query_account_by_email: (deps: QueryDeps, email: string) =>
|
|
|
36
42
|
* Otherwise tries username first then email. This supports a single
|
|
37
43
|
* login field that accepts either format.
|
|
38
44
|
*
|
|
45
|
+
* Excludes soft-deleted accounts (`deleted_at IS NULL`) — this is the
|
|
46
|
+
* login lookup, and a tombstoned account must not authenticate. The
|
|
47
|
+
* underlying `query_account_by_username` / `query_account_by_email` stay
|
|
48
|
+
* unfiltered because the invite-collision checks need to see soft-deleted
|
|
49
|
+
* accounts (usernames/emails stay reserved after a soft-delete).
|
|
50
|
+
*
|
|
39
51
|
* @param deps - query dependencies
|
|
40
52
|
* @param input - username or email address
|
|
41
|
-
* @returns the matching account, or `undefined`
|
|
53
|
+
* @returns the matching active account, or `undefined`
|
|
42
54
|
*/
|
|
43
55
|
export declare const query_account_by_username_or_email: (deps: QueryDeps, input: string) => Promise<Account | undefined>;
|
|
44
56
|
/**
|
|
@@ -63,11 +75,75 @@ export declare const query_account_by_username_or_email: (deps: QueryDeps, input
|
|
|
63
75
|
*/
|
|
64
76
|
export declare const query_update_account_password: (deps: QueryDeps, id: string, password_hash: string, updated_by: string | null, expected_hash: string) => Promise<boolean>;
|
|
65
77
|
/**
|
|
66
|
-
*
|
|
78
|
+
* Identifying values snapshotted into a deletion/purge audit event so the
|
|
79
|
+
* identity behind a now-orphaned `audit_log` id isn't lost. Mirrors the
|
|
80
|
+
* Rust `AccountIdentitySnapshot`.
|
|
81
|
+
*/
|
|
82
|
+
export interface AccountIdentitySnapshot {
|
|
83
|
+
username: string;
|
|
84
|
+
email: string | null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Soft-delete an account — the reversible tombstone (`delete` = soft).
|
|
88
|
+
*
|
|
89
|
+
* Stamps `deleted_at` + `deleted_by` (the initiator's actor) on the active
|
|
90
|
+
* row — paired like `role_grant`'s `revoked_at` / `revoked_by`, and
|
|
91
|
+
* deliberately leaving `updated_at` / `updated_by` untouched (deletion
|
|
92
|
+
* isn't a content edit). Returns the identity snapshot for the
|
|
93
|
+
* `account_delete` audit event, or `undefined` when no active row matched
|
|
94
|
+
* (missing or already soft-deleted). Auth resolution
|
|
95
|
+
* (`query_account_by_id`) already excludes soft-deleted accounts; the
|
|
96
|
+
* caller revokes sessions/tokens.
|
|
97
|
+
*
|
|
98
|
+
* @mutates `account` row - sets `deleted_at` + `deleted_by` on one active row
|
|
99
|
+
*/
|
|
100
|
+
export declare const query_account_soft_delete: (deps: QueryDeps, id: string, deleted_by: string | null) => Promise<AccountIdentitySnapshot | undefined>;
|
|
101
|
+
/**
|
|
102
|
+
* Hard-purge an account — irreversible cascading removal (`purge` = hard).
|
|
103
|
+
*
|
|
104
|
+
* Physically deletes the row, cascading to actors, role_grants, sessions,
|
|
105
|
+
* and tokens. Operates on active OR already-soft-deleted rows. Returns the
|
|
106
|
+
* identity snapshot for the `account_purge` audit event, or `undefined`
|
|
107
|
+
* when no row matched. The `audit_log` identity columns carry no FK, so
|
|
108
|
+
* the purged id survives on historical rows for forensic correlation back
|
|
109
|
+
* to the purge event.
|
|
110
|
+
*
|
|
111
|
+
* **Keeper-gated, loud, irreversible** — restrict to the keeper credential
|
|
112
|
+
* and confirm explicitly at the call site. The `purge` name flags the danger.
|
|
67
113
|
*
|
|
68
114
|
* @mutates `account` table and downstream FK rows - DELETE cascades through actors/role_grants/sessions/tokens
|
|
69
115
|
*/
|
|
70
|
-
export declare const
|
|
116
|
+
export declare const query_purge_account: (deps: QueryDeps, id: string) => Promise<AccountIdentitySnapshot | undefined>;
|
|
117
|
+
/**
|
|
118
|
+
* Soft-delete one actor (sets `deleted_at` + `deleted_by`). Returns `true`
|
|
119
|
+
* when an active row flipped, `false` when none matched. Emitted per actor
|
|
120
|
+
* alongside the account-level soft-delete.
|
|
121
|
+
*
|
|
122
|
+
* @mutates `actor` row - sets `deleted_at` + `deleted_by` on one active row
|
|
123
|
+
*/
|
|
124
|
+
export declare const query_actor_soft_delete: (deps: QueryDeps, id: string, deleted_by: string | null) => Promise<boolean>;
|
|
125
|
+
/**
|
|
126
|
+
* Reactivate a soft-deleted account — clears the `deleted_at` /
|
|
127
|
+
* `deleted_by` tombstone (the inverse of `query_account_soft_delete`).
|
|
128
|
+
*
|
|
129
|
+
* Operates only on a currently soft-deleted row (`deleted_at IS NOT NULL`)
|
|
130
|
+
* and returns the identity snapshot for the `account_undelete` audit
|
|
131
|
+
* event, or `undefined` when no soft-deleted row matched (missing or
|
|
132
|
+
* already active). Reactivation does **not** restore the revoked
|
|
133
|
+
* sessions/tokens — the account is live again but its principals re-auth
|
|
134
|
+
* fresh. `updated_at` / `updated_by` stay untouched.
|
|
135
|
+
*
|
|
136
|
+
* @mutates `account` row - clears `deleted_at` + `deleted_by` on one soft-deleted row
|
|
137
|
+
*/
|
|
138
|
+
export declare const query_account_undelete: (deps: QueryDeps, id: string) => Promise<AccountIdentitySnapshot | undefined>;
|
|
139
|
+
/**
|
|
140
|
+
* Reactivate one soft-deleted actor (clears `deleted_at` / `deleted_by`).
|
|
141
|
+
* Returns `true` when a soft-deleted row flipped back, `false` when none
|
|
142
|
+
* matched. Emitted per actor alongside the account-level reactivation.
|
|
143
|
+
*
|
|
144
|
+
* @mutates `actor` row - clears `deleted_at` + `deleted_by` on one soft-deleted row
|
|
145
|
+
*/
|
|
146
|
+
export declare const query_actor_undelete: (deps: QueryDeps, id: string) => Promise<boolean>;
|
|
71
147
|
/**
|
|
72
148
|
* Check if any account exists.
|
|
73
149
|
*/
|
|
@@ -120,6 +196,13 @@ export interface AdminAccountListOptions {
|
|
|
120
196
|
limit?: number | null;
|
|
121
197
|
/** Pagination offset. Defaults to 0. */
|
|
122
198
|
offset?: number | null;
|
|
199
|
+
/**
|
|
200
|
+
* Include soft-deleted (tombstoned) accounts. Defaults to `false` —
|
|
201
|
+
* the listing shows active accounts only, matching auth resolution.
|
|
202
|
+
* Set `true` for the admin UI's "show deleted" view, which offers
|
|
203
|
+
* reactivation via `account_undelete`.
|
|
204
|
+
*/
|
|
205
|
+
include_deleted?: boolean | null;
|
|
123
206
|
}
|
|
124
207
|
/**
|
|
125
208
|
* List accounts with their actors, active role_grants, and pending inbound
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAEN,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,MAAM,qBAAqB,CAAC;AAG7B;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,OAAO,kBAAkB,KACvB,OAAO,CAAC,OAAO,CAQjB,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"account_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAEN,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,MAAM,qBAAqB,CAAC;AAG7B;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,OAAO,kBAAkB,KACvB,OAAO,CAAC,OAAO,CAQjB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,IAAI,MAAM,KACR,OAAO,CAAC,OAAO,GAAG,SAAS,CAI7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,SAAS,EACf,UAAU,MAAM,KACd,OAAO,CAAC,OAAO,GAAG,SAAS,CAI7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,SAAS,EACf,OAAO,MAAM,KACX,OAAO,CAAC,OAAO,GAAG,SAAS,CAI7B,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,kCAAkC,GAC9C,MAAM,SAAS,EACf,OAAO,MAAM,KACX,OAAO,CAAC,OAAO,GAAG,SAAS,CAS7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,6BAA6B,GACzC,MAAM,SAAS,EACf,IAAI,MAAM,EACV,eAAe,MAAM,EACrB,YAAY,MAAM,GAAG,IAAI,EACzB,eAAe,MAAM,KACnB,OAAO,CAAC,OAAO,CAQjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,SAAS,EACf,IAAI,MAAM,EACV,YAAY,MAAM,GAAG,IAAI,KACvB,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAO7C,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,IAAI,MAAM,KACR,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAK7C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,IAAI,MAAM,EACV,YAAY,MAAM,GAAG,IAAI,KACvB,OAAO,CAAC,OAAO,CAQjB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,SAAS,EACf,IAAI,MAAM,KACR,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAO7C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAU,MAAM,SAAS,EAAE,IAAI,MAAM,KAAG,OAAO,CAAC,OAAO,CAQvF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAU,MAAM,SAAS,KAAG,OAAO,CAAC,OAAO,CAK5E,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAC9B,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,MAAM,MAAM,KACV,OAAO,CAAC,KAAK,CAMf,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,YAAY,MAAM,KAChB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAKtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,SAAS,EACf,IAAI,MAAM,KACR,OAAO,CAAC,KAAK,GAAG,SAAS,CAE3B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,GAC3C,MAAM,SAAS,EACf,OAAO,kBAAkB,KACvB,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAC,CAI1C,CAAC;AA2BF,8CAA8C;AAC9C,MAAM,WAAW,uBAAuB;IACvC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,GACpC,MAAM,SAAS,EACf,UAAU,uBAAuB,KAC/B,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CA8GtC,CAAC"}
|
|
@@ -24,10 +24,18 @@ export const query_create_account = async (deps, input) => {
|
|
|
24
24
|
return assert_row(row, 'INSERT INTO account');
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
|
-
* Find an account by id.
|
|
27
|
+
* Find an **active** account by id (`deleted_at IS NULL`).
|
|
28
|
+
*
|
|
29
|
+
* This is the auth-resolution workhorse (`build_request_context` /
|
|
30
|
+
* `build_account_context`) and the admin-target lookup, so it
|
|
31
|
+
* deliberately excludes soft-deleted accounts: a tombstoned account must
|
|
32
|
+
* not authenticate (`delete` = soft, `purge` = hard). Purge, which must operate on
|
|
33
|
+
* soft-deleted rows too, uses `query_purge_account` directly.
|
|
28
34
|
*/
|
|
29
35
|
export const query_account_by_id = async (deps, id) => {
|
|
30
|
-
return deps.db.query_one(`SELECT * FROM account WHERE id = $1`, [
|
|
36
|
+
return deps.db.query_one(`SELECT * FROM account WHERE id = $1 AND deleted_at IS NULL`, [
|
|
37
|
+
id,
|
|
38
|
+
]);
|
|
31
39
|
};
|
|
32
40
|
/**
|
|
33
41
|
* Find an account by username (case-insensitive).
|
|
@@ -52,15 +60,25 @@ export const query_account_by_email = async (deps, email) => {
|
|
|
52
60
|
* Otherwise tries username first then email. This supports a single
|
|
53
61
|
* login field that accepts either format.
|
|
54
62
|
*
|
|
63
|
+
* Excludes soft-deleted accounts (`deleted_at IS NULL`) — this is the
|
|
64
|
+
* login lookup, and a tombstoned account must not authenticate. The
|
|
65
|
+
* underlying `query_account_by_username` / `query_account_by_email` stay
|
|
66
|
+
* unfiltered because the invite-collision checks need to see soft-deleted
|
|
67
|
+
* accounts (usernames/emails stay reserved after a soft-delete).
|
|
68
|
+
*
|
|
55
69
|
* @param deps - query dependencies
|
|
56
70
|
* @param input - username or email address
|
|
57
|
-
* @returns the matching account, or `undefined`
|
|
71
|
+
* @returns the matching active account, or `undefined`
|
|
58
72
|
*/
|
|
59
73
|
export const query_account_by_username_or_email = async (deps, input) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
const account = input.includes('@')
|
|
75
|
+
? ((await query_account_by_email(deps, input)) ??
|
|
76
|
+
(await query_account_by_username(deps, input)))
|
|
77
|
+
: ((await query_account_by_username(deps, input)) ??
|
|
78
|
+
(await query_account_by_email(deps, input)));
|
|
79
|
+
// Login must not resolve a soft-deleted account, but the bare
|
|
80
|
+
// username/email lookups stay unfiltered for invite-collision checks.
|
|
81
|
+
return account && account.deleted_at === null ? account : undefined;
|
|
64
82
|
};
|
|
65
83
|
/**
|
|
66
84
|
* Update the password hash for an account, conditional on the current
|
|
@@ -89,15 +107,85 @@ export const query_update_account_password = async (deps, id, password_hash, upd
|
|
|
89
107
|
return rows.length > 0;
|
|
90
108
|
};
|
|
91
109
|
/**
|
|
92
|
-
*
|
|
110
|
+
* Soft-delete an account — the reversible tombstone (`delete` = soft).
|
|
111
|
+
*
|
|
112
|
+
* Stamps `deleted_at` + `deleted_by` (the initiator's actor) on the active
|
|
113
|
+
* row — paired like `role_grant`'s `revoked_at` / `revoked_by`, and
|
|
114
|
+
* deliberately leaving `updated_at` / `updated_by` untouched (deletion
|
|
115
|
+
* isn't a content edit). Returns the identity snapshot for the
|
|
116
|
+
* `account_delete` audit event, or `undefined` when no active row matched
|
|
117
|
+
* (missing or already soft-deleted). Auth resolution
|
|
118
|
+
* (`query_account_by_id`) already excludes soft-deleted accounts; the
|
|
119
|
+
* caller revokes sessions/tokens.
|
|
120
|
+
*
|
|
121
|
+
* @mutates `account` row - sets `deleted_at` + `deleted_by` on one active row
|
|
122
|
+
*/
|
|
123
|
+
export const query_account_soft_delete = async (deps, id, deleted_by) => {
|
|
124
|
+
return deps.db.query_one(`UPDATE account SET deleted_at = NOW(), deleted_by = $2
|
|
125
|
+
WHERE id = $1 AND deleted_at IS NULL
|
|
126
|
+
RETURNING username, email`, [id, deleted_by]);
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Hard-purge an account — irreversible cascading removal (`purge` = hard).
|
|
130
|
+
*
|
|
131
|
+
* Physically deletes the row, cascading to actors, role_grants, sessions,
|
|
132
|
+
* and tokens. Operates on active OR already-soft-deleted rows. Returns the
|
|
133
|
+
* identity snapshot for the `account_purge` audit event, or `undefined`
|
|
134
|
+
* when no row matched. The `audit_log` identity columns carry no FK, so
|
|
135
|
+
* the purged id survives on historical rows for forensic correlation back
|
|
136
|
+
* to the purge event.
|
|
137
|
+
*
|
|
138
|
+
* **Keeper-gated, loud, irreversible** — restrict to the keeper credential
|
|
139
|
+
* and confirm explicitly at the call site. The `purge` name flags the danger.
|
|
93
140
|
*
|
|
94
141
|
* @mutates `account` table and downstream FK rows - DELETE cascades through actors/role_grants/sessions/tokens
|
|
95
142
|
*/
|
|
96
|
-
export const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
143
|
+
export const query_purge_account = async (deps, id) => {
|
|
144
|
+
return deps.db.query_one(`DELETE FROM account WHERE id = $1 RETURNING username, email`, [id]);
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Soft-delete one actor (sets `deleted_at` + `deleted_by`). Returns `true`
|
|
148
|
+
* when an active row flipped, `false` when none matched. Emitted per actor
|
|
149
|
+
* alongside the account-level soft-delete.
|
|
150
|
+
*
|
|
151
|
+
* @mutates `actor` row - sets `deleted_at` + `deleted_by` on one active row
|
|
152
|
+
*/
|
|
153
|
+
export const query_actor_soft_delete = async (deps, id, deleted_by) => {
|
|
154
|
+
const row = await deps.db.query_one(`UPDATE actor SET deleted_at = NOW(), deleted_by = $2
|
|
155
|
+
WHERE id = $1 AND deleted_at IS NULL
|
|
156
|
+
RETURNING id`, [id, deleted_by]);
|
|
157
|
+
return row !== undefined;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Reactivate a soft-deleted account — clears the `deleted_at` /
|
|
161
|
+
* `deleted_by` tombstone (the inverse of `query_account_soft_delete`).
|
|
162
|
+
*
|
|
163
|
+
* Operates only on a currently soft-deleted row (`deleted_at IS NOT NULL`)
|
|
164
|
+
* and returns the identity snapshot for the `account_undelete` audit
|
|
165
|
+
* event, or `undefined` when no soft-deleted row matched (missing or
|
|
166
|
+
* already active). Reactivation does **not** restore the revoked
|
|
167
|
+
* sessions/tokens — the account is live again but its principals re-auth
|
|
168
|
+
* fresh. `updated_at` / `updated_by` stay untouched.
|
|
169
|
+
*
|
|
170
|
+
* @mutates `account` row - clears `deleted_at` + `deleted_by` on one soft-deleted row
|
|
171
|
+
*/
|
|
172
|
+
export const query_account_undelete = async (deps, id) => {
|
|
173
|
+
return deps.db.query_one(`UPDATE account SET deleted_at = NULL, deleted_by = NULL
|
|
174
|
+
WHERE id = $1 AND deleted_at IS NOT NULL
|
|
175
|
+
RETURNING username, email`, [id]);
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Reactivate one soft-deleted actor (clears `deleted_at` / `deleted_by`).
|
|
179
|
+
* Returns `true` when a soft-deleted row flipped back, `false` when none
|
|
180
|
+
* matched. Emitted per actor alongside the account-level reactivation.
|
|
181
|
+
*
|
|
182
|
+
* @mutates `actor` row - clears `deleted_at` + `deleted_by` on one soft-deleted row
|
|
183
|
+
*/
|
|
184
|
+
export const query_actor_undelete = async (deps, id) => {
|
|
185
|
+
const row = await deps.db.query_one(`UPDATE actor SET deleted_at = NULL, deleted_by = NULL
|
|
186
|
+
WHERE id = $1 AND deleted_at IS NOT NULL
|
|
187
|
+
RETURNING id`, [id]);
|
|
188
|
+
return row !== undefined;
|
|
101
189
|
};
|
|
102
190
|
/**
|
|
103
191
|
* Check if any account exists.
|
|
@@ -172,12 +260,14 @@ export const query_create_account_with_actor = async (deps, input) => {
|
|
|
172
260
|
export const query_admin_account_list = async (deps, options) => {
|
|
173
261
|
const limit = options?.limit === null ? null : (options?.limit ?? ADMIN_ACCOUNT_LIST_DEFAULT_LIMIT);
|
|
174
262
|
const offset = options?.offset ?? 0;
|
|
263
|
+
// Active-only by default; the admin UI's "show deleted" view passes
|
|
264
|
+
// `include_deleted` to surface tombstoned rows for reactivation.
|
|
265
|
+
const where = options?.include_deleted ? '' : 'WHERE deleted_at IS NULL';
|
|
175
266
|
const account_query = limit == null
|
|
176
|
-
? deps.db.query(`SELECT * FROM account ORDER BY created_at OFFSET $1`, [
|
|
177
|
-
: deps.db.query(`SELECT * FROM account ORDER BY created_at LIMIT $1 OFFSET $2`, [
|
|
178
|
-
limit,
|
|
267
|
+
? deps.db.query(`SELECT * FROM account ${where} ORDER BY created_at OFFSET $1`, [
|
|
179
268
|
offset,
|
|
180
|
-
])
|
|
269
|
+
])
|
|
270
|
+
: deps.db.query(`SELECT * FROM account ${where} ORDER BY created_at LIMIT $1 OFFSET $2`, [limit, offset]);
|
|
181
271
|
const accounts = await account_query;
|
|
182
272
|
if (accounts.length === 0)
|
|
183
273
|
return [];
|
|
@@ -30,6 +30,19 @@ export interface Account {
|
|
|
30
30
|
created_by: Uuid | null;
|
|
31
31
|
updated_at: string;
|
|
32
32
|
updated_by: Uuid | null;
|
|
33
|
+
/**
|
|
34
|
+
* Soft-delete tombstone. Non-null means the account is deleted
|
|
35
|
+
* (`delete` = soft); auth resolution treats it as absent. A hard
|
|
36
|
+
* `purge` removes the row entirely. See `auth/account_queries.ts`.
|
|
37
|
+
*/
|
|
38
|
+
deleted_at: string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Actor that performed the soft-delete (initiator: self / admin /
|
|
41
|
+
* keeper). Paired with `deleted_at`, mirroring `role_grant`'s
|
|
42
|
+
* `revoked_at` / `revoked_by`. Plain UUID (no FK, like
|
|
43
|
+
* `created_by` / `updated_by` on this table).
|
|
44
|
+
*/
|
|
45
|
+
deleted_by: Uuid | null;
|
|
33
46
|
}
|
|
34
47
|
/** Account without sensitive fields, scoped to the authenticated user's own session. */
|
|
35
48
|
export interface SessionAccount {
|
|
@@ -47,6 +60,10 @@ export interface Actor {
|
|
|
47
60
|
created_at: string;
|
|
48
61
|
updated_at: string | null;
|
|
49
62
|
updated_by: Uuid | null;
|
|
63
|
+
/** Soft-delete tombstone — set alongside the owning account's soft-delete. */
|
|
64
|
+
deleted_at: string | null;
|
|
65
|
+
/** Actor that performed the soft-delete. Paired with `deleted_at`. */
|
|
66
|
+
deleted_by: Uuid | null;
|
|
50
67
|
}
|
|
51
68
|
/**
|
|
52
69
|
* Maximum length of the optional free-form `revoked_reason` attached to a
|
|
@@ -158,6 +175,7 @@ export declare const AdminAccountJson: z.ZodObject<{
|
|
|
158
175
|
created_at: z.ZodString;
|
|
159
176
|
updated_at: z.ZodString;
|
|
160
177
|
updated_by: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
178
|
+
deleted_at: z.ZodNullable<z.ZodString>;
|
|
161
179
|
}, z.core.$strict>;
|
|
162
180
|
export type AdminAccountJson = z.infer<typeof AdminAccountJson>;
|
|
163
181
|
/**
|
|
@@ -194,6 +212,7 @@ export declare const AdminAccountEntryJson: z.ZodObject<{
|
|
|
194
212
|
created_at: z.ZodString;
|
|
195
213
|
updated_at: z.ZodString;
|
|
196
214
|
updated_by: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
215
|
+
deleted_at: z.ZodNullable<z.ZodString>;
|
|
197
216
|
}, z.core.$strict>;
|
|
198
217
|
actor: z.ZodNullable<z.ZodObject<{
|
|
199
218
|
id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_schema.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"account_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -73,6 +73,13 @@ export const ActorSummaryJson = z.strictObject({
|
|
|
73
73
|
export const AdminAccountJson = SessionAccountJson.extend({
|
|
74
74
|
updated_at: z.string(),
|
|
75
75
|
updated_by: Uuid.nullable(),
|
|
76
|
+
/**
|
|
77
|
+
* Soft-delete tombstone, non-null when the account is deleted. Surfaced
|
|
78
|
+
* so the admin UI can mark tombstoned rows (shown only when the listing
|
|
79
|
+
* is requested with `include_deleted`) and offer reactivation via
|
|
80
|
+
* `account_undelete`. Active listings always carry `null` here.
|
|
81
|
+
*/
|
|
82
|
+
deleted_at: z.string().nullable(),
|
|
76
83
|
});
|
|
77
84
|
/**
|
|
78
85
|
* Zod schema for a pending role_grant offer surfaced in admin account listings.
|
|
@@ -127,4 +134,5 @@ export const to_admin_account = (account) => ({
|
|
|
127
134
|
...to_session_account(account),
|
|
128
135
|
updated_at: account.updated_at,
|
|
129
136
|
updated_by: account.updated_by,
|
|
137
|
+
deleted_at: account.deleted_at,
|
|
130
138
|
});
|