@fuzdev/fuz_app 0.93.0 → 0.95.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/README.md +2 -2
- package/dist/actions/action_codegen.d.ts +18 -18
- package/dist/actions/action_codegen.js +30 -30
- package/dist/actions/action_event.js +1 -1
- package/dist/actions/action_event_helpers.d.ts +1 -1
- package/dist/actions/action_event_types.d.ts +1 -1
- package/dist/actions/action_rpc.d.ts +2 -2
- package/dist/actions/broadcast_api.d.ts +1 -1
- package/dist/actions/broadcast_api.js +1 -1
- package/dist/actions/perform_action.d.ts +2 -2
- package/dist/actions/register_action_ws.d.ts +2 -2
- package/dist/actions/register_action_ws.js +2 -2
- package/dist/actions/register_ws_endpoint.js +1 -1
- package/dist/actions/request_tracker.svelte.d.ts +1 -1
- package/dist/actions/request_tracker.svelte.js +1 -1
- package/dist/actions/rpc_client.d.ts +1 -1
- package/dist/actions/socket.svelte.d.ts +2 -2
- package/dist/actions/transports_ws.js +1 -1
- package/dist/actions/transports_ws_auth_guard.d.ts +1 -1
- package/dist/actions/transports_ws_backend.d.ts +1 -1
- package/dist/actions/transports_ws_backend.js +2 -2
- package/dist/auth/account_action_specs.js +1 -1
- package/dist/auth/account_schema.d.ts +1 -1
- package/dist/auth/account_schema.js +1 -1
- package/dist/auth/actor_lookup_action_specs.js +1 -1
- package/dist/auth/actor_lookup_queries.d.ts +1 -1
- package/dist/auth/actor_search_action_specs.js +1 -1
- package/dist/auth/actor_search_queries.d.ts +1 -1
- package/dist/auth/admin_action_specs.js +1 -1
- package/dist/auth/api_token.js +1 -1
- package/dist/auth/api_token_queries.d.ts +1 -1
- package/dist/auth/app_settings_schema.d.ts +1 -1
- package/dist/auth/app_settings_schema.js +1 -1
- package/dist/auth/audit_emitter.d.ts +2 -2
- package/dist/auth/audit_log_routes.d.ts +1 -1
- package/dist/auth/audit_log_schema.d.ts +1 -1
- package/dist/auth/audit_log_schema.js +2 -2
- package/dist/auth/bearer_auth.d.ts +1 -1
- package/dist/auth/bootstrap_account.d.ts +1 -1
- package/dist/auth/bootstrap_route_schema.js +1 -1
- package/dist/auth/bootstrap_routes.d.ts +1 -1
- package/dist/auth/bootstrap_routes.js +1 -1
- package/dist/auth/cell_action_specs.js +2 -2
- package/dist/auth/cell_audit_action_specs.js +1 -1
- package/dist/auth/cell_audit_metadata.js +1 -1
- package/dist/auth/cell_field_action_specs.js +1 -1
- package/dist/auth/cell_field_audit_metadata.js +1 -1
- package/dist/auth/cell_grant_action_specs.js +1 -1
- package/dist/auth/cell_grant_audit_metadata.js +1 -1
- package/dist/auth/cell_item_action_specs.d.ts +1 -1
- package/dist/auth/cell_item_action_specs.js +3 -3
- package/dist/auth/cell_item_audit_metadata.js +1 -1
- package/dist/auth/cell_relation_visibility.d.ts +1 -1
- package/dist/auth/cleanup.d.ts +1 -1
- package/dist/auth/daemon_token_middleware.d.ts +1 -1
- package/dist/auth/deps.d.ts +2 -2
- package/dist/auth/invite_schema.d.ts +1 -1
- package/dist/auth/invite_schema.js +1 -1
- package/dist/auth/request_context.d.ts +1 -1
- package/dist/auth/role_grant_offer_action_specs.js +1 -1
- package/dist/auth/role_grant_offer_notifications.d.ts +1 -1
- package/dist/auth/role_grant_offer_notifications.js +1 -1
- package/dist/auth/role_grant_offer_queries.d.ts +1 -1
- package/dist/auth/role_grant_offer_schema.d.ts +1 -1
- package/dist/auth/role_grant_offer_schema.js +1 -1
- package/dist/auth/role_grant_queries.d.ts +1 -1
- package/dist/auth/session_queries.d.ts +1 -1
- package/dist/auth/session_queries.js +1 -1
- package/dist/auth/signup_route_schema.js +1 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +2 -2
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/logger.d.ts +1 -1
- package/dist/cli/logger.js +1 -1
- package/dist/db/CLAUDE.md +1 -1
- package/dist/db/cell_audit_queries.d.ts +1 -1
- package/dist/db/cell_field_queries.d.ts +1 -1
- package/dist/db/cell_grant_queries.d.ts +1 -1
- package/dist/db/cell_item_queries.d.ts +1 -1
- package/dist/db/cell_queries.d.ts +3 -3
- package/dist/db/cell_queries.js +1 -1
- package/dist/db/fact_disk_storage.d.ts +2 -2
- package/dist/db/fact_disk_storage.js +4 -4
- package/dist/db/fact_queries.d.ts +1 -1
- package/dist/db/fact_store.d.ts +3 -3
- package/dist/db/fact_store.js +2 -2
- package/dist/db/file_fact_url.d.ts +1 -1
- package/dist/db/file_fact_url.js +1 -1
- package/dist/db/migrate.js +1 -1
- package/dist/db/status.js +1 -1
- package/dist/http/auth_shape.js +2 -2
- package/dist/http/common_routes.d.ts +1 -1
- package/dist/http/db_routes.d.ts +1 -1
- package/dist/http/origin.js +1 -1
- package/dist/http/pending_effects.d.ts +1 -1
- package/dist/http/proxy.d.ts +1 -1
- package/dist/http/route_spec.d.ts +1 -1
- package/dist/rate_limiter.js +1 -1
- package/dist/realtime/sse.d.ts +1 -1
- package/dist/realtime/sse_auth_guard.d.ts +1 -1
- package/dist/runtime/deno.js +1 -1
- package/dist/server/app_backend.d.ts +1 -1
- package/dist/server/app_backend.js +1 -1
- package/dist/server/env.js +1 -1
- package/dist/server/fact_write.d.ts +2 -2
- package/dist/server/fact_write.js +1 -1
- package/dist/server/serve_fact_route.d.ts +1 -1
- package/dist/server/serve_fact_route.js +2 -2
- package/dist/server/startup.d.ts +1 -1
- package/dist/testing/CLAUDE.md +61 -9
- package/dist/testing/adversarial_input.js +1 -1
- package/dist/testing/app_server.d.ts +1 -1
- package/dist/testing/app_server.js +1 -1
- package/dist/testing/auth_apps.js +1 -1
- package/dist/testing/cross_backend/bench/bench_report.d.ts +1 -1
- package/dist/testing/cross_backend/bench/bench_report.js +2 -2
- package/dist/testing/cross_backend/bench/run_cross_impl_bench.d.ts +1 -1
- package/dist/testing/cross_backend/bench/run_cross_impl_bench.js +1 -1
- package/dist/testing/cross_backend/bootstrap_backend.d.ts +1 -1
- package/dist/testing/cross_backend/capabilities.d.ts +25 -4
- package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
- package/dist/testing/cross_backend/capabilities.js +9 -4
- package/dist/testing/cross_backend/cell_relations.js +1 -1
- package/dist/testing/cross_backend/conformance_case.d.ts +4 -0
- package/dist/testing/cross_backend/conformance_case.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_case.js +26 -0
- package/dist/testing/cross_backend/conformance_table.d.ts +21 -0
- package/dist/testing/cross_backend/conformance_table.d.ts.map +1 -1
- package/dist/testing/cross_backend/conformance_table.js +109 -7
- package/dist/testing/cross_backend/create_cross_backend_global_setup.d.ts +1 -1
- package/dist/testing/cross_backend/create_dual_spawn_global_setup.d.ts +1 -1
- package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
- package/dist/testing/cross_backend/default_backend_configs.js +7 -0
- package/dist/testing/cross_backend/default_spine_surface.d.ts +1 -1
- package/dist/testing/cross_backend/fact_serving.js +1 -1
- package/dist/testing/cross_backend/peer_ping_ws.d.ts +23 -0
- package/dist/testing/cross_backend/peer_ping_ws.d.ts.map +1 -0
- package/dist/testing/cross_backend/peer_ping_ws.js +209 -0
- package/dist/testing/cross_backend/setup.d.ts +1 -1
- package/dist/testing/cross_backend/setup.js +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +2 -2
- package/dist/testing/cross_backend/testing_server_core.d.ts +1 -1
- package/dist/testing/cross_backend/testing_server_core.js +1 -1
- package/dist/testing/cross_backend/ws_round_trip.js +1 -1
- package/dist/testing/db.js +4 -4
- package/dist/testing/middleware.js +1 -1
- package/dist/testing/role_grant_helpers.d.ts +1 -1
- package/dist/testing/rpc_helpers.d.ts +18 -1
- package/dist/testing/rpc_helpers.d.ts.map +1 -1
- package/dist/testing/rpc_helpers.js +24 -2
- package/dist/testing/schema_generators.d.ts +1 -1
- package/dist/testing/schema_generators.js +1 -1
- package/dist/testing/stubs.js +1 -1
- package/dist/testing/testing_rate_limiter.d.ts +1 -1
- package/dist/testing/testing_rate_limiter.js +1 -1
- package/dist/testing/transports/bootstrap.d.ts +1 -1
- package/dist/testing/transports/bootstrap.js +1 -1
- package/dist/testing/transports/ws_client.d.ts +40 -1
- package/dist/testing/transports/ws_client.d.ts.map +1 -1
- package/dist/testing/transports/ws_client.js +46 -1
- package/dist/testing/transports/ws_transport.d.ts +10 -1
- package/dist/testing/transports/ws_transport.d.ts.map +1 -1
- package/dist/testing/transports/ws_transport.js +6 -10
- package/dist/testing/ws_round_trip.d.ts +13 -3
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +16 -12
- package/dist/ui/AdminSurface.svelte +1 -1
- package/dist/ui/AppShell.svelte +1 -1
- package/dist/ui/BootstrapForm.svelte +1 -1
- package/dist/ui/CLAUDE.md +1 -1
- package/dist/ui/ConfirmButton.svelte +2 -2
- package/dist/ui/ConfirmButton.svelte.d.ts +1 -1
- package/dist/ui/LoginForm.svelte +1 -1
- package/dist/ui/MenuLink.svelte +1 -1
- package/dist/ui/MenuLink.svelte.d.ts +1 -1
- package/dist/ui/PopoverButton.svelte +1 -1
- package/dist/ui/PopoverButton.svelte.d.ts +1 -1
- package/dist/ui/SignupForm.svelte +1 -1
- package/dist/ui/account_sessions_state.svelte.js +1 -1
- package/dist/ui/admin_accounts_state.svelte.d.ts +1 -1
- package/dist/ui/admin_accounts_state.svelte.js +1 -1
- package/dist/ui/admin_invites_state.svelte.d.ts +1 -1
- package/dist/ui/admin_invites_state.svelte.js +1 -1
- package/dist/ui/admin_sessions_state.svelte.d.ts +1 -1
- package/dist/ui/app_settings_state.svelte.js +1 -1
- package/dist/ui/async_slot.svelte.d.ts +2 -2
- package/dist/ui/async_slot.svelte.js +2 -2
- package/dist/ui/audit_log_state.svelte.js +1 -1
- package/dist/ui/auth_state.svelte.d.ts +1 -1
- package/dist/ui/auth_state.svelte.js +3 -3
- package/dist/ui/format_scope.js +1 -1
- package/dist/ui/popover.svelte.d.ts +1 -1
- package/dist/ui/popover.svelte.js +2 -2
- package/dist/ui/position_helpers.js +1 -1
- package/dist/ui/role_grant_offers_state.svelte.js +1 -1
- package/dist/ui/sidebar_state.svelte.js +1 -1
- package/dist/ui/table_state.svelte.d.ts +1 -1
- package/dist/ui/table_state.svelte.js +2 -2
- package/package.json +2 -2
package/dist/http/db_routes.d.ts
CHANGED
package/dist/http/origin.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module
|
|
11
11
|
*/
|
|
12
|
-
import { escape_regexp } from '@fuzdev/fuz_util/regexp.
|
|
12
|
+
import { escape_regexp } from '@fuzdev/fuz_util/regexp.ts';
|
|
13
13
|
import { ERROR_FORBIDDEN_ORIGIN } from './error_schemas.js';
|
|
14
14
|
/**
|
|
15
15
|
* Parses FUZ_ALLOWED_ORIGINS env var into regex matchers for request source verification.
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
*
|
|
40
40
|
* @module
|
|
41
41
|
*/
|
|
42
|
-
import type { Logger } from '@fuzdev/fuz_util/log.
|
|
42
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
43
43
|
/**
|
|
44
44
|
* Minimal structural context required by `emit_after_commit`. Both
|
|
45
45
|
* `RouteContext` and `ActionContext` satisfy this — they each carry
|
package/dist/http/proxy.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
import type { Context, MiddlewareHandler } from 'hono';
|
|
11
|
-
import type { Logger } from '@fuzdev/fuz_util/log.
|
|
11
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
12
12
|
import type { MiddlewareSpec } from './middleware_spec.js';
|
|
13
13
|
/**
|
|
14
14
|
* Normalize an IP address for consistent matching and storage.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { Context, Hono, MiddlewareHandler } from 'hono';
|
|
16
16
|
import type { z } from 'zod';
|
|
17
|
-
import type { Logger } from '@fuzdev/fuz_util/log.
|
|
17
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
18
18
|
import type { Db } from '../db/db.js';
|
|
19
19
|
import { type RouteErrorSchemas, type RateLimitKey } from './error_schemas.js';
|
|
20
20
|
import type { MiddlewareSpec } from './middleware_spec.js';
|
package/dist/rate_limiter.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
-
import { LruMap } from '@fuzdev/fuz_util/lru_map.
|
|
9
|
+
import { LruMap } from '@fuzdev/fuz_util/lru_map.ts';
|
|
10
10
|
import { ERROR_RATE_LIMIT_EXCEEDED } from './http/error_schemas.js';
|
|
11
11
|
/**
|
|
12
12
|
* Default tracked-key cap: bounds worst-case memory under key-enumeration
|
package/dist/realtime/sse.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
|
-
import type { Logger } from '@fuzdev/fuz_util/log.
|
|
13
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
14
14
|
import { type AuditLogEvent } from '../auth/audit_log_schema.js';
|
|
15
15
|
import { SubscriberRegistry, type SubscribeOptions } from './subscriber_registry.js';
|
|
16
16
|
import type { SseStream, SseNotification, EventSpec } from './sse.js';
|
package/dist/runtime/deno.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
|
-
import { Logger } from '@fuzdev/fuz_util/log.
|
|
13
|
+
import { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
14
14
|
import type { AppDeps } from '../auth/deps.js';
|
|
15
15
|
import { type AuditEmitter } from '../auth/audit_emitter.js';
|
|
16
16
|
import type { DbType, Db } from '../db/db.js';
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
|
-
import { Logger } from '@fuzdev/fuz_util/log.
|
|
13
|
+
import { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
14
14
|
import { create_audit_emitter } from '../auth/audit_emitter.js';
|
|
15
15
|
import { run_migrations } from '../db/migrate.js';
|
|
16
16
|
import { auth_migration_ns, reserved_migration_namespaces } from '../auth/migrations.js';
|
package/dist/server/env.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
11
|
import { z } from 'zod';
|
|
12
|
-
import { to_error_message } from '@fuzdev/fuz_util/error.
|
|
12
|
+
import { to_error_message } from '@fuzdev/fuz_util/error.ts';
|
|
13
13
|
import { create_validated_keyring } from '../auth/keyring.js';
|
|
14
14
|
import { parse_allowed_origins } from '../http/origin.js';
|
|
15
15
|
/**
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
|
-
import { type FactHash } from '@fuzdev/fuz_util/fact_hash.
|
|
14
|
-
import type { FactStore } from '@fuzdev/fuz_util/fact_store.
|
|
13
|
+
import { type FactHash } from '@fuzdev/fuz_util/fact_hash.ts';
|
|
14
|
+
import type { FactStore } from '@fuzdev/fuz_util/fact_store.ts';
|
|
15
15
|
export interface WriteFactOptions {
|
|
16
16
|
content_type: string;
|
|
17
17
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { randomBytes } from 'node:crypto';
|
|
14
14
|
import { writeFile, rename, mkdir, unlink } from 'node:fs/promises';
|
|
15
15
|
import { join } from 'node:path';
|
|
16
|
-
import { FACT_HASH_PREFIX, fact_hash_bytes } from '@fuzdev/fuz_util/fact_hash.
|
|
16
|
+
import { FACT_HASH_PREFIX, fact_hash_bytes } from '@fuzdev/fuz_util/fact_hash.ts';
|
|
17
17
|
import { mint_file_fact_url } from '../db/file_fact_url.js';
|
|
18
18
|
/**
|
|
19
19
|
* Write `bytes` as a fact, choosing embedded (PG) vs external (disk +
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
*
|
|
73
73
|
* @module
|
|
74
74
|
*/
|
|
75
|
-
import type { Logger } from '@fuzdev/fuz_util/log.
|
|
75
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
76
76
|
import { type RouteSpec } from '../http/route_spec.js';
|
|
77
77
|
import type { AppDeps } from '../auth/deps.js';
|
|
78
78
|
export interface CreateServeFactRouteSpecOptions {
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
import { createReadStream } from 'node:fs';
|
|
76
76
|
import { Readable } from 'node:stream';
|
|
77
77
|
import { join } from 'node:path';
|
|
78
|
-
import { FactHashSchema } from '@fuzdev/fuz_util/fact_hash.
|
|
79
|
-
import { Uuid } from '@fuzdev/fuz_util/id.
|
|
78
|
+
import { FactHashSchema } from '@fuzdev/fuz_util/fact_hash.ts';
|
|
79
|
+
import { Uuid } from '@fuzdev/fuz_util/id.ts';
|
|
80
80
|
import { z } from 'zod';
|
|
81
81
|
import { build_request_context, get_request_context, has_role, } from '../auth/request_context.js';
|
|
82
82
|
import { ROLE_ADMIN } from '../auth/role_schema.js';
|
package/dist/server/startup.d.ts
CHANGED
package/dist/testing/CLAUDE.md
CHANGED
|
@@ -13,7 +13,7 @@ testing-patterns. This file is a reference index for the helpers themselves.
|
|
|
13
13
|
|
|
14
14
|
## Production guard — always the first import
|
|
15
15
|
|
|
16
|
-
Every runtime-reachable module here starts with `import './assert_dev_env.
|
|
16
|
+
Every runtime-reachable module here starts with `import './assert_dev_env.ts';`
|
|
17
17
|
— reads `DEV` from `esm-env` and throws if false, preventing production-bundle
|
|
18
18
|
inclusion. Make this the first line in new modules. Enforced by
|
|
19
19
|
`src/test/testing/assert_dev_env_coverage.test.ts`, which fails if any module
|
|
@@ -770,7 +770,8 @@ One-shot transport:
|
|
|
770
770
|
|
|
771
771
|
- `RpcTestTransport = (url, init) => Promise<Response>` — duck type `Hono.request` already satisfies.
|
|
772
772
|
- `http_transport(app)` — adapter for anything with a `request()` method.
|
|
773
|
-
- `RpcCallResult` — discriminated `{ok: true, status, result}` / `{ok: false, status, error: {code, message, data?}}`.
|
|
773
|
+
- `RpcCallResult` — discriminated `{ok: true, status, headers, result}` / `{ok: false, status, headers, error: {code, message, data?}}`. `headers` is the lowercased-key response-header snapshot so callers can assert header-level properties (e.g. the conformance runner's no-fingerprint invariant).
|
|
774
|
+
- `headers_to_record(headers)` — snapshot a `Headers` into a lowercased-key `Record<string, string>` (multi-value collapses to the comma-joined form; `Set-Cookie` excluded). Used by `rpc_call` and the conformance table's REST branch to thread response headers through for assertions.
|
|
774
775
|
- `RpcCallArgs` — `{app, path, method, params?, headers?, id?, verb?}`. `verb` defaults to `'POST'`; use `'GET'` for `side_effects: false` methods.
|
|
775
776
|
- `rpc_call(args)` — merges `RPC_CALL_DEFAULT_HEADERS` (`host: 'localhost'`, `origin: 'http://localhost:5173'`, `Content-Type: 'application/json'`) under caller headers. Envelope-shape violations throw; JSON-RPC errors return `{ok: false, error}` so callers assert on `error.code` / `error.data.reason`.
|
|
776
777
|
- `rpc_call_typed<T>(args, output_schema)` — parses the success `result` through the schema; throws on envelope failure, error response, or schema mismatch. Use `rpc_call` when the test needs to assert on error shapes.
|
|
@@ -822,7 +823,7 @@ points:
|
|
|
822
823
|
|
|
823
824
|
- **`await_pending_effects: true`** is set by `create_test_app`. Fire-and-forget effects (audit logs, session touches, WS fan-out via `emit_after_commit`) resolve before the response returns, so tests can assert on side effects inline without manual flushing.
|
|
824
825
|
- **Deep-path imports only.** Import from the canonical module (`testing/db.js`, `testing/rpc_helpers.js`, etc.); fuz_app's `dist/` ships no barrel.
|
|
825
|
-
- **DI via small `*Deps` interfaces.** Stub factories accept the same narrow `*Deps` contracts production code uses — never `Pick<GodType, ...>`. New helpers needing env/fs/logger take `EnvDeps` / `FsReadDeps` / `Logger` from `runtime/deps.ts` or `@fuzdev/fuz_util/log.
|
|
826
|
+
- **DI via small `*Deps` interfaces.** Stub factories accept the same narrow `*Deps` contracts production code uses — never `Pick<GodType, ...>`. New helpers needing env/fs/logger take `EnvDeps` / `FsReadDeps` / `Logger` from `runtime/deps.ts` or `@fuzdev/fuz_util/log.ts`.
|
|
826
827
|
- **Keep the shared echo routes in sync with public surface.** When middleware or public API gains a new context variable, header, or field, update the echo in `middleware.ts` (`create_bearer_auth_test_app`, `create_test_middleware_stack_app`) alongside the assertions in `src/test/auth/*.test.ts`. Drift surfaces as a missed assertion, not a test failure.
|
|
827
828
|
|
|
828
829
|
## Cross-backend integration layer
|
|
@@ -893,7 +894,10 @@ source of truth for wire-shape conformance.
|
|
|
893
894
|
- `testing/cross_backend/capabilities.ts` — `BackendCapabilities` vocabulary
|
|
894
895
|
(the **gating** flags `ws` / `sse` / `cell_crud` / `cell_relations` /
|
|
895
896
|
`account_lifecycle` / `fact_serving` / `ready` / `account_status` /
|
|
896
|
-
`oversized_reject_closes_connection` — each has a `test_if`
|
|
897
|
+
`oversized_reject_closes_connection` / `peer_request` — each has a `test_if`
|
|
898
|
+
reader; `peer_request` (server-initiated requests — the `ActionPeer`
|
|
899
|
+
`peer/ping` round-trip) is `true` only for the Rust spine and `false` for the
|
|
900
|
+
TS family, whose server request transport is deferred),
|
|
897
901
|
`test_if(cond, name, fn)`
|
|
898
902
|
for capability-gated cases, and `in_process_capabilities` preset. The
|
|
899
903
|
non-gating wiring facts (`bearer_auth` / `trusted_proxy` / `login_rate_limit`,
|
|
@@ -966,7 +970,7 @@ wire-shape check passes green on even when behavior is wrong.
|
|
|
966
970
|
|
|
967
971
|
- `conformance_case.ts` — `ConformanceCase` Zod schema:
|
|
968
972
|
`{name, request: {method, params?, as, verb?}, expect: {status,
|
|
969
|
-
error_reason?, fields?}, note?, xfail?}`. A case is **data** — `method`
|
|
973
|
+
error_reason?, fields?, headers?, equivalence_group?}, note?, xfail?}`. A case is **data** — `method`
|
|
970
974
|
resolves its `input`/`output` from the live registry (RPC) or `RouteSpec`
|
|
971
975
|
(the 6 REST auth routes), so the case never carries a schema. `as` is the
|
|
972
976
|
closed `ConformancePrincipal` enum (`keeper` / `daemon` / `token` /
|
|
@@ -978,7 +982,24 @@ error_reason?, fields?}, note?, xfail?}`. A case is **data** — `method`
|
|
|
978
982
|
`error_reason` is the imported
|
|
979
983
|
`ERROR_*` constant (asserted against the RPC `error.data.reason` or the
|
|
980
984
|
REST flat-body `error`; the bare `unauthenticated()` 401 carries no
|
|
981
|
-
reason, so `status` pins that denial class).
|
|
985
|
+
reason, so `status` pins that denial class). `equivalence_group` is the
|
|
986
|
+
**negative-space** axis: every case tagged with the same group string must
|
|
987
|
+
produce a **byte-identical** normalized response (`{status, body}`),
|
|
988
|
+
asserted per impl after the case loop. It promotes a masked pair
|
|
989
|
+
(wrong-password ≡ account-not-found, found-but-unauthorized ≡ not-found)
|
|
990
|
+
from "same status + reason" to "wire-indistinguishable", so a prober
|
|
991
|
+
hitting either spine can't tell the members apart — the twin of the
|
|
992
|
+
positive `output`-schema parity the runner already enforces. The
|
|
993
|
+
per-case status/reason assertions stay the non-vacuous positive control
|
|
994
|
+
(a both-paths-identically-broken group still fails the per-case checks).
|
|
995
|
+
`headers` is the **header** negative-space axis: a string value pins a
|
|
996
|
+
header present-and-equal (case-insensitive name), `null` pins it absent.
|
|
997
|
+
Independent of it, the runner enforces an always-on **no-fingerprint**
|
|
998
|
+
invariant on _every_ response (`conformance_table.ts` `FINGERPRINT_HEADERS`
|
|
999
|
+
— `Server` / `X-Powered-By` / `WWW-Authenticate` must stay absent on both
|
|
1000
|
+
spines, so a framework upgrade adding one can't become a silent
|
|
1001
|
+
backend-fingerprinting oracle). Headers are deliberately kept out of the
|
|
1002
|
+
`equivalence_group` `{status, body}` comparison (`Set-Cookie` / `Date` vary).
|
|
982
1003
|
- `conformance_table.ts` — `describe_conformance_table_tests({cases,
|
|
983
1004
|
setup_test, surface_source, capabilities, rpc_endpoints, session_options,
|
|
984
1005
|
principals?, suite_name?})`. Same `{setup_test, surface_source,
|
|
@@ -1058,6 +1079,30 @@ where one exists (forge) and be offered the role; harmless on the auth-only
|
|
|
1058
1079
|
spine. Gated on `capabilities.ws`; cross-process only. fuz_app's own wiring is
|
|
1059
1080
|
`src/test/cross_backend/role_grant_offer_notification_ws.cross.test.ts`.
|
|
1060
1081
|
|
|
1082
|
+
### `cross_backend/peer_ping_ws.ts` — `describe_peer_ping_ws_tests`
|
|
1083
|
+
|
|
1084
|
+
The server→client **request/response** sibling of the notification suite above —
|
|
1085
|
+
the machinery proof for `ActionPeer`. `peer/ping` is `initiator: both`; the
|
|
1086
|
+
client→server direction already exists as `heartbeat`, this exercises the new
|
|
1087
|
+
server→client one. The observable trigger is a client invoking the `peer/ping`
|
|
1088
|
+
**action** over its own socket: the handler initiates a `peer/ping` request back
|
|
1089
|
+
to that socket (`ctx.request_client`), awaits the client's echo, validates it
|
|
1090
|
+
against `PingResponse`, and returns the validated shape — so one client RPC
|
|
1091
|
+
drives the whole round-trip and every outcome (success / `Timeout` / wrong-shape
|
|
1092
|
+
/ client-error) surfaces as that RPC's wire response. The client attaches an
|
|
1093
|
+
`on_request` responder **at construction** (the `create_ws_transport` seam) so
|
|
1094
|
+
the inbound server-initiated request is answered as soon as it arrives; the
|
|
1095
|
+
security negatives use the raw `WsClient.send` to inject unsolicited /
|
|
1096
|
+
cross-connection frames. Seven cases: the positive round-trip plus
|
|
1097
|
+
unsolicited-response rejection, per-connection id isolation, never-reply
|
|
1098
|
+
`Timeout`, wrong-shape rejection, client-error forwarding, and the HTTP
|
|
1099
|
+
no-transport path. Gated on `capabilities.peer_request` — `true` only on the
|
|
1100
|
+
Rust spine (server-initiated requests are Rust-first canonical), so it `.skip`s
|
|
1101
|
+
on the TS spines whose server request transport is the deferred convergence
|
|
1102
|
+
item; `peer/ping` is a protocol action (manifest-excluded), so parity is
|
|
1103
|
+
behavioral here, not via the manifest gate. Cross-process only; fuz_app's own
|
|
1104
|
+
wiring is `src/test/cross_backend/peer_ping_ws.cross.test.ts`.
|
|
1105
|
+
|
|
1061
1106
|
### `cross_backend/sse_round_trip.ts` — `describe_cross_process_sse_tests`
|
|
1062
1107
|
|
|
1063
1108
|
Cross-process counterpart to the in-process `sse_round_trip.ts` harness —
|
|
@@ -1159,12 +1204,19 @@ in-process legs (plain `gro test`) are `src/test/auth/cell_crud_parity.db.test.t
|
|
|
1159
1204
|
wire-frame types, and
|
|
1160
1205
|
predicates (`is_notification`, `is_response_for`, ...). Both in-process
|
|
1161
1206
|
(`ws_round_trip.ts`) and cross-process (`ws_transport.ts`) impls satisfy
|
|
1162
|
-
this interface.
|
|
1163
|
-
|
|
1207
|
+
this interface. Also owns `deliver_inbound` — the shared
|
|
1208
|
+
parse→(respond|push)→resolve receive core both impls call (so the responder
|
|
1209
|
+
branch is written once) — plus the `WsRequestResponder` / `WsResponderOutcome`
|
|
1210
|
+
types for the **`on_request`** seam: a responder answers a server-initiated
|
|
1211
|
+
request (`{result}` / `{error}` / `undefined` to swallow), the path
|
|
1212
|
+
`describe_peer_ping_ws_tests` drives. With no `on_request` the seam is inert
|
|
1213
|
+
(a server-initiated request flows to `messages` as before).
|
|
1214
|
+
- `testing/transports/ws_transport.ts` — `create_ws_transport({base_url, ws_path, cookies, origin?, on_request?})`
|
|
1164
1215
|
builds a real-upgrade WS client using the `ws` npm package (optional
|
|
1165
1216
|
peerDep; consumers wiring cross-process tests `npm install --save-dev ws`).
|
|
1166
1217
|
Threads the keeper cookie onto the upgrade so per-action auth succeeds on
|
|
1167
|
-
the first message.
|
|
1218
|
+
the first message. `on_request` (attached at construction, before the upgrade
|
|
1219
|
+
completes) answers server-initiated requests via the shared `deliver_inbound`.
|
|
1168
1220
|
- `testing/transports/sse_frame_reader.ts` — `create_sse_frame_reader(reader, default_timeout_ms?)`,
|
|
1169
1221
|
the transport-agnostic SSE framing core over a
|
|
1170
1222
|
`ReadableStreamDefaultReader<Uint8Array>`: `\n\n` framing, per-read timeout,
|
|
@@ -14,7 +14,7 @@ import './assert_dev_env.js';
|
|
|
14
14
|
*/
|
|
15
15
|
import { test, assert, describe } from 'vitest';
|
|
16
16
|
import { z } from 'zod';
|
|
17
|
-
import { zod_unwrap_to_object, zod_extract_fields } from '@fuzdev/fuz_util/zod.
|
|
17
|
+
import { zod_unwrap_to_object, zod_extract_fields } from '@fuzdev/fuz_util/zod.ts';
|
|
18
18
|
import { is_null_schema } from '../http/schema_helpers.js';
|
|
19
19
|
import { filter_routes_with_input, filter_routes_with_params, filter_routes_with_query, } from '../http/surface_query.js';
|
|
20
20
|
import { ValidationError, ERROR_INVALID_REQUEST_BODY, ERROR_INVALID_JSON_BODY, ERROR_INVALID_ROUTE_PARAMS, ERROR_INVALID_QUERY_PARAMS, } from '../http/error_schemas.js';
|
|
@@ -13,7 +13,7 @@ import './assert_dev_env.js';
|
|
|
13
13
|
* @module
|
|
14
14
|
*/
|
|
15
15
|
import type { Hono } from 'hono';
|
|
16
|
-
import type { Uuid } from '@fuzdev/fuz_util/id.
|
|
16
|
+
import type { Uuid } from '@fuzdev/fuz_util/id.ts';
|
|
17
17
|
import { type Keyring } from '../auth/keyring.js';
|
|
18
18
|
import type { Db, DbType } from '../db/db.js';
|
|
19
19
|
import type { PasswordHashDeps } from '../auth/password.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import './assert_dev_env.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { Logger } from '@fuzdev/fuz_util/log.
|
|
3
|
+
import { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
4
4
|
import { DEFAULT_TEST_PASSWORD } from './test_credentials.js';
|
|
5
5
|
import { ROLE_KEEPER } from '../auth/role_schema.js';
|
|
6
6
|
import { create_validated_keyring } from '../auth/keyring.js';
|
|
@@ -8,7 +8,7 @@ import './assert_dev_env.js';
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
import { Hono } from 'hono';
|
|
11
|
-
import { Logger } from '@fuzdev/fuz_util/log.
|
|
11
|
+
import { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
12
12
|
import { apply_route_specs } from '../http/route_spec.js';
|
|
13
13
|
import { is_public_auth } from '../http/auth_shape.js';
|
|
14
14
|
import { fuz_auth_guard_resolver } from '../auth/auth_guard_resolver.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../../assert_dev_env.js';
|
|
2
|
-
import { type BenchmarkComparison } from '@fuzdev/fuz_util/benchmark_stats.
|
|
2
|
+
import { type BenchmarkComparison } from '@fuzdev/fuz_util/benchmark_stats.ts';
|
|
3
3
|
import type { CrossImplBenchResult } from './run_cross_impl_bench.js';
|
|
4
4
|
/**
|
|
5
5
|
* Reporting adapters over a `CrossImplBenchResult` — all built on fuz_util's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../../assert_dev_env.js';
|
|
2
|
-
import { benchmark_format_markdown } from '@fuzdev/fuz_util/benchmark_format.
|
|
3
|
-
import { benchmark_stats_compare, } from '@fuzdev/fuz_util/benchmark_stats.
|
|
2
|
+
import { benchmark_format_markdown } from '@fuzdev/fuz_util/benchmark_format.ts';
|
|
3
|
+
import { benchmark_stats_compare, } from '@fuzdev/fuz_util/benchmark_stats.ts';
|
|
4
4
|
/**
|
|
5
5
|
* Reporting adapters over a `CrossImplBenchResult` — all built on fuz_util's
|
|
6
6
|
* formatters + Welch comparison. Markdown for human eyeballs, a per-scenario
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../../assert_dev_env.js';
|
|
2
|
-
import type { BenchmarkConfig, BenchmarkResult } from '@fuzdev/fuz_util/benchmark_types.
|
|
2
|
+
import type { BenchmarkConfig, BenchmarkResult } from '@fuzdev/fuz_util/benchmark_types.ts';
|
|
3
3
|
import type { BootstrappedBackendHandle } from '../setup.js';
|
|
4
4
|
import type { BenchScenario } from './scenario.js';
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../../assert_dev_env.js';
|
|
2
|
-
import { Benchmark } from '@fuzdev/fuz_util/benchmark.
|
|
2
|
+
import { Benchmark } from '@fuzdev/fuz_util/benchmark.ts';
|
|
3
3
|
/**
|
|
4
4
|
* Network-tuned defaults — fuz_util's micro-benchmark defaults (warmup 10,
|
|
5
5
|
* min 30, duration 1000ms) are sized for sub-microsecond functions. RPC round
|
|
@@ -6,7 +6,7 @@ import '../assert_dev_env.js';
|
|
|
6
6
|
* consumer's vitest `globalSetup` reduces to a single await:
|
|
7
7
|
*
|
|
8
8
|
* ```ts
|
|
9
|
-
* import {bootstrap_backend} from '@fuzdev/fuz_app/testing/cross_backend/bootstrap_backend.
|
|
9
|
+
* import {bootstrap_backend} from '@fuzdev/fuz_app/testing/cross_backend/bootstrap_backend.ts';
|
|
10
10
|
*
|
|
11
11
|
* export default async function ({provide}) {
|
|
12
12
|
* const bootstrapped = await bootstrap_backend(deno_backend_config());
|
|
@@ -139,12 +139,33 @@ export interface BackendCapabilities {
|
|
|
139
139
|
* smuggle detector. See `docs/security.md` §"Body Size Limiting".
|
|
140
140
|
*/
|
|
141
141
|
readonly oversized_reject_closes_connection: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* The backend can **initiate** a JSON-RPC request to a connected client
|
|
144
|
+
* and await its typed reply (the server→client request/response direction
|
|
145
|
+
* `ActionPeer` adds). Gates `describe_peer_ping_ws_tests` — the on-demand
|
|
146
|
+
* `peer/ping` round-trip plus its security negatives (unsolicited-response
|
|
147
|
+
* rejection, per-connection id isolation, never-replying `Timeout`,
|
|
148
|
+
* wrong-shape reply rejection).
|
|
149
|
+
*
|
|
150
|
+
* `true` for the Rust spine (server-initiated requests landed Rust-first
|
|
151
|
+
* canonical); `false` for the TS family — the TS server
|
|
152
|
+
* `BackendWebsocketTransport.send()` request path is the deferred
|
|
153
|
+
* twin-impl convergence item, so a TS backend can't yet drive the
|
|
154
|
+
* round-trip. Like ws/sse/cells, `peer/ping` stays off the standard
|
|
155
|
+
* declared surface (it's a protocol action, manifest-excluded), so this
|
|
156
|
+
* flag is the only opt-in into the peer parity coverage.
|
|
157
|
+
*/
|
|
158
|
+
readonly peer_request: boolean;
|
|
142
159
|
}
|
|
143
160
|
/**
|
|
144
|
-
* Capability declarations for the in-process Hono transport.
|
|
145
|
-
* is `true` because in-process testing exercises the full backend
|
|
146
|
-
* no missing optional behaviors.
|
|
147
|
-
*
|
|
161
|
+
* Capability declarations for the in-process Hono transport. Nearly every
|
|
162
|
+
* flag is `true` because in-process testing exercises the full backend
|
|
163
|
+
* with no missing optional behaviors. The one exception is `peer_request`:
|
|
164
|
+
* the in-process driver runs the **TS** server (`register_action_ws`),
|
|
165
|
+
* whose server-initiated request transport is deferred, so it can't drive
|
|
166
|
+
* a `peer/ping` round-trip — and `describe_peer_ping_ws_tests` is
|
|
167
|
+
* cross-process-only regardless. Cross-process consumers declare each flag
|
|
168
|
+
* explicitly per backend.
|
|
148
169
|
*/
|
|
149
170
|
export declare const in_process_capabilities: BackendCapabilities;
|
|
150
171
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwC9B;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,kCAAkC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAwC9B;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,kCAAkC,EAAE,OAAO,CAAC;IACrD;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAWpC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAInC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,EAAE,IAAI,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAG,IAMrF,CAAC"}
|
|
@@ -36,10 +36,14 @@ import '../assert_dev_env.js';
|
|
|
36
36
|
*/
|
|
37
37
|
import { test } from 'vitest';
|
|
38
38
|
/**
|
|
39
|
-
* Capability declarations for the in-process Hono transport.
|
|
40
|
-
* is `true` because in-process testing exercises the full backend
|
|
41
|
-
* no missing optional behaviors.
|
|
42
|
-
*
|
|
39
|
+
* Capability declarations for the in-process Hono transport. Nearly every
|
|
40
|
+
* flag is `true` because in-process testing exercises the full backend
|
|
41
|
+
* with no missing optional behaviors. The one exception is `peer_request`:
|
|
42
|
+
* the in-process driver runs the **TS** server (`register_action_ws`),
|
|
43
|
+
* whose server-initiated request transport is deferred, so it can't drive
|
|
44
|
+
* a `peer/ping` round-trip — and `describe_peer_ping_ws_tests` is
|
|
45
|
+
* cross-process-only regardless. Cross-process consumers declare each flag
|
|
46
|
+
* explicitly per backend.
|
|
43
47
|
*/
|
|
44
48
|
export const in_process_capabilities = Object.freeze({
|
|
45
49
|
ws: true,
|
|
@@ -51,6 +55,7 @@ export const in_process_capabilities = Object.freeze({
|
|
|
51
55
|
ready: true,
|
|
52
56
|
account_status: true,
|
|
53
57
|
oversized_reject_closes_connection: true,
|
|
58
|
+
peer_request: false,
|
|
54
59
|
});
|
|
55
60
|
/**
|
|
56
61
|
* Shape notes for the in-process Hono transport — every wiring fact present
|
|
@@ -52,7 +52,7 @@ import '../assert_dev_env.js';
|
|
|
52
52
|
* @module
|
|
53
53
|
*/
|
|
54
54
|
import { describe, assert } from 'vitest';
|
|
55
|
-
import { fractional_index_between } from '@fuzdev/fuz_util/fractional_index.
|
|
55
|
+
import { fractional_index_between } from '@fuzdev/fuz_util/fractional_index.ts';
|
|
56
56
|
import { CellCreateOutput, CellUpdateOutput, CellCloneOutput, CellGetOutput, } from '../../auth/cell_action_specs.js';
|
|
57
57
|
import { AuditLogListOutput } from '../../auth/admin_action_specs.js';
|
|
58
58
|
import { CellGrantCreateOutput, CellGrantListOutput, CellGrantRevokeOutput, } from '../../auth/cell_grant_action_specs.js';
|
|
@@ -85,6 +85,8 @@ export declare const ConformanceCaseExpectation: z.ZodObject<{
|
|
|
85
85
|
status: z.ZodNumber;
|
|
86
86
|
error_reason: z.ZodOptional<z.ZodString>;
|
|
87
87
|
fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
88
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
|
|
89
|
+
equivalence_group: z.ZodOptional<z.ZodString>;
|
|
88
90
|
}, z.core.$strict>;
|
|
89
91
|
export type ConformanceCaseExpectation = z.infer<typeof ConformanceCaseExpectation>;
|
|
90
92
|
/**
|
|
@@ -133,6 +135,8 @@ export declare const ConformanceCase: z.ZodObject<{
|
|
|
133
135
|
status: z.ZodNumber;
|
|
134
136
|
error_reason: z.ZodOptional<z.ZodString>;
|
|
135
137
|
fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
138
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
|
|
139
|
+
equivalence_group: z.ZodOptional<z.ZodString>;
|
|
136
140
|
}, z.core.$strict>;
|
|
137
141
|
note: z.ZodOptional<z.ZodString>;
|
|
138
142
|
xfail: z.ZodOptional<z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance_case.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_case.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;kBAgBjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,8DAA8D;AAC9D,eAAO,MAAM,0BAA0B
|
|
1
|
+
{"version":3,"file":"conformance_case.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_case.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;kBAgBjC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,8DAA8D;AAC9D,eAAO,MAAM,0BAA0B;;;;;;kBAiDrC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEpF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;kBAK/B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAS1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
|
|
@@ -96,6 +96,32 @@ export const ConformanceCaseExpectation = z.strictObject({
|
|
|
96
96
|
description: 'Specific field-value assertions on the success `result` (2xx) or the error ' +
|
|
97
97
|
'`error.data` (non-2xx). Each key must deep-equal the corresponding response field.',
|
|
98
98
|
}),
|
|
99
|
+
headers: z
|
|
100
|
+
.record(z.string(), z.string().nullable())
|
|
101
|
+
.optional()
|
|
102
|
+
.meta({
|
|
103
|
+
description: 'Per-header expectations on the response. Each key is a header name ' +
|
|
104
|
+
'(case-insensitive); a string value asserts the header is present and equals ' +
|
|
105
|
+
'it exactly, `null` asserts the header is ABSENT. Independent of this, the ' +
|
|
106
|
+
'runner enforces an unconditional no-fingerprint invariant on EVERY response ' +
|
|
107
|
+
'(`Server` / `X-Powered-By` / `WWW-Authenticate` must stay absent on both ' +
|
|
108
|
+
'spines), so a case only needs `headers` to pin a header beyond that ' +
|
|
109
|
+
'always-on floor.',
|
|
110
|
+
}),
|
|
111
|
+
equivalence_group: z
|
|
112
|
+
.string()
|
|
113
|
+
.optional()
|
|
114
|
+
.meta({
|
|
115
|
+
description: 'Tags this case as a member of an indistinguishability group. After all cases ' +
|
|
116
|
+
'run, the runner asserts every member of a group produced a BYTE-IDENTICAL ' +
|
|
117
|
+
'normalized response (`{status, body}`) — checked per impl. This promotes a ' +
|
|
118
|
+
'masked pair (found-but-unauthorized ≡ not-found, wrong-password ≡ ' +
|
|
119
|
+
'account-not-found) from "same status + reason" to "wire-indistinguishable", ' +
|
|
120
|
+
'and holds BOTH impls to it: a prober hitting either spine cannot tell the ' +
|
|
121
|
+
'members apart. A group needs >= 2 members; a member may still set `fields`. ' +
|
|
122
|
+
'The negative-space twin of the positive `output`-schema parity the runner ' +
|
|
123
|
+
'already asserts.',
|
|
124
|
+
}),
|
|
99
125
|
});
|
|
100
126
|
/**
|
|
101
127
|
* Marks a case as a deferred-by-design gap. The runner routes it through
|
|
@@ -36,6 +36,27 @@ export interface ConformanceTableOptions {
|
|
|
36
36
|
/** `describe` block label. Defaults to `'conformance table'`. */
|
|
37
37
|
readonly suite_name?: string;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Response headers that fingerprint the backend implementation or framework.
|
|
41
|
+
* Neither spine emits these; the runner asserts they stay absent on EVERY
|
|
42
|
+
* conformance response so a framework upgrade or consumer middleware that adds
|
|
43
|
+
* (say) `Server:` to one spine can't silently become a backend-identifying
|
|
44
|
+
* oracle. Lowercased — matched against the lowercased-key snapshot
|
|
45
|
+
* `headers_to_record` produces.
|
|
46
|
+
*/
|
|
47
|
+
export declare const FINGERPRINT_HEADERS: ReadonlyArray<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Assert a response carries none of the `FINGERPRINT_HEADERS`. Run on every
|
|
50
|
+
* case unconditionally — the always-on no-fingerprint floor.
|
|
51
|
+
*/
|
|
52
|
+
export declare const assert_no_fingerprint_headers: (headers: Record<string, string>, label: string) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Assert each declared header expectation: a string value must be present and
|
|
55
|
+
* equal (header name matched case-insensitively), `null` must be absent. The
|
|
56
|
+
* negative-space twin for headers — `expect.headers` pins a header beyond the
|
|
57
|
+
* always-on no-fingerprint floor.
|
|
58
|
+
*/
|
|
59
|
+
export declare const assert_expected_headers: (headers: Record<string, string>, expected: Record<string, string | null>, label: string) => void;
|
|
39
60
|
/**
|
|
40
61
|
* Register a `describe` block running every `ConformanceCase` as a
|
|
41
62
|
* vitest `test` (or `xfail_until` for deferred-by-design rows). Drives
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance_table.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_table.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"conformance_table.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/conformance_table.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AA8B9B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAE1D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAMjE,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,KAAK,eAAe,EAA4B,MAAM,uBAAuB,CAAC;AACtF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAC,SAAS,EAAc,MAAM,YAAY,CAAC;AAGvD;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACvC,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAC;IAChD,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AA+FD;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC,MAAM,CAIrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GACzC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,MAAM,KACX,IAQF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GACnC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACvC,OAAO,MAAM,KACX,IAYF,CAAC;AAgKF;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,GAAI,SAAS,uBAAuB,KAAG,IAkEnF,CAAC"}
|