@fuzdev/fuz_app 0.135.0 → 0.136.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 +2 -2
- package/dist/actions/transports_ws_backend.d.ts +1 -1
- package/dist/actions/transports_ws_backend.js +1 -1
- package/dist/auth/CLAUDE.md +8 -2
- package/dist/auth/account_action_specs.d.ts +7 -0
- package/dist/auth/account_action_specs.d.ts.map +1 -1
- package/dist/auth/account_action_specs.js +11 -1
- package/dist/auth/audit_emitter.d.ts +4 -0
- package/dist/auth/audit_emitter.d.ts.map +1 -1
- package/dist/auth/audit_emitter.js +18 -2
- package/dist/auth/cell_action_specs.d.ts +10 -0
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +17 -3
- package/dist/auth/role_grant_offer_action_specs.d.ts.map +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +7 -2
- package/dist/auth/scope_kind_schema.d.ts +10 -0
- package/dist/auth/scope_kind_schema.d.ts.map +1 -1
- package/dist/auth/scope_kind_schema.js +11 -0
- package/dist/env/load.d.ts +1 -1
- package/dist/env/load.js +1 -1
- package/dist/http/CLAUDE.md +1 -1
- package/dist/http/body_limit.d.ts +27 -14
- package/dist/http/body_limit.d.ts.map +1 -1
- package/dist/http/body_limit.js +29 -16
- package/dist/http/db_routes.d.ts.map +1 -1
- package/dist/http/db_routes.js +5 -3
- package/dist/testing/CLAUDE.md +36 -19
- package/dist/testing/audit_drift_guard.d.ts +18 -5
- package/dist/testing/audit_drift_guard.d.ts.map +1 -1
- package/dist/testing/audit_drift_guard.js +24 -8
- package/dist/testing/cross_backend/body_size.d.ts +18 -5
- package/dist/testing/cross_backend/body_size.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size.js +233 -34
- package/dist/testing/cross_backend/body_size_smuggling.d.ts +0 -12
- package/dist/testing/cross_backend/body_size_smuggling.d.ts.map +1 -1
- package/dist/testing/cross_backend/body_size_smuggling.js +92 -147
- package/dist/testing/cross_backend/capabilities.d.ts +3 -24
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +1 -4
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +31 -2
- package/dist/testing/cross_backend/conformance_case.d.ts +3 -3
- package/dist/testing/cross_backend/credential_header_robustness.d.ts.map +1 -1
- package/dist/testing/cross_backend/credential_header_robustness.js +18 -54
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +2 -8
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_backdoor.js +2 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +5 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +5 -0
- package/dist/testing/cross_backend/token_lifetime.d.ts.map +1 -1
- package/dist/testing/cross_backend/token_lifetime.js +34 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.d.ts.map +1 -1
- package/dist/testing/cross_backend/ts_spine_backend_config.js +7 -14
- package/dist/testing/cross_backend/ws_outbound_overflow.d.ts.map +1 -1
- package/dist/testing/cross_backend/ws_outbound_overflow.js +65 -0
- package/dist/testing/schema_introspect.d.ts +24 -4
- package/dist/testing/schema_introspect.d.ts.map +1 -1
- package/dist/testing/schema_introspect.js +27 -4
- package/dist/testing/transports/raw_http.d.ts +78 -0
- package/dist/testing/transports/raw_http.d.ts.map +1 -0
- package/dist/testing/transports/raw_http.js +141 -0
- package/package.json +1 -1
- package/dist/env/resolve.d.ts +0 -163
- package/dist/env/resolve.d.ts.map +0 -1
- package/dist/env/resolve.js +0 -267
package/dist/actions/CLAUDE.md
CHANGED
|
@@ -159,13 +159,13 @@ if a consumer genuinely owns protocol actions in their typed API.
|
|
|
159
159
|
|
|
160
160
|
**Consumer tiers.** Single-source consumers (zzz) drop into the helpers
|
|
161
161
|
and accept the default `* as specs` namespace import. Multi-source
|
|
162
|
-
consumers (
|
|
162
|
+
consumers (fuz_forge, visiones — stitching local specs with
|
|
163
163
|
`all_admin_action_specs` / `all_role_grant_offer_action_specs` /
|
|
164
164
|
`all_account_action_specs` / `all_self_service_role_action_specs` from
|
|
165
165
|
fuz_app) call `create_namespace_qualifier` once, then pass the returned
|
|
166
166
|
`qualify_spec` callback to multi-source helpers.
|
|
167
167
|
|
|
168
|
-
**Tier 1** (HTTP-only
|
|
168
|
+
**Tier 1** (HTTP-only) emits a smaller surface — typically
|
|
169
169
|
`ActionMethod` + `FrontendActionsApi` + `ActionInputs` / `ActionOutputs`.
|
|
170
170
|
Never calls `generate_typed_action_event_alias` or
|
|
171
171
|
`generate_frontend_action_handlers`. **Tier 2** (`TypedActionEvent`-aware,
|
|
@@ -409,7 +409,7 @@ export declare class BackendWebsocketTransport implements FilterableBroadcastTra
|
|
|
409
409
|
* registration pending admission is skipped before the predicate runs.
|
|
410
410
|
*
|
|
411
411
|
* Used by the broadcast API when a consumer supplies a subscription ACL hook
|
|
412
|
-
* (e.g.
|
|
412
|
+
* (e.g. an event that only reaches the account that owns the resource it reports).
|
|
413
413
|
* When no ACL is needed, callers should prefer `send(message)` / `#broadcast`
|
|
414
414
|
* to skip the per-connection predicate overhead.
|
|
415
415
|
*
|
|
@@ -634,7 +634,7 @@ export class BackendWebsocketTransport {
|
|
|
634
634
|
* registration pending admission is skipped before the predicate runs.
|
|
635
635
|
*
|
|
636
636
|
* Used by the broadcast API when a consumer supplies a subscription ACL hook
|
|
637
|
-
* (e.g.
|
|
637
|
+
* (e.g. an event that only reaches the account that owns the resource it reports).
|
|
638
638
|
* When no ACL is needed, callers should prefer `send(message)` / `#broadcast`
|
|
639
639
|
* to skip the per-connection predicate overhead.
|
|
640
640
|
*
|
package/dist/auth/CLAUDE.md
CHANGED
|
@@ -58,7 +58,7 @@ Convention — `*_schema.ts` is Zod-only; `*_ddl.ts` holds DDL strings.
|
|
|
58
58
|
|
|
59
59
|
- `auth/account_schema.ts` — `Account`, `Actor`, `RoleGrant`, `AuthSession`, `ApiToken` + client-safe JSON shapes. Grant predicates over wire fields: `is_role_grant_active` (not revoked, not expired) and `has_global_role(role_grants, role, now?)` (an active grant of the role with `scope_id === null` — the bare-list form of `has_scoped_role(ctx, role, null)`, used client-side by `AuthState`).
|
|
60
60
|
- `auth/role_schema.ts` — `RoleName` (lowercase letters and underscores, no leading or trailing underscore, at most `ROLE_NAME_LENGTH_MAX` = 64 characters — the grammar every `role` input and every registered role holds, twin of the Rust `is_valid_role_name`), `RoleSpec`, `ROLE_KEEPER`, `ROLE_ADMIN`, `is_builtin_role`, `create_role_schema`, `builtin_role_specs_by_name`, `role_has_grant_path`, `list_roles_with_grant_path`.
|
|
61
|
-
- `auth/scope_kind_schema.ts` — `ScopeKindName`, `create_scope_kind_schema` (open registry, no builtins).
|
|
61
|
+
- `auth/scope_kind_schema.ts` — `ScopeKindName`, `create_scope_kind_schema` (open registry, no builtins), `SCOPE_KIND_LENGTH_MAX` (64 — bounds a registered name and the `scope_kind` on `role_grant_offer_create` / `role_grant_assign`, which is copied into the row and its audit metadata).
|
|
62
62
|
- `auth/credential_type_schema.ts` — `CredentialTypeName`, `CREDENTIAL_TYPE_SESSION` / `_API_TOKEN` / `_DAEMON_TOKEN`, `create_credential_type_schema`.
|
|
63
63
|
- `auth/grant_path_schema.ts` — `GrantPathName`, `GRANT_PATH_ADMIN` / `_SELF_SERVICE` / `_SYSTEM` / `_BOOTSTRAP`, `create_grant_path_schema`.
|
|
64
64
|
- `auth/token_lifetime.ts` — the temporal axis of a minted token: `TokenLifetimeInput` (required union on `account_token_create` — `{kind:'eternal'}` or `{kind:'ttl', days}`), `token_lifetime_to_expires_at`, `TOKEN_TTL_DAYS_MAX`. No default — `expires_at IS NULL` always means "deliberately eternal".
|
|
@@ -168,6 +168,10 @@ compile until it declares its scope. Both revocation listeners
|
|
|
168
168
|
and `audit_unknown_event_type_failures` are process-wide, fail-open
|
|
169
169
|
(write the row anyway). Independent in implementation; under the factory
|
|
170
170
|
they track the same config. Sample via `get_*`; `reset_*` are test-only.
|
|
171
|
+
Another counter lives with the emitter (`auth/audit_emitter.ts`,
|
|
172
|
+
`get_audit_write_failures` / `reset_audit_write_failures`): rows the bound
|
|
173
|
+
emitter's pool write failed to insert. That write is fail-open too — logged,
|
|
174
|
+
counted, the request proceeds — so the count is how a lost row is seen.
|
|
171
175
|
|
|
172
176
|
### Routes
|
|
173
177
|
|
|
@@ -239,6 +243,8 @@ consumer's `validate_data` pass-through callback on `CellActionDeps`.
|
|
|
239
243
|
`visibility` / `path`), the write-once capability/identity axis; a stray
|
|
240
244
|
`kind` inside `data` is rejected fail-loud (`ERROR_CELL_KIND_IN_DATA`).
|
|
241
245
|
- `auth/cell_action_specs.ts` — `CellVisibility` enum, `CellPath` brand,
|
|
246
|
+
`CELL_KIND_LENGTH_MAX` (64 — the wire `kind` on `cell_create` and the
|
|
247
|
+
`cell_list` filter; the tag is copied into the cell's audit rows),
|
|
242
248
|
`CellJson`, the generic verb specs (`cell_create / get / update /
|
|
243
249
|
delete / list / clone / moderate`), error reasons, and `all_cell_action_specs`
|
|
244
250
|
(spreads in the grant / field / item / audit registries so codegen + UI
|
|
@@ -770,7 +776,7 @@ Options: `roles?: RoleSchemaResult` (drives admin-grant-path lookup),
|
|
|
770
776
|
- `account_session_list_action_spec` — read; input `z.void()`; output `{sessions}`.
|
|
771
777
|
- `account_session_revoke_action_spec` — mutation; input `{session_id}`; output `{ok, revoked}`.
|
|
772
778
|
- `account_session_revoke_all_action_spec` — mutation; input `z.void()`; output `{ok, count}`.
|
|
773
|
-
- `account_token_create_action_spec` — mutation; input `{name?, scope, lifetime}` (both `scope` and `lifetime` required — default-deny at mint on both axes); output `{ok, token, id, name, expires_at}`.
|
|
779
|
+
- `account_token_create_action_spec` — mutation; input `{name?, scope, lifetime}` (both `scope` and `lifetime` required — default-deny at mint on both axes; `name` at most `API_TOKEN_NAME_LENGTH_MAX` = 255 characters, since it is copied into the audit row); output `{ok, token, id, name, expires_at}`.
|
|
774
780
|
- `account_token_list_action_spec` — read; input `z.void()`; output `{tokens}`.
|
|
775
781
|
- `account_token_revoke_action_spec` — mutation; input `{token_id}`; output `{ok, revoked}`.
|
|
776
782
|
|
|
@@ -45,6 +45,13 @@ export declare const SessionRevokeAllOutput: z.ZodObject<{
|
|
|
45
45
|
count: z.ZodNumber;
|
|
46
46
|
}, z.core.$strict>;
|
|
47
47
|
export type SessionRevokeAllOutput = z.infer<typeof SessionRevokeAllOutput>;
|
|
48
|
+
/**
|
|
49
|
+
* Maximum length of an API token's `name`, in UTF-16 code units (what
|
|
50
|
+
* `String.length` and Zod's `.max()` measure). The name is copied into the
|
|
51
|
+
* `token_create` audit row, so it is bounded where it enters. Same value as
|
|
52
|
+
* the Rust spine's `API_TOKEN_NAME_LENGTH_MAX`.
|
|
53
|
+
*/
|
|
54
|
+
export declare const API_TOKEN_NAME_LENGTH_MAX = 255;
|
|
48
55
|
/**
|
|
49
56
|
* Input for `account_token_create`.
|
|
50
57
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAW3E,6EAA6E;AAC7E,eAAO,MAAM,WAAW,WAAW,CAAC;AACpC,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,yCAAyC;AACzC,eAAO,MAAM,iBAAiB;;;;;;;kBAE5B,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB;;kBAE7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,iFAAiF;AACjF,eAAO,MAAM,mBAAmB;;;kBAG9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE1E,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB;;;kBAGjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"account_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/account_action_specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,6 +37,13 @@ export const SessionRevokeAllOutput = z.strictObject({
|
|
|
37
37
|
ok: z.literal(true),
|
|
38
38
|
count: z.number()
|
|
39
39
|
});
|
|
40
|
+
/**
|
|
41
|
+
* Maximum length of an API token's `name`, in UTF-16 code units (what
|
|
42
|
+
* `String.length` and Zod's `.max()` measure). The name is copied into the
|
|
43
|
+
* `token_create` audit row, so it is bounded where it enters. Same value as
|
|
44
|
+
* the Rust spine's `API_TOKEN_NAME_LENGTH_MAX`.
|
|
45
|
+
*/
|
|
46
|
+
export const API_TOKEN_NAME_LENGTH_MAX = 255;
|
|
40
47
|
/**
|
|
41
48
|
* Input for `account_token_create`.
|
|
42
49
|
*
|
|
@@ -54,8 +61,11 @@ export const SessionRevokeAllOutput = z.strictObject({
|
|
|
54
61
|
export const TokenCreateInput = z.strictObject({
|
|
55
62
|
name: z
|
|
56
63
|
.string()
|
|
64
|
+
.max(API_TOKEN_NAME_LENGTH_MAX)
|
|
57
65
|
.default('CLI token')
|
|
58
|
-
.meta({
|
|
66
|
+
.meta({
|
|
67
|
+
description: `Human-friendly label; shown in the token list. At most ${API_TOKEN_NAME_LENGTH_MAX} characters.`
|
|
68
|
+
}),
|
|
59
69
|
scope: TokenScopeInput.meta({
|
|
60
70
|
description: "What the token may do. `{kind:'full'}` for full account authority, or " +
|
|
61
71
|
"`{kind:'methods',methods:[…]}` to narrow it to named RPC methods — a " +
|
|
@@ -285,6 +285,10 @@ export interface CreateAuditEmitterOptions {
|
|
|
285
285
|
*/
|
|
286
286
|
track_inflight?: boolean;
|
|
287
287
|
}
|
|
288
|
+
/** Number of audit rows an emitter failed to write since process start. */
|
|
289
|
+
export declare const get_audit_write_failures: () => number;
|
|
290
|
+
/** Reset the counter — for tests only. */
|
|
291
|
+
export declare const reset_audit_write_failures: () => void;
|
|
288
292
|
/**
|
|
289
293
|
* Build a bound `AuditEmitter`. Typical caller is the consumer's
|
|
290
294
|
* `audit_factory` callback on `CreateAppBackendOptions` —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit_emitter.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_emitter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"audit_emitter.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_emitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -68,6 +68,21 @@
|
|
|
68
68
|
import { emit_after_commit } from '../http/pending_effects.js';
|
|
69
69
|
import { query_audit_log } from './audit_log_queries.js';
|
|
70
70
|
import { builtin_audit_log_config } from './audit_log_schema.js';
|
|
71
|
+
/**
|
|
72
|
+
* Process-wide counter for audit rows an emitter failed to write. The pool
|
|
73
|
+
* write behind `emit` / `emit_pool` / `emit_role_grant_target` is fail-open —
|
|
74
|
+
* a refused `INSERT` is logged and the request proceeds — so a lost row is
|
|
75
|
+
* otherwise visible only in the log. Same posture and lifetime as the drift
|
|
76
|
+
* counters in `auth/audit_log_queries.ts`: in-process, resets on restart, and
|
|
77
|
+
* asserted zero per test by `install_audit_drift_guard`.
|
|
78
|
+
*/
|
|
79
|
+
let audit_write_failures = 0;
|
|
80
|
+
/** Number of audit rows an emitter failed to write since process start. */
|
|
81
|
+
export const get_audit_write_failures = () => audit_write_failures;
|
|
82
|
+
/** Reset the counter — for tests only. */
|
|
83
|
+
export const reset_audit_write_failures = () => {
|
|
84
|
+
audit_write_failures = 0;
|
|
85
|
+
};
|
|
71
86
|
/**
|
|
72
87
|
* Build a bound `AuditEmitter`. Typical caller is the consumer's
|
|
73
88
|
* `audit_factory` callback on `CreateAppBackendOptions` —
|
|
@@ -101,13 +116,14 @@ export const create_audit_emitter = (options) => {
|
|
|
101
116
|
}
|
|
102
117
|
}
|
|
103
118
|
};
|
|
104
|
-
// The pool write. Never rejects: a failed write is logged and
|
|
105
|
-
// `null`, so there is no row to announce.
|
|
119
|
+
// The pool write. Never rejects: a failed write is logged, counted, and
|
|
120
|
+
// resolves `null`, so there is no row to announce.
|
|
106
121
|
const write = async (input) => {
|
|
107
122
|
try {
|
|
108
123
|
return await query_audit_log({ db }, input, audit_log_config);
|
|
109
124
|
}
|
|
110
125
|
catch (err) {
|
|
126
|
+
audit_write_failures++;
|
|
111
127
|
log.error('Audit log write failed:', err);
|
|
112
128
|
return null;
|
|
113
129
|
}
|
|
@@ -126,6 +126,16 @@ export declare const CELL_PATH_LENGTH_MAX = 256;
|
|
|
126
126
|
*/
|
|
127
127
|
export declare const CellPath: z.core.$ZodBranded<z.ZodString, "CellPath", "out">;
|
|
128
128
|
export type CellPath = z.infer<typeof CellPath>;
|
|
129
|
+
/**
|
|
130
|
+
* Maximum length of a cell `kind` on the wire, in UTF-16 code units (what
|
|
131
|
+
* `String.length` and Zod's `.max()` measure) — on `cell_create`, and on the
|
|
132
|
+
* `cell_list` filter. The cell layer imposes no grammar on `kind`; the bound
|
|
133
|
+
* is there because the tag is copied into every audit row the cell's
|
|
134
|
+
* mutations write. The same bound a cell field name carries
|
|
135
|
+
* (`CELL_FIELD_NAME_REGEX`), the cell layer's other machine-readable tag,
|
|
136
|
+
* and the same value as the Rust spine's `CELL_KIND_LENGTH_MAX`.
|
|
137
|
+
*/
|
|
138
|
+
export declare const CELL_KIND_LENGTH_MAX = 64;
|
|
129
139
|
/**
|
|
130
140
|
* Soft cap on the size of a `cell.list` request page. Larger pages chew
|
|
131
141
|
* memory both server- and client-side; combined with the visibility
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cell_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cell_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,EAEN,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAE3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEN,0BAA0B,EAC1B,6BAA6B,EAC7B,2BAA2B,EAE3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEN,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,0BAA0B,EAE1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEN,2BAA2B,EAC3B,MAAM,8BAA8B,CAAC;AAGtC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc;;;EAAgC,CAAC;AAC5D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAO5D,OAAO,EACN,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,CAAC;AACF,OAAO,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,2BAA2B,EAAE,CAAC;AAClG,OAAO,EACN,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,0BAA0B,EAC1B,CAAC;AACF,OAAO,EAAE,2BAA2B,EAAE,CAAC;AAIvC,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,EAAG,gBAAyB,CAAC;AAE9D,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,EAAG,sBAA+B,CAAC;AAE1E;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAG,iBAA0B,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,EAAG,6BAAsC,CAAC;AAExF,6EAA6E;AAC7E,eAAO,MAAM,kCAAkC,EAAG,8BAAuC,CAAC;AAE1F;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAG,mBAA4B,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAG,iBAA0B,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAG,uBAAgC,CAAC;AAE5E;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,EAAG,yBAAkC,CAAC;AAEhF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,EAAG,yBAAkC,CAAC;AAEhF;;;;;GAKG;AACH,eAAO,MAAM,wCAAwC,EACpD,oCAA6C,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,yCAAyC,EACrD,qCAA8C,CAAC;AAIhD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,oDAAgE,CAAC;AACtF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;kBAkCnB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAIhD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;
|
|
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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"}
|
|
@@ -132,6 +132,16 @@ export const CELL_PATH_LENGTH_MAX = 256;
|
|
|
132
132
|
* callsite (`as CellPath`) — the runtime check still runs server-side.
|
|
133
133
|
*/
|
|
134
134
|
export const CellPath = z.string().min(1).max(CELL_PATH_LENGTH_MAX).brand('CellPath');
|
|
135
|
+
/**
|
|
136
|
+
* Maximum length of a cell `kind` on the wire, in UTF-16 code units (what
|
|
137
|
+
* `String.length` and Zod's `.max()` measure) — on `cell_create`, and on the
|
|
138
|
+
* `cell_list` filter. The cell layer imposes no grammar on `kind`; the bound
|
|
139
|
+
* is there because the tag is copied into every audit row the cell's
|
|
140
|
+
* mutations write. The same bound a cell field name carries
|
|
141
|
+
* (`CELL_FIELD_NAME_REGEX`), the cell layer's other machine-readable tag,
|
|
142
|
+
* and the same value as the Rust spine's `CELL_KIND_LENGTH_MAX`.
|
|
143
|
+
*/
|
|
144
|
+
export const CELL_KIND_LENGTH_MAX = 64;
|
|
135
145
|
/**
|
|
136
146
|
* Soft cap on the size of a `cell.list` request page. Larger pages chew
|
|
137
147
|
* memory both server- and client-side; combined with the visibility
|
|
@@ -201,8 +211,12 @@ export const CellCreateInput = z.strictObject({
|
|
|
201
211
|
data: CellData.meta({
|
|
202
212
|
description: 'Cell content. Base fields (label / summary) typed; extras loose. A `kind` key here is rejected (`ERROR_CELL_KIND_IN_DATA`) — kind is the top-level field. Per-kind shape is sub-API.'
|
|
203
213
|
}),
|
|
204
|
-
kind: z
|
|
205
|
-
|
|
214
|
+
kind: z
|
|
215
|
+
.string()
|
|
216
|
+
.max(CELL_KIND_LENGTH_MAX)
|
|
217
|
+
.nullish()
|
|
218
|
+
.meta({
|
|
219
|
+
description: `Capability / identity tag, written to the top-level \`cell.kind\` column (not \`data\`). Write-once — fixed at birth, not updatable. Non-empty when present (an empty string is rejected \`ERROR_CELL_KIND_EMPTY\`) and at most ${CELL_KIND_LENGTH_MAX} characters; omit / null for a typeless cell. A creation authorizer (if mounted) gates on this.`
|
|
206
220
|
}),
|
|
207
221
|
visibility: CellVisibility.optional().meta({
|
|
208
222
|
description: "Access-control tag. Top-level column (not in `data`). Default `'private'` when omitted."
|
|
@@ -306,7 +320,7 @@ export const CellListInput = z
|
|
|
306
320
|
.max(CELL_LIST_LIMIT_MAX)
|
|
307
321
|
.optional()
|
|
308
322
|
.meta({ description: 'Batch-fetch by id. Visibility predicate still applies.' }),
|
|
309
|
-
kind: z.string().optional().meta({
|
|
323
|
+
kind: z.string().max(CELL_KIND_LENGTH_MAX).optional().meta({
|
|
310
324
|
description: 'Match `cell.kind = ?`. An empty string matches nothing — no cell carries an empty kind.'
|
|
311
325
|
}),
|
|
312
326
|
visibility: CellVisibility.optional().meta({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role_grant_offer_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_offer_action_specs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"role_grant_offer_action_specs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_offer_action_specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,7 @@ import { z } from 'zod';
|
|
|
24
24
|
import { Uuid } from '@fuzdev/fuz_util/id.ts';
|
|
25
25
|
import { ERROR_INSUFFICIENT_PERMISSIONS, ERROR_ROLE_GRANT_NOT_FOUND, ERROR_ROLE_NOT_WEB_GRANTABLE } from '../http/error_schemas.js';
|
|
26
26
|
import { RoleName } from './role_schema.js';
|
|
27
|
+
import { SCOPE_KIND_LENGTH_MAX } from './scope_kind_schema.js';
|
|
27
28
|
import { ROLE_GRANT_OFFER_MESSAGE_LENGTH_MAX, RoleGrantOfferJson } from './role_grant_offer_schema.js';
|
|
28
29
|
import { ROLE_GRANT_REVOKED_REASON_LENGTH_MAX } from './account_schema.js';
|
|
29
30
|
import { ActingActor } from '../http/auth_shape.js';
|
|
@@ -63,8 +64,12 @@ export const is_grant_scope_paired = (input) => (input.scope_kind == null) === (
|
|
|
63
64
|
/** The message a half-scoped grant input fails with — the grant inputs' refine, and the UI's pre-RPC guard. */
|
|
64
65
|
export const GRANT_SCOPE_PAIRED_MESSAGE = "'scope_kind' and 'scope_id' must be given together (both for a scoped grant, neither for a global one)";
|
|
65
66
|
/** The `scope_kind` field both grant inputs share, paired with `scope_id`. */
|
|
66
|
-
const GrantScopeKind = z
|
|
67
|
-
|
|
67
|
+
const GrantScopeKind = z
|
|
68
|
+
.string()
|
|
69
|
+
.max(SCOPE_KIND_LENGTH_MAX)
|
|
70
|
+
.nullish()
|
|
71
|
+
.meta({
|
|
72
|
+
description: `Machine-readable kind tag for \`scope_id\` — paired-null with \`scope_id\` (both null for global, both non-null for scoped). Required iff \`scope_id\` is set. At most ${SCOPE_KIND_LENGTH_MAX} characters.`
|
|
68
73
|
});
|
|
69
74
|
// -- Input/output schemas ---------------------------------------------------
|
|
70
75
|
/**
|
|
@@ -37,6 +37,16 @@ import { z } from 'zod';
|
|
|
37
37
|
* `'GLOBAL'` token.
|
|
38
38
|
*/
|
|
39
39
|
export declare const SCOPE_KIND_NAME_REGEX: RegExp;
|
|
40
|
+
/**
|
|
41
|
+
* Maximum length of a `scope_kind`, in UTF-16 code units (what
|
|
42
|
+
* `String.length` and Zod's `.max()` measure). Bounds the tag where it enters
|
|
43
|
+
* — the grant inputs (`role_grant_offer_create`, `role_grant_assign`) copy it
|
|
44
|
+
* into the row and its audit metadata — and a registered name, so no
|
|
45
|
+
* registry declares a kind the grant inputs would refuse. Same value as
|
|
46
|
+
* `ROLE_NAME_LENGTH_MAX`, whose grammar the name mirrors, and as the Rust
|
|
47
|
+
* spine's `SCOPE_KIND_LENGTH_MAX`.
|
|
48
|
+
*/
|
|
49
|
+
export declare const SCOPE_KIND_LENGTH_MAX = 64;
|
|
40
50
|
/** Zod schema for valid scope-kind name strings. */
|
|
41
51
|
export declare const ScopeKindName: z.ZodString;
|
|
42
52
|
export type ScopeKindName = z.infer<typeof ScopeKindName>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope_kind_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/scope_kind_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAgC,CAAC;AAEnE,oDAAoD;AACpD,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"scope_kind_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/scope_kind_schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAgC,CAAC;AAEnE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,oDAAoD;AACpD,eAAO,MAAM,aAAa,aASxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACrC;;;;;OAKG;IACH,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,wBAAwB,GACpC,gBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,KAC3C,qBAwBF,CAAC"}
|
|
@@ -37,9 +37,20 @@ import { z } from 'zod';
|
|
|
37
37
|
* `'GLOBAL'` token.
|
|
38
38
|
*/
|
|
39
39
|
export const SCOPE_KIND_NAME_REGEX = /^[a-z][a-z_]*[a-z]$|^[a-z]$/;
|
|
40
|
+
/**
|
|
41
|
+
* Maximum length of a `scope_kind`, in UTF-16 code units (what
|
|
42
|
+
* `String.length` and Zod's `.max()` measure). Bounds the tag where it enters
|
|
43
|
+
* — the grant inputs (`role_grant_offer_create`, `role_grant_assign`) copy it
|
|
44
|
+
* into the row and its audit metadata — and a registered name, so no
|
|
45
|
+
* registry declares a kind the grant inputs would refuse. Same value as
|
|
46
|
+
* `ROLE_NAME_LENGTH_MAX`, whose grammar the name mirrors, and as the Rust
|
|
47
|
+
* spine's `SCOPE_KIND_LENGTH_MAX`.
|
|
48
|
+
*/
|
|
49
|
+
export const SCOPE_KIND_LENGTH_MAX = 64;
|
|
40
50
|
/** Zod schema for valid scope-kind name strings. */
|
|
41
51
|
export const ScopeKindName = z
|
|
42
52
|
.string()
|
|
53
|
+
.max(SCOPE_KIND_LENGTH_MAX, `Scope-kind names must be at most ${SCOPE_KIND_LENGTH_MAX} characters`)
|
|
43
54
|
.regex(SCOPE_KIND_NAME_REGEX, 'Scope-kind names must be lowercase letters and underscores (a-z_), no leading/trailing underscore');
|
|
44
55
|
/**
|
|
45
56
|
* Create a scope-kind schema from a consumer-declared registry.
|
package/dist/env/load.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare class EnvValidationError extends Error {
|
|
|
35
35
|
* `error.all_undefined` before calling this.
|
|
36
36
|
*
|
|
37
37
|
* @param error - the env validation error
|
|
38
|
-
* @param label - optional prefix for log lines (e.g., '
|
|
38
|
+
* @param label - optional prefix for log lines (e.g., 'server', 'env')
|
|
39
39
|
*/
|
|
40
40
|
export declare const log_env_validation_error: (error: EnvValidationError, label?: string) => void;
|
|
41
41
|
/**
|
package/dist/env/load.js
CHANGED
|
@@ -42,7 +42,7 @@ export class EnvValidationError extends Error {
|
|
|
42
42
|
* `error.all_undefined` before calling this.
|
|
43
43
|
*
|
|
44
44
|
* @param error - the env validation error
|
|
45
|
-
* @param label - optional prefix for log lines (e.g., '
|
|
45
|
+
* @param label - optional prefix for log lines (e.g., 'server', 'env')
|
|
46
46
|
*/
|
|
47
47
|
export const log_env_validation_error = (error, label) => {
|
|
48
48
|
const prefix = label ? `[${label}] ` : '';
|
package/dist/http/CLAUDE.md
CHANGED
|
@@ -19,7 +19,7 @@ effects, see ../../../docs/architecture.md.
|
|
|
19
19
|
- `http/error_schemas.ts` — `ERROR_*` constants, standard error shapes, `derive_error_schemas`.
|
|
20
20
|
- `http/schema_helpers.ts` — shared Zod introspection (null/void/strict/surface/merge/middleware-applies) + `to_void_params` / `to_input_params` / `safe_parse_dropping_unknown_keys`.
|
|
21
21
|
- `http/middleware_spec.ts` — `MiddlewareSpec` interface.
|
|
22
|
-
- `http/body_limit.ts` — `create_body_limit_middleware(max_size)`: the `413` body cap `create_app_server` mounts. Refuses on `Content-Length` without reading `c.req.raw.body` and answers `Connection: close` — `413` past the cap, `400` `ERROR_INVALID_CONTENT_LENGTH` when the value is not a plain run of ASCII digits (a length the cap cannot read, which Hono's `bodyLimit` would pass uncounted) — else falls through to Hono's
|
|
22
|
+
- `http/body_limit.ts` — `create_body_limit_middleware(max_size)`: the `413` body cap `create_app_server` mounts. Refuses on `Content-Length` without reading `c.req.raw.body` and answers `Connection: close` — `413` past the cap, `400` `ERROR_INVALID_CONTENT_LENGTH` when the value is not a plain run of ASCII digits (a length the cap cannot read, which Hono's `bodyLimit` would pass uncounted) — else falls through to Hono's `bodyLimit` (no `Content-Length`, or one beside `Transfer-Encoding`), which reads the body into memory up to the cap before the next middleware runs, so its `413` — no `Connection: close` — also precedes origin and auth. Mounted with `app.use`, not as a `MiddlewareSpec`, so neither status appears in a route's merged error schemas. After the header `413` Node and Bun close at once (the header is what makes them — Bun 1.4.3 is the tested floor, an older Bun kept the connection and served the next request) and Deno closes once the declared body has arrived (../../../docs/security.md §Body Size Limiting).
|
|
23
23
|
- `http/surface.ts` — `AppSurface`, `AppSurfaceSpec`, `generate_app_surface`, diagnostics.
|
|
24
24
|
- `http/surface_query.ts` — pure filters/groupings over `AppSurface`.
|
|
25
25
|
- `http/proxy.ts` — trusted-proxy middleware, CIDR parsing, rightmost-first XFF resolution. Pulls `hono/utils/ipaddr` for CIDR matching.
|
|
@@ -11,25 +11,36 @@
|
|
|
11
11
|
* The runtimes' HTTP parsers answer their own bodiless `400` to most of
|
|
12
12
|
* these before the application sees them, so this branch is defense in
|
|
13
13
|
* depth where they do and the refusal where they do not: Node's refuses
|
|
14
|
-
* them all; Deno
|
|
15
|
-
* (`50, 50`)
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* the one value.
|
|
14
|
+
* them all; Deno and Bun hand over a repeated equal header as one combined
|
|
15
|
+
* value (`50, 50`) and refuse the rest (observed on Node 24.14.1, Deno
|
|
16
|
+
* 2.8.3, Bun 1.4.3). The Rust spine's parser (hyper) refuses a malformed
|
|
17
|
+
* value and differing repeats, and accepts an equal repeat as the one
|
|
18
|
+
* value.
|
|
20
19
|
* - A request whose `Content-Length` exceeds the cap is refused with `413`
|
|
21
20
|
* `{error: 'payload_too_large'}`, whatever its method. A digit run of any
|
|
22
21
|
* length compares as a number, so one too long to represent exactly is over
|
|
23
|
-
* the cap, never unreadable.
|
|
22
|
+
* the cap, never unreadable. Over a socket that branch is reached on Node
|
|
23
|
+
* and Deno, whose parsers hand over any length below 2^64 and refuse a
|
|
24
|
+
* longer one with their own `400`. `Bun.serve` hands none over: with its
|
|
25
|
+
* default options it answers a length past 128 MiB with its own `413`, and
|
|
26
|
+
* one of 2^63 - 1 or more with its own `400` (observed on Node 24.14.1,
|
|
27
|
+
* Deno 2.8.3, Bun 1.4.3).
|
|
24
28
|
* - Both refusals answer on the header alone — without touching
|
|
25
29
|
* `c.req.raw.body` — and carry `Connection: close`.
|
|
26
30
|
* - A request with a well-formed `Content-Length` beside `Transfer-Encoding`,
|
|
27
|
-
* or with no `Content-Length`, falls through to `bodyLimit
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
+
* or with no `Content-Length`, falls through to `bodyLimit`, which measures
|
|
32
|
+
* the bytes that arrive: with `Transfer-Encoding` the declared length does
|
|
33
|
+
* not frame the body. `bodyLimit` reads the body into memory, up to the
|
|
34
|
+
* cap, **before** the next middleware runs, so that `413` — sent once more
|
|
35
|
+
* than the cap has been read, with no `Connection: close` — also comes
|
|
36
|
+
* ahead of the origin check, auth and the handler. The Rust spine counts
|
|
37
|
+
* such a body as its handler reads it instead, so there a refusal made on
|
|
38
|
+
* the headers answers first; which status an over-cap body with no declared
|
|
39
|
+
* length gets when another refusal also applies is implementation-defined
|
|
40
|
+
* across the two (`docs/security.md` §"Body Size Limiting").
|
|
31
41
|
* The Node, Deno and Bun parsers refuse a request carrying both headers
|
|
32
|
-
* with their own `400`; hyper accepts one
|
|
42
|
+
* with their own `400`; hyper accepts one, drops its `Content-Length`,
|
|
43
|
+
* frames the body as chunked, and closes the connection after the response.
|
|
33
44
|
* - A well-formed `Content-Length` within the cap is trusted to frame the
|
|
34
45
|
* body, as the runtime's HTTP parser enforces.
|
|
35
46
|
*
|
|
@@ -45,8 +56,10 @@
|
|
|
45
56
|
* connection open while a client withholds it; a request pipelined behind
|
|
46
57
|
* the body is not served. Neither the header nor what the handler does with
|
|
47
58
|
* the body changes that (observed on Deno 2.8.3).
|
|
48
|
-
* - **Bun**
|
|
49
|
-
*
|
|
59
|
+
* - **Bun** closes at once, the body unread, honouring the header. Bun 1.4.3
|
|
60
|
+
* is the tested floor: an older Bun kept the connection after the `413` and
|
|
61
|
+
* served the next request (correctly framed), so run Bun at the floor or
|
|
62
|
+
* later.
|
|
50
63
|
*
|
|
51
64
|
* @module
|
|
52
65
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body_limit.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/body_limit.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"body_limit.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/body_limit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAQ9C;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,GAAI,UAAU,MAAM,KAAG,iBAwB/D,CAAC"}
|
package/dist/http/body_limit.js
CHANGED
|
@@ -11,25 +11,36 @@
|
|
|
11
11
|
* The runtimes' HTTP parsers answer their own bodiless `400` to most of
|
|
12
12
|
* these before the application sees them, so this branch is defense in
|
|
13
13
|
* depth where they do and the refusal where they do not: Node's refuses
|
|
14
|
-
* them all; Deno
|
|
15
|
-
* (`50, 50`)
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* the one value.
|
|
14
|
+
* them all; Deno and Bun hand over a repeated equal header as one combined
|
|
15
|
+
* value (`50, 50`) and refuse the rest (observed on Node 24.14.1, Deno
|
|
16
|
+
* 2.8.3, Bun 1.4.3). The Rust spine's parser (hyper) refuses a malformed
|
|
17
|
+
* value and differing repeats, and accepts an equal repeat as the one
|
|
18
|
+
* value.
|
|
20
19
|
* - A request whose `Content-Length` exceeds the cap is refused with `413`
|
|
21
20
|
* `{error: 'payload_too_large'}`, whatever its method. A digit run of any
|
|
22
21
|
* length compares as a number, so one too long to represent exactly is over
|
|
23
|
-
* the cap, never unreadable.
|
|
22
|
+
* the cap, never unreadable. Over a socket that branch is reached on Node
|
|
23
|
+
* and Deno, whose parsers hand over any length below 2^64 and refuse a
|
|
24
|
+
* longer one with their own `400`. `Bun.serve` hands none over: with its
|
|
25
|
+
* default options it answers a length past 128 MiB with its own `413`, and
|
|
26
|
+
* one of 2^63 - 1 or more with its own `400` (observed on Node 24.14.1,
|
|
27
|
+
* Deno 2.8.3, Bun 1.4.3).
|
|
24
28
|
* - Both refusals answer on the header alone — without touching
|
|
25
29
|
* `c.req.raw.body` — and carry `Connection: close`.
|
|
26
30
|
* - A request with a well-formed `Content-Length` beside `Transfer-Encoding`,
|
|
27
|
-
* or with no `Content-Length`, falls through to `bodyLimit
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
+
* or with no `Content-Length`, falls through to `bodyLimit`, which measures
|
|
32
|
+
* the bytes that arrive: with `Transfer-Encoding` the declared length does
|
|
33
|
+
* not frame the body. `bodyLimit` reads the body into memory, up to the
|
|
34
|
+
* cap, **before** the next middleware runs, so that `413` — sent once more
|
|
35
|
+
* than the cap has been read, with no `Connection: close` — also comes
|
|
36
|
+
* ahead of the origin check, auth and the handler. The Rust spine counts
|
|
37
|
+
* such a body as its handler reads it instead, so there a refusal made on
|
|
38
|
+
* the headers answers first; which status an over-cap body with no declared
|
|
39
|
+
* length gets when another refusal also applies is implementation-defined
|
|
40
|
+
* across the two (`docs/security.md` §"Body Size Limiting").
|
|
31
41
|
* The Node, Deno and Bun parsers refuse a request carrying both headers
|
|
32
|
-
* with their own `400`; hyper accepts one
|
|
42
|
+
* with their own `400`; hyper accepts one, drops its `Content-Length`,
|
|
43
|
+
* frames the body as chunked, and closes the connection after the response.
|
|
33
44
|
* - A well-formed `Content-Length` within the cap is trusted to frame the
|
|
34
45
|
* body, as the runtime's HTTP parser enforces.
|
|
35
46
|
*
|
|
@@ -45,8 +56,10 @@
|
|
|
45
56
|
* connection open while a client withholds it; a request pipelined behind
|
|
46
57
|
* the body is not served. Neither the header nor what the handler does with
|
|
47
58
|
* the body changes that (observed on Deno 2.8.3).
|
|
48
|
-
* - **Bun**
|
|
49
|
-
*
|
|
59
|
+
* - **Bun** closes at once, the body unread, honouring the header. Bun 1.4.3
|
|
60
|
+
* is the tested floor: an older Bun kept the connection after the `413` and
|
|
61
|
+
* served the next request (correctly framed), so run Bun at the floor or
|
|
62
|
+
* later.
|
|
50
63
|
*
|
|
51
64
|
* @module
|
|
52
65
|
*/
|
|
@@ -77,8 +90,8 @@ export const create_body_limit_middleware = (max_size) => {
|
|
|
77
90
|
// still a huge number (or `Infinity`), so it compares as over the cap
|
|
78
91
|
if (!c.req.header('transfer-encoding') && Number(content_length) > max_size) {
|
|
79
92
|
// refused on the header alone, the body untouched; `Connection: close`
|
|
80
|
-
// makes `@hono/node-server` close at once instead of holding
|
|
81
|
-
// connection or serving the request behind the body
|
|
93
|
+
// makes `@hono/node-server` and Bun close at once instead of holding
|
|
94
|
+
// the connection or serving the request behind the body
|
|
82
95
|
return c.json({ error: ERROR_PAYLOAD_TOO_LARGE }, 413, { connection: 'close' });
|
|
83
96
|
}
|
|
84
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/db_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAqC,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAiBpF;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,sDAAsD;AACtD,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAKrD,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAKrD,CAAC;AAEH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;;;;;OAQG;IACH,KAAK,EAAE;QACN,IAAI,EAAE,CACL,GAAG,EAAE;YACJ,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACtC,mBAAmB,EAAE,KAAK,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;SACvD,EACD,KAAK,EAAE;YACN,UAAU,EAAE,qBAAqB,CAAC;YAClC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;YACxB,EAAE,EAAE,MAAM,CAAC;YACX,QAAQ,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC;SAC3D,KACG,IAAI,CAAC;KACV,CAAC;CACF;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,oBAAoB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC7C;AA2CD;;GAEG;AACH,eAAO,MAAM,qBAAqB,GACjC,MAAM,WAAW,EACjB,SAAS,cAAc,KACrB,KAAK,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"db_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/db_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAqC,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAiBpF;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,sDAAsD;AACtD,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAKrD,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAKrD,CAAC;AAEH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B;;;;;;;;OAQG;IACH,KAAK,EAAE;QACN,IAAI,EAAE,CACL,GAAG,EAAE;YACJ,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACtC,mBAAmB,EAAE,KAAK,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;SACvD,EACD,KAAK,EAAE;YACN,UAAU,EAAE,qBAAqB,CAAC;YAClC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;YACxB,EAAE,EAAE,MAAM,CAAC;YACX,QAAQ,EAAE;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC;SAC3D,KACG,IAAI,CAAC;KACV,CAAC;CACF;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,oBAAoB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC7C;AA2CD;;GAEG;AACH,eAAO,MAAM,qBAAqB,GACjC,MAAM,WAAW,EACjB,SAAS,cAAc,KACrB,KAAK,CAAC,SAAS,CA8XjB,CAAC"}
|
package/dist/http/db_routes.js
CHANGED
|
@@ -424,9 +424,11 @@ export const create_db_route_specs = (deps, options) => {
|
|
|
424
424
|
return c.json({ error: ERROR_ROW_NOT_FOUND }, 404);
|
|
425
425
|
}
|
|
426
426
|
// 23503 foreign_key_violation / 23001 restrict_violation — the
|
|
427
|
-
// same referencing-row refusal
|
|
428
|
-
// DELETE RESTRICT`
|
|
429
|
-
//
|
|
427
|
+
// same referencing-row refusal. Which one depends on the
|
|
428
|
+
// constraint: `ON DELETE RESTRICT` raises 23001 on PG 18, PGlite
|
|
429
|
+
// and pglet (23503 on PG ≤17), and `NO ACTION` — the default,
|
|
430
|
+
// when the constraint names no action — raises 23503 on all of
|
|
431
|
+
// them.
|
|
430
432
|
if (code === '23503' || code === '23001') {
|
|
431
433
|
const pg_err = err;
|
|
432
434
|
log?.warn('Foreign key violation:', pg_err.detail, pg_err.constraint);
|