@fuzdev/fuz_app 0.72.0 → 0.73.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.
@@ -47,7 +47,10 @@ export interface RpcRoundTripTestOptions {
47
47
  *
48
48
  * Error responses (from missing DB state, etc.) are expected and validated
49
49
  * as well-formed JSON-RPC errors. Successful responses are validated against
50
- * `action.spec.output`.
50
+ * `action.spec.output`. A `method not found` (-32601) error is the one
51
+ * exception — it means the backend is missing a method the local surface
52
+ * advertises, so the round-trip fails loud (`assert_method_implemented`)
53
+ * rather than accepting it as a valid error envelope.
51
54
  */
52
55
  export declare const describe_rpc_round_trip_tests: (options: RpcRoundTripTestOptions) => void;
53
56
  //# sourceMappingURL=rpc_round_trip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rpc_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/rpc_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAwB7B,OAAO,KAAK,EAAC,cAAc,EAAsB,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAMN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAC,SAAS,EAAc,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAE9D,mDAAmD;AACnD,MAAM,WAAW,uBAAuB;IACvC,kEAAkE;IAClE,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,uCAAuC;IACvC,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;;OAKG;IACH,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;OAKG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,qDAAqD;IACrD,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AA6BD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,6BAA6B,GAAI,SAAS,uBAAuB,KAAG,IAkHhF,CAAC"}
1
+ {"version":3,"file":"rpc_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/rpc_round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAyB7B,OAAO,KAAK,EAAC,cAAc,EAAsB,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAMN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAC,SAAS,EAAc,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAE9D,mDAAmD;AACnD,MAAM,WAAW,uBAAuB;IACvC,kEAAkE;IAClE,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,uCAAuC;IACvC,YAAY,EAAE,mBAAmB,CAAC;IAClC;;;;;OAKG;IACH,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;OAKG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,qDAAqD;IACrD,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AAoDD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,6BAA6B,GAAI,SAAS,uBAAuB,KAAG,IAoHhF,CAAC"}
@@ -15,8 +15,9 @@ import './assert_dev_env.js';
15
15
  *
16
16
  * @module
17
17
  */
18
- import { describe, test, beforeAll } from 'vitest';
18
+ import { describe, test, beforeAll, assert } from 'vitest';
19
19
  import { ROLE_ADMIN } from '../auth/role_schema.js';
20
+ import { JSONRPC_METHOD_NOT_FOUND, JsonrpcErrorResponse } from '../http/jsonrpc.js';
20
21
  import { generate_valid_body } from './schema_generators.js';
21
22
  import { is_public_auth } from '../http/auth_shape.js';
22
23
  import { create_rpc_post_init, create_rpc_get_url, assert_jsonrpc_error_response, assert_jsonrpc_success_response, resolve_rpc_endpoints_for_setup, } from './rpc_helpers.js';
@@ -41,6 +42,26 @@ const pick_rpc_auth_headers = (method, keeper, authed_account, admin_account) =>
41
42
  }
42
43
  return authed_account.create_session_headers();
43
44
  };
45
+ /**
46
+ * Guard against silent parity gaps: a method enumerated from the local action
47
+ * surface that the remote backend answers with `method not found` (-32601)
48
+ * means the backend is missing an implementation the local surface advertises.
49
+ * That is a well-formed JSON-RPC error, so the round-trip's
50
+ * `assert_jsonrpc_error_response` branch would otherwise accept it as a pass —
51
+ * masking missing methods across coequal backends. Fail loud instead, before
52
+ * the generic error-envelope acceptance runs.
53
+ *
54
+ * Only `JSONRPC_METHOD_NOT_FOUND` trips this — every other well-formed error
55
+ * (validation, `not_found` from missing DB state, auth denials) stays a valid
56
+ * round-trip outcome.
57
+ */
58
+ const assert_method_implemented = (method, body) => {
59
+ const parsed = JsonrpcErrorResponse.safeParse(body);
60
+ if (parsed.success && parsed.data.error.code === JSONRPC_METHOD_NOT_FOUND) {
61
+ assert.fail(`method '${method}' is registered on the local surface but the backend` +
62
+ ` returned method-not-found — backend is missing this method (parity gap)`);
63
+ }
64
+ };
44
65
  /**
45
66
  * Run schema-driven round-trip validation for RPC endpoints.
46
67
  *
@@ -53,7 +74,10 @@ const pick_rpc_auth_headers = (method, keeper, authed_account, admin_account) =>
53
74
  *
54
75
  * Error responses (from missing DB state, etc.) are expected and validated
55
76
  * as well-formed JSON-RPC errors. Successful responses are validated against
56
- * `action.spec.output`.
77
+ * `action.spec.output`. A `method not found` (-32601) error is the one
78
+ * exception — it means the backend is missing a method the local surface
79
+ * advertises, so the round-trip fails loud (`assert_method_implemented`)
80
+ * rather than accepting it as a valid error envelope.
57
81
  */
58
82
  export const describe_rpc_round_trip_tests = (options) => {
59
83
  const skip_set = new Set(options.skip_methods);
@@ -103,6 +127,7 @@ export const describe_rpc_round_trip_tests = (options) => {
103
127
  assert_jsonrpc_success_response(body, action.spec.output);
104
128
  }
105
129
  else {
130
+ assert_method_implemented(action.spec.method, body);
106
131
  assert_jsonrpc_error_response(body);
107
132
  }
108
133
  }
@@ -135,6 +160,7 @@ export const describe_rpc_round_trip_tests = (options) => {
135
160
  assert_jsonrpc_success_response(body, action.spec.output);
136
161
  }
137
162
  else {
163
+ assert_method_implemented(action.spec.method, body);
138
164
  assert_jsonrpc_error_response(body);
139
165
  }
140
166
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_app",
3
- "version": "0.72.0",
3
+ "version": "0.73.0",
4
4
  "description": "fullstack app library",
5
5
  "glyph": "🗝",
6
6
  "logo": "logo.svg",
@@ -48,6 +48,12 @@
48
48
  "@hono/node-ws": {
49
49
  "optional": true
50
50
  },
51
+ "@node-rs/argon2": {
52
+ "optional": true
53
+ },
54
+ "hono": {
55
+ "optional": true
56
+ },
51
57
  "pg": {
52
58
  "optional": true
53
59
  },