@fuzdev/fuz_app 0.67.0 → 0.68.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/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 +168 -0
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +146 -1
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +218 -4
- 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/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/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 +58 -5
- package/dist/testing/app_server.d.ts +12 -0
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +36 -2
- 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 +76 -0
- package/dist/testing/cross_backend/capabilities.d.ts +31 -0
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +3 -0
- 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_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/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +6 -0
- package/dist/testing/cross_backend/setup.d.ts.map +1 -1
- package/dist/testing/cross_backend/setup.js +5 -0
- package/dist/testing/cross_backend/spawn_backend.d.ts.map +1 -1
- package/dist/testing/cross_backend/spawn_backend.js +31 -3
- package/dist/testing/cross_backend/testing_server_bun.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_bun.js +29 -2
- package/dist/testing/entities.d.ts.map +1 -1
- package/dist/testing/entities.js +4 -0
- 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 +58 -0
- package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.d.ts +30 -2
- package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +45 -1
- 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/package.json +4 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cell_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_action_specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell RPC action specs — the declarative contract for the six generic
|
|
3
|
+
* cell verbs. App vocabulary (galleries, posts, events) lives in
|
|
4
|
+
* client-side helpers; the wire stays generic.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { Uuid } from '@fuzdev/fuz_util/id.js';
|
|
10
|
+
import { FactHashSchema } from '@fuzdev/fuz_util/fact_hash.js';
|
|
11
|
+
import { ActingActor } from '../http/auth_shape.js';
|
|
12
|
+
import { all_cell_grant_action_specs, cell_grant_create_action_spec, cell_grant_revoke_action_spec, cell_grant_list_action_spec, GrantJson, } from './cell_grant_action_specs.js';
|
|
13
|
+
import { all_cell_field_action_specs, cell_field_set_action_spec, cell_field_delete_action_spec, cell_field_list_action_spec, FieldJson, } from './cell_field_action_specs.js';
|
|
14
|
+
import { all_cell_item_action_specs, cell_item_insert_action_spec, cell_item_move_action_spec, cell_item_delete_action_spec, cell_item_list_action_spec, ItemJson, } from './cell_item_action_specs.js';
|
|
15
|
+
import { all_cell_audit_action_specs, cell_audit_list_action_spec, } from './cell_audit_action_specs.js';
|
|
16
|
+
import { CellData } from './cell_data_schema.js';
|
|
17
|
+
/**
|
|
18
|
+
* Cell visibility — the coarse-grained access-control axis for a cell.
|
|
19
|
+
* Sibling to `cell_grant` (the fine-grained allowlist of actor- /
|
|
20
|
+
* role-shaped principals at `viewer` / `editor` levels). Together they
|
|
21
|
+
* form the cell-layer access-control surface:
|
|
22
|
+
*
|
|
23
|
+
* - `cell.visibility = 'public'` admits everyone, including
|
|
24
|
+
* unauthenticated visitors. `cell_grant` rows still apply for edit-
|
|
25
|
+
* level admit; read is universal.
|
|
26
|
+
* - `cell.visibility = 'private'` (default) restricts read to admin /
|
|
27
|
+
* owner (`created_by`) / `cell_grant`-admitted callers.
|
|
28
|
+
*
|
|
29
|
+
* Stored as a top-level PG enum column (`cell.visibility`) — NOT inside
|
|
30
|
+
* `cell.data`, which is content metadata only. `can_view_cell` reads
|
|
31
|
+
* the column directly.
|
|
32
|
+
*/
|
|
33
|
+
export const CellVisibility = z.enum(['private', 'public']);
|
|
34
|
+
// Re-exported so the codegen's `cell_specs.*` qualifier resolves them
|
|
35
|
+
// under the single cell-layer namespace. `cell_action_specs.ts` is the
|
|
36
|
+
// registry/aggregator module for the cell layer; the grant / field /
|
|
37
|
+
// item specs live in their own files for source-file separation but
|
|
38
|
+
// ride the same namespace.
|
|
39
|
+
export { cell_grant_create_action_spec, cell_grant_revoke_action_spec, cell_grant_list_action_spec };
|
|
40
|
+
export { cell_field_set_action_spec, cell_field_delete_action_spec, cell_field_list_action_spec };
|
|
41
|
+
export { cell_item_insert_action_spec, cell_item_move_action_spec, cell_item_delete_action_spec, cell_item_list_action_spec, };
|
|
42
|
+
export { cell_audit_list_action_spec };
|
|
43
|
+
// -- Error reasons ----------------------------------------------------------
|
|
44
|
+
/** Error reason — cell id did not resolve, or caller can't view it. */
|
|
45
|
+
export const ERROR_CELL_NOT_FOUND = 'cell_not_found';
|
|
46
|
+
/** Error reason — caller is not an admin and supplied a `path` write. */
|
|
47
|
+
export const ERROR_CELL_PATH_ADMIN_ONLY = 'cell_path_admin_only';
|
|
48
|
+
/**
|
|
49
|
+
* Error reason — a `path` write collided with an existing active cell's
|
|
50
|
+
* path. `path` is globally unique on active rows (`idx_cell_path_unique`);
|
|
51
|
+
* the create / update handlers translate the unique-index violation into
|
|
52
|
+
* this `conflict` (409) reason rather than leaking a raw internal error.
|
|
53
|
+
* Soft-deleted rows free their path (the index is partial on
|
|
54
|
+
* `deleted_at IS NULL`), so reusing a deleted cell's path does not collide.
|
|
55
|
+
*/
|
|
56
|
+
export const ERROR_CELL_PATH_TAKEN = 'cell_path_taken';
|
|
57
|
+
/**
|
|
58
|
+
* Error reason — caller tried to write `cell.visibility` without the
|
|
59
|
+
* manage tier (`can_manage_cell` = admin / owner). Editor-grant holders
|
|
60
|
+
* may edit `data` but cannot flip a cell's visibility — that is a
|
|
61
|
+
* manage-tier-only operation.
|
|
62
|
+
*/
|
|
63
|
+
export const ERROR_CELL_VISIBILITY_MANAGE_ONLY = 'cell_visibility_manage_only';
|
|
64
|
+
/** Error reason — input shape for `cell_get` lacked both `id` and `path`. */
|
|
65
|
+
export const ERROR_CELL_GET_REQUIRES_ID_OR_PATH = 'cell_get_requires_id_or_path';
|
|
66
|
+
/**
|
|
67
|
+
* Error reason — `cell_clone` `with_data_patch` would change `data.kind`.
|
|
68
|
+
* Per-kind shape validation can pass coincidentally (e.g., one kind's
|
|
69
|
+
* schema accepts most of another's fields), so we reject the cross-kind
|
|
70
|
+
* patch explicitly to prevent incoherent clones.
|
|
71
|
+
*/
|
|
72
|
+
export const ERROR_CELL_CLONE_KIND_MISMATCH = 'cell_clone_kind_mismatch';
|
|
73
|
+
/**
|
|
74
|
+
* Error reason — null-auth `cell_list` caller passed a `created_by`
|
|
75
|
+
* filter. The filter is a soft account-id enumeration vector ("does
|
|
76
|
+
* account X have any public cells?"), so we require an authenticated
|
|
77
|
+
* caller to use it.
|
|
78
|
+
*/
|
|
79
|
+
export const ERROR_CELL_LIST_CREATED_BY_REQUIRES_AUTH = 'cell_list_created_by_requires_auth';
|
|
80
|
+
/**
|
|
81
|
+
* Error reason — null-auth `cell_list` caller passed `shared_with: 'me'`.
|
|
82
|
+
* The filter resolves to the caller's account + role_grants, which only
|
|
83
|
+
* exist for an authenticated session.
|
|
84
|
+
*/
|
|
85
|
+
export const ERROR_CELL_LIST_SHARED_WITH_REQUIRES_AUTH = 'cell_list_shared_with_requires_auth';
|
|
86
|
+
// -- Shared schemas ---------------------------------------------------------
|
|
87
|
+
/**
|
|
88
|
+
* Wire form for `cell.path`.
|
|
89
|
+
*
|
|
90
|
+
* At the spec level we only enforce that the value is a non-empty string
|
|
91
|
+
* with a sane upper bound — the cell layer is generic and doesn't impose
|
|
92
|
+
* a path grammar. App-side curation (well-known names like `/map/main`,
|
|
93
|
+
* `/site/events`) is admin-driven.
|
|
94
|
+
*/
|
|
95
|
+
export const CELL_PATH_LENGTH_MAX = 256;
|
|
96
|
+
/**
|
|
97
|
+
* Branded so the type system distinguishes a validated path from any other
|
|
98
|
+
* string. Construct via `CellPath.parse(s)` at external boundaries; the
|
|
99
|
+
* RPC dispatcher does this automatically when the wire schema (`CellCreateInput`,
|
|
100
|
+
* `CellGetInput`, `CellUpdateInput`, `CellListInput`) is parsed at the entry
|
|
101
|
+
* point. Frontend callers handing a raw string to `api.cell_*` cast at the
|
|
102
|
+
* callsite (`as CellPath`) — the runtime check still runs server-side.
|
|
103
|
+
*/
|
|
104
|
+
export const CellPath = z.string().min(1).max(CELL_PATH_LENGTH_MAX).brand('CellPath');
|
|
105
|
+
/**
|
|
106
|
+
* Soft cap on the size of a `cell.list` request page. Larger pages chew
|
|
107
|
+
* memory both server- and client-side; combined with the visibility
|
|
108
|
+
* predicate's filter cost, 200 is a safe ceiling.
|
|
109
|
+
*/
|
|
110
|
+
export const CELL_LIST_LIMIT_MAX = 200;
|
|
111
|
+
export const CELL_LIST_LIMIT_DEFAULT = 50;
|
|
112
|
+
/**
|
|
113
|
+
* Hard cap on bundled relation arrays in `cell_get` (per-relation
|
|
114
|
+
* `LIMIT`). Beyond this the response sets `*_truncated: true` and the
|
|
115
|
+
* client paginates via `cell_item_list({parent_id, position_after})` /
|
|
116
|
+
* `cell_field_list({source_id, name_after})`.
|
|
117
|
+
*/
|
|
118
|
+
export const CELL_RELATIONS_BUNDLE_LIMIT = 500;
|
|
119
|
+
/**
|
|
120
|
+
* Wire form for a cell row. `data` is the typed-but-permissive `CellData`
|
|
121
|
+
* shape (kind / label / summary typed-and-optional, additional fields
|
|
122
|
+
* pass through). Per-kind shape validation is sub-API and handled by
|
|
123
|
+
* the app's `validate_data` deps callback (see `cell_actions.ts`).
|
|
124
|
+
*
|
|
125
|
+
* `visibility` is the access-control axis — a top-level column on the
|
|
126
|
+
* row, not a field inside `data`. `cell_grant` and `visibility` are the
|
|
127
|
+
* two ACL surfaces; both live as peers, not embedded in content.
|
|
128
|
+
*
|
|
129
|
+
* `path` is the global namespace axis (no tenant/hub scoping).
|
|
130
|
+
*
|
|
131
|
+
* Relations (`items`, `fields`) are NOT carried on the cell row — they
|
|
132
|
+
* live in the `cell_item` / `cell_field` sibling tables. Bundled arrays
|
|
133
|
+
* appear on `CellGetOutput`; other read verbs (`cell_list`) do not bundle.
|
|
134
|
+
*/
|
|
135
|
+
export const CellJson = z.strictObject({
|
|
136
|
+
id: Uuid,
|
|
137
|
+
path: CellPath.nullable(),
|
|
138
|
+
data: CellData,
|
|
139
|
+
visibility: CellVisibility.meta({
|
|
140
|
+
description: "Access-control tag. `'public'` admits everyone (including unauthenticated visitors); `'private'` (default) admits admin / owner / `cell_grant`-admitted callers. Top-level column, not inside `data`.",
|
|
141
|
+
}),
|
|
142
|
+
refs: z.array(FactHashSchema).nullable(),
|
|
143
|
+
created_by: Uuid.nullable(),
|
|
144
|
+
updated_by: Uuid.nullable(),
|
|
145
|
+
created_at: z.string(),
|
|
146
|
+
updated_at: z.string().nullable(),
|
|
147
|
+
deleted_at: z.string().nullable(),
|
|
148
|
+
grant_count: z.number().int().nonnegative().meta({
|
|
149
|
+
description: 'Number of `cell_grant` rows naming this cell. Non-leaky scalar (no actor/role identity); surfaces "Shared with N" badges. Derived in SQL via a correlated subquery on `idx_cell_grant_cell`.',
|
|
150
|
+
}),
|
|
151
|
+
});
|
|
152
|
+
// -- cell_create ------------------------------------------------------------
|
|
153
|
+
/**
|
|
154
|
+
* Input for `cell_create`. `created_by` is NOT on the wire — the handler
|
|
155
|
+
* stamps it from auth.actor.id. `path` is admin-only; non-admin callers
|
|
156
|
+
* supplying `path` get `ERROR_CELL_PATH_ADMIN_ONLY` (forbidden).
|
|
157
|
+
*/
|
|
158
|
+
export const CellCreateInput = z.strictObject({
|
|
159
|
+
data: CellData.meta({
|
|
160
|
+
description: 'Cell data. Base fields (kind / label / summary) typed; extras loose. Per-kind shape is sub-API.',
|
|
161
|
+
}),
|
|
162
|
+
visibility: CellVisibility.optional().meta({
|
|
163
|
+
description: "Access-control tag. Top-level column (not in `data`). Default `'private'` when omitted.",
|
|
164
|
+
}),
|
|
165
|
+
path: CellPath.nullish().meta({
|
|
166
|
+
description: 'Admin-only named lookup alias. Globally unique on active rows.',
|
|
167
|
+
}),
|
|
168
|
+
acting: ActingActor,
|
|
169
|
+
});
|
|
170
|
+
export const CellCreateOutput = z.strictObject({ cell: CellJson });
|
|
171
|
+
// -- cell_get ---------------------------------------------------------------
|
|
172
|
+
/**
|
|
173
|
+
* Input for `cell_get`. Pass `id` OR `path` (exactly one expected; both
|
|
174
|
+
* accepted, `id` takes precedence). The handler responds with 404 when no
|
|
175
|
+
* row matches OR when `can_view_cell` rejects the caller — same code so
|
|
176
|
+
* private-cell existence doesn't leak.
|
|
177
|
+
*/
|
|
178
|
+
export const CellGetInput = z
|
|
179
|
+
.strictObject({
|
|
180
|
+
id: Uuid.optional(),
|
|
181
|
+
path: CellPath.optional(),
|
|
182
|
+
acting: ActingActor,
|
|
183
|
+
})
|
|
184
|
+
.refine((v) => v.id !== undefined || v.path !== undefined, {
|
|
185
|
+
message: ERROR_CELL_GET_REQUIRES_ID_OR_PATH,
|
|
186
|
+
});
|
|
187
|
+
/**
|
|
188
|
+
* Output for `cell_get`. Bundles relation arrays (`fields` + `items`)
|
|
189
|
+
* server-side via JOINs so the common "show this cell with its
|
|
190
|
+
* children" flow needs one round-trip. Targets are filtered to those the
|
|
191
|
+
* caller may view (strict target-visibility). Per-relation `LIMIT
|
|
192
|
+
* CELL_RELATIONS_BUNDLE_LIMIT`; clients paginate via
|
|
193
|
+
* `cell_item_list({parent_id, position_after})` /
|
|
194
|
+
* `cell_field_list({source_id})` when truncated.
|
|
195
|
+
*/
|
|
196
|
+
export const CellGetOutput = z.strictObject({
|
|
197
|
+
cell: CellJson,
|
|
198
|
+
fields: z.array(FieldJson),
|
|
199
|
+
fields_truncated: z.boolean(),
|
|
200
|
+
items: z.array(ItemJson),
|
|
201
|
+
items_truncated: z.boolean(),
|
|
202
|
+
can_edit: z.boolean(),
|
|
203
|
+
can_grant: z.boolean(),
|
|
204
|
+
});
|
|
205
|
+
// -- cell_update ------------------------------------------------------------
|
|
206
|
+
/**
|
|
207
|
+
* Input for `cell_update`. Fields left undefined keep their existing value.
|
|
208
|
+
* `path` writes are admin-only (handler-enforced); non-admin callers
|
|
209
|
+
* supplying `path` get `ERROR_CELL_PATH_ADMIN_ONLY` even if no other field
|
|
210
|
+
* is changing. `visibility` writes require the manage tier
|
|
211
|
+
* (`can_manage_cell` = admin / owner) — editor-grant holders editing
|
|
212
|
+
* `data` cannot flip visibility (`ERROR_CELL_VISIBILITY_MANAGE_ONLY`).
|
|
213
|
+
*/
|
|
214
|
+
export const CellUpdateInput = z.strictObject({
|
|
215
|
+
cell_id: Uuid.meta({ description: 'Cell to update.' }),
|
|
216
|
+
data: CellData.optional(),
|
|
217
|
+
visibility: CellVisibility.optional().meta({
|
|
218
|
+
description: 'Access-control tag. Top-level column (not in `data`). Manage-tier write.',
|
|
219
|
+
}),
|
|
220
|
+
path: CellPath.nullable().optional().meta({ description: 'Admin-only path write.' }),
|
|
221
|
+
acting: ActingActor,
|
|
222
|
+
});
|
|
223
|
+
export const CellUpdateOutput = z.strictObject({ cell: CellJson });
|
|
224
|
+
// -- cell_delete ------------------------------------------------------------
|
|
225
|
+
export const CellDeleteInput = z.strictObject({
|
|
226
|
+
cell_id: Uuid.meta({ description: 'Cell to soft-delete.' }),
|
|
227
|
+
acting: ActingActor,
|
|
228
|
+
});
|
|
229
|
+
export const CellDeleteOutput = z.strictObject({
|
|
230
|
+
ok: z.literal(true),
|
|
231
|
+
deleted: z.boolean(),
|
|
232
|
+
});
|
|
233
|
+
// -- cell_list --------------------------------------------------------------
|
|
234
|
+
/**
|
|
235
|
+
* Input for `cell_list`. Filters are optional and combine with AND. The
|
|
236
|
+
* handler applies the SQL-side visibility predicate from
|
|
237
|
+
* `query_cell_list` so the page-window stays correct under pagination —
|
|
238
|
+
* post-filtering in JS would silently truncate pages.
|
|
239
|
+
*
|
|
240
|
+
* `ids` is the batch-read filter — pass a list of cell ids to fetch them
|
|
241
|
+
* in one round-trip (avoids N+1 when rendering a collection's `items[]`).
|
|
242
|
+
* The visibility predicate still runs, so callers passing ids they can't
|
|
243
|
+
* view simply get fewer rows back. Capped at `CELL_LIST_LIMIT_MAX`.
|
|
244
|
+
*
|
|
245
|
+
* `shared_with: 'me'` narrows to cells that admit the caller via a
|
|
246
|
+
* `cell_grant` row (actor-shaped or role-shaped principal) AND that
|
|
247
|
+
* the caller does not own. Authenticated only; combine with
|
|
248
|
+
* `data_kind` / `path_prefix` etc. to scope further. Combining with
|
|
249
|
+
* `created_by: <my-actor-id>` produces an empty result by definition
|
|
250
|
+
* (owner is implicit, never appears as a grant principal); we don't
|
|
251
|
+
* reject the combination at the schema layer because SQL emptiness is
|
|
252
|
+
* correct.
|
|
253
|
+
*/
|
|
254
|
+
export const CellListInput = z
|
|
255
|
+
.strictObject({
|
|
256
|
+
ids: z
|
|
257
|
+
.array(Uuid)
|
|
258
|
+
.max(CELL_LIST_LIMIT_MAX)
|
|
259
|
+
.optional()
|
|
260
|
+
.meta({ description: 'Batch-fetch by id. Visibility predicate still applies.' }),
|
|
261
|
+
data_kind: z.string().min(1).optional().meta({ description: 'Match `data.kind = ?`.' }),
|
|
262
|
+
visibility: CellVisibility.optional().meta({
|
|
263
|
+
description: "Match `cell.visibility = ?`. The SQL-side auth-narrow already filters to public-or-admitted; this is an additional narrowing filter (e.g. `visibility: 'public'` on the discovery feed so authed callers don't see their own private entries mixed in).",
|
|
264
|
+
}),
|
|
265
|
+
ref: FactHashSchema.optional().meta({ description: 'Match cells referencing this fact hash.' }),
|
|
266
|
+
created_by: Uuid.optional().meta({ description: 'Filter to a specific creator.' }),
|
|
267
|
+
path_prefix: CellPath.optional().meta({
|
|
268
|
+
description: 'Match cells whose path starts with this.',
|
|
269
|
+
}),
|
|
270
|
+
shared_with: z.literal('me').optional().meta({
|
|
271
|
+
description: 'Narrow to cells admitting the caller via `cell_grant`, excluding cells the caller owns. Self-only — a `Uuid` form would need cross-actor role_grant loading.',
|
|
272
|
+
}),
|
|
273
|
+
order_by: z.enum(['created_at', 'updated_at']).optional(),
|
|
274
|
+
order_direction: z.enum(['asc', 'desc']).optional(),
|
|
275
|
+
limit: z.number().int().positive().max(CELL_LIST_LIMIT_MAX).optional(),
|
|
276
|
+
offset: z.number().int().nonnegative().optional(),
|
|
277
|
+
acting: ActingActor,
|
|
278
|
+
})
|
|
279
|
+
.default({});
|
|
280
|
+
export const CellListOutput = z.strictObject({
|
|
281
|
+
cells: z.array(CellJson),
|
|
282
|
+
cell_grants: z.record(z.string(), z.array(GrantJson)).optional(),
|
|
283
|
+
});
|
|
284
|
+
// -- cell_clone -------------------------------------------------------------
|
|
285
|
+
/**
|
|
286
|
+
* Input for `cell_clone`. Source must be view-admitted by `can_view_cell`
|
|
287
|
+
* (404 otherwise — IDOR mask). The clone is owned by the caller; `path`
|
|
288
|
+
* is always nulled (admin-only paths can't auto-clone). Provenance lives
|
|
289
|
+
* only in the `cell_clone` audit row's `source_id` — no provenance
|
|
290
|
+
* fields are stamped into `data`.
|
|
291
|
+
*/
|
|
292
|
+
export const CellCloneInput = z.strictObject({
|
|
293
|
+
source_id: Uuid.meta({ description: 'Cell to clone.' }),
|
|
294
|
+
deep: z.boolean().optional().meta({
|
|
295
|
+
description: 'Recurse into `items[]` (depth=1 — clones direct children only). Default false.',
|
|
296
|
+
}),
|
|
297
|
+
// TODO: cap `with_data_patch` size/depth once a consumer measures the
|
|
298
|
+
// upper bound. `z.json()` is unbounded — a multi-MB patch is in scope
|
|
299
|
+
// today, gated only by the JSON-RPC body limit. Realistic patches are
|
|
300
|
+
// O(few KB); a `.refine` on serialized size would tighten the surface
|
|
301
|
+
// without disturbing the patch-wins-last semantics.
|
|
302
|
+
with_data_patch: CellData.optional().meta({
|
|
303
|
+
description: "Optional shallow patch merged into the new root cell's `data` (patch-last semantics).",
|
|
304
|
+
}),
|
|
305
|
+
acting: ActingActor,
|
|
306
|
+
});
|
|
307
|
+
export const CellCloneOutput = z.strictObject({ cell: CellJson });
|
|
308
|
+
// -- Action specs -----------------------------------------------------------
|
|
309
|
+
export const cell_create_action_spec = {
|
|
310
|
+
method: 'cell_create',
|
|
311
|
+
kind: 'request_response',
|
|
312
|
+
initiator: 'frontend',
|
|
313
|
+
auth: { account: 'required', actor: 'required' },
|
|
314
|
+
side_effects: true,
|
|
315
|
+
input: CellCreateInput,
|
|
316
|
+
output: CellCreateOutput,
|
|
317
|
+
async: true,
|
|
318
|
+
rate_limit: 'account',
|
|
319
|
+
description: 'Create a cell. Handler stamps `created_by` from auth.actor.id; `path` writes are admin-only. Per-account rate-limited to bound write-spam.',
|
|
320
|
+
};
|
|
321
|
+
export const cell_get_action_spec = {
|
|
322
|
+
method: 'cell_get',
|
|
323
|
+
kind: 'request_response',
|
|
324
|
+
initiator: 'frontend',
|
|
325
|
+
auth: { account: 'optional', actor: 'optional' },
|
|
326
|
+
side_effects: false,
|
|
327
|
+
input: CellGetInput,
|
|
328
|
+
output: CellGetOutput,
|
|
329
|
+
async: true,
|
|
330
|
+
rate_limit: 'ip',
|
|
331
|
+
description: 'Fetch a cell by id or path. Per-row authz via `can_view_cell`; unauthed callers get only `cell.visibility === "public"` cells. 404 on miss or unauthorized — no existence leak. Bundled relations are filtered to viewable targets. Per-IP rate-limited as the defense-in-depth complement to `cell_list`: an id-walker that learns ids from a side channel can pivot from the enumeration entry point to per-row reads.',
|
|
332
|
+
};
|
|
333
|
+
export const cell_update_action_spec = {
|
|
334
|
+
method: 'cell_update',
|
|
335
|
+
kind: 'request_response',
|
|
336
|
+
initiator: 'frontend',
|
|
337
|
+
auth: { account: 'required', actor: 'required' },
|
|
338
|
+
side_effects: true,
|
|
339
|
+
input: CellUpdateInput,
|
|
340
|
+
output: CellUpdateOutput,
|
|
341
|
+
async: true,
|
|
342
|
+
description: 'Update a cell. Per-row `can_edit_cell` (admin / owner / editor-grant). `visibility` writes require the manage tier (admin / owner). `path` writes are admin-only. Stamps `updated_by`.',
|
|
343
|
+
};
|
|
344
|
+
export const cell_delete_action_spec = {
|
|
345
|
+
method: 'cell_delete',
|
|
346
|
+
kind: 'request_response',
|
|
347
|
+
initiator: 'frontend',
|
|
348
|
+
auth: { account: 'required', actor: 'required' },
|
|
349
|
+
side_effects: true,
|
|
350
|
+
input: CellDeleteInput,
|
|
351
|
+
output: CellDeleteOutput,
|
|
352
|
+
async: true,
|
|
353
|
+
description: 'Soft-delete a cell. Per-row `can_edit_cell` (admin / owner / editor-grant).',
|
|
354
|
+
};
|
|
355
|
+
export const cell_list_action_spec = {
|
|
356
|
+
method: 'cell_list',
|
|
357
|
+
kind: 'request_response',
|
|
358
|
+
initiator: 'frontend',
|
|
359
|
+
auth: { account: 'optional', actor: 'optional' },
|
|
360
|
+
side_effects: false,
|
|
361
|
+
input: CellListInput,
|
|
362
|
+
output: CellListOutput,
|
|
363
|
+
async: true,
|
|
364
|
+
rate_limit: 'ip',
|
|
365
|
+
description: 'List cells with optional filters. SQL-side visibility predicate: admin sees all; authed see owned + public + grant-admitted; null auth sees public-only. `created_by` filter is rejected for null auth (account-id enumeration guard). Per-IP rate-limited to bound the public-enumeration surface (paired with `actor_lookup` it would be a scrape primitive).',
|
|
366
|
+
};
|
|
367
|
+
export const cell_clone_action_spec = {
|
|
368
|
+
method: 'cell_clone',
|
|
369
|
+
kind: 'request_response',
|
|
370
|
+
initiator: 'frontend',
|
|
371
|
+
auth: { account: 'required', actor: 'required' },
|
|
372
|
+
side_effects: true,
|
|
373
|
+
input: CellCloneInput,
|
|
374
|
+
output: CellCloneOutput,
|
|
375
|
+
async: true,
|
|
376
|
+
rate_limit: 'account',
|
|
377
|
+
description: 'Clone a cell (optionally deep). New owner is the caller; `path` is always nulled. Provenance recorded only in the `cell_clone` audit row. Per-account rate-limited — `deep: true` walks `cell_item` rows and fans out, so unbounded clone is a write-amplification vector.',
|
|
378
|
+
};
|
|
379
|
+
/**
|
|
380
|
+
* All cell-layer action specs — composed by app registries. Bundles the
|
|
381
|
+
* six generic verbs (this module), the three `cell_grant_*` specs, the
|
|
382
|
+
* three `cell_field_*` specs, the four `cell_item_*` specs, and the
|
|
383
|
+
* `cell_audit_list` spec so codegen + UI clients see a single cell
|
|
384
|
+
* namespace.
|
|
385
|
+
*/
|
|
386
|
+
export const all_cell_action_specs = [
|
|
387
|
+
cell_create_action_spec,
|
|
388
|
+
cell_get_action_spec,
|
|
389
|
+
cell_update_action_spec,
|
|
390
|
+
cell_delete_action_spec,
|
|
391
|
+
cell_list_action_spec,
|
|
392
|
+
cell_clone_action_spec,
|
|
393
|
+
...all_cell_grant_action_specs,
|
|
394
|
+
...all_cell_field_action_specs,
|
|
395
|
+
...all_cell_item_action_specs,
|
|
396
|
+
...all_cell_audit_action_specs,
|
|
397
|
+
];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic cell RPC action handlers.
|
|
3
|
+
*
|
|
4
|
+
* Six `request_response` actions bound to the specs in
|
|
5
|
+
* `./cell_action_specs.ts`:
|
|
6
|
+
*
|
|
7
|
+
* - Mutations: `cell_create`, `cell_update`, `cell_delete`, `cell_clone`.
|
|
8
|
+
* - Reads: `cell_get`, `cell_list`.
|
|
9
|
+
*
|
|
10
|
+
* Authorization model:
|
|
11
|
+
*
|
|
12
|
+
* - `cell_create` is authenticated at the spec level. The handler stamps
|
|
13
|
+
* `created_by` from `auth.actor.id`. `path` writes are admin-only —
|
|
14
|
+
* non-admin callers supplying `path` get `ERROR_CELL_PATH_ADMIN_ONLY`.
|
|
15
|
+
* - `cell_get` is `optional` auth at the spec level. Per-row authorization
|
|
16
|
+
* via `can_view_cell(auth, cell)`. Misses + unauthorized reads both 404,
|
|
17
|
+
* so private-cell existence doesn't leak through the wire. Bundled
|
|
18
|
+
* relations are filtered to viewable targets (strict target-visibility).
|
|
19
|
+
* - `cell_update` / `cell_delete` are authenticated at the spec level
|
|
20
|
+
* with per-row `can_edit_cell` enforcement. `path` writes on update
|
|
21
|
+
* are admin-only; `visibility` writes require the manage tier
|
|
22
|
+
* (`can_manage_cell`).
|
|
23
|
+
* - `cell_list` is `optional` auth at the spec level. The SQL-side
|
|
24
|
+
* visibility predicate in `query_cell_list` admits null auth to
|
|
25
|
+
* public-only rows and authed callers to owned + public + grant-admitted
|
|
26
|
+
* rows; admin sees all. SQL-side because post-filtering in JS would
|
|
27
|
+
* silently truncate pages. The handler rejects the `created_by` filter
|
|
28
|
+
* for null auth (account-id enumeration guard).
|
|
29
|
+
*
|
|
30
|
+
* Mutations emit `cell_create` / `cell_update` / `cell_delete` audit
|
|
31
|
+
* events via `deps.audit.emit(...)`. The `AuditLogConfig` threaded through
|
|
32
|
+
* the consumer's `audit_factory` (see `create_app_backend`) must declare
|
|
33
|
+
* the cell event types (see `./cell_audit_metadata.ts`).
|
|
34
|
+
*
|
|
35
|
+
* App vocabulary (e.g., collection / entry kinds) lives in client-side
|
|
36
|
+
* helpers and per-app `validate_data` deps — this layer is generic-only
|
|
37
|
+
* by construction.
|
|
38
|
+
*
|
|
39
|
+
* @module
|
|
40
|
+
*/
|
|
41
|
+
import { type RpcAction } from '../actions/action_rpc.js';
|
|
42
|
+
import type { RouteFactoryDeps } from './deps.js';
|
|
43
|
+
import { type CellJson } from './cell_action_specs.js';
|
|
44
|
+
import { type CellRow } from '../db/cell_queries.js';
|
|
45
|
+
import type { CellData } from './cell_data_schema.js';
|
|
46
|
+
/**
|
|
47
|
+
* Dependencies for `create_cell_actions`.
|
|
48
|
+
*
|
|
49
|
+
* `validate_data` is the optional sub-API hook for per-kind shape
|
|
50
|
+
* validation (e.g., a collection/entry registry). It runs on every
|
|
51
|
+
* incoming `data` payload (create, update, clone-merged) and may throw
|
|
52
|
+
* a `ZodError` — the handler converts that into the standard
|
|
53
|
+
* `invalid_params` JSON-RPC error so per-kind validation failures
|
|
54
|
+
* surface to clients with code -32602 (not -32603 / internal). When
|
|
55
|
+
* omitted, payloads pass through as-is.
|
|
56
|
+
*/
|
|
57
|
+
export type CellActionDeps = Pick<RouteFactoryDeps, 'log' | 'audit'> & {
|
|
58
|
+
validate_data?: (data: CellData) => CellData;
|
|
59
|
+
};
|
|
60
|
+
export declare const to_cell_json: (row: CellRow) => CellJson;
|
|
61
|
+
/** Create the six generic cell RPC actions. */
|
|
62
|
+
export declare const create_cell_actions: (deps: CellActionDeps) => Array<RpcAction>;
|
|
63
|
+
//# sourceMappingURL=cell_actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cell_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAIH,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAGhD,OAAO,EA6BN,KAAK,QAAQ,EAEb,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAQN,KAAK,OAAO,EACZ,MAAM,uBAAuB,CAAC;AAkB/B,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,OAAO,CAAC,GAAG;IACtE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC;CAC7C,CAAC;AAgBF,eAAO,MAAM,YAAY,GAAI,KAAK,OAAO,KAAG,QAY1C,CAAC;AA2BH,+CAA+C;AAC/C,eAAO,MAAM,mBAAmB,GAAI,MAAM,cAAc,KAAG,KAAK,CAAC,SAAS,CA4ezE,CAAC"}
|