@graview/core 0.1.62 → 0.1.64
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/app.d.ts +12 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js.map +1 -1
- package/dist/arranging.js +2 -2
- package/dist/arranging.js.map +1 -1
- package/dist/cli/check/index.d.ts +1 -0
- package/dist/cli/check/index.d.ts.map +1 -1
- package/dist/cli/check/index.js +1 -0
- package/dist/cli/check/index.js.map +1 -1
- package/dist/cli/check/workflows.d.ts +11 -0
- package/dist/cli/check/workflows.d.ts.map +1 -0
- package/dist/cli/check/workflows.js +20 -0
- package/dist/cli/check/workflows.js.map +1 -0
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +2 -1
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/describe.d.ts.map +1 -1
- package/dist/cli/describe.js +31 -1
- package/dist/cli/describe.js.map +1 -1
- package/dist/cli/document-schema.d.ts.map +1 -1
- package/dist/cli/document-schema.js +9 -0
- package/dist/cli/document-schema.js.map +1 -1
- package/dist/compose.d.ts +1 -1
- package/dist/compose.d.ts.map +1 -1
- package/dist/document/amount.d.ts +1 -1
- package/dist/document/amount.d.ts.map +1 -1
- package/dist/document/amount.js +2 -2
- package/dist/document/amount.js.map +1 -1
- package/dist/document/blocks.d.ts.map +1 -1
- package/dist/document/blocks.js +17 -1
- package/dist/document/blocks.js.map +1 -1
- package/dist/document/brand-check.d.ts.map +1 -1
- package/dist/document/brand-check.js +8 -2
- package/dist/document/brand-check.js.map +1 -1
- package/dist/document/compile-checked.d.ts.map +1 -1
- package/dist/document/compile-checked.js +4 -2
- package/dist/document/compile-checked.js.map +1 -1
- package/dist/document/compile.d.ts.map +1 -1
- package/dist/document/compile.js +48 -9
- package/dist/document/compile.js.map +1 -1
- package/dist/document/compiled.d.ts +14 -0
- package/dist/document/compiled.d.ts.map +1 -1
- package/dist/document/compiled.js +39 -4
- package/dist/document/compiled.js.map +1 -1
- package/dist/document/connection-findings.js +93 -21
- package/dist/document/connection-findings.js.map +1 -1
- package/dist/document/connection-spec.d.ts +54 -1
- package/dist/document/connection-spec.d.ts.map +1 -1
- package/dist/document/connection-spec.js +76 -8
- package/dist/document/connection-spec.js.map +1 -1
- package/dist/document/derives-findings.d.ts +4 -0
- package/dist/document/derives-findings.d.ts.map +1 -0
- package/dist/document/derives-findings.js +68 -0
- package/dist/document/derives-findings.js.map +1 -0
- package/dist/document/describe-forms.js +2 -2
- package/dist/document/describe-forms.js.map +1 -1
- package/dist/document/diff.d.ts +6 -0
- package/dist/document/diff.d.ts.map +1 -1
- package/dist/document/diff.js +43 -1
- package/dist/document/diff.js.map +1 -1
- package/dist/document/edit.d.ts +1 -1
- package/dist/document/edit.d.ts.map +1 -1
- package/dist/document/edit.js +264 -23
- package/dist/document/edit.js.map +1 -1
- package/dist/document/expr/evaluate.d.ts +7 -0
- package/dist/document/expr/evaluate.d.ts.map +1 -1
- package/dist/document/expr/evaluate.js +29 -2
- package/dist/document/expr/evaluate.js.map +1 -1
- package/dist/document/format-words.d.ts +1 -0
- package/dist/document/format-words.d.ts.map +1 -1
- package/dist/document/format-words.js +2 -2
- package/dist/document/format-words.js.map +1 -1
- package/dist/document/kept-in-step-with.d.ts +20 -0
- package/dist/document/kept-in-step-with.d.ts.map +1 -0
- package/dist/document/kept-in-step-with.js +38 -0
- package/dist/document/kept-in-step-with.js.map +1 -0
- package/dist/document/kept-in-step.d.ts.map +1 -1
- package/dist/document/kept-in-step.js +3 -1
- package/dist/document/kept-in-step.js.map +1 -1
- package/dist/document/money.d.ts +10 -2
- package/dist/document/money.d.ts.map +1 -1
- package/dist/document/money.js +14 -5
- package/dist/document/money.js.map +1 -1
- package/dist/document/policy-words.d.ts +2 -0
- package/dist/document/policy-words.d.ts.map +1 -1
- package/dist/document/policy-words.js +11 -1
- package/dist/document/policy-words.js.map +1 -1
- package/dist/document/schema.d.ts +46 -1
- package/dist/document/schema.d.ts.map +1 -1
- package/dist/document/schema.js +48 -8
- package/dist/document/schema.js.map +1 -1
- package/dist/document/template-parse.d.ts.map +1 -1
- package/dist/document/template-parse.js +7 -1
- package/dist/document/template-parse.js.map +1 -1
- package/dist/document/template.d.ts +2 -0
- package/dist/document/template.d.ts.map +1 -1
- package/dist/document/template.js +10 -1
- package/dist/document/template.js.map +1 -1
- package/dist/document/to-document.js +2 -2
- package/dist/document/to-document.js.map +1 -1
- package/dist/document/workflow-spec.d.ts +72 -0
- package/dist/document/workflow-spec.d.ts.map +1 -0
- package/dist/document/workflow-spec.js +45 -0
- package/dist/document/workflow-spec.js.map +1 -0
- package/dist/document.schema.json +883 -4
- package/dist/head.d.ts +81 -0
- package/dist/head.d.ts.map +1 -0
- package/dist/head.js +123 -0
- package/dist/head.js.map +1 -0
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +2 -0
- package/dist/history.js.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/installation.d.ts +1 -1
- package/dist/job-findings.d.ts +5 -0
- package/dist/job-findings.d.ts.map +1 -1
- package/dist/job-findings.js +9 -3
- package/dist/job-findings.js.map +1 -1
- package/dist/keep-linked.d.ts +45 -0
- package/dist/keep-linked.d.ts.map +1 -0
- package/dist/keep-linked.js +188 -0
- package/dist/keep-linked.js.map +1 -0
- package/dist/mutations/derive-edits.js +2 -2
- package/dist/mutations/propose-changes.d.ts +24 -0
- package/dist/mutations/propose-changes.d.ts.map +1 -0
- package/dist/mutations/propose-changes.js +30 -0
- package/dist/mutations/propose-changes.js.map +1 -0
- package/dist/mutations/vote-suggestion.d.ts +30 -0
- package/dist/mutations/vote-suggestion.d.ts.map +1 -1
- package/dist/mutations/vote-suggestion.js +23 -0
- package/dist/mutations/vote-suggestion.js.map +1 -1
- package/dist/mutations/words.js +3 -3
- package/dist/ops/digest.d.ts +3 -1
- package/dist/ops/digest.d.ts.map +1 -1
- package/dist/ops/digest.js +7 -2
- package/dist/ops/digest.js.map +1 -1
- package/dist/ops/lineage.d.ts +19 -2
- package/dist/ops/lineage.d.ts.map +1 -1
- package/dist/ops/lineage.js +8 -4
- package/dist/ops/lineage.js.map +1 -1
- package/dist/ops/log.d.ts.map +1 -1
- package/dist/ops/log.js +13 -2
- package/dist/ops/log.js.map +1 -1
- package/dist/ops/suggestions.d.ts +47 -5
- package/dist/ops/suggestions.d.ts.map +1 -1
- package/dist/ops/suggestions.js +88 -13
- package/dist/ops/suggestions.js.map +1 -1
- package/dist/ops/tidying.d.ts.map +1 -1
- package/dist/ops/tidying.js +6 -1
- package/dist/ops/tidying.js.map +1 -1
- package/dist/ops/types.d.ts +28 -0
- package/dist/ops/types.d.ts.map +1 -1
- package/dist/ops/undo.d.ts.map +1 -1
- package/dist/ops/undo.js +17 -0
- package/dist/ops/undo.js.map +1 -1
- package/dist/permissions/policy.d.ts +7 -0
- package/dist/permissions/policy.d.ts.map +1 -1
- package/dist/permissions/policy.js +12 -0
- package/dist/permissions/policy.js.map +1 -1
- package/dist/permissions/types.d.ts +27 -0
- package/dist/permissions/types.d.ts.map +1 -1
- package/dist/permissions/types.js.map +1 -1
- package/dist/places.d.ts +10 -0
- package/dist/places.d.ts.map +1 -1
- package/dist/places.js +35 -1
- package/dist/places.js.map +1 -1
- package/dist/scene.d.ts +2 -0
- package/dist/scene.d.ts.map +1 -1
- package/dist/scene.js +2 -0
- package/dist/scene.js.map +1 -1
- package/dist/schema/amount-mark.d.ts +2 -0
- package/dist/schema/amount-mark.d.ts.map +1 -1
- package/dist/schema/amount-mark.js.map +1 -1
- package/dist/schema/amount-words.js +2 -2
- package/dist/schema/amount-words.js.map +1 -1
- package/dist/schema/choice-words.js +2 -2
- package/dist/schema/define-node.d.ts +8 -2
- package/dist/schema/define-node.d.ts.map +1 -1
- package/dist/schema/define-node.js +2 -2
- package/dist/schema/define-node.js.map +1 -1
- package/dist/schema/humanize.d.ts +17 -0
- package/dist/schema/humanize.d.ts.map +1 -1
- package/dist/schema/humanize.js +28 -1
- package/dist/schema/humanize.js.map +1 -1
- package/dist/schema/reading.d.ts +8 -0
- package/dist/schema/reading.d.ts.map +1 -1
- package/dist/schema/reading.js +16 -2
- package/dist/schema/reading.js.map +1 -1
- package/dist/schema/types.d.ts +8 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/value-words.js +2 -2
- package/dist/schema/value-words.js.map +1 -1
- package/dist/starting-document.d.ts +16 -3
- package/dist/starting-document.d.ts.map +1 -1
- package/dist/starting-document.js +32 -5
- package/dist/starting-document.js.map +1 -1
- package/dist/store.d.ts +47 -2
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +176 -13
- package/dist/store.js.map +1 -1
- package/dist/sync/connection.d.ts +24 -5
- package/dist/sync/connection.d.ts.map +1 -1
- package/dist/sync/connection.js +168 -31
- package/dist/sync/connection.js.map +1 -1
- package/dist/sync/engine.d.ts +97 -0
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js +159 -1
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/google-calendar.d.ts.map +1 -1
- package/dist/sync/google-calendar.js +18 -1
- package/dist/sync/google-calendar.js.map +1 -1
- package/dist/sync/guest-words.d.ts +9 -0
- package/dist/sync/guest-words.d.ts.map +1 -0
- package/dist/sync/guest-words.js +41 -0
- package/dist/sync/guest-words.js.map +1 -0
- package/dist/sync/index.d.ts +8 -5
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +2 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/notion-stub.d.ts +4 -1
- package/dist/sync/notion-stub.d.ts.map +1 -1
- package/dist/sync/notion-stub.js +40 -0
- package/dist/sync/notion-stub.js.map +1 -1
- package/dist/sync/notion.d.ts +44 -2
- package/dist/sync/notion.d.ts.map +1 -1
- package/dist/sync/notion.js +289 -143
- package/dist/sync/notion.js.map +1 -1
- package/dist/sync/status.d.ts +43 -0
- package/dist/sync/status.d.ts.map +1 -0
- package/dist/sync/status.js +46 -0
- package/dist/sync/status.js.map +1 -0
- package/dist/sync/types.d.ts +60 -0
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/sync/types.js.map +1 -1
- package/dist/theme/marks.d.ts +12 -0
- package/dist/theme/marks.d.ts.map +1 -1
- package/dist/theme/marks.js +5 -0
- package/dist/theme/marks.js.map +1 -1
- package/dist/tidying.d.ts +53 -4
- package/dist/tidying.d.ts.map +1 -1
- package/dist/tidying.js +110 -8
- package/dist/tidying.js.map +1 -1
- package/dist/validate-graph.d.ts +2 -1
- package/dist/validate-graph.d.ts.map +1 -1
- package/dist/validate-graph.js +32 -1
- package/dist/validate-graph.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/words.d.ts +4 -1
- package/dist/words.d.ts.map +1 -1
- package/dist/words.js +4 -1
- package/dist/words.js.map +1 -1
- package/dist/workflow-shape.d.ts +223 -0
- package/dist/workflow-shape.d.ts.map +1 -0
- package/dist/workflow-shape.js +31 -0
- package/dist/workflow-shape.js.map +1 -0
- package/dist/workflows/findings.d.ts +13 -0
- package/dist/workflows/findings.d.ts.map +1 -0
- package/dist/workflows/findings.js +157 -0
- package/dist/workflows/findings.js.map +1 -0
- package/dist/workflows/generate-words.d.ts +12 -0
- package/dist/workflows/generate-words.d.ts.map +1 -0
- package/dist/workflows/generate-words.js +25 -0
- package/dist/workflows/generate-words.js.map +1 -0
- package/dist/workflows/generate.d.ts +59 -0
- package/dist/workflows/generate.d.ts.map +1 -0
- package/dist/workflows/generate.js +165 -0
- package/dist/workflows/generate.js.map +1 -0
- package/dist/workflows/judging.d.ts +17 -0
- package/dist/workflows/judging.d.ts.map +1 -0
- package/dist/workflows/judging.js +11 -0
- package/dist/workflows/judging.js.map +1 -0
- package/dist/workflows/next.d.ts +18 -0
- package/dist/workflows/next.d.ts.map +1 -0
- package/dist/workflows/next.js +75 -0
- package/dist/workflows/next.js.map +1 -0
- package/dist/workflows/on-the-map.d.ts +79 -0
- package/dist/workflows/on-the-map.d.ts.map +1 -0
- package/dist/workflows/on-the-map.js +96 -0
- package/dist/workflows/on-the-map.js.map +1 -0
- package/dist/workflows/policies.d.ts +39 -0
- package/dist/workflows/policies.d.ts.map +1 -0
- package/dist/workflows/policies.js +95 -0
- package/dist/workflows/policies.js.map +1 -0
- package/dist/workflows/resolve.d.ts +55 -0
- package/dist/workflows/resolve.d.ts.map +1 -0
- package/dist/workflows/resolve.js +57 -0
- package/dist/workflows/resolve.js.map +1 -0
- package/dist/workflows/schedule.d.ts +28 -0
- package/dist/workflows/schedule.d.ts.map +1 -0
- package/dist/workflows/schedule.js +160 -0
- package/dist/workflows/schedule.js.map +1 -0
- package/dist/workflows/step-act.d.ts +6 -0
- package/dist/workflows/step-act.d.ts.map +1 -0
- package/dist/workflows/step-act.js +79 -0
- package/dist/workflows/step-act.js.map +1 -0
- package/dist/workflows/step-agent.d.ts +4 -0
- package/dist/workflows/step-agent.d.ts.map +1 -0
- package/dist/workflows/step-agent.js +55 -0
- package/dist/workflows/step-agent.js.map +1 -0
- package/dist/workflows/step-archive.d.ts +8 -0
- package/dist/workflows/step-archive.d.ts.map +1 -0
- package/dist/workflows/step-archive.js +74 -0
- package/dist/workflows/step-archive.js.map +1 -0
- package/dist/workflows/step-classify.d.ts +25 -0
- package/dist/workflows/step-classify.d.ts.map +1 -0
- package/dist/workflows/step-classify.js +160 -0
- package/dist/workflows/step-classify.js.map +1 -0
- package/dist/workflows/step-generate.d.ts +7 -0
- package/dist/workflows/step-generate.d.ts.map +1 -0
- package/dist/workflows/step-generate.js +185 -0
- package/dist/workflows/step-generate.js.map +1 -0
- package/dist/workflows/steps.d.ts +75 -0
- package/dist/workflows/steps.d.ts.map +1 -0
- package/dist/workflows/steps.js +40 -0
- package/dist/workflows/steps.js.map +1 -0
- package/dist/workflows/triggered.d.ts +35 -0
- package/dist/workflows/triggered.d.ts.map +1 -0
- package/dist/workflows/triggered.js +69 -0
- package/dist/workflows/triggered.js.map +1 -0
- package/dist/workflows/values.d.ts +28 -0
- package/dist/workflows/values.d.ts.map +1 -0
- package/dist/workflows/values.js +75 -0
- package/dist/workflows/values.js.map +1 -0
- package/dist/workflows/words.d.ts +10 -0
- package/dist/workflows/words.d.ts.map +1 -0
- package/dist/workflows/words.js +30 -0
- package/dist/workflows/words.js.map +1 -0
- package/dist/workflows/world.d.ts +23 -0
- package/dist/workflows/world.d.ts.map +1 -0
- package/dist/workflows/world.js +50 -0
- package/dist/workflows/world.js.map +1 -0
- package/dist/workflows.d.ts +35 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +20 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +12 -2
package/dist/store.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Graph, GraphError, MissingRecordError } from "./graph/graph.js";
|
|
|
4
4
|
import { resolveModules } from "./modules.js";
|
|
5
5
|
import { diffSnapshots, diffTouched, EMPTY_DIFF, isEmptyDiff } from "./graph/diff.js";
|
|
6
6
|
import { normalize, writesOf } from "./graph/primitives.js";
|
|
7
|
+
import { keepLinked, keepsLinked } from "./keep-linked.js";
|
|
7
8
|
import { bareOp, inverseOf } from "./ops/inverse.js";
|
|
8
9
|
import { LabelIndex, refusalFor } from "./labels.js";
|
|
9
10
|
import { nodeRefArgs } from "./mutations/node-ref.js";
|
|
@@ -19,11 +20,12 @@ import { namesMade, resolveMade } from "./mutations/made.js";
|
|
|
19
20
|
import { OperationLog } from "./ops/log.js";
|
|
20
21
|
import { lineageOf } from "./ops/lineage.js";
|
|
21
22
|
import { KEEP_LINK, keepLinkMutation, keepLinkVia } from "./mutations/keep-link.js";
|
|
22
|
-
import { VOTE_SUGGESTION, VOTING, voteSuggestionMutation } from "./mutations/vote-suggestion.js";
|
|
23
|
+
import { advisoryVoterOf, signedOutSeat, SIGN_IN_TO_VOTE, VOTE_SUGGESTION, VOTING, voteSuggestionMutation } from "./mutations/vote-suggestion.js";
|
|
23
24
|
import { TYPE_TEXT, TYPING } from "./text/typing-hook.js";
|
|
24
25
|
import { declinedIn, isAutomated, tidyingRefusal } from "./ops/tidying.js";
|
|
25
26
|
import { nameOfAuthor } from "./who.js";
|
|
26
|
-
import { actingAs, grantsTo, isSystem, permits, permittedMutations, subjectKinds } from "./permissions/policy.js";
|
|
27
|
+
import { actingAs, grantsTo, isSystem, permits, permittedMutations, proposes, subjectKinds } from "./permissions/policy.js";
|
|
28
|
+
import { MOST_PROPOSED, PROPOSE_CHANGES, proposeChangesMutation } from "./mutations/propose-changes.js";
|
|
27
29
|
import { namesUnseen, redact } from "./ops/withheld.js";
|
|
28
30
|
import { writersBehind } from "./ops/writers.js";
|
|
29
31
|
import { nounOf } from "./schema/define-node.js";
|
|
@@ -187,6 +189,8 @@ export class Store {
|
|
|
187
189
|
typer;
|
|
188
190
|
/** "Vote on a suggestion" (Roadmap f-suggestion-votes), when the app declared no act by that name. */
|
|
189
191
|
voter;
|
|
192
|
+
/** "Propose changes" (Roadmap f-proposals-for-review), when the app declared no act by that name. */
|
|
193
|
+
proposer;
|
|
190
194
|
invariants;
|
|
191
195
|
invariantOptions;
|
|
192
196
|
policy;
|
|
@@ -194,6 +198,8 @@ export class Store {
|
|
|
194
198
|
publishing;
|
|
195
199
|
/** What the declaration says of suggestions as a whole (`StoreOptions.tidying`). */
|
|
196
200
|
tidying;
|
|
201
|
+
/** What the host says of votes from a shared or signed-out seat (`StoreOptions.votes`). */
|
|
202
|
+
votes;
|
|
197
203
|
/**
|
|
198
204
|
* The intelligence the app declared, so a surface can read the DOORS.
|
|
199
205
|
*
|
|
@@ -230,6 +236,8 @@ export class Store {
|
|
|
230
236
|
rehearsing = false;
|
|
231
237
|
/** True of a rehearsal for a suggestion: the actor is held to what a person said, not to the declaration's `tidying`, since a person decides it. */
|
|
232
238
|
suggesting = false;
|
|
239
|
+
/** True of a rehearsal for a proposal (Roadmap f-proposals-for-review): an act its author may propose is let through, as it will be for whoever accepts it. */
|
|
240
|
+
proposing = false;
|
|
233
241
|
/**
|
|
234
242
|
* The day a host last ticked this store to (FR-176), and the day the clock
|
|
235
243
|
* read when it did: what its rules are judged on, where nothing pins one,
|
|
@@ -257,6 +265,7 @@ export class Store {
|
|
|
257
265
|
this.policy = options.policy;
|
|
258
266
|
this.publishing = options.publishing;
|
|
259
267
|
this.tidying = options.tidying;
|
|
268
|
+
this.votes = options.votes;
|
|
260
269
|
this.by = options.principal ?? HUMAN;
|
|
261
270
|
this.intelligence = options.intelligence ?? [];
|
|
262
271
|
for (const provider of options.intelligence ?? []) {
|
|
@@ -299,6 +308,11 @@ export class Store {
|
|
|
299
308
|
this.voter = voteSuggestionMutation();
|
|
300
309
|
this.mutations.set(VOTE_SUGGESTION, this.voter);
|
|
301
310
|
}
|
|
311
|
+
// "Propose changes" (Roadmap f-proposals-for-review): answered by every store, offered by no list.
|
|
312
|
+
if (!options.past && !this.mutations.has(PROPOSE_CHANGES)) {
|
|
313
|
+
this.proposer = proposeChangesMutation();
|
|
314
|
+
this.mutations.set(PROPOSE_CHANGES, this.proposer);
|
|
315
|
+
}
|
|
302
316
|
const horizon = given("horizon", options.horizon);
|
|
303
317
|
const validate = { validate: this.validate };
|
|
304
318
|
if (options.log) {
|
|
@@ -507,7 +521,7 @@ export class Store {
|
|
|
507
521
|
return mutation.derived !== undefined && this.modules.disabledKinds.has(mutation.derived.kind);
|
|
508
522
|
}
|
|
509
523
|
allMutations() {
|
|
510
|
-
return [...this.mutations.values(), ...(this.publisher ? [this.publisher] : [])].filter((mutation) => mutation !== this.keeper && mutation !== this.typer && mutation !== this.voter && !this.mutationDisabled(mutation));
|
|
524
|
+
return [...this.mutations.values(), ...(this.publisher ? [this.publisher] : [])].filter((mutation) => mutation !== this.keeper && mutation !== this.typer && mutation !== this.voter && mutation !== this.proposer && !this.mutationDisabled(mutation));
|
|
511
525
|
}
|
|
512
526
|
/** The declared acts a derived act resolves its permission through; keeping a link, those that make or break its relation. */
|
|
513
527
|
viaOf(mutation, call, principal) {
|
|
@@ -560,6 +574,23 @@ export class Store {
|
|
|
560
574
|
* action withheld by permission is stated rather than hidden, and stating
|
|
561
575
|
* it needs the same answer the enforcement uses. One source, two readings.
|
|
562
576
|
*/
|
|
577
|
+
/**
|
|
578
|
+
* Whether a change to a derived record may go back to its source
|
|
579
|
+
* (Roadmap f-keep-linked): when the store judges a policy, only when its
|
|
580
|
+
* author may make the source's own edit with that value.
|
|
581
|
+
*/
|
|
582
|
+
writesBack(principal) {
|
|
583
|
+
if (!this.policy)
|
|
584
|
+
return undefined;
|
|
585
|
+
return (source, field, value) => {
|
|
586
|
+
try {
|
|
587
|
+
return this.permits({ name: `edit-${source.kind}`, args: { id: source.id, [field]: value } }, principal).ok;
|
|
588
|
+
}
|
|
589
|
+
catch {
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
}
|
|
563
594
|
permits(call, principal = HUMAN) {
|
|
564
595
|
call = this.spelledCall(call);
|
|
565
596
|
/*
|
|
@@ -578,9 +609,20 @@ export class Store {
|
|
|
578
609
|
// Publishing is the declaration's `publishers`, not a grant's.
|
|
579
610
|
if (mutation && mutation === this.publisher)
|
|
580
611
|
return PUBLISHING.verdict(this, principal);
|
|
581
|
-
|
|
582
|
-
|
|
612
|
+
/*
|
|
613
|
+
* A vote on a suggestion is anybody's who may see it (Roadmap f-suggestion-votes): whether they do is judged where the op is made.
|
|
614
|
+
* But not a seat that is nobody in particular (Roadmap f-votes-shared-seat): every signed-out stranger served as one `anonymous`
|
|
615
|
+
* cast one shared vote that any of them could flip. Refused, unless the host keeps such votes as advisory and said whose this is.
|
|
616
|
+
*/
|
|
617
|
+
if (mutation && mutation === this.voter) {
|
|
618
|
+
if (signedOutSeat(principal) && (this.votes?.advisory !== "visitors" || advisoryVoterOf(principal) === undefined)) {
|
|
619
|
+
return { ok: false, refusal: { mutation: call.name, wouldNeed: [], message: SIGN_IN_TO_VOTE } };
|
|
620
|
+
}
|
|
583
621
|
return { ok: true };
|
|
622
|
+
}
|
|
623
|
+
// A proposal is its author's to make where each call it holds is one they may run or may propose (Roadmap f-proposals-for-review).
|
|
624
|
+
if (mutation && mutation === this.proposer)
|
|
625
|
+
return this.permitsProposal(call, principal);
|
|
584
626
|
/*
|
|
585
627
|
* KEEPING A LINK ONLY THE DERIVED ACTS MAKE is judged as they are: on
|
|
586
628
|
* the record it leaves, so riding everybody's grant it reaches only the
|
|
@@ -635,6 +677,82 @@ export class Store {
|
|
|
635
677
|
*/
|
|
636
678
|
return permits(this.policy, principal, call.name, kind, removeVia([...this.mutations.values()], mutation.derived.kind), typeof id === "string" ? id : undefined, this.words);
|
|
637
679
|
}
|
|
680
|
+
/**
|
|
681
|
+
* WHETHER THIS PRINCIPAL MAY PROPOSE THIS CALL AND MAY NOT RUN IT (Roadmap
|
|
682
|
+
* f-proposals-for-review): the policy refuses them the act and a grant's
|
|
683
|
+
* `propose` names it, on the kind the call is on. What turns an act's
|
|
684
|
+
* form's button into "Propose", and what a proposal's rehearsal lets
|
|
685
|
+
* through.
|
|
686
|
+
*/
|
|
687
|
+
mayPropose(call, principal = HUMAN) {
|
|
688
|
+
if (!this.policy || this.past || signedOutSeat(principal))
|
|
689
|
+
return false;
|
|
690
|
+
call = this.spelledCall(call);
|
|
691
|
+
const mutation = this.mutations.get(call.name);
|
|
692
|
+
if (!mutation || mutation === this.proposer || mutation === this.voter || this.refusesAgent(call, principal) || this.namesTurnedOff(call, principal))
|
|
693
|
+
return false;
|
|
694
|
+
return !this.permits(call, principal).ok && proposes(this.policy, principal, call.name, this.subjectKindOf(call, principal));
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* A PROPOSAL'S OP (Roadmap f-proposals-for-review): the calls a "Propose
|
|
698
|
+
* changes" call holds, rehearsed as its author with the grant to propose
|
|
699
|
+
* standing in for the grant to run, kept as `suggest` keeps a suggestion
|
|
700
|
+
* — no primitives, each call's sentence, the records they name — with
|
|
701
|
+
* the author as its maker and a lineage naming them (`proposedBy`), its
|
|
702
|
+
* basis the proposal in their own words, else "Proposed by Ada"; or
|
|
703
|
+
* undefined when the calls would change nothing. Made here, so a store
|
|
704
|
+
* answers a proposal over the wire whatever else it loaded.
|
|
705
|
+
*/
|
|
706
|
+
proposal(call, batch, author, via) {
|
|
707
|
+
const { calls, intent } = call.args;
|
|
708
|
+
if (calls.length === 0 || calls.length > MOST_PROPOSED || calls.some((one) => !one.args || typeof one.args !== "object" || Array.isArray(one.args)))
|
|
709
|
+
throw new GraphError(`A proposal holds 1 to ${MOST_PROPOSED} changes, each an act's name and its arguments.`);
|
|
710
|
+
const by = actingAs(author).id ?? author.session;
|
|
711
|
+
if (by === undefined)
|
|
712
|
+
throw new GraphError("A proposal is somebody's: sign in to propose a change.");
|
|
713
|
+
const lineage = lineageOf({ basis: (intent ?? `Proposed by ${author.name ?? by}`).slice(0, 500), proposedBy: by.slice(0, 120) });
|
|
714
|
+
const rehearsal = this.rehearsal();
|
|
715
|
+
rehearsal.proposing = true;
|
|
716
|
+
const planned = rehearsal.applying(calls, { author, lineage, ...given("via", via) });
|
|
717
|
+
if (planned.ops.length === 0)
|
|
718
|
+
return undefined;
|
|
719
|
+
const described = [...new Set(planned.ops.flatMap((op) => op.described ?? []))];
|
|
720
|
+
const own = planned.ops.filter((one) => one.mutation !== null && one.author === author);
|
|
721
|
+
return {
|
|
722
|
+
id: this.nextId(),
|
|
723
|
+
seq: this.log.length,
|
|
724
|
+
batch,
|
|
725
|
+
author,
|
|
726
|
+
intent: planned.ops.map((one) => one.intent).join("; "),
|
|
727
|
+
...given("batchIntent", intent),
|
|
728
|
+
mutation: null,
|
|
729
|
+
primitives: [],
|
|
730
|
+
reads: [],
|
|
731
|
+
writes: [],
|
|
732
|
+
...(described.length > 0 ? { described } : {}),
|
|
733
|
+
at: this.now(),
|
|
734
|
+
...given("via", via),
|
|
735
|
+
lineage,
|
|
736
|
+
suggests: calls,
|
|
737
|
+
...given("suggestsSaid", calls.length > 1 && own.length === calls.length ? own.map((one) => one.intent) : undefined),
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
/** A "Propose changes" call, judged: every call it holds one this principal may run or may propose, from a seat that is somebody. */
|
|
741
|
+
permitsProposal(call, principal) {
|
|
742
|
+
const no = (message) => ({ ok: false, refusal: { mutation: call.name, wouldNeed: [], message } });
|
|
743
|
+
if (signedOutSeat(principal))
|
|
744
|
+
return no("Sign in to propose a change.");
|
|
745
|
+
const calls = Array.isArray(call.args["calls"]) ? call.args["calls"] : [];
|
|
746
|
+
for (const one of calls) {
|
|
747
|
+
if (typeof one?.name !== "string")
|
|
748
|
+
continue;
|
|
749
|
+
const verdict = this.permits(one, principal);
|
|
750
|
+
if (verdict.ok || this.mayPropose(one, principal))
|
|
751
|
+
continue;
|
|
752
|
+
return no(`Not permitted to propose this: ${verdict.refusal.message.replace(/^Not permitted: /, "")}`);
|
|
753
|
+
}
|
|
754
|
+
return { ok: true };
|
|
755
|
+
}
|
|
638
756
|
/**
|
|
639
757
|
* The first record linked to the subject that this principal may not
|
|
640
758
|
* change, as a refusal of the act naming it (Roadmap f-acts-update-linked);
|
|
@@ -1123,7 +1241,15 @@ export class Store {
|
|
|
1123
1241
|
call = this.spelledCall(call);
|
|
1124
1242
|
const definition = this.mutation(call.name);
|
|
1125
1243
|
const compiled = compileMutation(this.graph, definition, call.args, this.sighted(options.author));
|
|
1126
|
-
|
|
1244
|
+
const made = this.asSplices(compiled.primitives);
|
|
1245
|
+
// And what would follow it (Roadmap f-keep-linked), worked out on a copy.
|
|
1246
|
+
let following = [];
|
|
1247
|
+
if (keepsLinked(this.schema)) {
|
|
1248
|
+
const trial = Graph.from(this.schema, this.graph.snapshot());
|
|
1249
|
+
trial.applyPrimitives(made);
|
|
1250
|
+
following = keepLinked(this.schema, trial, made, { mayWriteBack: this.writesBack(options.author ?? this.by) });
|
|
1251
|
+
}
|
|
1252
|
+
return this.previewPrimitives([...made, ...following], {
|
|
1127
1253
|
reads: compiled.reads,
|
|
1128
1254
|
writes: compiled.writes,
|
|
1129
1255
|
intent: compiled.intent,
|
|
@@ -1261,8 +1387,11 @@ export class Store {
|
|
|
1261
1387
|
* was brought in for, and the narrower of the two wins.
|
|
1262
1388
|
*/
|
|
1263
1389
|
const permitted = (call, as = author) => {
|
|
1264
|
-
|
|
1265
|
-
|
|
1390
|
+
// A vote is judged with no policy too: a shared seat's vote is refused whether or not the app says who may do what (Roadmap f-votes-shared-seat).
|
|
1391
|
+
const voting = this.voter !== undefined && this.mutations.get(call.name) === this.voter;
|
|
1392
|
+
const verdict = this.policy || (this.publisher && call.name === PUBLISH) || voting || this.mutations.get(call.name) === this.proposer ? this.permits(call, as) : undefined;
|
|
1393
|
+
// Rehearsing a proposal, an act its author may propose stands as the reviewer's would (Roadmap f-proposals-for-review).
|
|
1394
|
+
if (verdict && !verdict.ok && !(this.proposing && this.mayPropose(call, as)))
|
|
1266
1395
|
this.refuse(verdict.refusal, as.id);
|
|
1267
1396
|
};
|
|
1268
1397
|
const declared = (call, as = author) => {
|
|
@@ -1337,6 +1466,16 @@ export class Store {
|
|
|
1337
1466
|
queue.push({ sent: made, as: accept.author, lineage: lineageOf(accept.lineage), decided: true });
|
|
1338
1467
|
continue;
|
|
1339
1468
|
}
|
|
1469
|
+
if (definition === this.proposer) {
|
|
1470
|
+
// A proposal (Roadmap f-proposals-for-review): a suggestion with its author as its maker, and nothing of the graph until it is accepted.
|
|
1471
|
+
const op = this.proposal(call, batch, as, options.via);
|
|
1472
|
+
if (!op)
|
|
1473
|
+
continue;
|
|
1474
|
+
this.log.append(op);
|
|
1475
|
+
ops.push(op);
|
|
1476
|
+
intents.push(op.intent);
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1340
1479
|
const missing = this.missingFor(call, as);
|
|
1341
1480
|
if (missing)
|
|
1342
1481
|
throw missing;
|
|
@@ -1371,6 +1510,15 @@ export class Store {
|
|
|
1371
1510
|
if (compiled.primitives.length === 0)
|
|
1372
1511
|
continue;
|
|
1373
1512
|
minted[at] = compiled.firstMinted;
|
|
1513
|
+
/*
|
|
1514
|
+
* WHAT FOLLOWS IT (Roadmap f-keep-linked): the records that derive
|
|
1515
|
+
* from what this changed take their values from it, and a change
|
|
1516
|
+
* to one of those goes back to its source — in this op, so one undo
|
|
1517
|
+
* takes both back. Applied to the graph as they are worked out.
|
|
1518
|
+
*/
|
|
1519
|
+
const made = this.asSplices(compiled.primitives, options.base).map(normalize);
|
|
1520
|
+
this.graph.applyPrimitives(made);
|
|
1521
|
+
const following = keepsLinked(this.schema) ? keepLinked(this.schema, this.graph, made, { mayWriteBack: this.writesBack(as) }).map(normalize) : [];
|
|
1374
1522
|
madeIds[at] = compiled.primitives.find((primitive) => primitive.op === "add-node")?.node.id;
|
|
1375
1523
|
const op = {
|
|
1376
1524
|
id: this.nextId(),
|
|
@@ -1392,9 +1540,9 @@ export class Store {
|
|
|
1392
1540
|
* instruction is lost the moment the op is written to JSON and the
|
|
1393
1541
|
* inverse quietly does nothing. See `normalize` in primitives.ts.
|
|
1394
1542
|
*/
|
|
1395
|
-
primitives:
|
|
1543
|
+
primitives: [...made, ...following],
|
|
1396
1544
|
reads: compiled.reads,
|
|
1397
|
-
writes: compiled.writes,
|
|
1545
|
+
writes: following.length > 0 ? [...new Set([...compiled.writes, ...following.flatMap(writesOf)])] : compiled.writes,
|
|
1398
1546
|
// Which records its sentence read, so a reader who may not see one is not handed the sentence (FR-55).
|
|
1399
1547
|
...(definition.describe !== undefined && compiled.described && compiled.described.length > 0 ? { described: compiled.described } : {}),
|
|
1400
1548
|
...given("mergedInto", compiled.mergedInto),
|
|
@@ -1402,7 +1550,6 @@ export class Store {
|
|
|
1402
1550
|
...given("via", options.via),
|
|
1403
1551
|
...given("lineage", lined),
|
|
1404
1552
|
};
|
|
1405
|
-
this.graph.applyPrimitives(op.primitives);
|
|
1406
1553
|
this.log.append(op);
|
|
1407
1554
|
ops.push(op);
|
|
1408
1555
|
allPrimitives.push(...op.primitives);
|
|
@@ -1549,6 +1696,8 @@ export class Store {
|
|
|
1549
1696
|
...given("undoes", made.undoes),
|
|
1550
1697
|
...given("via", made.via),
|
|
1551
1698
|
...given("lineage", lineageOf(made.lineage)),
|
|
1699
|
+
...given("described", made.described),
|
|
1700
|
+
...given("sentOut", made.sentOut),
|
|
1552
1701
|
};
|
|
1553
1702
|
if (taken.has(op.id))
|
|
1554
1703
|
throw new GraphError(`Op "${op.id}" (${op.intent}) is already in the log`, "A host-made op needs an id of its own; leave `id` out and the store mints one.");
|
|
@@ -1592,7 +1741,18 @@ export class Store {
|
|
|
1592
1741
|
const rollback = this.graph.snapshot();
|
|
1593
1742
|
const intent = options.intent ?? "Apply a change";
|
|
1594
1743
|
const lineage = lineageOf(options.lineage);
|
|
1595
|
-
const
|
|
1744
|
+
const handed = this.asSplices(primitives, options.base).map(normalize);
|
|
1745
|
+
// What follows it (Roadmap f-keep-linked), worked out on the graph as it lands: the host's change keeps derived records in step too.
|
|
1746
|
+
this.graph.applyPrimitives(handed);
|
|
1747
|
+
let recorded = handed;
|
|
1748
|
+
try {
|
|
1749
|
+
if (keepsLinked(this.schema))
|
|
1750
|
+
recorded = [...handed, ...keepLinked(this.schema, this.graph, handed, { mayWriteBack: this.writesBack(author) }).map(normalize)];
|
|
1751
|
+
}
|
|
1752
|
+
catch (error) {
|
|
1753
|
+
this.putBack(rollback, this.log.length);
|
|
1754
|
+
throw error;
|
|
1755
|
+
}
|
|
1596
1756
|
const ops = [];
|
|
1597
1757
|
if (recorded.length > 0) {
|
|
1598
1758
|
const op = {
|
|
@@ -1609,7 +1769,6 @@ export class Store {
|
|
|
1609
1769
|
...given("via", options.via),
|
|
1610
1770
|
...given("lineage", lineage),
|
|
1611
1771
|
};
|
|
1612
|
-
this.graph.applyPrimitives(op.primitives);
|
|
1613
1772
|
this.log.append(op);
|
|
1614
1773
|
ops.push(op);
|
|
1615
1774
|
tellTheWatchOfAnAuthor(author.id);
|
|
@@ -1789,6 +1948,10 @@ export class Store {
|
|
|
1789
1948
|
const by = actingAs(judged.author).id;
|
|
1790
1949
|
// A vote is its voter's to take back (Roadmap f-suggestion-votes), the system's, or a seat's the policy grants every act.
|
|
1791
1950
|
if (judged.vote !== undefined) {
|
|
1951
|
+
// An advisory vote is its visitor's, not the shared seat's (Roadmap f-votes-shared-seat): another stranger on the same seat may not take it back.
|
|
1952
|
+
if (judged.vote.advisory && !isSystem(author) && advisoryVoterOf(author) !== judged.vote.voter && !(this.policy && this.grantsEveryAct(author))) {
|
|
1953
|
+
return { mutation: "undo", wouldNeed: [], message: `Not permitted to undo "${target.intent}": only whoever voted takes their vote back.` };
|
|
1954
|
+
}
|
|
1792
1955
|
if (this.policy && !isSystem(author) && by !== actingAs(author).id && !this.grantsEveryAct(author)) {
|
|
1793
1956
|
return { mutation: "undo", wouldNeed: [], message: `Not permitted to undo "${target.intent}": only whoever voted takes their vote back.` };
|
|
1794
1957
|
}
|