@fuzdev/fuz_app 0.143.0 → 0.145.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.
Files changed (56) hide show
  1. package/dist/auth/CLAUDE.md +8 -0
  2. package/dist/auth/cell_action_specs.d.ts +13 -0
  3. package/dist/auth/cell_action_specs.d.ts.map +1 -1
  4. package/dist/auth/cell_action_specs.js +13 -0
  5. package/dist/auth/cell_actions.d.ts +7 -0
  6. package/dist/auth/cell_actions.d.ts.map +1 -1
  7. package/dist/auth/cell_actions.js +30 -0
  8. package/dist/auth/cell_ref_admission.d.ts +51 -0
  9. package/dist/auth/cell_ref_admission.d.ts.map +1 -0
  10. package/dist/auth/cell_ref_admission.js +69 -0
  11. package/dist/auth/deps.d.ts +6 -3
  12. package/dist/auth/deps.d.ts.map +1 -1
  13. package/dist/db/CLAUDE.md +40 -23
  14. package/dist/db/cell_ddl.d.ts +3 -2
  15. package/dist/db/cell_ddl.d.ts.map +1 -1
  16. package/dist/db/cell_ddl.js +3 -2
  17. package/dist/db/cell_queries.d.ts +31 -6
  18. package/dist/db/cell_queries.d.ts.map +1 -1
  19. package/dist/db/cell_queries.js +45 -18
  20. package/dist/db/fact_ddl.d.ts +30 -4
  21. package/dist/db/fact_ddl.d.ts.map +1 -1
  22. package/dist/db/fact_ddl.js +44 -4
  23. package/dist/db/fact_holder_queries.d.ts +70 -0
  24. package/dist/db/fact_holder_queries.d.ts.map +1 -0
  25. package/dist/db/fact_holder_queries.js +79 -0
  26. package/dist/db/fact_queries.d.ts +19 -14
  27. package/dist/db/fact_queries.d.ts.map +1 -1
  28. package/dist/db/fact_queries.js +31 -10
  29. package/dist/db/fact_store.d.ts +65 -9
  30. package/dist/db/fact_store.d.ts.map +1 -1
  31. package/dist/db/fact_store.js +49 -20
  32. package/dist/server/fact_security_headers.d.ts +54 -0
  33. package/dist/server/fact_security_headers.d.ts.map +1 -0
  34. package/dist/server/fact_security_headers.js +53 -0
  35. package/dist/server/serve_fact_route.d.ts +33 -7
  36. package/dist/server/serve_fact_route.d.ts.map +1 -1
  37. package/dist/server/serve_fact_route.js +36 -32
  38. package/dist/server/x_accel.d.ts +106 -30
  39. package/dist/server/x_accel.d.ts.map +1 -1
  40. package/dist/server/x_accel.js +533 -86
  41. package/dist/testing/CLAUDE.md +25 -1
  42. package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
  43. package/dist/testing/cross_backend/cell_crud.js +6 -3
  44. package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
  45. package/dist/testing/cross_backend/cell_gated_create.js +25 -16
  46. package/dist/testing/cross_backend/cell_ref_admission.d.ts +4 -0
  47. package/dist/testing/cross_backend/cell_ref_admission.d.ts.map +1 -0
  48. package/dist/testing/cross_backend/cell_ref_admission.js +268 -0
  49. package/dist/testing/cross_backend/expected_schema.json +66 -10
  50. package/dist/testing/cross_backend/fact_serving.d.ts +19 -1
  51. package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
  52. package/dist/testing/cross_backend/fact_serving.js +31 -9
  53. package/dist/testing/cross_backend/testing_reset_actions.d.ts +6 -2
  54. package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
  55. package/dist/testing/cross_backend/testing_reset_actions.js +13 -3
  56. package/package.json +3 -3
@@ -26,7 +26,10 @@ import '../assert_dev_env.js';
26
26
  *
27
27
  * Facts are seeded **embedded** via `_testing_put_fact` (the cross-process
28
28
  * driver has no DB handle); the referencing cell via the `cell_create` RPC
29
- * (`extract_refs` lifts the `blake3:` hash in `data` into `cell.refs`). Gated
29
+ * (the hash, a whole string value in `data`, is derived into `cell.refs`). A
30
+ * non-admin owner's cell may reference only a fact it holds, so a fact a
31
+ * non-admin references is put with that owner as its `holder` (the keeper is
32
+ * a global admin, whom ref admission doesn't gate). Gated
30
33
  * on `capabilities.fact_serving`; runs under every `cross_backend_*` project —
31
34
  * the TS spine binary and the Rust `testing_spine_stub` both mount the serve
32
35
  * routes + the seeder.
@@ -52,6 +55,21 @@ const NIL_UUID = '00000000-0000-0000-0000-000000000000';
52
55
  * fails here rather than silently downstream.
53
56
  */
54
57
  const TestingPutFactOutput = z.strictObject({ hash: FactHashSchema });
58
+ /**
59
+ * Seed an embedded fact over the daemon channel via `_testing_put_fact`;
60
+ * returns its `blake3:` hash. A `holder` is recorded in `fact_holder` (a
61
+ * deduplicated put included), as a real upload records its uploader.
62
+ *
63
+ * @param fixture - the test fixture (its daemon token drives the backdoor)
64
+ * @param rpc_path - the backend's RPC path
65
+ * @param input - the content, optional content type, and optional holder
66
+ * @returns the fact hash
67
+ */
68
+ export const cross_put_fact = async (fixture, rpc_path, input) => expect_output(await cross_rpc_call(
69
+ // Origin-free transport — the daemon-token middleware discards the
70
+ // credential when an `Origin` / `Referer` is present (browser
71
+ // context), and cross-process `fixture.transport` auto-adds `Origin`.
72
+ fixture.fresh_transport({ origin: null }), rpc_path, '_testing_put_fact', input, fixture.create_daemon_token_headers()), TestingPutFactOutput).hash;
55
73
  /** GET a fact over a cross-process `FetchTransport`; returns `{status, content_type, text}`. */
56
74
  const fact_get = async (transport, path, headers) => {
57
75
  const res = await transport(path, { method: 'GET', headers });
@@ -64,12 +82,8 @@ const fact_get = async (transport, path, headers) => {
64
82
  export const describe_fact_serving_cross_tests = (options) => {
65
83
  const { setup_test, setup_test_multi_actor, capabilities } = options;
66
84
  const rpc_path = options.rpc_path ?? SPINE_RPC_PATH;
67
- /** Seed an embedded fact over the daemon channel; returns its `blake3:` hash. */
68
- const put_fact = async (fixture, content, content_type) => expect_output(await cross_rpc_call(
69
- // Origin-free transport — the daemon-token middleware discards the
70
- // credential when an `Origin` / `Referer` is present (browser
71
- // context), and cross-process `fixture.transport` auto-adds `Origin`.
72
- fixture.fresh_transport({ origin: null }), rpc_path, '_testing_put_fact', content_type === undefined ? { content } : { content, content_type }, fixture.create_daemon_token_headers()), TestingPutFactOutput).hash;
85
+ /** Seed an embedded system-put fact; returns its `blake3:` hash. */
86
+ const put_fact = (fixture, content, content_type) => cross_put_fact(fixture, rpc_path, content_type === undefined ? { content } : { content, content_type });
73
87
  /**
74
88
  * Create a cell referencing `hash` (`extract_refs` lifts it into `cell.refs`).
75
89
  * Pass `acting` when the caller's account holds more than one actor —
@@ -96,8 +110,16 @@ export const describe_fact_serving_cross_tests = (options) => {
96
110
  const fixture = await setup_test();
97
111
  const a = await fixture.create_account({ username: 'fact_owner_a' });
98
112
  const b = await fixture.create_account({ username: 'fact_owner_b' });
99
- // One fact, identical bytes from both owners — deduped to a single row.
100
- const hash = await put_fact(fixture, 'shared-deduped-bytes');
113
+ // One fact, identical bytes put by both owners — deduped to a single
114
+ // row, each owner a holder.
115
+ const hash = await cross_put_fact(fixture, rpc_path, {
116
+ content: 'shared-deduped-bytes',
117
+ holder: a.actor.id
118
+ });
119
+ assert.strictEqual(await cross_put_fact(fixture, rpc_path, {
120
+ content: 'shared-deduped-bytes',
121
+ holder: b.actor.id
122
+ }), hash);
101
123
  const t = fixture.fresh_transport();
102
124
  const a_cell = await create_cell_with_ref(t, a.create_session_headers(), hash, 'private');
103
125
  const b_cell = await create_cell_with_ref(t, b.create_session_headers(), hash, 'public');
@@ -261,8 +261,11 @@ export declare const create_testing_drain_effects_action: (audit: AuditEmitter)
261
261
  * cross-process fact-serving suite, which drives over real HTTP and has no
262
262
  * `PgFactStore` to call. Hashes the UTF-8 `content` (blake3, via
263
263
  * `fact_hash_bytes` — the same hash the Rust `_testing_put_fact` computes),
264
- * inserts the row idempotently, and returns `{hash}`. The referencing cell is
265
- * seeded separately via the `cell_create` RPC. Embedded-only is enough for the
264
+ * inserts the row idempotently, and returns `{hash}`. `holder` names the actor
265
+ * the put is on behalf of — recorded in `fact_holder` (deduplicated puts
266
+ * included), as a real upload records its uploader, so the suites can drive
267
+ * cell ref admission; absent, the put is a system put with no holder. The
268
+ * referencing cell is seeded separately via the `cell_create` RPC. Embedded-only is enough for the
266
269
  * authz assertions (cell-scoped admit, cross-owner-no-leak, 404-mask, bare-hash
267
270
  * admin-only); external / X-Accel parity stays covered by the forge's own gate.
268
271
  *
@@ -283,6 +286,7 @@ export declare const testing_put_fact_action_spec: {
283
286
  readonly input: z.ZodObject<{
284
287
  content: z.ZodString;
285
288
  content_type: z.ZodOptional<z.ZodString>;
289
+ holder: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
286
290
  }, z.core.$strict>;
287
291
  readonly output: z.ZodObject<{
288
292
  hash: z.ZodString & z.ZodType<import("@fuzdev/fuz_util/hash_schemas.js").FactHash, string, z.core.$ZodTypeInternals<import("@fuzdev/fuz_util/hash_schemas.js").FactHash, string>>;
@@ -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":"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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAOzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAsBzC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCQ,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;CAWA,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;CAwBC,CAAC;AAE/C;;;;;;;;GAQG;AACH,eAAO,MAAM,mCAAmC,GAAI,OAAO,YAAY,KAAG,SAIvE,CAAC;AAEJ;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;CAgBK,CAAC;AAE/C,kFAAkF;AAClF,eAAO,MAAM,iCAAiC,mBAAmB,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAE9D,8FAA8F;AAC9F,eAAO,MAAM,iCAAiC,kBAAkB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,uCAAuC;;;;;;;;;;;;;;;;;;;;CAwBN,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,yCAAyC,QAAO,SAmB1D,CAAC;AAEJ;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWF,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,QAAO,SAGvD,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qCAAqC;;;;;;;;;;;;;;;;;;;;CAYJ,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,uCAAuC,QAAO,SAGzD,CAAC;AAEH,0FAA0F;AAC1F,eAAO,MAAM,6CAA6C,IAAI,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,6CAA6C,KAAK,CAAC;AAShE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,6CAA6C;;;;;;;;;;;;;;;;;;;;CA2BZ,CAAC;AAE/C,2FAA2F;AAC3F,eAAO,MAAM,+CAA+C,QAAO,SAYhE,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAaF,CAAC;AAkB/C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qCAAqC,GACjD,SAAS,aAAa,CAAC,SAAS,CAAC,KAC/B,SAMF,CAAC;AAEF,4CAA4C;AAC5C,MAAM,WAAW,2BAA2B;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACjD;;;;;;OAMG;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;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,OAAO,EACb,SAAS,2BAA2B,KAClC,KAAK,CAAC,SAAS,CAkJjB,CAAC"}
@@ -83,6 +83,7 @@ import { jsonrpc_errors } from '../../http/jsonrpc_errors.js';
83
83
  import { emit_after_commit } from '../../http/pending_effects.js';
84
84
  import { protocol_action_specs } from '../../actions/protocol.js';
85
85
  import { query_put_fact } from '../../db/fact_queries.js';
86
+ import { query_put_fact_holder } from '../../db/fact_holder_queries.js';
86
87
  import { ROLE_ADMIN, ROLE_KEEPER } from '../../auth/role_schema.js';
87
88
  import { query_schema_snapshot, SchemaSnapshot, query_migration_tracker, MigrationTracker } from '../schema_introspect.js';
88
89
  import { ActionManifest, build_action_manifest } from './action_manifest.js';
@@ -262,8 +263,11 @@ export const create_testing_drain_effects_action = (audit) => rpc_action(testing
262
263
  * cross-process fact-serving suite, which drives over real HTTP and has no
263
264
  * `PgFactStore` to call. Hashes the UTF-8 `content` (blake3, via
264
265
  * `fact_hash_bytes` — the same hash the Rust `_testing_put_fact` computes),
265
- * inserts the row idempotently, and returns `{hash}`. The referencing cell is
266
- * seeded separately via the `cell_create` RPC. Embedded-only is enough for the
266
+ * inserts the row idempotently, and returns `{hash}`. `holder` names the actor
267
+ * the put is on behalf of — recorded in `fact_holder` (deduplicated puts
268
+ * included), as a real upload records its uploader, so the suites can drive
269
+ * cell ref admission; absent, the put is a system put with no holder. The
270
+ * referencing cell is seeded separately via the `cell_create` RPC. Embedded-only is enough for the
267
271
  * authz assertions (cell-scoped admit, cross-owner-no-leak, 404-mask, bare-hash
268
272
  * admin-only); external / X-Accel parity stays covered by the forge's own gate.
269
273
  *
@@ -279,7 +283,8 @@ export const testing_put_fact_action_spec = {
279
283
  side_effects: true,
280
284
  input: z.strictObject({
281
285
  content: z.string(),
282
- content_type: z.string().optional()
286
+ content_type: z.string().optional(),
287
+ holder: Uuid.optional()
283
288
  }),
284
289
  output: z.strictObject({ hash: FactHashSchema }),
285
290
  async: true,
@@ -719,6 +724,11 @@ export const create_testing_actions = (deps, options) => {
719
724
  content_type: input.content_type ?? null,
720
725
  size: bytes.length
721
726
  });
727
+ // the holder row, on a dedup hit too (`PgFactStore`'s put records it the
728
+ // same way); an unknown actor fails the FK
729
+ if (input.holder !== undefined) {
730
+ await query_put_fact_holder({ db: ctx.db }, input.holder, hash);
731
+ }
722
732
  return { hash };
723
733
  }),
724
734
  create_testing_drain_effects_action(deps.audit),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_app",
3
- "version": "0.143.0",
3
+ "version": "0.145.0",
4
4
  "description": "fullstack app library",
5
5
  "glyph": "🗝",
6
6
  "logo": "logo.svg",
@@ -36,7 +36,7 @@
36
36
  "@fuzdev/fuz_css": ">=0.70.0",
37
37
  "@fuzdev/fuz_schema": "^0.5.0",
38
38
  "@fuzdev/fuz_util": ">=0.77.0",
39
- "@fuzdev/pglet-wasm": ">=0.1.1",
39
+ "@fuzdev/pglet-wasm": ">=0.1.2",
40
40
  "@hono/bun": ">=1",
41
41
  "@hono/deno": ">=1",
42
42
  "@hono/node-server": ">=1",
@@ -98,7 +98,7 @@
98
98
  "@fuzdev/fuz_util": "^0.77.0",
99
99
  "@fuzdev/gro": "^0.220.0",
100
100
  "@fuzdev/mdz": "^0.6.0",
101
- "@fuzdev/pglet-wasm": "^0.1.1",
101
+ "@fuzdev/pglet-wasm": "^0.1.2",
102
102
  "@hono/bun": "^1.0.1",
103
103
  "@hono/deno": "^1.0.3",
104
104
  "@hono/node-server": "^1.19.14",