@fuzdev/fuz_app 0.148.0 → 0.150.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 +11 -9
- package/dist/actions/action_bridge.d.ts +7 -0
- package/dist/actions/action_bridge.d.ts.map +1 -1
- package/dist/actions/action_bridge.js +10 -0
- package/dist/actions/action_event.d.ts.map +1 -1
- package/dist/actions/action_event.js +14 -1
- package/dist/actions/action_event_types.d.ts +1 -1
- package/dist/actions/action_event_types.d.ts.map +1 -1
- package/dist/actions/perform_action.d.ts +17 -1
- package/dist/actions/perform_action.d.ts.map +1 -1
- package/dist/actions/perform_action.js +30 -7
- package/dist/actions/register_action_ws.d.ts +8 -2
- package/dist/actions/register_action_ws.d.ts.map +1 -1
- package/dist/actions/register_action_ws.js +24 -4
- package/dist/actions/transports_ws_auth_guard.d.ts +6 -4
- package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
- package/dist/actions/transports_ws_auth_guard.js +9 -6
- package/dist/actions/ws_endpoint_spec.d.ts +1 -1
- package/dist/auth/CLAUDE.md +72 -33
- package/dist/auth/account_action_specs.d.ts +12 -0
- package/dist/auth/account_action_specs.d.ts.map +1 -1
- package/dist/auth/account_action_specs.js +16 -2
- package/dist/auth/account_actions.d.ts.map +1 -1
- package/dist/auth/account_actions.js +7 -4
- package/dist/auth/actor_lookup_queries.d.ts +3 -2
- package/dist/auth/actor_lookup_queries.d.ts.map +1 -1
- package/dist/auth/actor_lookup_queries.js +6 -3
- package/dist/auth/actor_search_queries.d.ts +5 -2
- package/dist/auth/actor_search_queries.d.ts.map +1 -1
- package/dist/auth/actor_search_queries.js +11 -4
- package/dist/auth/admin_action_specs.d.ts +4 -4
- package/dist/auth/admin_action_specs.d.ts.map +1 -1
- package/dist/auth/admin_action_specs.js +33 -12
- package/dist/auth/admin_actions.d.ts.map +1 -1
- package/dist/auth/admin_actions.js +35 -6
- package/dist/auth/all_cell_actions.d.ts +11 -2
- package/dist/auth/all_cell_actions.d.ts.map +1 -1
- package/dist/auth/all_cell_actions.js +2 -1
- package/dist/auth/audit_emitter.d.ts +23 -3
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +14 -4
- package/dist/auth/audit_log_schema.d.ts +1 -0
- package/dist/auth/audit_log_schema.d.ts.map +1 -1
- package/dist/auth/audit_log_schema.js +9 -5
- package/dist/auth/bootstrap_account.d.ts +25 -1
- package/dist/auth/bootstrap_account.d.ts.map +1 -1
- package/dist/auth/bootstrap_account.js +37 -4
- package/dist/auth/bootstrap_routes.d.ts +3 -2
- package/dist/auth/bootstrap_routes.d.ts.map +1 -1
- package/dist/auth/bootstrap_routes.js +5 -4
- package/dist/auth/cell_action_specs.d.ts +215 -15
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +103 -16
- package/dist/auth/cell_actions.d.ts +40 -18
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +126 -19
- package/dist/auth/cell_audit_events.d.ts +1 -1
- package/dist/auth/cell_audit_events.d.ts.map +1 -1
- package/dist/auth/cell_audit_events.js +3 -2
- package/dist/auth/cell_audit_metadata.d.ts +11 -0
- package/dist/auth/cell_audit_metadata.d.ts.map +1 -1
- package/dist/auth/cell_audit_metadata.js +10 -0
- package/dist/auth/cell_grant_action_specs.d.ts +7 -0
- package/dist/auth/cell_grant_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_grant_action_specs.js +7 -0
- package/dist/auth/cell_grant_actions.d.ts +36 -4
- package/dist/auth/cell_grant_actions.d.ts.map +1 -1
- package/dist/auth/cell_grant_actions.js +20 -3
- package/dist/auth/credential_type_schema.d.ts +3 -2
- package/dist/auth/credential_type_schema.d.ts.map +1 -1
- package/dist/auth/credential_type_schema.js +3 -2
- package/dist/auth/role_grant_offer_action_specs.d.ts +18 -2
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +30 -6
- package/dist/auth/role_grant_offer_actions.d.ts +9 -4
- package/dist/auth/role_grant_offer_actions.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_actions.js +58 -7
- package/dist/auth/role_grant_offer_notifications.d.ts +3 -2
- package/dist/auth/role_grant_offer_notifications.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_notifications.js +3 -2
- package/dist/auth/role_grant_offer_queries.d.ts +20 -0
- package/dist/auth/role_grant_offer_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_queries.js +35 -0
- package/dist/auth/role_grant_queries.d.ts +27 -9
- package/dist/auth/role_grant_queries.d.ts.map +1 -1
- package/dist/auth/role_grant_queries.js +40 -13
- package/dist/auth/role_schema.d.ts +14 -8
- package/dist/auth/role_schema.d.ts.map +1 -1
- package/dist/auth/role_schema.js +6 -3
- package/dist/auth/self_service_role_actions.d.ts.map +1 -1
- package/dist/auth/self_service_role_actions.js +20 -0
- package/dist/db/CLAUDE.md +9 -2
- package/dist/db/cell_ddl.d.ts +9 -1
- package/dist/db/cell_ddl.d.ts.map +1 -1
- package/dist/db/cell_ddl.js +11 -1
- package/dist/db/cell_queries.d.ts +53 -7
- package/dist/db/cell_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.js +61 -7
- package/dist/http/CLAUDE.md +14 -2
- package/dist/http/body_limit.d.ts +3 -1
- package/dist/http/body_limit.d.ts.map +1 -1
- package/dist/http/body_limit.js +6 -1
- package/dist/http/error_schemas.d.ts +8 -0
- package/dist/http/error_schemas.d.ts.map +1 -1
- package/dist/http/error_schemas.js +12 -0
- package/dist/http/jsonrpc.d.ts +9 -0
- package/dist/http/jsonrpc.d.ts.map +1 -1
- package/dist/http/jsonrpc.js +17 -0
- package/dist/http/jsonrpc_errors.d.ts +40 -15
- package/dist/http/jsonrpc_errors.d.ts.map +1 -1
- package/dist/http/jsonrpc_errors.js +99 -35
- package/dist/http/proxy.d.ts +4 -2
- package/dist/http/proxy.d.ts.map +1 -1
- package/dist/http/proxy.js +7 -2
- package/dist/http/surface.d.ts +3 -1
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +7 -4
- package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
- package/dist/realtime/sse_auth_guard.js +3 -2
- package/dist/schema_meta.d.ts +92 -1
- package/dist/schema_meta.d.ts.map +1 -1
- package/dist/schema_meta.js +117 -0
- package/dist/server/app_server.d.ts +13 -5
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +32 -8
- package/dist/testing/CLAUDE.md +196 -82
- package/dist/testing/adversarial_input_cases.d.ts +67 -7
- package/dist/testing/adversarial_input_cases.d.ts.map +1 -1
- package/dist/testing/adversarial_input_cases.js +210 -165
- package/dist/testing/app_server.d.ts +3 -1
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.d.ts +3 -2
- package/dist/testing/audit_drift_guard.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.js +5 -3
- package/dist/testing/cross_backend/actor_lookup.d.ts.map +1 -1
- package/dist/testing/cross_backend/actor_lookup.js +27 -0
- package/dist/testing/cross_backend/audit_cross_helpers.d.ts +6 -0
- package/dist/testing/cross_backend/audit_cross_helpers.d.ts.map +1 -1
- package/dist/testing/cross_backend/audit_cross_helpers.js +11 -0
- package/dist/testing/cross_backend/capabilities.d.ts +29 -5
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +10 -6
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +117 -2
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +109 -13
- package/dist/testing/cross_backend/cell_moderate.d.ts +7 -1
- package/dist/testing/cross_backend/cell_moderate.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_moderate.js +68 -4
- package/dist/testing/cross_backend/cell_ref_admission.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_ref_admission.js +18 -9
- package/dist/testing/cross_backend/conformance_table.d.ts +5 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +12 -10
- package/dist/testing/cross_backend/cross_rpc.d.ts +3 -1
- package/dist/testing/cross_backend/cross_rpc.d.ts.map +1 -1
- package/dist/testing/cross_backend/cross_rpc.js +2 -2
- package/dist/testing/cross_backend/default_backend_configs.d.ts +9 -7
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +3 -3
- package/dist/testing/cross_backend/differential.d.ts +7 -0
- package/dist/testing/cross_backend/differential.d.ts.map +1 -1
- package/dist/testing/cross_backend/differential.js +17 -0
- package/dist/testing/cross_backend/expected_schema.json +1 -0
- package/dist/testing/cross_backend/full_spine_mount.d.ts.map +1 -1
- package/dist/testing/cross_backend/full_spine_mount.js +5 -4
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.d.ts.map +1 -1
- package/dist/testing/cross_backend/role_grant_offer_lifecycle.js +74 -2
- package/dist/testing/cross_backend/rpc_adversarial.d.ts +9 -0
- package/dist/testing/cross_backend/rpc_adversarial.d.ts.map +1 -1
- package/dist/testing/cross_backend/rpc_adversarial.js +16 -6
- package/dist/testing/cross_backend/rust_spine_consumer_surface.d.ts +1 -1
- 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 -3
- package/dist/testing/cross_backend/setup.d.ts +2 -2
- package/dist/testing/cross_backend/spine_suites.d.ts +85 -5
- package/dist/testing/cross_backend/spine_suites.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_suites.js +291 -20
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +15 -0
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +24 -0
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts +18 -19
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.d.ts.map +1 -1
- package/dist/testing/cross_backend/test_cell_gated_create_authorize.js +66 -42
- package/dist/testing/cross_backend/testing_backdoor.d.ts +27 -4
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +136 -41
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +30 -15
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +52 -35
- package/dist/testing/cross_backend/transport_composition.js +3 -3
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +6 -3
- package/dist/testing/rpc_attack_surface.d.ts +10 -0
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
- package/dist/testing/rpc_attack_surface.js +15 -3
- package/dist/testing/rpc_envelope_cases.d.ts +5 -2
- package/dist/testing/rpc_envelope_cases.d.ts.map +1 -1
- package/dist/testing/rpc_envelope_cases.js +4 -1
- package/dist/testing/rpc_round_trip.js +3 -3
- package/dist/testing/schema_generators.d.ts +99 -2
- package/dist/testing/schema_generators.d.ts.map +1 -1
- package/dist/testing/schema_generators.js +244 -76
- package/dist/testing/stubs.d.ts +4 -3
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +6 -4
- package/dist/zod.d.ts +9 -0
- package/dist/zod.d.ts.map +1 -1
- package/dist/zod.js +20 -0
- package/package.json +1 -1
package/dist/schema_meta.d.ts
CHANGED
|
@@ -11,7 +11,11 @@ import type { Sensitivity } from './sensitivity.js';
|
|
|
11
11
|
/** Zod `.meta()` shape for fuz_app schema metadata conventions. */
|
|
12
12
|
export interface SchemaFieldMeta {
|
|
13
13
|
description?: string;
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Sensitivity level for masking/redaction. `'secret'` masks the value.
|
|
16
|
+
* Read through every wrapping layer (`schema_sensitivity`), so
|
|
17
|
+
* `.meta({sensitivity: 'secret'}).optional()` masks too.
|
|
18
|
+
*/
|
|
15
19
|
sensitivity?: Sensitivity;
|
|
16
20
|
/**
|
|
17
21
|
* Set on an action's **input** schema that accepts `{}` by design while
|
|
@@ -25,6 +29,29 @@ export interface SchemaFieldMeta {
|
|
|
25
29
|
* schema itself, so a wrapper (`.optional()`, `.extend()`) drops it.
|
|
26
30
|
*/
|
|
27
31
|
empty_input_handler_guarded?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* The `error.data.reason` an action input refuses this field with. On a
|
|
34
|
+
* field of an action's **input** schema, every `invalid_params` whose first
|
|
35
|
+
* Zod issue lands on the field — missing, wrong type, `null`, out of range,
|
|
36
|
+
* malformed, or a fault anywhere inside it — carries this reason, where an
|
|
37
|
+
* undeclared field's refusal carries none. The message stays the generic
|
|
38
|
+
* `invalid params`. A body with faults on several fields answers the first
|
|
39
|
+
* issue's reason in Zod's order, which a twin checking in another order
|
|
40
|
+
* need not match, so the reason is defined for a single-fault body only —
|
|
41
|
+
* except that an issue on the input itself (an unknown key) anywhere among
|
|
42
|
+
* the issues means no reason, as the Rust twin refuses unknown keys first.
|
|
43
|
+
* Declared reasons are named `<field>_invalid`.
|
|
44
|
+
*
|
|
45
|
+
* The declaration is the one source of the reason: the dispatcher reads it
|
|
46
|
+
* (`perform_action`), the adversarial suites expect it, and the Rust twin
|
|
47
|
+
* owes the same reason on every refusal of the field. Read through the
|
|
48
|
+
* field's optional, nullable, default, prefault, transform and pipe layers
|
|
49
|
+
* (not `.readonly()`, `.catch()` or `z.lazy()`), so it may sit on any of
|
|
50
|
+
* them; a declaration on a nested field overrides its parent's for a fault
|
|
51
|
+
* inside it, and an object-level refine whose issue names the field takes
|
|
52
|
+
* its reason too. See `resolve_issues_invalid_reason`.
|
|
53
|
+
*/
|
|
54
|
+
invalid_reason?: string;
|
|
28
55
|
}
|
|
29
56
|
/**
|
|
30
57
|
* Whether `schema` carries `empty_input_handler_guarded: true` in its `.meta()`.
|
|
@@ -33,4 +60,68 @@ export interface SchemaFieldMeta {
|
|
|
33
60
|
* @returns whether its handler refuses the `{}` the schema admits
|
|
34
61
|
*/
|
|
35
62
|
export declare const is_empty_input_handler_guarded: (schema: z.ZodType) => boolean;
|
|
63
|
+
/**
|
|
64
|
+
* A `SchemaFieldMeta` key's value as a schema declares it, read through its
|
|
65
|
+
* optional, nullable, default, prefault, transform and pipe layers — Zod
|
|
66
|
+
* keeps `.meta()` on the instance it was set on, so a wrapper added after it
|
|
67
|
+
* carries none — the outermost declaration winning.
|
|
68
|
+
*
|
|
69
|
+
* @param schema - a field schema, possibly wrapped
|
|
70
|
+
* @param key - the metadata key to read
|
|
71
|
+
* @returns the declared value, or `undefined` when no layer declares one
|
|
72
|
+
*/
|
|
73
|
+
export declare const schema_meta_value: <TKey extends keyof SchemaFieldMeta>(schema: z.ZodType, key: TKey) => SchemaFieldMeta[TKey] | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* The `invalid_reason` a schema declares, read through its wrappers, the
|
|
76
|
+
* outermost declaration winning.
|
|
77
|
+
*
|
|
78
|
+
* @param schema - a field schema, possibly wrapped
|
|
79
|
+
* @returns the declared reason, or `undefined` when no layer declares one
|
|
80
|
+
*/
|
|
81
|
+
export declare const schema_invalid_reason: (schema: z.ZodType) => string | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* The `sensitivity` a schema declares anywhere among its wrapping layers, so
|
|
84
|
+
* a secret stays masked however the field is wrapped. Fail-safe where
|
|
85
|
+
* `schema_meta_value` reads one chain: the walk follows the `innerType` of
|
|
86
|
+
* every wrapper that has one (optional, nullable, default, prefault,
|
|
87
|
+
* nonoptional, catch, readonly), both sides of a pipe (so `.transform()`,
|
|
88
|
+
* `z.preprocess()` and `.pipe(secret)` all reach the secret), and a
|
|
89
|
+
* `z.lazy()` getter, and every member of a union or intersection (the
|
|
90
|
+
* value is one of them), visiting each schema once, and answers `'secret'`
|
|
91
|
+
* when any layer reached declares it. It stops at structural schemas — an
|
|
92
|
+
* object's fields and an array's element carry their own.
|
|
93
|
+
*
|
|
94
|
+
* @param schema - a field schema, possibly wrapped
|
|
95
|
+
* @returns `'secret'` when any reachable layer declares it, else `undefined`
|
|
96
|
+
*/
|
|
97
|
+
export declare const schema_sensitivity: (schema: z.ZodType) => Sensitivity | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* The `error.data.reason` an input validation failure at `path` carries: the
|
|
100
|
+
* `invalid_reason` of the deepest field along `path` that declares one.
|
|
101
|
+
*
|
|
102
|
+
* Walks object fields only, each through its wrappers: a segment that is not
|
|
103
|
+
* a key of an object schema (an array index, a union member's key, an unknown
|
|
104
|
+
* key) ends the walk, so a fault inside a declared field still resolves to
|
|
105
|
+
* that field's reason. An empty path — a whole-input fault such as an
|
|
106
|
+
* unrecognized key on the input object — resolves to none, as does a schema
|
|
107
|
+
* that is not an object.
|
|
108
|
+
*
|
|
109
|
+
* @param input_schema - an action's input schema
|
|
110
|
+
* @param path - the failing issue's path (`ZodError.issues[0].path`)
|
|
111
|
+
* @returns the declared reason, or `undefined`
|
|
112
|
+
*/
|
|
113
|
+
export declare const resolve_invalid_reason: (input_schema: z.ZodType, path: ReadonlyArray<PropertyKey>) => string | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* The `error.data.reason` a failed input parse answers: the declared reason
|
|
116
|
+
* of the first issue's field (`resolve_invalid_reason`), or none when any
|
|
117
|
+
* issue sits on the input itself. Such an issue is an unknown key on the
|
|
118
|
+
* input object (or a non-object input), which the Rust twin refuses before
|
|
119
|
+
* reading any field, so a stale client sending an extra key gets the same
|
|
120
|
+
* answer from both spines whatever else its body gets wrong.
|
|
121
|
+
*
|
|
122
|
+
* @param input_schema - an action's input schema
|
|
123
|
+
* @param issues - the failed parse's issues, in Zod's order
|
|
124
|
+
* @returns the declared reason, or `undefined`
|
|
125
|
+
*/
|
|
126
|
+
export declare const resolve_issues_invalid_reason: (input_schema: z.ZodType, issues: ReadonlyArray<z.core.$ZodIssue>) => string | undefined;
|
|
36
127
|
//# sourceMappingURL=schema_meta.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema_meta.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/schema_meta.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"schema_meta.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/schema_meta.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;;;;;;OAUG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OACkB,CAAC;AAEtF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,IAAI,SAAS,MAAM,eAAe,EACnE,QAAQ,CAAC,CAAC,OAAO,EACjB,KAAK,IAAI,KACP,eAAe,CAAC,IAAI,CAAC,GAAG,SAM1B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,MAAM,GAAG,SACvB,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,WAAW,GAAG,SAuBpE,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sBAAsB,GAClC,cAAc,CAAC,CAAC,OAAO,EACvB,MAAM,aAAa,CAAC,WAAW,CAAC,KAC9B,MAAM,GAAG,SAYX,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,6BAA6B,GACzC,cAAc,CAAC,CAAC,OAAO,EACvB,QAAQ,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KACrC,MAAM,GAAG,SAIX,CAAC"}
|
package/dist/schema_meta.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
+
import { zod_get_schema_layers, zod_unwrap_to_object } from './zod.js';
|
|
9
10
|
/**
|
|
10
11
|
* Whether `schema` carries `empty_input_handler_guarded: true` in its `.meta()`.
|
|
11
12
|
*
|
|
@@ -13,3 +14,119 @@
|
|
|
13
14
|
* @returns whether its handler refuses the `{}` the schema admits
|
|
14
15
|
*/
|
|
15
16
|
export const is_empty_input_handler_guarded = (schema) => schema.meta()?.empty_input_handler_guarded === true;
|
|
17
|
+
/**
|
|
18
|
+
* A `SchemaFieldMeta` key's value as a schema declares it, read through its
|
|
19
|
+
* optional, nullable, default, prefault, transform and pipe layers — Zod
|
|
20
|
+
* keeps `.meta()` on the instance it was set on, so a wrapper added after it
|
|
21
|
+
* carries none — the outermost declaration winning.
|
|
22
|
+
*
|
|
23
|
+
* @param schema - a field schema, possibly wrapped
|
|
24
|
+
* @param key - the metadata key to read
|
|
25
|
+
* @returns the declared value, or `undefined` when no layer declares one
|
|
26
|
+
*/
|
|
27
|
+
export const schema_meta_value = (schema, key) => {
|
|
28
|
+
for (const layer of zod_get_schema_layers(schema)) {
|
|
29
|
+
const value = layer.meta()?.[key];
|
|
30
|
+
if (value !== undefined)
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The `invalid_reason` a schema declares, read through its wrappers, the
|
|
37
|
+
* outermost declaration winning.
|
|
38
|
+
*
|
|
39
|
+
* @param schema - a field schema, possibly wrapped
|
|
40
|
+
* @returns the declared reason, or `undefined` when no layer declares one
|
|
41
|
+
*/
|
|
42
|
+
export const schema_invalid_reason = (schema) => schema_meta_value(schema, 'invalid_reason');
|
|
43
|
+
/**
|
|
44
|
+
* The `sensitivity` a schema declares anywhere among its wrapping layers, so
|
|
45
|
+
* a secret stays masked however the field is wrapped. Fail-safe where
|
|
46
|
+
* `schema_meta_value` reads one chain: the walk follows the `innerType` of
|
|
47
|
+
* every wrapper that has one (optional, nullable, default, prefault,
|
|
48
|
+
* nonoptional, catch, readonly), both sides of a pipe (so `.transform()`,
|
|
49
|
+
* `z.preprocess()` and `.pipe(secret)` all reach the secret), and a
|
|
50
|
+
* `z.lazy()` getter, and every member of a union or intersection (the
|
|
51
|
+
* value is one of them), visiting each schema once, and answers `'secret'`
|
|
52
|
+
* when any layer reached declares it. It stops at structural schemas — an
|
|
53
|
+
* object's fields and an array's element carry their own.
|
|
54
|
+
*
|
|
55
|
+
* @param schema - a field schema, possibly wrapped
|
|
56
|
+
* @returns `'secret'` when any reachable layer declares it, else `undefined`
|
|
57
|
+
*/
|
|
58
|
+
export const schema_sensitivity = (schema) => {
|
|
59
|
+
const seen = new Set();
|
|
60
|
+
const pending = [schema];
|
|
61
|
+
while (pending.length > 0) {
|
|
62
|
+
const layer = pending.pop();
|
|
63
|
+
if (seen.has(layer))
|
|
64
|
+
continue;
|
|
65
|
+
seen.add(layer);
|
|
66
|
+
if (layer.meta()?.sensitivity === 'secret')
|
|
67
|
+
return 'secret';
|
|
68
|
+
const def = layer.def;
|
|
69
|
+
if (def.type === 'lazy') {
|
|
70
|
+
pending.push(layer._zod.innerType);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (def.type === 'union' && Array.isArray(def.options)) {
|
|
74
|
+
pending.push(...def.options);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
for (const key of ['innerType', 'in', 'out', 'left', 'right']) {
|
|
78
|
+
const sub = def[key];
|
|
79
|
+
if (sub && typeof sub === 'object' && 'def' in sub)
|
|
80
|
+
pending.push(sub);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* The `error.data.reason` an input validation failure at `path` carries: the
|
|
87
|
+
* `invalid_reason` of the deepest field along `path` that declares one.
|
|
88
|
+
*
|
|
89
|
+
* Walks object fields only, each through its wrappers: a segment that is not
|
|
90
|
+
* a key of an object schema (an array index, a union member's key, an unknown
|
|
91
|
+
* key) ends the walk, so a fault inside a declared field still resolves to
|
|
92
|
+
* that field's reason. An empty path — a whole-input fault such as an
|
|
93
|
+
* unrecognized key on the input object — resolves to none, as does a schema
|
|
94
|
+
* that is not an object.
|
|
95
|
+
*
|
|
96
|
+
* @param input_schema - an action's input schema
|
|
97
|
+
* @param path - the failing issue's path (`ZodError.issues[0].path`)
|
|
98
|
+
* @returns the declared reason, or `undefined`
|
|
99
|
+
*/
|
|
100
|
+
export const resolve_invalid_reason = (input_schema, path) => {
|
|
101
|
+
let reason;
|
|
102
|
+
let schema = input_schema;
|
|
103
|
+
for (const segment of path) {
|
|
104
|
+
if (typeof segment !== 'string')
|
|
105
|
+
break;
|
|
106
|
+
const shape = zod_unwrap_to_object(schema)?.shape;
|
|
107
|
+
if (!shape || !Object.hasOwn(shape, segment))
|
|
108
|
+
break;
|
|
109
|
+
const field = shape[segment];
|
|
110
|
+
reason = schema_invalid_reason(field) ?? reason;
|
|
111
|
+
schema = field;
|
|
112
|
+
}
|
|
113
|
+
return reason;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* The `error.data.reason` a failed input parse answers: the declared reason
|
|
117
|
+
* of the first issue's field (`resolve_invalid_reason`), or none when any
|
|
118
|
+
* issue sits on the input itself. Such an issue is an unknown key on the
|
|
119
|
+
* input object (or a non-object input), which the Rust twin refuses before
|
|
120
|
+
* reading any field, so a stale client sending an extra key gets the same
|
|
121
|
+
* answer from both spines whatever else its body gets wrong.
|
|
122
|
+
*
|
|
123
|
+
* @param input_schema - an action's input schema
|
|
124
|
+
* @param issues - the failed parse's issues, in Zod's order
|
|
125
|
+
* @returns the declared reason, or `undefined`
|
|
126
|
+
*/
|
|
127
|
+
export const resolve_issues_invalid_reason = (input_schema, issues) => {
|
|
128
|
+
const first = issues[0];
|
|
129
|
+
if (!first || issues.some((issue) => issue.path.length === 0))
|
|
130
|
+
return undefined;
|
|
131
|
+
return resolve_invalid_reason(input_schema, first.path);
|
|
132
|
+
};
|
|
@@ -88,7 +88,10 @@ export interface AppServerOptions {
|
|
|
88
88
|
backend: AppBackend;
|
|
89
89
|
/** Session options for cookie-based auth. */
|
|
90
90
|
session_options: SessionOptions<string>;
|
|
91
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Parsed allowed origin patterns. Must not be empty — an empty list would
|
|
93
|
+
* refuse every browser request, so assembly throws.
|
|
94
|
+
*/
|
|
92
95
|
allowed_origins: Array<RegExp>;
|
|
93
96
|
/**
|
|
94
97
|
* Paths the origin check skips, each with its reason. The check covers
|
|
@@ -188,9 +191,11 @@ export interface AppServerOptions {
|
|
|
188
191
|
*/
|
|
189
192
|
action_account_rate_limiter?: RateLimiter | null;
|
|
190
193
|
/**
|
|
191
|
-
* Maximum allowed request body size in bytes
|
|
192
|
-
* Omit or `undefined` to use the
|
|
193
|
-
* Pass `null` to explicitly disable body size limiting
|
|
194
|
+
* Maximum allowed request body size in bytes, a safe integer `0` or more
|
|
195
|
+
* (anything else throws at assembly). Omit or `undefined` to use the
|
|
196
|
+
* default (1 MiB). Pass `null` to explicitly disable body size limiting,
|
|
197
|
+
* which adds a security warning to the surface's diagnostics (logged at
|
|
198
|
+
* startup).
|
|
194
199
|
*/
|
|
195
200
|
max_body_size?: number | null;
|
|
196
201
|
/** Daemon token state for keeper auth. Omit to disable. */
|
|
@@ -583,13 +588,16 @@ export interface ConfigDiagnosticsInput {
|
|
|
583
588
|
rate_limiter_mode: RateLimiterMode;
|
|
584
589
|
/** The resolved limiters, from `resolve_rate_limiters`. */
|
|
585
590
|
rate_limiters: Record<AppServerRateLimiterKey, RateLimiter | null>;
|
|
591
|
+
/** `AppServerOptions.max_body_size` as passed; `null` disables the body size limit. */
|
|
592
|
+
max_body_size: number | null | undefined;
|
|
586
593
|
}
|
|
587
594
|
/**
|
|
588
595
|
* The config-level diagnostics `create_app_server` appends to the surface's
|
|
589
596
|
* spec-level ones: a weakened session cookie, and an open rate-limited
|
|
590
597
|
* surface — one warning for `'disabled_for_testing'`, otherwise one per
|
|
591
598
|
* explicitly-null limiter, so a deployment that disables login's limiter but
|
|
592
|
-
* keeps signup's reads differently from one that disables both
|
|
599
|
+
* keeps signup's reads differently from one that disables both — and a
|
|
600
|
+
* disabled request body size limit (`max_body_size: null`).
|
|
593
601
|
*
|
|
594
602
|
* @internal
|
|
595
603
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"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"}
|
|
@@ -126,7 +126,8 @@ export const resolve_rate_limiters = (options) => {
|
|
|
126
126
|
* spec-level ones: a weakened session cookie, and an open rate-limited
|
|
127
127
|
* surface — one warning for `'disabled_for_testing'`, otherwise one per
|
|
128
128
|
* explicitly-null limiter, so a deployment that disables login's limiter but
|
|
129
|
-
* keeps signup's reads differently from one that disables both
|
|
129
|
+
* keeps signup's reads differently from one that disables both — and a
|
|
130
|
+
* disabled request body size limit (`max_body_size: null`).
|
|
130
131
|
*
|
|
131
132
|
* @internal
|
|
132
133
|
*/
|
|
@@ -176,6 +177,14 @@ export const collect_config_diagnostics = (input) => {
|
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
179
|
}
|
|
180
|
+
if (input.max_body_size === null) {
|
|
181
|
+
diagnostics.push({
|
|
182
|
+
level: 'warning',
|
|
183
|
+
category: 'security',
|
|
184
|
+
message: 'request body size limit explicitly disabled (max_body_size: null) — ' +
|
|
185
|
+
'every route must cap its own body'
|
|
186
|
+
});
|
|
187
|
+
}
|
|
179
188
|
return diagnostics;
|
|
180
189
|
};
|
|
181
190
|
/**
|
|
@@ -249,6 +258,16 @@ const assemble_app_server = async (options, releases) => {
|
|
|
249
258
|
const { backend } = options;
|
|
250
259
|
const { deps } = backend;
|
|
251
260
|
const { log } = deps;
|
|
261
|
+
// option checks first, before anything is acquired
|
|
262
|
+
if (options.allowed_origins.length === 0) {
|
|
263
|
+
throw new Error('create_app_server: allowed_origins is empty — list at least one origin pattern ' +
|
|
264
|
+
'(an empty list refuses every browser request)');
|
|
265
|
+
}
|
|
266
|
+
// body size limit — rejects oversized payloads before auth/validation; the
|
|
267
|
+
// middleware throws on a cap that is not a safe integer 0 or more
|
|
268
|
+
const body_limit_middleware = options.max_body_size === null
|
|
269
|
+
? null
|
|
270
|
+
: create_body_limit_middleware(options.max_body_size ?? DEFAULT_MAX_BODY_SIZE);
|
|
252
271
|
// Rate limiters — the ones built here are the server's to dispose, on
|
|
253
272
|
// close or when assembly fails.
|
|
254
273
|
const { mode: rate_limiter_mode, limiters: rate_limiters, built: built_rate_limiters } = resolve_rate_limiters(options);
|
|
@@ -392,7 +411,8 @@ const assemble_app_server = async (options, releases) => {
|
|
|
392
411
|
// WS path checks — pure data, so they run before anything mounts.
|
|
393
412
|
// `register_ws_endpoint` mounts a `GET path` upgrade route: a duplicate
|
|
394
413
|
// path, or one a `RouteSpec` already registered as `GET path`, would be
|
|
395
|
-
// silently shadowed by Hono's last-wins semantics — fail fast instead.
|
|
414
|
+
// silently shadowed by Hono's last-wins semantics — fail fast instead. An
|
|
415
|
+
// endpoint's own empty `allowed_origins` would refuse every browser upgrade.
|
|
396
416
|
if (ws_mount) {
|
|
397
417
|
const route_spec_get_paths = new Set();
|
|
398
418
|
for (const r of route_specs) {
|
|
@@ -407,6 +427,11 @@ const assemble_app_server = async (options, releases) => {
|
|
|
407
427
|
if (route_spec_get_paths.has(endpoint.path)) {
|
|
408
428
|
throw new Error(`create_app_server: ws_endpoints path collides with a GET RouteSpec: ${endpoint.path}`);
|
|
409
429
|
}
|
|
430
|
+
if (endpoint.allowed_origins.length === 0) {
|
|
431
|
+
throw new Error(`create_app_server: ws_endpoints allowed_origins is empty for ${endpoint.path} — ` +
|
|
432
|
+
'list at least one origin pattern, or omit it to take the server list ' +
|
|
433
|
+
'(an empty list refuses every browser upgrade)');
|
|
434
|
+
}
|
|
410
435
|
seen_paths.add(endpoint.path);
|
|
411
436
|
}
|
|
412
437
|
}
|
|
@@ -430,7 +455,8 @@ const assemble_app_server = async (options, releases) => {
|
|
|
430
455
|
const config_diagnostics = collect_config_diagnostics({
|
|
431
456
|
cookie_options: options.session_options.cookie_options,
|
|
432
457
|
rate_limiter_mode,
|
|
433
|
-
rate_limiters
|
|
458
|
+
rate_limiters,
|
|
459
|
+
max_body_size: options.max_body_size
|
|
434
460
|
});
|
|
435
461
|
if (config_diagnostics.length) {
|
|
436
462
|
surface_spec.surface.diagnostics = [...surface_spec.surface.diagnostics, ...config_diagnostics];
|
|
@@ -483,11 +509,9 @@ const assemble_app_server = async (options, releases) => {
|
|
|
483
509
|
if (log.level !== 'off') {
|
|
484
510
|
app.use(logger((msg) => log.info(msg)));
|
|
485
511
|
}
|
|
486
|
-
//
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
const max_size = options.max_body_size ?? DEFAULT_MAX_BODY_SIZE;
|
|
490
|
-
app.use(create_body_limit_middleware(max_size));
|
|
512
|
+
// body size limit, built with the option checks above
|
|
513
|
+
if (body_limit_middleware) {
|
|
514
|
+
app.use(body_limit_middleware);
|
|
491
515
|
}
|
|
492
516
|
apply_middleware_specs(app, middleware_specs);
|
|
493
517
|
const authorize = create_fuz_authorization_handler({ db: deps.db });
|