@fuzdev/fuz_app 0.140.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 +72 -22
- package/dist/actions/action_rpc.d.ts +5 -1
- package/dist/actions/action_rpc.d.ts.map +1 -1
- package/dist/actions/action_rpc.js +9 -1
- package/dist/actions/connection_closer.d.ts +44 -4
- package/dist/actions/connection_closer.d.ts.map +1 -1
- package/dist/actions/connection_closer.js +33 -3
- 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_action_ws.d.ts +42 -6
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +87 -19
- package/dist/actions/register_ws_endpoint.d.ts +15 -6
- package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
- package/dist/actions/register_ws_endpoint.js +10 -4
- package/dist/actions/socket.svelte.d.ts +19 -4
- package/dist/actions/socket.svelte.d.ts.map +1 -1
- package/dist/actions/socket.svelte.js +31 -4
- package/dist/actions/transports.d.ts +30 -1
- package/dist/actions/transports.d.ts.map +1 -1
- package/dist/actions/transports.js +30 -1
- package/dist/actions/transports_ws_auth_guard.d.ts +13 -6
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +24 -10
- package/dist/actions/transports_ws_backend.d.ts +51 -5
- package/dist/actions/transports_ws_backend.d.ts.map +1 -1
- package/dist/actions/transports_ws_backend.js +62 -9
- package/dist/actions/ws_endpoint_spec.d.ts +11 -10
- package/dist/actions/ws_endpoint_spec.d.ts.map +1 -1
- package/dist/auth/CLAUDE.md +44 -22
- 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 +1 -0
- package/dist/auth/account_route_schema.d.ts.map +1 -1
- package/dist/auth/account_route_schema.js +12 -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/api_token.d.ts +20 -0
- package/dist/auth/api_token.d.ts.map +1 -1
- package/dist/auth/api_token.js +21 -1
- package/dist/auth/api_token_queries.d.ts +22 -4
- package/dist/auth/api_token_queries.d.ts.map +1 -1
- package/dist/auth/api_token_queries.js +11 -6
- package/dist/auth/audit_log_routes.d.ts +10 -0
- package/dist/auth/audit_log_routes.d.ts.map +1 -1
- package/dist/auth/audit_log_routes.js +20 -0
- package/dist/auth/audit_log_schema.d.ts +30 -5
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +30 -0
- package/dist/auth/bearer_auth.d.ts +4 -2
- package/dist/auth/bearer_auth.d.ts.map +1 -1
- package/dist/auth/bearer_auth.js +19 -8
- package/dist/auth/bootstrap_route_schema.d.ts +1 -0
- package/dist/auth/bootstrap_route_schema.d.ts.map +1 -1
- package/dist/auth/bootstrap_route_schema.js +1 -0
- 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/cleanup.d.ts +9 -9
- package/dist/auth/cleanup.js +9 -9
- package/dist/auth/credential_deadline.d.ts +95 -0
- package/dist/auth/credential_deadline.d.ts.map +1 -0
- package/dist/auth/credential_deadline.js +139 -0
- package/dist/auth/daemon_token_middleware.d.ts.map +1 -1
- package/dist/auth/daemon_token_middleware.js +4 -1
- package/dist/auth/middleware.d.ts +90 -12
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +115 -16
- package/dist/auth/request_context.d.ts +8 -2
- package/dist/auth/request_context.d.ts.map +1 -1
- package/dist/auth/request_context.js +20 -4
- package/dist/auth/resolved_auth.d.ts +13 -2
- package/dist/auth/resolved_auth.d.ts.map +1 -1
- package/dist/auth/resolved_auth.js +5 -4
- 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/session_cookie.d.ts +4 -0
- package/dist/auth/session_cookie.d.ts.map +1 -1
- package/dist/auth/session_cookie.js +3 -2
- package/dist/auth/session_middleware.d.ts +1 -1
- package/dist/auth/session_middleware.d.ts.map +1 -1
- package/dist/auth/session_middleware.js +4 -1
- package/dist/auth/session_queries.d.ts +19 -2
- package/dist/auth/session_queries.d.ts.map +1 -1
- package/dist/auth/session_queries.js +8 -2
- package/dist/auth/signup_route_schema.d.ts.map +1 -1
- package/dist/auth/signup_route_schema.js +1 -0
- 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/hono_context.d.ts +23 -0
- package/dist/hono_context.d.ts.map +1 -1
- package/dist/hono_context.js +19 -0
- package/dist/http/CLAUDE.md +41 -15
- 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/http/middleware_spec.d.ts +16 -0
- package/dist/http/middleware_spec.d.ts.map +1 -1
- package/dist/http/origin.d.ts +113 -18
- package/dist/http/origin.d.ts.map +1 -1
- package/dist/http/origin.js +247 -127
- package/dist/http/route_spec.d.ts +21 -0
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/schema_helpers.d.ts +22 -0
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +24 -0
- package/dist/http/surface.d.ts +6 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +12 -5
- 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/realtime/sse_auth_guard.d.ts +22 -6
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +31 -12
- package/dist/realtime/subscriber_registry.d.ts +10 -1
- package/dist/realtime/subscriber_registry.d.ts.map +1 -1
- package/dist/realtime/subscriber_registry.js +10 -1
- package/dist/server/app_server.d.ts +20 -7
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +8 -3
- package/dist/server/env.d.ts +2 -1
- package/dist/server/env.d.ts.map +1 -1
- package/dist/server/env.js +7 -17
- 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 +16 -6
- package/dist/testing/CLAUDE.md +164 -25
- package/dist/testing/adversarial_headers.d.ts.map +1 -1
- package/dist/testing/adversarial_headers.js +13 -6
- package/dist/testing/connection_closer_helpers.d.ts +6 -1
- package/dist/testing/connection_closer_helpers.d.ts.map +1 -1
- package/dist/testing/connection_closer_helpers.js +4 -0
- 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/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +14 -65
- package/dist/testing/cross_backend/capabilities.d.ts +26 -2
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +9 -3
- 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/conformance_case.d.ts +11 -3
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +6 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +20 -19
- package/dist/testing/cross_backend/credential_deadline.d.ts +25 -0
- package/dist/testing/cross_backend/credential_deadline.d.ts.map +1 -0
- package/dist/testing/cross_backend/credential_deadline.js +185 -0
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +13 -2
- package/dist/testing/cross_backend/expected_schema.json +0 -1
- package/dist/testing/cross_backend/full_spine_mount.d.ts +3 -0
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +7 -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/narrowed_api_token.d.ts +23 -0
- package/dist/testing/cross_backend/narrowed_api_token.d.ts.map +1 -0
- package/dist/testing/cross_backend/narrowed_api_token.js +40 -0
- package/dist/testing/cross_backend/origin.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin.js +6 -26
- package/dist/testing/cross_backend/origin_conformance.d.ts +152 -0
- package/dist/testing/cross_backend/origin_conformance.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin_conformance.js +136 -0
- package/dist/testing/cross_backend/origin_conformance.json +1679 -0
- package/dist/testing/cross_backend/origin_scope.d.ts +16 -0
- package/dist/testing/cross_backend/origin_scope.d.ts.map +1 -0
- package/dist/testing/cross_backend/origin_scope.js +140 -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_cross_helpers.d.ts +35 -0
- package/dist/testing/cross_backend/role_grant_cross_helpers.d.ts.map +1 -0
- package/dist/testing/cross_backend/role_grant_cross_helpers.js +64 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts +8 -0
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_notification_ws.js +44 -33
- 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/rust_spine_stub_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/rust_spine_stub_backend_config.js +6 -4
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +20 -1
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +23 -1
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +20 -7
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +180 -5
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +154 -5
- package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_scope_surface.js +25 -21
- package/dist/testing/cross_backend/transport_composition.d.ts +60 -0
- package/dist/testing/cross_backend/transport_composition.d.ts.map +1 -0
- package/dist/testing/cross_backend/transport_composition.js +364 -0
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +21 -6
- 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/cross_backend/ws_role_gated.d.ts +38 -0
- package/dist/testing/cross_backend/ws_role_gated.d.ts.map +1 -0
- package/dist/testing/cross_backend/ws_role_gated.js +142 -0
- package/dist/testing/entities.d.ts +23 -0
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +37 -0
- package/dist/testing/integration.d.ts.map +1 -1
- package/dist/testing/integration.js +3 -1
- package/dist/testing/middleware.d.ts +10 -0
- package/dist/testing/middleware.d.ts.map +1 -1
- package/dist/testing/middleware.js +31 -7
- 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/testing/stubs.d.ts +16 -3
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +20 -7
- package/dist/testing/surface_invariants.js +2 -2
- 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
|
@@ -13,12 +13,19 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Three tiers:
|
|
15
15
|
*
|
|
16
|
-
* - `can_view_cell` — admin /
|
|
17
|
-
*
|
|
16
|
+
* - `can_view_cell` — admin / owner / public / any `viewer`+ grant, the
|
|
17
|
+
* public and grant arms only while the cell's `moderation` admits an
|
|
18
|
+
* audience (`db/cell_moderation.ts`: unmoderated or `'approved'`).
|
|
19
|
+
* - `can_edit_cell` — admin / owner / `editor` grant, the grant arm only
|
|
20
|
+
* while the cell's `moderation` admits an audience. NULL `created_by`
|
|
18
21
|
* is admin-only (system-origin defense-in-depth).
|
|
19
22
|
* - `can_manage_cell` — admin / owner only. Not delegable, not a grant
|
|
20
23
|
* level. Gates the manage tier: `visibility` writes and all grant
|
|
21
24
|
* management (`cell_grant_create` / `_list` / `_revoke`).
|
|
25
|
+
* - `can_steward_cell` — the governing root's manager reading a pending or
|
|
26
|
+
* rejected contribution under it. A separate read arm beside
|
|
27
|
+
* `can_view_cell`, composed only at the surfaces a moderator works from
|
|
28
|
+
* (`auth/cell_steward.ts` names them).
|
|
22
29
|
*
|
|
23
30
|
* Grant-admit branches: per-`actor_id` grants admit the matching
|
|
24
31
|
* actor; `(role, scope_id?)` grants admit any holder of an active
|
|
@@ -29,29 +36,55 @@
|
|
|
29
36
|
* The admin bypass on every tier is the **global** `admin` grant
|
|
30
37
|
* (`has_scoped_role(auth, ROLE_ADMIN, null)`), never a scoped one.
|
|
31
38
|
*
|
|
39
|
+
* Moderation gates the audience: a cell's effective audience is its
|
|
40
|
+
* visibility or grants **and** its admission, so a pending, rejected, or
|
|
41
|
+
* unknown-marker contribution is readable through `can_view_cell` by its owner
|
|
42
|
+
* and a global admin alone, whatever its `visibility` or grants say. The
|
|
43
|
+
* `editor` grant arm of `can_edit_cell` follows the same admission; the owner,
|
|
44
|
+
* admin, and manage arms don't consult it.
|
|
45
|
+
*
|
|
32
46
|
* @module
|
|
33
47
|
*/
|
|
34
48
|
import { type RequestContext } from './request_context.js';
|
|
35
|
-
import type { CellRow } from '../db/cell_queries.js';
|
|
49
|
+
import type { CellRow, CellViewRow } from '../db/cell_queries.js';
|
|
50
|
+
import { type CellViewer } from '../db/cell_view_sql.js';
|
|
36
51
|
import type { CellGrantRow } from '../db/cell_grant_queries.js';
|
|
37
52
|
/**
|
|
38
53
|
* View authorization for a cell.
|
|
39
54
|
*
|
|
40
55
|
* - Admin: always allowed.
|
|
41
|
-
* - `cell.visibility === 'public'`: allowed for everyone, including
|
|
42
|
-
* unauthenticated callers (e.g. a public landing cell).
|
|
43
56
|
* - Owner (`cell.created_by === auth.actor.id`): allowed.
|
|
57
|
+
* - `cell.visibility === 'public'`: allowed for everyone, including
|
|
58
|
+
* unauthenticated callers (e.g. a public landing cell) — while the cell's
|
|
59
|
+
* `moderation` admits an audience (`cell_moderation_admits_audience`).
|
|
44
60
|
* - Any active grant on the cell admits the caller (actor-shaped:
|
|
45
61
|
* match on actor_id; role-shaped: match on `(role, scope_id?)`
|
|
46
|
-
* against an active role_grant).
|
|
62
|
+
* against an active role_grant) — under the same moderation admission.
|
|
47
63
|
* - Otherwise: false.
|
|
48
64
|
*
|
|
65
|
+
* A pending or rejected contribution stays with its owner and admins even
|
|
66
|
+
* when public or granted.
|
|
67
|
+
*
|
|
68
|
+
* Reads only the view facts (`visibility`, `moderation`, `created_by`), so a
|
|
69
|
+
* full `CellRow` and the narrow `CellViewRow` both answer it.
|
|
70
|
+
*
|
|
49
71
|
* @param auth - request context, or `null` for unauthenticated callers
|
|
50
|
-
* @param cell - the cell row
|
|
72
|
+
* @param cell - the cell row, or its view facts
|
|
51
73
|
* @param grants - the cell's grant list, or `null` to skip the grant branch
|
|
52
74
|
* @returns whether the caller may view the cell
|
|
53
75
|
*/
|
|
54
|
-
export declare const can_view_cell: (auth: RequestContext | null, cell:
|
|
76
|
+
export declare const can_view_cell: (auth: RequestContext | null, cell: Omit<CellViewRow, "id">, grants: ReadonlyArray<CellGrantRow> | null) => boolean;
|
|
77
|
+
/**
|
|
78
|
+
* The `CellViewer` a SQL view filter (`db/cell_view_sql.ts`) binds for
|
|
79
|
+
* `auth` — the facts `can_view_cell` reads, so the two admit the same cells:
|
|
80
|
+
* the acting actor, the global `admin` grant, and the active role grants
|
|
81
|
+
* `grant_admits` matches against.
|
|
82
|
+
*
|
|
83
|
+
* @param auth - request context, or `null` for unauthenticated callers
|
|
84
|
+
* @param now - the instant role-grant expiry is judged at
|
|
85
|
+
* @returns the viewer
|
|
86
|
+
*/
|
|
87
|
+
export declare const cell_viewer_from_auth: (auth: RequestContext | null, now?: Date) => CellViewer;
|
|
55
88
|
/**
|
|
56
89
|
* Edit authorization for a cell.
|
|
57
90
|
*
|
|
@@ -66,6 +99,12 @@ export declare const can_view_cell: (auth: RequestContext | null, cell: CellRow,
|
|
|
66
99
|
* `false` for NULL via JS equality semantics — the explicit branch
|
|
67
100
|
* survives refactors and reads as a load-bearing security property.
|
|
68
101
|
*
|
|
102
|
+
* The `editor` grant arm requires the cell's `moderation` to admit an
|
|
103
|
+
* audience (`cell_moderation_admits_audience`), as in `can_view_cell`: a
|
|
104
|
+
* grant made while a contribution was approved stops admitting once it is
|
|
105
|
+
* rejected, for writes as for reads (every write verb echoes or reveals the
|
|
106
|
+
* row it touched).
|
|
107
|
+
*
|
|
69
108
|
* @param auth - request context, or `null` for unauthenticated callers
|
|
70
109
|
* @param cell - the cell row
|
|
71
110
|
* @param grants - the cell's grant list, or `null` to skip the grant branch
|
|
@@ -88,4 +127,26 @@ export declare const can_edit_cell: (auth: RequestContext | null, cell: CellRow,
|
|
|
88
127
|
* @returns whether the caller is in the manage tier for the cell
|
|
89
128
|
*/
|
|
90
129
|
export declare const can_manage_cell: (auth: RequestContext | null, cell: CellRow) => boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Steward authorization: whether `auth` manages `root` — the governing root of
|
|
132
|
+
* `cell` — and `cell` is a pending or rejected contribution under it.
|
|
133
|
+
*
|
|
134
|
+
* The moderator's read of a contribution its audience can't see: true when
|
|
135
|
+
* `cell.root_id` is `root.id`, `cell.moderation` is exactly `'pending'` or
|
|
136
|
+
* `'rejected'` (`cell_moderation_is_stewardable`), `root` is not soft-deleted,
|
|
137
|
+
* and `can_manage_cell` admits `auth` on `root` (global admin or the root's
|
|
138
|
+
* owner — no grant tier confers manage). Unauthenticated callers are never
|
|
139
|
+
* stewards. An approved contribution later narrowed to private is not
|
|
140
|
+
* stewarded — it reads like any cell its author narrowed.
|
|
141
|
+
*
|
|
142
|
+
* Not part of `can_view_cell`: the steward arm admits only where a moderator
|
|
143
|
+
* works (`auth/cell_steward.ts` names the sites), so the relation gates, clone,
|
|
144
|
+
* contribution parents, and the grant paths keep the narrower predicate.
|
|
145
|
+
*
|
|
146
|
+
* @param auth - request context, or `null` for unauthenticated callers
|
|
147
|
+
* @param cell - the contribution
|
|
148
|
+
* @param root - the cell's governing root
|
|
149
|
+
* @returns whether the caller stewards the contribution
|
|
150
|
+
*/
|
|
151
|
+
export declare const can_steward_cell: (auth: RequestContext | null, cell: CellRow, root: CellRow) => boolean;
|
|
91
152
|
//# sourceMappingURL=cell_authorize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_authorize.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_authorize.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cell_authorize.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_authorize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI5E,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAiEhE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,aAAa,GACzB,MAAM,cAAc,GAAG,IAAI,EAC3B,MAAM,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAC7B,QAAQ,aAAa,CAAC,YAAY,CAAC,GAAG,IAAI,KACxC,OAOF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,GACjC,MAAM,cAAc,GAAG,IAAI,EAC3B,MAAK,IAAiB,KACpB,UASF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,aAAa,GACzB,MAAM,cAAc,GAAG,IAAI,EAC3B,MAAM,OAAO,EACb,QAAQ,aAAa,CAAC,YAAY,CAAC,GAAG,IAAI,KACxC,OAYF,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,cAAc,GAAG,IAAI,EAAE,MAAM,OAAO,KAAG,OAI5E,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,gBAAgB,GAC5B,MAAM,cAAc,GAAG,IAAI,EAC3B,MAAM,OAAO,EACb,MAAM,OAAO,KACX,OAKyB,CAAC"}
|
|
@@ -13,12 +13,19 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Three tiers:
|
|
15
15
|
*
|
|
16
|
-
* - `can_view_cell` — admin /
|
|
17
|
-
*
|
|
16
|
+
* - `can_view_cell` — admin / owner / public / any `viewer`+ grant, the
|
|
17
|
+
* public and grant arms only while the cell's `moderation` admits an
|
|
18
|
+
* audience (`db/cell_moderation.ts`: unmoderated or `'approved'`).
|
|
19
|
+
* - `can_edit_cell` — admin / owner / `editor` grant, the grant arm only
|
|
20
|
+
* while the cell's `moderation` admits an audience. NULL `created_by`
|
|
18
21
|
* is admin-only (system-origin defense-in-depth).
|
|
19
22
|
* - `can_manage_cell` — admin / owner only. Not delegable, not a grant
|
|
20
23
|
* level. Gates the manage tier: `visibility` writes and all grant
|
|
21
24
|
* management (`cell_grant_create` / `_list` / `_revoke`).
|
|
25
|
+
* - `can_steward_cell` — the governing root's manager reading a pending or
|
|
26
|
+
* rejected contribution under it. A separate read arm beside
|
|
27
|
+
* `can_view_cell`, composed only at the surfaces a moderator works from
|
|
28
|
+
* (`auth/cell_steward.ts` names them).
|
|
22
29
|
*
|
|
23
30
|
* Grant-admit branches: per-`actor_id` grants admit the matching
|
|
24
31
|
* actor; `(role, scope_id?)` grants admit any holder of an active
|
|
@@ -29,12 +36,20 @@
|
|
|
29
36
|
* The admin bypass on every tier is the **global** `admin` grant
|
|
30
37
|
* (`has_scoped_role(auth, ROLE_ADMIN, null)`), never a scoped one.
|
|
31
38
|
*
|
|
39
|
+
* Moderation gates the audience: a cell's effective audience is its
|
|
40
|
+
* visibility or grants **and** its admission, so a pending, rejected, or
|
|
41
|
+
* unknown-marker contribution is readable through `can_view_cell` by its owner
|
|
42
|
+
* and a global admin alone, whatever its `visibility` or grants say. The
|
|
43
|
+
* `editor` grant arm of `can_edit_cell` follows the same admission; the owner,
|
|
44
|
+
* admin, and manage arms don't consult it.
|
|
45
|
+
*
|
|
32
46
|
* @module
|
|
33
47
|
*/
|
|
34
48
|
import { has_scoped_role } from './request_context.js';
|
|
35
49
|
import { is_role_grant_active } from './account_schema.js';
|
|
36
50
|
import { ROLE_ADMIN } from './role_schema.js';
|
|
37
|
-
|
|
51
|
+
import { CELL_VIEWER_ANONYMOUS } from '../db/cell_view_sql.js';
|
|
52
|
+
import { cell_moderation_admits_audience, cell_moderation_is_stewardable } from '../db/cell_moderation.js';
|
|
38
53
|
/**
|
|
39
54
|
* Whether any grant admits `auth` at the given level.
|
|
40
55
|
*
|
|
@@ -92,30 +107,60 @@ const is_owner = (auth, cell) => auth.actor !== null && cell.created_by !== null
|
|
|
92
107
|
* View authorization for a cell.
|
|
93
108
|
*
|
|
94
109
|
* - Admin: always allowed.
|
|
95
|
-
* - `cell.visibility === 'public'`: allowed for everyone, including
|
|
96
|
-
* unauthenticated callers (e.g. a public landing cell).
|
|
97
110
|
* - Owner (`cell.created_by === auth.actor.id`): allowed.
|
|
111
|
+
* - `cell.visibility === 'public'`: allowed for everyone, including
|
|
112
|
+
* unauthenticated callers (e.g. a public landing cell) — while the cell's
|
|
113
|
+
* `moderation` admits an audience (`cell_moderation_admits_audience`).
|
|
98
114
|
* - Any active grant on the cell admits the caller (actor-shaped:
|
|
99
115
|
* match on actor_id; role-shaped: match on `(role, scope_id?)`
|
|
100
|
-
* against an active role_grant).
|
|
116
|
+
* against an active role_grant) — under the same moderation admission.
|
|
101
117
|
* - Otherwise: false.
|
|
102
118
|
*
|
|
119
|
+
* A pending or rejected contribution stays with its owner and admins even
|
|
120
|
+
* when public or granted.
|
|
121
|
+
*
|
|
122
|
+
* Reads only the view facts (`visibility`, `moderation`, `created_by`), so a
|
|
123
|
+
* full `CellRow` and the narrow `CellViewRow` both answer it.
|
|
124
|
+
*
|
|
103
125
|
* @param auth - request context, or `null` for unauthenticated callers
|
|
104
|
-
* @param cell - the cell row
|
|
126
|
+
* @param cell - the cell row, or its view facts
|
|
105
127
|
* @param grants - the cell's grant list, or `null` to skip the grant branch
|
|
106
128
|
* @returns whether the caller may view the cell
|
|
107
129
|
*/
|
|
108
130
|
export const can_view_cell = (auth, cell, grants) => {
|
|
109
131
|
if (auth && has_scoped_role(auth, ROLE_ADMIN, null))
|
|
110
132
|
return true;
|
|
111
|
-
if (cell_is_public(cell))
|
|
112
|
-
return true;
|
|
113
133
|
if (auth && is_owner(auth, cell))
|
|
114
134
|
return true;
|
|
135
|
+
if (!cell_moderation_admits_audience(cell.moderation))
|
|
136
|
+
return false;
|
|
137
|
+
if (cell.visibility === 'public')
|
|
138
|
+
return true;
|
|
115
139
|
if (auth && grant_admits(auth, grants, 'viewer'))
|
|
116
140
|
return true;
|
|
117
141
|
return false;
|
|
118
142
|
};
|
|
143
|
+
/**
|
|
144
|
+
* The `CellViewer` a SQL view filter (`db/cell_view_sql.ts`) binds for
|
|
145
|
+
* `auth` — the facts `can_view_cell` reads, so the two admit the same cells:
|
|
146
|
+
* the acting actor, the global `admin` grant, and the active role grants
|
|
147
|
+
* `grant_admits` matches against.
|
|
148
|
+
*
|
|
149
|
+
* @param auth - request context, or `null` for unauthenticated callers
|
|
150
|
+
* @param now - the instant role-grant expiry is judged at
|
|
151
|
+
* @returns the viewer
|
|
152
|
+
*/
|
|
153
|
+
export const cell_viewer_from_auth = (auth, now = new Date()) => {
|
|
154
|
+
if (!auth)
|
|
155
|
+
return CELL_VIEWER_ANONYMOUS;
|
|
156
|
+
const active = auth.role_grants.filter((p) => is_role_grant_active(p, now));
|
|
157
|
+
return {
|
|
158
|
+
actor_id: auth.actor?.id ?? null,
|
|
159
|
+
is_admin: has_scoped_role(auth, ROLE_ADMIN, null, now),
|
|
160
|
+
role_grant_roles: active.map((p) => p.role),
|
|
161
|
+
role_grant_scope_ids: active.map((p) => p.scope_id)
|
|
162
|
+
};
|
|
163
|
+
};
|
|
119
164
|
/**
|
|
120
165
|
* Edit authorization for a cell.
|
|
121
166
|
*
|
|
@@ -130,6 +175,12 @@ export const can_view_cell = (auth, cell, grants) => {
|
|
|
130
175
|
* `false` for NULL via JS equality semantics — the explicit branch
|
|
131
176
|
* survives refactors and reads as a load-bearing security property.
|
|
132
177
|
*
|
|
178
|
+
* The `editor` grant arm requires the cell's `moderation` to admit an
|
|
179
|
+
* audience (`cell_moderation_admits_audience`), as in `can_view_cell`: a
|
|
180
|
+
* grant made while a contribution was approved stops admitting once it is
|
|
181
|
+
* rejected, for writes as for reads (every write verb echoes or reveals the
|
|
182
|
+
* row it touched).
|
|
183
|
+
*
|
|
133
184
|
* @param auth - request context, or `null` for unauthenticated callers
|
|
134
185
|
* @param cell - the cell row
|
|
135
186
|
* @param grants - the cell's grant list, or `null` to skip the grant branch
|
|
@@ -147,6 +198,9 @@ export const can_edit_cell = (auth, cell, grants) => {
|
|
|
147
198
|
// fallback below handles the actor-grain editor-grant path.
|
|
148
199
|
if (is_owner(auth, cell))
|
|
149
200
|
return true;
|
|
201
|
+
// the grant arm follows moderation admission, as in `can_view_cell`
|
|
202
|
+
if (!cell_moderation_admits_audience(cell.moderation))
|
|
203
|
+
return false;
|
|
150
204
|
if (grant_admits(auth, grants, 'editor'))
|
|
151
205
|
return true;
|
|
152
206
|
return false;
|
|
@@ -173,3 +227,29 @@ export const can_manage_cell = (auth, cell) => {
|
|
|
173
227
|
return true;
|
|
174
228
|
return is_owner(auth, cell);
|
|
175
229
|
};
|
|
230
|
+
/**
|
|
231
|
+
* Steward authorization: whether `auth` manages `root` — the governing root of
|
|
232
|
+
* `cell` — and `cell` is a pending or rejected contribution under it.
|
|
233
|
+
*
|
|
234
|
+
* The moderator's read of a contribution its audience can't see: true when
|
|
235
|
+
* `cell.root_id` is `root.id`, `cell.moderation` is exactly `'pending'` or
|
|
236
|
+
* `'rejected'` (`cell_moderation_is_stewardable`), `root` is not soft-deleted,
|
|
237
|
+
* and `can_manage_cell` admits `auth` on `root` (global admin or the root's
|
|
238
|
+
* owner — no grant tier confers manage). Unauthenticated callers are never
|
|
239
|
+
* stewards. An approved contribution later narrowed to private is not
|
|
240
|
+
* stewarded — it reads like any cell its author narrowed.
|
|
241
|
+
*
|
|
242
|
+
* Not part of `can_view_cell`: the steward arm admits only where a moderator
|
|
243
|
+
* works (`auth/cell_steward.ts` names the sites), so the relation gates, clone,
|
|
244
|
+
* contribution parents, and the grant paths keep the narrower predicate.
|
|
245
|
+
*
|
|
246
|
+
* @param auth - request context, or `null` for unauthenticated callers
|
|
247
|
+
* @param cell - the contribution
|
|
248
|
+
* @param root - the cell's governing root
|
|
249
|
+
* @returns whether the caller stewards the contribution
|
|
250
|
+
*/
|
|
251
|
+
export const can_steward_cell = (auth, cell, root) => auth !== null &&
|
|
252
|
+
cell.root_id === root.id &&
|
|
253
|
+
cell_moderation_is_stewardable(cell.moderation) &&
|
|
254
|
+
root.deleted_at === null &&
|
|
255
|
+
can_manage_cell(auth, root);
|
|
@@ -70,10 +70,11 @@ export type CellFieldDeleteOutput = z.infer<typeof CellFieldDeleteOutput>;
|
|
|
70
70
|
* both / neither). Reverse listing has 2-layer authz (target view-check
|
|
71
71
|
* gates the call; per-source view-check filters the rows).
|
|
72
72
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
73
|
+
* Either direction returns a page of up to `limit` fields (default
|
|
74
|
+
* `CELL_RELATION_LIST_LIMIT_DEFAULT`) whose other end the caller can view —
|
|
75
|
+
* the view check runs before the limit. Forward listing pages on via
|
|
76
|
+
* `name_after` (return rows whose `name > name_after` lex); the reverse
|
|
77
|
+
* listing has no cursor, oldest field first.
|
|
77
78
|
*/
|
|
78
79
|
export declare const CellFieldListInput: z.ZodObject<{
|
|
79
80
|
source_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_field_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_field_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"cell_field_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_field_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,gFAAgF;AAChF,eAAO,MAAM,+CAA+C,EAC3D,2CAAoD,CAAC;AAItD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAA2B,CAAC;AAC9D,eAAO,MAAM,aAAa,yDAAiE,CAAC;AAC5F,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D,2EAA2E;AAC3E,eAAO,MAAM,SAAS;;;;;kBAKpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAIlD;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;kBAO5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,eAAO,MAAM,kBAAkB;;;;;;;kBAAuC,CAAC;AACvE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAIpE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;kBAI/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,eAAO,MAAM,qBAAqB;;;kBAGhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAI1E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB;;;;;;kBAiB5B,CAAC;AACJ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,eAAO,MAAM,mBAAmB;;;;;;;kBAE9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAItE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;CAWF,CAAC;AAEtC,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;CAWL,CAAC;AAEtC,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYH,CAAC;AAEtC,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI9B,CAAC"}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
import { Uuid } from '../primitive_schemas.js';
|
|
15
15
|
import { ActingActor } from '../http/auth_shape.js';
|
|
16
|
+
import { CellRelationListLimit } from './cell_relation_list_limit.js';
|
|
16
17
|
// -- Error reasons ----------------------------------------------------------
|
|
17
18
|
/** Error reason — `cell_field_list` got neither `source_id` nor `target_id`. */
|
|
18
19
|
export const ERROR_CELL_FIELD_LIST_REQUIRES_SOURCE_OR_TARGET = 'cell_field_list_requires_source_or_target';
|
|
@@ -66,10 +67,11 @@ export const CellFieldDeleteOutput = z.strictObject({
|
|
|
66
67
|
* both / neither). Reverse listing has 2-layer authz (target view-check
|
|
67
68
|
* gates the call; per-source view-check filters the rows).
|
|
68
69
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
70
|
+
* Either direction returns a page of up to `limit` fields (default
|
|
71
|
+
* `CELL_RELATION_LIST_LIMIT_DEFAULT`) whose other end the caller can view —
|
|
72
|
+
* the view check runs before the limit. Forward listing pages on via
|
|
73
|
+
* `name_after` (return rows whose `name > name_after` lex); the reverse
|
|
74
|
+
* listing has no cursor, oldest field first.
|
|
73
75
|
*/
|
|
74
76
|
export const CellFieldListInput = z
|
|
75
77
|
.strictObject({
|
|
@@ -82,9 +84,7 @@ export const CellFieldListInput = z
|
|
|
82
84
|
name_after: CellFieldName.optional().meta({
|
|
83
85
|
description: 'Cursor for forward pagination — return rows whose name > this lex. Forward only.'
|
|
84
86
|
}),
|
|
85
|
-
limit:
|
|
86
|
-
description: 'Page size cap (max 500). Forward only. Omit for unbounded — explicit list calls escape the bundled `cell_get` cap.'
|
|
87
|
-
}),
|
|
87
|
+
limit: CellRelationListLimit,
|
|
88
88
|
acting: ActingActor
|
|
89
89
|
})
|
|
90
90
|
.refine((v) => Boolean(v.source_id) !== Boolean(v.target_id), {
|
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
* couldn't otherwise see). Idempotent UPSERT on `(source_id, name)`.
|
|
10
10
|
* - `cell_field_delete` — admin / owner / editor-grant on `source`.
|
|
11
11
|
* Idempotent: `deleted: false` when no row matched.
|
|
12
|
-
* - `cell_field_list` — bidirectional
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* - `cell_field_list` — bidirectional, a page of up to `limit` fields
|
|
13
|
+
* whose other end the caller may view (filtered in SQL, before the
|
|
14
|
+
* limit). Forward (pass `source_id`) is gated on `can_view_cell(source)`
|
|
15
|
+
* and pages the fields whose target is viewable (strict
|
|
16
|
+
* target-visibility). Reverse (pass `target_id`) has 2-layer authz: gate
|
|
17
|
+
* on `can_view_cell(target)` first, then page the fields whose source is
|
|
18
|
+
* viewable.
|
|
17
19
|
*
|
|
18
20
|
* IDOR-mask 404s on cell-miss / cell-unviewable, mirroring the existence-
|
|
19
21
|
* leak guards in `auth/cell_actions.ts` / `auth/cell_grant_actions.ts`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_field_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_field_actions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cell_field_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_field_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAUN,KAAK,SAAS,EACd,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAKN,KAAK,YAAY,EACjB,MAAM,6BAA6B,CAAC;AAMrC,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAEpD,eAAO,MAAM,aAAa,GAAI,KAAK,YAAY,KAAG,SAKhD,CAAC;AAEH,mDAAmD;AACnD,eAAO,MAAM,yBAAyB,GAAI,MAAM,mBAAmB,KAAG,KAAK,CAAC,SAAS,CAqIpF,CAAC"}
|
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
* couldn't otherwise see). Idempotent UPSERT on `(source_id, name)`.
|
|
10
10
|
* - `cell_field_delete` — admin / owner / editor-grant on `source`.
|
|
11
11
|
* Idempotent: `deleted: false` when no row matched.
|
|
12
|
-
* - `cell_field_list` — bidirectional
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* - `cell_field_list` — bidirectional, a page of up to `limit` fields
|
|
13
|
+
* whose other end the caller may view (filtered in SQL, before the
|
|
14
|
+
* limit). Forward (pass `source_id`) is gated on `can_view_cell(source)`
|
|
15
|
+
* and pages the fields whose target is viewable (strict
|
|
16
|
+
* target-visibility). Reverse (pass `target_id`) has 2-layer authz: gate
|
|
17
|
+
* on `can_view_cell(target)` first, then page the fields whose source is
|
|
18
|
+
* viewable.
|
|
17
19
|
*
|
|
18
20
|
* IDOR-mask 404s on cell-miss / cell-unviewable, mirroring the existence-
|
|
19
21
|
* leak guards in `auth/cell_actions.ts` / `auth/cell_grant_actions.ts`.
|
|
@@ -27,8 +29,8 @@ import { rpc_action } from '../actions/action_rpc.js';
|
|
|
27
29
|
import { jsonrpc_errors } from '../http/jsonrpc_errors.js';
|
|
28
30
|
import { cell_field_set_action_spec, cell_field_delete_action_spec, cell_field_list_action_spec } from './cell_field_action_specs.js';
|
|
29
31
|
import { ERROR_CELL_NOT_FOUND } from './cell_action_specs.js';
|
|
30
|
-
import { can_view_cell, can_edit_cell } from './cell_authorize.js';
|
|
31
|
-
import {
|
|
32
|
+
import { can_view_cell, can_edit_cell, cell_viewer_from_auth } from './cell_authorize.js';
|
|
33
|
+
import { CELL_RELATION_LIST_LIMIT_DEFAULT } from './cell_relation_list_limit.js';
|
|
32
34
|
import { query_cell_get } from '../db/cell_queries.js';
|
|
33
35
|
import { query_cell_grant_list_for_cell } from '../db/cell_grant_queries.js';
|
|
34
36
|
import { query_cell_field_set, query_cell_field_delete, query_cell_field_list_for_source, query_cell_field_list_for_target } from '../db/cell_field_queries.js';
|
|
@@ -108,8 +110,11 @@ export const create_cell_field_actions = (deps) => {
|
|
|
108
110
|
};
|
|
109
111
|
const list_handler = async (input, ctx) => {
|
|
110
112
|
const auth = ctx.auth;
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
+
// an omitted limit is the default page, either direction
|
|
114
|
+
const limit = input.limit ?? CELL_RELATION_LIST_LIMIT_DEFAULT;
|
|
115
|
+
// Forward listing: gate on can_view_cell(source), then page the fields
|
|
116
|
+
// whose target the caller may view (strict target-visibility, in SQL
|
|
117
|
+
// before the limit).
|
|
113
118
|
if (input.source_id !== undefined) {
|
|
114
119
|
const source = await query_cell_get(ctx, input.source_id);
|
|
115
120
|
if (!source) {
|
|
@@ -119,12 +124,8 @@ export const create_cell_field_actions = (deps) => {
|
|
|
119
124
|
if (!can_view_cell(auth, source, source_grants)) {
|
|
120
125
|
throw jsonrpc_errors.not_found('cell', { reason: ERROR_CELL_NOT_FOUND });
|
|
121
126
|
}
|
|
122
|
-
const rows = await query_cell_field_list_for_source(ctx, source.id, {
|
|
123
|
-
|
|
124
|
-
name_after: input.name_after
|
|
125
|
-
});
|
|
126
|
-
const visible_targets = await filter_visible_target_ids(ctx, auth, rows.map((r) => r.target_id));
|
|
127
|
-
return { fields: rows.filter((r) => visible_targets.has(r.target_id)).map(to_field_json) };
|
|
127
|
+
const rows = await query_cell_field_list_for_source(ctx, cell_viewer_from_auth(auth), source.id, { limit, name_after: input.name_after });
|
|
128
|
+
return { fields: rows.map(to_field_json) };
|
|
128
129
|
}
|
|
129
130
|
// Reverse listing: 2-layer authz. First, can_view_cell(target).
|
|
130
131
|
// Without this, the count of returned rows leaks "at least N
|
|
@@ -137,13 +138,14 @@ export const create_cell_field_actions = (deps) => {
|
|
|
137
138
|
if (!can_view_cell(auth, target, target_grants)) {
|
|
138
139
|
throw jsonrpc_errors.not_found('cell', { reason: ERROR_CELL_NOT_FOUND });
|
|
139
140
|
}
|
|
140
|
-
// Then
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
const rows = await query_cell_field_list_for_target(ctx, target.id, {
|
|
145
|
-
|
|
146
|
-
|
|
141
|
+
// Then page the fields whose source the caller may view — filtered in
|
|
142
|
+
// SQL before the limit, so hidden sources never crowd out visible ones,
|
|
143
|
+
// and bounded so a heavily inbound-linked target can't force an
|
|
144
|
+
// unbounded read on this public endpoint.
|
|
145
|
+
const rows = await query_cell_field_list_for_target(ctx, cell_viewer_from_auth(auth), target.id, {
|
|
146
|
+
limit
|
|
147
|
+
});
|
|
148
|
+
return { fields: rows.map(to_field_json) };
|
|
147
149
|
};
|
|
148
150
|
return [
|
|
149
151
|
rpc_action(cell_field_set_action_spec, set_handler),
|
|
@@ -29,6 +29,12 @@ export declare const ERROR_CELL_GRANT_PRINCIPAL_IS_OWNER: "cell_grant_principal_
|
|
|
29
29
|
* no role_grant could match.
|
|
30
30
|
*/
|
|
31
31
|
export declare const ERROR_CELL_GRANT_UNKNOWN_ROLE: "cell_grant_unknown_role";
|
|
32
|
+
/**
|
|
33
|
+
* Error reason — `cell_grant_create` on a cell whose `moderation` doesn't
|
|
34
|
+
* admit an audience (pending, rejected, or an unknown marker). A grant would
|
|
35
|
+
* extend an audience the cell doesn't have yet.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ERROR_CELL_GRANT_UNAPPROVED: "cell_grant_unapproved";
|
|
32
38
|
/** Grant level — view-only or view-plus-edit. */
|
|
33
39
|
export declare const CellGrantLevel: z.ZodEnum<{
|
|
34
40
|
viewer: "viewer";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_grant_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_grant_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,EAAG,sBAA+B,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,EAAG,+BAAwC,CAAC;AAE5F;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAG,yBAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"cell_grant_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_grant_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,EAAG,sBAA+B,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,EAAG,+BAAwC,CAAC;AAE5F;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAG,yBAAkC,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAG,uBAAgC,CAAC;AAI5E,iDAAiD;AACjD,eAAO,MAAM,cAAc;;;EAA+B,CAAC;AAC3D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;;;4BAYlC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;kBASpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAIlD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;kBAO/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;kBAAuC,CAAC;AAC1E,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAI1E,eAAO,MAAM,oBAAoB;;;kBAG/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;kBAGhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAI1E,eAAO,MAAM,kBAAkB;;;kBAG7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;kBAE9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAItE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWL,CAAC;AAEtC,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;CAWL,CAAC;AAEtC,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWH,CAAC;AAEtC,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI9B,CAAC"}
|
|
@@ -32,6 +32,12 @@ export const ERROR_CELL_GRANT_PRINCIPAL_IS_OWNER = 'cell_grant_principal_is_owne
|
|
|
32
32
|
* no role_grant could match.
|
|
33
33
|
*/
|
|
34
34
|
export const ERROR_CELL_GRANT_UNKNOWN_ROLE = 'cell_grant_unknown_role';
|
|
35
|
+
/**
|
|
36
|
+
* Error reason — `cell_grant_create` on a cell whose `moderation` doesn't
|
|
37
|
+
* admit an audience (pending, rejected, or an unknown marker). A grant would
|
|
38
|
+
* extend an audience the cell doesn't have yet.
|
|
39
|
+
*/
|
|
40
|
+
export const ERROR_CELL_GRANT_UNAPPROVED = 'cell_grant_unapproved';
|
|
35
41
|
// -- Shared schemas ---------------------------------------------------------
|
|
36
42
|
/** Grant level — view-only or view-plus-edit. */
|
|
37
43
|
export const CellGrantLevel = z.enum(['viewer', 'editor']);
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* cannot manage its grants — delegating the share list would let an editor
|
|
10
10
|
* widen access or mint peer editors and escape the manager's authority.
|
|
11
11
|
*
|
|
12
|
-
* - `cell_grant_create` — admin / owner only.
|
|
12
|
+
* - `cell_grant_create` — admin / owner only. Refuses a cell whose
|
|
13
|
+
* `moderation` doesn't admit an audience (403 `cell_grant_unapproved`,
|
|
14
|
+
* after the manage gate). Validates role-shaped
|
|
13
15
|
* principals against the role schema; rejects owner-as-principal.
|
|
14
16
|
* Actor-shaped principals carry a pre-resolved `actor_id` (callers pick
|
|
15
17
|
* via `actor_search`). Idempotent — re-granting the same principal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_grant_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_grant_actions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cell_grant_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_grant_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAcN,KAAK,SAAS,EACd,MAAM,8BAA8B,CAAC;AAKtC,OAAO,EAKN,KAAK,YAAY,EAEjB,MAAM,6BAA6B,CAAC;AAOrC;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,GAAG;IACrD,KAAK,EAAE,gBAAgB,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,KAAK,YAAY,KAAG,SAShD,CAAC;AAgDH,mDAAmD;AACnD,eAAO,MAAM,yBAAyB,GAAI,MAAM,mBAAmB,KAAG,KAAK,CAAC,SAAS,CA+IpF,CAAC"}
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* cannot manage its grants — delegating the share list would let an editor
|
|
10
10
|
* widen access or mint peer editors and escape the manager's authority.
|
|
11
11
|
*
|
|
12
|
-
* - `cell_grant_create` — admin / owner only.
|
|
12
|
+
* - `cell_grant_create` — admin / owner only. Refuses a cell whose
|
|
13
|
+
* `moderation` doesn't admit an audience (403 `cell_grant_unapproved`,
|
|
14
|
+
* after the manage gate). Validates role-shaped
|
|
13
15
|
* principals against the role schema; rejects owner-as-principal.
|
|
14
16
|
* Actor-shaped principals carry a pre-resolved `actor_id` (callers pick
|
|
15
17
|
* via `actor_search`). Idempotent — re-granting the same principal
|
|
@@ -31,10 +33,11 @@
|
|
|
31
33
|
*/
|
|
32
34
|
import { rpc_action } from '../actions/action_rpc.js';
|
|
33
35
|
import { jsonrpc_errors } from '../http/jsonrpc_errors.js';
|
|
34
|
-
import { cell_grant_create_action_spec, cell_grant_revoke_action_spec, cell_grant_list_action_spec, ERROR_CELL_GRANT_NOT_FOUND, ERROR_CELL_GRANT_PRINCIPAL_IS_OWNER, ERROR_CELL_GRANT_UNKNOWN_ROLE } from './cell_grant_action_specs.js';
|
|
36
|
+
import { cell_grant_create_action_spec, cell_grant_revoke_action_spec, cell_grant_list_action_spec, ERROR_CELL_GRANT_NOT_FOUND, ERROR_CELL_GRANT_PRINCIPAL_IS_OWNER, ERROR_CELL_GRANT_UNAPPROVED, ERROR_CELL_GRANT_UNKNOWN_ROLE } from './cell_grant_action_specs.js';
|
|
35
37
|
import { ERROR_CELL_NOT_FOUND } from './cell_action_specs.js';
|
|
36
38
|
import { can_view_cell, can_manage_cell } from './cell_authorize.js';
|
|
37
39
|
import { query_cell_get } from '../db/cell_queries.js';
|
|
40
|
+
import { cell_moderation_admits_audience } from '../db/cell_moderation.js';
|
|
38
41
|
import { query_cell_grant_create, query_cell_grant_get, query_cell_grant_delete, query_cell_grant_list_for_cell } from '../db/cell_grant_queries.js';
|
|
39
42
|
export const to_grant_json = (row) => ({
|
|
40
43
|
id: row.id,
|
|
@@ -105,6 +108,17 @@ export const create_cell_grant_actions = (deps) => {
|
|
|
105
108
|
if (!can_manage_cell(auth, cell)) {
|
|
106
109
|
throw jsonrpc_errors.not_found('cell', { reason: ERROR_CELL_NOT_FOUND });
|
|
107
110
|
}
|
|
111
|
+
// A grant extends a cell's audience, and a contribution whose moderation
|
|
112
|
+
// doesn't admit one (pending, rejected, or an unknown marker) has none past
|
|
113
|
+
// its author and admins — `can_view_cell`'s grant arm wouldn't admit on it —
|
|
114
|
+
// so refuse the grant rather than mint a row that would wake up on
|
|
115
|
+
// approval. After the manage gate, so a non-manager keeps the 404 mask; no
|
|
116
|
+
// admin exemption.
|
|
117
|
+
if (!cell_moderation_admits_audience(cell.moderation)) {
|
|
118
|
+
throw jsonrpc_errors.forbidden('cell_grant_create requires an unmoderated or approved cell', {
|
|
119
|
+
reason: ERROR_CELL_GRANT_UNAPPROVED
|
|
120
|
+
});
|
|
121
|
+
}
|
|
108
122
|
const principal = to_query_principal(input.principal);
|
|
109
123
|
// Role validity — only relevant for role-shaped principals; reject
|
|
110
124
|
// before insert so dead grant rows nothing can match are foreclosed.
|
|
@@ -110,10 +110,11 @@ export type CellItemDeleteOutput = z.infer<typeof CellItemDeleteOutput>;
|
|
|
110
110
|
* authz (child view-check gates the call; per-parent view-check filters
|
|
111
111
|
* the rows).
|
|
112
112
|
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
113
|
+
* Either direction returns a page of up to `limit` items (default
|
|
114
|
+
* `CELL_RELATION_LIST_LIMIT_DEFAULT`) whose other end the caller can view —
|
|
115
|
+
* the view check runs before the limit. Forward listing pages on via
|
|
116
|
+
* `position_after` (return rows with `position > position_after`); the
|
|
117
|
+
* reverse listing has no cursor, oldest item first.
|
|
117
118
|
*/
|
|
118
119
|
export declare const CellItemListInput: z.ZodObject<{
|
|
119
120
|
parent_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_item_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_item_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"cell_item_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_item_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,8EAA8E;AAC9E,eAAO,MAAM,6CAA6C,EACzD,yCAAkD,CAAC;AAEpD;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,EAAG,0BAAmC,CAAC;AAIlF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,4DAEF,CAAC;AAC5B,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ;;;;;kBAKnB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAIhD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB;;;;;kBAO9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,eAAO,MAAM,oBAAoB;;;;;;;kBAAqC,CAAC;AACvE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIxE;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;kBAK5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,eAAO,MAAM,kBAAkB;;;;;;;kBAAqC,CAAC;AACrE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAIpE,gEAAgE;AAChE,eAAO,MAAM,mBAAmB;;;;kBAI9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,eAAO,MAAM,oBAAoB;;;kBAG/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIxE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB;;;;;;kBAgB3B,CAAC;AACJ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,eAAO,MAAM,kBAAkB;;;;;;;kBAE7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAIpE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;CAWJ,CAAC;AAEtC,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;CAWF,CAAC;AAEtC,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;CAWJ,CAAC;AAEtC,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYF,CAAC;AAEtC,0EAA0E;AAC1E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK7B,CAAC"}
|