@powerhousedao/reactor-api 6.2.3-dev.34 → 6.2.3-dev.35

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/index.mjs CHANGED
@@ -1,12 +1,13 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="66ae2db7-0d74-5986-a811-364313026902")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9e720347-46a5-5d4d-a73c-901d11fe454f")}catch(e){}}();
3
3
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
4
- import { C as AuthorizationPolicy, D as AuthenticationRequiredError, E as AuthEvaluationUnsupportedError, O as ForbiddenError, S as createCanonicalDocumentIdResolver, T as createAuthorizationService, _ as loadProcessors, a as pieceListLocation, b as callerSubject, c as buildGraphQlDocument, d as buildGraphqlOperations, f as isSubgraphClass, g as loadDocumentModels, k as MalformedStoredOperationError, l as buildGraphQlDriveDocument, m as extractUpgradeManifests, o as piecesFromCdnList, p as debounce, r as PIECE_SOURCE_LIST, s as piecesFromListModule, u as buildGraphqlOperation, v as loadSubgraphs, w as AuthorizedDocumentHandle, x as CanonicalDocumentIdResolutionError, y as BaseSubgraph } from "./pieces-swupjgIO.mjs";
4
+ import { A as RefusalNotRecordedError, C as AuthorizationPolicy, D as AuthenticationRequiredError, E as AuthEvaluationUnsupportedError, O as ForbiddenError, S as createCanonicalDocumentIdResolver, T as createAuthorizationService, _ as loadProcessors, a as pieceListLocation, b as callerSubject, c as buildGraphQlDocument, d as buildGraphqlOperations, f as isSubgraphClass, g as loadDocumentModels, k as MalformedStoredOperationError, l as buildGraphQlDriveDocument, m as extractUpgradeManifests, o as piecesFromCdnList, p as debounce, r as PIECE_SOURCE_LIST, s as piecesFromListModule, u as buildGraphqlOperation, v as loadSubgraphs, w as AuthorizedDocumentHandle, x as CanonicalDocumentIdResolutionError, y as BaseSubgraph } from "./pieces-Bi5qxpi5.mjs";
5
5
  import { AnalyticsQueryEngine } from "@powerhousedao/analytics-engine-core";
6
6
  import { AnalyticsModel, AnalyticsResolvers, typedefs } from "@powerhousedao/analytics-engine-graphql";
7
7
  import { gql } from "graphql-tag";
8
8
  import { GraphQLError, Kind, Lexer, Source, TokenKind, parse, print, visit } from "graphql";
9
- import { AuthEnforcementDisabledError, BareReadGate, ChannelError, ChannelErrorSource, DEFAULT_DRIVE_CONTAINER_TYPES, DriveCollectionId, JobStatus, ModelReadGate, PropagationMode as PropagationMode$1, SyncOperation, SyncScopeGate, consolidateSyncOperations, createReactorHostModuleBase, driveIdFromUrl, envelopesToSyncOperations, parseDriveUrl, readDecisionModel, syncOperationErrorType } from "@powerhousedao/reactor";
9
+ import { AuthEnforcementDisabledError, BareReadGate, ChannelError, ChannelErrorSource, DEFAULT_DRIVE_CONTAINER_TYPES, DriveCollectionId, JobStatus, ModelReadGate, PropagationMode as PropagationMode$1, SyncOperation, SyncScopeGate, consolidateSyncOperations, createReactorHostModuleBase, driveIdFromUrl, envelopesToSyncOperations, parseDriveUrl, readDecisionModel, supportsPurgeRefusals, syncOperationErrorType } from "@powerhousedao/reactor";
10
+ import { deserializeSignature, readPeerManifest, serializeSignature, setName, withSignaturePolicy } from "@powerhousedao/shared/document-model";
10
11
  import { ConsoleLogger, childLogger, documentModelDocumentModelModule } from "document-model";
11
12
  import path, { isAbsolute, join } from "node:path";
12
13
  import { match } from "path-to-regexp";
@@ -20,7 +21,6 @@ import { buildSubgraphSchema } from "@apollo/subgraph";
20
21
  import { typeDefs } from "@powerhousedao/document-engineering/graphql";
21
22
  import { camelCase, kebabCase, pascalCase } from "change-case";
22
23
  import { GraphQLJSON, GraphQLJSONObject } from "graphql-type-json";
23
- import { deserializeSignature, readPeerManifest, serializeSignature, setName, withSignaturePolicy } from "@powerhousedao/shared/document-model";
24
24
  import * as z$1 from "zod";
25
25
  import { z } from "zod";
26
26
  import { createHandler } from "graphql-sse/lib/use/fetch";
@@ -87,7 +87,30 @@ var AnalyticsSubgraph = class extends BaseSubgraph {
87
87
  };
88
88
  //#endregion
89
89
  //#region src/graphql/auth/schema.graphql
90
- var schema_default$2 = "# Auth Subgraph Schema\n# Contains all document permission and authorization related types\n\nscalar DateTime\n\n# Permission levels for documents\nenum DocumentPermissionLevel {\n # Can fetch and read the document\n READ\n # Can push updates and modify the document\n WRITE\n # Can manage document permissions and settings\n ADMIN\n}\n\n# Document permission entry\ntype DocumentPermissionEntry {\n documentId: String!\n userAddress: String!\n permission: DocumentPermissionLevel!\n grantedBy: String!\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\n# Operation user permission entry\ntype OperationUserPermission {\n documentId: String!\n operationType: String!\n userAddress: String!\n grantedBy: String!\n createdAt: DateTime!\n}\n\n# Combined document access info\ntype DocumentAccessInfo {\n documentId: String!\n permissions: [DocumentPermissionEntry!]!\n}\n\n# Operation permissions info\ntype OperationPermissionsInfo {\n documentId: String!\n operationType: String!\n userPermissions: [OperationUserPermission!]!\n}\n\n# Document protection info\ntype DocumentProtectionInfo {\n documentId: String!\n protected: Boolean!\n ownerAddress: String\n}\n\ntype Query {\n # Get permissions for a document (requires ADMIN permission or global admin)\n documentAccess(documentId: String!): DocumentAccessInfo!\n\n # Get protection status for a document (requires ADMIN permission or global admin)\n documentProtection(documentId: String!): DocumentProtectionInfo!\n\n # Get all documents the current user has explicit access to\n userDocumentPermissions: [DocumentPermissionEntry!]!\n\n # Get operation permissions for a document and operation type\n # (requires ADMIN permission or global admin)\n operationPermissions(\n documentId: String!\n operationType: String!\n ): OperationPermissionsInfo!\n\n # Check if the current user can execute a specific operation on a document\n canExecuteOperation(documentId: String!, operationType: String!): Boolean!\n}\n\ntype Mutation {\n # Set document protection status (requires ADMIN permission or global admin)\n setDocumentProtection(\n documentId: String!\n protected: Boolean!\n ): DocumentProtectionInfo!\n\n # Transfer document ownership (requires ADMIN permission or global admin)\n transferDocumentOwnership(\n documentId: String!\n newOwnerAddress: String!\n ): DocumentProtectionInfo!\n\n # Grant a user permission on a document (requires ADMIN permission or global admin)\n grantDocumentPermission(\n documentId: String!\n userAddress: String!\n permission: DocumentPermissionLevel!\n ): DocumentPermissionEntry!\n\n # Revoke a user's permission on a document (requires ADMIN permission or global admin)\n revokeDocumentPermission(documentId: String!, userAddress: String!): Boolean!\n\n # --- Operation Permissions ---\n\n # Grant a user permission to execute an operation on a document\n grantOperationPermission(\n documentId: String!\n operationType: String!\n userAddress: String!\n ): OperationUserPermission!\n\n # Revoke a user's permission to execute an operation\n revokeOperationPermission(\n documentId: String!\n operationType: String!\n userAddress: String!\n ): Boolean!\n}\n";
90
+ var schema_default$2 = "# Auth Subgraph Schema\n# Contains all document permission and authorization related types\n\nscalar DateTime\n\n# Permission levels for documents\nenum DocumentPermissionLevel {\n # Can fetch and read the document\n READ\n # Can push updates and modify the document\n WRITE\n # Can manage document permissions and settings\n ADMIN\n}\n\n# Document permission entry\ntype DocumentPermissionEntry {\n documentId: String!\n userAddress: String!\n permission: DocumentPermissionLevel!\n grantedBy: String!\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\n# Operation user permission entry\ntype OperationUserPermission {\n documentId: String!\n operationType: String!\n userAddress: String!\n grantedBy: String!\n createdAt: DateTime!\n}\n\n# Combined document access info\ntype DocumentAccessInfo {\n documentId: String!\n permissions: [DocumentPermissionEntry!]!\n}\n\n# Operation permissions info\ntype OperationPermissionsInfo {\n documentId: String!\n operationType: String!\n userPermissions: [OperationUserPermission!]!\n}\n\n# Document protection info\ntype DocumentProtectionInfo {\n documentId: String!\n protected: Boolean!\n ownerAddress: String\n}\n\ntype Query {\n # Get permissions for a document (requires ADMIN permission or global admin)\n documentAccess(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n ): DocumentAccessInfo!\n\n # Get protection status for a document (requires ADMIN permission or global admin)\n documentProtection(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n ): DocumentProtectionInfo!\n\n # Get all documents the current user has explicit access to\n userDocumentPermissions: [DocumentPermissionEntry!]!\n\n # Get operation permissions for a document and operation type\n # (requires ADMIN permission or global admin)\n operationPermissions(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n ): OperationPermissionsInfo!\n\n # Check if the current user can execute a specific operation on a document\n canExecuteOperation(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n ): Boolean!\n}\n\ntype Mutation {\n # Set document protection status (requires ADMIN permission or global admin)\n setDocumentProtection(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n protected: Boolean!\n ): DocumentProtectionInfo!\n\n # Transfer document ownership (requires ADMIN permission or global admin)\n transferDocumentOwnership(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n newOwnerAddress: String!\n ): DocumentProtectionInfo!\n\n # Grant a user permission on a document (requires ADMIN permission or global admin)\n grantDocumentPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n userAddress: String!\n permission: DocumentPermissionLevel!\n ): DocumentPermissionEntry!\n\n # Revoke a user's permission on a document (requires ADMIN permission or global admin)\n revokeDocumentPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n userAddress: String!\n ): Boolean!\n\n # --- Operation Permissions ---\n\n # Grant a user permission to execute an operation on a document\n grantOperationPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n userAddress: String!\n ): OperationUserPermission!\n\n # Revoke a user's permission to execute an operation\n revokeOperationPermission(\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n operationType: String!\n userAddress: String!\n ): Boolean!\n}\n";
91
+ //#endregion
92
+ //#region src/graphql/argument-aliases.ts
93
+ /** A renamed argument given under both names, or a required one under neither. */
94
+ var ArgumentAliasError = class extends GraphQLError {
95
+ constructor(message) {
96
+ super(message, { extensions: { code: "BAD_USER_INPUT" } });
97
+ }
98
+ };
99
+ /** The value of a required argument that may still arrive under its old name. */
100
+ function requireOneOf(args, name, deprecatedName) {
101
+ const current = args[name] ?? void 0;
102
+ const deprecated = args[deprecatedName] ?? void 0;
103
+ if (current !== void 0 && deprecated !== void 0) throw new ArgumentAliasError(`Pass ${name} or ${deprecatedName}, not both.`);
104
+ if (current === void 0 && deprecated === void 0) throw new ArgumentAliasError(`${name} is required.`);
105
+ return current ?? deprecated;
106
+ }
107
+ /** The value of an optional argument that may still arrive under its old name. */
108
+ function optionalOneOf(args, name, deprecatedName) {
109
+ const current = args[name] ?? void 0;
110
+ const deprecated = args[deprecatedName] ?? void 0;
111
+ if (current !== void 0 && deprecated !== void 0) throw new ArgumentAliasError(`Pass ${name} or ${deprecatedName}, not both.`);
112
+ return current ?? deprecated;
113
+ }
91
114
  //#endregion
92
115
  //#region src/graphql/auth/resolvers.ts
93
116
  async function documentAccess(service, authorizationService, args, userAddress) {
@@ -183,7 +206,7 @@ var AuthSubgraph = class extends BaseSubgraph {
183
206
  this.logger.debug("documentAccess(@args)", args);
184
207
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
185
208
  try {
186
- return await documentAccess(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
209
+ return await documentAccess(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
187
210
  } catch (error) {
188
211
  this.logger.error("Error in documentAccess: @error", error);
189
212
  throw error;
@@ -204,7 +227,7 @@ var AuthSubgraph = class extends BaseSubgraph {
204
227
  this.logger.debug("operationPermissions(@args)", args);
205
228
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
206
229
  try {
207
- return await operationPermissions(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
230
+ return await operationPermissions(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
208
231
  } catch (error) {
209
232
  this.logger.error("Error in operationPermissions: @error", error);
210
233
  throw error;
@@ -213,7 +236,7 @@ var AuthSubgraph = class extends BaseSubgraph {
213
236
  canExecuteOperation: async (_parent, args, ctx) => {
214
237
  this.logger.debug("canExecuteOperation(@args)", args);
215
238
  try {
216
- return await canExecuteOperation(this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
239
+ return await canExecuteOperation(this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
217
240
  } catch (error) {
218
241
  this.logger.error("Error in canExecuteOperation: @error", error);
219
242
  throw error;
@@ -223,7 +246,7 @@ var AuthSubgraph = class extends BaseSubgraph {
223
246
  this.logger.debug("documentProtection(@args)", args);
224
247
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
225
248
  try {
226
- return await documentProtection(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
249
+ return await documentProtection(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
227
250
  } catch (error) {
228
251
  this.logger.error("Error in documentProtection: @error", error);
229
252
  throw error;
@@ -235,7 +258,7 @@ var AuthSubgraph = class extends BaseSubgraph {
235
258
  this.logger.debug("setDocumentProtection(@args)", args);
236
259
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
237
260
  try {
238
- return await setDocumentProtection(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
261
+ return await setDocumentProtection(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
239
262
  } catch (error) {
240
263
  this.logger.error("Error in setDocumentProtection: @error", error);
241
264
  throw error;
@@ -245,7 +268,7 @@ var AuthSubgraph = class extends BaseSubgraph {
245
268
  this.logger.debug("transferDocumentOwnership(@args)", args);
246
269
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
247
270
  try {
248
- return await transferDocumentOwnership(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
271
+ return await transferDocumentOwnership(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
249
272
  } catch (error) {
250
273
  this.logger.error("Error in transferDocumentOwnership: @error", error);
251
274
  throw error;
@@ -255,7 +278,7 @@ var AuthSubgraph = class extends BaseSubgraph {
255
278
  this.logger.debug("grantDocumentPermission(@args)", args);
256
279
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
257
280
  try {
258
- const resolved = await this.withCanonicalDocumentId(args, ctx);
281
+ const resolved = await this.#withCanonicalDocumentArgs(args, ctx);
259
282
  return await grantDocumentPermission(this.documentPermissionService, this.authorizationService, {
260
283
  ...resolved,
261
284
  permission: resolved.permission
@@ -269,7 +292,7 @@ var AuthSubgraph = class extends BaseSubgraph {
269
292
  this.logger.debug("revokeDocumentPermission(@args)", args);
270
293
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
271
294
  try {
272
- return await revokeDocumentPermission(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
295
+ return await revokeDocumentPermission(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
273
296
  } catch (error) {
274
297
  this.logger.error("Error in revokeDocumentPermission: @error", error);
275
298
  throw error;
@@ -279,7 +302,7 @@ var AuthSubgraph = class extends BaseSubgraph {
279
302
  this.logger.debug("grantOperationPermission(@args)", args);
280
303
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
281
304
  try {
282
- return await grantOperationPermission(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
305
+ return await grantOperationPermission(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
283
306
  } catch (error) {
284
307
  this.logger.error("Error in grantOperationPermission: @error", error);
285
308
  throw error;
@@ -289,7 +312,7 @@ var AuthSubgraph = class extends BaseSubgraph {
289
312
  this.logger.debug("revokeOperationPermission(@args)", args);
290
313
  if (!this.documentPermissionService) throw new GraphQLError("DocumentPermissionService not available");
291
314
  try {
292
- return await revokeOperationPermission(this.documentPermissionService, this.authorizationService, await this.withCanonicalDocumentId(args, ctx), ctx.user?.address);
315
+ return await revokeOperationPermission(this.documentPermissionService, this.authorizationService, await this.#withCanonicalDocumentArgs(args, ctx), ctx.user?.address);
293
316
  } catch (error) {
294
317
  this.logger.error("Error in revokeOperationPermission: @error", error);
295
318
  throw error;
@@ -297,6 +320,16 @@ var AuthSubgraph = class extends BaseSubgraph {
297
320
  }
298
321
  }
299
322
  };
323
+ #withCanonicalDocumentArgs(args, ctx) {
324
+ const { documentIdOrSlug, documentId, ...rest } = args;
325
+ return this.withCanonicalDocumentId({
326
+ ...rest,
327
+ documentId: requireOneOf({
328
+ documentIdOrSlug,
329
+ documentId
330
+ }, "documentIdOrSlug", "documentId")
331
+ }, ctx);
332
+ }
300
333
  onSetup() {
301
334
  this.logger.debug("Setting up AuthSubgraph");
302
335
  return Promise.resolve();
@@ -1985,7 +2018,7 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
1985
2018
 
1986
2019
  input ${documentName}_SearchFilterInput {
1987
2020
  parentId: String
1988
- identifiers: [String!]
2021
+ identifiers: [String!] @deprecated(reason: "Ignored. Filter by parentId.")
1989
2022
  }
1990
2023
  `;
1991
2024
  const revisionType = RevisionType;
@@ -2027,7 +2060,7 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
2027
2060
  const queries = `
2028
2061
  type ${documentName}Queries {
2029
2062
  """Get a specific ${documentName} document by identifier"""
2030
- document(identifier: String!, view: ${documentName}_ViewFilterInput): ${documentName}_DocumentWithChildren
2063
+ document(idOrSlug: String, identifier: String @deprecated(reason: "Use idOrSlug."), view: ${documentName}_ViewFilterInput): ${documentName}_DocumentWithChildren
2031
2064
 
2032
2065
  """Get all ${documentName} documents (paged)"""
2033
2066
  documents(paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
@@ -2036,10 +2069,10 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
2036
2069
  findDocuments(search: ${documentName}_SearchFilterInput, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
2037
2070
 
2038
2071
  """Get outgoing relationships of a ${documentName} document"""
2039
- documentOutgoingRelationships(sourceIdentifier: String!, relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
2072
+ documentOutgoingRelationships(sourceIdOrSlug: String, sourceIdentifier: String @deprecated(reason: "Use sourceIdOrSlug."), relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
2040
2073
 
2041
2074
  """Get incoming relationships to a ${documentName} document"""
2042
- documentIncomingRelationships(targetIdentifier: String!, relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
2075
+ documentIncomingRelationships(targetIdOrSlug: String, targetIdentifier: String @deprecated(reason: "Use targetIdOrSlug."), relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!
2043
2076
  }
2044
2077
  `;
2045
2078
  let initialStateInputSchema = "";
@@ -2070,9 +2103,9 @@ function generateNewApiSchema(documentName, specification, prefixedStateInputTyp
2070
2103
  initialStateInputSchema = inputTypeDefs ? `${inputTypeDefs}\n\n${wrapper}` : wrapper;
2071
2104
  }
2072
2105
  }
2073
- const createDocumentMutation = initialStateInputSchema ? `createDocument(name: String!, parentIdentifier: String, slug: String, preferredEditor: String, initialState: ${documentName}_InitialStateInput): ${documentName}MutationResult!` : `createDocument(name: String!, parentIdentifier: String, preferredEditor: String): ${documentName}MutationResult!`;
2074
- const createEmptyDocumentMutation = `createEmptyDocument(parentIdentifier: String): ${documentName}MutationResult!`;
2075
- const operationMutations = specification?.modules.flatMap((module) => module.operations.filter((op) => op.name && hasValidSchema(op.schema)).flatMap((op) => [`${camelCase(op.name)}(docId: PHID!, input: ${documentName}_${pascalCase(op.name)}Input!): ${documentName}MutationResult!`, `${camelCase(op.name)}Async(docId: PHID!, input: ${documentName}_${pascalCase(op.name)}Input!): String!`])).join("\n ") ?? "";
2106
+ const createDocumentMutation = initialStateInputSchema ? `createDocument(name: String!, parentIdOrSlug: String, parentIdentifier: String @deprecated(reason: "Use parentIdOrSlug."), slug: String, preferredEditor: String, initialState: ${documentName}_InitialStateInput): ${documentName}MutationResult!` : `createDocument(name: String!, parentIdOrSlug: String, parentIdentifier: String @deprecated(reason: "Use parentIdOrSlug."), preferredEditor: String): ${documentName}MutationResult!`;
2107
+ const createEmptyDocumentMutation = `createEmptyDocument(parentIdOrSlug: String, parentIdentifier: String @deprecated(reason: "Use parentIdOrSlug.")): ${documentName}MutationResult!`;
2108
+ const operationMutations = specification?.modules.flatMap((module) => module.operations.filter((op) => op.name && hasValidSchema(op.schema)).flatMap((op) => [`${camelCase(op.name)}(documentIdOrSlug: String, docId: PHID @deprecated(reason: "Use documentIdOrSlug."), input: ${documentName}_${pascalCase(op.name)}Input!): ${documentName}MutationResult!`, `${camelCase(op.name)}Async(documentIdOrSlug: String, docId: PHID @deprecated(reason: "Use documentIdOrSlug."), input: ${documentName}_${pascalCase(op.name)}Input!): String!`])).join("\n ") ?? "";
2076
2109
  const moduleSchemas = buildModuleSchemas(specification, documentName, allTypeNames, hasValidSchema);
2077
2110
  return gql`
2078
2111
  scalar DateTime
@@ -2226,7 +2259,8 @@ function OperationsFilterInputSchema() {
2226
2259
  return z$1.object({
2227
2260
  actionTypes: z$1.array(z$1.string()).nullish(),
2228
2261
  branch: z$1.string().nullish(),
2229
- documentId: z$1.string(),
2262
+ documentId: z$1.string().nullish(),
2263
+ documentIdOrSlug: z$1.string().nullish(),
2230
2264
  scopes: z$1.array(z$1.string()).nullish(),
2231
2265
  sinceRevision: z$1.number().nullish(),
2232
2266
  timestampFrom: z$1.string().nullish(),
@@ -2294,7 +2328,8 @@ function SyncEnvelopeInputSchema() {
2294
2328
  function SyncRefusalInputSchema() {
2295
2329
  return z$1.object({
2296
2330
  branch: z$1.string(),
2297
- documentId: z$1.string()
2331
+ documentId: z$1.string(),
2332
+ kind: z$1.string().nullish()
2298
2333
  });
2299
2334
  }
2300
2335
  function TouchChannelInputSchema() {
@@ -3457,13 +3492,13 @@ async function document(reactorClient, args, subject) {
3457
3492
  };
3458
3493
  let result;
3459
3494
  try {
3460
- result = await reactorClient.get(args.identifier, view);
3495
+ result = await reactorClient.get(args.idOrSlug, view);
3461
3496
  } catch (error) {
3462
3497
  throw new GraphQLError(`Failed to fetch document: ${error instanceof Error ? error.message : "Unknown error"}`);
3463
3498
  }
3464
3499
  let children;
3465
3500
  try {
3466
- children = await reactorClient.getOutgoingRelationships(args.identifier, "child", view);
3501
+ children = await reactorClient.getOutgoingRelationships(args.idOrSlug, "child", view);
3467
3502
  } catch (error) {
3468
3503
  throw new GraphQLError(`Failed to fetch children: ${error instanceof Error ? error.message : "Unknown error"}`);
3469
3504
  }
@@ -3494,7 +3529,7 @@ async function documentOutgoingRelationships(reactorClient, args, subject) {
3494
3529
  }
3495
3530
  let result;
3496
3531
  try {
3497
- result = await reactorClient.getOutgoingRelationships(args.sourceIdentifier, args.relationshipType, view, paging);
3532
+ result = await reactorClient.getOutgoingRelationships(args.sourceIdOrSlug, args.relationshipType, view, paging);
3498
3533
  } catch (error) {
3499
3534
  throw new GraphQLError(`Failed to fetch outgoing relationships: ${error instanceof Error ? error.message : "Unknown error"}`);
3500
3535
  }
@@ -3522,7 +3557,7 @@ async function documentIncomingRelationships(reactorClient, args, subject) {
3522
3557
  }
3523
3558
  let result;
3524
3559
  try {
3525
- result = await reactorClient.getIncomingRelationships(args.targetIdentifier, args.relationshipType, view, paging);
3560
+ result = await reactorClient.getIncomingRelationships(args.targetIdOrSlug, args.relationshipType, view, paging);
3526
3561
  } catch (error) {
3527
3562
  throw new GraphQLError(`Failed to fetch incoming relationships: ${error instanceof Error ? error.message : "Unknown error"}`);
3528
3563
  }
@@ -3537,7 +3572,7 @@ async function documentOutgoingRelationshipEdges(reactorClient, args, subject) {
3537
3572
  const paging = toRelationshipPagingOptions(args.paging);
3538
3573
  let result;
3539
3574
  try {
3540
- result = await reactorClient.getOutgoingRelationshipEdges(args.sourceIdentifier, fromInputMaybe(args.relationshipType), view, paging);
3575
+ result = await reactorClient.getOutgoingRelationshipEdges(args.sourceIdOrSlug, fromInputMaybe(args.relationshipType), view, paging);
3541
3576
  } catch (error) {
3542
3577
  throw new GraphQLError(`Failed to fetch outgoing relationship edges: ${error instanceof Error ? error.message : "Unknown error"}`);
3543
3578
  }
@@ -3552,7 +3587,7 @@ async function documentIncomingRelationshipEdges(reactorClient, args, subject) {
3552
3587
  const paging = toRelationshipPagingOptions(args.paging);
3553
3588
  let result;
3554
3589
  try {
3555
- result = await reactorClient.getIncomingRelationshipEdges(args.targetIdentifier, fromInputMaybe(args.relationshipType), view, paging);
3590
+ result = await reactorClient.getIncomingRelationshipEdges(args.targetIdOrSlug, fromInputMaybe(args.relationshipType), view, paging);
3556
3591
  } catch (error) {
3557
3592
  throw new GraphQLError(`Failed to fetch incoming relationship edges: ${error instanceof Error ? error.message : "Unknown error"}`);
3558
3593
  }
@@ -3685,7 +3720,7 @@ async function documentOperations(reactorClient, args, subject) {
3685
3720
  }
3686
3721
  let result;
3687
3722
  try {
3688
- result = await reactorClient.getOperations(args.filter.documentId, view, operationFilter, paging);
3723
+ result = await reactorClient.getOperations(args.filter.documentIdOrSlug, view, operationFilter, paging);
3689
3724
  } catch (error) {
3690
3725
  throw new GraphQLError(`Failed to fetch document operations: ${error instanceof Error ? error.message : "Unknown error"}`);
3691
3726
  }
@@ -3717,7 +3752,7 @@ async function evaluateActions(reactorClient, args, subject) {
3717
3752
  }));
3718
3753
  let result;
3719
3754
  try {
3720
- result = await reactorClient.evaluateActions(args.documentIdentifier, branch, candidates, subject);
3755
+ result = await reactorClient.evaluateActions(args.documentIdOrSlug, branch, candidates, subject);
3721
3756
  } catch (error) {
3722
3757
  if (AuthEnforcementDisabledError.isError(error)) throw new AuthEvaluationUnsupportedError();
3723
3758
  throw new GraphQLError(`Failed to evaluate actions: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -3734,13 +3769,13 @@ async function createDocument(reactorClient, args, reactorDriveClient, subject)
3734
3769
  if (!args.document || typeof args.document !== "object") throw new GraphQLError("Invalid document: must be an object");
3735
3770
  const document = args.document;
3736
3771
  if (!document.header || typeof document.header !== "object") throw new GraphQLError("Invalid document: missing or invalid header");
3737
- const parentIdentifier = fromInputMaybe(args.parentIdentifier);
3772
+ const parentIdOrSlug = fromInputMaybe(args.parentIdOrSlug);
3738
3773
  let result;
3739
3774
  try {
3740
- if (parentIdentifier) {
3741
- const parent = await reactorClient.get(parentIdentifier, subject && { subject });
3742
- if (isDriveContainerType(parent.header.documentType)) result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(parentIdentifier, document);
3743
- else result = await reactorClient.create(document, parentIdentifier);
3775
+ if (parentIdOrSlug) {
3776
+ const parent = await reactorClient.get(parentIdOrSlug, subject && { subject });
3777
+ if (isDriveContainerType(parent.header.documentType)) result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(parent.header.id, document);
3778
+ else result = await reactorClient.create(document, parentIdOrSlug);
3744
3779
  } else result = await reactorClient.create(document);
3745
3780
  } catch (error) {
3746
3781
  throw new GraphQLError(`Failed to create document: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -3753,18 +3788,18 @@ async function createDocument(reactorClient, args, reactorDriveClient, subject)
3753
3788
  }
3754
3789
  }
3755
3790
  async function createEmptyDocument(reactorClient, args, reactorDriveClient, subject) {
3756
- const parentIdentifier = fromInputMaybe(args.parentIdentifier);
3791
+ const parentIdOrSlug = fromInputMaybe(args.parentIdOrSlug);
3757
3792
  const name = fromInputMaybe(args.name);
3758
3793
  let result;
3759
3794
  try {
3760
- if (parentIdentifier) {
3761
- const parent = await reactorClient.get(parentIdentifier, subject && { subject });
3795
+ if (parentIdOrSlug) {
3796
+ const parent = await reactorClient.get(parentIdOrSlug, subject && { subject });
3762
3797
  if (isDriveContainerType(parent.header.documentType)) {
3763
3798
  const module = await reactorClient.getDocumentModelModule(args.documentType);
3764
3799
  const document = withSignaturePolicy(module.utils.createDocument(), await reactorClient.getCreateSignaturePolicy());
3765
3800
  if (name) document.header.name = name;
3766
- result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(parentIdentifier, document);
3767
- } else result = await reactorClient.createEmpty(args.documentType, { parentIdentifier });
3801
+ result = await pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient).addFile(parent.header.id, document);
3802
+ } else result = await reactorClient.createEmpty(args.documentType, { parentIdentifier: parentIdOrSlug });
3768
3803
  } else result = await reactorClient.createEmpty(args.documentType, {});
3769
3804
  } catch (error) {
3770
3805
  throw new GraphQLError(`Failed to create empty document: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -3777,7 +3812,7 @@ async function createEmptyDocument(reactorClient, args, reactorDriveClient, subj
3777
3812
  }
3778
3813
  }
3779
3814
  async function createDocumentWithInitialState(reactorClient, args, reactorDriveClient, subject) {
3780
- const parentIdentifier = fromInputMaybe(args.parentIdentifier);
3815
+ const parentIdOrSlug = fromInputMaybe(args.parentIdOrSlug);
3781
3816
  const name = fromInputMaybe(args.name);
3782
3817
  const slug = fromInputMaybe(args.slug);
3783
3818
  const preferredEditor = fromInputMaybe(args.preferredEditor);
@@ -3801,22 +3836,22 @@ async function createDocumentWithInitialState(reactorClient, args, reactorDriveC
3801
3836
  preferredEditor
3802
3837
  };
3803
3838
  let result;
3804
- if (parentIdentifier) {
3839
+ if (parentIdOrSlug) {
3805
3840
  let parent;
3806
3841
  try {
3807
- parent = await reactorClient.get(parentIdentifier, subject && { subject });
3842
+ parent = await reactorClient.get(parentIdOrSlug, subject && { subject });
3808
3843
  } catch (error) {
3809
3844
  throw new GraphQLError(`Parent document not found: ${error instanceof Error ? error.message : "Unknown error"}`);
3810
3845
  }
3811
3846
  if (isDriveContainerType(parent.header.documentType)) {
3812
3847
  const driveClient = pickDriveClient(reactorClient, parent.header.documentType, reactorDriveClient);
3813
3848
  try {
3814
- result = await driveClient.addFile(parentIdentifier, document);
3849
+ result = await driveClient.addFile(parent.header.id, document);
3815
3850
  } catch (error) {
3816
3851
  throw new GraphQLError(`Failed to create document in drive: ${error instanceof Error ? error.message : "Unknown error"}`);
3817
3852
  }
3818
3853
  } else try {
3819
- result = await reactorClient.create(document, parentIdentifier);
3854
+ result = await reactorClient.create(document, parentIdOrSlug);
3820
3855
  } catch (error) {
3821
3856
  throw new GraphQLError(`Failed to create document with parent: ${error instanceof Error ? error.message : "Unknown error"}`);
3822
3857
  }
@@ -3847,7 +3882,7 @@ async function execute(reactorClient, args, subject) {
3847
3882
  const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;
3848
3883
  let result;
3849
3884
  try {
3850
- result = await reactorClient.execute(args.documentIdentifier, branch, actions, void 0, subject);
3885
+ result = await reactorClient.execute(args.documentIdOrSlug, branch, actions, void 0, subject);
3851
3886
  } catch (error) {
3852
3887
  throw new GraphQLError(`Failed to execute actions: ${error instanceof Error ? error.message : "Unknown error"}`);
3853
3888
  }
@@ -3869,7 +3904,7 @@ async function executeAsync(reactorClient, args) {
3869
3904
  const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;
3870
3905
  let job;
3871
3906
  try {
3872
- job = await reactorClient.executeAsync(args.documentIdentifier, branch, actions);
3907
+ job = await reactorClient.executeAsync(args.documentIdOrSlug, branch, actions);
3873
3908
  } catch (error) {
3874
3909
  throw new GraphQLError(`Failed to submit actions: ${error instanceof Error ? error.message : "Unknown error"}`);
3875
3910
  }
@@ -3917,7 +3952,7 @@ async function renameDocument(reactorClient, args, signal, subject) {
3917
3952
  const branch = fromInputMaybe(args.branch);
3918
3953
  let result;
3919
3954
  try {
3920
- result = await reactorClient.rename(args.documentIdentifier, args.name, branch, signal);
3955
+ result = await reactorClient.rename(args.documentIdOrSlug, args.name, branch, signal);
3921
3956
  } catch (error) {
3922
3957
  throw new GraphQLError(`Failed to rename document: ${error instanceof Error ? error.message : "Unknown error"}`);
3923
3958
  }
@@ -3933,7 +3968,7 @@ async function setPreferredEditor(reactorClient, args, signal, subject) {
3933
3968
  const preferredEditor = fromInputMaybe(args.preferredEditor) ?? null;
3934
3969
  let result;
3935
3970
  try {
3936
- result = await reactorClient.setPreferredEditor(args.documentIdentifier, preferredEditor, branch, signal);
3971
+ result = await reactorClient.setPreferredEditor(args.documentIdOrSlug, preferredEditor, branch, signal);
3937
3972
  } catch (error) {
3938
3973
  throw new GraphQLError(`Failed to set preferred editor: ${error instanceof Error ? error.message : "Unknown error"}`);
3939
3974
  }
@@ -3949,7 +3984,7 @@ async function addRelationship(reactorClient, args, subject) {
3949
3984
  const metadata = fromInputMaybe(args.metadata);
3950
3985
  let result;
3951
3986
  try {
3952
- result = await reactorClient.addRelationship(args.sourceIdentifier, args.targetIdentifier, args.relationshipType, metadata, branch);
3987
+ result = await reactorClient.addRelationship(args.sourceIdOrSlug, args.targetIdOrSlug, args.relationshipType, metadata, branch);
3953
3988
  } catch (error) {
3954
3989
  throw new GraphQLError(`Failed to add relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
3955
3990
  }
@@ -3965,7 +4000,7 @@ async function updateRelationship(reactorClient, args, subject) {
3965
4000
  const metadata = fromInputMaybe(args.metadata) ?? null;
3966
4001
  let result;
3967
4002
  try {
3968
- result = await reactorClient.updateRelationship(args.sourceIdentifier, args.targetIdentifier, args.relationshipType, metadata, branch);
4003
+ result = await reactorClient.updateRelationship(args.sourceIdOrSlug, args.targetIdOrSlug, args.relationshipType, metadata, branch);
3969
4004
  } catch (error) {
3970
4005
  throw new GraphQLError(`Failed to update relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
3971
4006
  }
@@ -3980,7 +4015,7 @@ async function removeRelationship(reactorClient, args, subject) {
3980
4015
  const branch = fromInputMaybe(args.branch);
3981
4016
  let result;
3982
4017
  try {
3983
- result = await reactorClient.removeRelationship(args.sourceIdentifier, args.targetIdentifier, args.relationshipType, branch);
4018
+ result = await reactorClient.removeRelationship(args.sourceIdOrSlug, args.targetIdOrSlug, args.relationshipType, branch);
3984
4019
  } catch (error) {
3985
4020
  throw new GraphQLError(`Failed to remove relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
3986
4021
  }
@@ -3995,7 +4030,7 @@ async function moveRelationship(reactorClient, args, subject) {
3995
4030
  const branch = fromInputMaybe(args.branch);
3996
4031
  let result;
3997
4032
  try {
3998
- result = await reactorClient.moveRelationship(args.sourceParentIdentifier, args.targetParentIdentifier, args.targetIdentifier, args.relationshipType, branch);
4033
+ result = await reactorClient.moveRelationship(args.sourceParentIdOrSlug, args.targetParentIdOrSlug, args.targetIdOrSlug, args.relationshipType, branch);
3999
4034
  } catch (error) {
4000
4035
  throw new GraphQLError(`Failed to move relationship: ${error instanceof Error ? error.message : "Unknown error"}`);
4001
4036
  }
@@ -4015,9 +4050,12 @@ async function moveRelationship(reactorClient, args, subject) {
4015
4050
  async function deleteDocument(reactorClient, args, reactorDriveClient) {
4016
4051
  const propagate = toReactorPropagationMode(args.propagate);
4017
4052
  try {
4018
- const driveParent = (await reactorClient.getIncomingRelationships(args.identifier, "child")).results.find((p) => isDriveContainerType(p.header.documentType));
4019
- if (driveParent) await pickDriveClient(reactorClient, driveParent.header.documentType, reactorDriveClient).removeNode(driveParent.header.id, args.identifier);
4020
- else await reactorClient.deleteDocument(args.identifier, propagate);
4053
+ const driveParent = (await reactorClient.getIncomingRelationships(args.idOrSlug, "child")).results.find((p) => isDriveContainerType(p.header.documentType));
4054
+ if (driveParent) {
4055
+ const driveClient = pickDriveClient(reactorClient, driveParent.header.documentType, reactorDriveClient);
4056
+ const documentId = await reactorClient.resolveIdOrSlug(args.idOrSlug);
4057
+ await driveClient.removeNode(driveParent.header.id, documentId);
4058
+ } else await reactorClient.deleteDocument(args.idOrSlug, propagate);
4021
4059
  return true;
4022
4060
  } catch (error) {
4023
4061
  throw new GraphQLError(`Failed to delete document: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -4025,9 +4063,9 @@ async function deleteDocument(reactorClient, args, reactorDriveClient) {
4025
4063
  }
4026
4064
  async function deleteDocuments(reactorClient, args) {
4027
4065
  const propagate = toReactorPropagationMode(args.propagate);
4028
- const identifiers = [...args.identifiers];
4066
+ const idsOrSlugs = [...args.idsOrSlugs];
4029
4067
  try {
4030
- await reactorClient.deleteDocuments(identifiers, propagate);
4068
+ await reactorClient.deleteDocuments(idsOrSlugs, propagate);
4031
4069
  return true;
4032
4070
  } catch (error) {
4033
4071
  throw new GraphQLError(`Failed to delete documents: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -4226,6 +4264,7 @@ function pollSyncEnvelopes(syncManager, args, forbiddenIds = /* @__PURE__ */ new
4226
4264
  if (isHeld(syncOp)) continue;
4227
4265
  syncOp.deliveredCount ??= 0;
4228
4266
  syncOp.emittedCount ??= 0;
4267
+ if (!forbiddenIds.has(syncOp.documentId)) while (syncOp.deliveredCount > 0 && syncOp.operations[syncOp.deliveredCount - 1].context.ordinal > args.outboxLatest) syncOp.deliveredCount -= 1;
4229
4268
  while (syncOp.deliveredCount < syncOp.emittedCount && syncOp.operations[syncOp.deliveredCount].context.ordinal <= args.outboxLatest) syncOp.deliveredCount += 1;
4230
4269
  const remaining = syncOp.operations.slice(syncOp.deliveredCount);
4231
4270
  if (remaining.length === 0) continue;
@@ -4281,11 +4320,15 @@ function pollSyncEnvelopes(syncManager, args, forbiddenIds = /* @__PURE__ */ new
4281
4320
  ...revisions
4282
4321
  };
4283
4322
  }
4323
+ const MARKER_REFUSAL = "marker";
4284
4324
  /**
4285
4325
  * The client's UNSUPPORTED_PROTOCOL refusals of polled rows. Each becomes a hold
4286
4326
  * for that client, as a pushed refusal does, rather than counting as delivered.
4327
+ * A refused marker is not a hold: {@link recordPollMarkerRefusals} takes it.
4328
+ * A kind this server does not know is ignored.
4287
4329
  */
4288
- function holdPollRefusals(syncManager, channelId, refusals) {
4330
+ function holdPollRefusals(syncManager, channelId, all) {
4331
+ const refusals = all?.filter((refusal) => refusal.kind === void 0 || refusal.kind === null);
4289
4332
  if (!refusals?.length) return;
4290
4333
  let remote;
4291
4334
  try {
@@ -4301,6 +4344,30 @@ function holdPollRefusals(syncManager, channelId, refusals) {
4301
4344
  remote.channel.deadLetter.add(...refused);
4302
4345
  }
4303
4346
  /**
4347
+ * The client's refusals of purge markers it polled. Persisted before the poll is
4348
+ * served; a failure fails the poll, and the client reports them again. The sync
4349
+ * manager keeps only refusals of markers this remote was owed.
4350
+ */
4351
+ async function recordPollMarkerRefusals(syncManager, channelId, all) {
4352
+ const refusals = all?.filter((refusal) => refusal.kind === MARKER_REFUSAL);
4353
+ if (!refusals?.length) return;
4354
+ if (!supportsPurgeRefusals(syncManager)) return;
4355
+ let remote;
4356
+ try {
4357
+ remote = syncManager.getById(channelId);
4358
+ } catch {
4359
+ return;
4360
+ }
4361
+ try {
4362
+ await syncManager.recordPolledMarkerRefusals(remote.meta.name, refusals.map(({ documentId, branch }) => ({
4363
+ documentId,
4364
+ branch
4365
+ })));
4366
+ } catch (error) {
4367
+ throw new RefusalNotRecordedError(error);
4368
+ }
4369
+ }
4370
+ /**
4304
4371
  * A poll naming no revision is from a client without peer agreement: it is
4305
4372
  * recorded silent, and what it can no longer run is held, before it is served.
4306
4373
  */
@@ -4322,7 +4389,7 @@ async function silenceUnversionedPoll(syncManager, channelId, manifestRevision)
4322
4389
  * It must be preserved because the inbox mailbox tracks applied ordinals
4323
4390
  * and returns the highest one as `ackOrdinal` in pollSyncEnvelopes.
4324
4391
  */
4325
- function pushSyncEnvelopes(syncManager, args) {
4392
+ async function pushSyncEnvelopes(syncManager, args) {
4326
4393
  const remoteSyncOps = /* @__PURE__ */ new Map();
4327
4394
  for (const envelope of args.envelopes) {
4328
4395
  let remote;
@@ -4343,7 +4410,12 @@ function pushSyncEnvelopes(syncManager, args) {
4343
4410
  for (const syncOp of consolidated) syncOp.jobDependencies = syncOp.jobDependencies.filter((dep) => validKeys.has(dep));
4344
4411
  remote.channel.inbox.add(...consolidated);
4345
4412
  }
4346
- return Promise.resolve(true);
4413
+ try {
4414
+ await syncManager.receiptsStored?.([...remoteSyncOps.keys()].map((remote) => remote.meta.name));
4415
+ } catch (error) {
4416
+ throw new GraphQLError(`Failed to store received markers: ${error instanceof Error ? error.message : String(error)}`);
4417
+ }
4418
+ return true;
4347
4419
  }
4348
4420
  //#endregion
4349
4421
  //#region src/graphql/document-model-subgraph.ts
@@ -4435,13 +4507,14 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
4435
4507
  Query: { [documentName]: () => ({}) },
4436
4508
  [`${documentName}Queries`]: {
4437
4509
  document: async (_, args, ctx) => {
4438
- const { identifier, view } = args;
4439
- if (!identifier) throw new GraphQLError("Document identifier is required");
4510
+ const idOrSlug = requireOneOf(args, "idOrSlug", "identifier");
4511
+ const { view } = args;
4512
+ if (!idOrSlug) throw new GraphQLError("Document identifier is required");
4440
4513
  const result = await document(this.reactorClient, {
4441
- identifier,
4514
+ idOrSlug,
4442
4515
  view
4443
4516
  }, this.viewSubject(ctx));
4444
- if (result.document.documentType !== documentType) throw new GraphQLError(`Document with id ${identifier} is not of type ${documentType}`);
4517
+ if (result.document.documentType !== documentType) throw new GraphQLError(`Document with id ${idOrSlug} is not of type ${documentType}`);
4445
4518
  await this.assertCanReadCanonical(result.document.id, ctx);
4446
4519
  return result;
4447
4520
  },
@@ -4466,10 +4539,11 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
4466
4539
  return this.#readableItems(result, ctx);
4467
4540
  },
4468
4541
  documentOutgoingRelationships: async (_, args, ctx) => {
4542
+ const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
4469
4543
  const { relationshipType, view, paging } = args;
4470
- const handle = await this.assertCanRead(args.sourceIdentifier, ctx);
4544
+ const handle = await this.assertCanRead(sourceIdOrSlug, ctx);
4471
4545
  const result = await documentOutgoingRelationships(this.reactorClient, {
4472
- sourceIdentifier: handle.fetchIdentifier,
4546
+ sourceIdOrSlug: handle.fetchIdentifier,
4473
4547
  relationshipType,
4474
4548
  view,
4475
4549
  paging
@@ -4482,10 +4556,11 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
4482
4556
  };
4483
4557
  },
4484
4558
  documentIncomingRelationships: async (_, args, ctx) => {
4559
+ const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
4485
4560
  const { relationshipType, view, paging } = args;
4486
- const handle = await this.assertCanRead(args.targetIdentifier, ctx);
4561
+ const handle = await this.assertCanRead(targetIdOrSlug, ctx);
4487
4562
  const result = await documentIncomingRelationships(this.reactorClient, {
4488
- targetIdentifier: handle.fetchIdentifier,
4563
+ targetIdOrSlug: handle.fetchIdentifier,
4489
4564
  relationshipType,
4490
4565
  view,
4491
4566
  paging
@@ -4497,13 +4572,13 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
4497
4572
  [`${documentName}Mutations`]: {
4498
4573
  createDocument: async (_, args, ctx) => {
4499
4574
  const { name, slug, preferredEditor, initialState } = args;
4500
- let parentIdentifier = args.parentIdentifier;
4501
- if (parentIdentifier) parentIdentifier = (await this.assertCanWrite(parentIdentifier, ctx)).fetchIdentifier;
4575
+ let parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
4576
+ if (parentIdOrSlug) parentIdOrSlug = (await this.assertCanWrite(parentIdOrSlug, ctx)).fetchIdentifier;
4502
4577
  else this.assertCanCreate(ctx);
4503
4578
  let createdDoc;
4504
4579
  if (initialState || preferredEditor) createdDoc = await createDocumentWithInitialState(this.reactorClient, {
4505
4580
  documentType,
4506
- parentIdentifier,
4581
+ parentIdOrSlug,
4507
4582
  name,
4508
4583
  slug,
4509
4584
  preferredEditor,
@@ -4511,7 +4586,7 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
4511
4586
  }, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
4512
4587
  else createdDoc = await createEmptyDocument(this.reactorClient, {
4513
4588
  documentType,
4514
- parentIdentifier,
4589
+ parentIdOrSlug,
4515
4590
  name
4516
4591
  }, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
4517
4592
  if (ctx.user?.address && createdDoc?.id) await this.documentPermissionService?.initializeDocumentProtection(createdDoc.id, ctx.user.address, this.authorizationService.config.defaultProtection);
@@ -4519,21 +4594,22 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
4519
4594
  return createdDoc;
4520
4595
  },
4521
4596
  createEmptyDocument: async (_, args, ctx) => {
4522
- let parentIdentifier = args.parentIdentifier;
4523
- if (parentIdentifier) parentIdentifier = (await this.assertCanWrite(parentIdentifier, ctx)).fetchIdentifier;
4597
+ let parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
4598
+ if (parentIdOrSlug) parentIdOrSlug = (await this.assertCanWrite(parentIdOrSlug, ctx)).fetchIdentifier;
4524
4599
  else this.assertCanCreate(ctx);
4525
4600
  const result = await createEmptyDocument(this.reactorClient, {
4526
4601
  documentType,
4527
- parentIdentifier
4602
+ parentIdOrSlug
4528
4603
  }, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
4529
4604
  if (ctx.user?.address && result?.id) await this.documentPermissionService?.initializeDocumentProtection(result.id, ctx.user.address, this.authorizationService.config.defaultProtection);
4530
4605
  return result;
4531
4606
  },
4532
4607
  ...operations.reduce((mutations, op) => {
4533
4608
  mutations[camelCase(op.name)] = async (_, args, ctx) => {
4534
- const { docId, input } = args;
4535
- const effectiveDocId = (await this.assertCanExecuteOperation(docId, op.name, ctx)).fetchIdentifier;
4536
- if ((await this.reactorClient.get(effectiveDocId, { subject: this.viewSubject(ctx) })).header.documentType !== documentType) throw new GraphQLError(`Document with id ${docId} is not of type ${documentType}`);
4609
+ const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "docId");
4610
+ const { input } = args;
4611
+ const effectiveDocId = (await this.assertCanExecuteOperation(documentIdOrSlug, op.name, ctx)).fetchIdentifier;
4612
+ if ((await this.reactorClient.get(effectiveDocId, { subject: this.viewSubject(ctx) })).header.documentType !== documentType) throw new GraphQLError(`Document with id ${documentIdOrSlug} is not of type ${documentType}`);
4537
4613
  const action = this.documentModel.actions[camelCase(op.name)];
4538
4614
  if (!action) throw new GraphQLError(`Action ${op.name} not found`);
4539
4615
  try {
@@ -4543,9 +4619,10 @@ var DocumentModelSubgraph = class extends BaseSubgraph {
4543
4619
  }
4544
4620
  };
4545
4621
  mutations[`${camelCase(op.name)}Async`] = async (_, args, ctx) => {
4546
- const { docId, input } = args;
4547
- const effectiveDocId = (await this.assertCanExecuteOperation(docId, op.name, ctx)).fetchIdentifier;
4548
- if ((await this.reactorClient.get(effectiveDocId, { subject: this.viewSubject(ctx) })).header.documentType !== documentType) throw new GraphQLError(`Document with id ${docId} is not of type ${documentType}`);
4622
+ const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "docId");
4623
+ const { input } = args;
4624
+ const effectiveDocId = (await this.assertCanExecuteOperation(documentIdOrSlug, op.name, ctx)).fetchIdentifier;
4625
+ if ((await this.reactorClient.get(effectiveDocId, { subject: this.viewSubject(ctx) })).header.documentType !== documentType) throw new GraphQLError(`Document with id ${documentIdOrSlug} is not of type ${documentType}`);
4549
4626
  const action = this.documentModel.actions[camelCase(op.name)];
4550
4627
  if (!action) throw new GraphQLError(`Action ${op.name} not found`);
4551
4628
  try {
@@ -5870,7 +5947,7 @@ function createReactorGraphQLClient(url, fetchImpl = fetch, headers) {
5870
5947
  }
5871
5948
  //#endregion
5872
5949
  //#region src/graphql/reactor/schema.graphql
5873
- var schema_default = "# Scalar types (for codegen - also defined in create-schema.ts)\nscalar JSONObject\nscalar DateTime\n\n# Input types\ninput PagingInput {\n limit: Int\n offset: Int\n cursor: String\n}\n\ninput ViewFilterInput {\n branch: String\n scopes: [String!]\n}\n\ninput SearchFilterInput {\n type: String\n parentId: String\n identifiers: [String!]\n}\n\ninput OperationsFilterInput {\n documentId: String!\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\ninput DocumentOperationsFilterInput {\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\n# Enums\nenum PropagationMode {\n CASCADE\n ORPHAN\n}\n\nenum DocumentChangeType {\n CREATED\n DELETED\n UPDATED\n PARENT_ADDED\n PARENT_REMOVED\n CHILD_ADDED\n CHILD_REMOVED\n}\n\n# Object types\ntype DocumentModelGlobalState {\n id: String!\n name: String!\n namespace: String\n version: String\n specification: JSONObject!\n}\n\ntype DocumentModelResultPage {\n items: [DocumentModelGlobalState!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype Revision {\n scope: String!\n revision: Int!\n}\n\ntype PHDocument {\n id: String!\n slug: String\n preferredEditor: String\n name: String!\n documentType: String!\n state: JSONObject!\n revisionsList: [Revision!]!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(\n filter: DocumentOperationsFilterInput\n paging: PagingInput\n ): ReactorOperationResultPage\n}\n\ntype PHDocumentResultPage {\n items: [PHDocument!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\n# A directed edge between two documents, with the metadata recorded against it.\ntype DocumentRelationship {\n sourceId: String!\n targetId: String!\n relationshipType: String!\n metadata: JSONObject\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\ntype DocumentRelationshipResultPage {\n items: [DocumentRelationship!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype ReactorOperationResultPage {\n items: [ReactorOperation!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype DeadLetterInfo {\n documentId: String!\n error: String!\n \"\"\"\n How the origin classified the failure. A peer needs this to mirror the origin's\n quarantine decision; without it a held auth operation would freeze the document\n on the peer side while the origin kept syncing.\n \"\"\"\n errorType: String\n jobId: String!\n branch: String!\n scopes: [String!]!\n operationCount: Int!\n}\n\ntype PollSyncEnvelopesResult {\n envelopes: [SyncEnvelope!]!\n ackOrdinal: Int!\n deadLetters: [DeadLetterInfo!]!\n hasMore: Boolean!\n # The server's current manifest revision\n manifestRevision: String\n # The client's manifest revision as the server holds it\n peerManifestRevision: String\n}\n\ntype SyncHoldReason {\n protocol: String!\n version: Int!\n peerSupports: [Int!]!\n}\n\n# A document held back from a remote whose peer cannot run its versions\ntype SyncHold {\n remoteName: String!\n documentId: String!\n branch: String!\n reason: SyncHoldReason!\n heldAtUtcMs: String!\n}\n\ntype PeerAgreementMember {\n remoteName: String!\n # False for a peer that announced nothing: it gets the baselines\n announced: Boolean!\n protocols: JSONObject!\n features: JSONObject!\n}\n\ntype PeerAgreementLimit {\n protocol: String!\n # The remotes whose peers lack the version new documents would take\n remoteNames: [String!]!\n}\n\ntype PeerAgreement {\n collectionId: String!\n local: JSONObject!\n members: [PeerAgreementMember!]!\n limitedBy: [PeerAgreementLimit!]!\n}\n\ntype DocumentWithChildren {\n document: PHDocument!\n childIds: [String!]!\n}\n\ntype MoveRelationshipResult {\n source: PHDocument!\n target: PHDocument!\n}\n\ntype JobInfo {\n id: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Null until then, which\n is the state every job is in when it is handed back from a submission.\n \"\"\"\n result: JSONObject\n\n error: String\n createdAt: DateTime!\n completedAt: DateTime\n}\n\ntype DocumentChangeEvent {\n type: DocumentChangeType!\n documents: [PHDocument!]!\n context: DocumentChangeContext\n}\n\ntype DocumentChangeContext {\n parentId: String\n childId: String\n}\n\ntype JobChangeEvent {\n jobId: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Nullable for the same\n reason as `JobInfo.result`: a job that has not written yet has produced\n nothing, and an empty object would claim otherwise.\n \"\"\"\n result: JSONObject\n\n error: String\n}\n\ntype ReactorSignerUser {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ntype ReactorSignerApp {\n name: String!\n key: String!\n}\n\ntype ReactorSigner {\n user: ReactorSignerUser\n app: ReactorSignerApp\n signatures: [String!]!\n}\n\ntype ActionContext {\n signer: ReactorSigner\n}\n\ntype Action {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContext\n}\n\n\"\"\"\nOne operation an authorization preflight predicts a verdict for.\n\n`input` is what a conditional grant reads, so a candidate standing for a\nfilled-in form carries that form's input. Omitting it predicts the verdict an\nempty input earns, not the verdict the filled-in form will get.\n\"\"\"\ninput ActionCandidateInput {\n scope: String!\n type: String!\n input: JSONObject\n}\n\nenum AuthDecision {\n ALLOW\n DENY\n}\n\n\"\"\"\nOne candidate's predicted verdict. `reason` carries the refusal a DENY is\nrecorded with, and is null on an ALLOW.\n\"\"\"\ntype ActionEvaluation {\n decision: AuthDecision!\n reason: String\n}\n\n\"\"\"\nThe predicted verdicts for a set of candidates, in the order they were given,\nwith the aggregates a caller branches on.\n\nThe aggregates are redundant -- a verdict is binary -- and all four are returned\nso a caller reads the one its question is phrased in rather than negating\nanother. Over no candidates every aggregate is false: nothing is allowed and\nnothing is denied.\n\"\"\"\ntype ActionEvaluations {\n evaluations: [ActionEvaluation!]!\n allAllowed: Boolean!\n anyAllowed: Boolean!\n allDenied: Boolean!\n anyDenied: Boolean!\n}\n\n# Input types for sync operations\n\"\"\"\nAn action's context, as a caller submits it.\n\nDeclares every field `ActionContext` carries, because an input object rejects a\nfield it does not declare: an action stamped with the head it applies to - which\nis what a signing client sends - is refused outright if these are missing, and\nthat refusal is a whole-request one, not a per-field one.\n\n`prevOpHash` and `prevOpIndex` are the scope head the action was composed\nagainst. They are recorded rather than enforced; a signature is verified from\nthe params carried in its own tuple, which do not include them.\n\"\"\"\ninput ActionContextInput {\n \"\"\"\n The index of the last operation in the scope the action applies to.\n \"\"\"\n prevOpIndex: Int\n\n \"\"\"\n The hash of the state the action applies to.\n \"\"\"\n prevOpHash: String\n\n \"\"\"\n Covers replay of an operation that would otherwise be a no-op.\n \"\"\"\n nonce: String\n\n signer: ReactorSignerInput\n}\n\ninput ReactorSignerInput {\n user: ReactorSignerUserInput\n app: ReactorSignerAppInput\n signatures: [String!]!\n}\n\ninput ReactorSignerUserInput {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ninput ReactorSignerAppInput {\n name: String!\n key: String!\n}\n\ninput ActionInput {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContextInput\n}\n\n# Synchronization types\ntype ReactorOperation {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: Action!\n}\n\ninput OperationInput {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: ActionInput!\n}\n\ntype OperationContext {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ninput OperationContextInput {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ntype OperationWithContext {\n operation: ReactorOperation!\n context: OperationContext!\n}\n\ninput OperationWithContextInput {\n operation: OperationInput!\n context: OperationContextInput!\n}\n\ntype ChannelMeta {\n id: String!\n}\n\ninput ChannelMetaInput {\n id: String!\n}\n\ntype RemoteCursor {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\ninput RemoteCursorInput {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\nenum SyncEnvelopeType {\n OPERATIONS\n ACK\n}\n\ntype SyncEnvelope {\n type: SyncEnvelopeType!\n channelMeta: ChannelMeta!\n operations: [OperationWithContext!]\n cursor: RemoteCursor\n key: String\n dependsOn: [String!]\n}\n\ninput SyncEnvelopeInput {\n type: SyncEnvelopeType!\n channelMeta: ChannelMetaInput!\n operations: [OperationWithContextInput!]\n cursor: RemoteCursorInput\n key: String\n dependsOn: [String!]\n}\n\ninput RemoteFilterInput {\n documentId: [String!]!\n scope: [String!]!\n branch: String!\n}\n\ninput SyncRefusalInput {\n documentId: String!\n branch: String!\n}\n\ninput TouchChannelInput {\n id: String!\n name: String!\n collectionId: String!\n filter: RemoteFilterInput!\n sinceTimestampUtcMs: String!\n # The client's peer manifest; absent from a client without peer agreement\n manifest: JSONObject\n}\n\ntype TouchChannelResult {\n success: Boolean!\n ackOrdinal: Int!\n # The server's peer manifest\n manifest: JSONObject\n}\n\ntype Query {\n # Get document models for a namespace\n documentModels(\n namespace: String\n paging: PagingInput\n ): DocumentModelResultPage!\n\n # Get a specific document by ID or slug\n document(identifier: String!, view: ViewFilterInput): DocumentWithChildren\n\n # Get outgoing relationships of a given type from a source document\n documentOutgoingRelationships(\n sourceIdentifier: String!\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get incoming relationships of a given type to a target document\n documentIncomingRelationships(\n targetIdentifier: String!\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get the outgoing relationship edges of a source document. Unlike\n # documentOutgoingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentOutgoingRelationshipEdges(\n sourceIdentifier: String!\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Get the incoming relationship edges of a target document. Unlike\n # documentIncomingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentIncomingRelationshipEdges(\n targetIdentifier: String!\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Find documents by search criteria\n findDocuments(\n search: SearchFilterInput\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get job status\n jobStatus(jobId: String!): JobInfo\n\n # Get operations for a document with filtering and pagination\n documentOperations(\n filter: OperationsFilterInput!\n paging: PagingInput\n ): ReactorOperationResultPage!\n\n \"\"\"\n Predicts whether the calling subject would be admitted to execute each of a\n set of candidate operations, without submitting any of them. A UI asks this to\n disable a control rather than offer an action that fails on submit.\n\n The answer is a prediction, not a promise:\n\n - Real admission compiles an append condition over everything it read and the\n store enforces it at write time. A preflight reads no future, so a policy\n change landing between this answer and the submit changes the verdict. The\n submit path stays the only authority.\n - The verdict is evaluated at the stream heads, so it is correct for a\n candidate about to be submitted. A backdated submission is out of contract;\n the reactor decides that one by position.\n - A candidate whose verdict depends on its input has to carry that input, since\n a conditional grant reads it.\n\n The subject is the authenticated caller and cannot be named in the request:\n answering for an arbitrary subject would disclose what a policy grants\n somebody else. It carries both the caller's address and the did:key of the app\n instance whose token authenticated the request, so a policy naming either\n matches the same principal the write path presents.\n\n Requires the reactor's authEnforcement feature flag. Without it the reactor\n holds no decision model, so this fails with extensions.code\n AUTH_EVALUATION_UNSUPPORTED rather than guessing.\n \"\"\"\n evaluateActions(\n documentIdentifier: String!\n branch: String\n candidates: [ActionCandidateInput!]!\n ): ActionEvaluations!\n\n \"\"\"\n Polls for sync envelopes from a channel.\n\n An operation stored before the API required an action id cannot be\n represented by this schema, and rather than serving a partial response beside\n a bare non-null violation, this fails with extensions.code\n MALFORMED_STORED_OPERATION naming the operation. That code means the failure\n is worth polling through: the document holding the operation needs repairing,\n but the channel serves every other document, and a peer that stopped polling\n would stop receiving those too.\n \"\"\"\n pollSyncEnvelopes(\n channelId: String!\n outboxAck: Int!\n outboxLatest: Int!\n # The client's manifest revision; absent from a client without peer agreement\n manifestRevision: String\n # Documents the client refused as UNSUPPORTED_PROTOCOL from earlier polls\n refusals: [SyncRefusalInput!]\n ): PollSyncEnvelopesResult!\n\n # Supreme admin, or the address the named remote's channel is bound to\n syncHolds(remoteName: String, documentId: String): [SyncHold!]!\n\n # Supreme admin, or an address bound to a channel in the collection\n peerAgreement(collectionId: String!): PeerAgreement!\n}\n\ntype Mutation {\n # Create a new document\n createDocument(document: JSONObject!, parentIdentifier: String): PHDocument!\n\n # Create an empty document of specified type\n createEmptyDocument(\n documentType: String!\n parentIdentifier: String\n ): PHDocument!\n\n \"\"\"\n Applies actions to a document and waits for the result.\n\n Each action is coerced against `ActionInput`, so one missing a field the wire\n declares is refused before any work starts. The id in particular: it is hashed\n into the operation id and replay dedupes by it, so an action without one is\n stored under an operation id shared by every id-less operation on the same\n document, scope and branch.\n\n Named for `IReactorClient.execute`, which this is the wire form of. `branch`\n defaults to `main`.\n \"\"\"\n execute(\n documentIdentifier: String!\n actions: [ActionInput!]!\n branch: String\n ): PHDocument!\n\n \"\"\"\n Submits actions to a document and returns the job that will apply them.\n\n Coerced exactly as `execute` is, so a malformed action is refused here rather\n than surfacing later as a failed job. Returns the job rather than only its id,\n so a caller has the status and the creation time it would otherwise have to\n ask for; `result` is null until the job produces one.\n \"\"\"\n executeAsync(\n documentIdentifier: String!\n actions: [ActionInput!]!\n branch: String\n ): JobInfo!\n\n # Apply actions to a document (synchronous)\n mutateDocument(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): PHDocument!\n @deprecated(\n reason: \"Use execute. Actions here are untyped, so a malformed one is refused by a hand-written check rather than by the schema, and `view.scopes` is accepted but ignored.\"\n )\n\n # Submit actions to a document (asynchronous)\n mutateDocumentAsync(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): String!\n @deprecated(\n reason: \"Use executeAsync, which is typed and returns the job rather than only its id.\"\n )\n\n # Rename a document\n renameDocument(\n documentIdentifier: String!\n name: String!\n branch: String\n ): PHDocument!\n\n # Update the preferred editor recorded in the document header meta.\n # Pass null/omit to clear it.\n setPreferredEditor(\n documentIdentifier: String!\n preferredEditor: String\n branch: String\n ): PHDocument!\n\n # Add a relationship between two documents. Adding one that already exists is\n # a no-op, metadata included -- use updateRelationship to change an edge.\n addRelationship(\n sourceIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Replace the metadata of an existing relationship, preserving its createdAt.\n # Omitting metadata, or passing null, clears it.\n updateRelationship(\n sourceIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Remove a relationship between two documents\n removeRelationship(\n sourceIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n branch: String\n ): PHDocument!\n\n # Move a relationship from one source to another\n moveRelationship(\n sourceParentIdentifier: String!\n targetParentIdentifier: String!\n targetIdentifier: String!\n relationshipType: String!\n branch: String\n ): MoveRelationshipResult!\n\n # Delete a single document\n deleteDocument(identifier: String!, propagate: PropagationMode): Boolean!\n\n # Delete multiple documents\n deleteDocuments(identifiers: [String!]!, propagate: PropagationMode): Boolean!\n\n # Touch (create or update) a channel for sync\n touchChannel(input: TouchChannelInput!): TouchChannelResult!\n\n # Push sync envelopes to a channel\n pushSyncEnvelopes(\n envelopes: [SyncEnvelopeInput!]!\n # The server's manifest revision the client gated these envelopes under\n peerManifestRevision: String\n ): Boolean!\n}\n\ntype Subscription {\n # Subscribe to document changes\n documentChanges(\n search: SearchFilterInput\n view: ViewFilterInput\n ): DocumentChangeEvent!\n\n # Subscribe to job changes\n jobChanges(jobId: String!): JobChangeEvent!\n}\n";
5950
+ var schema_default = "# Scalar types (for codegen - also defined in create-schema.ts)\nscalar JSONObject\nscalar DateTime\n\n# Input types\ninput PagingInput {\n limit: Int\n offset: Int\n cursor: String\n}\n\ninput ViewFilterInput {\n branch: String\n scopes: [String!]\n}\n\ninput SearchFilterInput {\n type: String\n parentId: String\n identifiers: [String!]\n @deprecated(reason: \"Ignored. Filter by type or parentId.\")\n}\n\ninput OperationsFilterInput {\n documentIdOrSlug: String\n documentId: String @deprecated(reason: \"Use documentIdOrSlug.\")\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\ninput DocumentOperationsFilterInput {\n branch: String\n scopes: [String!]\n actionTypes: [String!]\n sinceRevision: Int\n timestampFrom: String\n timestampTo: String\n}\n\n# Enums\nenum PropagationMode {\n CASCADE\n ORPHAN\n}\n\nenum DocumentChangeType {\n CREATED\n DELETED\n UPDATED\n PARENT_ADDED\n PARENT_REMOVED\n CHILD_ADDED\n CHILD_REMOVED\n}\n\n# Object types\ntype DocumentModelGlobalState {\n id: String!\n name: String!\n namespace: String\n version: String\n specification: JSONObject!\n}\n\ntype DocumentModelResultPage {\n items: [DocumentModelGlobalState!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype Revision {\n scope: String!\n revision: Int!\n}\n\ntype PHDocument {\n id: String!\n slug: String\n preferredEditor: String\n name: String!\n documentType: String!\n state: JSONObject!\n revisionsList: [Revision!]!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(\n filter: DocumentOperationsFilterInput\n paging: PagingInput\n ): ReactorOperationResultPage\n}\n\ntype PHDocumentResultPage {\n items: [PHDocument!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\n# A directed edge between two documents, with the metadata recorded against it.\ntype DocumentRelationship {\n sourceId: String!\n targetId: String!\n relationshipType: String!\n metadata: JSONObject\n createdAt: DateTime!\n updatedAt: DateTime!\n}\n\ntype DocumentRelationshipResultPage {\n items: [DocumentRelationship!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype ReactorOperationResultPage {\n items: [ReactorOperation!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n}\n\ntype DeadLetterInfo {\n documentId: String!\n error: String!\n \"\"\"\n How the origin classified the failure. A peer needs this to mirror the origin's\n quarantine decision; without it a held auth operation would freeze the document\n on the peer side while the origin kept syncing.\n \"\"\"\n errorType: String\n jobId: String!\n branch: String!\n scopes: [String!]!\n operationCount: Int!\n}\n\ntype PollSyncEnvelopesResult {\n envelopes: [SyncEnvelope!]!\n ackOrdinal: Int!\n deadLetters: [DeadLetterInfo!]!\n hasMore: Boolean!\n # The server's current manifest revision\n manifestRevision: String\n # The client's manifest revision as the server holds it\n peerManifestRevision: String\n}\n\ntype SyncHoldReason {\n protocol: String!\n version: Int!\n peerSupports: [Int!]!\n}\n\n# A document held back from a remote whose peer cannot run its versions\ntype SyncHold {\n remoteName: String!\n documentId: String!\n branch: String!\n reason: SyncHoldReason!\n heldAtUtcMs: String!\n}\n\ntype PeerAgreementMember {\n remoteName: String!\n # False for a peer that announced nothing: it gets the baselines\n announced: Boolean!\n protocols: JSONObject!\n features: JSONObject!\n}\n\ntype PeerAgreementLimit {\n protocol: String!\n # The remotes whose peers lack the version new documents would take\n remoteNames: [String!]!\n}\n\ntype PeerAgreement {\n collectionId: String!\n local: JSONObject!\n members: [PeerAgreementMember!]!\n limitedBy: [PeerAgreementLimit!]!\n}\n\ntype DocumentWithChildren {\n document: PHDocument!\n childIds: [String!]!\n}\n\ntype MoveRelationshipResult {\n source: PHDocument!\n target: PHDocument!\n}\n\ntype JobInfo {\n id: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Null until then, which\n is the state every job is in when it is handed back from a submission.\n \"\"\"\n result: JSONObject\n\n error: String\n createdAt: DateTime!\n completedAt: DateTime\n}\n\ntype DocumentChangeEvent {\n type: DocumentChangeType!\n documents: [PHDocument!]!\n context: DocumentChangeContext\n}\n\ntype DocumentChangeContext {\n parentId: String\n childId: String\n}\n\ntype JobChangeEvent {\n jobId: String!\n status: String!\n\n \"\"\"\n What the job produced, once it has produced anything. Nullable for the same\n reason as `JobInfo.result`: a job that has not written yet has produced\n nothing, and an empty object would claim otherwise.\n \"\"\"\n result: JSONObject\n\n error: String\n}\n\ntype ReactorSignerUser {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ntype ReactorSignerApp {\n name: String!\n key: String!\n}\n\ntype ReactorSigner {\n user: ReactorSignerUser\n app: ReactorSignerApp\n signatures: [String!]!\n}\n\ntype ActionContext {\n signer: ReactorSigner\n}\n\ntype Action {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContext\n}\n\n\"\"\"\nOne operation an authorization preflight predicts a verdict for.\n\n`input` is what a conditional grant reads, so a candidate standing for a\nfilled-in form carries that form's input. Omitting it predicts the verdict an\nempty input earns, not the verdict the filled-in form will get.\n\"\"\"\ninput ActionCandidateInput {\n scope: String!\n type: String!\n input: JSONObject\n}\n\nenum AuthDecision {\n ALLOW\n DENY\n}\n\n\"\"\"\nOne candidate's predicted verdict. `reason` carries the refusal a DENY is\nrecorded with, and is null on an ALLOW.\n\"\"\"\ntype ActionEvaluation {\n decision: AuthDecision!\n reason: String\n}\n\n\"\"\"\nThe predicted verdicts for a set of candidates, in the order they were given,\nwith the aggregates a caller branches on.\n\nThe aggregates are redundant -- a verdict is binary -- and all four are returned\nso a caller reads the one its question is phrased in rather than negating\nanother. Over no candidates every aggregate is false: nothing is allowed and\nnothing is denied.\n\"\"\"\ntype ActionEvaluations {\n evaluations: [ActionEvaluation!]!\n allAllowed: Boolean!\n anyAllowed: Boolean!\n allDenied: Boolean!\n anyDenied: Boolean!\n}\n\n# Input types for sync operations\n\"\"\"\nAn action's context, as a caller submits it.\n\nDeclares every field `ActionContext` carries, because an input object rejects a\nfield it does not declare: an action stamped with the head it applies to - which\nis what a signing client sends - is refused outright if these are missing, and\nthat refusal is a whole-request one, not a per-field one.\n\n`prevOpHash` and `prevOpIndex` are the scope head the action was composed\nagainst. They are recorded rather than enforced; a signature is verified from\nthe params carried in its own tuple, which do not include them.\n\"\"\"\ninput ActionContextInput {\n \"\"\"\n The index of the last operation in the scope the action applies to.\n \"\"\"\n prevOpIndex: Int\n\n \"\"\"\n The hash of the state the action applies to.\n \"\"\"\n prevOpHash: String\n\n \"\"\"\n Covers replay of an operation that would otherwise be a no-op.\n \"\"\"\n nonce: String\n\n signer: ReactorSignerInput\n}\n\ninput ReactorSignerInput {\n user: ReactorSignerUserInput\n app: ReactorSignerAppInput\n signatures: [String!]!\n}\n\ninput ReactorSignerUserInput {\n address: String!\n networkId: String!\n chainId: Int!\n}\n\ninput ReactorSignerAppInput {\n name: String!\n key: String!\n}\n\ninput ActionInput {\n id: String!\n type: String!\n timestampUtcMs: String!\n input: JSONObject!\n scope: String!\n context: ActionContextInput\n}\n\n# Synchronization types\ntype ReactorOperation {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: Action!\n}\n\ninput OperationInput {\n index: Int!\n timestampUtcMs: String!\n hash: String!\n skip: Int!\n error: String\n deniedReason: String\n id: String\n action: ActionInput!\n}\n\ntype OperationContext {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ninput OperationContextInput {\n documentId: String!\n documentType: String!\n scope: String!\n branch: String!\n ordinal: Int!\n}\n\ntype OperationWithContext {\n operation: ReactorOperation!\n context: OperationContext!\n}\n\ninput OperationWithContextInput {\n operation: OperationInput!\n context: OperationContextInput!\n}\n\ntype ChannelMeta {\n id: String!\n}\n\ninput ChannelMetaInput {\n id: String!\n}\n\ntype RemoteCursor {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\ninput RemoteCursorInput {\n remoteName: String!\n cursorOrdinal: Int!\n lastSyncedAtUtcMs: String\n}\n\nenum SyncEnvelopeType {\n OPERATIONS\n ACK\n}\n\ntype SyncEnvelope {\n type: SyncEnvelopeType!\n channelMeta: ChannelMeta!\n operations: [OperationWithContext!]\n cursor: RemoteCursor\n key: String\n dependsOn: [String!]\n}\n\ninput SyncEnvelopeInput {\n type: SyncEnvelopeType!\n channelMeta: ChannelMetaInput!\n operations: [OperationWithContextInput!]\n cursor: RemoteCursorInput\n key: String\n dependsOn: [String!]\n}\n\ninput RemoteFilterInput {\n documentId: [String!]!\n scope: [String!]!\n branch: String!\n}\n\ninput SyncRefusalInput {\n documentId: String!\n branch: String!\n # \"marker\" for a refused purge marker; absent for UNSUPPORTED_PROTOCOL\n kind: String\n}\n\ninput TouchChannelInput {\n id: String!\n name: String!\n collectionId: String!\n filter: RemoteFilterInput!\n sinceTimestampUtcMs: String!\n # The client's peer manifest; absent from a client without peer agreement\n manifest: JSONObject\n}\n\ntype TouchChannelResult {\n success: Boolean!\n ackOrdinal: Int!\n # The server's peer manifest\n manifest: JSONObject\n}\n\ntype Query {\n # Get document models for a namespace\n documentModels(\n namespace: String\n paging: PagingInput\n ): DocumentModelResultPage!\n\n # Get a specific document by ID or slug\n document(\n idOrSlug: String\n identifier: String @deprecated(reason: \"Use idOrSlug.\")\n view: ViewFilterInput\n ): DocumentWithChildren\n\n # Get outgoing relationships of a given type from a source document\n documentOutgoingRelationships(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get incoming relationships of a given type to a target document\n documentIncomingRelationships(\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get the outgoing relationship edges of a source document. Unlike\n # documentOutgoingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentOutgoingRelationshipEdges(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Get the incoming relationship edges of a target document. Unlike\n # documentIncomingRelationships, which returns the documents at the far end,\n # this returns the edges themselves, carrying their metadata and timestamps.\n # Omit relationshipType to return edges of every type.\n documentIncomingRelationshipEdges(\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String\n view: ViewFilterInput\n paging: PagingInput\n ): DocumentRelationshipResultPage!\n\n # Find documents by search criteria\n findDocuments(\n search: SearchFilterInput\n view: ViewFilterInput\n paging: PagingInput\n ): PHDocumentResultPage!\n\n # Get job status\n jobStatus(jobId: String!): JobInfo\n\n # Get operations for a document with filtering and pagination\n documentOperations(\n filter: OperationsFilterInput!\n paging: PagingInput\n ): ReactorOperationResultPage!\n\n \"\"\"\n Predicts whether the calling subject would be admitted to execute each of a\n set of candidate operations, without submitting any of them. A UI asks this to\n disable a control rather than offer an action that fails on submit.\n\n The answer is a prediction, not a promise:\n\n - Real admission compiles an append condition over everything it read and the\n store enforces it at write time. A preflight reads no future, so a policy\n change landing between this answer and the submit changes the verdict. The\n submit path stays the only authority.\n - The verdict is evaluated at the stream heads, so it is correct for a\n candidate about to be submitted. A backdated submission is out of contract;\n the reactor decides that one by position.\n - A candidate whose verdict depends on its input has to carry that input, since\n a conditional grant reads it.\n\n The subject is the authenticated caller and cannot be named in the request:\n answering for an arbitrary subject would disclose what a policy grants\n somebody else. It carries both the caller's address and the did:key of the app\n instance whose token authenticated the request, so a policy naming either\n matches the same principal the write path presents.\n\n Requires the reactor's authEnforcement feature flag. Without it the reactor\n holds no decision model, so this fails with extensions.code\n AUTH_EVALUATION_UNSUPPORTED rather than guessing.\n \"\"\"\n evaluateActions(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n branch: String\n candidates: [ActionCandidateInput!]!\n ): ActionEvaluations!\n\n \"\"\"\n Polls for sync envelopes from a channel.\n\n An operation stored before the API required an action id cannot be\n represented by this schema, and rather than serving a partial response beside\n a bare non-null violation, this fails with extensions.code\n MALFORMED_STORED_OPERATION naming the operation. That code means the failure\n is worth polling through: the document holding the operation needs repairing,\n but the channel serves every other document, and a peer that stopped polling\n would stop receiving those too.\n \"\"\"\n pollSyncEnvelopes(\n channelId: String!\n outboxAck: Int!\n outboxLatest: Int!\n # The client's manifest revision; absent from a client without peer agreement\n manifestRevision: String\n # Documents the client refused from earlier polls: held, or a refused marker\n refusals: [SyncRefusalInput!]\n ): PollSyncEnvelopesResult!\n\n # Supreme admin, or the address the named remote's channel is bound to\n syncHolds(remoteName: String, documentId: String): [SyncHold!]!\n\n # Supreme admin, or an address bound to a channel in the collection\n peerAgreement(collectionId: String!): PeerAgreement!\n}\n\ntype Mutation {\n # Create a new document\n createDocument(\n document: JSONObject!\n parentIdOrSlug: String\n parentIdentifier: String @deprecated(reason: \"Use parentIdOrSlug.\")\n ): PHDocument!\n\n # Create an empty document of specified type\n createEmptyDocument(\n documentType: String!\n parentIdOrSlug: String\n parentIdentifier: String @deprecated(reason: \"Use parentIdOrSlug.\")\n ): PHDocument!\n\n \"\"\"\n Applies actions to a document and waits for the result.\n\n Each action is coerced against `ActionInput`, so one missing a field the wire\n declares is refused before any work starts. The id in particular: it is hashed\n into the operation id and replay dedupes by it, so an action without one is\n stored under an operation id shared by every id-less operation on the same\n document, scope and branch.\n\n Named for `IReactorClient.execute`, which this is the wire form of. `branch`\n defaults to `main`.\n \"\"\"\n execute(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n actions: [ActionInput!]!\n branch: String\n ): PHDocument!\n\n \"\"\"\n Submits actions to a document and returns the job that will apply them.\n\n Coerced exactly as `execute` is, so a malformed action is refused here rather\n than surfacing later as a failed job. Returns the job rather than only its id,\n so a caller has the status and the creation time it would otherwise have to\n ask for; `result` is null until the job produces one.\n \"\"\"\n executeAsync(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n actions: [ActionInput!]!\n branch: String\n ): JobInfo!\n\n # Apply actions to a document (synchronous)\n mutateDocument(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): PHDocument!\n @deprecated(\n reason: \"Use execute. Actions here are untyped, so a malformed one is refused by a hand-written check rather than by the schema, and `view.scopes` is accepted but ignored.\"\n )\n\n # Submit actions to a document (asynchronous)\n mutateDocumentAsync(\n documentIdentifier: String!\n actions: [JSONObject!]!\n view: ViewFilterInput\n ): String!\n @deprecated(\n reason: \"Use executeAsync, which is typed and returns the job rather than only its id.\"\n )\n\n # Rename a document\n renameDocument(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n name: String!\n branch: String\n ): PHDocument!\n\n # Update the preferred editor recorded in the document header meta.\n # Pass null/omit to clear it.\n setPreferredEditor(\n documentIdOrSlug: String\n documentIdentifier: String @deprecated(reason: \"Use documentIdOrSlug.\")\n preferredEditor: String\n branch: String\n ): PHDocument!\n\n # Add a relationship between two documents. Adding one that already exists is\n # a no-op, metadata included -- use updateRelationship to change an edge.\n addRelationship(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Replace the metadata of an existing relationship, preserving its createdAt.\n # Omitting metadata, or passing null, clears it.\n updateRelationship(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n metadata: JSONObject\n branch: String\n ): PHDocument!\n\n # Remove a relationship between two documents\n removeRelationship(\n sourceIdOrSlug: String\n sourceIdentifier: String @deprecated(reason: \"Use sourceIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n branch: String\n ): PHDocument!\n\n # Move a relationship from one source to another\n moveRelationship(\n sourceParentIdOrSlug: String\n sourceParentIdentifier: String\n @deprecated(reason: \"Use sourceParentIdOrSlug.\")\n targetParentIdOrSlug: String\n targetParentIdentifier: String\n @deprecated(reason: \"Use targetParentIdOrSlug.\")\n targetIdOrSlug: String\n targetIdentifier: String @deprecated(reason: \"Use targetIdOrSlug.\")\n relationshipType: String!\n branch: String\n ): MoveRelationshipResult!\n\n # Delete a single document\n deleteDocument(\n idOrSlug: String\n identifier: String @deprecated(reason: \"Use idOrSlug.\")\n propagate: PropagationMode\n ): Boolean!\n\n # Delete multiple documents\n deleteDocuments(\n idsOrSlugs: [String!]\n identifiers: [String!] @deprecated(reason: \"Use idsOrSlugs.\")\n propagate: PropagationMode\n ): Boolean!\n\n # Touch (create or update) a channel for sync\n touchChannel(input: TouchChannelInput!): TouchChannelResult!\n\n # Push sync envelopes to a channel\n pushSyncEnvelopes(\n envelopes: [SyncEnvelopeInput!]!\n # The server's manifest revision the client gated these envelopes under\n peerManifestRevision: String\n ): Boolean!\n}\n\ntype Subscription {\n # Subscribe to document changes\n documentChanges(\n search: SearchFilterInput\n view: ViewFilterInput\n ): DocumentChangeEvent!\n\n # Subscribe to job changes\n jobChanges(jobId: String!): JobChangeEvent!\n}\n";
5874
5951
  //#endregion
5875
5952
  //#region src/graphql/reactor/pubsub.ts
5876
5953
  const pubSub = new PubSub();
@@ -6149,7 +6226,7 @@ var ReactorSubgraph = class extends BaseSubgraph {
6149
6226
  await this.assertCanReadCanonical(parent.id, ctx);
6150
6227
  try {
6151
6228
  const filter = {
6152
- documentId: parent.id,
6229
+ documentIdOrSlug: parent.id,
6153
6230
  branch: args.filter?.branch,
6154
6231
  scopes: args.filter?.scopes,
6155
6232
  actionTypes: args.filter?.actionTypes,
@@ -6179,10 +6256,11 @@ var ReactorSubgraph = class extends BaseSubgraph {
6179
6256
  document: async (_parent, args, ctx) => {
6180
6257
  this.logger.debug("document(@args)", args);
6181
6258
  try {
6182
- const handle = await this.assertCanRead(args.identifier, ctx);
6259
+ const idOrSlug = requireOneOf(args, "idOrSlug", "identifier");
6260
+ const handle = await this.assertCanRead(idOrSlug, ctx);
6183
6261
  return await document(this.reactorClient, {
6184
- ...args,
6185
- identifier: handle.fetchIdentifier
6262
+ idOrSlug: handle.fetchIdentifier,
6263
+ view: args.view
6186
6264
  }, this.viewSubject(ctx));
6187
6265
  } catch (error) {
6188
6266
  this.logger.error("Error in document: @Error", error);
@@ -6192,10 +6270,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
6192
6270
  documentOutgoingRelationships: async (_parent, args, ctx) => {
6193
6271
  this.logger.debug("documentOutgoingRelationships(@args)", args);
6194
6272
  try {
6195
- const handle = await this.assertCanRead(args.sourceIdentifier, ctx);
6273
+ const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
6274
+ const handle = await this.assertCanRead(sourceIdOrSlug, ctx);
6196
6275
  return await documentOutgoingRelationships(this.reactorClient, {
6197
- ...args,
6198
- sourceIdentifier: handle.fetchIdentifier
6276
+ sourceIdOrSlug: handle.fetchIdentifier,
6277
+ relationshipType: args.relationshipType,
6278
+ view: args.view,
6279
+ paging: args.paging
6199
6280
  }, this.viewSubject(ctx));
6200
6281
  } catch (error) {
6201
6282
  this.logger.error("Error in documentOutgoingRelationships: @Error", error);
@@ -6205,10 +6286,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
6205
6286
  documentIncomingRelationships: async (_parent, args, ctx) => {
6206
6287
  this.logger.debug("documentIncomingRelationships(@args)", args);
6207
6288
  try {
6208
- const handle = await this.assertCanRead(args.targetIdentifier, ctx);
6289
+ const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
6290
+ const handle = await this.assertCanRead(targetIdOrSlug, ctx);
6209
6291
  const result = await documentIncomingRelationships(this.reactorClient, {
6210
- ...args,
6211
- targetIdentifier: handle.fetchIdentifier
6292
+ targetIdOrSlug: handle.fetchIdentifier,
6293
+ relationshipType: args.relationshipType,
6294
+ view: args.view,
6295
+ paging: args.paging
6212
6296
  }, this.viewSubject(ctx));
6213
6297
  if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {
6214
6298
  const filteredItems = [];
@@ -6227,10 +6311,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
6227
6311
  documentOutgoingRelationshipEdges: async (_parent, args, ctx) => {
6228
6312
  this.logger.debug("documentOutgoingRelationshipEdges(@args)", args);
6229
6313
  try {
6230
- const handle = await this.assertCanRead(args.sourceIdentifier, ctx);
6314
+ const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
6315
+ const handle = await this.assertCanRead(sourceIdOrSlug, ctx);
6231
6316
  const result = await documentOutgoingRelationshipEdges(this.reactorClient, {
6232
- ...args,
6233
- sourceIdentifier: handle.fetchIdentifier
6317
+ sourceIdOrSlug: handle.fetchIdentifier,
6318
+ relationshipType: args.relationshipType,
6319
+ view: args.view,
6320
+ paging: args.paging
6234
6321
  }, this.viewSubject(ctx));
6235
6322
  return await this.filterRelationshipEdges(result, "targetId", ctx);
6236
6323
  } catch (error) {
@@ -6241,10 +6328,13 @@ var ReactorSubgraph = class extends BaseSubgraph {
6241
6328
  documentIncomingRelationshipEdges: async (_parent, args, ctx) => {
6242
6329
  this.logger.debug("documentIncomingRelationshipEdges(@args)", args);
6243
6330
  try {
6244
- const handle = await this.assertCanRead(args.targetIdentifier, ctx);
6331
+ const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
6332
+ const handle = await this.assertCanRead(targetIdOrSlug, ctx);
6245
6333
  const result = await documentIncomingRelationshipEdges(this.reactorClient, {
6246
- ...args,
6247
- targetIdentifier: handle.fetchIdentifier
6334
+ targetIdOrSlug: handle.fetchIdentifier,
6335
+ relationshipType: args.relationshipType,
6336
+ view: args.view,
6337
+ paging: args.paging
6248
6338
  }, this.viewSubject(ctx));
6249
6339
  return await this.filterRelationshipEdges(result, "sourceId", ctx);
6250
6340
  } catch (error) {
@@ -6285,13 +6375,17 @@ var ReactorSubgraph = class extends BaseSubgraph {
6285
6375
  documentOperations: async (_parent, args, ctx) => {
6286
6376
  this.logger.debug("documentOperations(@args)", args);
6287
6377
  try {
6288
- const handle = await this.assertCanRead(args.filter.documentId, ctx);
6378
+ const { documentIdOrSlug, documentId, ...filter } = args.filter;
6379
+ const handle = await this.assertCanRead(requireOneOf({
6380
+ documentIdOrSlug,
6381
+ documentId
6382
+ }, "documentIdOrSlug", "documentId"), ctx);
6289
6383
  return await documentOperations(this.reactorClient, {
6290
- ...args,
6291
6384
  filter: {
6292
- ...args.filter,
6293
- documentId: handle.fetchIdentifier
6294
- }
6385
+ ...filter,
6386
+ documentIdOrSlug: handle.fetchIdentifier
6387
+ },
6388
+ paging: args.paging
6295
6389
  }, this.viewSubject(ctx));
6296
6390
  } catch (error) {
6297
6391
  this.logger.error("Error in documentOperations: @Error", error);
@@ -6308,10 +6402,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
6308
6402
  evaluateActions: async (_parent, args, ctx) => {
6309
6403
  this.logger.debug("evaluateActions(@args)", args);
6310
6404
  try {
6311
- const handle = await this.assertCanRead(args.documentIdentifier, ctx);
6405
+ const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
6406
+ const handle = await this.assertCanRead(documentIdOrSlug, ctx);
6312
6407
  return await evaluateActions(this.reactorClient, {
6313
- ...args,
6314
- documentIdentifier: handle.fetchIdentifier
6408
+ documentIdOrSlug: handle.fetchIdentifier,
6409
+ branch: args.branch,
6410
+ candidates: args.candidates
6315
6411
  }, this.viewSubject(ctx));
6316
6412
  } catch (error) {
6317
6413
  this.logger.error("Error in evaluateActions: @Error", error);
@@ -6350,6 +6446,7 @@ var ReactorSubgraph = class extends BaseSubgraph {
6350
6446
  if (!isAdmin) await this.assertCanReadCanonical(driveId, ctx);
6351
6447
  await this.#bindOrRefuseChannel(args.channelId, ctx);
6352
6448
  holdPollRefusals(this.syncManager, args.channelId, args.refusals);
6449
+ await recordPollMarkerRefusals(this.syncManager, args.channelId, args.refusals);
6353
6450
  await silenceUnversionedPoll(this.syncManager, args.channelId, args.manifestRevision);
6354
6451
  const forbiddenIds = /* @__PURE__ */ new Set();
6355
6452
  if (!isAdmin) {
@@ -6370,11 +6467,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
6370
6467
  createDocument: async (_parent, args, ctx) => {
6371
6468
  this.logger.debug("createDocument(@args)", args);
6372
6469
  try {
6373
- if (args.parentIdentifier) {
6374
- const parent = await document(this.reactorClient, { identifier: args.parentIdentifier });
6470
+ const parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
6471
+ if (parentIdOrSlug) {
6472
+ const parent = await document(this.reactorClient, { idOrSlug: parentIdOrSlug });
6375
6473
  await this.assertCanWriteCanonical(parent.document.id, ctx);
6376
6474
  } else this.assertCanCreate(ctx);
6377
- const result = await createDocument(this.reactorClient, args, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
6475
+ const result = await createDocument(this.reactorClient, {
6476
+ document: args.document,
6477
+ parentIdOrSlug
6478
+ }, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
6378
6479
  if (result?.id && isDriveContainerType(result.documentType)) this.graphqlManager.driveOwnershipCache.add(result.id);
6379
6480
  if (ctx.user?.address && result?.id) await this.documentPermissionService?.initializeDocumentProtection(result.id, ctx.user.address, this.authorizationService.config.defaultProtection);
6380
6481
  return result;
@@ -6386,11 +6487,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
6386
6487
  createEmptyDocument: async (_parent, args, ctx) => {
6387
6488
  this.logger.debug("createEmptyDocument(@args)", args);
6388
6489
  try {
6389
- if (args.parentIdentifier) {
6390
- const parent = await document(this.reactorClient, { identifier: args.parentIdentifier });
6490
+ const parentIdOrSlug = optionalOneOf(args, "parentIdOrSlug", "parentIdentifier");
6491
+ if (parentIdOrSlug) {
6492
+ const parent = await document(this.reactorClient, { idOrSlug: parentIdOrSlug });
6391
6493
  await this.assertCanWriteCanonical(parent.document.id, ctx);
6392
6494
  } else this.assertCanCreate(ctx);
6393
- const result = await createEmptyDocument(this.reactorClient, args, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
6495
+ const result = await createEmptyDocument(this.reactorClient, {
6496
+ documentType: args.documentType,
6497
+ parentIdOrSlug
6498
+ }, this.graphqlManager.reactorDriveClient, this.viewSubject(ctx));
6394
6499
  if (result?.id && isDriveContainerType(result.documentType)) this.graphqlManager.driveOwnershipCache.add(result.id);
6395
6500
  if (ctx.user?.address && result?.id) await this.documentPermissionService?.initializeDocumentProtection(result.id, ctx.user.address, this.authorizationService.config.defaultProtection);
6396
6501
  return result;
@@ -6402,10 +6507,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
6402
6507
  execute: async (_parent, args, ctx) => {
6403
6508
  this.logger.debug("execute(@args)", args);
6404
6509
  try {
6405
- const handle = await this.assertCanExecuteOperations(args.documentIdentifier, args.actions, ctx);
6510
+ const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
6511
+ const handle = await this.assertCanExecuteOperations(documentIdOrSlug, args.actions, ctx);
6406
6512
  return await execute(this.reactorClient, {
6407
- ...args,
6408
- documentIdentifier: handle.fetchIdentifier
6513
+ documentIdOrSlug: handle.fetchIdentifier,
6514
+ actions: args.actions,
6515
+ branch: args.branch
6409
6516
  }, this.viewSubject(ctx));
6410
6517
  } catch (error) {
6411
6518
  this.logger.error("Error in execute(@args): @Error", args, error);
@@ -6415,10 +6522,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
6415
6522
  executeAsync: async (_parent, args, ctx) => {
6416
6523
  this.logger.debug("executeAsync(@args)", args);
6417
6524
  try {
6418
- const handle = await this.assertCanExecuteOperations(args.documentIdentifier, args.actions, ctx);
6525
+ const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
6526
+ const handle = await this.assertCanExecuteOperations(documentIdOrSlug, args.actions, ctx);
6419
6527
  return await executeAsync(this.reactorClient, {
6420
- ...args,
6421
- documentIdentifier: handle.fetchIdentifier
6528
+ documentIdOrSlug: handle.fetchIdentifier,
6529
+ actions: args.actions,
6530
+ branch: args.branch
6422
6531
  });
6423
6532
  } catch (error) {
6424
6533
  this.logger.error("Error in executeAsync(@args): @Error", args, error);
@@ -6454,10 +6563,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
6454
6563
  renameDocument: async (_parent, args, ctx) => {
6455
6564
  this.logger.debug("renameDocument(@args)", args);
6456
6565
  try {
6457
- const handle = await this.assertCanWrite(args.documentIdentifier, ctx);
6566
+ const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
6567
+ const handle = await this.assertCanWrite(documentIdOrSlug, ctx);
6458
6568
  return await renameDocument(this.reactorClient, {
6459
- ...args,
6460
- documentIdentifier: handle.fetchIdentifier
6569
+ documentIdOrSlug: handle.fetchIdentifier,
6570
+ name: args.name,
6571
+ branch: args.branch
6461
6572
  }, void 0, this.viewSubject(ctx));
6462
6573
  } catch (error) {
6463
6574
  this.logger.error("Error in renameDocument(@args): @Error", args, error);
@@ -6467,10 +6578,12 @@ var ReactorSubgraph = class extends BaseSubgraph {
6467
6578
  setPreferredEditor: async (_parent, args, ctx) => {
6468
6579
  this.logger.debug("setPreferredEditor(@args)", args);
6469
6580
  try {
6470
- const handle = await this.assertCanWrite(args.documentIdentifier, ctx);
6581
+ const documentIdOrSlug = requireOneOf(args, "documentIdOrSlug", "documentIdentifier");
6582
+ const handle = await this.assertCanWrite(documentIdOrSlug, ctx);
6471
6583
  return await setPreferredEditor(this.reactorClient, {
6472
- ...args,
6473
- documentIdentifier: handle.fetchIdentifier
6584
+ documentIdOrSlug: handle.fetchIdentifier,
6585
+ preferredEditor: args.preferredEditor,
6586
+ branch: args.branch
6474
6587
  }, void 0, this.viewSubject(ctx));
6475
6588
  } catch (error) {
6476
6589
  this.logger.error("Error in setPreferredEditor(@args): @Error", args, error);
@@ -6480,10 +6593,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
6480
6593
  addRelationship: async (_parent, args, ctx) => {
6481
6594
  this.logger.debug("addRelationship(@args)", args);
6482
6595
  try {
6483
- const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);
6596
+ const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
6597
+ const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
6598
+ const handle = await this.assertCanWrite(sourceIdOrSlug, ctx);
6484
6599
  return await addRelationship(this.reactorClient, {
6485
- ...args,
6486
- sourceIdentifier: handle.fetchIdentifier
6600
+ sourceIdOrSlug: handle.fetchIdentifier,
6601
+ targetIdOrSlug,
6602
+ relationshipType: args.relationshipType,
6603
+ metadata: args.metadata,
6604
+ branch: args.branch
6487
6605
  }, this.viewSubject(ctx));
6488
6606
  } catch (error) {
6489
6607
  this.logger.error("Error in addRelationship(@args): @Error", args, error);
@@ -6493,10 +6611,15 @@ var ReactorSubgraph = class extends BaseSubgraph {
6493
6611
  updateRelationship: async (_parent, args, ctx) => {
6494
6612
  this.logger.debug("updateRelationship(@args)", args);
6495
6613
  try {
6496
- const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);
6614
+ const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
6615
+ const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
6616
+ const handle = await this.assertCanWrite(sourceIdOrSlug, ctx);
6497
6617
  return await updateRelationship(this.reactorClient, {
6498
- ...args,
6499
- sourceIdentifier: handle.fetchIdentifier
6618
+ sourceIdOrSlug: handle.fetchIdentifier,
6619
+ targetIdOrSlug,
6620
+ relationshipType: args.relationshipType,
6621
+ metadata: args.metadata,
6622
+ branch: args.branch
6500
6623
  }, this.viewSubject(ctx));
6501
6624
  } catch (error) {
6502
6625
  this.logger.error("Error in updateRelationship(@args): @Error", args, error);
@@ -6506,10 +6629,14 @@ var ReactorSubgraph = class extends BaseSubgraph {
6506
6629
  removeRelationship: async (_parent, args, ctx) => {
6507
6630
  this.logger.debug("removeRelationship(@args)", args);
6508
6631
  try {
6509
- const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);
6632
+ const sourceIdOrSlug = requireOneOf(args, "sourceIdOrSlug", "sourceIdentifier");
6633
+ const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
6634
+ const handle = await this.assertCanWrite(sourceIdOrSlug, ctx);
6510
6635
  return await removeRelationship(this.reactorClient, {
6511
- ...args,
6512
- sourceIdentifier: handle.fetchIdentifier
6636
+ sourceIdOrSlug: handle.fetchIdentifier,
6637
+ targetIdOrSlug,
6638
+ relationshipType: args.relationshipType,
6639
+ branch: args.branch
6513
6640
  }, this.viewSubject(ctx));
6514
6641
  } catch (error) {
6515
6642
  this.logger.error("Error in removeRelationship(@args): @Error", args, error);
@@ -6519,12 +6646,17 @@ var ReactorSubgraph = class extends BaseSubgraph {
6519
6646
  moveRelationship: async (_parent, args, ctx) => {
6520
6647
  this.logger.debug("moveRelationship(@args)", args);
6521
6648
  try {
6522
- const sourceHandle = await this.assertCanWrite(args.sourceParentIdentifier, ctx);
6523
- const targetHandle = await this.assertCanWrite(args.targetParentIdentifier, ctx);
6649
+ const sourceParentIdOrSlug = requireOneOf(args, "sourceParentIdOrSlug", "sourceParentIdentifier");
6650
+ const targetParentIdOrSlug = requireOneOf(args, "targetParentIdOrSlug", "targetParentIdentifier");
6651
+ const targetIdOrSlug = requireOneOf(args, "targetIdOrSlug", "targetIdentifier");
6652
+ const sourceHandle = await this.assertCanWrite(sourceParentIdOrSlug, ctx);
6653
+ const targetHandle = await this.assertCanWrite(targetParentIdOrSlug, ctx);
6524
6654
  return await moveRelationship(this.reactorClient, {
6525
- ...args,
6526
- sourceParentIdentifier: sourceHandle.fetchIdentifier,
6527
- targetParentIdentifier: targetHandle.fetchIdentifier
6655
+ sourceParentIdOrSlug: sourceHandle.fetchIdentifier,
6656
+ targetParentIdOrSlug: targetHandle.fetchIdentifier,
6657
+ targetIdOrSlug,
6658
+ relationshipType: args.relationshipType,
6659
+ branch: args.branch
6528
6660
  }, this.viewSubject(ctx));
6529
6661
  } catch (error) {
6530
6662
  this.logger.error("Error in moveRelationship(@args): @Error @args", error, args);
@@ -6534,11 +6666,11 @@ var ReactorSubgraph = class extends BaseSubgraph {
6534
6666
  deleteDocument: async (_parent, args, ctx) => {
6535
6667
  this.logger.debug("deleteDocument(@args)", args);
6536
6668
  try {
6537
- const identifier = (await this.assertCanWrite(args.identifier, ctx)).fetchIdentifier;
6538
- const driveIdToInvalidate = await this.#resolveDriveId(identifier);
6669
+ const idOrSlug = (await this.assertCanWrite(requireOneOf(args, "idOrSlug", "identifier"), ctx)).fetchIdentifier;
6670
+ const driveIdToInvalidate = await this.#resolveDriveId(idOrSlug);
6539
6671
  const result = await deleteDocument(this.reactorClient, {
6540
- ...args,
6541
- identifier
6672
+ idOrSlug,
6673
+ propagate: args.propagate
6542
6674
  }, this.graphqlManager.reactorDriveClient);
6543
6675
  if (result && driveIdToInvalidate) this.graphqlManager.driveOwnershipCache.remove(driveIdToInvalidate);
6544
6676
  return result;
@@ -6550,14 +6682,14 @@ var ReactorSubgraph = class extends BaseSubgraph {
6550
6682
  deleteDocuments: async (_parent, args, ctx) => {
6551
6683
  this.logger.debug("deleteDocuments(@args)", args);
6552
6684
  try {
6553
- const identifiers = [];
6554
- for (const identifier of args.identifiers) {
6555
- const handle = await this.assertCanWrite(identifier, ctx);
6556
- identifiers.push(handle.fetchIdentifier);
6685
+ const idsOrSlugs = [];
6686
+ for (const idOrSlug of requireOneOf(args, "idsOrSlugs", "identifiers")) {
6687
+ const handle = await this.assertCanWrite(idOrSlug, ctx);
6688
+ idsOrSlugs.push(handle.fetchIdentifier);
6557
6689
  }
6558
6690
  return await deleteDocuments(this.reactorClient, {
6559
- ...args,
6560
- identifiers
6691
+ idsOrSlugs,
6692
+ propagate: args.propagate
6561
6693
  });
6562
6694
  } catch (error) {
6563
6695
  this.logger.error("Error in deleteDocuments(@args): @Error", args, error);
@@ -6692,10 +6824,10 @@ const ADMIN_USERS = getAdminUsers();
6692
6824
  //#endregion
6693
6825
  //#region src/graphql/system/version.ts
6694
6826
  function getVersion() {
6695
- return "6.2.3-dev.34";
6827
+ return "6.2.3-dev.35";
6696
6828
  }
6697
6829
  function getGitHash() {
6698
- return "1dd3921f7bb9c83cd15b8ae12987778505730b52";
6830
+ return "bc7439e3ee5e24332c3684b0d19bc98d8640fa83";
6699
6831
  }
6700
6832
  function getGitUrl() {
6701
6833
  return buildTreeUrl(getGitHash());
@@ -8078,8 +8210,38 @@ var DocumentPermissionService = class {
8078
8210
  * Delete all permissions for a document (used when deleting a document)
8079
8211
  */
8080
8212
  async deleteAllDocumentPermissions(documentId) {
8081
- await this.db.deleteFrom("DocumentPermission").where("documentId", "=", documentId).execute();
8082
- await this.db.deleteFrom("OperationUserPermission").where("documentId", "=", documentId).execute();
8213
+ const permissions = await this.db.deleteFrom("DocumentPermission").where("documentId", "=", documentId).returning("id").execute();
8214
+ const operations = await this.db.deleteFrom("OperationUserPermission").where("documentId", "=", documentId).returning("id").execute();
8215
+ return {
8216
+ DocumentPermission: permissions.length,
8217
+ OperationUserPermission: operations.length
8218
+ };
8219
+ }
8220
+ /** Delete a document's protection row, which names its owner. */
8221
+ async deleteDocumentProtection(documentId) {
8222
+ return (await this.db.deleteFrom("DocumentProtection").where("documentId", "=", documentId).returning("documentId").execute()).length;
8223
+ }
8224
+ /** Every row that names the address, for a subject access request. */
8225
+ async rowsForAddress(address) {
8226
+ const lower = address.toLowerCase();
8227
+ return {
8228
+ permissions: await this.db.selectFrom("DocumentPermission").select([
8229
+ "documentId",
8230
+ "userAddress",
8231
+ "permission",
8232
+ "grantedBy",
8233
+ "createdAt",
8234
+ "updatedAt"
8235
+ ]).where((eb) => eb.or([eb("userAddress", "=", lower), eb("grantedBy", "=", lower)])).orderBy("documentId").execute(),
8236
+ operationPermissions: await this.db.selectFrom("OperationUserPermission").select([
8237
+ "documentId",
8238
+ "operationType",
8239
+ "userAddress",
8240
+ "grantedBy",
8241
+ "createdAt"
8242
+ ]).where((eb) => eb.or([eb("userAddress", "=", lower), eb("grantedBy", "=", lower)])).orderBy("documentId").execute(),
8243
+ ownedDocumentIds: (await this.db.selectFrom("DocumentProtection").select("documentId").where("ownerAddress", "=", lower).orderBy("documentId").execute()).map((row) => row.documentId)
8244
+ };
8083
8245
  }
8084
8246
  /**
8085
8247
  * Grant a user permission to execute an operation on a document
@@ -9068,7 +9230,8 @@ async function initializeAndStartAPI(clientInitializer, options, processorApp) {
9068
9230
  documentModelRegistry,
9069
9231
  readiness,
9070
9232
  attachmentReferenceProjection,
9071
- packageManager: packages
9233
+ packageManager: packages,
9234
+ documentPermissionService
9072
9235
  };
9073
9236
  }
9074
9237
  /**
@@ -9092,6 +9255,55 @@ function withScheme(origin) {
9092
9255
  return /^https?:\/\//.test(trimmed) ? trimmed : `https://${trimmed}`;
9093
9256
  }
9094
9257
  //#endregion
9258
+ //#region src/services/privacy-permissions.ts
9259
+ /**
9260
+ * reactor-privacy's permission lookup and eraser, over this host's
9261
+ * DocumentPermissionService. Typed structurally on the privacy side.
9262
+ */
9263
+ var PrivacyPermissionAdapter = class {
9264
+ service;
9265
+ constructor(service) {
9266
+ this.service = service;
9267
+ }
9268
+ async rowsForAddress(address) {
9269
+ const lower = address.toLowerCase();
9270
+ const found = await this.service.rowsForAddress(address);
9271
+ const rows = [];
9272
+ for (const row of found.permissions) for (const column of ["userAddress", "grantedBy"]) {
9273
+ if (row[column] !== lower) continue;
9274
+ rows.push({
9275
+ table: "DocumentPermission",
9276
+ column,
9277
+ documentId: row.documentId,
9278
+ detail: { permission: row.permission }
9279
+ });
9280
+ }
9281
+ for (const row of found.operationPermissions) for (const column of ["userAddress", "grantedBy"]) {
9282
+ if (row[column] !== lower) continue;
9283
+ rows.push({
9284
+ table: "OperationUserPermission",
9285
+ column,
9286
+ documentId: row.documentId,
9287
+ detail: { operationType: row.operationType }
9288
+ });
9289
+ }
9290
+ for (const documentId of found.ownedDocumentIds) rows.push({
9291
+ table: "DocumentProtection",
9292
+ column: "ownerAddress",
9293
+ documentId
9294
+ });
9295
+ return rows;
9296
+ }
9297
+ async erasePermissions(documentId) {
9298
+ const permissions = await this.service.deleteAllDocumentPermissions(documentId);
9299
+ const protection = await this.service.deleteDocumentProtection(documentId);
9300
+ return {
9301
+ ...permissions,
9302
+ DocumentProtection: protection
9303
+ };
9304
+ }
9305
+ };
9306
+ //#endregion
9095
9307
  //#region src/services/package-storage.ts
9096
9308
  var InMemoryPackageStorage = class {
9097
9309
  packages = /* @__PURE__ */ new Map();
@@ -9195,7 +9407,7 @@ var PackageManagementService = class {
9195
9407
  }
9196
9408
  };
9197
9409
  //#endregion
9198
- export { ADMIN_USERS, ActionCandidateInputSchema, ActionContextInputSchema, ActionInputSchema, AddRelationshipDocument, AnalyticsSubgraph, AttachmentAccessService, AuthDecision, AuthDecisionSchema, AuthEvaluationUnsupportedError, AuthService, AuthSubgraph, AuthenticationRequiredError, AuthorizationPolicy, AuthorizedDocumentHandle, BaseSubgraph, CORE_PACKAGE_NAME, CanonicalDocumentIdResolutionError, ChannelMetaInputSchema, CreateDocumentDocument, CreateEmptyDocumentDocument, DeleteDocumentDocument, DeleteDocumentsDocument, DocumentChangeType, DocumentChangeTypeSchema, DocumentChangesDocument, DocumentOperationsFilterInputSchema, DocumentPermissionService, DocumentRelationshipFieldsFragmentDoc, EvaluateActionsDocument, FindDocumentsDocument, ForbiddenError, GetDocumentDocument, GetDocumentIncomingRelationshipEdgesDocument, GetDocumentIncomingRelationshipsDocument, GetDocumentModelsDocument, GetDocumentOperationsDocument, GetDocumentOutgoingRelationshipEdgesDocument, GetDocumentOutgoingRelationshipsDocument, GetDocumentWithOperationsDocument, GetJobStatusDocument, GraphQLManager, HttpDocumentModelLoader, HttpPackageLoader, HttpRouteService, ImportPackageLoader, InMemoryPackageStorage, InvalidNamespaceError, JobChangesDocument, MalformedStoredOperationError, MemoryWebhookStore, MoveRelationshipDocument, MutateDocumentAsyncDocument, MutateDocumentDocument, OperationContextInputSchema, OperationInputSchema, OperationWithContextInputSchema, OperationsFilterInputSchema, PACKAGE_ROUTE_SEGMENT, PGLITE_UTC_PARSERS, PackageManagementService, PackageManager, PackagesSubgraph, PagingInputSchema, PhDocumentFieldsFragmentDoc, PollSyncEnvelopesDocument, PropagationMode, PropagationModeSchema, PushSyncEnvelopesDocument, ReactorSignerAppInputSchema, ReactorSignerInputSchema, ReactorSignerUserInputSchema, ReactorSubgraph, RelationalWebhookStore, RemoteCursorInputSchema, RemoteFilterInputSchema, RemoveRelationshipDocument, RenameDocumentDocument, SearchFilterInputSchema, SetPreferredEditorDocument, SyncEnvelopeInputSchema, SyncEnvelopeType, SyncEnvelopeTypeSchema, SyncRefusalInputSchema, SystemSubgraph, TouchChannelDocument, TouchChannelInputSchema, UpdateRelationshipDocument, ViewFilterInputSchema, WEBHOOK_SEGMENT, WS_AUTH_CLOSE_REASONS, WS_CLOSE_REASON_AUTHENTICATION_REQUIRED, WS_CLOSE_REASON_BEARER_REJECTED, WebhookService, assertAttachmentPolicyReadsAllowed, assertAuthRequiredForDocumentPermissions, assertCredentialVerifierForSource, assertHostMountPath, assertRequireAuthenticatedCallerAllowed, assertSkipCredentialVerificationAllowed, buildGraphQlDocument, buildGraphQlDriveDocument, buildGraphqlOperation, buildGraphqlOperations, buildSubgraphSchemaModule, callerSubject, createAuthFetchMiddleware, createCanonicalDocumentIdResolver, createGatewayAdapter, createHttpAdapter, createMergedSchema, createReactorGraphQLClient, createRenownCredentialVerifier, createSchema, createWsAuthHandlers, decodeExplorerUrlState, definedNonNullAnySchema, driveIdFromUrl, extractSubgraphsFromModule, generateDocumentModelSchema, getAuthContext, getDbClient, getDocumentModelSchemaName, getDocumentModelTypeDefs, getExplorerPrefix, getGitHash, getGitUrl, getSdk, getUniqueDocumentModels, getUniqueUpgradeManifests, getVersion, initAnalyticsStoreSql, initializeAndStartAPI, isDefinedNonNullAny, isExpectedLoaderMiss, isSubgraphClass, namespacePath, namespaceSegments, newWebhookToken, parseDriveUrl, parseWebhookBody, piecesBaseUrl, redactHeaders, renderGraphqlPlayground, resolvePackageName, resolveRenownConfig, verifyWebhook };
9410
+ export { ADMIN_USERS, ActionCandidateInputSchema, ActionContextInputSchema, ActionInputSchema, AddRelationshipDocument, AnalyticsSubgraph, AttachmentAccessService, AuthDecision, AuthDecisionSchema, AuthEvaluationUnsupportedError, AuthService, AuthSubgraph, AuthenticationRequiredError, AuthorizationPolicy, AuthorizedDocumentHandle, BaseSubgraph, CORE_PACKAGE_NAME, CanonicalDocumentIdResolutionError, ChannelMetaInputSchema, CreateDocumentDocument, CreateEmptyDocumentDocument, DeleteDocumentDocument, DeleteDocumentsDocument, DocumentChangeType, DocumentChangeTypeSchema, DocumentChangesDocument, DocumentOperationsFilterInputSchema, DocumentPermissionService, DocumentRelationshipFieldsFragmentDoc, EvaluateActionsDocument, FindDocumentsDocument, ForbiddenError, GetDocumentDocument, GetDocumentIncomingRelationshipEdgesDocument, GetDocumentIncomingRelationshipsDocument, GetDocumentModelsDocument, GetDocumentOperationsDocument, GetDocumentOutgoingRelationshipEdgesDocument, GetDocumentOutgoingRelationshipsDocument, GetDocumentWithOperationsDocument, GetJobStatusDocument, GraphQLManager, HttpDocumentModelLoader, HttpPackageLoader, HttpRouteService, ImportPackageLoader, InMemoryPackageStorage, InvalidNamespaceError, JobChangesDocument, MalformedStoredOperationError, MemoryWebhookStore, MoveRelationshipDocument, MutateDocumentAsyncDocument, MutateDocumentDocument, OperationContextInputSchema, OperationInputSchema, OperationWithContextInputSchema, OperationsFilterInputSchema, PACKAGE_ROUTE_SEGMENT, PGLITE_UTC_PARSERS, PackageManagementService, PackageManager, PackagesSubgraph, PagingInputSchema, PhDocumentFieldsFragmentDoc, PollSyncEnvelopesDocument, PrivacyPermissionAdapter, PropagationMode, PropagationModeSchema, PushSyncEnvelopesDocument, ReactorSignerAppInputSchema, ReactorSignerInputSchema, ReactorSignerUserInputSchema, ReactorSubgraph, RefusalNotRecordedError, RelationalWebhookStore, RemoteCursorInputSchema, RemoteFilterInputSchema, RemoveRelationshipDocument, RenameDocumentDocument, SearchFilterInputSchema, SetPreferredEditorDocument, SyncEnvelopeInputSchema, SyncEnvelopeType, SyncEnvelopeTypeSchema, SyncRefusalInputSchema, SystemSubgraph, TouchChannelDocument, TouchChannelInputSchema, UpdateRelationshipDocument, ViewFilterInputSchema, WEBHOOK_SEGMENT, WS_AUTH_CLOSE_REASONS, WS_CLOSE_REASON_AUTHENTICATION_REQUIRED, WS_CLOSE_REASON_BEARER_REJECTED, WebhookService, assertAttachmentPolicyReadsAllowed, assertAuthRequiredForDocumentPermissions, assertCredentialVerifierForSource, assertHostMountPath, assertRequireAuthenticatedCallerAllowed, assertSkipCredentialVerificationAllowed, buildGraphQlDocument, buildGraphQlDriveDocument, buildGraphqlOperation, buildGraphqlOperations, buildSubgraphSchemaModule, callerSubject, createAuthFetchMiddleware, createCanonicalDocumentIdResolver, createGatewayAdapter, createHttpAdapter, createMergedSchema, createReactorGraphQLClient, createRenownCredentialVerifier, createSchema, createWsAuthHandlers, decodeExplorerUrlState, definedNonNullAnySchema, driveIdFromUrl, extractSubgraphsFromModule, generateDocumentModelSchema, getAuthContext, getDbClient, getDocumentModelSchemaName, getDocumentModelTypeDefs, getExplorerPrefix, getGitHash, getGitUrl, getSdk, getUniqueDocumentModels, getUniqueUpgradeManifests, getVersion, initAnalyticsStoreSql, initializeAndStartAPI, isDefinedNonNullAny, isExpectedLoaderMiss, isSubgraphClass, namespacePath, namespaceSegments, newWebhookToken, parseDriveUrl, parseWebhookBody, piecesBaseUrl, redactHeaders, renderGraphqlPlayground, resolvePackageName, resolveRenownConfig, verifyWebhook };
9199
9411
 
9200
9412
  //# sourceMappingURL=index.mjs.map
9201
- //# debugId=66ae2db7-0d74-5986-a811-364313026902
9413
+ //# debugId=9e720347-46a5-5d4d-a73c-901d11fe454f