@astrosheep/square 0.3.106 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/activity-feed.js +1 -1
- package/dist/artifact-store.d.ts +41 -0
- package/dist/artifact-store.js +272 -0
- package/dist/artifact.d.ts +6 -12
- package/dist/artifact.js +43 -344
- package/dist/attention-presentation.d.ts +13 -7
- package/dist/attention-presentation.js +29 -68
- package/dist/boundary-presentation.d.ts +3 -16
- package/dist/boundary-presentation.js +29 -109
- package/dist/card-presentation.d.ts +1 -0
- package/dist/card-presentation.js +2 -0
- package/dist/catch-decisions.d.ts +2 -2
- package/dist/catch-decisions.js +7 -3
- package/dist/catch-selection.d.ts +8 -0
- package/dist/catch-selection.js +5 -0
- package/dist/claude-delivery.d.ts +14 -12
- package/dist/claude-delivery.js +42 -142
- package/dist/claude-mcp-context.js +2 -2
- package/dist/claude-mod.js +28 -140
- package/dist/claude-transport.d.ts +5 -0
- package/dist/claude-transport.js +34 -0
- package/dist/cli/context.d.ts +2 -2
- package/dist/cli/context.js +7 -10
- package/dist/cli/maintenance-commands.d.ts +0 -4
- package/dist/cli/maintenance-commands.js +2 -29
- package/dist/cli/observation-commands.d.ts +2 -0
- package/dist/cli/observation-commands.js +12 -2
- package/dist/cli/program.js +1 -1
- package/dist/cli/registry.js +4 -3
- package/dist/codex-address.d.ts +2 -2
- package/dist/codex-boundary-state.d.ts +1 -5
- package/dist/codex-boundary-state.js +0 -4
- package/dist/codex-hook.d.ts +7 -10
- package/dist/codex-hook.js +69 -33
- package/dist/codex-queue.d.ts +10 -11
- package/dist/codex-queue.js +32 -34
- package/dist/codex-watch.d.ts +2 -0
- package/dist/codex-watch.js +100 -0
- package/dist/decisions.js +3 -3
- package/dist/delivery-deferral.d.ts +1 -19
- package/dist/delivery-deferral.js +1 -29
- package/dist/delivery-frame.d.ts +7 -0
- package/dist/delivery-frame.js +11 -0
- package/dist/delivery-ledger-sqlite.d.ts +97 -0
- package/dist/delivery-ledger-sqlite.js +496 -0
- package/dist/delivery-ledger.d.ts +196 -0
- package/dist/delivery-ledger.js +268 -0
- package/dist/delivery-lifetime.d.ts +6 -0
- package/dist/delivery-lifetime.js +45 -0
- package/dist/harness-links.js +61 -7
- package/dist/harness.js +12 -17
- package/dist/help.js +3 -6
- package/dist/http-delivery.d.ts +5 -9
- package/dist/http-delivery.js +20 -79
- package/dist/inbox.d.ts +6 -57
- package/dist/inbox.js +24 -380
- package/dist/index.d.ts +7 -4
- package/dist/index.js +5 -2
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +40 -70
- package/dist/message.d.ts +7 -0
- package/dist/message.js +23 -0
- package/dist/model.d.ts +15 -91
- package/dist/model.js +2 -140
- package/dist/neutral.d.ts +72 -0
- package/dist/neutral.js +27 -0
- package/dist/notifications.d.ts +24 -26
- package/dist/notifications.js +39 -143
- package/dist/operation-control.d.ts +4 -0
- package/dist/operation-control.js +20 -0
- package/dist/operation-presentation.d.ts +1 -2
- package/dist/operation-presentation.js +1 -7
- package/dist/owner.d.ts +2 -2
- package/dist/owner.js +1 -1
- package/dist/packages/agent-delivery/src/claude-native.d.ts +2 -0
- package/dist/packages/agent-delivery/src/claude-native.js +5 -0
- package/dist/packages/agent-delivery/src/codex-boundary.d.ts +11 -6
- package/dist/packages/agent-delivery/src/codex-boundary.js +31 -40
- package/dist/packages/agent-delivery/src/codex-hook.d.ts +17 -12
- package/dist/packages/agent-delivery/src/codex-hook.js +26 -39
- package/dist/packages/agent-delivery/src/codex.d.ts +3 -0
- package/dist/packages/agent-delivery/src/codex.js +41 -4
- package/dist/packages/agent-delivery/src/index.d.ts +3 -1
- package/dist/packages/agent-delivery/src/index.js +1 -1
- package/dist/packages/agent-delivery/src/paseo.js +11 -2
- package/dist/packages/agent-delivery/src/types.d.ts +1 -0
- package/dist/paseo-delivery.d.ts +5 -5
- package/dist/paseo-delivery.js +19 -99
- package/dist/paseo.d.ts +1 -1
- package/dist/paseo.js +1 -1
- package/dist/plugins/opencode/index.d.ts +5 -3
- package/dist/plugins/opencode/index.js +99 -21
- package/dist/plugins/opencode-shared/delivery.d.ts +23 -0
- package/dist/plugins/opencode-shared/delivery.js +109 -0
- package/dist/plugins/opencode-v1/index.d.ts +28 -0
- package/dist/plugins/opencode-v1/index.js +41 -0
- package/dist/plugins/opencode-v1/runtime.d.ts +56 -0
- package/dist/plugins/opencode-v1/runtime.js +152 -0
- package/dist/plugins/opencode-v1/transport.d.ts +13 -0
- package/dist/plugins/opencode-v1/transport.js +50 -0
- package/dist/plugins/paseo/shared/card-presentation.d.ts +10 -0
- package/dist/plugins/paseo/shared/card-presentation.js +7 -0
- package/dist/ports.d.ts +33 -214
- package/dist/presentation.d.ts +5 -5
- package/dist/presentation.js +1 -0
- package/dist/runtime.js +2 -2
- package/dist/search.js +1 -1
- package/dist/session-lifecycle.d.ts +8 -7
- package/dist/session-lifecycle.js +40 -42
- package/dist/sqlite-framing.d.ts +8 -0
- package/dist/sqlite-framing.js +31 -0
- package/dist/sqlite-square.d.ts +16 -26
- package/dist/sqlite-square.js +199 -262
- package/dist/sqlite-values.d.ts +21 -0
- package/dist/sqlite-values.js +78 -0
- package/dist/square-api.d.ts +1 -1
- package/dist/square-api.js +5 -8
- package/dist/square-core.d.ts +0 -1
- package/dist/square-domain.d.ts +12 -10
- package/dist/square-domain.js +105 -223
- package/dist/square-facade.d.ts +25 -76
- package/dist/square-location.d.ts +6 -1
- package/dist/square-location.js +1 -1
- package/dist/square-post.d.ts +53 -0
- package/dist/square-post.js +4 -0
- package/dist/square-posting.d.ts +13 -0
- package/dist/square-posting.js +174 -0
- package/dist/square-producer-sqlite.d.ts +11 -0
- package/dist/square-producer-sqlite.js +210 -0
- package/dist/square-receive.d.ts +2 -3
- package/dist/square-sqlite.d.ts +33 -42
- package/dist/square-sqlite.js +236 -768
- package/dist/square-tools.d.ts +8 -0
- package/dist/square-tools.js +39 -0
- package/dist/square-values.d.ts +27 -0
- package/dist/square-values.js +90 -0
- package/dist/views.d.ts +6 -6
- package/dist/views.js +14 -9
- package/dist/wake-sink.d.ts +4 -11
- package/dist/wake-sink.js +8 -32
- package/dist/wake-transports.d.ts +4 -0
- package/dist/wake-transports.js +11 -0
- package/examples/symmetric-domains.mjs +29 -249
- package/guides/change-waits.md +13 -53
- package/guides/claude-native.md +19 -172
- package/guides/codex-delivery.md +55 -78
- package/guides/delivery-primitives.md +48 -207
- package/guides/operation-cancellation.md +2 -5
- package/guides/participant-ownership.md +25 -89
- package/guides/pi-native-delivery.md +19 -56
- package/guides/pi-tools.md +6 -8
- package/guides/row-runtime-delivery-evidence.md +2 -0
- package/guides/row-storage-design.md +19 -44
- package/guides/square-api.md +113 -538
- package/package.json +8 -8
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/hooks/hooks.json +1 -1
- package/plugins/claude/{hooks/register.js → mods/square.js} +4 -7
- package/plugins/claude/types.d.ts +1 -1
- package/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/hooks/hooks.json +11 -23
- package/plugins/opencode/index.ts +91 -23
- package/plugins/opencode-shared/delivery.ts +91 -0
- package/plugins/opencode-v1/index.ts +36 -0
- package/plugins/opencode-v1/runtime.ts +134 -0
- package/plugins/opencode-v1/transport.ts +41 -0
- package/plugins/paseo/OVERVIEW.md +5 -5
- package/plugins/paseo/README.md +7 -6
- package/plugins/paseo/client/markdown.tsx +5 -5
- package/plugins/paseo/client/square-message.tsx +28 -24
- package/plugins/paseo/client/transform.ts +8 -5
- package/plugins/paseo/shared/card-presentation.ts +16 -0
- package/plugins/paseo/shared/message.ts +6 -11
- package/plugins/pi/square-pi.js +167 -451
- package/dist/channel.d.ts +0 -74
- package/dist/channel.js +0 -92
- package/dist/claude-delivery-status.d.ts +0 -13
- package/dist/claude-delivery-status.js +0 -46
- package/dist/cmd/notify-once.d.ts +0 -2
- package/dist/cmd/notify-once.js +0 -29
- package/dist/delivery-attempts.d.ts +0 -52
- package/dist/delivery-attempts.js +0 -73
- package/dist/delivery-effects.d.ts +0 -139
- package/dist/delivery-effects.js +0 -163
- package/dist/delivery-health.d.ts +0 -51
- package/dist/delivery-health.js +0 -173
- package/dist/delivery-operations.d.ts +0 -9
- package/dist/delivery-operations.js +0 -168
- package/dist/delivery-primitives.d.ts +0 -5
- package/dist/delivery-primitives.js +0 -3
- package/dist/delivery.d.ts +0 -45
- package/dist/delivery.js +0 -106
- package/dist/plugins/opencode/delivery.d.ts +0 -19
- package/dist/plugins/opencode/delivery.js +0 -238
- package/dist/presentation-operations.d.ts +0 -18
- package/dist/presentation-operations.js +0 -86
- package/dist/square-index.d.ts +0 -16
- package/dist/square-index.js +0 -106
- package/dist/square-legacy-framing.d.ts +0 -11
- package/dist/square-legacy-framing.js +0 -64
- package/dist/square-migration-host-ledger.d.ts +0 -26
- package/dist/square-migration-host-ledger.js +0 -169
- package/dist/square-migration.d.ts +0 -30
- package/dist/square-migration.js +0 -599
- package/guides/migration.md +0 -156
- package/plugins/opencode/delivery.ts +0 -211
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SquareError, type FactPage, type IndexPage } from './neutral.js';
|
|
2
|
+
export type Row = Record<string, string | number | null>;
|
|
3
|
+
export declare const encode: {
|
|
4
|
+
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
5
|
+
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
|
|
6
|
+
};
|
|
7
|
+
export declare const key: (name: string) => string;
|
|
8
|
+
export declare function invalidArtifact(detail: string): SquareError;
|
|
9
|
+
export declare function requireFact(ok: unknown, detail?: string): asserts ok;
|
|
10
|
+
export declare function integer(value: unknown, minimum?: number): number;
|
|
11
|
+
export declare function finite(value: unknown): number;
|
|
12
|
+
export declare function string(value: unknown, nonempty?: boolean): string;
|
|
13
|
+
export declare function json(value: unknown): unknown;
|
|
14
|
+
export declare function object(value: unknown): Record<string, unknown>;
|
|
15
|
+
export declare function shape(value: unknown, required: readonly string[], optional?: readonly string[]): Record<string, unknown>;
|
|
16
|
+
export declare function strings(value: unknown): string[];
|
|
17
|
+
export declare function decoded(value: unknown, nonempty?: boolean): string;
|
|
18
|
+
export declare function immutable<T>(value: T): T;
|
|
19
|
+
export declare function stableJson(value: unknown): string;
|
|
20
|
+
export declare function pageRows<T>(rows: Row[], page: IndexPage, decode: (row: Row) => T): FactPage<T>;
|
|
21
|
+
export declare function pageLimit(page: IndexPage): number;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { SquareError, nameKey } from './neutral.js';
|
|
2
|
+
export const encode = JSON.stringify;
|
|
3
|
+
export const key = (name) => encode(nameKey(name));
|
|
4
|
+
export function invalidArtifact(detail) {
|
|
5
|
+
return new SquareError('invalid_args', `Invalid square artifact: ${detail}`);
|
|
6
|
+
}
|
|
7
|
+
export function requireFact(ok, detail = 'row is malformed.') {
|
|
8
|
+
if (!ok)
|
|
9
|
+
throw invalidArtifact(detail);
|
|
10
|
+
}
|
|
11
|
+
export function integer(value, minimum = 0) {
|
|
12
|
+
requireFact(Number.isSafeInteger(value) && value >= minimum);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
export function finite(value) {
|
|
16
|
+
requireFact(typeof value === 'number' && Number.isFinite(value));
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
export function string(value, nonempty = false) {
|
|
20
|
+
requireFact(typeof value === 'string' && (!nonempty || value.length > 0));
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
export function json(value) {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(string(value));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw invalidArtifact('row contains invalid JSON.');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function object(value) {
|
|
32
|
+
requireFact(typeof value === 'object' && value !== null && !Array.isArray(value));
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
export function shape(value, required, optional = []) {
|
|
36
|
+
const result = object(value);
|
|
37
|
+
requireFact(required.every(k => Object.hasOwn(result, k)) && Object.keys(result).every(k => required.includes(k) || optional.includes(k)));
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
export function strings(value) {
|
|
41
|
+
requireFact(Array.isArray(value) && value.every(v => typeof v === 'string'));
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
export function decoded(value, nonempty = false) {
|
|
45
|
+
const result = string(json(value), nonempty);
|
|
46
|
+
requireFact(encode(result) === value, 'string encoding is malformed.');
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
export function immutable(value) {
|
|
50
|
+
if (value !== null && typeof value === 'object') {
|
|
51
|
+
for (const item of Object.values(value))
|
|
52
|
+
immutable(item);
|
|
53
|
+
Object.freeze(value);
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
// Sorted object keys express small-value structural equality, never whole-state comparison.
|
|
58
|
+
export function stableJson(value) {
|
|
59
|
+
if (value === null || typeof value !== 'object') {
|
|
60
|
+
requireFact(value === null || typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' && Number.isFinite(value), 'value contains a non-finite or unsupported JSON value.');
|
|
61
|
+
return encode(value);
|
|
62
|
+
}
|
|
63
|
+
if (Array.isArray(value))
|
|
64
|
+
return '[' + value.map(stableJson).join(',') + ']';
|
|
65
|
+
return '{' + Object.keys(value).sort().map(k => encode(k) + ':' + stableJson(value[k])).join(',') + '}';
|
|
66
|
+
}
|
|
67
|
+
export function pageRows(rows, page, decode) {
|
|
68
|
+
const hasMore = rows.length > page.limit;
|
|
69
|
+
if (hasMore)
|
|
70
|
+
rows.pop();
|
|
71
|
+
if (page.edge === 'newest')
|
|
72
|
+
rows.reverse();
|
|
73
|
+
return immutable({ items: rows.map(decode), hasMore });
|
|
74
|
+
}
|
|
75
|
+
export function pageLimit(page) {
|
|
76
|
+
requireFact(page.edge === 'oldest' || page.edge === 'newest');
|
|
77
|
+
return Math.min(integer(page.limit, 1) + 1, Number.MAX_SAFE_INTEGER);
|
|
78
|
+
}
|
package/dist/square-api.d.ts
CHANGED
|
@@ -16,4 +16,4 @@ export declare function selectOwnSeat(square: Pick<SqliteSquare, 'participant' |
|
|
|
16
16
|
}): Promise<Participant | undefined>;
|
|
17
17
|
export { ACTIVITY_METADATA_MAX_BYTES } from './model.js';
|
|
18
18
|
export { localUserOwner, harnessOwner, decodeHarnessOwner } from './owner.js';
|
|
19
|
-
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare,
|
|
19
|
+
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
|
package/dist/square-api.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { SqliteSquare } from './sqlite-square.js';
|
|
2
2
|
import { SquareError } from './model.js';
|
|
3
3
|
import { requireOwner } from './seats.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
build: async (input, control) => SqliteSquare.build({ ...input, wakeTransport: await resolveWakeTransport(input) }, control), inMemory: SqliteSquare.inMemory };
|
|
7
|
-
const resolveWakeTransport = (input) => input.wakeTransport !== undefined
|
|
8
|
-
? Promise.resolve(input.wakeTransport)
|
|
9
|
-
: createDefaultWakeTransport(input.env ?? process.env).catch(() => undefined);
|
|
4
|
+
export const Square = { at: (input, control) => SqliteSquare.at(input, control),
|
|
5
|
+
build: (input, control) => SqliteSquare.build(input, control), inMemory: SqliteSquare.inMemory };
|
|
10
6
|
export { requireOwner, requireJoinName } from './seats.js';
|
|
11
7
|
export { squareLocation } from './square-location.js';
|
|
12
8
|
export async function selectOwnSeat(square, owner, name, options) {
|
|
@@ -15,7 +11,8 @@ export async function selectOwnSeat(square, owner, name, options) {
|
|
|
15
11
|
const caller = requireOwner(owner);
|
|
16
12
|
if (name !== undefined)
|
|
17
13
|
return square.participant(name, { owner: caller });
|
|
18
|
-
|
|
14
|
+
// Selection is local producer custody, not a ledger attachment check.
|
|
15
|
+
const seats = await square.seatsOf(caller);
|
|
19
16
|
if (seats.length !== 1) {
|
|
20
17
|
if (options?.optional)
|
|
21
18
|
return undefined;
|
|
@@ -27,4 +24,4 @@ export async function selectOwnSeat(square, owner, name, options) {
|
|
|
27
24
|
}
|
|
28
25
|
export { ACTIVITY_METADATA_MAX_BYTES } from './model.js';
|
|
29
26
|
export { localUserOwner, harnessOwner, decodeHarnessOwner } from './owner.js';
|
|
30
|
-
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare,
|
|
27
|
+
export { squareClock, createSquareResourceOwner, formatActivityId, parseActivityId, MAX_IDENTITY_SET_SIZE, CATCH_DEFAULT_LIMIT, CATCH_MAX_LIMIT, HISTORY_DEFAULT_LIMIT, HISTORY_MAX_LIMIT, DEFAULT_LIST_DEPTH, MAX_LIST_DEPTH, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, diagnoseSquare, discover, inbox } from './sqlite-square.js';
|
package/dist/square-core.d.ts
CHANGED
package/dist/square-domain.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ActDraft, type Seat } from './model.js';
|
|
2
2
|
import type { ArtifactWriteAuthority, AttentionFact, LandedRecipient, ParticipantFact, SeatRef, SquareRead, SquareWrite } from './ports.js';
|
|
3
|
+
import type { ProducerWrite } from './square-post.js';
|
|
3
4
|
export interface LandingEffect {
|
|
4
|
-
readonly activity:
|
|
5
|
+
readonly activity: ActDraft & {
|
|
6
|
+
readonly index: number;
|
|
7
|
+
};
|
|
5
8
|
readonly participant?: ParticipantFact;
|
|
6
9
|
readonly removeListeningOf?: string;
|
|
7
10
|
readonly removeListening?: {
|
|
@@ -14,24 +17,23 @@ export interface LandingEffect {
|
|
|
14
17
|
export interface LandingFacts {
|
|
15
18
|
readonly actor?: ParticipantFact;
|
|
16
19
|
readonly standing: readonly ParticipantFact[];
|
|
20
|
+
readonly seats: ReadonlyMap<string, Seat>;
|
|
17
21
|
readonly incoming: readonly AttentionFact[];
|
|
18
22
|
readonly outgoing: readonly AttentionFact[];
|
|
19
23
|
readonly replyAuthor?: string;
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export
|
|
25
|
-
|
|
25
|
+
export declare function deriveLanding(activity: ActDraft & {
|
|
26
|
+
readonly index: number;
|
|
27
|
+
}, facts: LandingFacts): LandingEffect;
|
|
28
|
+
export declare function landingFacts(read: SquareRead, activity: ActDraft): LandingFacts;
|
|
29
|
+
export interface LandingWriter extends Pick<SquareWrite, 'putLease' | 'removeLease' | 'markSeen' | 'setSeatAttachment'>, ProducerWrite {
|
|
26
30
|
storeSeat(seat: Seat): boolean;
|
|
27
|
-
removeSeat(seat:
|
|
31
|
+
removeSeat(seat: SeatRef): boolean;
|
|
28
32
|
applyLanding(effect: LandingEffect): void;
|
|
29
33
|
}
|
|
30
34
|
export interface SquareWriteGate {
|
|
31
35
|
readonly facts: SquareWrite;
|
|
32
36
|
complete(): void;
|
|
33
37
|
}
|
|
34
|
-
/** Read probes and writes share the same captured-coordinate and attachment fence. */
|
|
35
38
|
export declare function assertCurrentSeat(read: SquareRead, expected: SeatRef, allowDetached?: boolean): void;
|
|
36
|
-
/** The artifact transaction supplies one captured authority; every mutation checks it here. */
|
|
37
39
|
export declare function wrapSquareWrite(read: SquareRead, writes: LandingWriter, authority: ArtifactWriteAuthority): SquareWriteGate;
|
package/dist/square-domain.js
CHANGED
|
@@ -1,61 +1,47 @@
|
|
|
1
|
-
import { SquareError,
|
|
1
|
+
import { SquareError, nameKey, sameName, validateOwner, validateName } from './model.js';
|
|
2
|
+
import { newEndpointGeneration, validateEndpointGeneration } from './message.js';
|
|
2
3
|
import { resolveAudience } from './attention.js';
|
|
3
|
-
|
|
4
|
+
import { freshWatchLease } from './runtime.js';
|
|
5
|
+
import { leaseOwnsNotification } from './catch-selection.js';
|
|
4
6
|
export function deriveLanding(activity, facts) {
|
|
5
|
-
if (activity.kind === 'say' && activity.delivery?.mode === 'direct') {
|
|
6
|
-
const audience = [];
|
|
7
|
-
for (const mention of activity.mentions ?? []) {
|
|
8
|
-
const recipient = facts.standing.find(item => sameName(item.name, mention))?.name;
|
|
9
|
-
if (recipient !== undefined && !audience.some(item => sameName(item.recipient, recipient)))
|
|
10
|
-
audience.push({ recipient, route: 'mention' });
|
|
11
|
-
}
|
|
12
|
-
return { activity, audience };
|
|
13
|
-
}
|
|
14
7
|
const audience = activity.kind === 'say' ? resolveAudience({
|
|
15
|
-
actor: activity.actor, recipients: facts.standing.map(
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
actor: activity.actor, recipients: facts.standing.map(item => item.name), mentions: activity.mentions,
|
|
9
|
+
replyAuthor: facts.replyAuthor, reach: activity.reach, incoming: facts.incoming, sameIdentity: sameName,
|
|
10
|
+
}).map(recipient => {
|
|
11
|
+
const seat = facts.seats.get(nameKey(recipient.recipient));
|
|
12
|
+
return { ...recipient, ...(seat === undefined ? {} : { generation: seat.generation, owner: seat.owner }) };
|
|
18
13
|
}) : [];
|
|
19
|
-
const
|
|
20
|
-
const previous = facts.actor ?? { name: actor, firstIndex: activity.index, joined: false, done: false, sayCount: 0 };
|
|
14
|
+
const previous = facts.actor ?? { name: activity.actor, firstIndex: activity.index, joined: false, done: false, sayCount: 0 };
|
|
21
15
|
const participant = {
|
|
22
|
-
...previous,
|
|
23
|
-
lastActiveAt: Math.max(previous.lastActiveAt ?? -Infinity, activity.at),
|
|
16
|
+
...previous, lastActiveAt: Math.max(previous.lastActiveAt ?? -Infinity, activity.at),
|
|
24
17
|
...(activity.kind === 'join' ? { joined: true, done: false, lastJoinIndex: activity.index } : {}),
|
|
25
18
|
...(activity.kind === 'done' ? { joined: false, done: true } : {}),
|
|
26
19
|
...(activity.kind === 'say' ? { sayCount: previous.sayCount + 1 } : {}),
|
|
27
20
|
};
|
|
28
21
|
let replaceAttention;
|
|
29
22
|
if (activity.kind === 'listen' || activity.kind === 'ignore') {
|
|
30
|
-
const existing = facts.outgoing.find(
|
|
31
|
-
if (existing?.kind !== activity.kind)
|
|
23
|
+
const existing = facts.outgoing.find(item => sameName(item.target, activity.target));
|
|
24
|
+
if (existing?.kind !== activity.kind)
|
|
32
25
|
replaceAttention = { listener: participant.name, target: activity.target, kind: activity.kind, sinceIndex: activity.index };
|
|
33
|
-
}
|
|
34
26
|
}
|
|
35
|
-
const removeListening = activity.kind === 'unlisten'
|
|
36
|
-
&& facts.outgoing.some((item) => item.kind === 'listen' && sameName(item.target, activity.target))
|
|
27
|
+
const removeListening = activity.kind === 'unlisten' && facts.outgoing.some(item => item.kind === 'listen' && sameName(item.target, activity.target))
|
|
37
28
|
? { listener: participant.name, target: activity.target } : undefined;
|
|
38
|
-
return {
|
|
39
|
-
|
|
40
|
-
...(activity.kind === 'done' ? { removeListeningOf: participant.name } : {}),
|
|
41
|
-
...(removeListening === undefined ? {} : { removeListening }),
|
|
42
|
-
...(replaceAttention === undefined ? {} : { replaceAttention }),
|
|
43
|
-
};
|
|
29
|
+
return { activity, participant, audience, ...(activity.kind === 'done' ? { removeListeningOf: participant.name } : {}),
|
|
30
|
+
...(removeListening === undefined ? {} : { removeListening }), ...(replaceAttention === undefined ? {} : { replaceAttention }) };
|
|
44
31
|
}
|
|
45
32
|
export function landingFacts(read, activity) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
33
|
+
const standing = activity.kind === 'say' ? read.roster().filter(item => item.joined) : [];
|
|
34
|
+
const seats = new Map();
|
|
35
|
+
for (const participant of standing) {
|
|
36
|
+
const seat = read.seat(participant.name);
|
|
37
|
+
if (seat !== undefined)
|
|
38
|
+
seats.set(nameKey(participant.name), seat);
|
|
39
|
+
}
|
|
40
|
+
return { actor: read.participant(activity.actor), standing, seats,
|
|
49
41
|
incoming: activity.kind === 'say' ? read.incomingAttention(activity.actor) : [],
|
|
50
42
|
outgoing: activity.kind === 'listen' || activity.kind === 'ignore' || activity.kind === 'unlisten' ? read.attention(activity.actor) : [],
|
|
51
|
-
replyAuthor: activity.kind === 'say' && activity.reply !== undefined ? read.activity(activity.reply)?.actor : undefined
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
function validateGeneration(value) {
|
|
55
|
-
if (typeof value !== 'string' || parseActivityId(value) === undefined)
|
|
56
|
-
throw new SquareError('invalid_args', 'Artifact authority requires a valid join generation.');
|
|
43
|
+
replyAuthor: activity.kind === 'say' && activity.reply !== undefined ? read.activity(activity.reply)?.actor : undefined };
|
|
57
44
|
}
|
|
58
|
-
/** Read probes and writes share the same captured-coordinate and attachment fence. */
|
|
59
45
|
export function assertCurrentSeat(read, expected, allowDetached = false) {
|
|
60
46
|
const current = read.seat(expected.participant);
|
|
61
47
|
if (current === undefined || current.owner !== expected.owner || current.generation !== expected.generation)
|
|
@@ -63,234 +49,130 @@ export function assertCurrentSeat(read, expected, allowDetached = false) {
|
|
|
63
49
|
if (!allowDetached && current.attachment !== 'attached')
|
|
64
50
|
throw new SquareError('already_joined', 'This participant is away; join again before writing.', { reason: 'needs_seat', activityUnsent: true });
|
|
65
51
|
}
|
|
66
|
-
/** The artifact transaction supplies one captured authority; every mutation checks it here. */
|
|
67
52
|
export function wrapSquareWrite(read, writes, authority) {
|
|
68
|
-
if (authority
|
|
53
|
+
if (!authority || typeof authority !== 'object')
|
|
69
54
|
throw new SquareError('invalid_args', 'Artifact writes require an explicit authority.');
|
|
70
|
-
const {
|
|
55
|
+
const denied = () => { throw new SquareError('invalid_args', 'This authority cannot perform that write.'); };
|
|
56
|
+
const deniedWrites = { land: denied, putLease: denied, removeLease: denied, markSeen: denied, setSeatAttachment: denied, insertNotice: denied, ackMatching: denied, acquirePost: denied, settlePost: denied, foldReceipt: denied };
|
|
57
|
+
if (authority.kind === 'producer') {
|
|
58
|
+
return { facts: Object.assign({}, read, deniedWrites, {
|
|
59
|
+
acquirePost(post, token, pid, now, exportAt) {
|
|
60
|
+
if (post.kind === 'activity') {
|
|
61
|
+
const lease = freshWatchLease(read, post.recipient, now);
|
|
62
|
+
const arrival = read.directedAt(post.recipient, post.index);
|
|
63
|
+
if (lease && arrival?.generation === post.generation && leaseOwnsNotification(lease, arrival))
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return writes.acquirePost(post, token, pid, now, exportAt);
|
|
67
|
+
},
|
|
68
|
+
settlePost: writes.settlePost, foldReceipt: writes.foldReceipt, setSeatAttachment: writes.setSeatAttachment,
|
|
69
|
+
}), complete() { } };
|
|
70
|
+
}
|
|
71
|
+
if (authority.kind === 'send') {
|
|
72
|
+
validateName(authority.actor);
|
|
73
|
+
return { facts: Object.assign({}, read, deniedWrites, { insertNotice(input, at) {
|
|
74
|
+
if (!sameName(input.from, authority.actor))
|
|
75
|
+
throw new SquareError('invalid_args', 'Notice sender does not match its authority.');
|
|
76
|
+
return writes.insertNotice(input, at);
|
|
77
|
+
} }), complete() { } };
|
|
78
|
+
}
|
|
71
79
|
const seated = authority.kind === 'participant' || authority.kind === 'host-cleanup';
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
throw new SquareError('invalid_args', 'Artifact write authority is malformed.');
|
|
75
|
-
validateName(expectedName);
|
|
80
|
+
const name = seated ? authority.seat.participant : authority.participant;
|
|
81
|
+
validateName(name);
|
|
76
82
|
if (seated) {
|
|
77
83
|
validateOwner(authority.seat.owner);
|
|
78
|
-
|
|
84
|
+
validateEndpointGeneration(authority.seat.generation);
|
|
79
85
|
}
|
|
80
|
-
else
|
|
86
|
+
else {
|
|
81
87
|
validateOwner(authority.owner);
|
|
82
88
|
if (authority.kind === 'takeover')
|
|
83
|
-
|
|
89
|
+
validateEndpointGeneration(authority.expectedGeneration);
|
|
84
90
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
if (authority.kind === 'participant')
|
|
92
|
+
assertCurrentSeat(read, authority.seat);
|
|
93
|
+
if (authority.kind === 'join' && read.participant(name)?.joined) {
|
|
94
|
+
const seat = read.seat(name);
|
|
95
|
+
if (seat === undefined || seat.owner !== authority.owner)
|
|
96
|
+
throw new SquareError('already_joined', `${name} is held by another owner; take it over explicitly`);
|
|
97
|
+
}
|
|
98
|
+
if (authority.kind === 'takeover' && read.seat(name)?.generation !== authority.expectedGeneration)
|
|
99
|
+
throw new SquareError('already_joined', 'The participant seat changed before takeover.');
|
|
100
|
+
let takeoverPhase = 'ready';
|
|
101
|
+
let establishedSeat;
|
|
102
|
+
const participant = (requested, generation) => {
|
|
103
|
+
if (authority.kind !== 'participant' || !sameName(requested, name) || generation !== undefined && generation !== authority.seat.generation)
|
|
93
104
|
throw new SquareError('already_joined', 'This write needs the current participant seat.');
|
|
94
|
-
|
|
105
|
+
assertCurrentSeat(read, authority.seat);
|
|
95
106
|
};
|
|
96
|
-
|
|
97
|
-
let takeoverPhase = authority.kind === 'takeover' ? 'ready' : undefined;
|
|
98
|
-
if (authority.kind === 'participant') {
|
|
99
|
-
assertSeat(authority.seat);
|
|
100
|
-
}
|
|
101
|
-
else if (authority.kind === 'host-cleanup') {
|
|
102
|
-
// A late host cleanup is allowed to inspect a stale coordinate and return a no-op.
|
|
103
|
-
}
|
|
104
|
-
else if (authority.kind === 'join') {
|
|
105
|
-
const participant = read.participant(expectedName), seat = read.seat(expectedName);
|
|
106
|
-
if (participant?.joined) {
|
|
107
|
-
if (seat === undefined || seat.owner !== authority.owner)
|
|
108
|
-
throw new SquareError('already_joined', `${expectedName} is held by another owner; take it over explicitly`);
|
|
109
|
-
reconnectSeat = seat;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else if (authority.kind === 'takeover') {
|
|
113
|
-
const current = read.seat(expectedName);
|
|
114
|
-
if (current === undefined || current.generation !== authority.expectedGeneration)
|
|
115
|
-
throw new SquareError('already_joined', 'The participant seat changed before takeover.');
|
|
116
|
-
}
|
|
117
|
-
let lastActivity;
|
|
118
|
-
const facts = Object.assign({}, read, {
|
|
107
|
+
const facts = Object.assign({}, read, deniedWrites, {
|
|
119
108
|
land(activity) {
|
|
120
|
-
|
|
121
|
-
if (actor === undefined)
|
|
122
|
-
throw new SquareError('invalid_args', 'Participant activities require a named actor.');
|
|
123
|
-
validateName(actor);
|
|
124
|
-
if (!sameName(actor, expectedName))
|
|
109
|
+
if (!sameName(activity.actor, name))
|
|
125
110
|
throw new SquareError('already_joined', 'Activity actor does not match the artifact authority.');
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
if (authority.kind === 'send') {
|
|
129
|
-
if (activity.kind !== 'say' || activity.delivery?.mode !== 'direct' || activity.reach !== undefined || activity.reply !== undefined)
|
|
130
|
-
throw new SquareError('invalid_args', 'Send authority may only land direct messages without bell or reply.');
|
|
131
|
-
}
|
|
132
|
-
else if (authority.kind === 'participant') {
|
|
133
|
-
assertSeat(authority.seat);
|
|
111
|
+
if (authority.kind === 'participant') {
|
|
112
|
+
assertCurrentSeat(read, authority.seat);
|
|
134
113
|
if (activity.kind === 'join')
|
|
135
|
-
throw new SquareError('invalid_args', 'A participant seat can only be
|
|
114
|
+
throw new SquareError('invalid_args', 'A participant seat can only be established by join.');
|
|
136
115
|
}
|
|
137
116
|
else if (authority.kind === 'host-cleanup') {
|
|
138
|
-
|
|
117
|
+
assertCurrentSeat(read, authority.seat, true);
|
|
139
118
|
if (activity.kind !== 'done')
|
|
140
119
|
throw new SquareError('invalid_args', 'Host cleanup may only end membership.');
|
|
141
120
|
}
|
|
142
121
|
else if (authority.kind === 'join') {
|
|
143
|
-
if (activity.kind !== 'join')
|
|
144
|
-
throw new SquareError('
|
|
145
|
-
if (read.participant(expectedName)?.joined)
|
|
146
|
-
throw new SquareError('already_joined', `${expectedName} is already standing; join cannot replace an existing seat.`);
|
|
122
|
+
if (activity.kind !== 'join' || read.participant(name)?.joined)
|
|
123
|
+
throw new SquareError('already_joined', 'A new seat requires a new join.');
|
|
147
124
|
}
|
|
148
125
|
else if (takeoverPhase === 'ready') {
|
|
149
|
-
|
|
150
|
-
if (activity.kind !== 'done' || current === undefined || current.generation !== authority.expectedGeneration)
|
|
126
|
+
if (activity.kind !== 'done' || read.seat(name)?.generation !== authority.expectedGeneration)
|
|
151
127
|
throw new SquareError('already_joined', 'Takeover must first complete the captured participant.');
|
|
152
128
|
}
|
|
153
|
-
else if (
|
|
154
|
-
if (activity.kind !== 'join' || !read.participant(
|
|
129
|
+
else if (takeoverPhase === 'done') {
|
|
130
|
+
if (activity.kind !== 'join' || !read.participant(name)?.done)
|
|
155
131
|
throw new SquareError('already_joined', 'Takeover must join after its captured done activity.');
|
|
156
132
|
}
|
|
157
|
-
else
|
|
133
|
+
else
|
|
158
134
|
throw new SquareError('invalid_args', 'Takeover permits only one done followed by one join.');
|
|
159
|
-
}
|
|
160
135
|
const index = read.header().nextActIndex;
|
|
161
136
|
if (!Number.isSafeInteger(index) || index < 0 || index >= Number.MAX_SAFE_INTEGER)
|
|
162
137
|
throw new SquareError('invalid_args', 'Square activity index is exhausted.');
|
|
163
|
-
const captured = authority.kind === 'takeover' && activity.kind === 'done'
|
|
164
|
-
? read.seat(expectedName) : undefined;
|
|
138
|
+
const captured = authority.kind === 'takeover' && activity.kind === 'done' ? read.seat(name) : undefined;
|
|
165
139
|
const stored = { ...activity, index };
|
|
166
|
-
applyLanding(deriveLanding(stored, landingFacts(read,
|
|
140
|
+
writes.applyLanding(deriveLanding(stored, landingFacts(read, activity)));
|
|
167
141
|
if (stored.kind === 'join') {
|
|
168
142
|
if (authority.kind !== 'join' && authority.kind !== 'takeover')
|
|
169
143
|
throw new SquareError('invalid_args', 'Seat authority cannot establish another seat.');
|
|
170
|
-
const seat = {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
generation: formatActivityId(stored.index),
|
|
174
|
-
attachment: 'attached',
|
|
175
|
-
...(authority.wakeAddress === undefined ? {} : { wakeAddress: authority.wakeAddress }),
|
|
176
|
-
};
|
|
177
|
-
mutations.storeSeat(seat);
|
|
178
|
-
const established = read.seat(seat.participant);
|
|
179
|
-
if (established === undefined || established.owner !== seat.owner || established.generation !== seat.generation)
|
|
180
|
-
throw new SquareError('invalid_args', 'The join activity did not establish its artifact seat.');
|
|
144
|
+
const seat = { participant: stored.actor, owner: authority.owner, generation: newEndpointGeneration(), attachment: 'attached', ...(authority.wakeAddress === undefined ? {} : { wakeAddress: authority.wakeAddress }) };
|
|
145
|
+
writes.storeSeat(seat);
|
|
146
|
+
establishedSeat = seat;
|
|
181
147
|
if (authority.kind === 'takeover')
|
|
182
148
|
takeoverPhase = 'joined';
|
|
183
149
|
}
|
|
184
150
|
else if (stored.kind === 'done' && seated) {
|
|
185
|
-
if (!
|
|
186
|
-
throw new SquareError('already_joined', 'The participant seat changed while it
|
|
151
|
+
if (!writes.removeSeat(authority.seat))
|
|
152
|
+
throw new SquareError('already_joined', 'The participant seat changed while completing it.');
|
|
187
153
|
}
|
|
188
154
|
else if (stored.kind === 'done' && authority.kind === 'takeover') {
|
|
189
|
-
if (captured === undefined || !
|
|
190
|
-
throw new SquareError('already_joined', 'The participant seat changed while takeover
|
|
155
|
+
if (captured === undefined || !writes.removeSeat(captured))
|
|
156
|
+
throw new SquareError('already_joined', 'The participant seat changed while takeover completed it.');
|
|
191
157
|
takeoverPhase = 'done';
|
|
192
158
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
throw new SquareError('already_joined', 'Reattachment requires a same-owner join.');
|
|
205
|
-
assertSeat(seat, reconnectSeat, true);
|
|
206
|
-
return mutations.reattachSeat(seat, wakeAddress);
|
|
207
|
-
},
|
|
208
|
-
detachSeat(seat) {
|
|
209
|
-
if (authority.kind !== 'host-cleanup')
|
|
210
|
-
throw new SquareError('already_joined', 'Detach requires captured host cleanup authority.');
|
|
211
|
-
const current = read.seat(seat.participant), expected = authority.seat;
|
|
212
|
-
if (!sameName(seat.participant, expected.participant) || seat.owner !== expected.owner || seat.generation !== expected.generation)
|
|
213
|
-
throw new SquareError('already_joined', 'Host cleanup does not match its captured seat.');
|
|
214
|
-
if (current === undefined || current.attachment !== 'attached' || current.owner !== expected.owner
|
|
215
|
-
|| current.generation !== expected.generation)
|
|
216
|
-
return false;
|
|
217
|
-
return mutations.detachSeat(seat);
|
|
218
|
-
},
|
|
219
|
-
cancelThrough(seat, through) {
|
|
220
|
-
assertSeat(seat);
|
|
221
|
-
if (!Number.isSafeInteger(through) || through < 0 || through >= read.header().nextActIndex)
|
|
222
|
-
throw new SquareError('invalid_args', 'Cancellation boundary must be an assigned activity index below the allocator.');
|
|
223
|
-
return mutations.cancelThrough(seat, through);
|
|
224
|
-
},
|
|
225
|
-
markSeen(name, indexes, at) {
|
|
226
|
-
assertParticipant(name);
|
|
227
|
-
return mutations.markSeen(name, indexes, at);
|
|
228
|
-
},
|
|
229
|
-
putLease(name, lease, generation) {
|
|
230
|
-
assertParticipant(name, generation);
|
|
231
|
-
return mutations.putLease(name, lease, generation);
|
|
232
|
-
},
|
|
233
|
-
removeLease(name, leaseId, generation) {
|
|
234
|
-
assertParticipant(name, generation);
|
|
235
|
-
return mutations.removeLease(name, leaseId, generation);
|
|
236
|
-
},
|
|
237
|
-
putDeliveryDeferral(...args) {
|
|
238
|
-
assertSeat(args[0]);
|
|
239
|
-
return mutations.putDeliveryDeferral(...args);
|
|
240
|
-
},
|
|
241
|
-
renewDeliveryDeferral(...args) {
|
|
242
|
-
assertSeat(args[0]);
|
|
243
|
-
return mutations.renewDeliveryDeferral(...args);
|
|
244
|
-
},
|
|
245
|
-
releaseDeliveryDeferral(...args) {
|
|
246
|
-
assertSeat(args[0]);
|
|
247
|
-
return mutations.releaseDeliveryDeferral(...args);
|
|
248
|
-
},
|
|
249
|
-
claimDelivery(input) {
|
|
250
|
-
assertSeat(input.seat);
|
|
251
|
-
const evidence = read.deliveryEvidence(input.seat.participant, input.seat.generation, input.activity);
|
|
252
|
-
if (input.observationOf !== undefined) {
|
|
253
|
-
// Receiver adapters validate native identity/content before entering this transaction.
|
|
254
|
-
// This path records that existing message, rather than acquiring a second send.
|
|
255
|
-
if (input.kind !== 'presentation' || !evidence.some(row => row.kind === 'wake'
|
|
256
|
-
&& row.claimToken === input.observationOf && ['dispatching', 'accepted', 'unknown'].includes(row.outcome)))
|
|
257
|
-
return { status: 'stale' };
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
const blocker = evidence.find(row => row.kind !== input.kind
|
|
261
|
-
&& row.outcome !== 'failed' && row.outcome !== 'released');
|
|
262
|
-
if (blocker !== undefined) {
|
|
263
|
-
if (blocker.outcome === 'dispatching' && blocker.expiresAt !== undefined && blocker.expiresAt <= input.at) {
|
|
264
|
-
// Normalize abandoned custody to unknown in the same transaction, never steal it.
|
|
265
|
-
return mutations.claimDelivery({ ...input, kind: blocker.kind });
|
|
266
|
-
}
|
|
267
|
-
return { status: blocker.outcome === 'dispatching' ? 'busy' : 'terminal', evidence: blocker };
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return mutations.claimDelivery(input);
|
|
271
|
-
},
|
|
272
|
-
prepareDelivery(input) {
|
|
273
|
-
assertSeat(input.seat);
|
|
274
|
-
return mutations.prepareDelivery(input);
|
|
275
|
-
},
|
|
276
|
-
completeDelivery(input) {
|
|
277
|
-
assertSeat(input.seat);
|
|
278
|
-
return mutations.completeDelivery(input);
|
|
279
|
-
},
|
|
280
|
-
observeNativeDelivery(input) {
|
|
281
|
-
assertSeat(input.seat);
|
|
282
|
-
return mutations.observeNativeDelivery(input);
|
|
283
|
-
},
|
|
159
|
+
// Return the persisted, detached fact rather than freezing the caller's draft.
|
|
160
|
+
const landed = read.activity(index);
|
|
161
|
+
if (landed === undefined)
|
|
162
|
+
throw new SquareError('invalid_args', 'The activity did not land.');
|
|
163
|
+
return landed;
|
|
164
|
+
},
|
|
165
|
+
putLease(name, lease, generation) { participant(name, generation); return writes.putLease(name, lease, generation); },
|
|
166
|
+
removeLease(name, leaseId, generation) { participant(name, generation); return writes.removeLease(name, leaseId, generation); },
|
|
167
|
+
markSeen(name, indexes, at) { participant(name); return writes.markSeen(name, indexes, at); },
|
|
168
|
+
ackMatching(seat, input, at) { participant(seat.participant, seat.generation); if (authority.kind !== 'participant' || authority.seat.owner !== seat.owner)
|
|
169
|
+
throw new SquareError('already_joined', 'Seat owner changed.'); return writes.ackMatching(seat, input, at); },
|
|
284
170
|
});
|
|
285
|
-
return {
|
|
286
|
-
facts,
|
|
287
|
-
complete() {
|
|
171
|
+
return { facts, complete() {
|
|
288
172
|
if (authority.kind !== 'takeover')
|
|
289
173
|
return;
|
|
290
|
-
const seat = read.seat(
|
|
291
|
-
if (takeoverPhase !== 'joined' ||
|
|
292
|
-
|| seat.owner !== authority.owner || seat.generation !== formatActivityId(lastActivity.index))
|
|
174
|
+
const seat = read.seat(name);
|
|
175
|
+
if (takeoverPhase !== 'joined' || seat === undefined || establishedSeat === undefined || seat.owner !== establishedSeat.owner || seat.generation !== establishedSeat.generation)
|
|
293
176
|
throw new SquareError('already_joined', 'Takeover did not complete its replacement join.');
|
|
294
|
-
}
|
|
295
|
-
};
|
|
177
|
+
} };
|
|
296
178
|
}
|