@fuzdev/fuz_app 0.110.0 → 0.110.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"admin_integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/admin_integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAgC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAW3E,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAkB1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,0BAA0B,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,mCAAmC;IACnD;;;;OAIG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,uCAAuC;IACvC,YAAY,EAAE,mBAAmB,CAAC;IAClC,uFAAuF;IACvF,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,4GAA4G;IAC5G,KAAK,EAAE,gBAAgB,CAAC;IACxB;;;OAGG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAiBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,mCAAmC,KAC1C,IA23BF,CAAC"}
1
+ {"version":3,"file":"admin_integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/admin_integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAgC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAW3E,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAmB1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,0BAA0B,CAAC;AAYvE;;GAEG;AACH,MAAM,WAAW,mCAAmC;IACnD;;;;OAIG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,uCAAuC;IACvC,YAAY,EAAE,mBAAmB,CAAC;IAClC,uFAAuF;IACvF,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,4GAA4G;IAC5G,KAAK,EAAE,gBAAgB,CAAC;IACxB;;;OAGG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAiBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,mCAAmC,KAC1C,IAm5BF,CAAC"}
@@ -36,6 +36,14 @@ import { rpc_call_for_spec, require_rpc_endpoint_path, resolve_rpc_endpoints_for
36
36
  import { role_grant_offer_create_action_spec, role_grant_revoke_action_spec } from '../auth/role_grant_offer_action_specs.js';
37
37
  import { admin_account_list_action_spec, ADMIN_ACCOUNT_LIST_LIMIT_MAX, admin_session_list_action_spec, admin_session_revoke_all_action_spec, admin_token_revoke_all_action_spec, audit_log_list_action_spec, audit_log_role_grant_history_action_spec } from '../auth/admin_action_specs.js';
38
38
  import { account_token_create_action_spec, account_verify_action_spec } from '../auth/account_action_specs.js';
39
+ /**
40
+ * How long a failure-audit read waits for the pool-routed row to land.
41
+ */
42
+ const AUDIT_FAILURE_ROW_TIMEOUT = 2000;
43
+ /**
44
+ * Gap between failure-audit read attempts.
45
+ */
46
+ const AUDIT_FAILURE_ROW_POLL_INTERVAL = 20;
39
47
  /**
40
48
  * Pick a role for admin-grant testing, preferring a non-admin app-defined
41
49
  * role whose `RoleSpec.grant_paths` includes `'admin'` (the
@@ -112,6 +120,43 @@ export const describe_standard_admin_integration_tests = (options) => {
112
120
  * the cross-suite contract.
113
121
  */
114
122
  const offer_and_accept = (args) => role_grant_offer_and_accept({ ...args, rpc_path });
123
+ /**
124
+ * Read `audit_log_list` for `event_type` until a failure-outcome row
125
+ * appears, or the deadline passes.
126
+ *
127
+ * Failure audits are **pool-routed** on both spines — the write is
128
+ * deliberately detached from the request transaction so the forensic row
129
+ * survives the rollback that discards the attempted mutation. A single
130
+ * read taken straight after the refusal therefore races that write. The
131
+ * TS spine wins the race by construction (`create_test_app` sets
132
+ * `await_pending_effects: true`, so the emit is awaited before the
133
+ * response returns) and the first attempt succeeds; the Rust spine emits
134
+ * from a detached task, so under load the row can land after the read —
135
+ * observed as a load-dependent drop of the revoke-all failure-audit
136
+ * cases in a busy cross-process run.
137
+ *
138
+ * The cross-backend conformance suites reach for the deterministic
139
+ * `_testing_drain_effects` barrier instead. That action is test-binary
140
+ * only, and this suite also runs against consumers' production RPC
141
+ * surfaces where it isn't mounted — hence a bounded poll.
142
+ */
143
+ const read_failure_audit_event = async (fixture, event_type) => {
144
+ const deadline = Date.now() + AUDIT_FAILURE_ROW_TIMEOUT;
145
+ for (;;) {
146
+ const audit_res = await rpc_call_for_spec({
147
+ app: { request: fixture.transport },
148
+ path: rpc_path,
149
+ spec: audit_log_list_action_spec,
150
+ params: { event_type },
151
+ headers: fixture.create_session_headers()
152
+ });
153
+ assert.ok(audit_res.ok, 'audit_log_list should succeed');
154
+ const failure = audit_res.result.events.find((e) => e.outcome === 'failure');
155
+ if (failure || Date.now() >= deadline)
156
+ return failure;
157
+ await new Promise((resolve) => setTimeout(resolve, AUDIT_FAILURE_ROW_POLL_INTERVAL));
158
+ }
159
+ };
115
160
  // --- 1. Admin account listing (RPC) ---
116
161
  describe('admin account listing', () => {
117
162
  test('admin can list all accounts', async () => {
@@ -476,15 +521,7 @@ export const describe_standard_admin_integration_tests = (options) => {
476
521
  // Failure audit row should be visible on the audit-log feed.
477
522
  // `target_account_id` is null (FK prevents referencing a missing id)
478
523
  // — the probed id is preserved under `metadata.attempted_account_id`.
479
- const audit_res = await rpc_call_for_spec({
480
- app: { request: fixture.transport },
481
- path: rpc_path,
482
- spec: audit_log_list_action_spec,
483
- params: { event_type: 'session_revoke_all' },
484
- headers: fixture.create_session_headers()
485
- });
486
- assert.ok(audit_res.ok, 'audit_log_list should succeed');
487
- const failure = audit_res.result.events.find((e) => e.outcome === 'failure');
524
+ const failure = await read_failure_audit_event(fixture, 'session_revoke_all');
488
525
  assert.ok(failure, 'Expected a failure-outcome session_revoke_all audit event');
489
526
  assert.strictEqual(failure.target_account_id, null);
490
527
  const failure_meta = failure.metadata;
@@ -504,15 +541,7 @@ export const describe_standard_admin_integration_tests = (options) => {
504
541
  assert.ok(!res.ok, 'Expected 404 for missing account');
505
542
  assert.strictEqual(res.status, 404);
506
543
  assert.strictEqual(res.error.data.reason, 'account_not_found');
507
- const audit_res = await rpc_call_for_spec({
508
- app: { request: fixture.transport },
509
- path: rpc_path,
510
- spec: audit_log_list_action_spec,
511
- params: { event_type: 'token_revoke_all' },
512
- headers: fixture.create_session_headers()
513
- });
514
- assert.ok(audit_res.ok, 'audit_log_list should succeed');
515
- const failure = audit_res.result.events.find((e) => e.outcome === 'failure');
544
+ const failure = await read_failure_audit_event(fixture, 'token_revoke_all');
516
545
  assert.ok(failure, 'Expected a failure-outcome token_revoke_all audit event');
517
546
  assert.strictEqual(failure.target_account_id, null);
518
547
  const failure_meta = failure.metadata;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_app",
3
- "version": "0.110.0",
3
+ "version": "0.110.1",
4
4
  "description": "fullstack app library",
5
5
  "glyph": "🗝",
6
6
  "logo": "logo.svg",