@graview/core 0.1.49 → 0.1.50

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 (233) hide show
  1. package/dist/answer-seen.js +2 -2
  2. package/dist/answer-seen.js.map +1 -1
  3. package/dist/app.d.ts +11 -0
  4. package/dist/app.d.ts.map +1 -1
  5. package/dist/app.js.map +1 -1
  6. package/dist/capabilities.d.ts +7 -1
  7. package/dist/capabilities.d.ts.map +1 -1
  8. package/dist/capabilities.js.map +1 -1
  9. package/dist/cli/check/index.d.ts +1 -0
  10. package/dist/cli/check/index.d.ts.map +1 -1
  11. package/dist/cli/check/index.js +1 -0
  12. package/dist/cli/check/index.js.map +1 -1
  13. package/dist/cli/check/publishing.d.ts +13 -0
  14. package/dist/cli/check/publishing.d.ts.map +1 -0
  15. package/dist/cli/check/publishing.js +36 -0
  16. package/dist/cli/check/publishing.js.map +1 -0
  17. package/dist/cli/check.d.ts.map +1 -1
  18. package/dist/cli/check.js +2 -1
  19. package/dist/cli/check.js.map +1 -1
  20. package/dist/cli/describe.d.ts.map +1 -1
  21. package/dist/cli/describe.js +15 -0
  22. package/dist/cli/describe.js.map +1 -1
  23. package/dist/cli/index.d.ts +1 -0
  24. package/dist/cli/index.d.ts.map +1 -1
  25. package/dist/cli/index.js +3 -1
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/document/compiled.d.ts.map +1 -1
  28. package/dist/document/compiled.js +5 -0
  29. package/dist/document/compiled.js.map +1 -1
  30. package/dist/document/field-spec.d.ts.map +1 -1
  31. package/dist/document/field-spec.js +8 -2
  32. package/dist/document/field-spec.js.map +1 -1
  33. package/dist/document/format-findings.d.ts.map +1 -1
  34. package/dist/document/format-findings.js +5 -0
  35. package/dist/document/format-findings.js.map +1 -1
  36. package/dist/document/schema.d.ts +13 -0
  37. package/dist/document/schema.d.ts.map +1 -1
  38. package/dist/document/schema.js +16 -0
  39. package/dist/document/schema.js.map +1 -1
  40. package/dist/document/to-document.d.ts.map +1 -1
  41. package/dist/document/to-document.js +1 -0
  42. package/dist/document/to-document.js.map +1 -1
  43. package/dist/document.schema.json +42 -2
  44. package/dist/field-sight.js +5 -4
  45. package/dist/field-sight.js.map +1 -1
  46. package/dist/format-error.d.ts +54 -0
  47. package/dist/format-error.d.ts.map +1 -0
  48. package/dist/format-error.js +73 -0
  49. package/dist/format-error.js.map +1 -0
  50. package/dist/formats.d.ts +16 -13
  51. package/dist/formats.d.ts.map +1 -1
  52. package/dist/formats.js +18 -17
  53. package/dist/formats.js.map +1 -1
  54. package/dist/graph/diff.js +1 -1
  55. package/dist/graph/diff.js.map +1 -1
  56. package/dist/graph/edge-fields.d.ts +20 -0
  57. package/dist/graph/edge-fields.d.ts.map +1 -0
  58. package/dist/graph/edge-fields.js +21 -0
  59. package/dist/graph/edge-fields.js.map +1 -0
  60. package/dist/graph/graph.d.ts +3 -0
  61. package/dist/graph/graph.d.ts.map +1 -1
  62. package/dist/graph/graph.js +57 -4
  63. package/dist/graph/graph.js.map +1 -1
  64. package/dist/graph/primitives.d.ts +22 -2
  65. package/dist/graph/primitives.d.ts.map +1 -1
  66. package/dist/graph/primitives.js +20 -0
  67. package/dist/graph/primitives.js.map +1 -1
  68. package/dist/graph/types.d.ts +15 -1
  69. package/dist/graph/types.d.ts.map +1 -1
  70. package/dist/graph/types.js +0 -0
  71. package/dist/graph/types.js.map +1 -1
  72. package/dist/history.d.ts +23 -2
  73. package/dist/history.d.ts.map +1 -1
  74. package/dist/history.js +23 -3
  75. package/dist/history.js.map +1 -1
  76. package/dist/index.d.ts +17 -6
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +12 -2
  79. package/dist/index.js.map +1 -1
  80. package/dist/integrity.d.ts.map +1 -1
  81. package/dist/integrity.js +2 -1
  82. package/dist/integrity.js.map +1 -1
  83. package/dist/linked.d.ts +1 -0
  84. package/dist/linked.d.ts.map +1 -1
  85. package/dist/linked.js +1 -0
  86. package/dist/linked.js.map +1 -1
  87. package/dist/mutations/define-mutation.d.ts +4 -0
  88. package/dist/mutations/define-mutation.d.ts.map +1 -1
  89. package/dist/mutations/define-mutation.js +32 -8
  90. package/dist/mutations/define-mutation.js.map +1 -1
  91. package/dist/mutations/keep-link.d.ts.map +1 -1
  92. package/dist/mutations/keep-link.js +4 -2
  93. package/dist/mutations/keep-link.js.map +1 -1
  94. package/dist/mutations/type-text.d.ts +49 -0
  95. package/dist/mutations/type-text.d.ts.map +1 -0
  96. package/dist/mutations/type-text.js +106 -0
  97. package/dist/mutations/type-text.js.map +1 -0
  98. package/dist/mutations/types.d.ts +8 -0
  99. package/dist/mutations/types.d.ts.map +1 -1
  100. package/dist/mutations/visitor-form.js +1 -1
  101. package/dist/mutations/visitor-form.js.map +1 -1
  102. package/dist/ops/digest.d.ts +17 -6
  103. package/dist/ops/digest.d.ts.map +1 -1
  104. package/dist/ops/digest.js +36 -15
  105. package/dist/ops/digest.js.map +1 -1
  106. package/dist/ops/kept-fields.d.ts +1 -1
  107. package/dist/ops/kept-fields.d.ts.map +1 -1
  108. package/dist/ops/kept-fields.js +4 -1
  109. package/dist/ops/kept-fields.js.map +1 -1
  110. package/dist/ops/log.d.ts.map +1 -1
  111. package/dist/ops/log.js +3 -0
  112. package/dist/ops/log.js.map +1 -1
  113. package/dist/ops/provenance.d.ts.map +1 -1
  114. package/dist/ops/provenance.js +3 -1
  115. package/dist/ops/provenance.js.map +1 -1
  116. package/dist/ops/revisions.d.ts +8 -2
  117. package/dist/ops/revisions.d.ts.map +1 -1
  118. package/dist/ops/revisions.js +12 -3
  119. package/dist/ops/revisions.js.map +1 -1
  120. package/dist/ops/served.d.ts.map +1 -1
  121. package/dist/ops/served.js +30 -4
  122. package/dist/ops/served.js.map +1 -1
  123. package/dist/ops/suggestions.d.ts +14 -0
  124. package/dist/ops/suggestions.d.ts.map +1 -1
  125. package/dist/ops/suggestions.js.map +1 -1
  126. package/dist/ops/types.d.ts +43 -3
  127. package/dist/ops/types.d.ts.map +1 -1
  128. package/dist/ops/types.js +16 -1
  129. package/dist/ops/types.js.map +1 -1
  130. package/dist/ops/undo.d.ts +15 -2
  131. package/dist/ops/undo.d.ts.map +1 -1
  132. package/dist/ops/undo.js +22 -3
  133. package/dist/ops/undo.js.map +1 -1
  134. package/dist/ops/withheld.d.ts.map +1 -1
  135. package/dist/ops/withheld.js +4 -0
  136. package/dist/ops/withheld.js.map +1 -1
  137. package/dist/ops/writers.d.ts.map +1 -1
  138. package/dist/ops/writers.js +3 -0
  139. package/dist/ops/writers.js.map +1 -1
  140. package/dist/past.d.ts +1 -0
  141. package/dist/past.d.ts.map +1 -1
  142. package/dist/past.js +9 -2
  143. package/dist/past.js.map +1 -1
  144. package/dist/persistence/memory.d.ts +1 -1
  145. package/dist/persistence/memory.d.ts.map +1 -1
  146. package/dist/persistence/memory.js +5 -1
  147. package/dist/persistence/memory.js.map +1 -1
  148. package/dist/persistence/sql.d.ts +1 -1
  149. package/dist/persistence/sql.d.ts.map +1 -1
  150. package/dist/persistence/sql.js +45 -5
  151. package/dist/persistence/sql.js.map +1 -1
  152. package/dist/persistence/sqlite.d.ts +1 -0
  153. package/dist/persistence/sqlite.d.ts.map +1 -1
  154. package/dist/persistence/sqlite.js +1 -0
  155. package/dist/persistence/sqlite.js.map +1 -1
  156. package/dist/persistence/types.d.ts +34 -1
  157. package/dist/persistence/types.d.ts.map +1 -1
  158. package/dist/persistence/types.js +35 -1
  159. package/dist/persistence/types.js.map +1 -1
  160. package/dist/presence.d.ts +2 -1
  161. package/dist/presence.d.ts.map +1 -1
  162. package/dist/presence.js +2 -1
  163. package/dist/presence.js.map +1 -1
  164. package/dist/publish.d.ts +78 -0
  165. package/dist/publish.d.ts.map +1 -0
  166. package/dist/publish.js +23 -0
  167. package/dist/publish.js.map +1 -0
  168. package/dist/publishing.d.ts +10 -0
  169. package/dist/publishing.d.ts.map +1 -0
  170. package/dist/publishing.js +168 -0
  171. package/dist/publishing.js.map +1 -0
  172. package/dist/refused.d.ts +13 -6
  173. package/dist/refused.d.ts.map +1 -1
  174. package/dist/refused.js +13 -6
  175. package/dist/refused.js.map +1 -1
  176. package/dist/schema/collaborative.d.ts +14 -0
  177. package/dist/schema/collaborative.d.ts.map +1 -0
  178. package/dist/schema/collaborative.js +65 -0
  179. package/dist/schema/collaborative.js.map +1 -0
  180. package/dist/seen.d.ts +44 -1
  181. package/dist/seen.d.ts.map +1 -1
  182. package/dist/seen.js +59 -14
  183. package/dist/seen.js.map +1 -1
  184. package/dist/store.d.ts +78 -4
  185. package/dist/store.d.ts.map +1 -1
  186. package/dist/store.js +118 -24
  187. package/dist/store.js.map +1 -1
  188. package/dist/subscriptions.d.ts.map +1 -1
  189. package/dist/subscriptions.js +13 -1
  190. package/dist/subscriptions.js.map +1 -1
  191. package/dist/sync/engine.d.ts.map +1 -1
  192. package/dist/sync/engine.js +43 -15
  193. package/dist/sync/engine.js.map +1 -1
  194. package/dist/sync/index.d.ts +1 -1
  195. package/dist/sync/index.d.ts.map +1 -1
  196. package/dist/sync/index.js +1 -1
  197. package/dist/sync/index.js.map +1 -1
  198. package/dist/sync/types.d.ts +10 -0
  199. package/dist/sync/types.d.ts.map +1 -1
  200. package/dist/sync/types.js +8 -0
  201. package/dist/sync/types.js.map +1 -1
  202. package/dist/testing.d.ts.map +1 -1
  203. package/dist/testing.js +1 -0
  204. package/dist/testing.js.map +1 -1
  205. package/dist/text/diff.d.ts +10 -0
  206. package/dist/text/diff.d.ts.map +1 -0
  207. package/dist/text/diff.js +26 -0
  208. package/dist/text/diff.js.map +1 -0
  209. package/dist/text/since.d.ts +29 -0
  210. package/dist/text/since.d.ts.map +1 -0
  211. package/dist/text/since.js +66 -0
  212. package/dist/text/since.js.map +1 -0
  213. package/dist/text/splice.d.ts +51 -0
  214. package/dist/text/splice.d.ts.map +1 -0
  215. package/dist/text/splice.js +71 -0
  216. package/dist/text/splice.js.map +1 -0
  217. package/dist/text/typing-hook.d.ts +37 -0
  218. package/dist/text/typing-hook.d.ts.map +1 -0
  219. package/dist/text/typing-hook.js +16 -0
  220. package/dist/text/typing-hook.js.map +1 -0
  221. package/dist/tidying.d.ts +1 -1
  222. package/dist/tidying.d.ts.map +1 -1
  223. package/dist/typing.d.ts +2 -0
  224. package/dist/typing.d.ts.map +1 -0
  225. package/dist/typing.js +109 -0
  226. package/dist/typing.js.map +1 -0
  227. package/dist/version.d.ts +1 -1
  228. package/dist/version.js +1 -1
  229. package/dist/who.d.ts +1 -1
  230. package/dist/who.d.ts.map +1 -1
  231. package/dist/who.js +5 -2
  232. package/dist/who.js.map +1 -1
  233. package/package.json +12 -2
@@ -0,0 +1,23 @@
1
+ import { actingAs, isSystem } from "./permissions/policy.js";
2
+ import * as z from "./schema/zod.js";
3
+ /** The built-in act that publishes: every store of an `on-publish` app answers to it once `@graview/core/publishing` is loaded. */
4
+ export const PUBLISH = "publish";
5
+ /** Whether an app's readers are served what was published rather than the head. */
6
+ export const onPublish = (publishing) => publishing?.mode === "on-publish";
7
+ /**
8
+ * Whether a seat is a reader — served what was published — under this
9
+ * declaration: not the system, and (unless it asked to see the app as
10
+ * readers do) holding no `working` role, an agent's read through the
11
+ * person it acts for.
12
+ */
13
+ export const readsPublished = (publishing, principal, as) => onPublish(publishing) && !isSystem(principal) && (as === "published" || !(actingAs(principal).roles ?? []).some((role) => publishing.working.includes(role)));
14
+ /*
15
+ * One object for the store, the seat view and `@graview/core/publishing`,
16
+ * found by a key every copy agrees on, as a seat's view is (`seat-of.ts`):
17
+ * the module a page fetches imports nothing of what it loaded first, so
18
+ * a bundler leaves all of that where it was — a page that never draws a
19
+ * store (the guest host) does not load the seat view for its sake.
20
+ */
21
+ export const PUBLISHING = (globalThis[Symbol.for("@graview/core:publishing")] ??= {});
22
+ PUBLISHING.input = () => z.object({ through: z.optional(z.number()) });
23
+ //# sourceMappingURL=publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,KAAK,CAAC,MAAM,iBAAiB,CAAC;AA4BrC,mIAAmI;AACnI,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC;AAEjC,mFAAmF;AACnF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,UAAkC,EAA4B,EAAE,CAAC,UAAU,EAAE,IAAI,KAAK,YAAY,CAAC;AAE7H;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAkC,EAAE,SAAoB,EAAE,EAAyB,EAAW,EAAE,CAC7H,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,WAAW,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAyBhK;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAqB,CAAE,UAA2D,CAAC,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;AAC1J,UAAU,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { AnyMutationDefinition } from "./mutations/types.js";
2
+ import type { OperationLog } from "./ops/log.js";
3
+ import type { Principal, Refusal } from "./permissions/types.js";
4
+ import type { Publishing } from "./publish.js";
5
+ import type { AnySchema } from "./schema/schema.js";
6
+ export declare const publishMutation: <S extends AnySchema>() => AnyMutationDefinition<S>;
7
+ export declare function publishedSeqOf(log: Pick<OperationLog, "all" | "undoneIds">): number | undefined;
8
+ /** Who may publish: a refusal in a sentence when this principal may not — whoever holds none of `publishers` (else `working`), the system aside. */
9
+ export declare function publishRefusal(publishing: Publishing | undefined, principal: Principal): Refusal | undefined;
10
+ //# sourceMappingURL=publishing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publishing.d.ts","sourceRoot":"","sources":["../src/publishing.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA6BpD,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,SAAS,OAAK,qBAAqB,CAAC,CAAC,CAAiD,CAAC;AAYjI,wBAAgB,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,GAAG,WAAW,CAAC,GAAG,MAAM,GAAG,SAAS,CAe/F;AAED,oJAAoJ;AACpJ,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAK5G"}
@@ -0,0 +1,168 @@
1
+ import { pastOf } from "./past.js";
2
+ /** The store's and the seat view's own (`publish.ts`), found by its key: nothing of a page's first chunk is imported here. */
3
+ const PUBLISHING = (globalThis[Symbol.for("@graview/core:publishing")] ??= {});
4
+ /** What the seat view lends, once its module has run — which it has wherever a store is served. */
5
+ const kit = () => PUBLISHING.kit;
6
+ /*
7
+ * Written out here rather than imported where they are kept (`PUBLISH`,
8
+ * `onPublish`, the seat view's key and `bound`), so a page that fetches
9
+ * this asks its first chunk for as few names as it can.
10
+ */
11
+ const NAME = "publish";
12
+ const publishes = (publishing) => publishing?.mode === "on-publish";
13
+ const SEAT = Symbol.for("@graview/core:seat");
14
+ const bound = (target, prop) => {
15
+ const value = Reflect.get(target, prop, target);
16
+ return typeof value === "function" ? value.bind(target) : value;
17
+ };
18
+ /**
19
+ * "PUBLISH": no record is its subject and it makes none. Its one argument,
20
+ * `through`, publishes through an earlier seq; absent, everything to the
21
+ * head. The store writes its op itself (`publishedThrough`), so its body
22
+ * is never run; offered, as the store offers it, to `publishers`.
23
+ */
24
+ let made;
25
+ const act = () => (made ??= { name: NAME, title: "Publish", description: "Publish what collaborators have changed, so readers see it.", input: PUBLISHING.input(), apply() { } });
26
+ export const publishMutation = () => act();
27
+ /**
28
+ * HOW FAR READERS ARE SERVED: the `publishedThrough` of the last publish
29
+ * op that stands (an undone one does not — undoing a publish takes readers
30
+ * back to the one before), or `undefined` when nothing was ever published.
31
+ * Kept per log while its length and last op are the ones it was read at.
32
+ */
33
+ const READ = new WeakMap();
34
+ export function publishedSeqOf(log) {
35
+ const ops = log.all();
36
+ const last = ops.at(-1)?.id;
37
+ const held = READ.get(log);
38
+ if (held && held.length === ops.length && held.last === last)
39
+ return held.seq;
40
+ let seq;
41
+ let undone;
42
+ for (let at = ops.length - 1; at >= 0; at--) {
43
+ const op = ops[at];
44
+ if (op.publishedThrough === undefined || (undone ??= log.undoneIds()).has(op.id))
45
+ continue;
46
+ seq = op.publishedThrough;
47
+ break;
48
+ }
49
+ READ.set(log, { length: ops.length, last, seq });
50
+ return seq;
51
+ }
52
+ /** Who may publish: a refusal in a sentence when this principal may not — whoever holds none of `publishers` (else `working`), the system aside. */
53
+ export function publishRefusal(publishing, principal) {
54
+ if (!publishes(publishing))
55
+ return { mutation: NAME, message: "this app is live: every edit reaches its readers as it is made, so there is nothing to publish.", wouldNeed: [] };
56
+ const roles = publishing.publishers ?? publishing.working;
57
+ if (!kit().reads({ mode: "on-publish", working: roles }, principal))
58
+ return undefined;
59
+ return { mutation: NAME, message: `only ${roles.join(", ") || "nobody"} may publish.`, wouldNeed: [...roles] };
60
+ }
61
+ /**
62
+ * THE MARKER A PUBLISH IS: one op that touches no record and says how far
63
+ * readers are served — through itself, or through `through` when the call
64
+ * names an earlier seq the store holds — appended to the store's log.
65
+ */
66
+ const publishOp = (held, made, call, batch, author, options) => {
67
+ const { log } = held;
68
+ const seq = log.length;
69
+ const asked = call.args["through"];
70
+ if (asked !== undefined && (!Number.isInteger(asked) || asked < log.horizon || asked > seq)) {
71
+ throw new RangeError(`Cannot publish through seq ${String(asked)}: this store holds seqs ${log.horizon} to ${seq}.`);
72
+ }
73
+ const through = asked ?? seq + 1;
74
+ const was = publishedSeqOf(log) ?? log.horizon;
75
+ const changes = log.batches().filter((one) => !one.undone && one.ops.some((op) => op.seq >= was && op.seq < through && op.publishedThrough === undefined)).length;
76
+ const op = {
77
+ id: made.id,
78
+ seq,
79
+ batch,
80
+ author,
81
+ intent: through < was ? "Take back what was published" : `Publish ${changes === 1 ? "1 change" : `${changes} changes`}`,
82
+ ...(options.intent !== undefined ? { batchIntent: options.intent } : {}),
83
+ mutation: call,
84
+ primitives: [],
85
+ reads: [],
86
+ writes: [],
87
+ at: made.at,
88
+ ...(options.via !== undefined ? { via: options.via } : {}),
89
+ publishedThrough: through,
90
+ };
91
+ log.append(op);
92
+ return op;
93
+ };
94
+ /** The reads a reader's view answers from what was published; every other, and every write, is the head's. */
95
+ const PUBLISHED_READS = new Set(["graph", "log", "snapshot", "batches", "violations", "findings", "canUndo", "servedSeq", "checkpoint"]);
96
+ /**
97
+ * THE APP AS A READER IS SERVED IT, in an app that publishes: its graph,
98
+ * log, problems and history are those of the app as it stood at the last
99
+ * publish (`pastOf`) — before the first, the start of the log (the seed,
100
+ * or the horizon of a log compacted past it) — as the seat may see it;
101
+ * and every act, preview and permission still goes to the store and is
102
+ * judged at the head, where what the reader writes lands — read by readers
103
+ * when it is next published. It follows the published seq as a publish (or
104
+ * the undo of one) moves it, and tells its subscribers only when it does,
105
+ * with the change between the two.
106
+ */
107
+ function servedBehind(store, principal) {
108
+ const { seatView, viewsOf, viewKey, diff: diffSnapshots } = kit();
109
+ const views = viewsOf(store);
110
+ const key = viewKey(principal, "published");
111
+ const held = views.get(key);
112
+ if (held)
113
+ return held;
114
+ const head = seatView(store, principal);
115
+ let kept;
116
+ const now = () => {
117
+ const seq = Math.max(store.publishedSeq ?? store.log.horizon, store.log.horizon);
118
+ if (seq >= store.log.length)
119
+ return head;
120
+ const id = store.log.all()[seq - 1 - store.log.horizon]?.id;
121
+ if (kept?.seq !== seq || kept.id !== id)
122
+ kept = { seq, id, view: seatView(pastOf(store, seq), principal) };
123
+ return kept.view;
124
+ };
125
+ const seqOf = (served) => served.servedSeq;
126
+ const subscribe = (listener) => {
127
+ let from = seqOf(now());
128
+ let shot = now().graph.snapshot();
129
+ return store.subscribe((() => {
130
+ const served = now();
131
+ const to = seqOf(served);
132
+ if (to === from)
133
+ return;
134
+ const after = served.graph.snapshot();
135
+ const ops = to > from ? served.log.all().filter((op) => op.seq >= from) : [];
136
+ const diff = diffSnapshots(shot, after);
137
+ [from, shot] = [to, after];
138
+ listener(diff, ops);
139
+ }));
140
+ };
141
+ const view = new Proxy(head, {
142
+ get(target, prop) {
143
+ switch (prop) {
144
+ case SEAT:
145
+ return { store, principal };
146
+ case "subscribe":
147
+ return subscribe;
148
+ case "seenBy":
149
+ return (other, options) => store.seenBy(other, options);
150
+ case "seenFor":
151
+ return principal;
152
+ default:
153
+ return PUBLISHED_READS.has(prop) ? bound(now(), prop) : bound(target, prop);
154
+ }
155
+ },
156
+ });
157
+ views.set(key, view);
158
+ return view;
159
+ }
160
+ PUBLISHING.served = servedBehind;
161
+ PUBLISHING.act = (held, declared) => (publishes(held.publishing) && !held.past && !declared.has(NAME) ? act() : undefined);
162
+ PUBLISHING.verdict = (held, principal) => {
163
+ const refusal = publishRefusal(held.publishing, principal);
164
+ return refusal ? { ok: false, refusal } : { ok: true };
165
+ };
166
+ PUBLISHING.seq = (held) => (publishes(held.publishing) ? publishedSeqOf(held.log) : undefined);
167
+ PUBLISHING.op = publishOp;
168
+ //# sourceMappingURL=publishing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publishing.js","sourceRoot":"","sources":["../src/publishing.ts"],"names":[],"mappings":"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"}
package/dist/refused.d.ts CHANGED
@@ -3,9 +3,12 @@
3
3
  *
4
4
  * A refusal reached a client as a sentence and nothing else, so an MCP tool
5
5
  * and an interface told "you may not" from "it is gone" by matching words.
6
- * The set is closed and on the stability surface (docs/stability.md): a
7
- * code never changes meaning, and before 1.0 one may be added, the
8
- * changelog saying so (`unavailable`, FR-66; `refused`, FR-119).
6
+ * The set is OPEN and on the stability surface (docs/stability.md): a code
7
+ * never changes meaning, a code may be added within a major, the changelog
8
+ * saying so (`unavailable`, FR-66; `refused`, FR-119; `unauthenticated`
9
+ * and `quota`, 1.0's foundation), and a client meeting a code it does not
10
+ * know treats it as a final refusal — the change is taken back, its
11
+ * sentence shown — never as `unavailable`.
9
12
  *
10
13
  * forbidden the seat may not: the policy, a sight, an agent's `may`, a module turned off
11
14
  * missing what the call names is not there: a record, or a batch to take back
@@ -13,16 +16,20 @@
13
16
  * limit the host's hard cap: the call can never succeed as asked, however long the caller waits
14
17
  * unavailable the host takes no changes for a while — a room read-only while it is checked, storage that failed to write — and does not know for how long
15
18
  * refused the act's own rule said no to a well-formed call: a document act's `allowedWhen`, a TypeScript mutation's `ActRefusal` (FR-119)
19
+ * unauthenticated the host does not know who is asking: no session, or one that ran out; signing in again may let the same change through
20
+ * quota the account the app belongs to has used what its plan allows: the change may succeed once the allowance grows, never by waiting
16
21
  *
17
- * `limit` and `unavailable` are the host's to say; nothing in the store
18
- * says them. Neither is `busy`: busy is "not now, after `retryAfter`", and
22
+ * A body too large to take is `limit` (413), and a caller sending too much
23
+ * too fast is told `busy` with a wait (429), which is not a refusal.
24
+ * `limit`, `unavailable`, `unauthenticated` and `quota` are the host's to
25
+ * say; nothing in the store says them. Neither is `busy`: busy is "not now, after `retryAfter`", and
19
26
  * the client keeps the change and sends it again (FR-45). `unavailable` is
20
27
  * the one refusal that is not final: nothing was judged, and the client
21
28
  * keeps the change pending and sends it again, backing off as it does to
22
29
  * reconnect, until the host takes it. A refusal of any other reason is
23
30
  * final, and the change is taken back.
24
31
  */
25
- export declare const REFUSAL_REASONS: readonly ["forbidden", "missing", "invalid", "limit", "unavailable", "refused"];
32
+ export declare const REFUSAL_REASONS: readonly ["forbidden", "missing", "invalid", "limit", "unavailable", "refused", "unauthenticated", "quota"];
26
33
  export type RefusalReason = (typeof REFUSAL_REASONS)[number];
27
34
  /**
28
35
  * A REFUSAL AN ACT SAYS ITSELF, TYPED (FR-110).
@@ -1 +1 @@
1
- {"version":3,"file":"refused.d.ts","sourceRoot":"","sources":["../src/refused.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,eAAe,iFAAkF,CAAC;AAE/G,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAW,SAAQ,KAAK;IAEjC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa;gBADrB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,aAAyB;CAK7C"}
1
+ {"version":3,"file":"refused.d.ts","sourceRoot":"","sources":["../src/refused.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,eAAe,6GAA8G,CAAC;AAE3I,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAW,SAAQ,KAAK;IAEjC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa;gBADrB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,aAAyB;CAK7C"}
package/dist/refused.js CHANGED
@@ -3,9 +3,12 @@
3
3
  *
4
4
  * A refusal reached a client as a sentence and nothing else, so an MCP tool
5
5
  * and an interface told "you may not" from "it is gone" by matching words.
6
- * The set is closed and on the stability surface (docs/stability.md): a
7
- * code never changes meaning, and before 1.0 one may be added, the
8
- * changelog saying so (`unavailable`, FR-66; `refused`, FR-119).
6
+ * The set is OPEN and on the stability surface (docs/stability.md): a code
7
+ * never changes meaning, a code may be added within a major, the changelog
8
+ * saying so (`unavailable`, FR-66; `refused`, FR-119; `unauthenticated`
9
+ * and `quota`, 1.0's foundation), and a client meeting a code it does not
10
+ * know treats it as a final refusal — the change is taken back, its
11
+ * sentence shown — never as `unavailable`.
9
12
  *
10
13
  * forbidden the seat may not: the policy, a sight, an agent's `may`, a module turned off
11
14
  * missing what the call names is not there: a record, or a batch to take back
@@ -13,16 +16,20 @@
13
16
  * limit the host's hard cap: the call can never succeed as asked, however long the caller waits
14
17
  * unavailable the host takes no changes for a while — a room read-only while it is checked, storage that failed to write — and does not know for how long
15
18
  * refused the act's own rule said no to a well-formed call: a document act's `allowedWhen`, a TypeScript mutation's `ActRefusal` (FR-119)
19
+ * unauthenticated the host does not know who is asking: no session, or one that ran out; signing in again may let the same change through
20
+ * quota the account the app belongs to has used what its plan allows: the change may succeed once the allowance grows, never by waiting
16
21
  *
17
- * `limit` and `unavailable` are the host's to say; nothing in the store
18
- * says them. Neither is `busy`: busy is "not now, after `retryAfter`", and
22
+ * A body too large to take is `limit` (413), and a caller sending too much
23
+ * too fast is told `busy` with a wait (429), which is not a refusal.
24
+ * `limit`, `unavailable`, `unauthenticated` and `quota` are the host's to
25
+ * say; nothing in the store says them. Neither is `busy`: busy is "not now, after `retryAfter`", and
19
26
  * the client keeps the change and sends it again (FR-45). `unavailable` is
20
27
  * the one refusal that is not final: nothing was judged, and the client
21
28
  * keeps the change pending and sends it again, backing off as it does to
22
29
  * reconnect, until the host takes it. A refusal of any other reason is
23
30
  * final, and the change is taken back.
24
31
  */
25
- export const REFUSAL_REASONS = ["forbidden", "missing", "invalid", "limit", "unavailable", "refused"];
32
+ export const REFUSAL_REASONS = ["forbidden", "missing", "invalid", "limit", "unavailable", "refused", "unauthenticated", "quota"];
26
33
  /**
27
34
  * A REFUSAL AN ACT SAYS ITSELF, TYPED (FR-110).
28
35
  *
@@ -1 +1 @@
1
- {"version":3,"file":"refused.js","sourceRoot":"","sources":["../src/refused.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,CAAU,CAAC;AAI/G;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAExB;IACA;IAFX,YACW,QAAgB,EAChB,SAAwB,SAAS;QAE1C,KAAK,CAAC,QAAQ,CAAC,CAAC;QAHP,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAA2B;QAG1C,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF"}
1
+ {"version":3,"file":"refused.js","sourceRoot":"","sources":["../src/refused.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,OAAO,CAAU,CAAC;AAI3I;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IAExB;IACA;IAFX,YACW,QAAgB,EAChB,SAAwB,SAAS;QAE1C,KAAK,CAAC,QAAQ,CAAC,CAAC;QAHP,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAA2B;QAG1C,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ export declare const COLLABORATIVE: unique symbol;
2
+ /** Marks a schema as typed together (`true`, the default) or written whole (`false`), whatever it would be by default. */
3
+ export declare const markCollaborative: <T extends object>(schema: T, on?: boolean) => T;
4
+ /**
5
+ * Whether a field is typed together: its mark where it has one, under
6
+ * optional, default and nullable; else whether it is declared prose — a
7
+ * Markdown field, or a string declared to hold more than 500 characters.
8
+ */
9
+ export declare function isCollaborativeField(schema: unknown): boolean;
10
+ /** Whether one field of a kind is typed together, read off the declaration: false for a field the kind does not declare. */
11
+ export declare function collaborativeFieldOf(schema: {
12
+ tryDefinition(kind: string): unknown;
13
+ }, kind: string | undefined, field: string): boolean;
14
+ //# sourceMappingURL=collaborative.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collaborative.d.ts","sourceRoot":"","sources":["../../src/schema/collaborative.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,aAAa,eAA4C,CAAC;AASvE,0HAA0H;AAC1H,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAS,KAAG,CAI1E,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAiB7D;AAED,4HAA4H;AAC5H,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAIvI"}
@@ -0,0 +1,65 @@
1
+ /*
2
+ * TEXT TYPED TOGETHER (Roadmap f-collab-text, phase 2).
3
+ *
4
+ * Whether two people may type into one text field at once — each keystroke
5
+ * a splice, transformed over the others — is the declaration's to say, and
6
+ * never the value's: an empty draft of an essay is typed together as the
7
+ * essay is. Declared prose is, unless it says otherwise: a Markdown field,
8
+ * a document's `text`, a string declared to hold more than 500 characters
9
+ * (`z.string().max(5000)`). A short string — a name, a code, a status — is
10
+ * written whole, and a stale write of it is a conflict to choose over.
11
+ *
12
+ * The mark is on the schema's def, as Markdown's is (`markdown.ts`), so a
13
+ * clone shares it and a wrapper holds it inside; `markCollaborative(schema,
14
+ * false)` says a long field is written whole, and a document's field says
15
+ * `"collaborative": false | true`, marked where it is built (`fieldSchema`)
16
+ * by the same `Symbol.for`. Read without zod, so the store carries it and
17
+ * not zod's helpers.
18
+ */
19
+ export const COLLABORATIVE = Symbol.for("@graview/core:collaborative");
20
+ const MARKDOWN = Symbol.for("@graview/core:markdown");
21
+ /** What a string field may hold beyond which it is prose, as a record's page reads it (`isLongText`). */
22
+ const PROSE_ALLOWED = 500;
23
+ const defOf = (schema) => (typeof schema === "object" && schema !== null ? schema._zod?.def : undefined);
24
+ /** Marks a schema as typed together (`true`, the default) or written whole (`false`), whatever it would be by default. */
25
+ export const markCollaborative = (schema, on = true) => {
26
+ const def = defOf(schema);
27
+ if (def)
28
+ def[COLLABORATIVE] = on ? 1 : 0;
29
+ return schema;
30
+ };
31
+ /**
32
+ * Whether a field is typed together: its mark where it has one, under
33
+ * optional, default and nullable; else whether it is declared prose — a
34
+ * Markdown field, or a string declared to hold more than 500 characters.
35
+ */
36
+ export function isCollaborativeField(schema) {
37
+ let at = schema;
38
+ for (let depth = 0; depth < 6; depth++) {
39
+ const def = defOf(at);
40
+ if (!def)
41
+ return false;
42
+ if (def[COLLABORATIVE] !== undefined)
43
+ return def[COLLABORATIVE] === 1;
44
+ if (def[MARKDOWN] === 1)
45
+ return true;
46
+ if (def.type === "string") {
47
+ return (def.checks ?? []).some((check) => {
48
+ const said = defOf(check);
49
+ return said?.check === "max_length" && (said.maximum ?? 0) > PROSE_ALLOWED;
50
+ });
51
+ }
52
+ if (def.innerType === undefined)
53
+ return false;
54
+ at = def.innerType;
55
+ }
56
+ return false;
57
+ }
58
+ /** Whether one field of a kind is typed together, read off the declaration: false for a field the kind does not declare. */
59
+ export function collaborativeFieldOf(schema, kind, field) {
60
+ if (kind === undefined || field === "id" || field === "kind")
61
+ return false;
62
+ const shape = schema.tryDefinition(kind)?.fields?.shape;
63
+ return !!shape && Object.prototype.hasOwnProperty.call(shape, field) && isCollaborativeField(shape[field]);
64
+ }
65
+ //# sourceMappingURL=collaborative.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collaborative.js","sourceRoot":"","sources":["../../src/schema/collaborative.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AACvE,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AAEtD,yGAAyG;AACzG,MAAM,aAAa,GAAG,GAAG,CAAC;AAG1B,MAAM,KAAK,GAAG,CAAC,MAAe,EAAmB,EAAE,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAE,MAAmC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAEjK,0HAA0H;AAC1H,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAmB,MAAS,EAAE,EAAE,GAAG,IAAI,EAAK,EAAE;IAC7E,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAwC,CAAC;IACjE,IAAI,GAAG;QAAE,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,IAAI,EAAE,GAAG,MAAM,CAAC;IAChB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;QACtB,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QACvB,IAAI,GAAG,CAAC,aAAa,CAAC,KAAK,SAAS;YAAE,OAAO,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACtE,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;gBACvC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAuE,CAAC;gBAChG,OAAO,IAAI,EAAE,KAAK,KAAK,YAAY,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,aAAa,CAAC;YAC7E,CAAC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC9C,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,4HAA4H;AAC5H,MAAM,UAAU,oBAAoB,CAAC,MAAgD,EAAE,IAAwB,EAAE,KAAa;IAC5H,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAC3E,MAAM,KAAK,GAAI,MAAM,CAAC,aAAa,CAAC,IAAI,CAAkE,EAAE,MAAM,EAAE,KAAK,CAAC;IAC1H,OAAO,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7G,CAAC"}
package/dist/seen.d.ts CHANGED
@@ -5,6 +5,7 @@ import type { Operation } from "./ops/types.js";
5
5
  import { type SeatLens } from "./ops/withheld.js";
6
6
  import { type Judged } from "./permissions/sight.js";
7
7
  import type { Principal } from "./permissions/types.js";
8
+ import { type Publishing } from "./publish.js";
8
9
  /**
9
10
  * WHETHER ANYTHING IS KEPT FROM THIS SEAT: a sight the policy declares
10
11
  * (FR-02), or a module the workspace has off (FR-12). When neither, every
@@ -60,6 +61,36 @@ export declare function seatLens(store: Judged, principal: Principal): SeatLens;
60
61
  export declare function logSeenBy(store: Judged, principal: Principal): readonly Operation[];
61
62
  /** A log reading over a seat's redacted ops, for `checkUndo`. */
62
63
  export declare function readingOf(ops: readonly Operation[], epochs: LogReading["epochs"]): LogReading;
64
+ /**
65
+ * WHERE A SEAT'S VIEW IS SERVED THROUGH (`servedSeq`): the head, for a seat
66
+ * of a live app and a collaborator of one that publishes — the view reads
67
+ * its store as it grows — or what was published, for a reader of one
68
+ * (`servedBehind`), which moves when a publish does. The store a seat's
69
+ * view is of, the module reading what is off and the policy are each the
70
+ * store's own, so the view's key is the seat and this.
71
+ */
72
+ export declare const viewKey: (principal: Principal, served: "head" | "published") => string;
73
+ export declare const bound: (target: object, prop: PropertyKey) => unknown;
74
+ /**
75
+ * THE APP AS THIS SEAT IS SERVED IT.
76
+ *
77
+ * Every surface reads `store.graph` — the scene, the pages, Find, the
78
+ * chat, an agent's tools — and none of them asked who was looking: a
79
+ * storefront showed a stranger every customer's name, email and finance
80
+ * question, because a policy could only say who may ACT. With the policy's
81
+ * `sees` declared, this is the store a surface is handed: its graph, its
82
+ * log, its history and its problems hold only what the principal may see,
83
+ * and every act still goes to the store itself, judged there — at the
84
+ * head — as always. With no `sees`, it is the store, unchanged.
85
+ *
86
+ * What a seat is served is not promised to be the head: it is served
87
+ * through `servedSeq`, which is the head today and which a policy may set
88
+ * behind it (docs/stability.md, "Served state and the head"). Nor is it
89
+ * promised to be one object per principal: the view is kept to save
90
+ * judging again, keyed by what serving depends on (`viewKey`).
91
+ */
92
+ /** The key a seat's view answers with the store it is of and the seat (`seatOf`, `@graview/core/seat-of`'s reading of it). */
93
+ export declare const SEAT: unique symbol;
63
94
  /**
64
95
  * WHAT A SEAT'S VIEW IS A VIEW OF: a store as `seenBy` reads it — beyond
65
96
  * what judges its sight, its graph and its log whole, which the view serves
@@ -84,6 +115,18 @@ export interface Viewed extends Judged {
84
115
  readonly author: Principal;
85
116
  }): unknown;
86
117
  checkpoint(options?: never): Epoch | undefined;
118
+ readonly publishing?: Publishing | undefined;
119
+ readonly publishedSeq?: number | undefined;
120
+ subscribe(listener: never): () => void;
121
+ }
122
+ /** How a seat asks to be served: as it is (the default), or — a collaborator previewing — as readers are, `"published"`. */
123
+ export interface SeenOptions {
124
+ readonly as?: "head" | "published";
87
125
  }
88
- export declare function seenBy<T extends Viewed>(store: T, principal: Principal): T;
126
+ export declare function seenBy<T extends Viewed>(store: T, principal: Principal, options?: SeenOptions): T;
127
+ /** Whether readers of an app that publishes can be served here: true once `@graview/core/publishing` is loaded. */
128
+ export declare const servesReaders: () => boolean;
129
+ export declare function viewsOf(store: object): Map<string, unknown>;
130
+ /** The app as a seat is served it at the head: what its sight reaches, as the store grows. */
131
+ export declare function seatView<T extends Viewed>(store: T, principal: Principal): T;
89
132
  //# sourceMappingURL=seen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"seen.d.ts","sourceRoot":"","sources":["../src/seen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"seen.d.ts","sourceRoot":"","sources":["../src/seen.ts"],"names":[],"mappings":"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"}
package/dist/seen.js CHANGED
@@ -4,6 +4,8 @@ import { writersOf } from "./ops/writers.js";
4
4
  import { namesUnseen, redact } from "./ops/withheld.js";
5
5
  import { actingAs, grantsTo, isSystem } from "./permissions/policy.js";
6
6
  import { FIELD_SIGHT, fieldsJudged, partialSight, recordsOf, sees } from "./permissions/sight.js";
7
+ import { diffSnapshots } from "./graph/diff.js";
8
+ import { PUBLISHING, readsPublished } from "./publish.js";
7
9
  const NOTHING = new Set();
8
10
  /**
9
11
  * The kinds kept from a seat because their module is off (FR-12): from
@@ -293,7 +295,7 @@ const touchedIds = (ops) => {
293
295
  for (const primitive of op.primitives) {
294
296
  if (primitive.op === "add-node" || primitive.op === "remove-node")
295
297
  ids.add(primitive.node.id);
296
- else if (primitive.op === "patch-node")
298
+ else if (primitive.op === "patch-node" || primitive.op === "splice-text")
297
299
  ids.add(primitive.id);
298
300
  else {
299
301
  ids.add(primitive.edge.from);
@@ -370,17 +372,33 @@ export function readingOf(ops, epochs) {
370
372
  return { all: () => ops, undoneIds: () => undoneIn(ops), epochs };
371
373
  }
372
374
  const VIEWS = new WeakMap();
373
- /** A seat, keyed by the seat the policy judges: an agent for Nick is not the same agent alone. */
375
+ /**
376
+ * A seat, keyed by the seat the policy judges: an agent for Nick is not the
377
+ * same agent alone. It is everything serving reads of the principal — its
378
+ * kind, the id and roles sight is judged by (`actingAs`), and whether it
379
+ * acts for somebody — and nothing it does not (a session, a name), so two
380
+ * tabs of one seat share what they are served.
381
+ */
374
382
  function seatKey(principal) {
375
383
  const judged = isSystem(principal) ? principal : actingAs(principal);
376
- return `${principal.kind}|${judged.id ?? ""}|${(judged.roles ?? []).join(",")}|${principal.onBehalfOf ? "for" : ""}`;
384
+ // An agent's own id too: two agents for one person are two seats, and each view answers as its own (`seenFor`, `wouldChange`, `preview`).
385
+ return `${principal.kind}|${judged.id ?? ""}|${(judged.roles ?? []).join(",")}|${principal.onBehalfOf ? `for:${principal.id ?? ""}` : ""}`;
377
386
  }
378
- const bound = (target, prop) => {
387
+ /**
388
+ * WHERE A SEAT'S VIEW IS SERVED THROUGH (`servedSeq`): the head, for a seat
389
+ * of a live app and a collaborator of one that publishes — the view reads
390
+ * its store as it grows — or what was published, for a reader of one
391
+ * (`servedBehind`), which moves when a publish does. The store a seat's
392
+ * view is of, the module reading what is off and the policy are each the
393
+ * store's own, so the view's key is the seat and this.
394
+ */
395
+ export const viewKey = (principal, served) => `${seatKey(principal)}@${served}`;
396
+ export const bound = (target, prop) => {
379
397
  const value = Reflect.get(target, prop, target);
380
398
  return typeof value === "function" ? value.bind(target) : value;
381
399
  };
382
400
  /**
383
- * THE STORE AS ONE PRINCIPAL MAY SEE IT.
401
+ * THE APP AS THIS SEAT IS SERVED IT.
384
402
  *
385
403
  * Every surface reads `store.graph` — the scene, the pages, Find, the
386
404
  * chat, an agent's tools — and none of them asked who was looking: a
@@ -388,19 +406,41 @@ const bound = (target, prop) => {
388
406
  * question, because a policy could only say who may ACT. With the policy's
389
407
  * `sees` declared, this is the store a surface is handed: its graph, its
390
408
  * log, its history and its problems hold only what the principal may see,
391
- * and every act still goes to the store itself, judged there as always.
392
- * With no `sees`, it is the store, unchanged.
409
+ * and every act still goes to the store itself, judged there — at the
410
+ * head — as always. With no `sees`, it is the store, unchanged.
411
+ *
412
+ * What a seat is served is not promised to be the head: it is served
413
+ * through `servedSeq`, which is the head today and which a policy may set
414
+ * behind it (docs/stability.md, "Served state and the head"). Nor is it
415
+ * promised to be one object per principal: the view is kept to save
416
+ * judging again, keyed by what serving depends on (`viewKey`).
393
417
  */
394
418
  /** The key a seat's view answers with the store it is of and the seat (`seatOf`, `@graview/core/seat-of`'s reading of it). */
395
- const SEAT = Symbol.for("@graview/core:seat");
396
- export function seenBy(store, principal) {
397
- // A module off keeps its kinds from every seat as a sight would (FR-12); the view reads which are off as it goes. The system is kept from nothing.
398
- if (!hidesFrom(store, principal))
399
- return store;
400
- const key = seatKey(principal);
419
+ export const SEAT = Symbol.for("@graview/core:seat");
420
+ export function seenBy(store, principal, options = {}) {
421
+ // A reader of an app that publishes is served what was published (Roadmap f-publishing-lifecycle), once `@graview/core/publishing` says how; until then, refused — never the head.
422
+ if (readsPublished(store.publishing, principal, options.as)) {
423
+ if (PUBLISHING.served)
424
+ return PUBLISHING.served(store, principal);
425
+ throw new Error("Load @graview/core/publishing to serve a reader of an app that publishes.");
426
+ }
427
+ return seatView(store, principal);
428
+ }
429
+ /** Whether readers of an app that publishes can be served here: true once `@graview/core/publishing` is loaded. */
430
+ export const servesReaders = () => PUBLISHING.served !== undefined;
431
+ export function viewsOf(store) {
401
432
  let views = VIEWS.get(store);
402
433
  if (!views)
403
434
  VIEWS.set(store, (views = new Map()));
435
+ return views;
436
+ }
437
+ /** The app as a seat is served it at the head: what its sight reaches, as the store grows. */
438
+ export function seatView(store, principal) {
439
+ // A module off keeps its kinds from every seat as a sight would (FR-12); the view reads which are off as it goes. The system is kept from nothing.
440
+ if (!hidesFrom(store, principal))
441
+ return store;
442
+ const key = viewKey(principal, "head");
443
+ const views = viewsOf(store);
404
444
  const held = views.get(key);
405
445
  if (held)
406
446
  return held;
@@ -577,9 +617,12 @@ export function seenBy(store, principal) {
577
617
  case "preview":
578
618
  return (call, context, options) => target.preview(call, context, { author: principal, ...options });
579
619
  case "seenBy":
580
- return (other) => seenBy(target, other);
620
+ return (other, options) => seenBy(target, other, options);
581
621
  case "seenFor":
582
622
  return principal;
623
+ // Where what this seat is served ends: the store's own (`servedSeq`) — its head, or a past's seq; never set through the view.
624
+ case "servedSeq":
625
+ return target.servedSeq;
583
626
  // A checkpoint taken through the seat's view is the one it is served.
584
627
  case "checkpoint":
585
628
  return (options) => servedIf(target.checkpoint(options));
@@ -591,4 +634,6 @@ export function seenBy(store, principal) {
591
634
  views.set(key, view);
592
635
  return view;
593
636
  }
637
+ // What the reader's view borrows of this module (`@graview/core/publishing`), lent rather than imported.
638
+ PUBLISHING.kit = { seatView: seatView, viewsOf, viewKey, diff: diffSnapshots, reads: readsPublished };
594
639
  //# sourceMappingURL=seen.js.map