@fuzdev/fuz_app 0.84.0 → 0.85.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.
- package/dist/testing/CLAUDE.md +32 -5
- package/dist/testing/cross_backend/testing_backdoor.d.ts +6 -0
- package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -0
- package/dist/testing/cross_backend/testing_backdoor.js +126 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +12 -3
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +40 -9
- package/dist/testing/cross_backend/testing_server_core.d.ts +13 -2
- package/dist/testing/cross_backend/testing_server_core.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_server_core.js +19 -7
- package/dist/testing/db.d.ts +9 -16
- package/dist/testing/db.d.ts.map +1 -1
- package/dist/testing/db.js +12 -32
- package/dist/testing/mock_fs.d.ts +1 -0
- package/dist/testing/mock_fs.d.ts.map +1 -1
- package/dist/testing/mock_fs.js +1 -6
- package/dist/testing/surface_invariants.d.ts +34 -1
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +49 -1
- package/dist/testing/ws_round_trip.d.ts +1 -0
- package/dist/testing/ws_round_trip.d.ts.map +1 -1
- package/dist/testing/ws_round_trip.js +1 -38
- package/dist/ui/ConfirmButton.svelte +4 -5
- package/dist/ui/ConfirmButton.svelte.d.ts.map +1 -1
- package/package.json +5 -4
package/dist/testing/CLAUDE.md
CHANGED
|
@@ -13,9 +13,13 @@ 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 module here starts with `import './assert_dev_env.js';`
|
|
17
|
-
from `esm-env` and throws if false, preventing production-bundle
|
|
18
|
-
|
|
16
|
+
Every runtime-reachable module here starts with `import './assert_dev_env.js';`
|
|
17
|
+
— reads `DEV` from `esm-env` and throws if false, preventing production-bundle
|
|
18
|
+
inclusion. Make this the first line in new modules. Enforced by
|
|
19
|
+
`src/test/testing/assert_dev_env_coverage.test.ts`, which fails if any module
|
|
20
|
+
omits the guard. The sole exemption is `cross_backend/make_cross_backend_project.ts`
|
|
21
|
+
— a vitest-project factory consumed by consumers' `vite.config.ts` at config
|
|
22
|
+
time (never runtime), where a throwing guard would break `vite build`.
|
|
19
23
|
|
|
20
24
|
## Stubs, factories, mocks
|
|
21
25
|
|
|
@@ -121,8 +125,7 @@ factories accept any migration namespace set.
|
|
|
121
125
|
- `create_pg_factory(init_schema, test_url?)` — PostgreSQL; `skip: true` when `test_url` missing. Drops `schema_version` before `init_schema` so migrations re-evaluate against actual tables (prevents stale tracker rows from skipping migrations when DDL changes between sessions). Pool reused + cleaned up across `create()` calls.
|
|
122
126
|
- `auth_truncate_tables` — `['invite', 'api_token', 'auth_session', 'role_grant', 'role_grant_offer', 'actor', 'account']` in FK-safe order. Excludes `audit_log` — unit DB tests don't need to truncate it.
|
|
123
127
|
- `auth_integration_truncate_tables` — `auth_truncate_tables + ['audit_log']` for integration suites that exercise the audit path.
|
|
124
|
-
- `
|
|
125
|
-
- `drop_auth_schema(db)` — `DROP TABLE IF EXISTS <table> CASCADE` for every entry in `auth_drop_tables` plus `schema_version`. Safe on fresh DBs.
|
|
128
|
+
- `drop_auth_schema(db)` — `DROP SCHEMA public CASCADE; CREATE SCHEMA public`; call at the top of `init_schema` on persistent pg databases that may hold stale DDL from previous fuz_app versions. Drift-proof full-schema reset (despite the name, not auth-scoped) — same mechanism as `reset_pglite`.
|
|
126
129
|
- `create_describe_db(factories, truncate_tables)` — returns `describe_db(name, fn)` running `fn(get_db)` once per factory inside a `describe` with shared `beforeAll(create)` + `beforeEach(TRUNCATE)` + `afterAll(close)`. Skipped factories use `describe.skip`.
|
|
127
130
|
- `log_db_factory_status(factories)` — console summary of enabled / skipped factories.
|
|
128
131
|
|
|
@@ -275,6 +278,7 @@ RPC / WS structural invariants (options-free, apply over `surface.rpc_endpoints`
|
|
|
275
278
|
* `assert_ws_method_descriptions_present` — every WS method on every endpoint has a non-empty `description`.
|
|
276
279
|
* `assert_ws_endpoints_include_protocol_actions` — every WS endpoint includes `heartbeat` + `cancel` (the `protocol_actions` spread from `actions/protocol.js`).
|
|
277
280
|
* `assert_ws_notifications_have_null_auth` — WS method `kind === 'remote_notification' ⟺ auth === null`; guards against drift between spec union and surface emitter.
|
|
281
|
+
* `assert_no_testing_methods` — no `_testing_*` backdoor action (`TESTING_METHOD_PREFIX`) appears as an RPC or WS method on the declared surface. The test-binary actions are live-mounted only; this guards against a future wiring change folding `create_testing_actions(...)` into the surface-generating registry.
|
|
278
282
|
|
|
279
283
|
Per-endpoint duplicate method names and the auth-shape biconditional are
|
|
280
284
|
already enforced at startup by `compile_action_registry` (see
|
|
@@ -1209,6 +1213,29 @@ spine bootstrap (auth + cell + cell_history + fact) and is regenerated +
|
|
|
1209
1213
|
drift-guarded by `src/test/cross_backend/spine_expected_schema.db.test.ts`
|
|
1210
1214
|
(`UPDATE_SCHEMA_READY=1`, then `gro format`).
|
|
1211
1215
|
|
|
1216
|
+
### Testing-backdoor credential gate — `cross_backend/testing_backdoor.ts`
|
|
1217
|
+
|
|
1218
|
+
`describe_testing_backdoor_cross_tests({setup_test, capabilities, rpc_path?})` —
|
|
1219
|
+
the negative-credential parity suite for the `_testing_*` backdoor actions.
|
|
1220
|
+
For each of `_testing_reset` / `_testing_mint_session` / `_testing_put_fact` /
|
|
1221
|
+
`_testing_schema_snapshot` (the three privileged writes plus the schema-dump
|
|
1222
|
+
read) it fires three principals over real HTTP: **anonymous** → 401, **session** →
|
|
1223
|
+
403 `credential_type_required`, **bearer** → 403 `credential_type_required` —
|
|
1224
|
+
proving the daemon-token gate that fences each backdoor action holds end-to-end
|
|
1225
|
+
on the real dispatcher (the spec-derived `describe_rpc_attack_surface_tests`
|
|
1226
|
+
never enumerates them because they're off the declared surface). Each method is
|
|
1227
|
+
sent with **valid** params so the session/bearer cases clear the 400
|
|
1228
|
+
input-validation phase and reach the 403 credential gate (order is
|
|
1229
|
+
401 → 400 → 403); the handler never runs. Cited property: `docs/security.md`
|
|
1230
|
+
§Test Backdoor Actions. Cross-process only (the `_testing_*` actions are
|
|
1231
|
+
mounted on the spawned binary, not the in-process app — like the ws/sse
|
|
1232
|
+
suites); ungated, since every cross backend that uses
|
|
1233
|
+
`default_cross_process_setup` mounts them. fuz_app's own wiring is
|
|
1234
|
+
`src/test/cross_backend/testing_backdoor.cross.test.ts`. The complement is the
|
|
1235
|
+
in-process spec-level gate test (`src/test/testing/testing_actions_auth.test.ts`,
|
|
1236
|
+
asserting each spec declares `credential_types: ['daemon_token']`) + the
|
|
1237
|
+
`assert_no_testing_methods` surface invariant.
|
|
1238
|
+
|
|
1212
1239
|
### Building a TS test-server binary — `testing_server_core.ts` + adapters
|
|
1213
1240
|
|
|
1214
1241
|
The reusable shape for standing up a **spawnable TS** cross-process test
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
import type { CellCrossTestOptions } from './cell_cross_helpers.js';
|
|
3
|
+
/** Options for the testing-backdoor negative-credential suite. */
|
|
4
|
+
export type TestingBackdoorCrossTestOptions = CellCrossTestOptions;
|
|
5
|
+
export declare const describe_testing_backdoor_cross_tests: (options: TestingBackdoorCrossTestOptions) => void;
|
|
6
|
+
//# sourceMappingURL=testing_backdoor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing_backdoor.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_backdoor.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAyD9B,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,yBAAyB,CAAC;AAgElE,kEAAkE;AAClE,MAAM,MAAM,+BAA+B,GAAG,oBAAoB,CAAC;AAEnE,eAAO,MAAM,qCAAqC,GACjD,SAAS,+BAA+B,KACtC,IAiCF,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import '../assert_dev_env.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-backend negative-credential suite for the `_testing_*` backdoor
|
|
4
|
+
* actions.
|
|
5
|
+
*
|
|
6
|
+
* `_testing_reset` / `_testing_mint_session` / `_testing_put_fact` /
|
|
7
|
+
* `_testing_schema_snapshot` are privileged test-binary actions the
|
|
8
|
+
* production wire never exposes — three direct DB writes (full auth wipe,
|
|
9
|
+
* forged session row, raw fact insert) plus a full-schema introspection read
|
|
10
|
+
* (the highest info-leak of the set were the gate to break). Their only
|
|
11
|
+
* structural fence is the **daemon-token** credential gate on
|
|
12
|
+
* each spec's `auth` axis. A test binary live-mounts them on its RPC
|
|
13
|
+
* endpoint but keeps them off the declared surface — so the spec-derived
|
|
14
|
+
* `describe_rpc_attack_surface_tests` never enumerates them, and nothing
|
|
15
|
+
* else fires them with a non-daemon credential to prove the gate holds
|
|
16
|
+
* end-to-end. This suite does, against each impl's real auth resolution.
|
|
17
|
+
*
|
|
18
|
+
* For every backdoor method, three principals:
|
|
19
|
+
*
|
|
20
|
+
* - **anonymous** (no credential) → `401` (pre-validation auth refuses an
|
|
21
|
+
* account-less caller before anything else).
|
|
22
|
+
* - **session** (the keeper's browser-context cookie) → `403`
|
|
23
|
+
* `credential_type_required` — a session cookie, even one carrying the
|
|
24
|
+
* keeper role, tops out below the daemon-token channel.
|
|
25
|
+
* - **bearer** (the keeper's api-token, non-browser context) → `403`
|
|
26
|
+
* `credential_type_required` — same ceiling; an api token cannot reach
|
|
27
|
+
* keeper operations.
|
|
28
|
+
*
|
|
29
|
+
* Each method is sent with **valid** params so the session/bearer cases
|
|
30
|
+
* clear the dispatcher's input-validation (400) phase and actually reach the
|
|
31
|
+
* post-authorization credential gate (the order is 401 → 400 → 403); the
|
|
32
|
+
* handler never runs (the gate refuses first), so the writes never execute.
|
|
33
|
+
*
|
|
34
|
+
* Complements the spec-level gate check (which pins that each spec *declares*
|
|
35
|
+
* `credential_types: ['daemon_token']`) and the surface-absence invariant
|
|
36
|
+
* (`assert_no_testing_methods`) — this one pins the runtime 401/403 behavior
|
|
37
|
+
* on both impls. Cited property: `security.md` §Test Backdoor Actions
|
|
38
|
+
* (daemon-token-gated, off-surface, DEV-excluded).
|
|
39
|
+
*
|
|
40
|
+
* Cross-process only — the `_testing_*` actions are mounted on the spawned
|
|
41
|
+
* binary, not the in-process app — like the ws/sse suites. Wire from a
|
|
42
|
+
* `*.cross.test.ts`. Requires the standard `_testing_*` actions mounted (the
|
|
43
|
+
* same precondition `default_cross_process_setup` already imposes for its
|
|
44
|
+
* per-test `_testing_reset`); ungated, since every cross backend mounts them.
|
|
45
|
+
*
|
|
46
|
+
* `$lib`-free by contract (relative specifiers only), like the sibling
|
|
47
|
+
* cross-backend suites.
|
|
48
|
+
*
|
|
49
|
+
* @module
|
|
50
|
+
*/
|
|
51
|
+
import { describe, test, assert } from 'vitest';
|
|
52
|
+
import { ERROR_CREDENTIAL_TYPE_REQUIRED } from '../../http/error_schemas.js';
|
|
53
|
+
import { rpc_call } from '../rpc_helpers.js';
|
|
54
|
+
import { SPINE_RPC_PATH } from './default_spine_surface.js';
|
|
55
|
+
/** A well-formed UUID that never names a real row. */
|
|
56
|
+
const NIL_UUID = '00000000-0000-0000-0000-000000000000';
|
|
57
|
+
/**
|
|
58
|
+
* The backdoor methods + a **valid** params payload each (so the
|
|
59
|
+
* session/bearer cases reach the 403 credential gate rather than a 400 on
|
|
60
|
+
* input validation). The handlers never run — the gate refuses first.
|
|
61
|
+
*/
|
|
62
|
+
const backdoor_methods = [
|
|
63
|
+
{ method: '_testing_reset', params: {} },
|
|
64
|
+
{ method: '_testing_mint_session', params: { account_id: NIL_UUID, expires_in_seconds: -60 } },
|
|
65
|
+
{ method: '_testing_put_fact', params: { content: 'backdoor-probe' } },
|
|
66
|
+
// The schema-dump read — `exclude_tables` is optional, so `{}` is valid
|
|
67
|
+
// and clears the 400 phase like the writes above.
|
|
68
|
+
{ method: '_testing_schema_snapshot', params: {} },
|
|
69
|
+
];
|
|
70
|
+
const principals = [
|
|
71
|
+
{
|
|
72
|
+
name: 'anonymous',
|
|
73
|
+
status: 401,
|
|
74
|
+
// Fresh jar so the keeper cookie (cross-process) can't leak in.
|
|
75
|
+
resolve: (f) => ({ transport: f.fresh_transport(), headers: {} }),
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'session',
|
|
79
|
+
status: 403,
|
|
80
|
+
reason: ERROR_CREDENTIAL_TYPE_REQUIRED,
|
|
81
|
+
resolve: (f) => ({ transport: f.transport, headers: f.create_session_headers() }),
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'bearer',
|
|
85
|
+
status: 403,
|
|
86
|
+
reason: ERROR_CREDENTIAL_TYPE_REQUIRED,
|
|
87
|
+
// Bearer is discarded in a browser context, so suppress Origin (empty
|
|
88
|
+
// jar + no Origin) — the credential must actually resolve so the refusal
|
|
89
|
+
// lands on the credential-type gate, not on bearer-discard (→ 401).
|
|
90
|
+
resolve: (f) => ({
|
|
91
|
+
transport: f.fresh_transport({ origin: null }),
|
|
92
|
+
headers: f.create_bearer_headers(),
|
|
93
|
+
suppress_default_origin: true,
|
|
94
|
+
}),
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
export const describe_testing_backdoor_cross_tests = (options) => {
|
|
98
|
+
const { setup_test } = options;
|
|
99
|
+
const rpc_path = options.rpc_path ?? SPINE_RPC_PATH;
|
|
100
|
+
describe('testing backdoor credential gate parity', () => {
|
|
101
|
+
for (const { method, params } of backdoor_methods) {
|
|
102
|
+
for (const principal of principals) {
|
|
103
|
+
test(`${method} rejects ${principal.name} → ${principal.status}`, async () => {
|
|
104
|
+
const fixture = await setup_test();
|
|
105
|
+
const { transport, headers, suppress_default_origin } = principal.resolve(fixture);
|
|
106
|
+
const res = await rpc_call({
|
|
107
|
+
app: transport,
|
|
108
|
+
path: rpc_path,
|
|
109
|
+
method,
|
|
110
|
+
params,
|
|
111
|
+
headers,
|
|
112
|
+
...(suppress_default_origin && { suppress_default_origin: true }),
|
|
113
|
+
});
|
|
114
|
+
const label = `${method} ${principal.name}`;
|
|
115
|
+
assert.ok(!res.ok, `${label}: expected denial (${principal.status}) but the call succeeded`);
|
|
116
|
+
assert.strictEqual(res.status, principal.status, `${label}: status`);
|
|
117
|
+
// `!res.ok` narrows `res` to the error variant for `res.error`.
|
|
118
|
+
if (principal.reason !== undefined && !res.ok) {
|
|
119
|
+
const reason = res.error.data?.reason;
|
|
120
|
+
assert.strictEqual(reason, principal.reason, `${label}: error.data.reason`);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
};
|
|
@@ -183,9 +183,18 @@ export declare const testing_drain_effects_action_spec: {
|
|
|
183
183
|
* `_testing_mint_session` — mint an expired-by-construction server-side
|
|
184
184
|
* session for an existing account and return its signed cookie value.
|
|
185
185
|
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
186
|
+
* `expires_in_seconds` is **constrained negative** (`z.number().int().negative()`)
|
|
187
|
+
* so the action is structurally incapable of minting a *usable* session: it
|
|
188
|
+
* can only produce an already-backdated, already-dead `auth_session` row. The
|
|
189
|
+
* daemon-token gate + loopback binding already fence the backdoor, but the
|
|
190
|
+
* negative constraint is the make-impossible-states floor — even a misuse
|
|
191
|
+
* can't forge a valid session for an arbitrary `account_id`. The Rust mirror
|
|
192
|
+
* (`fuz_testing::create_testing_mint_session_action_spec`) enforces the same
|
|
193
|
+
* floor.
|
|
194
|
+
*
|
|
195
|
+
* The minted `auth_session` row's `expires_at` is backdated while the
|
|
196
|
+
* returned cookie's own signed payload stays valid (future). Cross-process
|
|
197
|
+
* auth resolution therefore passes the
|
|
189
198
|
* cookie-payload gate (`parse_session`) and is refused by the authoritative
|
|
190
199
|
* DB-row gate (`query_session_get_valid` — `WHERE expires_at > NOW()`) —
|
|
191
200
|
* the gate the in-process payload-expiry tests never reach and the one that
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing_reset_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_reset_actions.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAItB,OAAO,EAAa,KAAK,SAAS,EAAC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"testing_reset_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_reset_actions.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAItB,OAAO,EAAa,KAAK,SAAS,EAAC,MAAM,6BAA6B,CAAC;AAIvE,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,gBAAgB,CAAC;AAkCvC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;QAiBpC;;;;;;;;WAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWyC,CAAC;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;CAWA,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;CAwBC,CAAC;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,QAAO,SACiB,CAAC;AAEzE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;CAeK,CAAC;AAE/C;;;;;;;;;GASG;AACH,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWF,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,QAAO,SAGvD,CAAC;AAEH,4CAA4C;AAC5C,MAAM,WAAW,2BAA2B;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC9C;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACxD;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,OAAO,EACb,SAAS,2BAA2B,KAClC,KAAK,CAAC,SAAS,CAqIjB,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,UAAmC,CAAC"}
|
|
@@ -68,6 +68,20 @@ import { auth_integration_truncate_tables } from '../db.js';
|
|
|
68
68
|
import { query_schema_snapshot, SchemaSnapshot } from '../schema_introspect.js';
|
|
69
69
|
import { query_create_actor } from '../../auth/account_queries.js';
|
|
70
70
|
import { create_test_account_with_credentials, mint_test_session, DEFAULT_TEST_PASSWORD, } from '../app_server.js';
|
|
71
|
+
/**
|
|
72
|
+
* Shared `auth` axis for every `_testing_*` action: keeper-only via the
|
|
73
|
+
* daemon-token credential, no acting actor. This is the entire structural
|
|
74
|
+
* fence on the backdoor surface (these actions run direct DB writes the
|
|
75
|
+
* production wire never exposes), so all five specs reference this one const
|
|
76
|
+
* rather than re-declaring it — a single source of truth the gate test
|
|
77
|
+
* (`testing_actions_auth.test.ts`) pins. Mirrors the Rust `DAEMON_TOKEN_ONLY`
|
|
78
|
+
* / shared `AuthSpec` in `fuz_testing`.
|
|
79
|
+
*/
|
|
80
|
+
const TESTING_ACTION_AUTH = {
|
|
81
|
+
account: 'required',
|
|
82
|
+
actor: 'none',
|
|
83
|
+
credential_types: ['daemon_token'],
|
|
84
|
+
};
|
|
71
85
|
/** Output shape for an individual seeded account (keeper or extra). */
|
|
72
86
|
const SeededAccountShape = z.strictObject({
|
|
73
87
|
account: z.strictObject({ id: Uuid, username: z.string() }),
|
|
@@ -104,7 +118,7 @@ export const testing_reset_action_spec = {
|
|
|
104
118
|
method: '_testing_reset',
|
|
105
119
|
kind: 'request_response',
|
|
106
120
|
initiator: 'frontend',
|
|
107
|
-
auth:
|
|
121
|
+
auth: TESTING_ACTION_AUTH,
|
|
108
122
|
side_effects: true,
|
|
109
123
|
input: z.strictObject({
|
|
110
124
|
extra_keeper_roles: z.array(z.string()).optional(),
|
|
@@ -154,7 +168,7 @@ export const testing_drain_effects_action_spec = {
|
|
|
154
168
|
method: '_testing_drain_effects',
|
|
155
169
|
kind: 'request_response',
|
|
156
170
|
initiator: 'frontend',
|
|
157
|
-
auth:
|
|
171
|
+
auth: TESTING_ACTION_AUTH,
|
|
158
172
|
side_effects: false,
|
|
159
173
|
input: z.void(),
|
|
160
174
|
output: z.strictObject({ ok: z.boolean() }),
|
|
@@ -165,9 +179,18 @@ export const testing_drain_effects_action_spec = {
|
|
|
165
179
|
* `_testing_mint_session` — mint an expired-by-construction server-side
|
|
166
180
|
* session for an existing account and return its signed cookie value.
|
|
167
181
|
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
182
|
+
* `expires_in_seconds` is **constrained negative** (`z.number().int().negative()`)
|
|
183
|
+
* so the action is structurally incapable of minting a *usable* session: it
|
|
184
|
+
* can only produce an already-backdated, already-dead `auth_session` row. The
|
|
185
|
+
* daemon-token gate + loopback binding already fence the backdoor, but the
|
|
186
|
+
* negative constraint is the make-impossible-states floor — even a misuse
|
|
187
|
+
* can't forge a valid session for an arbitrary `account_id`. The Rust mirror
|
|
188
|
+
* (`fuz_testing::create_testing_mint_session_action_spec`) enforces the same
|
|
189
|
+
* floor.
|
|
190
|
+
*
|
|
191
|
+
* The minted `auth_session` row's `expires_at` is backdated while the
|
|
192
|
+
* returned cookie's own signed payload stays valid (future). Cross-process
|
|
193
|
+
* auth resolution therefore passes the
|
|
171
194
|
* cookie-payload gate (`parse_session`) and is refused by the authoritative
|
|
172
195
|
* DB-row gate (`query_session_get_valid` — `WHERE expires_at > NOW()`) —
|
|
173
196
|
* the gate the in-process payload-expiry tests never reach and the one that
|
|
@@ -186,11 +209,19 @@ export const testing_mint_session_action_spec = {
|
|
|
186
209
|
method: '_testing_mint_session',
|
|
187
210
|
kind: 'request_response',
|
|
188
211
|
initiator: 'frontend',
|
|
189
|
-
auth:
|
|
212
|
+
auth: TESTING_ACTION_AUTH,
|
|
190
213
|
side_effects: true,
|
|
191
214
|
input: z.strictObject({
|
|
192
215
|
account_id: Uuid,
|
|
193
|
-
expires_in_seconds: z
|
|
216
|
+
expires_in_seconds: z
|
|
217
|
+
.number()
|
|
218
|
+
.int()
|
|
219
|
+
.negative()
|
|
220
|
+
.meta({
|
|
221
|
+
description: 'Seconds to offset the session row from NOW(). Constrained negative so this ' +
|
|
222
|
+
'backdoor can ONLY mint an already-expired (backdated) row — never a usable ' +
|
|
223
|
+
'session for an arbitrary account. Its sole use is the expired-session gate.',
|
|
224
|
+
}),
|
|
194
225
|
}),
|
|
195
226
|
output: z.strictObject({ session_cookie: z.string() }),
|
|
196
227
|
async: true,
|
|
@@ -223,7 +254,7 @@ export const testing_put_fact_action_spec = {
|
|
|
223
254
|
method: '_testing_put_fact',
|
|
224
255
|
kind: 'request_response',
|
|
225
256
|
initiator: 'frontend',
|
|
226
|
-
auth:
|
|
257
|
+
auth: TESTING_ACTION_AUTH,
|
|
227
258
|
side_effects: true,
|
|
228
259
|
input: z.strictObject({
|
|
229
260
|
content: z.string(),
|
|
@@ -248,7 +279,7 @@ export const testing_schema_snapshot_action_spec = {
|
|
|
248
279
|
method: '_testing_schema_snapshot',
|
|
249
280
|
kind: 'request_response',
|
|
250
281
|
initiator: 'frontend',
|
|
251
|
-
auth:
|
|
282
|
+
auth: TESTING_ACTION_AUTH,
|
|
252
283
|
side_effects: false,
|
|
253
284
|
input: z.strictObject({ exclude_tables: z.array(z.string()).optional() }),
|
|
254
285
|
output: SchemaSnapshot,
|
|
@@ -127,14 +127,25 @@ export interface StartTestingServerOptions {
|
|
|
127
127
|
/** Optional logger; defaults to a `[daemon_name]`-namespaced `Logger`. */
|
|
128
128
|
log?: LoggerType;
|
|
129
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Loopback bind hosts — the only ones the test binary may serve on. It ships
|
|
132
|
+
* deterministic dev secrets (fixed cookie keys + bootstrap token in
|
|
133
|
+
* `default_secrets.ts`), so binding any network-reachable interface would let
|
|
134
|
+
* anyone who knows those fixed keys forge cookies against it. An allowlist
|
|
135
|
+
* (not an `0.0.0.0`/`::` blocklist) closes the gap a concrete LAN/public
|
|
136
|
+
* interface IP — e.g. `--host 192.168.1.50` — would otherwise slip through.
|
|
137
|
+
* Covers `localhost`, the IPv4 loopback `127.0.0.0/8`, and IPv6 `::1`.
|
|
138
|
+
*/
|
|
139
|
+
export declare const is_loopback_host: (host: string) => boolean;
|
|
130
140
|
/**
|
|
131
141
|
* Boot a test-mode server using the supplied runtime adapter.
|
|
132
142
|
*
|
|
133
143
|
* Mirrors a production `start_server` at the surface level — stale-daemon
|
|
134
144
|
* check, daemon-info write, bind, graceful drain — but the app is the
|
|
135
145
|
* caller's no-domain (or domain) {@link StartTestingServerOptions.build_app}
|
|
136
|
-
* and the runtime boundary is the {@link TestingServerAdapter}. Refuses
|
|
137
|
-
* bind
|
|
146
|
+
* and the runtime boundary is the {@link TestingServerAdapter}. Refuses any
|
|
147
|
+
* non-loopback bind host (the test binary must stay on loopback — see
|
|
148
|
+
* `is_loopback_host`).
|
|
138
149
|
*/
|
|
139
150
|
export declare const start_testing_server: (options: StartTestingServerOptions) => Promise<void>;
|
|
140
151
|
//# sourceMappingURL=testing_server_core.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing_server_core.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_server_core.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,MAAM,CAAC;AACxC,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAS,KAAK,MAAM,IAAI,UAAU,EAAC,MAAM,yBAAyB,CAAC;AAG1E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IACjC,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;CACjD;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACpC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,OAAO,EAAE,WAAW,CAAC;IACrB,6DAA6D;IAC7D,iBAAiB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,mFAAmF;IACnF,iBAAiB,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,iBAAiB,CAAC;IACpD,8EAA8E;IAC9E,KAAK,EAAE,CAAC,OAAO,EAAE;QAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,KAAK,WAAW,CAAC;IACxF,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,yBAAyB,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IAClE,oEAAoE;IACpE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC/B,kEAAkE;IAClE,GAAG,EAAE,IAAI,CAAC;IACV,qEAAqE;IACrE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,uEAAuE;IACvE,eAAe,CAAC,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAChE;AAED,gDAAgD;AAChD,MAAM,WAAW,yBAAyB;IACzC,+CAA+C;IAC/C,OAAO,EAAE,oBAAoB,CAAC;IAC9B;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,GAAG,CAAC,EAAE,UAAU,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"testing_server_core.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/testing_server_core.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,MAAM,CAAC;AACxC,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAS,KAAK,MAAM,IAAI,UAAU,EAAC,MAAM,yBAAyB,CAAC;AAG1E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IACjC,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;CACjD;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACpC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,OAAO,EAAE,WAAW,CAAC;IACrB,6DAA6D;IAC7D,iBAAiB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,mFAAmF;IACnF,iBAAiB,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,iBAAiB,CAAC;IACpD,8EAA8E;IAC9E,KAAK,EAAE,CAAC,OAAO,EAAE;QAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,KAAK,WAAW,CAAC;IACxF,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,yBAAyB,EAAE,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IAClE,oEAAoE;IACpE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC/B,kEAAkE;IAClE,GAAG,EAAE,IAAI,CAAC;IACV,qEAAqE;IACrE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,uEAAuE;IACvE,eAAe,CAAC,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAChE;AAED,gDAAgD;AAChD,MAAM,WAAW,yBAAyB;IACzC,+CAA+C;IAC/C,OAAO,EAAE,oBAAoB,CAAC;IAC9B;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,GAAG,CAAC,EAAE,UAAU,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,OAG/C,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAAU,SAAS,yBAAyB,KAAG,OAAO,CAAC,IAAI,CA4D3F,CAAC"}
|
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
import '../assert_dev_env.js';
|
|
2
2
|
import { Logger } from '@fuzdev/fuz_util/log.js';
|
|
3
3
|
import { write_daemon_info, read_daemon_info, is_daemon_running } from '../../cli/daemon.js';
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Loopback bind hosts — the only ones the test binary may serve on. It ships
|
|
6
|
+
* deterministic dev secrets (fixed cookie keys + bootstrap token in
|
|
7
|
+
* `default_secrets.ts`), so binding any network-reachable interface would let
|
|
8
|
+
* anyone who knows those fixed keys forge cookies against it. An allowlist
|
|
9
|
+
* (not an `0.0.0.0`/`::` blocklist) closes the gap a concrete LAN/public
|
|
10
|
+
* interface IP — e.g. `--host 192.168.1.50` — would otherwise slip through.
|
|
11
|
+
* Covers `localhost`, the IPv4 loopback `127.0.0.0/8`, and IPv6 `::1`.
|
|
12
|
+
*/
|
|
13
|
+
export const is_loopback_host = (host) => {
|
|
14
|
+
const h = host.replace(/^\[(.*)\]$/, '$1'); // unwrap an `[::1]`-style IPv6 literal
|
|
15
|
+
return h === 'localhost' || h === '::1' || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h);
|
|
16
|
+
};
|
|
6
17
|
/**
|
|
7
18
|
* Boot a test-mode server using the supplied runtime adapter.
|
|
8
19
|
*
|
|
9
20
|
* Mirrors a production `start_server` at the surface level — stale-daemon
|
|
10
21
|
* check, daemon-info write, bind, graceful drain — but the app is the
|
|
11
22
|
* caller's no-domain (or domain) {@link StartTestingServerOptions.build_app}
|
|
12
|
-
* and the runtime boundary is the {@link TestingServerAdapter}. Refuses
|
|
13
|
-
* bind
|
|
23
|
+
* and the runtime boundary is the {@link TestingServerAdapter}. Refuses any
|
|
24
|
+
* non-loopback bind host (the test binary must stay on loopback — see
|
|
25
|
+
* `is_loopback_host`).
|
|
14
26
|
*/
|
|
15
27
|
export const start_testing_server = async (options) => {
|
|
16
28
|
const { adapter, daemon_name, host, port, app_version, build_app } = options;
|
|
17
29
|
const log = options.log ?? new Logger(`[${daemon_name}]`);
|
|
18
30
|
const { runtime } = adapter;
|
|
19
|
-
if (
|
|
20
|
-
log.error(`FATAL: binding to '${host}' exposes the test binary
|
|
21
|
-
`Use --host localhost (default)
|
|
31
|
+
if (!is_loopback_host(host)) {
|
|
32
|
+
log.error(`FATAL: binding to '${host}' exposes the test binary (which ships deterministic ` +
|
|
33
|
+
`dev secrets) beyond loopback. Use --host localhost (default), 127.0.0.1, or ::1 instead.`);
|
|
22
34
|
adapter.exit(1);
|
|
23
35
|
}
|
|
24
36
|
const stale = await read_daemon_info(runtime, daemon_name);
|
package/dist/testing/db.d.ts
CHANGED
|
@@ -71,25 +71,18 @@ export declare const auth_truncate_tables: string[];
|
|
|
71
71
|
*/
|
|
72
72
|
export declare const auth_integration_truncate_tables: string[];
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* The full set created by `auth_migrations` — use for clean-slate
|
|
77
|
-
* test DB initialization. `auth_truncate_tables` is the subset for
|
|
78
|
-
* between-test data cleanup (excludes `audit_log`).
|
|
79
|
-
*
|
|
80
|
-
* When adding tables to `auth_migrations`, add them here too.
|
|
81
|
-
*/
|
|
82
|
-
export declare const auth_drop_tables: readonly ["app_settings", "invite", "audit_log", "api_token", "auth_session", "role_grant", "role_grant_offer", "actor", "account", "bootstrap_lock"];
|
|
83
|
-
/**
|
|
84
|
-
* Drop all auth tables and schema version tracking for a clean slate.
|
|
74
|
+
* Reset the entire `public` schema for a clean slate before re-migration.
|
|
85
75
|
*
|
|
86
76
|
* Recommended at the start of `init_schema` callbacks for `create_pg_factory`.
|
|
87
|
-
* Persistent test databases
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
77
|
+
* Persistent test databases accumulate stale DDL across fuz_app versions;
|
|
78
|
+
* `DROP SCHEMA public CASCADE; CREATE SCHEMA public` wipes every table, type,
|
|
79
|
+
* and sequence regardless of namespace, so migrations always run against a
|
|
80
|
+
* truly empty database. Drift-proof — unlike a hand-maintained drop list it
|
|
81
|
+
* needs no upkeep when the schema gains a table. Despite the historical name,
|
|
82
|
+
* this resets the whole schema, not just auth tables (the only documented use
|
|
83
|
+
* is clean-slate re-migration, which always wanted a full reset).
|
|
91
84
|
*
|
|
92
|
-
* @mutates db - drops
|
|
85
|
+
* @mutates db - drops and recreates the `public` schema; all tables gone.
|
|
93
86
|
*/
|
|
94
87
|
export declare const drop_auth_schema: (db: Db) => Promise<void>;
|
|
95
88
|
/**
|
package/dist/testing/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/db.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA6B7B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAKpC;;GAEG;AACH,eAAO,MAAM,KAAK,SAA4B,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAGvD,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,SAkB7E,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EACtC,WAAW,MAAM,KACf,SA2DF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,UAQhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,UAAyC,CAAC;AAEvF
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/db.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA6B7B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AAKpC;;GAEG;AACH,eAAO,MAAM,KAAK,SAA4B,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAGvD,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,SAkB7E,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,EACtC,WAAW,MAAM,KACf,SA2DF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,UAQhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,UAAyC,CAAC;AAEvF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,GAAU,IAAI,EAAE,KAAG,OAAO,CAAC,IAAI,CAG3D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,GAC9B,WAAW,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,EACvC,iBAAiB,KAAK,CAAC,MAAM,CAAC,KAC5B,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,KAAK,IAAI,CAwBzD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,KAAK,CAAC,SAAS,CAAC,KAAG,IAMnE,CAAC"}
|
package/dist/testing/db.js
CHANGED
|
@@ -178,42 +178,22 @@ export const auth_truncate_tables = [
|
|
|
178
178
|
*/
|
|
179
179
|
export const auth_integration_truncate_tables = [...auth_truncate_tables, 'audit_log'];
|
|
180
180
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* The full set created by `auth_migrations` — use for clean-slate
|
|
184
|
-
* test DB initialization. `auth_truncate_tables` is the subset for
|
|
185
|
-
* between-test data cleanup (excludes `audit_log`).
|
|
186
|
-
*
|
|
187
|
-
* When adding tables to `auth_migrations`, add them here too.
|
|
188
|
-
*/
|
|
189
|
-
export const auth_drop_tables = [
|
|
190
|
-
'app_settings',
|
|
191
|
-
'invite',
|
|
192
|
-
'audit_log',
|
|
193
|
-
'api_token',
|
|
194
|
-
'auth_session',
|
|
195
|
-
'role_grant',
|
|
196
|
-
'role_grant_offer',
|
|
197
|
-
'actor',
|
|
198
|
-
'account',
|
|
199
|
-
'bootstrap_lock',
|
|
200
|
-
];
|
|
201
|
-
/**
|
|
202
|
-
* Drop all auth tables and schema version tracking for a clean slate.
|
|
181
|
+
* Reset the entire `public` schema for a clean slate before re-migration.
|
|
203
182
|
*
|
|
204
183
|
* Recommended at the start of `init_schema` callbacks for `create_pg_factory`.
|
|
205
|
-
* Persistent test databases
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
184
|
+
* Persistent test databases accumulate stale DDL across fuz_app versions;
|
|
185
|
+
* `DROP SCHEMA public CASCADE; CREATE SCHEMA public` wipes every table, type,
|
|
186
|
+
* and sequence regardless of namespace, so migrations always run against a
|
|
187
|
+
* truly empty database. Drift-proof — unlike a hand-maintained drop list it
|
|
188
|
+
* needs no upkeep when the schema gains a table. Despite the historical name,
|
|
189
|
+
* this resets the whole schema, not just auth tables (the only documented use
|
|
190
|
+
* is clean-slate re-migration, which always wanted a full reset).
|
|
191
|
+
*
|
|
192
|
+
* @mutates db - drops and recreates the `public` schema; all tables gone.
|
|
211
193
|
*/
|
|
212
194
|
export const drop_auth_schema = async (db) => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
await db.query('DROP TABLE IF EXISTS schema_version CASCADE');
|
|
195
|
+
await db.query('DROP SCHEMA public CASCADE');
|
|
196
|
+
await db.query('CREATE SCHEMA public');
|
|
217
197
|
};
|
|
218
198
|
/**
|
|
219
199
|
* Create a `describe_db` function bound to specific factories and truncate tables.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock_fs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/mock_fs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,MAAM;IACtB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,gBAAe,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAAG,MAsB3E,CAAC"}
|
|
1
|
+
{"version":3,"file":"mock_fs.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/mock_fs.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;GAKG;AAEH,MAAM,WAAW,MAAM;IACtB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,gBAAe,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAAG,MAsB3E,CAAC"}
|
package/dist/testing/mock_fs.js
CHANGED
|
@@ -142,6 +142,38 @@ export declare const assert_ws_endpoints_include_protocol_actions: (surface: App
|
|
|
142
142
|
* surface mocks the shape incorrectly.
|
|
143
143
|
*/
|
|
144
144
|
export declare const assert_ws_notifications_have_null_auth: (surface: AppSurface) => void;
|
|
145
|
+
/**
|
|
146
|
+
* Reserved method-name prefix for the daemon-token-gated test-backdoor
|
|
147
|
+
* actions (`_testing_reset`, `_testing_mint_session`, `_testing_put_fact`,
|
|
148
|
+
* `_testing_drain_effects`, `_testing_schema_snapshot`). Test binaries
|
|
149
|
+
* live-mount these on their RPC endpoint but they must never appear on a
|
|
150
|
+
* **declared** surface.
|
|
151
|
+
*/
|
|
152
|
+
export declare const TESTING_METHOD_PREFIX = "_testing_";
|
|
153
|
+
/**
|
|
154
|
+
* No `_testing_*` backdoor action ever appears as a method on the declared
|
|
155
|
+
* surface (RPC or WS).
|
|
156
|
+
*
|
|
157
|
+
* The test-backdoor actions (`_testing_reset` et al.) are daemon-token-gated
|
|
158
|
+
* privileged actions a consumer's test binary appends to its live RPC
|
|
159
|
+
* endpoint at assembly time — but they are deliberately excluded from
|
|
160
|
+
* surface generation (`spine_rpc_endpoints` and every consumer's
|
|
161
|
+
* `create_*_app_surface_spec` omit them) so the published attack surface,
|
|
162
|
+
* the committed `*_attack_surface.json` snapshot, and codegen never carry
|
|
163
|
+
* a backdoor. This invariant is the structural guard against a future
|
|
164
|
+
* wiring change that folds `create_testing_actions(...)` into the *declared*
|
|
165
|
+
* registry instead of the live-only append — the surface stays the
|
|
166
|
+
* authoritative "what the server exposes" map only if a backdoor can never
|
|
167
|
+
* hide in it.
|
|
168
|
+
*
|
|
169
|
+
* Pairs with the wire-level negative-credential check
|
|
170
|
+
* (`describe_testing_backdoor_cross_tests`, cross-process) and the
|
|
171
|
+
* spec-level gate check: this one pins absence-from-surface, those pin
|
|
172
|
+
* the daemon-token gate and the 401/403 behavior.
|
|
173
|
+
*
|
|
174
|
+
* @throws AssertionError naming the offending endpoint + method.
|
|
175
|
+
*/
|
|
176
|
+
export declare const assert_no_testing_methods: (surface: AppSurface) => void;
|
|
145
177
|
/**
|
|
146
178
|
* Configuration for security policy invariants.
|
|
147
179
|
*
|
|
@@ -282,7 +314,8 @@ export declare const assert_surface_invariants: (surface: AppSurface) => void;
|
|
|
282
314
|
* `actions/CLAUDE.md` §Registry compile) — these assertions cover only
|
|
283
315
|
* the contract-surface concerns that a runtime registration check
|
|
284
316
|
* cannot: empty descriptions, missing protocol-action spread on WS
|
|
285
|
-
* endpoints,
|
|
317
|
+
* endpoints, kind ⇔ auth drift on WS methods, and a `_testing_*`
|
|
318
|
+
* backdoor action leaking onto the declared surface.
|
|
286
319
|
*
|
|
287
320
|
* @throws AssertionError on the first invariant violation; the message
|
|
288
321
|
* names the offending endpoint, method, and field.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface_invariants.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/surface_invariants.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"surface_invariants.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/surface_invariants.ts"],"names":[],"mappings":"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"}
|
|
@@ -452,6 +452,52 @@ export const assert_ws_notifications_have_null_auth = (surface) => {
|
|
|
452
452
|
}
|
|
453
453
|
}
|
|
454
454
|
};
|
|
455
|
+
/**
|
|
456
|
+
* Reserved method-name prefix for the daemon-token-gated test-backdoor
|
|
457
|
+
* actions (`_testing_reset`, `_testing_mint_session`, `_testing_put_fact`,
|
|
458
|
+
* `_testing_drain_effects`, `_testing_schema_snapshot`). Test binaries
|
|
459
|
+
* live-mount these on their RPC endpoint but they must never appear on a
|
|
460
|
+
* **declared** surface.
|
|
461
|
+
*/
|
|
462
|
+
export const TESTING_METHOD_PREFIX = '_testing_';
|
|
463
|
+
/**
|
|
464
|
+
* No `_testing_*` backdoor action ever appears as a method on the declared
|
|
465
|
+
* surface (RPC or WS).
|
|
466
|
+
*
|
|
467
|
+
* The test-backdoor actions (`_testing_reset` et al.) are daemon-token-gated
|
|
468
|
+
* privileged actions a consumer's test binary appends to its live RPC
|
|
469
|
+
* endpoint at assembly time — but they are deliberately excluded from
|
|
470
|
+
* surface generation (`spine_rpc_endpoints` and every consumer's
|
|
471
|
+
* `create_*_app_surface_spec` omit them) so the published attack surface,
|
|
472
|
+
* the committed `*_attack_surface.json` snapshot, and codegen never carry
|
|
473
|
+
* a backdoor. This invariant is the structural guard against a future
|
|
474
|
+
* wiring change that folds `create_testing_actions(...)` into the *declared*
|
|
475
|
+
* registry instead of the live-only append — the surface stays the
|
|
476
|
+
* authoritative "what the server exposes" map only if a backdoor can never
|
|
477
|
+
* hide in it.
|
|
478
|
+
*
|
|
479
|
+
* Pairs with the wire-level negative-credential check
|
|
480
|
+
* (`describe_testing_backdoor_cross_tests`, cross-process) and the
|
|
481
|
+
* spec-level gate check: this one pins absence-from-surface, those pin
|
|
482
|
+
* the daemon-token gate and the 401/403 behavior.
|
|
483
|
+
*
|
|
484
|
+
* @throws AssertionError naming the offending endpoint + method.
|
|
485
|
+
*/
|
|
486
|
+
export const assert_no_testing_methods = (surface) => {
|
|
487
|
+
for (const ep of surface.rpc_endpoints) {
|
|
488
|
+
for (const method of ep.methods) {
|
|
489
|
+
assert.ok(!method.name.startsWith(TESTING_METHOD_PREFIX), `RPC endpoint '${ep.path}' exposes test-backdoor method '${method.name}' on the ` +
|
|
490
|
+
`declared surface — '${TESTING_METHOD_PREFIX}*' actions must be live-mounted only, ` +
|
|
491
|
+
`never folded into the surface-generating registry`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
for (const ep of surface.ws_endpoints) {
|
|
495
|
+
for (const method of ep.methods) {
|
|
496
|
+
assert.ok(!method.name.startsWith(TESTING_METHOD_PREFIX), `WS endpoint '${ep.path}' exposes test-backdoor method '${method.name}' on the ` +
|
|
497
|
+
`declared surface — '${TESTING_METHOD_PREFIX}*' actions must be live-mounted only`);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
};
|
|
455
501
|
/** Default patterns for sensitive REST routes that should be rate-limited. */
|
|
456
502
|
const DEFAULT_SENSITIVE_PATTERNS = [
|
|
457
503
|
/\/login$/,
|
|
@@ -637,7 +683,8 @@ export const assert_surface_invariants = (surface) => {
|
|
|
637
683
|
* `actions/CLAUDE.md` §Registry compile) — these assertions cover only
|
|
638
684
|
* the contract-surface concerns that a runtime registration check
|
|
639
685
|
* cannot: empty descriptions, missing protocol-action spread on WS
|
|
640
|
-
* endpoints,
|
|
686
|
+
* endpoints, kind ⇔ auth drift on WS methods, and a `_testing_*`
|
|
687
|
+
* backdoor action leaking onto the declared surface.
|
|
641
688
|
*
|
|
642
689
|
* @throws AssertionError on the first invariant violation; the message
|
|
643
690
|
* names the offending endpoint, method, and field.
|
|
@@ -647,6 +694,7 @@ export const assert_rpc_ws_surface_invariants = (surface) => {
|
|
|
647
694
|
assert_ws_method_descriptions_present(surface);
|
|
648
695
|
assert_ws_endpoints_include_protocol_actions(surface);
|
|
649
696
|
assert_ws_notifications_have_null_auth(surface);
|
|
697
|
+
assert_no_testing_methods(surface);
|
|
650
698
|
};
|
|
651
699
|
/**
|
|
652
700
|
* Run security policy invariants. Configurable with sensible defaults.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/ws_round_trip.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ws_round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/ws_round_trip.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* In-process test helpers for WebSocket JSON-RPC round-trips.
|
|
3
|
-
*
|
|
4
|
-
* Drives `register_action_ws` without an HTTP server. Consumers supply
|
|
5
|
-
* specs + handlers; the harness constructs real `WSContext` instances
|
|
6
|
-
* backed by test-owned `send`/`close` pairs, fakes the authenticated
|
|
7
|
-
* Hono context (`request_context`, credential type, session id, api
|
|
8
|
-
* token id), and exposes a `connect()` factory returning a `WsClient`
|
|
9
|
-
* per connection.
|
|
10
|
-
*
|
|
11
|
-
* Three layers are exported:
|
|
12
|
-
*
|
|
13
|
-
* - **Primitives** (`create_fake_ws`, `create_fake_hono_context`,
|
|
14
|
-
* `create_stub_upgrade`, `MinimalActionEnvironment`,
|
|
15
|
-
* `dispatch_ws_message`) — used by fuz_app's own dispatcher tests
|
|
16
|
-
* and by consumers wiring tight one-off tests.
|
|
17
|
-
* - **Harness** (`create_ws_test_harness`, `keeper_identity`) — the
|
|
18
|
-
* high-level driver. Give it specs + handlers, get back
|
|
19
|
-
* `{transport, connect()}`. `connect()` is async and resolves after
|
|
20
|
-
* `on_socket_open` completes, so broadcasts sent immediately after
|
|
21
|
-
* `await harness.connect()` reach the client. Returns a `WsClient`
|
|
22
|
-
* (shared interface — see `transports/ws_client.ts`); the same
|
|
23
|
-
* interface is implemented by `transports/ws_transport.ts` for
|
|
24
|
-
* cross-process tests.
|
|
25
|
-
* - **Broadcast wiring** — `build_broadcast_api` for wiring a typed
|
|
26
|
-
* broadcast API against the harness's transport. Wire-frame types
|
|
27
|
-
* + predicates (`is_notification`, `is_response_for`,
|
|
28
|
-
* `JsonrpcNotificationFrame`, ...) live in `transports/ws_client.ts`
|
|
29
|
-
* so both in-process and cross-process drivers reference one source.
|
|
30
|
-
*
|
|
31
|
-
* Hono's wire upgrade is skipped — the Node test runtime has no
|
|
32
|
-
* `@hono/node-ws` adapter — but the full dispatch path is exercised
|
|
33
|
-
* (per-action auth, input validation, `ctx.notify` back to the
|
|
34
|
-
* originating socket, broadcast via `BackendWebsocketTransport`, and
|
|
35
|
-
* close-on-revoke).
|
|
36
|
-
*
|
|
37
|
-
* @module
|
|
38
|
-
*/
|
|
1
|
+
import './assert_dev_env.js';
|
|
39
2
|
import { WSContext, createWSMessageEvent, } from 'hono/ws';
|
|
40
3
|
import { Logger } from '@fuzdev/fuz_util/log.js';
|
|
41
4
|
import { create_uuid } from '@fuzdev/fuz_util/id.js';
|
|
@@ -50,14 +50,13 @@
|
|
|
50
50
|
import type {SvelteHTMLElements} from 'svelte/elements';
|
|
51
51
|
import type {ComponentProps, Snippet} from 'svelte';
|
|
52
52
|
import type {OmitStrict} from '@fuzdev/fuz_util/types.js';
|
|
53
|
-
import
|
|
53
|
+
import {icon_remove} from '@fuzdev/fuz_ui/icons.js';
|
|
54
54
|
import PendingAnimation from '@fuzdev/fuz_ui/PendingAnimation.svelte';
|
|
55
|
+
import Svg from '@fuzdev/fuz_ui/Svg.svelte';
|
|
55
56
|
|
|
56
57
|
import PopoverButton from './PopoverButton.svelte';
|
|
57
58
|
import type {Popover} from './popover.svelte.js';
|
|
58
59
|
|
|
59
|
-
const GLYPH_REMOVE = '🗙';
|
|
60
|
-
|
|
61
60
|
const {
|
|
62
61
|
onconfirm,
|
|
63
62
|
popover_button_attrs,
|
|
@@ -140,7 +139,7 @@
|
|
|
140
139
|
{#if popover_button_content}
|
|
141
140
|
{@render popover_button_content(popover, () => confirm(popover))}
|
|
142
141
|
{:else}
|
|
143
|
-
<
|
|
142
|
+
<Svg data={icon_remove} />
|
|
144
143
|
{/if}
|
|
145
144
|
</button>
|
|
146
145
|
{/if}
|
|
@@ -155,7 +154,7 @@
|
|
|
155
154
|
{:else if label !== undefined}
|
|
156
155
|
{label}
|
|
157
156
|
{:else}
|
|
158
|
-
<
|
|
157
|
+
<Svg data={icon_remove} />
|
|
159
158
|
{/if}
|
|
160
159
|
</span>
|
|
161
160
|
{#if pending}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmButton.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/ConfirmButton.svelte"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAC,cAAc,EAAE,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfirmButton.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/ConfirmButton.svelte"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAC,cAAc,EAAE,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AAK1D,OAAO,aAAa,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,qBAAqB,CAAC;AAEhD,KAAK,gBAAgB,GAAI,UAAU,CAAC,cAAc,CAAC,OAAO,aAAa,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAAC,GACxG,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IACtD,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,oBAAoB,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;IAChE,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,yEAAyE;IACzE,eAAe,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAC/E,qCAAqC;IACrC,sBAAsB,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACtF,yDAAyD;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACxE,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B,CAAC;AA+FJ,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuzdev/fuz_app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.85.1",
|
|
4
4
|
"description": "fullstack app library",
|
|
5
5
|
"glyph": "🗝",
|
|
6
6
|
"logo": "logo.svg",
|
|
@@ -70,10 +70,11 @@
|
|
|
70
70
|
"@electric-sql/pglite": "^0.4.5",
|
|
71
71
|
"@fuzdev/blake3_wasm": "^0.1.1",
|
|
72
72
|
"@fuzdev/fuz_code": "^0.46.0",
|
|
73
|
-
"@fuzdev/fuz_css": "^0.
|
|
74
|
-
"@fuzdev/fuz_ui": "^0.
|
|
73
|
+
"@fuzdev/fuz_css": "^0.63.0",
|
|
74
|
+
"@fuzdev/fuz_ui": "^0.205.0",
|
|
75
75
|
"@fuzdev/fuz_util": "^0.65.1",
|
|
76
76
|
"@fuzdev/gro": "^0.204.0",
|
|
77
|
+
"@fuzdev/mdz": "^0.1.0",
|
|
77
78
|
"@hono/node-server": "^1.19.14",
|
|
78
79
|
"@hono/node-ws": "^1.3.1",
|
|
79
80
|
"@node-rs/argon2": "^2.0.2",
|
|
@@ -98,7 +99,7 @@
|
|
|
98
99
|
"prettier-plugin-svelte": "^3.5.1",
|
|
99
100
|
"svelte": "^5.56.2",
|
|
100
101
|
"svelte-check": "^4.6.0",
|
|
101
|
-
"svelte-docinfo": "^0.
|
|
102
|
+
"svelte-docinfo": "^0.5.1",
|
|
102
103
|
"svelte2tsx": "^0.7.52",
|
|
103
104
|
"tslib": "^2.8.1",
|
|
104
105
|
"typescript": "^5.9.3",
|